forked from AkkomaGang/akkoma
Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into feature/local-only-scope
This commit is contained in:
commit
fec1ed802e
214 changed files with 2561 additions and 1646 deletions
6
.gitattributes
vendored
6
.gitattributes
vendored
|
@ -1,2 +1,8 @@
|
||||||
*.ex diff=elixir
|
*.ex diff=elixir
|
||||||
*.exs diff=elixir
|
*.exs diff=elixir
|
||||||
|
# At the time of writing all js/css files included
|
||||||
|
# in the repo are minified bundles, and we don't want
|
||||||
|
# to search/diff those as text files.
|
||||||
|
*.js binary
|
||||||
|
*.js.map binary
|
||||||
|
*.css binary
|
||||||
|
|
96
CHANGELOG.md
96
CHANGELOG.md
|
@ -1,29 +1,63 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Polls now always return a `voters_count`, even if they are single-choice.
|
||||||
|
- Admin Emails: The ap id is used as the user link in emails now.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Mix tasks for controlling user account confirmation status in bulk (`mix pleroma.user confirm_all` and `mix pleroma.user unconfirm_all`)
|
|
||||||
- Mix task for sending confirmation emails to all unconfirmed users (`mix pleroma.email send_confirmation_mails`)
|
- Reports now generate notifications for admins and mods.
|
||||||
- Mix task option for force-unfollowing relays
|
|
||||||
- Media preview proxy (requires `ffmpeg` and `ImageMagick` to be installed and media proxy to be enabled; see `:media_preview_proxy` config for more details).
|
|
||||||
- Pleroma API: Importing the mutes users from CSV files.
|
|
||||||
- Experimental websocket-based federation between Pleroma instances.
|
- Experimental websocket-based federation between Pleroma instances.
|
||||||
- Support for local-only statuses
|
- Support for local-only statuses
|
||||||
- Support pagination of blocks and mutes
|
- Support pagination of blocks and mutes.
|
||||||
- App metrics: ability to restrict access to specified IP whitelist.
|
- Account backup.
|
||||||
- Account backup
|
|
||||||
- Configuration: Add `:instance, autofollowing_nicknames` setting to provide a way to make accounts automatically follow new users that register on the local Pleroma instance.
|
- Configuration: Add `:instance, autofollowing_nicknames` setting to provide a way to make accounts automatically follow new users that register on the local Pleroma instance.
|
||||||
|
- Ability to view remote timelines, with ex. `/api/v1/timelines/public?instance=lain.com` and streams `public:remote` and `public:remote:media`.
|
||||||
|
- The site title is now injected as a `title` tag like preloads or metadata.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>API Changes</summary>
|
||||||
|
- Admin API: (`GET /api/pleroma/admin/users`) filter users by `unconfirmed` status and `actor_type`.
|
||||||
|
- Pleroma API: Add `idempotency_key` to the chat message entity that can be used for optimistic message sending.
|
||||||
|
- Pleroma API: (`GET /api/v1/pleroma/federation_status`) Add a way to get a list of unreachable instances.
|
||||||
|
- Mastodon API: User and conversation mutes can now auto-expire if `expires_in` parameter was given while adding the mute.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>API Changes</summary>
|
||||||
|
- Mastodon API: Current user is now included in conversation if it's the only participant.
|
||||||
|
- Mastodon API: Fixed last_status.account being not filled with account data.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Unreleased (Patch)
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Config generation: rename `Pleroma.Upload.Filter.ExifTool` to `Pleroma.Upload.Filter.Exiftool`.
|
||||||
|
- S3 Uploads with Elixir 1.11.
|
||||||
|
|
||||||
|
## [2.2.0] - 2020-11-12
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Fixed the possibility of using file uploads to spoof posts.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **Breaking** Requires `libmagic` (or `file`) to guess file types.
|
- **Breaking** Requires `libmagic` (or `file`) to guess file types.
|
||||||
|
- **Breaking:** App metrics endpoint (`/api/pleroma/app_metrics`) is disabled by default, check `docs/API/prometheus.md` on enabling and configuring.
|
||||||
- **Breaking:** Pleroma Admin API: emoji packs and files routes changed.
|
- **Breaking:** Pleroma Admin API: emoji packs and files routes changed.
|
||||||
- **Breaking:** Sensitive/NSFW statuses no longer disable link previews.
|
- **Breaking:** Sensitive/NSFW statuses no longer disable link previews.
|
||||||
- **Breaking:** App metrics endpoint (`/api/pleroma/app_metrics`) is disabled by default, check `docs/API/prometheus.md` on enabling and configuring.
|
|
||||||
- Search: Users are now findable by their urls.
|
- Search: Users are now findable by their urls.
|
||||||
- Renamed `:await_up_timeout` in `:connections_pool` namespace to `:connect_timeout`, old name is deprecated.
|
- Renamed `:await_up_timeout` in `:connections_pool` namespace to `:connect_timeout`, old name is deprecated.
|
||||||
- Renamed `:timeout` in `pools` namespace to `:recv_timeout`, old name is deprecated.
|
- Renamed `:timeout` in `pools` namespace to `:recv_timeout`, old name is deprecated.
|
||||||
|
@ -31,17 +65,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Users with the `discoverable` field set to false will not show up in searches.
|
- Users with the `discoverable` field set to false will not show up in searches.
|
||||||
- Minimum lifetime for ephmeral activities changed to 10 minutes and made configurable (`:min_lifetime` option).
|
- Minimum lifetime for ephmeral activities changed to 10 minutes and made configurable (`:min_lifetime` option).
|
||||||
- Introduced optional dependencies on `ffmpeg`, `ImageMagick`, `exiftool` software packages. Please refer to `docs/installation/optional/media_graphics_packages.md`.
|
- Introduced optional dependencies on `ffmpeg`, `ImageMagick`, `exiftool` software packages. Please refer to `docs/installation/optional/media_graphics_packages.md`.
|
||||||
|
- <details>
|
||||||
<details>
|
|
||||||
<summary>API Changes</summary>
|
<summary>API Changes</summary>
|
||||||
|
- API: Empty parameter values for integer parameters are now ignored in non-strict validaton mode.
|
||||||
- Pleroma API: Importing the mutes users from CSV files.
|
|
||||||
- Admin API: Importing emoji from a zip file
|
|
||||||
- Pleroma API: Pagination for remote/local packs and emoji.
|
|
||||||
- Admin API: (`GET /api/pleroma/admin/users`) added filters user by `unconfirmed` status
|
|
||||||
- Admin API: (`GET /api/pleroma/admin/users`) added filters user by `actor_type`
|
|
||||||
- Pleroma API: Add `idempotency_key` to the chat message entity that can be used for optimistic message sending.
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
@ -52,20 +78,38 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Removed `:managed_config` option. In practice, it was accidentally removed with 2.0.0 release when frontends were
|
- Removed `:managed_config` option. In practice, it was accidentally removed with 2.0.0 release when frontends were
|
||||||
switched to a new configuration mechanism, however it was not officially removed until now.
|
switched to a new configuration mechanism, however it was not officially removed until now.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Media preview proxy (requires `ffmpeg` and `ImageMagick` to be installed and media proxy to be enabled; see `:media_preview_proxy` config for more details).
|
||||||
|
- Mix tasks for controlling user account confirmation status in bulk (`mix pleroma.user confirm_all` and `mix pleroma.user unconfirm_all`)
|
||||||
|
- Mix task for sending confirmation emails to all unconfirmed users (`mix pleroma.email send_confirmation_mails`)
|
||||||
|
- Mix task option for force-unfollowing relays
|
||||||
|
- App metrics: ability to restrict access to specified IP whitelist.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>API Changes</summary>
|
||||||
|
|
||||||
|
- Admin API: Importing emoji from a zip file
|
||||||
|
- Pleroma API: Importing the mutes users from CSV files.
|
||||||
|
- Pleroma API: Pagination for remote/local packs and emoji.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Add documented-but-missing chat pagination.
|
- Add documented-but-missing chat pagination.
|
||||||
- Allow sending out emails again.
|
- Allow sending out emails again.
|
||||||
- Allow sending chat messages to yourself.
|
- Allow sending chat messages to yourself
|
||||||
- Fix remote users with a whitespace name.
|
|
||||||
- OStatus / static FE endpoints: fixed inaccessibility for anonymous users on non-federating instances, switched to handling per `:restrict_unauthenticated` setting.
|
- OStatus / static FE endpoints: fixed inaccessibility for anonymous users on non-federating instances, switched to handling per `:restrict_unauthenticated` setting.
|
||||||
- Mastodon API: Current user is now included in conversation if it's the only participant
|
- Fix remote users with a whitespace name.
|
||||||
- Mastodon API: Fixed last_status.account being not filled with account data
|
|
||||||
|
|
||||||
## Unreleased (Patch)
|
### Upgrade notes
|
||||||
|
|
||||||
### Changed
|
1. Install libmagic and development headers (`libmagic-dev` on Ubuntu/Debian, `file-dev` on Alpine Linux)
|
||||||
- API: Empty parameter values for integer parameters are now ignored in non-strict validaton mode.
|
2. Run database migrations (inside Pleroma directory):
|
||||||
|
- OTP: `./bin/pleroma_ctl migrate`
|
||||||
|
- From Source: `mix ecto.migrate`
|
||||||
|
3. Restart Pleroma
|
||||||
|
|
||||||
## [2.1.2] - 2020-09-17
|
## [2.1.2] - 2020-09-17
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ COPY . .
|
||||||
|
|
||||||
ENV MIX_ENV=prod
|
ENV MIX_ENV=prod
|
||||||
|
|
||||||
RUN apk add git gcc g++ musl-dev make cmake &&\
|
RUN apk add git gcc g++ musl-dev make cmake file-dev &&\
|
||||||
echo "import Mix.Config" > config/prod.secret.exs &&\
|
echo "import Mix.Config" > config/prod.secret.exs &&\
|
||||||
mix local.hex --force &&\
|
mix local.hex --force &&\
|
||||||
mix local.rebar --force &&\
|
mix local.rebar --force &&\
|
||||||
|
|
|
@ -6,7 +6,7 @@ Currently, Pleroma offers bugfixes and security patches only for the latest mino
|
||||||
|
|
||||||
| Version | Support
|
| Version | Support
|
||||||
|---------| --------
|
|---------| --------
|
||||||
| 2.1 | Bugfixes and security patches
|
| 2.2 | Bugfixes and security patches
|
||||||
|
|
||||||
## Reporting a vulnerability
|
## Reporting a vulnerability
|
||||||
|
|
||||||
|
|
|
@ -562,7 +562,8 @@ config :pleroma, Oban,
|
||||||
background: 5,
|
background: 5,
|
||||||
remote_fetcher: 2,
|
remote_fetcher: 2,
|
||||||
attachments_cleanup: 5,
|
attachments_cleanup: 5,
|
||||||
new_users_digest: 1
|
new_users_digest: 1,
|
||||||
|
mute_expire: 5
|
||||||
],
|
],
|
||||||
plugins: [Oban.Plugins.Pruner],
|
plugins: [Oban.Plugins.Pruner],
|
||||||
crontab: [
|
crontab: [
|
||||||
|
@ -820,7 +821,7 @@ config :pleroma, :restrict_unauthenticated,
|
||||||
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: false
|
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: false
|
||||||
|
|
||||||
config :pleroma, :mrf,
|
config :pleroma, :mrf,
|
||||||
policies: Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy,
|
policies: [Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy, Pleroma.Web.ActivityPub.MRF.TagPolicy],
|
||||||
transparency: true,
|
transparency: true,
|
||||||
transparency_exclusions: []
|
transparency_exclusions: []
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use Mix.Config
|
use Mix.Config
|
||||||
alias Pleroma.Docs.Generator
|
|
||||||
|
|
||||||
websocket_config = [
|
websocket_config = [
|
||||||
path: "/websocket",
|
path: "/websocket",
|
||||||
|
@ -1555,298 +1554,6 @@ config :pleroma, :config_description, [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
%{
|
|
||||||
group: :pleroma,
|
|
||||||
key: :mrf,
|
|
||||||
tab: :mrf,
|
|
||||||
label: "MRF",
|
|
||||||
type: :group,
|
|
||||||
description: "General MRF settings",
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :policies,
|
|
||||||
type: [:module, {:list, :module}],
|
|
||||||
description:
|
|
||||||
"A list of MRF policies enabled. Module names are shortened (removed leading `Pleroma.Web.ActivityPub.MRF.` part), but on adding custom module you need to use full name.",
|
|
||||||
suggestions: {:list_behaviour_implementations, Pleroma.Web.ActivityPub.MRF}
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :transparency,
|
|
||||||
label: "MRF transparency",
|
|
||||||
type: :boolean,
|
|
||||||
description:
|
|
||||||
"Make the content of your Message Rewrite Facility settings public (via nodeinfo)"
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :transparency_exclusions,
|
|
||||||
label: "MRF transparency exclusions",
|
|
||||||
type: {:list, :string},
|
|
||||||
description:
|
|
||||||
"Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.",
|
|
||||||
suggestions: [
|
|
||||||
"exclusion.com"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
group: :pleroma,
|
|
||||||
key: :mrf_simple,
|
|
||||||
tab: :mrf,
|
|
||||||
related_policy: "Pleroma.Web.ActivityPub.MRF.SimplePolicy",
|
|
||||||
label: "MRF Simple",
|
|
||||||
type: :group,
|
|
||||||
description: "Simple ingress policies",
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :media_removal,
|
|
||||||
type: {:list, :string},
|
|
||||||
description: "List of instances to strip media attachments from",
|
|
||||||
suggestions: ["example.com", "*.example.com"]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :media_nsfw,
|
|
||||||
label: "Media NSFW",
|
|
||||||
type: {:list, :string},
|
|
||||||
description: "List of instances to tag all media as NSFW (sensitive) from",
|
|
||||||
suggestions: ["example.com", "*.example.com"]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :federated_timeline_removal,
|
|
||||||
type: {:list, :string},
|
|
||||||
description:
|
|
||||||
"List of instances to remove from the Federated (aka The Whole Known Network) Timeline",
|
|
||||||
suggestions: ["example.com", "*.example.com"]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :reject,
|
|
||||||
type: {:list, :string},
|
|
||||||
description: "List of instances to reject activities from (except deletes)",
|
|
||||||
suggestions: ["example.com", "*.example.com"]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :accept,
|
|
||||||
type: {:list, :string},
|
|
||||||
description: "List of instances to only accept activities from (except deletes)",
|
|
||||||
suggestions: ["example.com", "*.example.com"]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :followers_only,
|
|
||||||
type: {:list, :string},
|
|
||||||
description: "Force posts from the given instances to be visible by followers only",
|
|
||||||
suggestions: ["example.com", "*.example.com"]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :report_removal,
|
|
||||||
type: {:list, :string},
|
|
||||||
description: "List of instances to reject reports from",
|
|
||||||
suggestions: ["example.com", "*.example.com"]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :avatar_removal,
|
|
||||||
type: {:list, :string},
|
|
||||||
description: "List of instances to strip avatars from",
|
|
||||||
suggestions: ["example.com", "*.example.com"]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :banner_removal,
|
|
||||||
type: {:list, :string},
|
|
||||||
description: "List of instances to strip banners from",
|
|
||||||
suggestions: ["example.com", "*.example.com"]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :reject_deletes,
|
|
||||||
type: {:list, :string},
|
|
||||||
description: "List of instances to reject deletions from",
|
|
||||||
suggestions: ["example.com", "*.example.com"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
group: :pleroma,
|
|
||||||
key: :mrf_activity_expiration,
|
|
||||||
tab: :mrf,
|
|
||||||
related_policy: "Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy",
|
|
||||||
label: "MRF Activity Expiration Policy",
|
|
||||||
type: :group,
|
|
||||||
description: "Adds automatic expiration to all local activities",
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :days,
|
|
||||||
type: :integer,
|
|
||||||
description: "Default global expiration time for all local activities (in days)",
|
|
||||||
suggestions: [90, 365]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
group: :pleroma,
|
|
||||||
key: :mrf_subchain,
|
|
||||||
tab: :mrf,
|
|
||||||
related_policy: "Pleroma.Web.ActivityPub.MRF.SubchainPolicy",
|
|
||||||
label: "MRF Subchain",
|
|
||||||
type: :group,
|
|
||||||
description:
|
|
||||||
"This policy processes messages through an alternate pipeline when a given message matches certain criteria." <>
|
|
||||||
" All criteria are configured as a map of regular expressions to lists of policy modules.",
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :match_actor,
|
|
||||||
type: {:map, {:list, :string}},
|
|
||||||
description: "Matches a series of regular expressions against the actor field",
|
|
||||||
suggestions: [
|
|
||||||
%{
|
|
||||||
~r/https:\/\/example.com/s => [Pleroma.Web.ActivityPub.MRF.DropPolicy]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
group: :pleroma,
|
|
||||||
key: :mrf_rejectnonpublic,
|
|
||||||
tab: :mrf,
|
|
||||||
related_policy: "Pleroma.Web.ActivityPub.MRF.RejectNonPublic",
|
|
||||||
description: "RejectNonPublic drops posts with non-public visibility settings.",
|
|
||||||
label: "MRF Reject Non Public",
|
|
||||||
type: :group,
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :allow_followersonly,
|
|
||||||
label: "Allow followers-only",
|
|
||||||
type: :boolean,
|
|
||||||
description: "Whether to allow followers-only posts"
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :allow_direct,
|
|
||||||
type: :boolean,
|
|
||||||
description: "Whether to allow direct messages"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
group: :pleroma,
|
|
||||||
key: :mrf_hellthread,
|
|
||||||
tab: :mrf,
|
|
||||||
related_policy: "Pleroma.Web.ActivityPub.MRF.HellthreadPolicy",
|
|
||||||
label: "MRF Hellthread",
|
|
||||||
type: :group,
|
|
||||||
description: "Block messages with excessive user mentions",
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :delist_threshold,
|
|
||||||
type: :integer,
|
|
||||||
description:
|
|
||||||
"Number of mentioned users after which the message gets removed from timelines and" <>
|
|
||||||
"disables notifications. Set to 0 to disable.",
|
|
||||||
suggestions: [10]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :reject_threshold,
|
|
||||||
type: :integer,
|
|
||||||
description:
|
|
||||||
"Number of mentioned users after which the messaged gets rejected. Set to 0 to disable.",
|
|
||||||
suggestions: [20]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
group: :pleroma,
|
|
||||||
key: :mrf_keyword,
|
|
||||||
tab: :mrf,
|
|
||||||
related_policy: "Pleroma.Web.ActivityPub.MRF.KeywordPolicy",
|
|
||||||
label: "MRF Keyword",
|
|
||||||
type: :group,
|
|
||||||
description:
|
|
||||||
"Reject or Word-Replace messages matching a keyword or [Regex](https://hexdocs.pm/elixir/Regex.html).",
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :reject,
|
|
||||||
type: {:list, :string},
|
|
||||||
description: """
|
|
||||||
A list of patterns which result in message being rejected.
|
|
||||||
|
|
||||||
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
|
|
||||||
""",
|
|
||||||
suggestions: ["foo", ~r/foo/iu]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :federated_timeline_removal,
|
|
||||||
type: {:list, :string},
|
|
||||||
description: """
|
|
||||||
A list of patterns which result in message being removed from federated timelines (a.k.a unlisted).
|
|
||||||
|
|
||||||
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
|
|
||||||
""",
|
|
||||||
suggestions: ["foo", ~r/foo/iu]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :replace,
|
|
||||||
type: {:list, :tuple},
|
|
||||||
description: """
|
|
||||||
**Pattern**: a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
|
|
||||||
|
|
||||||
**Replacement**: a string. Leaving the field empty is permitted.
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
group: :pleroma,
|
|
||||||
key: :mrf_mention,
|
|
||||||
tab: :mrf,
|
|
||||||
related_policy: "Pleroma.Web.ActivityPub.MRF.MentionPolicy",
|
|
||||||
label: "MRF Mention",
|
|
||||||
type: :group,
|
|
||||||
description: "Block messages which mention a specific user",
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :actors,
|
|
||||||
type: {:list, :string},
|
|
||||||
description: "A list of actors for which any post mentioning them will be dropped",
|
|
||||||
suggestions: ["actor1", "actor2"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
group: :pleroma,
|
|
||||||
key: :mrf_vocabulary,
|
|
||||||
tab: :mrf,
|
|
||||||
related_policy: "Pleroma.Web.ActivityPub.MRF.VocabularyPolicy",
|
|
||||||
label: "MRF Vocabulary",
|
|
||||||
type: :group,
|
|
||||||
description: "Filter messages which belong to certain activity vocabularies",
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :accept,
|
|
||||||
type: {:list, :string},
|
|
||||||
description:
|
|
||||||
"A list of ActivityStreams terms to accept. If empty, all supported messages are accepted.",
|
|
||||||
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :reject,
|
|
||||||
type: {:list, :string},
|
|
||||||
description:
|
|
||||||
"A list of ActivityStreams terms to reject. If empty, no messages are rejected.",
|
|
||||||
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
# %{
|
|
||||||
# group: :pleroma,
|
|
||||||
# key: :mrf_user_allowlist,
|
|
||||||
# tab: :mrf,
|
|
||||||
# related_policy: "Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy",
|
|
||||||
# type: :map,
|
|
||||||
# description:
|
|
||||||
# "The keys in this section are the domain names that the policy should apply to." <>
|
|
||||||
# " Each key should be assigned a list of users that should be allowed through by their ActivityPub ID",
|
|
||||||
# suggestions: [
|
|
||||||
# %{"example.org" => ["https://example.org/users/admin"]}
|
|
||||||
# ]
|
|
||||||
# ]
|
|
||||||
# },
|
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :media_proxy,
|
key: :media_proxy,
|
||||||
|
@ -3159,22 +2866,6 @@ config :pleroma, :config_description, [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
%{
|
|
||||||
group: :pleroma,
|
|
||||||
key: :mrf_normalize_markup,
|
|
||||||
tab: :mrf,
|
|
||||||
related_policy: "Pleroma.Web.ActivityPub.MRF.NormalizeMarkup",
|
|
||||||
label: "MRF Normalize Markup",
|
|
||||||
description: "MRF NormalizeMarkup settings. Scrub configured hypertext markup.",
|
|
||||||
type: :group,
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :scrub_policy,
|
|
||||||
type: :module,
|
|
||||||
suggestions: [Pleroma.HTML.Scrubber.Default]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: Pleroma.User,
|
key: Pleroma.User,
|
||||||
|
@ -3364,33 +3055,6 @@ config :pleroma, :config_description, [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
%{
|
|
||||||
group: :pleroma,
|
|
||||||
key: :mrf_object_age,
|
|
||||||
tab: :mrf,
|
|
||||||
related_policy: "Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy",
|
|
||||||
label: "MRF Object Age",
|
|
||||||
type: :group,
|
|
||||||
description:
|
|
||||||
"Rejects or delists posts based on their timestamp deviance from your server's clock.",
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :threshold,
|
|
||||||
type: :integer,
|
|
||||||
description: "Required age (in seconds) of a post before actions are taken.",
|
|
||||||
suggestions: [172_800]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :actions,
|
|
||||||
type: {:list, :atom},
|
|
||||||
description:
|
|
||||||
"A list of actions to apply to the post. `:delist` removes the post from public timelines; " <>
|
|
||||||
"`:strip_followers` removes followers from the ActivityPub recipient list ensuring they won't be delivered to home timelines; " <>
|
|
||||||
"`:reject` rejects the message entirely",
|
|
||||||
suggestions: [:delist, :strip_followers, :reject]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :modules,
|
key: :modules,
|
||||||
|
|
|
@ -116,6 +116,10 @@ The modified chat message
|
||||||
This will return a list of chats that you have been involved in, sorted by their
|
This will return a list of chats that you have been involved in, sorted by their
|
||||||
last update (so new chats will be at the top).
|
last update (so new chats will be at the top).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- with_muted: Include chats from muted users (boolean).
|
||||||
|
|
||||||
Returned data:
|
Returned data:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|
|
@ -9,9 +9,13 @@ Pleroma uses 128-bit ids as opposed to Mastodon's 64 bits. However just like Mas
|
||||||
## Timelines
|
## Timelines
|
||||||
|
|
||||||
Adding the parameter `with_muted=true` to the timeline queries will also return activities by muted (not by blocked!) users.
|
Adding the parameter `with_muted=true` to the timeline queries will also return activities by muted (not by blocked!) users.
|
||||||
|
|
||||||
Adding the parameter `exclude_visibilities` to the timeline queries will exclude the statuses with the given visibilities. The parameter accepts an array of visibility types (`public`, `unlisted`, `private`, `direct`), e.g., `exclude_visibilities[]=direct&exclude_visibilities[]=private`.
|
Adding the parameter `exclude_visibilities` to the timeline queries will exclude the statuses with the given visibilities. The parameter accepts an array of visibility types (`public`, `unlisted`, `private`, `direct`), e.g., `exclude_visibilities[]=direct&exclude_visibilities[]=private`.
|
||||||
|
|
||||||
Adding the parameter `reply_visibility` to the public and home timelines queries will filter replies. Possible values: without parameter (default) shows all replies, `following` - replies directed to you or users you follow, `self` - replies directed to you.
|
Adding the parameter `reply_visibility` to the public and home timelines queries will filter replies. Possible values: without parameter (default) shows all replies, `following` - replies directed to you or users you follow, `self` - replies directed to you.
|
||||||
|
|
||||||
|
Adding the parameter `instance=lain.com` to the public timeline will show only statuses originating from `lain.com` (or any remote instance).
|
||||||
|
|
||||||
## Statuses
|
## Statuses
|
||||||
|
|
||||||
- `visibility`: has additional possible values `list` and `local` (for local-only statuses)
|
- `visibility`: has additional possible values `list` and `local` (for local-only statuses)
|
||||||
|
@ -125,12 +129,30 @@ The `type` value is `pleroma:emoji_reaction`. Has these fields:
|
||||||
- `account`: The account of the user who reacted
|
- `account`: The account of the user who reacted
|
||||||
- `status`: The status that was reacted on
|
- `status`: The status that was reacted on
|
||||||
|
|
||||||
|
### ChatMention Notification (not default)
|
||||||
|
|
||||||
|
This notification has to be requested explicitly.
|
||||||
|
|
||||||
|
The `type` value is `pleroma:chat_mention`
|
||||||
|
|
||||||
|
- `account`: The account who sent the message
|
||||||
|
- `chat_message`: The chat message
|
||||||
|
|
||||||
|
### Report Notification (not default)
|
||||||
|
|
||||||
|
This notification has to be requested explicitly.
|
||||||
|
|
||||||
|
The `type` value is `pleroma:report`
|
||||||
|
|
||||||
|
- `account`: The account who reported
|
||||||
|
- `report`: The report
|
||||||
|
|
||||||
## GET `/api/v1/notifications`
|
## GET `/api/v1/notifications`
|
||||||
|
|
||||||
Accepts additional parameters:
|
Accepts additional parameters:
|
||||||
|
|
||||||
- `exclude_visibilities`: will exclude the notifications for activities with the given visibilities. The parameter accepts an array of visibility types (`public`, `unlisted`, `private`, `direct`). Usage example: `GET /api/v1/notifications?exclude_visibilities[]=direct&exclude_visibilities[]=private`.
|
- `exclude_visibilities`: will exclude the notifications for activities with the given visibilities. The parameter accepts an array of visibility types (`public`, `unlisted`, `private`, `direct`). Usage example: `GET /api/v1/notifications?exclude_visibilities[]=direct&exclude_visibilities[]=private`.
|
||||||
- `include_types`: will include the notifications for activities with the given types. The parameter accepts an array of types (`mention`, `follow`, `reblog`, `favourite`, `move`, `pleroma:emoji_reaction`). Usage example: `GET /api/v1/notifications?include_types[]=mention&include_types[]=reblog`.
|
- `include_types`: will include the notifications for activities with the given types. The parameter accepts an array of types (`mention`, `follow`, `reblog`, `favourite`, `move`, `pleroma:emoji_reaction`, `pleroma:chat_mention`, `pleroma:report`). Usage example: `GET /api/v1/notifications?include_types[]=mention&include_types[]=reblog`.
|
||||||
|
|
||||||
## DELETE `/api/v1/notifications/destroy_multiple`
|
## DELETE `/api/v1/notifications/destroy_multiple`
|
||||||
|
|
||||||
|
@ -249,6 +271,12 @@ Has these additional fields under the `pleroma` object:
|
||||||
|
|
||||||
There is an additional `user:pleroma_chat` stream. Incoming chat messages will make the current chat be sent to this `user` stream. The `event` of an incoming chat message is `pleroma:chat_update`. The payload is the updated chat with the incoming chat message in the `last_message` field.
|
There is an additional `user:pleroma_chat` stream. Incoming chat messages will make the current chat be sent to this `user` stream. The `event` of an incoming chat message is `pleroma:chat_update`. The payload is the updated chat with the incoming chat message in the `last_message` field.
|
||||||
|
|
||||||
|
For viewing remote server timelines, there are `public:remote` and `public:remote:media` streams. Each of these accept a parameter like `?instance=lain.com`.
|
||||||
|
|
||||||
|
## User muting and thread muting
|
||||||
|
|
||||||
|
Both user muting and thread muting can be done for only a certain time by adding an `expires_in` parameter to the API calls and giving the expiration time in seconds.
|
||||||
|
|
||||||
## Not implemented
|
## Not implemented
|
||||||
|
|
||||||
Pleroma is generally compatible with the Mastodon 2.7.2 API, but some newer features and non-essential features are omitted. These features usually return an HTTP 200 status code, but with an empty response. While they may be added in the future, they are considered low priority.
|
Pleroma is generally compatible with the Mastodon 2.7.2 API, but some newer features and non-essential features are omitted. These features usually return an HTTP 200 status code, but with an empty response. While they may be added in the future, they are considered low priority.
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
# Generate release environment file
|
|
||||||
|
|
||||||
```sh tab="OTP"
|
|
||||||
./bin/pleroma_ctl release_env gen
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh tab="From Source"
|
|
||||||
mix pleroma.release_env gen
|
|
||||||
```
|
|
136
docs/configuration/howto_ejabberd.md
Normal file
136
docs/configuration/howto_ejabberd.md
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
# Configuring Ejabberd (XMPP Server) to use Pleroma for authentication
|
||||||
|
|
||||||
|
If you want to give your Pleroma users an XMPP (chat) account, you can configure [Ejabberd](https://github.com/processone/ejabberd) to use your Pleroma server for user authentication, automatically giving every local user an XMPP account.
|
||||||
|
|
||||||
|
In general, you just have to follow the configuration described at [https://docs.ejabberd.im/admin/configuration/authentication/#external-script](https://docs.ejabberd.im/admin/configuration/authentication/#external-script). Please read this section carefully.
|
||||||
|
|
||||||
|
Copy the script below to suitable path on your system and set owner and permissions. Also do not forget adjusting `PLEROMA_HOST` and `PLEROMA_PORT`, if necessary.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp pleroma_ejabberd_auth.py /etc/ejabberd/pleroma_ejabberd_auth.py
|
||||||
|
chown ejabberd /etc/ejabberd/pleroma_ejabberd_auth.py
|
||||||
|
chmod 700 /etc/ejabberd/pleroma_ejabberd_auth.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Set external auth params in ejabberd.yaml file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
auth_method: [external]
|
||||||
|
extauth_program: "python3 /etc/ejabberd/pleroma_ejabberd_auth.py"
|
||||||
|
extauth_instances: 3
|
||||||
|
auth_use_cache: false
|
||||||
|
```
|
||||||
|
|
||||||
|
Restart / reload your ejabberd service.
|
||||||
|
|
||||||
|
After restarting your Ejabberd server, your users should now be able to connect with their Pleroma credentials.
|
||||||
|
|
||||||
|
|
||||||
|
```python
|
||||||
|
import sys
|
||||||
|
import struct
|
||||||
|
import http.client
|
||||||
|
from base64 import b64encode
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
PLEROMA_HOST = "127.0.0.1"
|
||||||
|
PLEROMA_PORT = "4000"
|
||||||
|
AUTH_ENDPOINT = "/api/v1/accounts/verify_credentials"
|
||||||
|
USER_ENDPOINT = "/api/v1/accounts"
|
||||||
|
LOGFILE = "/var/log/ejabberd/pleroma_auth.log"
|
||||||
|
|
||||||
|
logging.basicConfig(filename=LOGFILE, level=logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
|
# Pleroma functions
|
||||||
|
def create_connection():
|
||||||
|
return http.client.HTTPConnection(PLEROMA_HOST, PLEROMA_PORT)
|
||||||
|
|
||||||
|
|
||||||
|
def verify_credentials(user: str, password: str) -> bool:
|
||||||
|
user_pass_b64 = b64encode("{}:{}".format(
|
||||||
|
user, password).encode('utf-8')).decode("ascii")
|
||||||
|
params = {}
|
||||||
|
headers = {
|
||||||
|
"Authorization": "Basic {}".format(user_pass_b64)
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
conn = create_connection()
|
||||||
|
conn.request("GET", AUTH_ENDPOINT, params, headers)
|
||||||
|
|
||||||
|
response = conn.getresponse()
|
||||||
|
if response.status == 200:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
logging.info("Can not connect: %s", str(e))
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def does_user_exist(user: str) -> bool:
|
||||||
|
conn = create_connection()
|
||||||
|
conn.request("GET", "{}/{}".format(USER_ENDPOINT, user))
|
||||||
|
|
||||||
|
response = conn.getresponse()
|
||||||
|
if response.status == 200:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def auth(username: str, server: str, password: str) -> bool:
|
||||||
|
return verify_credentials(username, password)
|
||||||
|
|
||||||
|
|
||||||
|
def isuser(username, server):
|
||||||
|
return does_user_exist(username)
|
||||||
|
|
||||||
|
|
||||||
|
def read():
|
||||||
|
(pkt_size,) = struct.unpack('>H', bytes(sys.stdin.read(2), encoding='utf8'))
|
||||||
|
pkt = sys.stdin.read(pkt_size)
|
||||||
|
cmd = pkt.split(':')[0]
|
||||||
|
if cmd == 'auth':
|
||||||
|
username, server, password = pkt.split(':', 3)[1:]
|
||||||
|
write(auth(username, server, password))
|
||||||
|
elif cmd == 'isuser':
|
||||||
|
username, server = pkt.split(':', 2)[1:]
|
||||||
|
write(isuser(username, server))
|
||||||
|
elif cmd == 'setpass':
|
||||||
|
# u, s, p = pkt.split(':', 3)[1:]
|
||||||
|
write(False)
|
||||||
|
elif cmd == 'tryregister':
|
||||||
|
# u, s, p = pkt.split(':', 3)[1:]
|
||||||
|
write(False)
|
||||||
|
elif cmd == 'removeuser':
|
||||||
|
# u, s = pkt.split(':', 2)[1:]
|
||||||
|
write(False)
|
||||||
|
elif cmd == 'removeuser3':
|
||||||
|
# u, s, p = pkt.split(':', 3)[1:]
|
||||||
|
write(False)
|
||||||
|
else:
|
||||||
|
write(False)
|
||||||
|
|
||||||
|
|
||||||
|
def write(result):
|
||||||
|
if result:
|
||||||
|
sys.stdout.write('\x00\x02\x00\x01')
|
||||||
|
else:
|
||||||
|
sys.stdout.write('\x00\x02\x00\x00')
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
logging.info("Starting pleroma ejabberd auth daemon...")
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
read()
|
||||||
|
except Exception as e:
|
||||||
|
logging.info(
|
||||||
|
"Error while processing data from ejabberd %s", str(e))
|
||||||
|
pass
|
||||||
|
|
||||||
|
```
|
66
docs/configuration/optimizing_beam.md
Normal file
66
docs/configuration/optimizing_beam.md
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
# Optimizing the BEAM
|
||||||
|
|
||||||
|
Pleroma is built upon the Erlang/OTP VM known as BEAM. The BEAM VM is highly optimized for latency, but this has drawbacks in environments without dedicated hardware. One of the tricks used by the BEAM VM is [busy waiting](https://en.wikipedia.org/wiki/Busy_waiting). This allows the application to pretend to be busy working so the OS kernel does not pause the application process and switch to another process waiting for the CPU to execute its workload. It does this by spinning for a period of time which inflates the apparent CPU usage of the application so it is immediately ready to execute another task. This can be observed with utilities like **top(1)** which will show consistently high CPU usage for the process. Switching between procesess is a rather expensive operation and also clears CPU caches further affecting latency and performance. The goal of busy waiting is to avoid this penalty.
|
||||||
|
|
||||||
|
This strategy is very successful in making a performant and responsive application, but is not desirable on Virtual Machines or hardware with few CPU cores. Pleroma instances are often deployed on the same server as the required PostgreSQL database which can lead to situations where the Pleroma application is holding the CPU in a busy-wait loop and as a result the database cannot process requests in a timely manner. The fewer CPUs available, the more this problem is exacerbated. The latency is further amplified by the OS being installed on a Virtual Machine as the Hypervisor uses CPU time-slicing to pause the entire OS and switch between other tasks.
|
||||||
|
|
||||||
|
More adventurous admins can be creative with CPU affinity (e.g., *taskset* for Linux and *cpuset* on FreeBSD) to pin processes to specific CPUs and eliminate much of this contention. The most important advice is to run as few processes as possible on your server to achieve the best performance. Even idle background processes can occasionally create [software interrupts](https://en.wikipedia.org/wiki/Interrupt) and take attention away from the executing process creating latency spikes and invalidation of the CPU caches as they must be cleared when switching between processes for security.
|
||||||
|
|
||||||
|
Please only change these settings if you are experiencing issues or really know what you are doing. In general, there's no need to change these settings.
|
||||||
|
|
||||||
|
## VPS Provider Recommendations
|
||||||
|
|
||||||
|
### Good
|
||||||
|
|
||||||
|
* Hetzner Cloud
|
||||||
|
|
||||||
|
### Bad
|
||||||
|
|
||||||
|
* AWS (known to use burst scheduling)
|
||||||
|
|
||||||
|
|
||||||
|
## Example configurations
|
||||||
|
|
||||||
|
Tuning the BEAM requires you provide a config file normally called [vm.args](http://erlang.org/doc/man/erl.html#emulator-flags). If you are using systemd to manage the service you can modify the unit file as such:
|
||||||
|
|
||||||
|
`ExecStart=/usr/bin/elixir --erl '-args_file /opt/pleroma/config/vm.args' -S /usr/bin/mix phx.server`
|
||||||
|
|
||||||
|
Check your OS documentation to adopt a similar strategy on other platforms.
|
||||||
|
|
||||||
|
### Virtual Machine and/or few CPU cores
|
||||||
|
|
||||||
|
Disable the busy-waiting. This should generally only be done if you're on a platform that does burst scheduling, like AWS.
|
||||||
|
|
||||||
|
**vm.args:**
|
||||||
|
|
||||||
|
```
|
||||||
|
+sbwt none
|
||||||
|
+sbwtdcpu none
|
||||||
|
+sbwtdio none
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dedicated Hardware
|
||||||
|
|
||||||
|
Enable more busy waiting, increase the internal maximum limit of BEAM processes and ports. You can use this if you run on dedicated hardware, but it is not necessary.
|
||||||
|
|
||||||
|
**vm.args:**
|
||||||
|
|
||||||
|
```
|
||||||
|
+P 16777216
|
||||||
|
+Q 16777216
|
||||||
|
+K true
|
||||||
|
+A 128
|
||||||
|
+sbt db
|
||||||
|
+sbwt very_long
|
||||||
|
+swt very_low
|
||||||
|
+sub true
|
||||||
|
+Mulmbcs 32767
|
||||||
|
+Mumbcgs 1
|
||||||
|
+Musmbcs 2047
|
||||||
|
```
|
||||||
|
|
||||||
|
## Additional Reading
|
||||||
|
|
||||||
|
* [WhatsApp: Scaling to Millions of Simultaneous Connections](https://www.erlang-factory.com/upload/presentations/558/efsf2012-whatsapp-scaling.pdf)
|
||||||
|
* [Preemptive Scheduling and Spinlocks](https://www.uio.no/studier/emner/matnat/ifi/nedlagte-emner/INF3150/h03/annet/slides/preemptive.pdf)
|
||||||
|
* [The Curious Case of BEAM CPU Usage](https://stressgrid.com/blog/beam_cpu_usage/)
|
23
docs/dev.md
23
docs/dev.md
|
@ -21,3 +21,26 @@ This document contains notes and guidelines for Pleroma developers.
|
||||||
## Auth-related configuration, OAuth consumer mode etc.
|
## Auth-related configuration, OAuth consumer mode etc.
|
||||||
|
|
||||||
See `Authentication` section of [the configuration cheatsheet](configuration/cheatsheet.md#authentication).
|
See `Authentication` section of [the configuration cheatsheet](configuration/cheatsheet.md#authentication).
|
||||||
|
|
||||||
|
## MRF policies descriptions
|
||||||
|
|
||||||
|
If MRF policy depends on config, it can be added into MRF tab to adminFE by adding `config_description/0` method, which returns map with special structure.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
%{
|
||||||
|
key: :mrf_activity_expiration,
|
||||||
|
related_policy: "Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy",
|
||||||
|
label: "MRF Activity Expiration Policy",
|
||||||
|
description: "Adds automatic expiration to all local activities",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :days,
|
||||||
|
type: :integer,
|
||||||
|
description: "Default global expiration time for all local activities (in days)",
|
||||||
|
suggestions: [90, 365]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
@ -35,7 +35,7 @@ sudo apt full-upgrade
|
||||||
* Install some of the above mentioned programs:
|
* Install some of the above mentioned programs:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo apt install git build-essential postgresql postgresql-contrib cmake libmagic-devel
|
sudo apt install git build-essential postgresql postgresql-contrib cmake libmagic-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install Elixir and Erlang
|
### Install Elixir and Erlang
|
||||||
|
@ -182,7 +182,6 @@ sudo cp /opt/pleroma/installation/pleroma.service /etc/systemd/system/pleroma.se
|
||||||
```
|
```
|
||||||
|
|
||||||
* Edit the service file and make sure that all paths fit your installation
|
* Edit the service file and make sure that all paths fit your installation
|
||||||
* Check that `EnvironmentFile` contains the correct path to the env file. Or generate the env file: `sudo -Hu pleroma mix pleroma.release_env gen`
|
|
||||||
* Enable and start `pleroma.service`:
|
* Enable and start `pleroma.service`:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
|
|
@ -149,9 +149,6 @@ chown -R pleroma /etc/pleroma
|
||||||
# Run the config generator
|
# Run the config generator
|
||||||
su pleroma -s $SHELL -lc "./bin/pleroma_ctl instance gen --output /etc/pleroma/config.exs --output-psql /tmp/setup_db.psql"
|
su pleroma -s $SHELL -lc "./bin/pleroma_ctl instance gen --output /etc/pleroma/config.exs --output-psql /tmp/setup_db.psql"
|
||||||
|
|
||||||
# Run the environment file generator.
|
|
||||||
su pleroma -s $SHELL -lc "./bin/pleroma_ctl release_env gen"
|
|
||||||
|
|
||||||
# Create the postgres database
|
# Create the postgres database
|
||||||
su postgres -s $SHELL -lc "psql -f /tmp/setup_db.psql"
|
su postgres -s $SHELL -lc "psql -f /tmp/setup_db.psql"
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ pidfile="/var/run/pleroma.pid"
|
||||||
directory=/opt/pleroma
|
directory=/opt/pleroma
|
||||||
healthcheck_delay=60
|
healthcheck_delay=60
|
||||||
healthcheck_timer=30
|
healthcheck_timer=30
|
||||||
export $(cat /opt/pleroma/config/pleroma.env)
|
|
||||||
|
|
||||||
: ${pleroma_port:-4000}
|
: ${pleroma_port:-4000}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,6 @@ Environment="MIX_ENV=prod"
|
||||||
Environment="HOME=/var/lib/pleroma"
|
Environment="HOME=/var/lib/pleroma"
|
||||||
; Path to the folder containing the Pleroma installation.
|
; Path to the folder containing the Pleroma installation.
|
||||||
WorkingDirectory=/opt/pleroma
|
WorkingDirectory=/opt/pleroma
|
||||||
; Path to the environment file. the file contains RELEASE_COOKIE and etc
|
|
||||||
EnvironmentFile=/opt/pleroma/config/pleroma.env
|
|
||||||
; Path to the Mix binary.
|
; Path to the Mix binary.
|
||||||
ExecStart=/usr/bin/mix phx.server
|
ExecStart=/usr/bin/mix phx.server
|
||||||
|
|
||||||
|
|
|
@ -36,9 +36,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
|
||||||
listen_port: :string,
|
listen_port: :string,
|
||||||
strip_uploads: :string,
|
strip_uploads: :string,
|
||||||
anonymize_uploads: :string,
|
anonymize_uploads: :string,
|
||||||
dedupe_uploads: :string,
|
dedupe_uploads: :string
|
||||||
skip_release_env: :boolean,
|
|
||||||
release_env_file: :string
|
|
||||||
],
|
],
|
||||||
aliases: [
|
aliases: [
|
||||||
o: :output,
|
o: :output,
|
||||||
|
@ -243,24 +241,6 @@ defmodule Mix.Tasks.Pleroma.Instance do
|
||||||
|
|
||||||
write_robots_txt(static_dir, indexable, template_dir)
|
write_robots_txt(static_dir, indexable, template_dir)
|
||||||
|
|
||||||
if Keyword.get(options, :skip_release_env, false) do
|
|
||||||
shell_info("""
|
|
||||||
Release environment file is skip. Please generate the release env file before start.
|
|
||||||
`MIX_ENV=#{Mix.env()} mix pleroma.release_env gen`
|
|
||||||
""")
|
|
||||||
else
|
|
||||||
shell_info("Generation the environment file:")
|
|
||||||
|
|
||||||
release_env_args =
|
|
||||||
with path when not is_nil(path) <- Keyword.get(options, :release_env_file) do
|
|
||||||
["gen", "--path", path]
|
|
||||||
else
|
|
||||||
_ -> ["gen"]
|
|
||||||
end
|
|
||||||
|
|
||||||
Mix.Tasks.Pleroma.ReleaseEnv.run(release_env_args)
|
|
||||||
end
|
|
||||||
|
|
||||||
shell_info(
|
shell_info(
|
||||||
"\n All files successfully written! Refer to the installation instructions for your platform for next steps."
|
"\n All files successfully written! Refer to the installation instructions for your platform for next steps."
|
||||||
)
|
)
|
||||||
|
@ -304,7 +284,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
|
||||||
defp upload_filters(filters) when is_map(filters) do
|
defp upload_filters(filters) when is_map(filters) do
|
||||||
enabled_filters =
|
enabled_filters =
|
||||||
if filters.strip do
|
if filters.strip do
|
||||||
[Pleroma.Upload.Filter.ExifTool]
|
[Pleroma.Upload.Filter.Exiftool]
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
# Pleroma: A lightweight social networking server
|
|
||||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
defmodule Mix.Tasks.Pleroma.ReleaseEnv do
|
|
||||||
use Mix.Task
|
|
||||||
import Mix.Pleroma
|
|
||||||
|
|
||||||
@shortdoc "Generate Pleroma environment file."
|
|
||||||
@moduledoc File.read!("docs/administration/CLI_tasks/release_environments.md")
|
|
||||||
|
|
||||||
def run(["gen" | rest]) do
|
|
||||||
{options, [], []} =
|
|
||||||
OptionParser.parse(
|
|
||||||
rest,
|
|
||||||
strict: [
|
|
||||||
force: :boolean,
|
|
||||||
path: :string
|
|
||||||
],
|
|
||||||
aliases: [
|
|
||||||
p: :path,
|
|
||||||
f: :force
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
file_path =
|
|
||||||
get_option(
|
|
||||||
options,
|
|
||||||
:path,
|
|
||||||
"Environment file path",
|
|
||||||
"./config/pleroma.env"
|
|
||||||
)
|
|
||||||
|
|
||||||
env_path = Path.expand(file_path)
|
|
||||||
|
|
||||||
proceed? =
|
|
||||||
if File.exists?(env_path) do
|
|
||||||
get_option(
|
|
||||||
options,
|
|
||||||
:force,
|
|
||||||
"Environment file already exists. Do you want to overwrite the #{env_path} file? (y/n)",
|
|
||||||
"n"
|
|
||||||
) === "y"
|
|
||||||
else
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
if proceed? do
|
|
||||||
case do_generate(env_path) do
|
|
||||||
{:error, reason} ->
|
|
||||||
shell_error(
|
|
||||||
File.Error.message(%{action: "write to file", reason: reason, path: env_path})
|
|
||||||
)
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
shell_info("\nThe file generated: #{env_path}.\n")
|
|
||||||
|
|
||||||
shell_info("""
|
|
||||||
WARNING: before start pleroma app please make sure to make the file read-only and non-modifiable.
|
|
||||||
Example:
|
|
||||||
chmod 0444 #{file_path}
|
|
||||||
chattr +i #{file_path}
|
|
||||||
""")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
shell_info("\nThe file is exist. #{env_path}.\n")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def do_generate(path) do
|
|
||||||
content = "RELEASE_COOKIE=#{Base.encode32(:crypto.strong_rand_bytes(32))}"
|
|
||||||
|
|
||||||
File.mkdir_p!(Path.dirname(path))
|
|
||||||
File.write(path, content)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -40,7 +40,8 @@ defmodule Pleroma.Activity.Ir.Topics do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp item_creation_tags(tags, object, %{data: %{"type" => "Create"}} = activity) do
|
defp item_creation_tags(tags, object, %{data: %{"type" => "Create"}} = activity) do
|
||||||
tags ++ hashtags_to_topics(object) ++ attachment_topics(object, activity)
|
tags ++
|
||||||
|
remote_topics(activity) ++ hashtags_to_topics(object) ++ attachment_topics(object, activity)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp item_creation_tags(tags, _, _) do
|
defp item_creation_tags(tags, _, _) do
|
||||||
|
@ -55,9 +56,19 @@ defmodule Pleroma.Activity.Ir.Topics do
|
||||||
|
|
||||||
defp hashtags_to_topics(_), do: []
|
defp hashtags_to_topics(_), do: []
|
||||||
|
|
||||||
|
defp remote_topics(%{local: true}), do: []
|
||||||
|
|
||||||
|
defp remote_topics(%{actor: actor}) when is_binary(actor),
|
||||||
|
do: ["public:remote:" <> URI.parse(actor).host]
|
||||||
|
|
||||||
|
defp remote_topics(_), do: []
|
||||||
|
|
||||||
defp attachment_topics(%{data: %{"attachment" => []}}, _act), do: []
|
defp attachment_topics(%{data: %{"attachment" => []}}, _act), do: []
|
||||||
|
|
||||||
defp attachment_topics(_object, %{local: true}), do: ["public:media", "public:local:media"]
|
defp attachment_topics(_object, %{local: true}), do: ["public:media", "public:local:media"]
|
||||||
|
|
||||||
|
defp attachment_topics(_object, %{actor: actor}) when is_binary(actor),
|
||||||
|
do: ["public:media", "public:remote:media:" <> URI.parse(actor).host]
|
||||||
|
|
||||||
defp attachment_topics(_object, _act), do: ["public:media"]
|
defp attachment_topics(_object, _act), do: ["public:media"]
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,7 +11,11 @@ defmodule Pleroma.Docs.JSON do
|
||||||
|
|
||||||
@spec compile :: :ok
|
@spec compile :: :ok
|
||||||
def compile do
|
def compile do
|
||||||
:persistent_term.put(@term, Pleroma.Docs.Generator.convert_to_strings(@raw_descriptions))
|
descriptions =
|
||||||
|
Pleroma.Web.ActivityPub.MRF.config_descriptions()
|
||||||
|
|> Enum.reduce(@raw_descriptions, fn description, acc -> [description | acc] end)
|
||||||
|
|
||||||
|
:persistent_term.put(@term, Pleroma.Docs.Generator.convert_to_strings(descriptions))
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec compiled_descriptions :: Map.t()
|
@spec compiled_descriptions :: Map.t()
|
||||||
|
|
|
@ -18,10 +18,6 @@ defmodule Pleroma.Emails.AdminEmail do
|
||||||
Keyword.get(instance_config(), :notify_email, instance_config()[:email])
|
Keyword.get(instance_config(), :notify_email, instance_config()[:email])
|
||||||
end
|
end
|
||||||
|
|
||||||
defp user_url(user) do
|
|
||||||
Helpers.user_feed_url(Pleroma.Web.Endpoint, :feed_redirect, user.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_email(mail_to \\ nil) do
|
def test_email(mail_to \\ nil) do
|
||||||
html_body = """
|
html_body = """
|
||||||
<h3>Instance Test Email</h3>
|
<h3>Instance Test Email</h3>
|
||||||
|
@ -69,8 +65,8 @@ defmodule Pleroma.Emails.AdminEmail do
|
||||||
end
|
end
|
||||||
|
|
||||||
html_body = """
|
html_body = """
|
||||||
<p>Reported by: <a href="#{user_url(reporter)}">#{reporter.nickname}</a></p>
|
<p>Reported by: <a href="#{reporter.ap_id}">#{reporter.nickname}</a></p>
|
||||||
<p>Reported Account: <a href="#{user_url(account)}">#{account.nickname}</a></p>
|
<p>Reported Account: <a href="#{account.ap_id}">#{account.nickname}</a></p>
|
||||||
#{comment_html}
|
#{comment_html}
|
||||||
#{statuses_html}
|
#{statuses_html}
|
||||||
<p>
|
<p>
|
||||||
|
@ -86,7 +82,7 @@ defmodule Pleroma.Emails.AdminEmail do
|
||||||
|
|
||||||
def new_unapproved_registration(to, account) do
|
def new_unapproved_registration(to, account) do
|
||||||
html_body = """
|
html_body = """
|
||||||
<p>New account for review: <a href="#{user_url(account)}">@#{account.nickname}</a></p>
|
<p>New account for review: <a href="#{account.ap_id}">@#{account.nickname}</a></p>
|
||||||
<blockquote>#{HTML.strip_tags(account.registration_reason)}</blockquote>
|
<blockquote>#{HTML.strip_tags(account.registration_reason)}</blockquote>
|
||||||
<a href="#{Pleroma.Web.base_url()}/pleroma/admin/#/users/#{account.id}/">Visit AdminFE</a>
|
<a href="#{Pleroma.Web.base_url()}/pleroma/admin/#/users/#{account.id}/">Visit AdminFE</a>
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -11,6 +11,7 @@ defmodule Pleroma.Instances do
|
||||||
defdelegate reachable?(url_or_host), to: @adapter
|
defdelegate reachable?(url_or_host), to: @adapter
|
||||||
defdelegate set_reachable(url_or_host), to: @adapter
|
defdelegate set_reachable(url_or_host), to: @adapter
|
||||||
defdelegate set_unreachable(url_or_host, unreachable_since \\ nil), to: @adapter
|
defdelegate set_unreachable(url_or_host, unreachable_since \\ nil), to: @adapter
|
||||||
|
defdelegate get_consistently_unreachable(), to: @adapter
|
||||||
|
|
||||||
def set_consistently_unreachable(url_or_host),
|
def set_consistently_unreachable(url_or_host),
|
||||||
do: set_unreachable(url_or_host, reachability_datetime_threshold())
|
do: set_unreachable(url_or_host, reachability_datetime_threshold())
|
||||||
|
|
|
@ -119,6 +119,17 @@ defmodule Pleroma.Instances.Instance do
|
||||||
|
|
||||||
def set_unreachable(_, _), do: {:error, nil}
|
def set_unreachable(_, _), do: {:error, nil}
|
||||||
|
|
||||||
|
def get_consistently_unreachable do
|
||||||
|
reachability_datetime_threshold = Instances.reachability_datetime_threshold()
|
||||||
|
|
||||||
|
from(i in Instance,
|
||||||
|
where: ^reachability_datetime_threshold > i.unreachable_since,
|
||||||
|
order_by: i.unreachable_since,
|
||||||
|
select: {i.host, i.unreachable_since}
|
||||||
|
)
|
||||||
|
|> Repo.all()
|
||||||
|
end
|
||||||
|
|
||||||
defp parse_datetime(datetime) when is_binary(datetime) do
|
defp parse_datetime(datetime) when is_binary(datetime) do
|
||||||
NaiveDateTime.from_iso8601(datetime)
|
NaiveDateTime.from_iso8601(datetime)
|
||||||
end
|
end
|
||||||
|
|
|
@ -70,6 +70,7 @@ defmodule Pleroma.Notification do
|
||||||
move
|
move
|
||||||
pleroma:chat_mention
|
pleroma:chat_mention
|
||||||
pleroma:emoji_reaction
|
pleroma:emoji_reaction
|
||||||
|
pleroma:report
|
||||||
reblog
|
reblog
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,7 +368,7 @@ defmodule Pleroma.Notification do
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_notifications(%Activity{data: %{"type" => type}} = activity, options)
|
def create_notifications(%Activity{data: %{"type" => type}} = activity, options)
|
||||||
when type in ["Follow", "Like", "Announce", "Move", "EmojiReact"] do
|
when type in ["Follow", "Like", "Announce", "Move", "EmojiReact", "Flag"] do
|
||||||
do_create_notifications(activity, options)
|
do_create_notifications(activity, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -410,6 +411,9 @@ defmodule Pleroma.Notification do
|
||||||
"EmojiReact" ->
|
"EmojiReact" ->
|
||||||
"pleroma:emoji_reaction"
|
"pleroma:emoji_reaction"
|
||||||
|
|
||||||
|
"Flag" ->
|
||||||
|
"pleroma:report"
|
||||||
|
|
||||||
# Compatibility with old reactions
|
# Compatibility with old reactions
|
||||||
"EmojiReaction" ->
|
"EmojiReaction" ->
|
||||||
"pleroma:emoji_reaction"
|
"pleroma:emoji_reaction"
|
||||||
|
@ -467,7 +471,7 @@ defmodule Pleroma.Notification do
|
||||||
def get_notified_from_activity(activity, local_only \\ true)
|
def get_notified_from_activity(activity, local_only \\ true)
|
||||||
|
|
||||||
def get_notified_from_activity(%Activity{data: %{"type" => type}} = activity, local_only)
|
def get_notified_from_activity(%Activity{data: %{"type" => type}} = activity, local_only)
|
||||||
when type in ["Create", "Like", "Announce", "Follow", "Move", "EmojiReact"] do
|
when type in ["Create", "Like", "Announce", "Follow", "Move", "EmojiReact", "Flag"] do
|
||||||
potential_receiver_ap_ids = get_potential_receiver_ap_ids(activity)
|
potential_receiver_ap_ids = get_potential_receiver_ap_ids(activity)
|
||||||
|
|
||||||
potential_receivers =
|
potential_receivers =
|
||||||
|
@ -503,6 +507,10 @@ defmodule Pleroma.Notification do
|
||||||
[object_id]
|
[object_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_potential_receiver_ap_ids(%{data: %{"type" => "Flag"}}) do
|
||||||
|
User.all_superusers() |> Enum.map(fn user -> user.ap_id end)
|
||||||
|
end
|
||||||
|
|
||||||
def get_potential_receiver_ap_ids(activity) do
|
def get_potential_receiver_ap_ids(activity) do
|
||||||
[]
|
[]
|
||||||
|> Utils.maybe_notify_to_recipients(activity)
|
|> Utils.maybe_notify_to_recipients(activity)
|
||||||
|
|
|
@ -232,9 +232,25 @@ defmodule Pleroma.Object.Fetcher do
|
||||||
|> sign_fetch(id, date)
|
|> sign_fetch(id, date)
|
||||||
|
|
||||||
case HTTP.get(id, headers) do
|
case HTTP.get(id, headers) do
|
||||||
{:ok, %{body: body, status: code}} when code in 200..299 ->
|
{:ok, %{body: body, status: code, headers: headers}} when code in 200..299 ->
|
||||||
|
case List.keyfind(headers, "content-type", 0) do
|
||||||
|
{_, content_type} ->
|
||||||
|
case Plug.Conn.Utils.media_type(content_type) do
|
||||||
|
{:ok, "application", "activity+json", _} ->
|
||||||
{:ok, body}
|
{:ok, body}
|
||||||
|
|
||||||
|
{:ok, "application", "ld+json",
|
||||||
|
%{"profile" => "https://www.w3.org/ns/activitystreams"}} ->
|
||||||
|
{:ok, body}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
{:error, {:content_type, content_type}}
|
||||||
|
end
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
{:error, {:content_type, nil}}
|
||||||
|
end
|
||||||
|
|
||||||
{:ok, %{status: code}} when code in [404, 410] ->
|
{:ok, %{status: code}} when code in [404, 410] ->
|
||||||
{:error, "Object has been deleted"}
|
{:error, "Object has been deleted"}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ defmodule Pleroma.Stats do
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def init(_args) do
|
def init(_args) do
|
||||||
if Pleroma.Config.get(:env) == :test, do: :ok = Ecto.Adapters.SQL.Sandbox.checkout(Repo)
|
|
||||||
{:ok, nil, {:continue, :calculate_stats}}
|
{:ok, nil, {:continue, :calculate_stats}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -32,11 +31,6 @@ defmodule Pleroma.Stats do
|
||||||
GenServer.call(__MODULE__, :force_update)
|
GenServer.call(__MODULE__, :force_update)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc "Performs collect stats"
|
|
||||||
def do_collect do
|
|
||||||
GenServer.cast(__MODULE__, :run_update)
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc "Returns stats data"
|
@doc "Returns stats data"
|
||||||
@spec get_stats() :: %{
|
@spec get_stats() :: %{
|
||||||
domain_count: non_neg_integer(),
|
domain_count: non_neg_integer(),
|
||||||
|
@ -111,7 +105,11 @@ defmodule Pleroma.Stats do
|
||||||
@impl true
|
@impl true
|
||||||
def handle_continue(:calculate_stats, _) do
|
def handle_continue(:calculate_stats, _) do
|
||||||
stats = calculate_stat_data()
|
stats = calculate_stat_data()
|
||||||
|
|
||||||
|
unless Pleroma.Config.get(:env) == :test do
|
||||||
Process.send_after(self(), :run_update, @interval)
|
Process.send_after(self(), :run_update, @interval)
|
||||||
|
end
|
||||||
|
|
||||||
{:noreply, stats}
|
{:noreply, stats}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -126,13 +124,6 @@ defmodule Pleroma.Stats do
|
||||||
{:reply, state, state}
|
{:reply, state, state}
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
|
||||||
def handle_cast(:run_update, _state) do
|
|
||||||
new_stats = calculate_stat_data()
|
|
||||||
|
|
||||||
{:noreply, new_stats}
|
|
||||||
end
|
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_info(:run_update, _) do
|
def handle_info(:run_update, _) do
|
||||||
new_stats = calculate_stat_data()
|
new_stats = calculate_stat_data()
|
||||||
|
|
|
@ -1324,14 +1324,48 @@ defmodule Pleroma.User do
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec mute(User.t(), User.t(), boolean()) ::
|
@spec mute(User.t(), User.t(), map()) ::
|
||||||
{:ok, list(UserRelationship.t())} | {:error, String.t()}
|
{:ok, list(UserRelationship.t())} | {:error, String.t()}
|
||||||
def mute(%User{} = muter, %User{} = mutee, notifications? \\ true) do
|
def mute(%User{} = muter, %User{} = mutee, params \\ %{}) do
|
||||||
add_to_mutes(muter, mutee, notifications?)
|
notifications? = Map.get(params, :notifications, true)
|
||||||
|
expires_in = Map.get(params, :expires_in, 0)
|
||||||
|
|
||||||
|
with {:ok, user_mute} <- UserRelationship.create_mute(muter, mutee),
|
||||||
|
{:ok, user_notification_mute} <-
|
||||||
|
(notifications? && UserRelationship.create_notification_mute(muter, mutee)) ||
|
||||||
|
{:ok, nil} do
|
||||||
|
if expires_in > 0 do
|
||||||
|
Pleroma.Workers.MuteExpireWorker.enqueue(
|
||||||
|
"unmute_user",
|
||||||
|
%{"muter_id" => muter.id, "mutee_id" => mutee.id},
|
||||||
|
schedule_in: expires_in
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
{:ok, Enum.filter([user_mute, user_notification_mute], & &1)}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def unmute(%User{} = muter, %User{} = mutee) do
|
def unmute(%User{} = muter, %User{} = mutee) do
|
||||||
remove_from_mutes(muter, mutee)
|
with {:ok, user_mute} <- UserRelationship.delete_mute(muter, mutee),
|
||||||
|
{:ok, user_notification_mute} <-
|
||||||
|
UserRelationship.delete_notification_mute(muter, mutee) do
|
||||||
|
{:ok, [user_mute, user_notification_mute]}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def unmute(muter_id, mutee_id) do
|
||||||
|
with {:muter, %User{} = muter} <- {:muter, User.get_by_id(muter_id)},
|
||||||
|
{:mutee, %User{} = mutee} <- {:mutee, User.get_by_id(mutee_id)} do
|
||||||
|
unmute(muter, mutee)
|
||||||
|
else
|
||||||
|
{who, result} = error ->
|
||||||
|
Logger.warn(
|
||||||
|
"User.unmute/2 failed. #{who}: #{result}, muter_id: #{muter_id}, mutee_id: #{mutee_id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
{:error, error}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def subscribe(%User{} = subscriber, %User{} = target) do
|
def subscribe(%User{} = subscriber, %User{} = target) do
|
||||||
|
@ -2320,23 +2354,6 @@ defmodule Pleroma.User do
|
||||||
UserRelationship.delete_block(user, blocked)
|
UserRelationship.delete_block(user, blocked)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp add_to_mutes(%User{} = user, %User{} = muted_user, notifications?) do
|
|
||||||
with {:ok, user_mute} <- UserRelationship.create_mute(user, muted_user),
|
|
||||||
{:ok, user_notification_mute} <-
|
|
||||||
(notifications? && UserRelationship.create_notification_mute(user, muted_user)) ||
|
|
||||||
{:ok, nil} do
|
|
||||||
{:ok, Enum.filter([user_mute, user_notification_mute], & &1)}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp remove_from_mutes(user, %User{} = muted_user) do
|
|
||||||
with {:ok, user_mute} <- UserRelationship.delete_mute(user, muted_user),
|
|
||||||
{:ok, user_notification_mute} <-
|
|
||||||
UserRelationship.delete_notification_mute(user, muted_user) do
|
|
||||||
{:ok, [user_mute, user_notification_mute]}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_invisible(user, invisible) do
|
def set_invisible(user, invisible) do
|
||||||
params = %{invisible: invisible}
|
params = %{invisible: invisible}
|
||||||
|
|
||||||
|
|
|
@ -937,16 +937,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
|
|
||||||
defp restrict_muted_reblogs(query, _), do: query
|
defp restrict_muted_reblogs(query, _), do: query
|
||||||
|
|
||||||
defp restrict_instance(query, %{instance: instance}) do
|
defp restrict_instance(query, %{instance: instance}) when is_binary(instance) do
|
||||||
users =
|
|
||||||
from(
|
from(
|
||||||
u in User,
|
activity in query,
|
||||||
select: u.ap_id,
|
where: fragment("split_part(actor::text, '/'::text, 3) = ?", ^instance)
|
||||||
where: fragment("? LIKE ?", u.nickname, ^"%@#{instance}")
|
|
||||||
)
|
)
|
||||||
|> Repo.all()
|
|
||||||
|
|
||||||
from(activity in query, where: activity.actor in ^users)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp restrict_instance(query, _), do: query
|
defp restrict_instance(query, _), do: query
|
||||||
|
|
|
@ -3,7 +3,62 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Web.ActivityPub.MRF do
|
defmodule Pleroma.Web.ActivityPub.MRF do
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
@mrf_config_descriptions [
|
||||||
|
%{
|
||||||
|
group: :pleroma,
|
||||||
|
key: :mrf,
|
||||||
|
tab: :mrf,
|
||||||
|
label: "MRF",
|
||||||
|
type: :group,
|
||||||
|
description: "General MRF settings",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :policies,
|
||||||
|
type: [:module, {:list, :module}],
|
||||||
|
description:
|
||||||
|
"A list of MRF policies enabled. Module names are shortened (removed leading `Pleroma.Web.ActivityPub.MRF.` part), but on adding custom module you need to use full name.",
|
||||||
|
suggestions: {:list_behaviour_implementations, Pleroma.Web.ActivityPub.MRF}
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :transparency,
|
||||||
|
label: "MRF transparency",
|
||||||
|
type: :boolean,
|
||||||
|
description:
|
||||||
|
"Make the content of your Message Rewrite Facility settings public (via nodeinfo)"
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :transparency_exclusions,
|
||||||
|
label: "MRF transparency exclusions",
|
||||||
|
type: {:list, :string},
|
||||||
|
description:
|
||||||
|
"Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.",
|
||||||
|
suggestions: [
|
||||||
|
"exclusion.com"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
@default_description %{
|
||||||
|
label: "",
|
||||||
|
description: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
@required_description_keys [:key, :related_policy]
|
||||||
|
|
||||||
@callback filter(Map.t()) :: {:ok | :reject, Map.t()}
|
@callback filter(Map.t()) :: {:ok | :reject, Map.t()}
|
||||||
|
@callback describe() :: {:ok | :error, Map.t()}
|
||||||
|
@callback config_description() :: %{
|
||||||
|
optional(:children) => [map()],
|
||||||
|
key: atom(),
|
||||||
|
related_policy: String.t(),
|
||||||
|
label: String.t(),
|
||||||
|
description: String.t()
|
||||||
|
}
|
||||||
|
@optional_callbacks config_description: 0
|
||||||
|
|
||||||
def filter(policies, %{} = message) do
|
def filter(policies, %{} = message) do
|
||||||
policies
|
policies
|
||||||
|
@ -51,8 +106,6 @@ defmodule Pleroma.Web.ActivityPub.MRF do
|
||||||
Enum.any?(domains, fn domain -> Regex.match?(domain, host) end)
|
Enum.any?(domains, fn domain -> Regex.match?(domain, host) end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@callback describe() :: {:ok | :error, Map.t()}
|
|
||||||
|
|
||||||
def describe(policies) do
|
def describe(policies) do
|
||||||
{:ok, policy_configs} =
|
{:ok, policy_configs} =
|
||||||
policies
|
policies
|
||||||
|
@ -82,4 +135,41 @@ defmodule Pleroma.Web.ActivityPub.MRF do
|
||||||
end
|
end
|
||||||
|
|
||||||
def describe, do: get_policies() |> describe()
|
def describe, do: get_policies() |> describe()
|
||||||
|
|
||||||
|
def config_descriptions do
|
||||||
|
Pleroma.Web.ActivityPub.MRF
|
||||||
|
|> Pleroma.Docs.Generator.list_behaviour_implementations()
|
||||||
|
|> config_descriptions()
|
||||||
|
end
|
||||||
|
|
||||||
|
def config_descriptions(policies) do
|
||||||
|
Enum.reduce(policies, @mrf_config_descriptions, fn policy, acc ->
|
||||||
|
if function_exported?(policy, :config_description, 0) do
|
||||||
|
description =
|
||||||
|
@default_description
|
||||||
|
|> Map.merge(policy.config_description)
|
||||||
|
|> Map.put(:group, :pleroma)
|
||||||
|
|> Map.put(:tab, :mrf)
|
||||||
|
|> Map.put(:type, :group)
|
||||||
|
|
||||||
|
if Enum.all?(@required_description_keys, &Map.has_key?(description, &1)) do
|
||||||
|
[description | acc]
|
||||||
|
else
|
||||||
|
Logger.warn(
|
||||||
|
"#{policy} config description doesn't have one or all required keys #{
|
||||||
|
inspect(@required_description_keys)
|
||||||
|
}"
|
||||||
|
)
|
||||||
|
|
||||||
|
acc
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Logger.debug(
|
||||||
|
"#{policy} is excluded from config descriptions, because does not implement `config_description/0` method."
|
||||||
|
)
|
||||||
|
|
||||||
|
acc
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -40,4 +40,22 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy do
|
||||||
_ -> Map.put(activity, "expires_at", expires_at)
|
_ -> Map.put(activity, "expires_at", expires_at)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def config_description do
|
||||||
|
%{
|
||||||
|
key: :mrf_activity_expiration,
|
||||||
|
related_policy: "Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy",
|
||||||
|
label: "MRF Activity Expiration Policy",
|
||||||
|
description: "Adds automatic expiration to all local activities",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :days,
|
||||||
|
type: :integer,
|
||||||
|
description: "Default global expiration time for all local activities (in days)",
|
||||||
|
suggestions: [90, 365]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -97,4 +97,31 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
|
||||||
@impl true
|
@impl true
|
||||||
def describe,
|
def describe,
|
||||||
do: {:ok, %{mrf_hellthread: Pleroma.Config.get(:mrf_hellthread) |> Enum.into(%{})}}
|
do: {:ok, %{mrf_hellthread: Pleroma.Config.get(:mrf_hellthread) |> Enum.into(%{})}}
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def config_description do
|
||||||
|
%{
|
||||||
|
key: :mrf_hellthread,
|
||||||
|
related_policy: "Pleroma.Web.ActivityPub.MRF.HellthreadPolicy",
|
||||||
|
label: "MRF Hellthread",
|
||||||
|
description: "Block messages with excessive user mentions",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :delist_threshold,
|
||||||
|
type: :integer,
|
||||||
|
description:
|
||||||
|
"Number of mentioned users after which the message gets removed from timelines and" <>
|
||||||
|
"disables notifications. Set to 0 to disable.",
|
||||||
|
suggestions: [10]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :reject_threshold,
|
||||||
|
type: :integer,
|
||||||
|
description:
|
||||||
|
"Number of mentioned users after which the messaged gets rejected. Set to 0 to disable.",
|
||||||
|
suggestions: [20]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -126,4 +126,46 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
||||||
|
|
||||||
{:ok, %{mrf_keyword: mrf_keyword}}
|
{:ok, %{mrf_keyword: mrf_keyword}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def config_description do
|
||||||
|
%{
|
||||||
|
key: :mrf_keyword,
|
||||||
|
related_policy: "Pleroma.Web.ActivityPub.MRF.KeywordPolicy",
|
||||||
|
label: "MRF Keyword",
|
||||||
|
description:
|
||||||
|
"Reject or Word-Replace messages matching a keyword or [Regex](https://hexdocs.pm/elixir/Regex.html).",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :reject,
|
||||||
|
type: {:list, :string},
|
||||||
|
description: """
|
||||||
|
A list of patterns which result in message being rejected.
|
||||||
|
|
||||||
|
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
|
||||||
|
""",
|
||||||
|
suggestions: ["foo", ~r/foo/iu]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :federated_timeline_removal,
|
||||||
|
type: {:list, :string},
|
||||||
|
description: """
|
||||||
|
A list of patterns which result in message being removed from federated timelines (a.k.a unlisted).
|
||||||
|
|
||||||
|
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
|
||||||
|
""",
|
||||||
|
suggestions: ["foo", ~r/foo/iu]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :replace,
|
||||||
|
type: {:list, :tuple},
|
||||||
|
description: """
|
||||||
|
**Pattern**: a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
|
||||||
|
|
||||||
|
**Replacement**: a string. Leaving the field empty is permitted.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,4 +25,22 @@ defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicy do
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def describe, do: {:ok, %{}}
|
def describe, do: {:ok, %{}}
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def config_description do
|
||||||
|
%{
|
||||||
|
key: :mrf_mention,
|
||||||
|
related_policy: "Pleroma.Web.ActivityPub.MRF.MentionPolicy",
|
||||||
|
label: "MRF Mention",
|
||||||
|
description: "Block messages which mention a specific user",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :actors,
|
||||||
|
type: {:list, :string},
|
||||||
|
description: "A list of actors for which any post mentioning them will be dropped",
|
||||||
|
suggestions: ["actor1", "actor2"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,6 +8,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkup do
|
||||||
|
|
||||||
@behaviour Pleroma.Web.ActivityPub.MRF
|
@behaviour Pleroma.Web.ActivityPub.MRF
|
||||||
|
|
||||||
|
@impl true
|
||||||
def filter(%{"type" => "Create", "object" => child_object} = object) do
|
def filter(%{"type" => "Create", "object" => child_object} = object) do
|
||||||
scrub_policy = Pleroma.Config.get([:mrf_normalize_markup, :scrub_policy])
|
scrub_policy = Pleroma.Config.get([:mrf_normalize_markup, :scrub_policy])
|
||||||
|
|
||||||
|
@ -22,5 +23,23 @@ defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkup do
|
||||||
|
|
||||||
def filter(object), do: {:ok, object}
|
def filter(object), do: {:ok, object}
|
||||||
|
|
||||||
|
@impl true
|
||||||
def describe, do: {:ok, %{}}
|
def describe, do: {:ok, %{}}
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def config_description do
|
||||||
|
%{
|
||||||
|
key: :mrf_normalize_markup,
|
||||||
|
related_policy: "Pleroma.Web.ActivityPub.MRF.NormalizeMarkup",
|
||||||
|
label: "MRF Normalize Markup",
|
||||||
|
description: "MRF NormalizeMarkup settings. Scrub configured hypertext markup.",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :scrub_policy,
|
||||||
|
type: :module,
|
||||||
|
suggestions: [Pleroma.HTML.Scrubber.Default]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -106,4 +106,32 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
|
||||||
|
|
||||||
{:ok, %{mrf_object_age: mrf_object_age}}
|
{:ok, %{mrf_object_age: mrf_object_age}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def config_description do
|
||||||
|
%{
|
||||||
|
key: :mrf_object_age,
|
||||||
|
related_policy: "Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy",
|
||||||
|
label: "MRF Object Age",
|
||||||
|
description:
|
||||||
|
"Rejects or delists posts based on their timestamp deviance from your server's clock.",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :threshold,
|
||||||
|
type: :integer,
|
||||||
|
description: "Required age (in seconds) of a post before actions are taken.",
|
||||||
|
suggestions: [172_800]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :actions,
|
||||||
|
type: {:list, :atom},
|
||||||
|
description:
|
||||||
|
"A list of actions to apply to the post. `:delist` removes the post from public timelines; " <>
|
||||||
|
"`:strip_followers` removes followers from the ActivityPub recipient list ensuring they won't be delivered to home timelines; " <>
|
||||||
|
"`:reject` rejects the message entirely",
|
||||||
|
suggestions: [:delist, :strip_followers, :reject]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -48,4 +48,27 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do
|
||||||
@impl true
|
@impl true
|
||||||
def describe,
|
def describe,
|
||||||
do: {:ok, %{mrf_rejectnonpublic: Config.get(:mrf_rejectnonpublic) |> Enum.into(%{})}}
|
do: {:ok, %{mrf_rejectnonpublic: Config.get(:mrf_rejectnonpublic) |> Enum.into(%{})}}
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def config_description do
|
||||||
|
%{
|
||||||
|
key: :mrf_rejectnonpublic,
|
||||||
|
related_policy: "Pleroma.Web.ActivityPub.MRF.RejectNonPublic",
|
||||||
|
description: "RejectNonPublic drops posts with non-public visibility settings.",
|
||||||
|
label: "MRF Reject Non Public",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :allow_followersonly,
|
||||||
|
label: "Allow followers-only",
|
||||||
|
type: :boolean,
|
||||||
|
description: "Whether to allow followers-only posts"
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :allow_direct,
|
||||||
|
type: :boolean,
|
||||||
|
description: "Whether to allow direct messages"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -244,4 +244,78 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
||||||
|
|
||||||
{:ok, %{mrf_simple: mrf_simple}}
|
{:ok, %{mrf_simple: mrf_simple}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def config_description do
|
||||||
|
%{
|
||||||
|
key: :mrf_simple,
|
||||||
|
related_policy: "Pleroma.Web.ActivityPub.MRF.SimplePolicy",
|
||||||
|
label: "MRF Simple",
|
||||||
|
description: "Simple ingress policies",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :media_removal,
|
||||||
|
type: {:list, :string},
|
||||||
|
description: "List of instances to strip media attachments from",
|
||||||
|
suggestions: ["example.com", "*.example.com"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :media_nsfw,
|
||||||
|
label: "Media NSFW",
|
||||||
|
type: {:list, :string},
|
||||||
|
description: "List of instances to tag all media as NSFW (sensitive) from",
|
||||||
|
suggestions: ["example.com", "*.example.com"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :federated_timeline_removal,
|
||||||
|
type: {:list, :string},
|
||||||
|
description:
|
||||||
|
"List of instances to remove from the Federated (aka The Whole Known Network) Timeline",
|
||||||
|
suggestions: ["example.com", "*.example.com"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :reject,
|
||||||
|
type: {:list, :string},
|
||||||
|
description: "List of instances to reject activities from (except deletes)",
|
||||||
|
suggestions: ["example.com", "*.example.com"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :accept,
|
||||||
|
type: {:list, :string},
|
||||||
|
description: "List of instances to only accept activities from (except deletes)",
|
||||||
|
suggestions: ["example.com", "*.example.com"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :followers_only,
|
||||||
|
type: {:list, :string},
|
||||||
|
description: "Force posts from the given instances to be visible by followers only",
|
||||||
|
suggestions: ["example.com", "*.example.com"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :report_removal,
|
||||||
|
type: {:list, :string},
|
||||||
|
description: "List of instances to reject reports from",
|
||||||
|
suggestions: ["example.com", "*.example.com"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :avatar_removal,
|
||||||
|
type: {:list, :string},
|
||||||
|
description: "List of instances to strip avatars from",
|
||||||
|
suggestions: ["example.com", "*.example.com"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :banner_removal,
|
||||||
|
type: {:list, :string},
|
||||||
|
description: "List of instances to strip banners from",
|
||||||
|
suggestions: ["example.com", "*.example.com"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :reject_deletes,
|
||||||
|
type: {:list, :string},
|
||||||
|
description: "List of instances to reject deletions from",
|
||||||
|
suggestions: ["example.com", "*.example.com"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -39,4 +39,28 @@ defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicy do
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def describe, do: {:ok, %{}}
|
def describe, do: {:ok, %{}}
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def config_description do
|
||||||
|
%{
|
||||||
|
key: :mrf_subchain,
|
||||||
|
related_policy: "Pleroma.Web.ActivityPub.MRF.SubchainPolicy",
|
||||||
|
label: "MRF Subchain",
|
||||||
|
description:
|
||||||
|
"This policy processes messages through an alternate pipeline when a given message matches certain criteria." <>
|
||||||
|
" All criteria are configured as a map of regular expressions to lists of policy modules.",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :match_actor,
|
||||||
|
type: {:map, {:list, :string}},
|
||||||
|
description: "Matches a series of regular expressions against the actor field",
|
||||||
|
suggestions: [
|
||||||
|
%{
|
||||||
|
~r/https:\/\/example.com/s => [Pleroma.Web.ActivityPub.MRF.DropPolicy]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -41,4 +41,25 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do
|
||||||
|
|
||||||
{:ok, %{mrf_user_allowlist: mrf_user_allowlist}}
|
{:ok, %{mrf_user_allowlist: mrf_user_allowlist}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO: change way of getting settings on `lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex:18` to use `hosts` subkey
|
||||||
|
# @impl true
|
||||||
|
# def config_description do
|
||||||
|
# %{
|
||||||
|
# key: :mrf_user_allowlist,
|
||||||
|
# related_policy: "Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy",
|
||||||
|
# description: "Accept-list of users from specified instances",
|
||||||
|
# children: [
|
||||||
|
# %{
|
||||||
|
# key: :hosts,
|
||||||
|
# type: :map,
|
||||||
|
# description:
|
||||||
|
# "The keys in this section are the domain names that the policy should apply to." <>
|
||||||
|
# " Each key should be assigned a list of users that should be allowed " <>
|
||||||
|
# "through by their ActivityPub ID",
|
||||||
|
# suggestions: [%{"example.org" => ["https://example.org/users/admin"]}]
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
# end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicy do
|
||||||
|
|
||||||
@behaviour Pleroma.Web.ActivityPub.MRF
|
@behaviour Pleroma.Web.ActivityPub.MRF
|
||||||
|
|
||||||
|
@impl true
|
||||||
def filter(%{"type" => "Undo", "object" => child_message} = message) do
|
def filter(%{"type" => "Undo", "object" => child_message} = message) do
|
||||||
with {:ok, _} <- filter(child_message) do
|
with {:ok, _} <- filter(child_message) do
|
||||||
{:ok, message}
|
{:ok, message}
|
||||||
|
@ -36,6 +37,33 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicy do
|
||||||
|
|
||||||
def filter(message), do: {:ok, message}
|
def filter(message), do: {:ok, message}
|
||||||
|
|
||||||
|
@impl true
|
||||||
def describe,
|
def describe,
|
||||||
do: {:ok, %{mrf_vocabulary: Pleroma.Config.get(:mrf_vocabulary) |> Enum.into(%{})}}
|
do: {:ok, %{mrf_vocabulary: Pleroma.Config.get(:mrf_vocabulary) |> Enum.into(%{})}}
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def config_description do
|
||||||
|
%{
|
||||||
|
key: :mrf_vocabulary,
|
||||||
|
related_policy: "Pleroma.Web.ActivityPub.MRF.VocabularyPolicy",
|
||||||
|
label: "MRF Vocabulary",
|
||||||
|
description: "Filter messages which belong to certain activity vocabularies",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :accept,
|
||||||
|
type: {:list, :string},
|
||||||
|
description:
|
||||||
|
"A list of ActivityStreams terms to accept. If empty, all supported messages are accepted.",
|
||||||
|
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :reject,
|
||||||
|
type: {:list, :string},
|
||||||
|
description:
|
||||||
|
"A list of ActivityStreams terms to reject. If empty, no messages are rejected.",
|
||||||
|
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,6 +15,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do
|
||||||
field(:type, :string)
|
field(:type, :string)
|
||||||
field(:mediaType, :string, default: "application/octet-stream")
|
field(:mediaType, :string, default: "application/octet-stream")
|
||||||
field(:name, :string)
|
field(:name, :string)
|
||||||
|
field(:blurhash, :string)
|
||||||
|
|
||||||
embeds_many :url, UrlObjectValidator, primary_key: false do
|
embeds_many :url, UrlObjectValidator, primary_key: false do
|
||||||
field(:type, :string)
|
field(:type, :string)
|
||||||
|
@ -41,7 +42,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do
|
||||||
|> fix_url()
|
|> fix_url()
|
||||||
|
|
||||||
struct
|
struct
|
||||||
|> cast(data, [:type, :mediaType, :name])
|
|> cast(data, [:type, :mediaType, :name, :blurhash])
|
||||||
|> cast_embed(:url, with: &url_changeset/2)
|
|> cast_embed(:url, with: &url_changeset/2)
|
||||||
|> validate_inclusion(:type, ~w[Link Document Audio Image Video])
|
|> validate_inclusion(:type, ~w[Link Document Audio Image Video])
|
||||||
|> validate_required([:type, :mediaType, :url])
|
|> validate_required([:type, :mediaType, :url])
|
||||||
|
|
|
@ -252,6 +252,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||||
}
|
}
|
||||||
|> Maps.put_if_present("mediaType", media_type)
|
|> Maps.put_if_present("mediaType", media_type)
|
||||||
|> Maps.put_if_present("name", data["name"])
|
|> Maps.put_if_present("name", data["name"])
|
||||||
|
|> Maps.put_if_present("blurhash", data["blurhash"])
|
||||||
else
|
else
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -262,6 +262,12 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
||||||
:query,
|
:query,
|
||||||
%Schema{allOf: [BooleanLike], default: true},
|
%Schema{allOf: [BooleanLike], default: true},
|
||||||
"Mute notifications in addition to statuses? Defaults to `true`."
|
"Mute notifications in addition to statuses? Defaults to `true`."
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:expires_in,
|
||||||
|
:query,
|
||||||
|
%Schema{type: :integer, default: 0},
|
||||||
|
"Expire the mute in `expires_in` seconds. Default 0 for infinity"
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
responses: %{
|
responses: %{
|
||||||
|
@ -723,10 +729,17 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "Mute notifications in addition to statuses? Defaults to true.",
|
description: "Mute notifications in addition to statuses? Defaults to true.",
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
expires_in: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
nullable: true,
|
||||||
|
description: "Expire the mute in `expires_in` seconds. Default 0 for infinity",
|
||||||
|
default: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
example: %{
|
example: %{
|
||||||
"notifications" => true
|
"notifications" => true,
|
||||||
|
"expires_in" => 86_400
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
|
||||||
alias OpenApiSpex.Operation
|
alias OpenApiSpex.Operation
|
||||||
alias OpenApiSpex.Schema
|
alias OpenApiSpex.Schema
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.Chat
|
alias Pleroma.Web.ApiSpec.Schemas.Chat
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.ChatMessage
|
alias Pleroma.Web.ApiSpec.Schemas.ChatMessage
|
||||||
|
|
||||||
|
@ -132,7 +133,10 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
|
||||||
tags: ["chat"],
|
tags: ["chat"],
|
||||||
summary: "Get a list of chats that you participated in",
|
summary: "Get a list of chats that you participated in",
|
||||||
operationId: "ChatController.index",
|
operationId: "ChatController.index",
|
||||||
parameters: pagination_params(),
|
parameters: [
|
||||||
|
Operation.parameter(:with_muted, :query, BooleanLike, "Include chats from muted users")
|
||||||
|
| pagination_params()
|
||||||
|
],
|
||||||
responses: %{
|
responses: %{
|
||||||
200 => Operation.response("The chats of the user", "application/json", chats_response())
|
200 => Operation.response("The chats of the user", "application/json", chats_response())
|
||||||
},
|
},
|
||||||
|
|
|
@ -193,6 +193,7 @@ defmodule Pleroma.Web.ApiSpec.NotificationOperation do
|
||||||
"mention",
|
"mention",
|
||||||
"pleroma:emoji_reaction",
|
"pleroma:emoji_reaction",
|
||||||
"pleroma:chat_mention",
|
"pleroma:chat_mention",
|
||||||
|
"pleroma:report",
|
||||||
"move",
|
"move",
|
||||||
"follow_request"
|
"follow_request"
|
||||||
],
|
],
|
||||||
|
@ -206,6 +207,8 @@ defmodule Pleroma.Web.ApiSpec.NotificationOperation do
|
||||||
- `poll` - A poll you have voted in or created has ended
|
- `poll` - A poll you have voted in or created has ended
|
||||||
- `move` - Someone moved their account
|
- `move` - Someone moved their account
|
||||||
- `pleroma:emoji_reaction` - Someone reacted with emoji to your status
|
- `pleroma:emoji_reaction` - Someone reacted with emoji to your status
|
||||||
|
- `pleroma:chat_mention` - Someone mentioned you in a chat message
|
||||||
|
- `pleroma:report` - Someone was reported
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ApiSpec.PleromaInstancesOperation do
|
||||||
|
alias OpenApiSpex.Operation
|
||||||
|
alias OpenApiSpex.Schema
|
||||||
|
|
||||||
|
def open_api_operation(action) do
|
||||||
|
operation = String.to_existing_atom("#{action}_operation")
|
||||||
|
apply(__MODULE__, operation, [])
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["PleromaInstances"],
|
||||||
|
summary: "Instances federation status",
|
||||||
|
description: "Information about instances deemed unreachable by the server",
|
||||||
|
operationId: "PleromaInstances.show",
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("PleromaInstances", "application/json", pleroma_instances())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def pleroma_instances do
|
||||||
|
%Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
unreachable: %Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{hostname: %Schema{type: :string, format: :"date-time"}}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
example: %{
|
||||||
|
"unreachable" => %{"consistently-unreachable.name" => "2020-10-14 22:07:58.216473"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
|
@ -223,7 +223,27 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
|
||||||
security: [%{"oAuth" => ["write:mutes"]}],
|
security: [%{"oAuth" => ["write:mutes"]}],
|
||||||
description: "Do not receive notifications for the thread that this status is part of.",
|
description: "Do not receive notifications for the thread that this status is part of.",
|
||||||
operationId: "StatusController.mute_conversation",
|
operationId: "StatusController.mute_conversation",
|
||||||
parameters: [id_param()],
|
requestBody:
|
||||||
|
request_body("Parameters", %Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
expires_in: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
nullable: true,
|
||||||
|
description: "Expire the mute in `expires_in` seconds. Default 0 for infinity",
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
parameters: [
|
||||||
|
id_param(),
|
||||||
|
Operation.parameter(
|
||||||
|
:expires_in,
|
||||||
|
:query,
|
||||||
|
%Schema{type: :integer, default: 0},
|
||||||
|
"Expire the mute in `expires_in` seconds. Default 0 for infinity"
|
||||||
|
)
|
||||||
|
],
|
||||||
responses: %{
|
responses: %{
|
||||||
200 => status_response(),
|
200 => status_response(),
|
||||||
400 => Operation.response("Error", "application/json", ApiError)
|
400 => Operation.response("Error", "application/json", ApiError)
|
||||||
|
|
|
@ -59,6 +59,7 @@ defmodule Pleroma.Web.ApiSpec.TimelineOperation do
|
||||||
security: [%{"oAuth" => ["read:statuses"]}],
|
security: [%{"oAuth" => ["read:statuses"]}],
|
||||||
parameters: [
|
parameters: [
|
||||||
local_param(),
|
local_param(),
|
||||||
|
instance_param(),
|
||||||
only_media_param(),
|
only_media_param(),
|
||||||
with_muted_param(),
|
with_muted_param(),
|
||||||
exclude_visibilities_param(),
|
exclude_visibilities_param(),
|
||||||
|
@ -158,8 +159,17 @@ defmodule Pleroma.Web.ApiSpec.TimelineOperation do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp instance_param do
|
||||||
|
Operation.parameter(
|
||||||
|
:instance,
|
||||||
|
:query,
|
||||||
|
%Schema{type: :string},
|
||||||
|
"Show only statuses from the given domain"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
defp with_muted_param do
|
defp with_muted_param do
|
||||||
Operation.parameter(:with_muted, :query, BooleanLike, "Includeactivities by muted users")
|
Operation.parameter(:with_muted, :query, BooleanLike, "Include activities by muted users")
|
||||||
end
|
end
|
||||||
|
|
||||||
defp exclude_visibilities_param do
|
defp exclude_visibilities_param do
|
||||||
|
|
|
@ -28,8 +28,11 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Poll do
|
||||||
},
|
},
|
||||||
votes_count: %Schema{
|
votes_count: %Schema{
|
||||||
type: :integer,
|
type: :integer,
|
||||||
nullable: true,
|
description: "How many votes have been received. Number."
|
||||||
description: "How many votes have been received. Number, or null if `multiple` is false."
|
},
|
||||||
|
voters_count: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
description: "How many unique accounts have voted. Number."
|
||||||
},
|
},
|
||||||
voted: %Schema{
|
voted: %Schema{
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
|
@ -61,7 +64,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Poll do
|
||||||
expired: true,
|
expired: true,
|
||||||
multiple: false,
|
multiple: false,
|
||||||
votes_count: 10,
|
votes_count: 10,
|
||||||
voters_count: nil,
|
voters_count: 10,
|
||||||
voted: true,
|
voted: true,
|
||||||
own_votes: [
|
own_votes: [
|
||||||
1
|
1
|
||||||
|
|
|
@ -437,20 +437,46 @@ defmodule Pleroma.Web.CommonAPI do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_mute(user, activity) do
|
def add_mute(user, activity, params \\ %{}) do
|
||||||
|
expires_in = Map.get(params, :expires_in, 0)
|
||||||
|
|
||||||
with {:ok, _} <- ThreadMute.add_mute(user.id, activity.data["context"]),
|
with {:ok, _} <- ThreadMute.add_mute(user.id, activity.data["context"]),
|
||||||
_ <- Pleroma.Notification.mark_context_as_read(user, activity.data["context"]) do
|
_ <- Pleroma.Notification.mark_context_as_read(user, activity.data["context"]) do
|
||||||
|
if expires_in > 0 do
|
||||||
|
Pleroma.Workers.MuteExpireWorker.enqueue(
|
||||||
|
"unmute_conversation",
|
||||||
|
%{"user_id" => user.id, "activity_id" => activity.id},
|
||||||
|
schedule_in: expires_in
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
{:ok, activity}
|
{:ok, activity}
|
||||||
else
|
else
|
||||||
{:error, _} -> {:error, dgettext("errors", "conversation is already muted")}
|
{:error, _} -> {:error, dgettext("errors", "conversation is already muted")}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_mute(user, activity) do
|
def remove_mute(%User{} = user, %Activity{} = activity) do
|
||||||
ThreadMute.remove_mute(user.id, activity.data["context"])
|
ThreadMute.remove_mute(user.id, activity.data["context"])
|
||||||
{:ok, activity}
|
{:ok, activity}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def remove_mute(user_id, activity_id) do
|
||||||
|
with {:user, %User{} = user} <- {:user, User.get_by_id(user_id)},
|
||||||
|
{:activity, %Activity{} = activity} <- {:activity, Activity.get_by_id(activity_id)} do
|
||||||
|
remove_mute(user, activity)
|
||||||
|
else
|
||||||
|
{what, result} = error ->
|
||||||
|
Logger.warn(
|
||||||
|
"CommonAPI.remove_mute/2 failed. #{what}: #{result}, user_id: #{user_id}, activity_id: #{
|
||||||
|
activity_id
|
||||||
|
}"
|
||||||
|
)
|
||||||
|
|
||||||
|
{:error, error}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def thread_muted?(%User{id: user_id}, %{data: %{"context" => context}})
|
def thread_muted?(%User{id: user_id}, %{data: %{"context" => context}})
|
||||||
when is_binary(context) do
|
when is_binary(context) do
|
||||||
ThreadMute.exists?(user_id, context)
|
ThreadMute.exists?(user_id, context)
|
||||||
|
|
|
@ -37,10 +37,11 @@ defmodule Pleroma.Web.Fallback.RedirectController do
|
||||||
|
|
||||||
tags = build_tags(conn, params)
|
tags = build_tags(conn, params)
|
||||||
preloads = preload_data(conn, params)
|
preloads = preload_data(conn, params)
|
||||||
|
title = "<title>#{Pleroma.Config.get([:instance, :name])}</title>"
|
||||||
|
|
||||||
response =
|
response =
|
||||||
index_content
|
index_content
|
||||||
|> String.replace("<!--server-generated-meta-->", tags <> preloads)
|
|> String.replace("<!--server-generated-meta-->", tags <> preloads <> title)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_resp_content_type("text/html")
|
|> put_resp_content_type("text/html")
|
||||||
|
@ -54,10 +55,11 @@ defmodule Pleroma.Web.Fallback.RedirectController do
|
||||||
def redirector_with_preload(conn, params) do
|
def redirector_with_preload(conn, params) do
|
||||||
{:ok, index_content} = File.read(index_file_path())
|
{:ok, index_content} = File.read(index_file_path())
|
||||||
preloads = preload_data(conn, params)
|
preloads = preload_data(conn, params)
|
||||||
|
title = "<title>#{Pleroma.Config.get([:instance, :name])}</title>"
|
||||||
|
|
||||||
response =
|
response =
|
||||||
index_content
|
index_content
|
||||||
|> String.replace("<!--server-generated-meta-->", preloads)
|
|> String.replace("<!--server-generated-meta-->", preloads <> title)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_resp_content_type("text/html")
|
|> put_resp_content_type("text/html")
|
||||||
|
|
|
@ -83,7 +83,7 @@ defmodule Pleroma.Web.Feed.FeedView do
|
||||||
|
|
||||||
def activity_content(_), do: ""
|
def activity_content(_), do: ""
|
||||||
|
|
||||||
def activity_context(activity), do: activity.data["context"]
|
def activity_context(activity), do: escape(activity.data["context"])
|
||||||
|
|
||||||
def attachment_href(attachment) do
|
def attachment_href(attachment) do
|
||||||
attachment["url"]
|
attachment["url"]
|
||||||
|
|
|
@ -394,7 +394,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
||||||
|
|
||||||
@doc "POST /api/v1/accounts/:id/mute"
|
@doc "POST /api/v1/accounts/:id/mute"
|
||||||
def mute(%{assigns: %{user: muter, account: muted}, body_params: params} = conn, _params) do
|
def mute(%{assigns: %{user: muter, account: muted}, body_params: params} = conn, _params) do
|
||||||
with {:ok, _user_relationships} <- User.mute(muter, muted, params.notifications) do
|
with {:ok, _user_relationships} <- User.mute(muter, muted, params) do
|
||||||
render(conn, "relationship.json", user: muter, target: muted)
|
render(conn, "relationship.json", user: muter, target: muted)
|
||||||
else
|
else
|
||||||
{:error, message} -> json_response(conn, :forbidden, %{error: message})
|
{:error, message} -> json_response(conn, :forbidden, %{error: message})
|
||||||
|
|
|
@ -284,9 +284,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc "POST /api/v1/statuses/:id/mute"
|
@doc "POST /api/v1/statuses/:id/mute"
|
||||||
def mute_conversation(%{assigns: %{user: user}} = conn, %{id: id}) do
|
def mute_conversation(%{assigns: %{user: user}, body_params: params} = conn, %{id: id}) do
|
||||||
with %Activity{} = activity <- Activity.get_by_id(id),
|
with %Activity{} = activity <- Activity.get_by_id(id),
|
||||||
{:ok, activity} <- CommonAPI.add_mute(user, activity) do
|
{:ok, activity} <- CommonAPI.add_mute(user, activity, params) do
|
||||||
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
|
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -111,6 +111,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
|
||||||
|> Map.put(:blocking_user, user)
|
|> Map.put(:blocking_user, user)
|
||||||
|> Map.put(:muting_user, user)
|
|> Map.put(:muting_user, user)
|
||||||
|> Map.put(:reply_filtering_user, user)
|
|> Map.put(:reply_filtering_user, user)
|
||||||
|
|> Map.put(:instance, params[:instance])
|
||||||
|> ActivityPub.fetch_public_activities()
|
|> ActivityPub.fetch_public_activities()
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|
|
|
@ -23,7 +23,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
|
||||||
streaming_api: Pleroma.Web.Endpoint.websocket_url()
|
streaming_api: Pleroma.Web.Endpoint.websocket_url()
|
||||||
},
|
},
|
||||||
stats: Pleroma.Stats.get_stats(),
|
stats: Pleroma.Stats.get_stats(),
|
||||||
thumbnail: Keyword.get(instance, :instance_thumbnail),
|
thumbnail: Pleroma.Web.base_url() <> Keyword.get(instance, :instance_thumbnail),
|
||||||
languages: ["en"],
|
languages: ["en"],
|
||||||
registrations: Keyword.get(instance, :registrations_open),
|
registrations: Keyword.get(instance, :registrations_open),
|
||||||
approval_required: Keyword.get(instance, :account_approval_required),
|
approval_required: Keyword.get(instance, :account_approval_required),
|
||||||
|
@ -34,7 +34,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
|
||||||
avatar_upload_limit: Keyword.get(instance, :avatar_upload_limit),
|
avatar_upload_limit: Keyword.get(instance, :avatar_upload_limit),
|
||||||
background_upload_limit: Keyword.get(instance, :background_upload_limit),
|
background_upload_limit: Keyword.get(instance, :background_upload_limit),
|
||||||
banner_upload_limit: Keyword.get(instance, :banner_upload_limit),
|
banner_upload_limit: Keyword.get(instance, :banner_upload_limit),
|
||||||
background_image: Keyword.get(instance, :background_image),
|
background_image: Pleroma.Web.base_url() <> Keyword.get(instance, :background_image),
|
||||||
chat_limit: Keyword.get(instance, :chat_limit),
|
chat_limit: Keyword.get(instance, :chat_limit),
|
||||||
description_limit: Keyword.get(instance, :description_limit),
|
description_limit: Keyword.get(instance, :description_limit),
|
||||||
pleroma: %{
|
pleroma: %{
|
||||||
|
|
|
@ -11,6 +11,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.UserRelationship
|
alias Pleroma.UserRelationship
|
||||||
|
alias Pleroma.Web.AdminAPI.Report
|
||||||
|
alias Pleroma.Web.AdminAPI.ReportView
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.MastodonAPI.AccountView
|
alias Pleroma.Web.MastodonAPI.AccountView
|
||||||
alias Pleroma.Web.MastodonAPI.NotificationView
|
alias Pleroma.Web.MastodonAPI.NotificationView
|
||||||
|
@ -118,11 +120,20 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do
|
||||||
"pleroma:chat_mention" ->
|
"pleroma:chat_mention" ->
|
||||||
put_chat_message(response, activity, reading_user, status_render_opts)
|
put_chat_message(response, activity, reading_user, status_render_opts)
|
||||||
|
|
||||||
|
"pleroma:report" ->
|
||||||
|
put_report(response, activity)
|
||||||
|
|
||||||
type when type in ["follow", "follow_request"] ->
|
type when type in ["follow", "follow_request"] ->
|
||||||
response
|
response
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp put_report(response, activity) do
|
||||||
|
report_render = ReportView.render("show.json", Report.extract_report_info(activity))
|
||||||
|
|
||||||
|
Map.put(response, :report, report_render)
|
||||||
|
end
|
||||||
|
|
||||||
defp put_emoji(response, activity) do
|
defp put_emoji(response, activity) do
|
||||||
Map.put(response, :emoji, activity.data["content"])
|
Map.put(response, :emoji, activity.data["content"])
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,7 +19,7 @@ defmodule Pleroma.Web.MastodonAPI.PollView do
|
||||||
expired: expired,
|
expired: expired,
|
||||||
multiple: multiple,
|
multiple: multiple,
|
||||||
votes_count: votes_count,
|
votes_count: votes_count,
|
||||||
voters_count: (multiple || nil) && voters_count(object),
|
voters_count: voters_count(object),
|
||||||
options: options,
|
options: options,
|
||||||
voted: voted?(params),
|
voted: voted?(params),
|
||||||
emojis: Pleroma.Web.MastodonAPI.StatusView.build_emojis(object.data["emoji"])
|
emojis: Pleroma.Web.MastodonAPI.StatusView.build_emojis(object.data["emoji"])
|
||||||
|
|
|
@ -435,7 +435,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
||||||
text_url: href,
|
text_url: href,
|
||||||
type: type,
|
type: type,
|
||||||
description: attachment["name"],
|
description: attachment["name"],
|
||||||
pleroma: %{mime_type: media_type}
|
pleroma: %{mime_type: media_type},
|
||||||
|
blurhash: attachment["blurhash"]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView
|
alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView
|
||||||
alias Pleroma.Web.PleromaAPI.ChatView
|
|
||||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||||
|
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
@ -121,9 +120,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
|
||||||
) do
|
) do
|
||||||
with {:ok, chat} <- Chat.get_by_user_and_id(user, id),
|
with {:ok, chat} <- Chat.get_by_user_and_id(user, id),
|
||||||
{_n, _} <- MessageReference.set_all_seen_for_chat(chat, last_read_id) do
|
{_n, _} <- MessageReference.set_all_seen_for_chat(chat, last_read_id) do
|
||||||
conn
|
render(conn, "show.json", chat: chat)
|
||||||
|> put_view(ChatView)
|
|
||||||
|> render("show.json", chat: chat)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -141,33 +138,30 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def index(%{assigns: %{user: %{id: user_id} = user}} = conn, _params) do
|
def index(%{assigns: %{user: %{id: user_id} = user}} = conn, params) do
|
||||||
blocked_ap_ids = User.blocked_users_ap_ids(user)
|
exclude_users =
|
||||||
|
User.blocked_users_ap_ids(user) ++
|
||||||
|
if params[:with_muted], do: [], else: User.muted_users_ap_ids(user)
|
||||||
|
|
||||||
chats =
|
chats =
|
||||||
Chat.for_user_query(user_id)
|
user_id
|
||||||
|> where([c], c.recipient not in ^blocked_ap_ids)
|
|> Chat.for_user_query()
|
||||||
|
|> where([c], c.recipient not in ^exclude_users)
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
|
|
||||||
conn
|
render(conn, "index.json", chats: chats)
|
||||||
|> put_view(ChatView)
|
|
||||||
|> render("index.json", chats: chats)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def create(%{assigns: %{user: user}} = conn, %{id: id}) do
|
def create(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||||
with %User{ap_id: recipient} <- User.get_cached_by_id(id),
|
with %User{ap_id: recipient} <- User.get_cached_by_id(id),
|
||||||
{:ok, %Chat{} = chat} <- Chat.get_or_create(user.id, recipient) do
|
{:ok, %Chat{} = chat} <- Chat.get_or_create(user.id, recipient) do
|
||||||
conn
|
render(conn, "show.json", chat: chat)
|
||||||
|> put_view(ChatView)
|
|
||||||
|> render("show.json", chat: chat)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def show(%{assigns: %{user: user}} = conn, %{id: id}) do
|
def show(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||||
with {:ok, chat} <- Chat.get_by_user_and_id(user, id) do
|
with {:ok, chat} <- Chat.get_by_user_and_id(user, id) do
|
||||||
conn
|
render(conn, "show.json", chat: chat)
|
||||||
|> put_view(ChatView)
|
|
||||||
|> render("show.json", chat: chat)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.PleromaAPI.InstancesController do
|
||||||
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
alias Pleroma.Instances
|
||||||
|
|
||||||
|
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||||
|
|
||||||
|
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaInstancesOperation
|
||||||
|
|
||||||
|
def show(conn, _params) do
|
||||||
|
unreachable =
|
||||||
|
Instances.get_consistently_unreachable()
|
||||||
|
|> Map.new(fn {host, date} -> {host, to_string(date)} end)
|
||||||
|
|
||||||
|
json(conn, %{"unreachable" => unreachable})
|
||||||
|
end
|
||||||
|
end
|
|
@ -398,6 +398,7 @@ defmodule Pleroma.Web.Router do
|
||||||
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
|
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
|
||||||
pipe_through(:api)
|
pipe_through(:api)
|
||||||
get("/accounts/:id/scrobbles", ScrobbleController, :index)
|
get("/accounts/:id/scrobbles", ScrobbleController, :index)
|
||||||
|
get("/federation_status", InstancesController, :show)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/api/v1", Pleroma.Web.MastodonAPI do
|
scope "/api/v1", Pleroma.Web.MastodonAPI do
|
||||||
|
|
|
@ -57,6 +57,15 @@ defmodule Pleroma.Web.Streamer do
|
||||||
{:ok, "hashtag:" <> tag}
|
{:ok, "hashtag:" <> tag}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Allow remote instance streams.
|
||||||
|
def get_topic("public:remote", _user, _oauth_token, %{"instance" => instance} = _params) do
|
||||||
|
{:ok, "public:remote:" <> instance}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_topic("public:remote:media", _user, _oauth_token, %{"instance" => instance} = _params) do
|
||||||
|
{:ok, "public:remote:media:" <> instance}
|
||||||
|
end
|
||||||
|
|
||||||
# Expand user streams.
|
# Expand user streams.
|
||||||
def get_topic(
|
def get_topic(
|
||||||
stream,
|
stream,
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<link href="<%= activity_context(@activity) %>" rel="ostatus:conversation"/>
|
<link href="<%= activity_context(@activity) %>" rel="ostatus:conversation"/>
|
||||||
|
|
||||||
<%= if @data["summary"] do %>
|
<%= if @data["summary"] do %>
|
||||||
<summary><%= @data["summary"] %></summary>
|
<summary><%= escape(@data["summary"]) %></summary>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= if @activity.local do %>
|
<%= if @activity.local do %>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<link rel="ostatus:conversation"><%= activity_context(@activity) %></link>
|
<link rel="ostatus:conversation"><%= activity_context(@activity) %></link>
|
||||||
|
|
||||||
<%= if @data["summary"] do %>
|
<%= if @data["summary"] do %>
|
||||||
<description><%= @data["summary"] %></description>
|
<description><%= escape(@data["summary"]) %></description>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= if @activity.local do %>
|
<%= if @activity.local do %>
|
||||||
|
|
20
lib/pleroma/workers/mute_expire_worker.ex
Normal file
20
lib/pleroma/workers/mute_expire_worker.ex
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Workers.MuteExpireWorker do
|
||||||
|
use Pleroma.Workers.WorkerHelper, queue: "mute_expire"
|
||||||
|
|
||||||
|
@impl Oban.Worker
|
||||||
|
def perform(%Job{args: %{"op" => "unmute_user", "muter_id" => muter_id, "mutee_id" => mutee_id}}) do
|
||||||
|
Pleroma.User.unmute(muter_id, mutee_id)
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform(%Job{
|
||||||
|
args: %{"op" => "unmute_conversation", "user_id" => user_id, "activity_id" => activity_id}
|
||||||
|
}) do
|
||||||
|
Pleroma.Web.CommonAPI.remove_mute(user_id, activity_id)
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
9
mix.exs
9
mix.exs
|
@ -4,7 +4,7 @@ defmodule Pleroma.Mixfile do
|
||||||
def project do
|
def project do
|
||||||
[
|
[
|
||||||
app: :pleroma,
|
app: :pleroma,
|
||||||
version: version("2.1.50"),
|
version: version("2.2.50"),
|
||||||
elixir: "~> 1.9",
|
elixir: "~> 1.9",
|
||||||
elixirc_paths: elixirc_paths(Mix.env()),
|
elixirc_paths: elixirc_paths(Mix.env()),
|
||||||
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
|
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
|
||||||
|
@ -133,17 +133,14 @@ defmodule Pleroma.Mixfile do
|
||||||
{:calendar, "~> 1.0"},
|
{:calendar, "~> 1.0"},
|
||||||
{:cachex, "~> 3.2"},
|
{:cachex, "~> 3.2"},
|
||||||
{:poison, "~> 3.0", override: true},
|
{:poison, "~> 3.0", override: true},
|
||||||
{:tesla,
|
{:tesla, "~> 1.4.0", override: true},
|
||||||
git: "https://github.com/teamon/tesla.git",
|
|
||||||
ref: "9f7261ca49f9f901ceb73b60219ad6f8a9f6aa30",
|
|
||||||
override: true},
|
|
||||||
{:castore, "~> 0.1"},
|
{:castore, "~> 0.1"},
|
||||||
{:cowlib, "~> 2.9", override: true},
|
{:cowlib, "~> 2.9", override: true},
|
||||||
{:gun,
|
{:gun,
|
||||||
github: "ninenines/gun", ref: "921c47146b2d9567eac7e9a4d2ccc60fffd4f327", override: true},
|
github: "ninenines/gun", ref: "921c47146b2d9567eac7e9a4d2ccc60fffd4f327", override: true},
|
||||||
{:jason, "~> 1.2"},
|
{:jason, "~> 1.2"},
|
||||||
{:mogrify, "~> 0.7.4"},
|
{:mogrify, "~> 0.7.4"},
|
||||||
{:ex_aws, "~> 2.1"},
|
{:ex_aws, "~> 2.1.6"},
|
||||||
{:ex_aws_s3, "~> 2.0"},
|
{:ex_aws_s3, "~> 2.0"},
|
||||||
{:sweet_xml, "~> 0.6.6"},
|
{:sweet_xml, "~> 0.6.6"},
|
||||||
{:earmark, "1.4.3"},
|
{:earmark, "1.4.3"},
|
||||||
|
|
4
mix.lock
4
mix.lock
|
@ -37,7 +37,7 @@
|
||||||
"esshd": {:hex, :esshd, "0.1.1", "d4dd4c46698093a40a56afecce8a46e246eb35463c457c246dacba2e056f31b5", [:mix], [], "hexpm", "d73e341e3009d390aa36387dc8862860bf9f874c94d9fd92ade2926376f49981"},
|
"esshd": {:hex, :esshd, "0.1.1", "d4dd4c46698093a40a56afecce8a46e246eb35463c457c246dacba2e056f31b5", [:mix], [], "hexpm", "d73e341e3009d390aa36387dc8862860bf9f874c94d9fd92ade2926376f49981"},
|
||||||
"eternal": {:hex, :eternal, "1.2.1", "d5b6b2499ba876c57be2581b5b999ee9bdf861c647401066d3eeed111d096bc4", [:mix], [], "hexpm", "b14f1dc204321429479c569cfbe8fb287541184ed040956c8862cb7a677b8406"},
|
"eternal": {:hex, :eternal, "1.2.1", "d5b6b2499ba876c57be2581b5b999ee9bdf861c647401066d3eeed111d096bc4", [:mix], [], "hexpm", "b14f1dc204321429479c569cfbe8fb287541184ed040956c8862cb7a677b8406"},
|
||||||
"ex2ms": {:hex, :ex2ms, "1.5.0", "19e27f9212be9a96093fed8cdfbef0a2b56c21237196d26760f11dfcfae58e97", [:mix], [], "hexpm"},
|
"ex2ms": {:hex, :ex2ms, "1.5.0", "19e27f9212be9a96093fed8cdfbef0a2b56c21237196d26760f11dfcfae58e97", [:mix], [], "hexpm"},
|
||||||
"ex_aws": {:hex, :ex_aws, "2.1.3", "26b6f036f0127548706aade4a509978fc7c26bd5334b004fba9bfe2687a525df", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8", [hex: :jsx, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "0bdbe2aed9f326922fc5a6a80417e32f0c895f4b3b2b0b9676ebf23dd16c5da4"},
|
"ex_aws": {:hex, :ex_aws, "2.1.6", "41ab8b4caa48035c96d07faa035d2d9de6df480e7e084c054e662ac888dcd4d4", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8", [hex: :jsx, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "a541bd042c1ee26412bb1e749ddf2a1c327e4fb7e382b1cd227e1b00eed3d469"},
|
||||||
"ex_aws_s3": {:hex, :ex_aws_s3, "2.0.2", "c0258bbdfea55de4f98f0b2f0ca61fe402cc696f573815134beb1866e778f47b", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "0569f5b211b1a3b12b705fe2a9d0e237eb1360b9d76298028df2346cad13097a"},
|
"ex_aws_s3": {:hex, :ex_aws_s3, "2.0.2", "c0258bbdfea55de4f98f0b2f0ca61fe402cc696f573815134beb1866e778f47b", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "0569f5b211b1a3b12b705fe2a9d0e237eb1360b9d76298028df2346cad13097a"},
|
||||||
"ex_const": {:hex, :ex_const, "0.2.4", "d06e540c9d834865b012a17407761455efa71d0ce91e5831e86881b9c9d82448", [:mix], [], "hexpm", "96fd346610cc992b8f896ed26a98be82ac4efb065a0578f334a32d60a3ba9767"},
|
"ex_const": {:hex, :ex_const, "0.2.4", "d06e540c9d834865b012a17407761455efa71d0ce91e5831e86881b9c9d82448", [:mix], [], "hexpm", "96fd346610cc992b8f896ed26a98be82ac4efb065a0578f334a32d60a3ba9767"},
|
||||||
"ex_doc": {:hex, :ex_doc, "0.22.2", "03a2a58bdd2ba0d83d004507c4ee113b9c521956938298eba16e55cc4aba4a6c", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "cf60e1b3e2efe317095b6bb79651f83a2c1b3edcb4d319c421d7fcda8b3aff26"},
|
"ex_doc": {:hex, :ex_doc, "0.22.2", "03a2a58bdd2ba0d83d004507c4ee113b9c521956938298eba16e55cc4aba4a6c", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "cf60e1b3e2efe317095b6bb79651f83a2c1b3edcb4d319c421d7fcda8b3aff26"},
|
||||||
|
@ -115,7 +115,7 @@
|
||||||
"swoosh": {:hex, :swoosh, "1.0.6", "6765e334c67dacabe721f0d701c7e5a6f06e4595c90df6f91e73ebd54d555833", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "7c50ef78e4acfd1cbd4907dc1fa87b5540675a6be9dc979d04890f49d7ec1830"},
|
"swoosh": {:hex, :swoosh, "1.0.6", "6765e334c67dacabe721f0d701c7e5a6f06e4595c90df6f91e73ebd54d555833", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "7c50ef78e4acfd1cbd4907dc1fa87b5540675a6be9dc979d04890f49d7ec1830"},
|
||||||
"syslog": {:hex, :syslog, "1.1.0", "6419a232bea84f07b56dc575225007ffe34d9fdc91abe6f1b2f254fd71d8efc2", [:rebar3], [], "hexpm", "4c6a41373c7e20587be33ef841d3de6f3beba08519809329ecc4d27b15b659e1"},
|
"syslog": {:hex, :syslog, "1.1.0", "6419a232bea84f07b56dc575225007ffe34d9fdc91abe6f1b2f254fd71d8efc2", [:rebar3], [], "hexpm", "4c6a41373c7e20587be33ef841d3de6f3beba08519809329ecc4d27b15b659e1"},
|
||||||
"telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
|
"telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
|
||||||
"tesla": {:git, "https://github.com/teamon/tesla.git", "9f7261ca49f9f901ceb73b60219ad6f8a9f6aa30", [ref: "9f7261ca49f9f901ceb73b60219ad6f8a9f6aa30"]},
|
"tesla": {:hex, :tesla, "1.4.0", "1081bef0124b8bdec1c3d330bbe91956648fb008cf0d3950a369cda466a31a87", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.3", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "bf1374a5569f5fca8e641363b63f7347d680d91388880979a33bc12a6eb3e0aa"},
|
||||||
"timex": {:hex, :timex, "3.6.2", "845cdeb6119e2fef10751c0b247b6c59d86d78554c83f78db612e3290f819bc2", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "26030b46199d02a590be61c2394b37ea25a3664c02fafbeca0b24c972025d47a"},
|
"timex": {:hex, :timex, "3.6.2", "845cdeb6119e2fef10751c0b247b6c59d86d78554c83f78db612e3290f819bc2", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "26030b46199d02a590be61c2394b37ea25a3664c02fafbeca0b24c972025d47a"},
|
||||||
"trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bd4fde4c15f3e993a999e019d64347489b91b7a9096af68b2bdadd192afa693f"},
|
"trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bd4fde4c15f3e993a999e019d64347489b91b7a9096af68b2bdadd192afa693f"},
|
||||||
"tzdata": {:hex, :tzdata, "1.0.4", "a3baa4709ea8dba552dca165af6ae97c624a2d6ac14bd265165eaa8e8af94af6", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "b02637db3df1fd66dd2d3c4f194a81633d0e4b44308d36c1b2fdfd1e4e6f169b"},
|
"tzdata": {:hex, :tzdata, "1.0.4", "a3baa4709ea8dba552dca165af6ae97c624a2d6ac14bd265165eaa8e8af94af6", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "b02637db3df1fd66dd2d3c4f194a81633d0e4b44308d36c1b2fdfd1e4e6f169b"},
|
||||||
|
|
596
priv/gettext/he/LC_MESSAGES/errors.po
Normal file
596
priv/gettext/he/LC_MESSAGES/errors.po
Normal file
|
@ -0,0 +1,596 @@
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2020-11-10 13:39+0000\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: Automatically generated\n"
|
||||||
|
"Language-Team: none\n"
|
||||||
|
"Language: he\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Generator: Translate Toolkit 2.5.1\n"
|
||||||
|
|
||||||
|
## This file is a PO Template file.
|
||||||
|
##
|
||||||
|
## `msgid`s here are often extracted from source code.
|
||||||
|
## Add new translations manually only if they're dynamic
|
||||||
|
## translations that can't be statically extracted.
|
||||||
|
##
|
||||||
|
## Run `mix gettext.extract` to bring this file up to
|
||||||
|
## date. Leave `msgstr`s empty as changing them here as no
|
||||||
|
## effect: edit them in PO (`.po`) files instead.
|
||||||
|
## From Ecto.Changeset.cast/4
|
||||||
|
msgid "can't be blank"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
## From Ecto.Changeset.unique_constraint/3
|
||||||
|
msgid "has already been taken"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
## From Ecto.Changeset.put_change/3
|
||||||
|
msgid "is invalid"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
## From Ecto.Changeset.validate_format/3
|
||||||
|
msgid "has invalid format"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
## From Ecto.Changeset.validate_subset/3
|
||||||
|
msgid "has an invalid entry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
## From Ecto.Changeset.validate_exclusion/3
|
||||||
|
msgid "is reserved"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
## From Ecto.Changeset.validate_confirmation/3
|
||||||
|
msgid "does not match confirmation"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
## From Ecto.Changeset.no_assoc_constraint/3
|
||||||
|
msgid "is still associated with this entry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "are still associated with this entry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
## From Ecto.Changeset.validate_length/3
|
||||||
|
msgid "should be %{count} character(s)"
|
||||||
|
msgid_plural "should be %{count} character(s)"
|
||||||
|
msgstr[0] ""
|
||||||
|
msgstr[1] ""
|
||||||
|
msgstr[2] ""
|
||||||
|
msgstr[3] ""
|
||||||
|
|
||||||
|
msgid "should have %{count} item(s)"
|
||||||
|
msgid_plural "should have %{count} item(s)"
|
||||||
|
msgstr[0] ""
|
||||||
|
msgstr[1] ""
|
||||||
|
msgstr[2] ""
|
||||||
|
msgstr[3] ""
|
||||||
|
|
||||||
|
msgid "should be at least %{count} character(s)"
|
||||||
|
msgid_plural "should be at least %{count} character(s)"
|
||||||
|
msgstr[0] ""
|
||||||
|
msgstr[1] ""
|
||||||
|
msgstr[2] ""
|
||||||
|
msgstr[3] ""
|
||||||
|
|
||||||
|
msgid "should have at least %{count} item(s)"
|
||||||
|
msgid_plural "should have at least %{count} item(s)"
|
||||||
|
msgstr[0] ""
|
||||||
|
msgstr[1] ""
|
||||||
|
msgstr[2] ""
|
||||||
|
msgstr[3] ""
|
||||||
|
|
||||||
|
msgid "should be at most %{count} character(s)"
|
||||||
|
msgid_plural "should be at most %{count} character(s)"
|
||||||
|
msgstr[0] ""
|
||||||
|
msgstr[1] ""
|
||||||
|
msgstr[2] ""
|
||||||
|
msgstr[3] ""
|
||||||
|
|
||||||
|
msgid "should have at most %{count} item(s)"
|
||||||
|
msgid_plural "should have at most %{count} item(s)"
|
||||||
|
msgstr[0] ""
|
||||||
|
msgstr[1] ""
|
||||||
|
msgstr[2] ""
|
||||||
|
msgstr[3] ""
|
||||||
|
|
||||||
|
## From Ecto.Changeset.validate_number/3
|
||||||
|
msgid "must be less than %{number}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "must be greater than %{number}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "must be less than or equal to %{number}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "must be greater than or equal to %{number}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "must be equal to %{number}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:505
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Account not found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:339
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Already voted"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/oauth/oauth_controller.ex:359
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Bad request"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:426
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Can't delete object"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/controller_helper.ex:105
|
||||||
|
#: lib/pleroma/web/controller_helper.ex:111
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Can't display this activity"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:285
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Can't find user"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:61
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Can't get favorites"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:438
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Can't like object"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/utils.ex:563
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Cannot post an empty status without attachments"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/utils.ex:511
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Comment must be up to %{max_size} characters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/config/config_db.ex:191
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Config with params %{params} not found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:181
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:185
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Could not delete"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:231
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Could not favorite"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:453
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Could not pin"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:278
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Could not unfavorite"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:463
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Could not unpin"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:216
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Could not unrepeat"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:512
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:521
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Could not update state"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:207
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Error."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/twitter_api/twitter_api.ex:106
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Invalid CAPTCHA"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:116
|
||||||
|
#: lib/pleroma/web/oauth/oauth_controller.ex:568
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Invalid credentials"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:38
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Invalid credentials."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:355
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Invalid indices"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:29
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Invalid parameters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/utils.ex:414
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Invalid password."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:220
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Invalid request"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/twitter_api/twitter_api.ex:109
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Kocaptcha service unavailable"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:112
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Missing parameters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/utils.ex:547
|
||||||
|
#, elixir-format
|
||||||
|
msgid "No such conversation"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:388
|
||||||
|
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:414 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:456
|
||||||
|
#, elixir-format
|
||||||
|
msgid "No such permission_group"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/plugs/uploaded_media.ex:84
|
||||||
|
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:486 lib/pleroma/web/admin_api/controllers/fallback_controller.ex:11
|
||||||
|
#: lib/pleroma/web/feed/user_controller.ex:71 lib/pleroma/web/ostatus/ostatus_controller.ex:143
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Not found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:331
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Poll's author can't vote"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:20
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:37 lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:49
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:50 lib/pleroma/web/mastodon_api/controllers/status_controller.ex:306
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:71
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Record not found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:35
|
||||||
|
#: lib/pleroma/web/feed/user_controller.ex:77 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:36
|
||||||
|
#: lib/pleroma/web/ostatus/ostatus_controller.ex:149
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Something went wrong"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/activity_draft.ex:107
|
||||||
|
#, elixir-format
|
||||||
|
msgid "The message visibility must be direct"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/utils.ex:573
|
||||||
|
#, elixir-format
|
||||||
|
msgid "The status is over the character limit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31
|
||||||
|
#, elixir-format
|
||||||
|
msgid "This resource requires authentication."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Throttled"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:356
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Too many choices"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:443
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Unhandled activity type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:485
|
||||||
|
#, elixir-format
|
||||||
|
msgid "You can't revoke your own admin status."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/oauth/oauth_controller.ex:221
|
||||||
|
#: lib/pleroma/web/oauth/oauth_controller.ex:308
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Your account is currently disabled"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/oauth/oauth_controller.ex:183
|
||||||
|
#: lib/pleroma/web/oauth/oauth_controller.ex:331
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Your login is missing a confirmed e-mail address"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:390
|
||||||
|
#, elixir-format
|
||||||
|
msgid "can't read inbox of %{nickname} as %{as_nickname}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:473
|
||||||
|
#, elixir-format
|
||||||
|
msgid "can't update outbox of %{nickname} as %{as_nickname}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:471
|
||||||
|
#, elixir-format
|
||||||
|
msgid "conversation is already muted"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:314
|
||||||
|
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:492
|
||||||
|
#, elixir-format
|
||||||
|
msgid "error"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:32
|
||||||
|
#, elixir-format
|
||||||
|
msgid "mascots can only be images"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:62
|
||||||
|
#, elixir-format
|
||||||
|
msgid "not found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/oauth/oauth_controller.ex:394
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Bad OAuth request."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/twitter_api/twitter_api.ex:115
|
||||||
|
#, elixir-format
|
||||||
|
msgid "CAPTCHA already used"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/twitter_api/twitter_api.ex:112
|
||||||
|
#, elixir-format
|
||||||
|
msgid "CAPTCHA expired"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/plugs/uploaded_media.ex:57
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/oauth/oauth_controller.ex:410
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Failed to authenticate: %{message}."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/oauth/oauth_controller.ex:441
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Failed to set up user account."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/plugs/oauth_scopes_plug.ex:38
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Insufficient permissions: %{permissions}."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/plugs/uploaded_media.ex:104
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Internal Error"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/oauth/fallback_controller.ex:22
|
||||||
|
#: lib/pleroma/web/oauth/fallback_controller.ex:29
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Invalid Username/Password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/twitter_api/twitter_api.ex:118
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Invalid answer data"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:33
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Nodeinfo schema version not handled"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/oauth/oauth_controller.ex:172
|
||||||
|
#, elixir-format
|
||||||
|
msgid "This action is outside the authorized scopes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/oauth/fallback_controller.ex:14
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Unknown error, please check the details and try again."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/oauth/oauth_controller.ex:119
|
||||||
|
#: lib/pleroma/web/oauth/oauth_controller.ex:158
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Unlisted redirect_uri."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/oauth/oauth_controller.ex:390
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Unsupported OAuth provider: %{provider}."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/uploaders/uploader.ex:72
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Uploader callback timeout"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/uploader_controller.ex:23
|
||||||
|
#, elixir-format
|
||||||
|
msgid "bad request"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/twitter_api/twitter_api.ex:103
|
||||||
|
#, elixir-format
|
||||||
|
msgid "CAPTCHA Error"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:290
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Could not add reaction emoji"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/common_api/common_api.ex:301
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Could not remove reaction emoji"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/twitter_api/twitter_api.ex:129
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Invalid CAPTCHA (Missing parameter: %{name})"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92
|
||||||
|
#, elixir-format
|
||||||
|
msgid "List not found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:123
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Missing parameter: %{name}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/oauth/oauth_controller.ex:210
|
||||||
|
#: lib/pleroma/web/oauth/oauth_controller.ex:321
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Password reset is required"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/tests/auth_test_controller.ex:9
|
||||||
|
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:6 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:6
|
||||||
|
#: lib/pleroma/web/admin_api/controllers/config_controller.ex:6 lib/pleroma/web/admin_api/controllers/fallback_controller.ex:6
|
||||||
|
#: lib/pleroma/web/admin_api/controllers/invite_controller.ex:6 lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex:6
|
||||||
|
#: lib/pleroma/web/admin_api/controllers/oauth_app_controller.ex:6 lib/pleroma/web/admin_api/controllers/relay_controller.ex:6
|
||||||
|
#: lib/pleroma/web/admin_api/controllers/report_controller.ex:6 lib/pleroma/web/admin_api/controllers/status_controller.ex:6
|
||||||
|
#: lib/pleroma/web/controller_helper.ex:6 lib/pleroma/web/embed_controller.ex:6
|
||||||
|
#: lib/pleroma/web/fallback_redirect_controller.ex:6 lib/pleroma/web/feed/tag_controller.ex:6
|
||||||
|
#: lib/pleroma/web/feed/user_controller.ex:6 lib/pleroma/web/mailer/subscription_controller.ex:2
|
||||||
|
#: lib/pleroma/web/masto_fe_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/account_controller.ex:6
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/app_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/auth_controller.ex:6
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex:6
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:6
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/filter_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex:6
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/instance_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/list_controller.ex:6
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/marker_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex:14
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/media_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/notification_controller.ex:6
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/report_controller.ex:8
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/search_controller.ex:6
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:7
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:6
|
||||||
|
#: lib/pleroma/web/media_proxy/media_proxy_controller.ex:6 lib/pleroma/web/mongooseim/mongoose_im_controller.ex:6
|
||||||
|
#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:6 lib/pleroma/web/oauth/fallback_controller.ex:6
|
||||||
|
#: lib/pleroma/web/oauth/mfa_controller.ex:10 lib/pleroma/web/oauth/oauth_controller.ex:6
|
||||||
|
#: lib/pleroma/web/ostatus/ostatus_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/account_controller.ex:6
|
||||||
|
#: lib/pleroma/web/pleroma_api/controllers/chat_controller.ex:5 lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex:6
|
||||||
|
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:2 lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex:6
|
||||||
|
#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/notification_controller.ex:6
|
||||||
|
#: lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex:6
|
||||||
|
#: lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex:7 lib/pleroma/web/static_fe/static_fe_controller.ex:6
|
||||||
|
#: lib/pleroma/web/twitter_api/controllers/password_controller.ex:10 lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex:6
|
||||||
|
#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:6 lib/pleroma/web/twitter_api/twitter_api_controller.ex:6
|
||||||
|
#: lib/pleroma/web/uploader_controller.ex:6 lib/pleroma/web/web_finger/web_finger_controller.ex:6
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Security violation: OAuth scopes check was neither handled nor explicitly skipped."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:28
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Two-factor authentication enabled, you must use a access token."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:210
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Unexpected error occurred while adding file to pack."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:138
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Unexpected error occurred while creating pack."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:278
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Unexpected error occurred while removing file from pack."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:250
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Unexpected error occurred while updating file in pack."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:179
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Unexpected error occurred while updating pack metadata."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Web push subscription is disabled on this Pleroma instance"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:451
|
||||||
|
#, elixir-format
|
||||||
|
msgid "You can't revoke your own admin/moderator status."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:126
|
||||||
|
#, elixir-format
|
||||||
|
msgid "authorization required for timeline view"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:24
|
||||||
|
#, elixir-format
|
||||||
|
msgid "Access denied"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:282
|
||||||
|
#, elixir-format
|
||||||
|
msgid "This API requires an authenticated user"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/pleroma/plugs/user_is_admin_plug.ex:21
|
||||||
|
#, elixir-format
|
||||||
|
msgid "User is not an admin."
|
||||||
|
msgstr ""
|
|
@ -0,0 +1,48 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.AddPleromaReportTypeToEnumForNotifications do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
@disable_ddl_transaction true
|
||||||
|
|
||||||
|
def up do
|
||||||
|
"""
|
||||||
|
alter type notification_type add value 'pleroma:report'
|
||||||
|
"""
|
||||||
|
|> execute()
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
alter table(:notifications) do
|
||||||
|
modify(:type, :string)
|
||||||
|
end
|
||||||
|
|
||||||
|
"""
|
||||||
|
delete from notifications where type = 'pleroma:report'
|
||||||
|
"""
|
||||||
|
|> execute()
|
||||||
|
|
||||||
|
"""
|
||||||
|
drop type if exists notification_type
|
||||||
|
"""
|
||||||
|
|> execute()
|
||||||
|
|
||||||
|
"""
|
||||||
|
create type notification_type as enum (
|
||||||
|
'follow',
|
||||||
|
'follow_request',
|
||||||
|
'mention',
|
||||||
|
'move',
|
||||||
|
'pleroma:emoji_reaction',
|
||||||
|
'pleroma:chat_mention',
|
||||||
|
'reblog',
|
||||||
|
'favourite'
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
|> execute()
|
||||||
|
|
||||||
|
"""
|
||||||
|
alter table notifications
|
||||||
|
alter column type type notification_type using (type::notification_type)
|
||||||
|
"""
|
||||||
|
|> execute()
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,19 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.RemovePurgeExpiredActivityWorkerFromObanConfig do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
with %Pleroma.ConfigDB{} = config <-
|
||||||
|
Pleroma.ConfigDB.get_by_params(%{group: :pleroma, key: Oban}),
|
||||||
|
crontab when is_list(crontab) <- config.value[:crontab],
|
||||||
|
index when is_integer(index) <-
|
||||||
|
Enum.find_index(crontab, fn {_, worker} ->
|
||||||
|
worker == Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker
|
||||||
|
end) do
|
||||||
|
updated_value = Keyword.put(config.value, :crontab, List.delete_at(crontab, index))
|
||||||
|
|
||||||
|
config
|
||||||
|
|> Ecto.Changeset.change(value: updated_value)
|
||||||
|
|> Pleroma.Repo.update()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1 +1 @@
|
||||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link href=/static/css/app.77b1644622e3bae24b6b.css rel=stylesheet><link href=/static/fontello.1600365488745.css rel=stylesheet></head><body class=hidden><noscript>To use Pleroma, please enable JavaScript.</noscript><div id=app></div><script type=text/javascript src=/static/js/vendors~app.90c4af83c1ae68f4cd95.js></script><script type=text/javascript src=/static/js/app.826c44232e0a76bbd9ba.js></script></body></html>
|
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link href=/static/css/app.9a4c5ede37b2f0230836.css rel=stylesheet></head><body class=hidden><noscript>To use Pleroma, please enable JavaScript.</noscript><div id=app></div><script type=text/javascript src=/static/js/vendors~app.952124344a84613dbac0.js></script><script type=text/javascript src=/static/js/app.45547c05212c403dd77c.js></script></body></html>
|
|
@ -10,9 +10,10 @@
|
||||||
"hideSitename": false,
|
"hideSitename": false,
|
||||||
"hideUserStats": false,
|
"hideUserStats": false,
|
||||||
"loginMethod": "password",
|
"loginMethod": "password",
|
||||||
"logo": "/static/logo.png",
|
"logo": "/static/logo.svg",
|
||||||
"logoMargin": ".1em",
|
"logoMargin": ".1em",
|
||||||
"logoMask": true,
|
"logoMask": true,
|
||||||
|
"logoLeft": false,
|
||||||
"minimalScopesMode": false,
|
"minimalScopesMode": false,
|
||||||
"nsfwCensorImage": "",
|
"nsfwCensorImage": "",
|
||||||
"postContentType": "text/plain",
|
"postContentType": "text/plain",
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -3,7 +3,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
.tab-switcher .tab-icon {
|
.tab-switcher .tab-icon {
|
||||||
font-size: 2em;
|
margin: 0.2em auto;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
.tab-switcher.top-tabs {
|
.tab-switcher.top-tabs {
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
}
|
}
|
||||||
@media all and (max-width: 800px) {
|
@media all and (max-width: 800px) {
|
||||||
.tab-switcher.side-tabs > .tabs .tab-wrapper {
|
.tab-switcher.side-tabs > .tabs .tab-wrapper {
|
||||||
min-width: 1em;
|
min-width: 4em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.tab-switcher.side-tabs > .tabs .tab-wrapper:not(.active)::after {
|
.tab-switcher.side-tabs > .tabs .tab-wrapper:not(.active)::after {
|
||||||
|
@ -243,4 +243,4 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*# sourceMappingURL=app.77b1644622e3bae24b6b.css.map*/
|
/*# sourceMappingURL=app.9a4c5ede37b2f0230836.css.map*/
|
1
priv/static/static/css/app.9a4c5ede37b2f0230836.css.map
Normal file
1
priv/static/static/css/app.9a4c5ede37b2f0230836.css.map
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1,140 +0,0 @@
|
||||||
<?xml version="1.0" standalone="no"?>
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<metadata>Copyright (C) 2020 by original authors @ fontello.com</metadata>
|
|
||||||
<defs>
|
|
||||||
<font id="fontello" horiz-adv-x="1000" >
|
|
||||||
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="857" descent="-143" />
|
|
||||||
<missing-glyph horiz-adv-x="1000" />
|
|
||||||
<glyph glyph-name="cancel" unicode="" d="M724 119q0-22-15-38l-76-76q-16-15-38-15t-38 15l-164 165-164-165q-16-15-38-15t-38 15l-76 76q-16 16-16 38t16 38l164 164-164 164q-16 16-16 38t16 38l76 76q16 16 38 16t38-16l164-164 164 164q16 16 38 16t38-16l76-76q15-15 15-38t-15-38l-164-164 164-164q15-15 15-38z" horiz-adv-x="785.7" />
|
|
||||||
|
|
||||||
<glyph glyph-name="upload" unicode="" d="M714 36q0 14-10 25t-25 10-25-10-11-25 11-25 25-11 25 11 10 25z m143 0q0 14-10 25t-26 10-25-10-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-38t-38-16h-821q-23 0-38 16t-16 38v179q0 22 16 38t38 15h238q12-31 39-51t62-20h143q34 0 61 20t40 51h238q22 0 38-15t16-38z m-182 361q-9-22-33-22h-143v-250q0-15-10-25t-25-11h-143q-15 0-25 11t-11 25v250h-143q-23 0-33 22-9 22 8 39l250 250q10 10 25 10t25-10l250-250q18-17 8-39z" horiz-adv-x="928.6" />
|
|
||||||
|
|
||||||
<glyph glyph-name="star" unicode="" d="M929 496q0-12-15-27l-202-197 48-279q0-4 0-12 0-11-6-19t-17-9q-10 0-22 7l-251 132-250-132q-12-7-23-7-11 0-17 9t-6 19q0 4 1 12l48 279-203 197q-14 15-14 27 0 21 31 26l280 40 126 254q11 23 27 23t28-23l125-254 280-40q32-5 32-26z" horiz-adv-x="928.6" />
|
|
||||||
|
|
||||||
<glyph glyph-name="star-empty" unicode="" d="M635 297l170 166-235 34-106 213-105-213-236-34 171-166-41-235 211 111 211-111z m294 199q0-12-15-27l-202-197 48-279q0-4 0-12 0-28-23-28-10 0-22 7l-251 132-250-132q-12-7-23-7-11 0-17 9t-6 19q0 4 1 12l48 279-203 197q-14 15-14 27 0 21 31 26l280 40 126 254q11 23 27 23t28-23l125-254 280-40q32-5 32-26z" horiz-adv-x="928.6" />
|
|
||||||
|
|
||||||
<glyph glyph-name="retweet" unicode="" d="M714 18q0-7-5-13t-13-5h-535q-5 0-8 1t-5 4-3 4-2 7 0 6v335h-107q-15 0-25 11t-11 25q0 13 8 23l179 214q11 12 27 12t28-12l178-214q9-10 9-23 0-15-11-25t-25-11h-107v-214h321q9 0 14-6l89-108q4-5 4-11z m357 232q0-13-8-23l-178-214q-12-13-28-13t-27 13l-179 214q-8 10-8 23 0 14 11 25t25 11h107v214h-322q-9 0-14 7l-89 107q-4 5-4 11 0 7 5 12t13 6h536q4 0 7-1t5-4 3-5 2-6 1-7v-334h107q14 0 25-11t10-25z" horiz-adv-x="1071.4" />
|
|
||||||
|
|
||||||
<glyph glyph-name="eye-off" unicode="" d="M310 112l43 79q-48 35-76 88t-27 114q0 67 34 125-128-65-213-197 94-144 239-209z m217 424q0 11-8 19t-19 7q-70 0-120-50t-50-119q0-11 8-19t19-8 19 8 8 19q0 48 34 82t82 34q11 0 19 8t8 19z m202 106q0-4 0-5-59-105-176-316t-176-316l-28-50q-5-9-15-9-7 0-75 39-9 6-9 16 0 7 25 49-80 36-147 96t-117 137q-11 17-11 38t11 39q86 131 212 207t277 76q50 0 100-10l31 54q5 9 15 9 3 0 10-3t18-9 18-10 18-10 10-7q9-5 9-15z m21-249q0-78-44-142t-117-91l157 280q4-25 4-47z m250-72q0-19-11-38-22-36-61-81-84-96-194-149t-234-53l41 74q119 10 219 76t169 171q-65 100-158 164l35 63q53-36 102-85t81-103q11-19 11-39z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="search" unicode="" d="M643 393q0 103-73 176t-177 74-177-74-73-176 73-177 177-73 177 73 73 177z m286-465q0-29-22-50t-50-21q-30 0-50 21l-191 191q-100-69-223-69-80 0-153 31t-125 84-84 125-31 153 31 152 84 126 125 84 153 31 153-31 125-84 84-126 31-152q0-123-69-223l191-191q21-21 21-51z" horiz-adv-x="928.6" />
|
|
||||||
|
|
||||||
<glyph glyph-name="cog" unicode="" d="M571 357q0 59-41 101t-101 42-101-42-42-101 42-101 101-42 101 42 41 101z m286 61v-124q0-7-4-13t-11-7l-104-16q-10-30-21-51 19-27 59-77 6-6 6-13t-5-13q-15-21-55-61t-53-39q-7 0-14 5l-77 60q-25-13-51-21-9-76-16-104-4-16-20-16h-124q-8 0-14 5t-6 12l-16 103q-27 9-50 21l-79-60q-6-5-14-5-8 0-14 6-70 64-92 94-4 5-4 13 0 6 5 12 8 12 28 37t30 40q-15 28-23 55l-102 15q-7 1-11 7t-5 13v124q0 7 5 13t10 7l104 16q8 25 22 51-23 32-60 77-6 7-6 14 0 5 5 12 15 20 55 60t53 40q7 0 15-5l77-60q24 13 50 21 9 76 17 104 3 16 20 16h124q7 0 13-5t7-12l15-103q28-9 51-20l79 59q5 5 13 5 7 0 14-5 72-67 92-95 4-5 4-12 0-7-4-13-9-12-29-37t-30-40q15-28 23-54l102-16q7-1 12-7t4-13z" horiz-adv-x="857.1" />
|
|
||||||
|
|
||||||
<glyph glyph-name="logout" unicode="" d="M357 53q0-2 1-11t0-14-2-14-5-10-12-4h-178q-67 0-114 47t-47 114v392q0 67 47 114t114 47h178q8 0 13-5t5-13q0-2 1-11t0-15-2-13-5-11-12-3h-178q-37 0-63-26t-27-64v-392q0-37 27-63t63-27h174t6 0 7-2 4-3 4-5 1-8z m518 304q0-14-11-25l-303-304q-11-10-25-10t-25 10-11 25v161h-250q-14 0-25 11t-11 25v214q0 15 11 25t25 11h250v161q0 14 11 25t25 10 25-10l303-304q11-10 11-25z" horiz-adv-x="928.6" />
|
|
||||||
|
|
||||||
<glyph glyph-name="down-open" unicode="" d="M939 406l-414-413q-10-11-25-11t-25 11l-414 413q-11 11-11 26t11 25l93 92q10 11 25 11t25-11l296-296 296 296q11 11 25 11t26-11l92-92q11-11 11-25t-11-26z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="attach" unicode="" d="M244-133q-102 0-170 72-72 70-74 166t84 190l496 496q80 80 174 54 44-12 79-47t47-79q26-96-54-176l-474-474q-40-40-88-46-48-4-80 28-30 24-27 74t47 92l332 334q24 26 50 0t0-50l-332-332q-44-44-20-70 12-8 24-6 24 4 46 26l474 474q50 50 34 108-16 60-76 76-54 14-108-36l-494-494q-66-76-64-143t52-117q50-48 117-50t141 62l496 494q24 24 50 0 26-22 0-48l-496-496q-82-82-186-82z" horiz-adv-x="939" />
|
|
||||||
|
|
||||||
<glyph glyph-name="picture" unicode="" d="M357 536q0-45-31-76t-76-32-76 32-31 76 31 76 76 31 76-31 31-76z m572-215v-250h-786v107l178 179 90-89 285 285z m53 393h-893q-7 0-12-5t-6-13v-678q0-7 6-13t12-5h893q7 0 13 5t5 13v678q0 8-5 13t-13 5z m89-18v-678q0-37-26-63t-63-27h-893q-36 0-63 27t-26 63v678q0 37 26 63t63 27h893q37 0 63-27t26-63z" horiz-adv-x="1071.4" />
|
|
||||||
|
|
||||||
<glyph glyph-name="video" unicode="" d="M214-36v72q0 14-10 25t-25 10h-72q-14 0-25-10t-11-25v-72q0-14 11-25t25-11h72q14 0 25 11t10 25z m0 214v72q0 14-10 25t-25 11h-72q-14 0-25-11t-11-25v-72q0-14 11-25t25-10h72q14 0 25 10t10 25z m0 215v71q0 15-10 25t-25 11h-72q-14 0-25-11t-11-25v-71q0-15 11-25t25-11h72q14 0 25 11t10 25z m572-429v286q0 14-11 25t-25 11h-429q-14 0-25-11t-10-25v-286q0-14 10-25t25-11h429q15 0 25 11t11 25z m-572 643v71q0 15-10 26t-25 10h-72q-14 0-25-10t-11-26v-71q0-14 11-25t25-11h72q14 0 25 11t10 25z m786-643v72q0 14-11 25t-25 10h-71q-15 0-25-10t-11-25v-72q0-14 11-25t25-11h71q15 0 25 11t11 25z m-214 429v285q0 15-11 26t-25 10h-429q-14 0-25-10t-10-26v-285q0-15 10-25t25-11h429q15 0 25 11t11 25z m214-215v72q0 14-11 25t-25 11h-71q-15 0-25-11t-11-25v-72q0-14 11-25t25-10h71q15 0 25 10t11 25z m0 215v71q0 15-11 25t-25 11h-71q-15 0-25-11t-11-25v-71q0-15 11-25t25-11h71q15 0 25 11t11 25z m0 214v71q0 15-11 26t-25 10h-71q-15 0-25-10t-11-26v-71q0-14 11-25t25-11h71q15 0 25 11t11 25z m71 89v-750q0-37-26-63t-63-26h-893q-36 0-63 26t-26 63v750q0 37 26 63t63 27h893q37 0 63-27t26-63z" horiz-adv-x="1071.4" />
|
|
||||||
|
|
||||||
<glyph glyph-name="right-open" unicode="" d="M618 368l-414-415q-11-10-25-10t-25 10l-93 93q-11 11-11 25t11 25l296 297-296 296q-11 11-11 25t11 25l93 93q10 11 25 11t25-11l414-414q10-11 10-25t-10-25z" horiz-adv-x="714.3" />
|
|
||||||
|
|
||||||
<glyph glyph-name="left-open" unicode="" d="M654 689l-297-296 297-297q10-10 10-25t-10-25l-93-93q-11-10-25-10t-25 10l-414 415q-11 10-11 25t11 25l414 414q10 11 25 11t25-11l93-93q10-10 10-25t-10-25z" horiz-adv-x="714.3" />
|
|
||||||
|
|
||||||
<glyph glyph-name="up-open" unicode="" d="M939 114l-92-92q-11-10-26-10t-25 10l-296 297-296-297q-11-10-25-10t-25 10l-93 92q-11 11-11 26t11 25l414 414q11 10 25 10t25-10l414-414q11-11 11-25t-11-26z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="bell-ringing-o" unicode="" d="M498 857c-30 0-54-24-54-53 0-8 2-15 5-22-147-22-236-138-236-245 0-268-95-393-177-462 0-39 32-71 71-71h249c0-79 63-143 142-143s142 64 142 143h249c39 0 71 32 71 71-82 69-178 194-178 462 0 107-88 223-235 245 2 7 4 14 4 22 0 29-24 53-53 53z m-309-45c-81-74-118-170-118-275l71 0c0 89 28 162 95 223l-48 52z m617 0l-48-52c67-61 96-134 95-223l71 0c1 105-37 201-118 275z m-397-799c5 0 9-4 9-9 0-44 36-80 80-80 5 0 9-4 9-9s-4-9-9-9c-54 0-98 44-98 98 0 5 4 9 9 9z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="lock" unicode="" d="M179 428h285v108q0 59-42 101t-101 41-101-41-41-101v-108z m464-53v-322q0-22-16-37t-38-16h-535q-23 0-38 16t-16 37v322q0 22 16 38t38 15h17v108q0 102 74 176t176 74 177-74 73-176v-108h18q23 0 38-15t16-38z" horiz-adv-x="642.9" />
|
|
||||||
|
|
||||||
<glyph glyph-name="globe" unicode="" d="M429 786q116 0 215-58t156-156 57-215-57-215-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58z m153-291q-2-1-6-5t-7-6q1 0 2 3t3 6 2 4q3 4 12 8 8 4 29 7 19 5 29-6-1 1 5 7t8 7q2 1 8 3t9 4l1 12q-7-1-10 4t-3 12q0-2-4-5 0 4-2 5t-7-1-5-1q-5 2-8 5t-5 9-2 8q-1 3-5 6t-5 6q-1 1-2 3t-1 4-3 3-3 1-4-3-4-5-2-3q-2 1-4 1t-2-1-3-1-3-2q-1-2-4-2t-5-1q8 3-1 6-5 2-9 2 6 2 5 6t-5 8h3q-1 2-5 5t-10 5-7 3q-5 3-19 5t-18 1q-3-4-3-6t2-8 2-7q1-3-3-7t-3-7q0-4 7-9t6-12q-2-4-9-9t-9-6q-3-5-1-11t6-9q1-1 1-2t-2-3-3-2-4-2l-1-1q-7-3-12 3t-7 15q-4 14-9 17-13 4-16-1-3 7-23 15-14 5-33 2 4 0 0 8-4 9-10 7 1 3 2 10t0 7q2 8 7 13 1 1 4 5t5 7 1 4q19-3 28 6 2 3 6 9t6 10q5 3 8 3t8-3 8-3q8-1 8 6t-4 11q7 0 2 10-2 4-5 5-6 2-15-3-4-2 2-4-1 0-6-6t-9-10-9 3q0 0-3 7t-5 8q-5 0-9-9 1 5-6 9t-14 4q11 7-4 15-4 3-12 3t-11-2q-2-4-3-7t3-4 6-3 6-2 5-2q8-6 5-8-1 0-5-2t-6-2-4-2q-1-3 0-8t-1-8q-3 3-5 10t-4 9q4-5-14-3l-5 0q-3 0-9-1t-12-1-7 5q-3 4 0 11 0 2 2 1-2 2-6 5t-6 5q-25-8-52-23 3 0 6 1 3 1 8 4t5 3q19 7 24 4l3 2q7-9 11-14-4 3-17 1-11-3-12-7 4-6 2-10-2 2-6 6t-8 6-8 3q-9 0-13-1-81-45-131-124 4-4 7-4 2-1 3-5t1-6 6 1q5-4 2-10 1 0 25-15 10-10 11-12 2-6-5-10-1 1-5 5t-5 2q-2-3 0-10t6-7q-4 0-5-9t-2-20 0-13l1-1q-2-6 3-19t12-11q-7-1 11-24 3-4 4-5 2-1 7-4t9-6 5-5q2-3 6-13t8-13q-2-3 5-11t6-13q-1 0-2-1t-1 0q2-4 9-8t8-7q1-2 1-6t2-6 4-1q2 11-13 35-8 13-9 16-2 2-4 8t-2 8q1 0 3 0t5-2 4-3 1-1q-1-4 1-10t7-10 10-11 6-7q4-4 8-11t0-8q5 0 11-5t10-11q3-5 4-15t3-13q1-4 5-8t7-5l9-5t7-3q3-2 10-6t12-7q6-2 9-2t8 1 8 2q8 1 16-8t12-12q20-10 30-6-1 0 1-4t4-9 5-8 3-5q3-3 10-8t10-8q4 2 4 5-1-5 4-11t10-6q8 2 8 18-17-8-27 10 0 0-2 3t-2 5-1 4 0 5 2 1q5 0 6 2t-1 7-2 8q-1 4-6 11t-7 8q-3-5-9-4t-9 5q0-1-1-3t-1-4q-7 0-8 0 1 2 1 10t2 13q1 2 3 6t5 9 2 7-3 5-9 1q-11 0-15-11-1-2-2-6t-2-6-5-4q-4-2-14-1t-13 3q-8 4-13 16t-5 20q0 6 1 15t2 14-3 14q2 1 5 5t5 6q2 1 3 1t3 0 2 1 1 3q0 1-2 2-1 1-2 1 4-1 16 1t15-1q9-6 12 1 0 1-1 6t0 7q3-15 16-5 2-1 9-3t9-2q2-1 4-3t3-3 3 0 5 4q5-8 7-13 6-23 10-25 4-2 6-1t3 5 0 8-1 7l-1 5v10l0 4q-8 2-10 7t0 10 9 10q0 1 4 2t9 4 7 4q12 11 8 20 4 0 6 5 0 0-2 2t-5 2-2 2q5 2 1 8 3 2 4 7t4 5q5-6 12-1 5 5 1 9 2 4 11 6t10 5q4-1 5 1t0 7 2 7q2 2 9 5t7 2l9 7q2 2 0 2 10-1 18 6 5 6-4 11 2 4-1 5t-9 4q2 0 7 0t5 1q9 5-3 9-10 2-24-7z m-91-490q115 21 195 106-1 2-7 2t-7 2q-10 4-13 5 1 4-1 7t-5 5-7 5-6 4q-1 1-4 3t-4 3-4 2-5 2-5-1l-2-1q-2 0-3-1t-3-2-2-1 0-2q-12 10-20 13-3 0-6 3t-6 4-6 0-6-3q-3-3-4-9t-1-7q-4 3 0 10t1 10q-1 3-6 2t-6-2-7-5-5-3-4-3-5-5q-2-2-4-6t-2-6q-1 2-7 3t-5 3q1-5 2-19t3-22q4-17-7-26-15-14-16-23-2-12 7-14 0-4-5-12t-4-12q0-3 2-9z" horiz-adv-x="857.1" />
|
|
||||||
|
|
||||||
<glyph glyph-name="brush" unicode="" d="M464 209q0-124-87-212t-210-87q-81 0-149 40 68 39 109 108t40 151q0 61 44 105t105 44 105-44 43-105z m415 562q32-32 32-79t-33-79l-318-318q-20 55-61 97t-97 62l318 318q32 32 79 32t80-33z" horiz-adv-x="928" />
|
|
||||||
|
|
||||||
<glyph glyph-name="attention" unicode="" d="M571 90v106q0 8-5 13t-12 5h-108q-7 0-12-5t-5-13v-106q0-8 5-13t12-6h108q7 0 12 6t5 13z m-1 208l10 257q0 6-5 10-7 6-14 6h-122q-6 0-14-6-5-4-5-12l9-255q0-5 6-9t13-3h103q8 0 14 3t5 9z m-7 522l428-786q20-35-1-70-9-17-26-26t-35-10h-858q-18 0-35 10t-26 26q-21 35-1 70l429 786q9 17 26 27t36 10 36-10 27-27z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="plus" unicode="" d="M786 446v-107q0-22-16-38t-38-15h-232v-233q0-22-16-37t-38-16h-107q-22 0-38 16t-15 37v233h-232q-23 0-38 15t-16 38v107q0 23 16 38t38 16h232v232q0 22 15 38t38 16h107q23 0 38-16t16-38v-232h232q23 0 38-16t16-38z" horiz-adv-x="785.7" />
|
|
||||||
|
|
||||||
<glyph glyph-name="adjust" unicode="" d="M429 53v608q-83 0-153-41t-110-111-41-152 41-152 110-111 153-41z m428 304q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
|
|
||||||
|
|
||||||
<glyph glyph-name="edit" unicode="" d="M496 196l64 65-85 85-64-65v-31h53v-54h32z m245 402q-9 9-18 0l-196-196q-9-9 0-18t18 0l196 196q9 9 0 18z m45-331v-106q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q35 0 65-14 9-4 10-13 2-10-5-16l-27-28q-8-8-18-4-13 3-25 3h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v70q0 7 5 12l36 36q8 8 20 4t11-16z m-54 411l161-160-375-375h-161v160z m248-73l-51-52-161 161 51 52q16 15 38 15t38-15l85-85q16-16 16-38t-16-38z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="pencil" unicode="" d="M203 0l50 51-131 131-51-51v-60h72v-71h60z m291 518q0 12-12 12-5 0-9-4l-303-302q-4-4-4-10 0-12 13-12 5 0 9 4l303 302q3 4 3 10z m-30 107l232-232-464-465h-232v233z m381-54q0-29-20-50l-93-93-232 233 93 92q20 21 50 21 29 0 51-21l131-131q20-22 20-51z" horiz-adv-x="857.1" />
|
|
||||||
|
|
||||||
<glyph glyph-name="pin" unicode="" d="M268 375v250q0 8-5 13t-13 5-13-5-5-13v-250q0-8 5-13t13-5 13 5 5 13z m375-197q0-14-11-25t-25-10h-239l-29-270q-1-7-6-11t-11-5h-1q-15 0-17 15l-43 271h-225q-15 0-25 10t-11 25q0 69 44 124t99 55v286q-29 0-50 21t-22 50 22 50 50 22h357q29 0 50-22t21-50-21-50-50-21v-286q55 0 99-55t44-124z" horiz-adv-x="642.9" />
|
|
||||||
|
|
||||||
<glyph glyph-name="wrench" unicode="" d="M214 36q0 14-10 25t-25 10-25-10-11-25 11-25 25-11 25 11 10 25z m360 234l-381-381q-21-20-50-20-29 0-51 20l-59 61q-21 20-21 50 0 29 21 51l380 380q22-55 64-97t97-64z m354 243q0-22-13-59-27-75-92-122t-144-46q-104 0-177 73t-73 177 73 176 177 74q32 0 67-10t60-26q9-6 9-15t-9-16l-163-94v-125l108-60q2 2 44 27t75 45 40 20q8 0 13-5t5-14z" horiz-adv-x="928.6" />
|
|
||||||
|
|
||||||
<glyph glyph-name="chart-bar" unicode="" d="M357 357v-286h-143v286h143z m214 286v-572h-142v572h142z m572-643v-72h-1143v858h71v-786h1072z m-357 500v-429h-143v429h143z m214 214v-643h-143v643h143z" horiz-adv-x="1142.9" />
|
|
||||||
|
|
||||||
<glyph glyph-name="zoom-in" unicode="" d="M571 411v-36q0-7-5-13t-12-5h-125v-125q0-7-6-13t-12-5h-36q-7 0-13 5t-5 13v125h-125q-7 0-12 5t-6 13v36q0 7 6 12t12 5h125v125q0 8 5 13t13 5h36q7 0 12-5t6-13v-125h125q7 0 12-5t5-12z m72-18q0 103-73 176t-177 74-177-74-73-176 73-177 177-73 177 73 73 177z m286-465q0-29-21-50t-51-21q-30 0-50 21l-191 191q-100-69-223-69-80 0-153 31t-125 84-84 125-31 153 31 152 84 126 125 84 153 31 153-31 125-84 84-126 31-152q0-123-69-223l191-191q21-21 21-51z" horiz-adv-x="928.6" />
|
|
||||||
|
|
||||||
<glyph glyph-name="users" unicode="" d="M331 357q-90-3-148-71h-75q-45 0-77 22t-31 66q0 197 69 197 4 0 25-11t54-24 66-12q38 0 75 13-3-21-3-37 0-78 45-143z m598-355q0-67-41-106t-108-39h-488q-68 0-108 39t-41 106q0 29 2 57t8 61 14 61 24 54 35 45 48 30 62 11q6 0 24-12t41-26 59-27 76-12 75 12 60 27 41 26 24 12q34 0 62-11t47-30 35-45 24-54 15-61 8-61 2-57z m-572 712q0-59-42-101t-101-42-101 42-42 101 42 101 101 42 101-42 42-101z m393-214q0-89-63-152t-151-62-152 62-63 152 63 151 152 63 151-63 63-151z m321-126q0-43-31-66t-77-22h-75q-57 68-147 71 45 65 45 143 0 16-3 37 37-13 74-13 33 0 67 12t54 24 24 11q69 0 69-197z m-71 340q0-59-42-101t-101-42-101 42-42 101 42 101 101 42 101-42 42-101z" horiz-adv-x="1071.4" />
|
|
||||||
|
|
||||||
<glyph glyph-name="chat" unicode="" d="M786 428q0-77-53-143t-143-104-197-38q-48 0-98 9-70-49-155-72-21-5-48-9h-2q-6 0-12 5t-6 12q-1 1-1 3t1 4 1 3l1 3t2 3 2 3 3 3 2 2q3 3 13 14t15 16 12 17 14 21 11 25q-69 40-108 98t-40 125q0 78 53 144t143 104 197 38 197-38 143-104 53-144z m214-142q0-67-40-126t-108-98q5-14 11-25t14-21 13-16 14-17 13-14q0 0 2-2t3-3 2-3 2-3l1-3t1-3 1-4-1-3q-2-8-7-13t-12-4q-28 4-48 9-86 23-156 72-50-9-98-9-151 0-263 74 32-3 49-3 90 0 172 25t148 72q69 52 107 119t37 141q0 43-13 85 72-39 114-99t42-128z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="info-circled" unicode="" d="M571 89v89q0 8-5 13t-12 5h-54v286q0 8-5 13t-13 5h-178q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h53v-179h-53q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h250q7 0 12 5t5 13z m-71 500v89q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h107q8 0 13 5t5 13z m357-232q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
|
|
||||||
|
|
||||||
<glyph glyph-name="login" unicode="" d="M661 357q0-14-11-25l-303-304q-11-10-26-10t-25 10-10 25v161h-250q-15 0-25 11t-11 25v214q0 15 11 25t25 11h250v161q0 14 10 25t25 10 26-10l303-304q11-10 11-25z m196 196v-392q0-67-47-114t-114-47h-178q-7 0-13 5t-5 13q0 2-1 11t0 15 2 13 5 11 12 3h178q37 0 64 27t26 63v392q0 37-26 64t-64 26h-174t-6 0-6 2-5 3-4 5-1 8q0 2-1 11t0 15 2 13 5 11 12 3h178q67 0 114-47t47-114z" horiz-adv-x="857.1" />
|
|
||||||
|
|
||||||
<glyph glyph-name="home-2" unicode="" d="M521 826q322-279 500-429 20-16 20-40 0-21-15-37t-36-15l-105 0 0-364q0-21-15-37t-36-16l-156 0q-22 0-37 16t-16 37l0 208-209 0 0-208q0-21-15-37t-36-16l-156 0q-21 0-37 16t-16 37l0 364-103 0q-22 0-37 15t-16 37 19 40z" horiz-adv-x="1041" />
|
|
||||||
|
|
||||||
<glyph glyph-name="arrow-curved" unicode="" d="M799 302l0-56 112 0-223-223-224 223 112 0 0 56q0 116-81 197t-197 82-198-82-82-197q0 162 115 276t276 114 276-114 114-276z" horiz-adv-x="928" />
|
|
||||||
|
|
||||||
<glyph glyph-name="link" unicode="" d="M813 178q0 23-16 38l-116 116q-16 16-38 16-24 0-40-18 1-1 10-10t12-12 9-11 7-14 2-15q0-23-16-38t-38-16q-8 0-15 2t-14 7-11 9-12 12-10 10q-19-17-19-40 0-23 16-38l115-116q15-15 38-15 22 0 38 15l82 81q16 16 16 37z m-393 394q0 22-15 38l-115 115q-16 16-38 16-22 0-38-15l-82-82q-16-15-16-37 0-22 16-38l116-116q15-15 38-15 23 0 40 17-2 2-11 11t-12 12-8 10-7 14-2 16q0 22 15 38t38 15q9 0 16-2t14-7 11-8 12-12 10-11q18 17 18 41z m500-394q0-66-48-113l-82-81q-46-47-113-47-68 0-114 48l-115 115q-46 47-46 114 0 68 49 116l-49 49q-48-49-116-49-67 0-114 47l-116 116q-47 47-47 114t47 113l82 82q47 46 114 46 67 0 114-47l115-116q46-46 46-113 0-69-49-117l49-49q48 49 116 49 67 0 114-47l116-116q47-47 47-114z" horiz-adv-x="928.6" />
|
|
||||||
|
|
||||||
<glyph glyph-name="user" unicode="" d="M714 76q0-60-35-104t-84-44h-476q-49 0-84 44t-35 104q0 48 5 90t17 85 33 73 52 50 76 19q73-72 174-72t175 72q42 0 75-19t52-50 33-73 18-85 4-90z m-143 495q0-88-62-151t-152-63-151 63-63 151 63 152 151 63 152-63 62-152z" horiz-adv-x="714.3" />
|
|
||||||
|
|
||||||
<glyph glyph-name="download" unicode="" d="M714 107q0 15-10 25t-25 11-25-11-11-25 11-25 25-11 25 11 10 25z m143 0q0 15-10 25t-26 11-25-11-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-37t-38-16h-821q-23 0-38 16t-16 37v179q0 22 16 38t38 16h259l75-76q33-32 76-32t76 32l76 76h259q22 0 38-16t16-38z m-182 318q10-23-8-39l-250-250q-10-11-25-11t-25 11l-250 250q-17 16-8 39 10 21 33 21h143v250q0 15 11 25t25 11h143q14 0 25-11t10-25v-250h143q24 0 33-21z" horiz-adv-x="928.6" />
|
|
||||||
|
|
||||||
<glyph glyph-name="bookmark" unicode="" d="M650 786q12 0 24-5 19-8 29-23t11-35v-719q0-19-11-35t-29-23q-10-4-24-4-27 0-47 18l-246 236-246-236q-20-19-46-19-13 0-25 5-18 7-29 23t-11 35v719q0 19 11 35t29 23q12 5 25 5h585z" horiz-adv-x="714.3" />
|
|
||||||
|
|
||||||
<glyph glyph-name="ok" unicode="" d="M933 541q0-22-16-38l-404-404-76-76q-16-15-38-15t-38 15l-76 76-202 202q-15 16-15 38t15 38l76 76q16 16 38 16t38-16l164-165 366 367q16 16 38 16t38-16l76-76q16-15 16-38z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="music" unicode="" d="M857 732v-625q0-28-19-50t-48-33-58-18-53-6-54 6-58 18-48 33-19 50 19 50 48 33 58 18 54 6q58 0 107-22v300l-429-132v-396q0-28-19-50t-48-33-58-18-53-6-54 6-58 18-48 33-19 50 19 50 48 34 58 17 54 6q58 0 107-21v539q0 17 10 32t28 20l464 142q7 3 16 3 22 0 38-16t15-38z" horiz-adv-x="857.1" />
|
|
||||||
|
|
||||||
<glyph glyph-name="doc" unicode="" d="M819 645q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z" horiz-adv-x="857.1" />
|
|
||||||
|
|
||||||
<glyph glyph-name="block" unicode="" d="M732 359q0 90-48 164l-421-420q76-50 166-50 62 0 118 25t96 65 65 97 24 119z m-557-167l421 421q-75 50-167 50-83 0-153-40t-110-111-41-153q0-91 50-167z m682 167q0-88-34-168t-91-137-137-92-166-34-167 34-137 92-91 137-34 168 34 167 91 137 137 91 167 34 166-34 137-91 91-137 34-167z" horiz-adv-x="857.1" />
|
|
||||||
|
|
||||||
<glyph glyph-name="megaphone" unicode="" d="M929 500q29 0 50-21t21-51-21-50-50-21v-214q0-29-22-50t-50-22q-233 194-453 212-32-10-51-36t-17-57 22-51q-11-19-13-37t4-32 19-31 26-28 35-28q-17-32-63-46t-94-7-73 31q-4 13-17 49t-18 53-12 50-9 56 2 55 12 62h-68q-36 0-63 26t-26 63v107q0 37 26 63t63 26h268q243 0 500 215 29 0 50-22t22-50v-214z m-72-337v532q-220-168-428-191v-151q210-23 428-190z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="spin3" unicode="" d="M494 857c-266 0-483-210-494-472-1-19 13-20 13-20l84 0c16 0 19 10 19 18 10 199 176 358 378 358 107 0 205-45 273-118l-58-57c-11-12-11-27 5-31l247-50c21-5 46 11 37 44l-58 227c-2 9-16 22-29 13l-65-60c-89 91-214 148-352 148z m409-508c-16 0-19-10-19-18-10-199-176-358-377-358-108 0-205 45-274 118l59 57c10 12 10 27-5 31l-248 50c-21 5-46-11-37-44l58-227c2-9 16-22 30-13l64 60c89-91 214-148 353-148 265 0 482 210 493 473 1 18-13 19-13 19l-84 0z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="spin4" unicode="" d="M498 857c-114 0-228-39-320-116l0 0c173 140 428 130 588-31 134-134 164-332 89-495-10-29-5-50 12-68 21-20 61-23 84 0 3 3 12 15 15 24 71 180 33 393-112 539-99 98-228 147-356 147z m-409-274c-14 0-29-5-39-16-3-3-13-15-15-24-71-180-34-393 112-539 185-185 479-195 676-31l0 0c-173-140-428-130-589 31-134 134-163 333-89 495 11 29 6 50-12 68-11 11-27 17-44 16z" horiz-adv-x="1001" />
|
|
||||||
|
|
||||||
<glyph glyph-name="link-ext" unicode="" d="M786 339v-178q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h393q7 0 12-5t5-13v-36q0-8-5-13t-12-5h-393q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v178q0 8 5 13t13 5h36q8 0 13-5t5-13z m214 482v-285q0-15-11-25t-25-11-25 11l-98 98-364-364q-5-6-13-6t-12 6l-64 64q-6 5-6 12t6 13l364 364-98 98q-11 11-11 25t11 25 25 11h285q15 0 25-11t11-25z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="link-ext-alt" unicode="" d="M714 339v268q0 15-10 25t-25 11h-268q-24 0-33-22-10-23 8-39l80-80-298-298q-11-11-11-26t11-25l57-57q11-10 25-10t25 10l298 298 81-80q10-11 25-11 6 0 14 3 21 10 21 33z m143 286v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
|
|
||||||
|
|
||||||
<glyph glyph-name="bookmark-empty" unicode="" d="M643 714h-572v-693l237 227 49 47 50-47 236-227v693z m7 72q12 0 24-5 19-8 29-23t11-35v-719q0-19-11-35t-29-23q-10-4-24-4-27 0-47 18l-246 236-246-236q-20-19-46-19-13 0-25 5-18 7-29 23t-11 35v719q0 19 11 35t29 23q12 5 25 5h585z" horiz-adv-x="714.3" />
|
|
||||||
|
|
||||||
<glyph glyph-name="filter" unicode="" d="M783 692q9-22-8-39l-275-275v-414q0-23-22-33-7-3-14-3-15 0-25 11l-143 143q-10 11-10 25v271l-275 275q-18 17-8 39 9 22 33 22h714q23 0 33-22z" horiz-adv-x="785.7" />
|
|
||||||
|
|
||||||
<glyph glyph-name="menu" unicode="" d="M857 107v-71q0-15-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 25t25 11h785q15 0 26-11t10-25z m0 286v-72q0-14-10-25t-26-10h-785q-15 0-25 10t-11 25v72q0 14 11 25t25 10h785q15 0 26-10t10-25z m0 285v-71q0-14-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 26t25 10h785q15 0 26-10t10-26z" horiz-adv-x="857.1" />
|
|
||||||
|
|
||||||
<glyph glyph-name="mail-alt" unicode="" d="M1000 461v-443q0-37-26-63t-63-27h-822q-36 0-63 27t-26 63v443q25-27 56-49 202-137 278-192 32-24 51-37t53-27 61-13h2q28 0 61 13t53 27 51 37q95 68 278 192 32 22 56 49z m0 164q0-44-27-84t-68-69q-210-146-262-181-5-4-23-17t-30-22-29-18-32-15-28-5h-2q-12 0-27 5t-32 15-30 18-30 22-23 17q-51 35-147 101t-114 80q-35 23-65 64t-31 77q0 43 23 72t66 29h822q36 0 63-26t26-63z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="gauge" unicode="" d="M214 214q0 30-21 51t-50 21-51-21-21-51 21-50 51-21 50 21 21 50z m107 250q0 30-20 51t-51 21-50-21-21-51 21-50 50-21 51 21 20 50z m239-268l57 213q3 14-5 27t-21 16-27-3-17-22l-56-213q-33-3-60-25t-35-55q-11-43 11-81t66-50 81 11 50 66q9 33-4 65t-40 51z m369 18q0 30-21 51t-51 21-50-21-21-51 21-50 50-21 51 21 21 50z m-358 357q0 30-20 51t-51 21-50-21-21-51 21-50 50-21 51 21 20 50z m250-107q0 30-20 51t-51 21-50-21-21-51 21-50 50-21 51 21 20 50z m179-250q0-145-79-269-10-17-30-17h-782q-20 0-30 17-79 123-79 269 0 102 40 194t106 160 160 107 194 39 194-39 160-107 106-160 40-194z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="comment-empty" unicode="" d="M500 643q-114 0-213-39t-157-105-59-142q0-62 40-119t113-98l48-28-15-53q-13-51-39-97 85 36 154 96l24 21 32-3q38-5 72-5 114 0 213 39t157 105 59 142-59 142-157 105-213 39z m500-286q0-97-67-179t-182-130-251-48q-39 0-81 4-110-97-257-135-27-8-63-12h-3q-8 0-15 6t-9 15v1q-2 2 0 6t1 6 2 5l4 5t4 5 4 5q4 5 17 19t20 22 17 22 18 28 15 33 15 42q-88 50-138 123t-51 157q0 97 67 179t182 130 251 48 251-48 182-130 67-179z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="bell-alt" unicode="" d="M509-89q0 8-9 8-33 0-57 24t-23 57q0 9-9 9t-9-9q0-41 29-70t69-28q9 0 9 9z m455 160q0-29-21-50t-50-21h-250q0-59-42-101t-101-42-101 42-42 101h-250q-29 0-50 21t-21 50q28 24 51 49t47 67 42 89 27 115 11 145q0 84 66 157t171 89q-5 10-5 21 0 23 16 38t38 16 38-16 16-38q0-11-5-21 106-16 171-89t66-157q0-78 11-145t28-115 41-89 48-67 50-49z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="plus-squared" unicode="" d="M714 321v72q0 14-10 25t-25 10h-179v179q0 15-11 25t-25 11h-71q-15 0-25-11t-11-25v-179h-178q-15 0-25-10t-11-25v-72q0-14 11-25t25-10h178v-179q0-14 11-25t25-11h71q15 0 25 11t11 25v179h179q14 0 25 10t10 25z m143 304v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
|
|
||||||
|
|
||||||
<glyph glyph-name="reply" unicode="" d="M1000 232q0-93-71-252-1-4-6-13t-7-17-7-12q-7-10-16-10-8 0-13 6t-5 14q0 5 1 15t2 13q3 38 3 69 0 56-10 101t-27 77-45 56-59 39-74 24-86 12-98 3h-125v-143q0-14-10-25t-26-11-25 11l-285 286q-11 10-11 25t11 25l285 286q11 10 25 10t26-10 10-25v-143h125q398 0 488-225 30-75 30-186z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="smile" unicode="" d="M633 257q-21-67-77-109t-127-41-128 41-77 109q-4 14 3 27t21 18q14 4 27-2t17-22q14-44 52-72t85-28 84 28 52 72q4 15 18 22t27 2 21-18 2-27z m-276 243q0-30-21-51t-50-21-51 21-21 51 21 50 51 21 50-21 21-50z m286 0q0-30-21-51t-51-21-50 21-21 51 21 50 50 21 51-21 21-50z m143-143q0 73-29 139t-76 114-114 76-138 28-139-28-114-76-76-114-29-139 29-139 76-113 114-77 139-28 138 28 114 77 76 113 29 139z m71 0q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
|
|
||||||
|
|
||||||
<glyph glyph-name="lock-open-alt" unicode="" d="M589 428q23 0 38-15t16-38v-322q0-22-16-37t-38-16h-535q-23 0-38 16t-16 37v322q0 22 16 38t38 15h17v179q0 103 74 177t176 73 177-73 73-177q0-14-10-25t-25-11h-36q-14 0-25 11t-11 25q0 59-42 101t-101 42-101-42-41-101v-179h410z" horiz-adv-x="642.9" />
|
|
||||||
|
|
||||||
<glyph glyph-name="ellipsis" unicode="" d="M214 446v-107q0-22-15-38t-38-15h-107q-23 0-38 15t-16 38v107q0 23 16 38t38 16h107q22 0 38-16t15-38z m286 0v-107q0-22-16-38t-38-15h-107q-22 0-38 15t-15 38v107q0 23 15 38t38 16h107q23 0 38-16t16-38z m286 0v-107q0-22-16-38t-38-15h-107q-22 0-38 15t-16 38v107q0 23 16 38t38 16h107q23 0 38-16t16-38z" horiz-adv-x="785.7" />
|
|
||||||
|
|
||||||
<glyph glyph-name="play-circled" unicode="" d="M429 786q116 0 215-58t156-156 57-215-57-215-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58z m214-460q18 10 18 31t-18 31l-304 178q-17 11-35 1-18-11-18-31v-358q0-20 18-31 9-4 17-4 10 0 18 5z" horiz-adv-x="857.1" />
|
|
||||||
|
|
||||||
<glyph glyph-name="thumbs-up-alt" unicode="" d="M143 107q0 15-11 25t-25 11q-15 0-25-11t-11-25q0-15 11-25t25-11q15 0 25 11t11 25z m89 286v-357q0-15-10-25t-26-11h-160q-15 0-25 11t-11 25v357q0 14 11 25t25 10h160q15 0 26-10t10-25z m661 0q0-48-31-83 9-25 9-43 1-42-24-76 9-31 0-66-9-31-31-52 5-62-27-101-36-43-110-44h-72q-37 0-80 9t-68 16-67 22q-69 24-88 25-15 0-25 11t-11 25v357q0 14 10 25t24 11q13 1 42 33t57 67q38 49 56 67 10 10 17 27t10 27 8 34q4 22 7 34t11 29 19 28q10 11 25 11 25 0 46-6t33-15 22-22 14-25 7-28 2-25 1-22q0-21-6-43t-10-33-16-31q-1-4-5-10t-6-13-5-13h155q43 0 75-32t32-75z" horiz-adv-x="928.6" />
|
|
||||||
|
|
||||||
<glyph glyph-name="share" unicode="" d="M679 286q74 0 126-53t52-126-52-126-126-53-127 53-52 126q0 7 1 19l-201 100q-51-48-121-48-75 0-127 53t-52 126 52 126 127 53q70 0 121-48l201 100q-1 12-1 19 0 74 52 126t127 53 126-53 52-126-52-126-126-53q-71 0-122 48l-201-100q1-12 1-19t-1-19l201-100q51 48 122 48z" horiz-adv-x="857.1" />
|
|
||||||
|
|
||||||
<glyph glyph-name="binoculars" unicode="" d="M393 678v-428q0-15-11-25t-25-11v-321q0-15-10-25t-26-11h-285q-15 0-25 11t-11 25v285l139 488q4 12 17 12h237z m178 0v-392h-142v392h142z m429-500v-285q0-15-11-25t-25-11h-285q-15 0-25 11t-11 25v321q-15 0-25 11t-11 25v428h237q13 0 17-12z m-589 661v-125h-197v125q0 8 5 13t13 5h161q8 0 13-5t5-13z m375 0v-125h-197v125q0 8 5 13t13 5h161q8 0 13-5t5-13z" horiz-adv-x="1000" />
|
|
||||||
|
|
||||||
<glyph glyph-name="user-plus" unicode="" d="M393 357q-89 0-152 63t-62 151 62 152 152 63 151-63 63-152-63-151-151-63z m536-71h196q7 0 13-6t5-12v-107q0-8-5-13t-13-5h-196v-197q0-7-6-12t-12-6h-107q-8 0-13 6t-5 12v197h-197q-7 0-12 5t-6 13v107q0 7 6 12t12 6h197v196q0 7 5 13t13 5h107q7 0 12-5t6-13v-196z m-411-125q0-29 21-51t50-21h143v-133q-38-28-95-28h-488q-67 0-108 39t-41 106q0 30 2 58t8 61 15 60 24 55 34 45 48 30 62 11q11 0 22-10 44-34 86-51t92-17 92 17 86 51q11 10 22 10 73 0 121-54h-125q-29 0-50-21t-21-50v-107z" horiz-adv-x="1142.9" />
|
|
||||||
</font>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 28 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
160
priv/static/static/fontello.1600365488745.css
vendored
160
priv/static/static/fontello.1600365488745.css
vendored
|
@ -1,160 +0,0 @@
|
||||||
@font-face {
|
|
||||||
font-family: "Icons";
|
|
||||||
src: url("./font/fontello.1600365488745.eot");
|
|
||||||
src: url("./font/fontello.1600365488745.eot") format("embedded-opentype"),
|
|
||||||
url("./font/fontello.1600365488745.woff2") format("woff2"),
|
|
||||||
url("./font/fontello.1600365488745.woff") format("woff"),
|
|
||||||
url("./font/fontello.1600365488745.ttf") format("truetype"),
|
|
||||||
url("./font/fontello.1600365488745.svg") format("svg");
|
|
||||||
font-weight: normal;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
[class^="icon-"]::before,
|
|
||||||
[class*=" icon-"]::before {
|
|
||||||
font-family: "Icons";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: normal;
|
|
||||||
speak: none;
|
|
||||||
display: inline-block;
|
|
||||||
text-decoration: inherit;
|
|
||||||
width: 1em;
|
|
||||||
margin-right: .2em;
|
|
||||||
text-align: center;
|
|
||||||
font-variant: normal;
|
|
||||||
text-transform: none;
|
|
||||||
line-height: 1em;
|
|
||||||
margin-left: .2em;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-spin4::before { content: "\e834"; }
|
|
||||||
|
|
||||||
.icon-cancel::before { content: "\e800"; }
|
|
||||||
|
|
||||||
.icon-upload::before { content: "\e801"; }
|
|
||||||
|
|
||||||
.icon-spin3::before { content: "\e832"; }
|
|
||||||
|
|
||||||
.icon-reply::before { content: "\f112"; }
|
|
||||||
|
|
||||||
.icon-star::before { content: "\e802"; }
|
|
||||||
|
|
||||||
.icon-star-empty::before { content: "\e803"; }
|
|
||||||
|
|
||||||
.icon-retweet::before { content: "\e804"; }
|
|
||||||
|
|
||||||
.icon-eye-off::before { content: "\e805"; }
|
|
||||||
|
|
||||||
.icon-binoculars::before { content: "\f1e5"; }
|
|
||||||
|
|
||||||
.icon-cog::before { content: "\e807"; }
|
|
||||||
|
|
||||||
.icon-user-plus::before { content: "\f234"; }
|
|
||||||
|
|
||||||
.icon-menu::before { content: "\f0c9"; }
|
|
||||||
|
|
||||||
.icon-logout::before { content: "\e808"; }
|
|
||||||
|
|
||||||
.icon-down-open::before { content: "\e809"; }
|
|
||||||
|
|
||||||
.icon-attach::before { content: "\e80a"; }
|
|
||||||
|
|
||||||
.icon-link-ext::before { content: "\f08e"; }
|
|
||||||
|
|
||||||
.icon-link-ext-alt::before { content: "\f08f"; }
|
|
||||||
|
|
||||||
.icon-picture::before { content: "\e80b"; }
|
|
||||||
|
|
||||||
.icon-video::before { content: "\e80c"; }
|
|
||||||
|
|
||||||
.icon-right-open::before { content: "\e80d"; }
|
|
||||||
|
|
||||||
.icon-left-open::before { content: "\e80e"; }
|
|
||||||
|
|
||||||
.icon-up-open::before { content: "\e80f"; }
|
|
||||||
|
|
||||||
.icon-comment-empty::before { content: "\f0e5"; }
|
|
||||||
|
|
||||||
.icon-mail-alt::before { content: "\f0e0"; }
|
|
||||||
|
|
||||||
.icon-lock::before { content: "\e811"; }
|
|
||||||
|
|
||||||
.icon-lock-open-alt::before { content: "\f13e"; }
|
|
||||||
|
|
||||||
.icon-globe::before { content: "\e812"; }
|
|
||||||
|
|
||||||
.icon-brush::before { content: "\e813"; }
|
|
||||||
|
|
||||||
.icon-search::before { content: "\e806"; }
|
|
||||||
|
|
||||||
.icon-adjust::before { content: "\e816"; }
|
|
||||||
|
|
||||||
.icon-thumbs-up-alt::before { content: "\f164"; }
|
|
||||||
|
|
||||||
.icon-attention::before { content: "\e814"; }
|
|
||||||
|
|
||||||
.icon-plus-squared::before { content: "\f0fe"; }
|
|
||||||
|
|
||||||
.icon-plus::before { content: "\e815"; }
|
|
||||||
|
|
||||||
.icon-edit::before { content: "\e817"; }
|
|
||||||
|
|
||||||
.icon-play-circled::before { content: "\f144"; }
|
|
||||||
|
|
||||||
.icon-pencil::before { content: "\e818"; }
|
|
||||||
|
|
||||||
.icon-chart-bar::before { content: "\e81b"; }
|
|
||||||
|
|
||||||
.icon-smile::before { content: "\f118"; }
|
|
||||||
|
|
||||||
.icon-bell-alt::before { content: "\f0f3"; }
|
|
||||||
|
|
||||||
.icon-wrench::before { content: "\e81a"; }
|
|
||||||
|
|
||||||
.icon-pin::before { content: "\e819"; }
|
|
||||||
|
|
||||||
.icon-ellipsis::before { content: "\f141"; }
|
|
||||||
|
|
||||||
.icon-bell-ringing-o::before { content: "\e810"; }
|
|
||||||
|
|
||||||
.icon-zoom-in::before { content: "\e81c"; }
|
|
||||||
|
|
||||||
.icon-gauge::before { content: "\f0e4"; }
|
|
||||||
|
|
||||||
.icon-users::before { content: "\e81d"; }
|
|
||||||
|
|
||||||
.icon-info-circled::before { content: "\e81f"; }
|
|
||||||
|
|
||||||
.icon-home-2::before { content: "\e821"; }
|
|
||||||
|
|
||||||
.icon-chat::before { content: "\e81e"; }
|
|
||||||
|
|
||||||
.icon-login::before { content: "\e820"; }
|
|
||||||
|
|
||||||
.icon-arrow-curved::before { content: "\e822"; }
|
|
||||||
|
|
||||||
.icon-link::before { content: "\e823"; }
|
|
||||||
|
|
||||||
.icon-share::before { content: "\f1e0"; }
|
|
||||||
|
|
||||||
.icon-user::before { content: "\e824"; }
|
|
||||||
|
|
||||||
.icon-ok::before { content: "\e827"; }
|
|
||||||
|
|
||||||
.icon-filter::before { content: "\f0b0"; }
|
|
||||||
|
|
||||||
.icon-download::before { content: "\e825"; }
|
|
||||||
|
|
||||||
.icon-bookmark::before { content: "\e826"; }
|
|
||||||
|
|
||||||
.icon-bookmark-empty::before { content: "\f097"; }
|
|
||||||
|
|
||||||
.icon-music::before { content: "\e828"; }
|
|
||||||
|
|
||||||
.icon-doc::before { content: "\e829"; }
|
|
||||||
|
|
||||||
.icon-block::before { content: "\e82a"; }
|
|
||||||
|
|
||||||
.icon-megaphone::before { content: "\e82b"; }
|
|
|
@ -1,416 +0,0 @@
|
||||||
{
|
|
||||||
"name": "",
|
|
||||||
"css_prefix_text": "icon-",
|
|
||||||
"css_use_suffix": false,
|
|
||||||
"hinting": true,
|
|
||||||
"units_per_em": 1000,
|
|
||||||
"ascent": 857,
|
|
||||||
"glyphs": [
|
|
||||||
{
|
|
||||||
"uid": "9bd60140934a1eb9236fd7a8ab1ff6ba",
|
|
||||||
"css": "spin4",
|
|
||||||
"code": 59444,
|
|
||||||
"src": "fontelico"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "5211af474d3a9848f67f945e2ccaf143",
|
|
||||||
"css": "cancel",
|
|
||||||
"code": 59392,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "eeec3208c90b7b48e804919d0d2d4a41",
|
|
||||||
"css": "upload",
|
|
||||||
"code": 59393,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "2a6740fc2f9d0edea54205963f662594",
|
|
||||||
"css": "spin3",
|
|
||||||
"code": 59442,
|
|
||||||
"src": "fontelico"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "c6be5a58ee4e63a5ec399c2b0d15cf2c",
|
|
||||||
"css": "reply",
|
|
||||||
"code": 61714,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "474656633f79ea2f1dad59ff63f6bf07",
|
|
||||||
"css": "star",
|
|
||||||
"code": 59394,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "d17030afaecc1e1c22349b99f3c4992a",
|
|
||||||
"css": "star-empty",
|
|
||||||
"code": 59395,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "09feb4465d9bd1364f4e301c9ddbaa92",
|
|
||||||
"css": "retweet",
|
|
||||||
"code": 59396,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "7fd683b2c518ceb9e5fa6757f2276faa",
|
|
||||||
"css": "eye-off",
|
|
||||||
"code": 59397,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "73ffeb70554099177620847206c12457",
|
|
||||||
"css": "binoculars",
|
|
||||||
"code": 61925,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "e99461abfef3923546da8d745372c995",
|
|
||||||
"css": "cog",
|
|
||||||
"code": 59399,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "1bafeeb1808a5fe24484c7890096901a",
|
|
||||||
"css": "user-plus",
|
|
||||||
"code": 62004,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "559647a6f430b3aeadbecd67194451dd",
|
|
||||||
"css": "menu",
|
|
||||||
"code": 61641,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "0d20938846444af8deb1920dc85a29fb",
|
|
||||||
"css": "logout",
|
|
||||||
"code": 59400,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "ccddff8e8670dcd130e3cb55fdfc2fd0",
|
|
||||||
"css": "down-open",
|
|
||||||
"code": 59401,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "44b9e75612c5fad5505edd70d071651f",
|
|
||||||
"css": "attach",
|
|
||||||
"code": 59402,
|
|
||||||
"src": "entypo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "e15f0d620a7897e2035c18c80142f6d9",
|
|
||||||
"css": "link-ext",
|
|
||||||
"code": 61582,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "e35de5ea31cd56970498e33efbcb8e36",
|
|
||||||
"css": "link-ext-alt",
|
|
||||||
"code": 61583,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "381da2c2f7fd51f8de877c044d7f439d",
|
|
||||||
"css": "picture",
|
|
||||||
"code": 59403,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "872d9516df93eb6b776cc4d94bd97dac",
|
|
||||||
"css": "video",
|
|
||||||
"code": 59404,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "399ef63b1e23ab1b761dfbb5591fa4da",
|
|
||||||
"css": "right-open",
|
|
||||||
"code": 59405,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "d870630ff8f81e6de3958ecaeac532f2",
|
|
||||||
"css": "left-open",
|
|
||||||
"code": 59406,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "fe6697b391355dec12f3d86d6d490397",
|
|
||||||
"css": "up-open",
|
|
||||||
"code": 59407,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "9c1376672bb4f1ed616fdd78a23667e9",
|
|
||||||
"css": "comment-empty",
|
|
||||||
"code": 61669,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "ccc2329632396dc096bb638d4b46fb98",
|
|
||||||
"css": "mail-alt",
|
|
||||||
"code": 61664,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "c1f1975c885aa9f3dad7810c53b82074",
|
|
||||||
"css": "lock",
|
|
||||||
"code": 59409,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "05376be04a27d5a46e855a233d6e8508",
|
|
||||||
"css": "lock-open-alt",
|
|
||||||
"code": 61758,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "197375a3cea8cb90b02d06e4ddf1433d",
|
|
||||||
"css": "globe",
|
|
||||||
"code": 59410,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "b3a9e2dab4d19ea3b2f628242c926bfe",
|
|
||||||
"css": "brush",
|
|
||||||
"code": 59411,
|
|
||||||
"src": "iconic"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "9dd9e835aebe1060ba7190ad2b2ed951",
|
|
||||||
"css": "search",
|
|
||||||
"code": 59398,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "ca90da02d2c6a3183f2458e4dc416285",
|
|
||||||
"css": "adjust",
|
|
||||||
"code": 59414,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "5e2ab018e3044337bcef5f7e94098ea1",
|
|
||||||
"css": "thumbs-up-alt",
|
|
||||||
"code": 61796,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "c76b7947c957c9b78b11741173c8349b",
|
|
||||||
"css": "attention",
|
|
||||||
"code": 59412,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "1a5cfa186647e8c929c2b17b9fc4dac1",
|
|
||||||
"css": "plus-squared",
|
|
||||||
"code": 61694,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "44e04715aecbca7f266a17d5a7863c68",
|
|
||||||
"css": "plus",
|
|
||||||
"code": 59413,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "41087bc74d4b20b55059c60a33bf4008",
|
|
||||||
"css": "edit",
|
|
||||||
"code": 59415,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "5717236f6134afe2d2a278a5c9b3927a",
|
|
||||||
"css": "play-circled",
|
|
||||||
"code": 61764,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "d35a1d35efeb784d1dc9ac18b9b6c2b6",
|
|
||||||
"css": "pencil",
|
|
||||||
"code": 59416,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "266d5d9adf15a61800477a5acf9a4462",
|
|
||||||
"css": "chart-bar",
|
|
||||||
"code": 59419,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "d862a10e1448589215be19702f98f2c1",
|
|
||||||
"css": "smile",
|
|
||||||
"code": 61720,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "671f29fa10dda08074a4c6a341bb4f39",
|
|
||||||
"css": "bell-alt",
|
|
||||||
"code": 61683,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "5bb103cd29de77e0e06a52638527b575",
|
|
||||||
"css": "wrench",
|
|
||||||
"code": 59418,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "5b0772e9484a1a11646793a82edd622a",
|
|
||||||
"css": "pin",
|
|
||||||
"code": 59417,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "22411a88489225a018f68db737de3c77",
|
|
||||||
"css": "ellipsis",
|
|
||||||
"code": 61761,
|
|
||||||
"src": "custom_icons",
|
|
||||||
"selected": true,
|
|
||||||
"svg": {
|
|
||||||
"path": "M214 411V518Q214 540 199 556T161 571H54Q31 571 16 556T0 518V411Q0 388 16 373T54 357H161Q183 357 199 373T214 411ZM500 411V518Q500 540 484 556T446 571H339Q317 571 301 556T286 518V411Q286 388 301 373T339 357H446Q469 357 484 373T500 411ZM786 411V518Q786 540 770 556T732 571H625Q603 571 587 556T571 518V411Q571 388 587 373T625 357H732Q755 357 770 373T786 411Z",
|
|
||||||
"width": 785.7
|
|
||||||
},
|
|
||||||
"search": [
|
|
||||||
"ellipsis"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "0bef873af785ead27781fdf98b3ae740",
|
|
||||||
"css": "bell-ringing-o",
|
|
||||||
"code": 59408,
|
|
||||||
"src": "custom_icons",
|
|
||||||
"selected": true,
|
|
||||||
"svg": {
|
|
||||||
"path": "M497.8 0C468.3 0 444.4 23.9 444.4 53.3 444.4 61.1 446.1 68.3 448.9 75 301.7 96.7 213.3 213.3 213.3 320 213.3 588.3 117.8 712.8 35.6 782.2 35.6 821.1 67.8 853.3 106.7 853.3H355.6C355.6 931.7 419.4 995.6 497.8 995.6S640 931.7 640 853.3H888.9C927.8 853.3 960 821.1 960 782.2 877.8 712.8 782.2 588.3 782.2 320 782.2 213.3 693.9 96.7 546.7 75 549.4 68.3 551.1 61.1 551.1 53.3 551.1 23.9 527.2 0 497.8 0ZM189.4 44.8C108.4 118.6 70.5 215.1 71.1 320.2L142.2 319.8C141.7 231.2 170.4 158.3 237.3 97.4L189.4 44.8ZM806.2 44.8L758.3 97.4C825.2 158.3 853.9 231.2 853.3 319.8L924.4 320.2C925.1 215.1 887.2 118.6 806.2 44.8ZM408.9 844.4C413.9 844.4 417.8 848.3 417.8 853.3 417.8 897.2 453.9 933.3 497.8 933.3 502.8 933.3 506.7 937.2 506.7 942.2S502.8 951.1 497.8 951.1C443.9 951.1 400 907.2 400 853.3 400 848.3 403.9 844.4 408.9 844.4Z",
|
|
||||||
"width": 1000
|
|
||||||
},
|
|
||||||
"search": [
|
|
||||||
"bell-ringing-o"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "0b2b66e526028a6972d51a6f10281b4b",
|
|
||||||
"css": "zoom-in",
|
|
||||||
"code": 59420,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "0bda4bc779d4c32623dec2e43bd67ee8",
|
|
||||||
"css": "gauge",
|
|
||||||
"code": 61668,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "31972e4e9d080eaa796290349ae6c1fd",
|
|
||||||
"css": "users",
|
|
||||||
"code": 59421,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "e82cedfa1d5f15b00c5a81c9bd731ea2",
|
|
||||||
"css": "info-circled",
|
|
||||||
"code": 59423,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "w3nzesrlbezu6f30q7ytyq919p6gdlb6",
|
|
||||||
"css": "home-2",
|
|
||||||
"code": 59425,
|
|
||||||
"src": "typicons"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "dcedf50ab1ede3283d7a6c70e2fe32f3",
|
|
||||||
"css": "chat",
|
|
||||||
"code": 59422,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "3a00327e61b997b58518bd43ed83c3df",
|
|
||||||
"css": "login",
|
|
||||||
"code": 59424,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "f3ebd6751c15a280af5cc5f4a764187d",
|
|
||||||
"css": "arrow-curved",
|
|
||||||
"code": 59426,
|
|
||||||
"src": "iconic"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "0ddd3e8201ccc7d41f7b7c9d27eca6c1",
|
|
||||||
"css": "link",
|
|
||||||
"code": 59427,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "4aad6bb50b02c18508aae9cbe14e784e",
|
|
||||||
"css": "share",
|
|
||||||
"code": 61920,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "8b80d36d4ef43889db10bc1f0dc9a862",
|
|
||||||
"css": "user",
|
|
||||||
"code": 59428,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "12f4ece88e46abd864e40b35e05b11cd",
|
|
||||||
"css": "ok",
|
|
||||||
"code": 59431,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "4109c474ff99cad28fd5a2c38af2ec6f",
|
|
||||||
"css": "filter",
|
|
||||||
"code": 61616,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "9a76bc135eac17d2c8b8ad4a5774fc87",
|
|
||||||
"css": "download",
|
|
||||||
"code": 59429,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "f04a5d24e9e659145b966739c4fde82a",
|
|
||||||
"css": "bookmark",
|
|
||||||
"code": 59430,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "2f5ef6f6b7aaebc56458ab4e865beff5",
|
|
||||||
"css": "bookmark-empty",
|
|
||||||
"code": 61591,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "9ea0a737ccc45d6c510dcbae56058849",
|
|
||||||
"css": "music",
|
|
||||||
"code": 59432,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "1b5a5d7b7e3c71437f5a26befdd045ed",
|
|
||||||
"css": "doc",
|
|
||||||
"code": 59433,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "98d9c83c1ee7c2c25af784b518c522c5",
|
|
||||||
"css": "block",
|
|
||||||
"code": 59434,
|
|
||||||
"src": "fontawesome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uid": "3e674995cacc2b09692c096ea7eb6165",
|
|
||||||
"css": "megaphone",
|
|
||||||
"code": 59435,
|
|
||||||
"src": "fontawesome"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
{"version":3,"sources":[],"names":[],"mappings":"","file":"static/js/10.46fbbdfaf0d4800f349b.js","sourceRoot":""}
|
{"version":3,"sources":[],"names":[],"mappings":"","file":"static/js/10.46f441b948010eda4403.js","sourceRoot":""}
|
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
{"version":3,"sources":[],"names":[],"mappings":"","file":"static/js/11.708cc2513c53879a92cc.js","sourceRoot":""}
|
{"version":3,"sources":[],"names":[],"mappings":"","file":"static/js/11.8ff1ed54814f2d34cb3e.js","sourceRoot":""}
|
2
priv/static/static/js/12.13204bdd0ad5703a3ea3.js
Normal file
2
priv/static/static/js/12.13204bdd0ad5703a3ea3.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
{"version":3,"sources":[],"names":[],"mappings":"","file":"static/js/12.b3bf0bc313861d6ec36b.js","sourceRoot":""}
|
{"version":3,"sources":[],"names":[],"mappings":"","file":"static/js/12.13204bdd0ad5703a3ea3.js","sourceRoot":""}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
{"version":3,"sources":[],"names":[],"mappings":"","file":"static/js/13.adb8a942514d735722c4.js","sourceRoot":""}
|
{"version":3,"sources":[],"names":[],"mappings":"","file":"static/js/13.e27c3eeddcc4b11c1f54.js","sourceRoot":""}
|
2
priv/static/static/js/14.273855b3e4e27ce80219.js
Normal file
2
priv/static/static/js/14.273855b3e4e27ce80219.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/static/js/14.273855b3e4e27ce80219.js.map
Normal file
1
priv/static/static/js/14.273855b3e4e27ce80219.js.map
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"sources":[],"names":[],"mappings":"","file":"static/js/14.273855b3e4e27ce80219.js","sourceRoot":""}
|
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
||||||
{"version":3,"sources":[],"names":[],"mappings":"","file":"static/js/14.d015d9b2ea16407e389c.js","sourceRoot":""}
|
|
|
@ -1 +0,0 @@
|
||||||
{"version":3,"sources":[],"names":[],"mappings":"","file":"static/js/15.19866e6a366ccf982284.js","sourceRoot":""}
|
|
File diff suppressed because one or more lines are too long
1
priv/static/static/js/15.afbe29b6665fcd015b2d.js.map
Normal file
1
priv/static/static/js/15.afbe29b6665fcd015b2d.js.map
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"sources":[],"names":[],"mappings":"","file":"static/js/15.afbe29b6665fcd015b2d.js","sourceRoot":""}
|
|
@ -1 +0,0 @@
|
||||||
{"version":3,"sources":[],"names":[],"mappings":"","file":"static/js/16.38a984effd54736f6a2c.js","sourceRoot":""}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue