diff --git a/CHANGELOG.md b/CHANGELOG.md index a14e03b68..a6459ac97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,13 +8,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Changed +- **Breaking**: Changed `mix pleroma.user toggle_confirmed` to `mix pleroma.user confirm` +- **Breaking**: Changed `mix pleroma.user toggle_activated` to `mix pleroma.user activate/deactivate` +- **Breaking**: AdminAPI changed User field `confirmation_pending` to `is_confirmed` +- **Breaking**: AdminAPI changed User field `approval_pending` to `is_approved` +- **Breaking**: AdminAPI changed User field `deactivated` to `is_active` - 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. - Improved registration workflow for email confirmation and account approval modes. -- **Breaking:** Changed `mix pleroma.user toggle_confirmed` to `mix pleroma.user confirm` - Search: When using Postgres 11+, Pleroma will use the `websearch_to_tsvector` function to parse search queries. - Emoji: Support the full Unicode 13.1 set of Emoji for reactions, plus regional indicators. - Admin API: Reports now ordered by newest +- Deprecated `Pleroma.Uploaders.S3, :public_endpoint`. Now `Pleroma.Upload, :base_url` is the standard configuration key for all uploaders. +- Improved Apache webserver support: updated sample configuration, MediaProxy cache invalidation verified with the included sample script ### Added @@ -31,6 +37,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - OAuth form improvements: users are remembered by their cookie, the CSS is overridable by the admin, and the style has been improved. - OAuth improvements and fixes: more secure session-based authentication (by token that could be revoked anytime), ability to revoke belonging OAuth token from any client etc. - Ability to set ActivityPub aliases for follower migration. +- Configurable background job limits for RichMedia (link previews) and MediaProxyWarmingPolicy +
API Changes @@ -48,18 +56,30 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Users with `is_discoverable` field set to false (default value) will appear in in-service search results but be hidden from external services (search bots etc.). - Streaming API: Posts and notifications are not dropped, when CLI task is executing. - Creating incorrect IPv4 address-style HTTP links when encountering certain numbers. +- Reblog API Endpoint: Do not set visibility parameter to public by default and let CommonAPI to infer it from status, so a user can reblog their private status without explicitly setting reblog visibility to private. +- Tag URLs in statuses are now absolute
API Changes - 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. - Mastodon API: Fix not being able to add or remove multiple users at once in lists. + - Mastodon API: Fixed own_votes being not returned with poll data.
## Unreleased (Patch) + +## [2.2.2] - 2020-01-18 + ### Fixed + - StealEmojiPolicy creates dir for emojis, if it doesn't exist. +- Updated `elixir_make` to a non-retired version + +### Upgrade notes + +1. Restart Pleroma ## [2.2.1] - 2020-12-22 diff --git a/config/config.exs b/config/config.exs index db45f7a3d..5eca250bb 100644 --- a/config/config.exs +++ b/config/config.exs @@ -64,14 +64,23 @@ link_name: false, proxy_remote: false, filename_display_max_length: 30, - default_description: nil + default_description: nil, + base_url: nil config :pleroma, Pleroma.Uploaders.Local, uploads: "uploads" config :pleroma, Pleroma.Uploaders.S3, bucket: nil, - streaming_enabled: true, - public_endpoint: "https://s3.amazonaws.com" + bucket_namespace: nil, + truncated_namespace: nil, + streaming_enabled: true + +config :ex_aws, :s3, + # host: "s3.wasabisys.com", # required if not Amazon AWS + access_key_id: nil, + secret_access_key: nil, + # region: "us-east-1", # may be required for Amazon AWS + scheme: "https://" config :pleroma, :emoji, shortcode_globs: ["/emoji/custom/**/*.png"], @@ -429,7 +438,9 @@ headers: [], options: [] -config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Script, script_path: nil +config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Script, + script_path: nil, + url_format: nil # Note: media preview proxy depends on media proxy to be enabled config :pleroma, :media_preview_proxy, @@ -823,6 +834,11 @@ limit_days: 7, dir: nil +config :pleroma, ConcurrentLimiter, [ + {Pleroma.Web.RichMedia.Helpers, [max_running: 5, max_waiting: 5]}, + {Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy, [max_running: 5, max_waiting: 5]} +] + # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. import_config "#{Mix.env()}.exs" diff --git a/config/description.exs b/config/description.exs index f438a88ab..d7dc264ee 100644 --- a/config/description.exs +++ b/config/description.exs @@ -149,18 +149,12 @@ description: "S3 bucket namespace", suggestions: ["pleroma"] }, - %{ - key: :public_endpoint, - type: :string, - description: "S3 endpoint", - suggestions: ["https://s3.amazonaws.com"] - }, %{ key: :truncated_namespace, type: :string, description: "If you use S3 compatible service such as Digital Ocean Spaces or CDN, set folder name or \"\" etc." <> - " For example, when using CDN to S3 virtual host format, set \"\". At this time, write CNAME to CDN in public_endpoint." + " For example, when using CDN to S3 virtual host format, set \"\". At this time, write CNAME to CDN in Upload base_url." }, %{ key: :streaming_enabled, @@ -1633,13 +1627,20 @@ group: :pleroma, key: Pleroma.Web.MediaProxy.Invalidation.Script, type: :group, - description: "Script invalidate settings", + description: "Invalidation script settings", children: [ %{ key: :script_path, type: :string, - description: "Path to shell script. Which will run purge cache.", + description: "Path to executable script which will purge cached items.", suggestions: ["./installation/nginx-cache-purge.sh.example"] + }, + %{ + key: :url_format, + type: :string, + description: + "Optional URL format preprocessing. Only required for Apache's htcacheclean.", + suggestions: [":htcacheclean"] } ] }, @@ -3336,5 +3337,53 @@ suggestions: [:text, :protobuf] } ] + }, + %{ + group: :pleroma, + key: ConcurrentLimiter, + type: :group, + description: "Limits configuration for background tasks.", + children: [ + %{ + key: Pleroma.Web.RichMedia.Helpers, + type: :keyword, + description: "Concurrent limits configuration for getting RichMedia for activities.", + suggestions: [max_running: 5, max_waiting: 5], + children: [ + %{ + key: :max_running, + type: :integer, + description: "Max running concurrently jobs.", + suggestion: [5] + }, + %{ + key: :max_waiting, + type: :integer, + description: "Max waiting jobs.", + suggestion: [5] + } + ] + }, + %{ + key: Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy, + type: :keyword, + description: "Concurrent limits configuration for MediaProxyWarmingPolicy.", + suggestions: [max_running: 5, max_waiting: 5], + children: [ + %{ + key: :max_running, + type: :integer, + description: "Max running concurrently jobs.", + suggestion: [5] + }, + %{ + key: :max_waiting, + type: :integer, + description: "Max waiting jobs.", + suggestion: [5] + } + ] + } + ] } ] diff --git a/config/test.exs b/config/test.exs index 6f6b18558..690c98e40 100644 --- a/config/test.exs +++ b/config/test.exs @@ -115,11 +115,6 @@ config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: true -config :pleroma, Pleroma.Uploaders.S3, - bucket: nil, - streaming_enabled: true, - public_endpoint: nil - config :tzdata, :autoupdate, :disabled config :pleroma, :mrf, policies: [] diff --git a/docs/administration/CLI_tasks/user.md b/docs/administration/CLI_tasks/user.md index b57dce0e7..24fdaeab4 100644 --- a/docs/administration/CLI_tasks/user.md +++ b/docs/administration/CLI_tasks/user.md @@ -133,22 +133,20 @@ mix pleroma.user sign_out ``` - -## Deactivate or activate a user +## Activate a user === "OTP" ```sh - ./bin/pleroma_ctl user toggle_activated + ./bin/pleroma_ctl user activate NICKNAME ``` === "From Source" ```sh - mix pleroma.user toggle_activated + mix pleroma.user activate NICKNAME ``` - ## Deactivate a user and unsubscribes local users from the user === "OTP" diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md index 85551362c..9d4b07bf4 100644 --- a/docs/configuration/cheatsheet.md +++ b/docs/configuration/cheatsheet.md @@ -321,9 +321,10 @@ This section describe PWA manifest instance-specific values. Currently this opti #### Pleroma.Web.MediaProxy.Invalidation.Script This strategy allow perform external shell script to purge cache. -Urls of attachments pass to script as arguments. +Urls of attachments are passed to the script as arguments. -* `script_path`: path to external script. +* `script_path`: Path to the external script. +* `url_format`: Set to `:htcacheclean` if using Apache's htcacheclean utility. Example: @@ -549,7 +550,7 @@ the source code is here: [kocaptcha](https://github.com/koto-bank/kocaptcha). Th * `uploader`: Which one of the [uploaders](#uploaders) to use. * `filters`: List of [upload filters](#upload-filters) to use. * `link_name`: When enabled Pleroma will add a `name` parameter to the url of the upload, for example `https://instance.tld/media/corndog.png?name=corndog.png`. This is needed to provide the correct filename in Content-Disposition headers when using filters like `Pleroma.Upload.Filter.Dedupe` -* `base_url`: The base URL to access a user-uploaded file. Useful when you want to proxy the media files via another host. +* `base_url`: The base URL to access a user-uploaded file. Useful when you want to host the media files via another domain or are using a 3rd party S3 provider. * `proxy_remote`: If you're using a remote uploader, Pleroma will proxy media requests instead of redirecting to it. * `proxy_opts`: Proxy options, see `Pleroma.ReverseProxy` documentation. * `filename_display_max_length`: Set max length of a filename to display. 0 = no limit. Default: 30. @@ -570,10 +571,7 @@ Don't forget to configure [Ex AWS S3](#ex-aws-s3-settings) * `bucket`: S3 bucket name. * `bucket_namespace`: S3 bucket namespace. -* `public_endpoint`: S3 endpoint that the user finally accesses(ex. "https://s3.dualstack.ap-northeast-1.amazonaws.com") * `truncated_namespace`: If you use S3 compatible service such as Digital Ocean Spaces or CDN, set folder name or "" etc. -For example, when using CDN to S3 virtual host format, set "". -At this time, write CNAME to CDN in public_endpoint. * `streaming_enabled`: Enable streaming uploads, when enabled the file will be sent to the server in chunks as it's being read. This may be unsupported by some providers, try disabling this if you have upload problems. #### Ex AWS S3 settings @@ -1113,3 +1111,15 @@ Settings to enable and configure expiration for ephemeral activities * `:enabled` - enables ephemeral activities creation * `:min_lifetime` - minimum lifetime for ephemeral activities (in seconds). Default: 10 minutes. + +## ConcurrentLimiter + +Settings to restrict concurrently running jobs. Jobs which can be configured: + +* `Pleroma.Web.RichMedia.Helpers` - generating link previews of URLs in activities +* `Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy` - warming remote media cache via MediaProxyWarmingPolicy + +Each job has these settings: + +* `:max_running` - max concurrently runnings jobs +* `:max_waiting` - max waiting jobs diff --git a/docs/configuration/postgresql.md b/docs/configuration/postgresql.md index 6983fb459..e251eb83b 100644 --- a/docs/configuration/postgresql.md +++ b/docs/configuration/postgresql.md @@ -1,10 +1,28 @@ -# Optimizing your PostgreSQL performance +# Optimizing PostgreSQL performance -Pleroma performance depends to a large extent on good database performance. The default PostgreSQL settings are mostly fine, but often you can get better performance by changing a few settings. +Pleroma performance is largely dependent on performance of the underlying database. Better performance can be achieved by adjusting a few settings. -You can use [PGTune](https://pgtune.leopard.in.ua) to get recommendations for your setup. If you do, set the "Number of Connections" field to 20, as Pleroma will only use 10 concurrent connections anyway. If you don't, it will give you advice that might even hurt your performance. +## PGTune -We also recommend not using the "Network Storage" option. +[PgTune](https://pgtune.leopard.in.ua) can be used to get recommended settings. Be sure to set "Number of Connections" to 20, otherwise it might produce settings hurtful to database performance. It is also recommended to not use "Network Storage" option. + +## Disable generic query plans + +When PostgreSQL receives a query, it decides on a strategy for searching the requested data, this is called a query plan. The query planner has two modes: generic and custom. Generic makes a plan for all queries of the same shape, ignoring the parameters, which is then cached and reused. Custom, on the contrary, generates a unique query plan based on query parameters. + +By default PostgreSQL has an algorithm to decide which mode is more efficient for particular query, however this algorithm has been observed to be wrong on some of the queries Pleroma sends, leading to serious performance loss. Therefore, it is recommended to disable generic mode. + + +Pleroma already avoids generic query plans by default, however the method it uses is not the most efficient because it needs to be compatible with all supported PostgreSQL versions. For PostgreSQL 12 and higher additional performance can be gained by adding the following to Pleroma configuration: +```elixir +config :pleroma, Pleroma.Repo, + prepare: :named, + parameters: [ + plan_cache_mode: "force_custom_plan" + ] +``` + +A more detailed explaination of the issue can be found at . ## Example configurations @@ -28,4 +46,3 @@ max_worker_processes = 2 max_parallel_workers_per_gather = 1 max_parallel_workers = 2 ``` - diff --git a/docs/installation/alpine_linux_en.md b/docs/installation/alpine_linux_en.md index 2f8520a78..7eb1718f2 100644 --- a/docs/installation/alpine_linux_en.md +++ b/docs/installation/alpine_linux_en.md @@ -125,7 +125,7 @@ sudo -Hu pleroma mix deps.get * Check the configuration and if all looks right, rename it, so Pleroma will load it (`prod.secret.exs` for productive instance, `dev.secret.exs` for development instances): ```shell -mv config/{generated_config.exs,prod.secret.exs} +sudo -Hu pleroma mv config/{generated_config.exs,prod.secret.exs} ``` * The previous command creates also the file `config/setup_db.psql`, with which you can create the database: diff --git a/docs/installation/arch_linux_en.md b/docs/installation/arch_linux_en.md index 9cbd3f429..da78c3205 100644 --- a/docs/installation/arch_linux_en.md +++ b/docs/installation/arch_linux_en.md @@ -100,7 +100,7 @@ sudo -Hu pleroma mix deps.get * Check the configuration and if all looks right, rename it, so Pleroma will load it (`prod.secret.exs` for productive instance, `dev.secret.exs` for development instances): ```shell -mv config/{generated_config.exs,prod.secret.exs} +sudo -Hu pleroma mv config/{generated_config.exs,prod.secret.exs} ``` * The previous command creates also the file `config/setup_db.psql`, with which you can create the database: diff --git a/docs/installation/debian_based_en.md b/docs/installation/debian_based_en.md index 926a85367..c5687a01e 100644 --- a/docs/installation/debian_based_en.md +++ b/docs/installation/debian_based_en.md @@ -98,7 +98,7 @@ sudo -Hu pleroma mix deps.get * Check the configuration and if all looks right, rename it, so Pleroma will load it (`prod.secret.exs` for productive instance, `dev.secret.exs` for development instances): ```shell -mv config/{generated_config.exs,prod.secret.exs} +sudo -Hu pleroma mv config/{generated_config.exs,prod.secret.exs} ``` diff --git a/docs/installation/debian_based_jp.md b/docs/installation/debian_based_jp.md index 2613a86d9..c4bbd4780 100644 --- a/docs/installation/debian_based_jp.md +++ b/docs/installation/debian_based_jp.md @@ -98,7 +98,7 @@ sudo -Hu pleroma mix pleroma.instance gen * コンフィギュレーションを確認して、もし問題なければ、ファイル名を変更してください。 ``` -mv config/{generated_config.exs,prod.secret.exs} +sudo -Hu pleroma mv config/{generated_config.exs,prod.secret.exs} ``` * 先程のコマンドで、すでに `config/setup_db.psql` というファイルが作られています。このファイルをもとに、データベースを作成します。 diff --git a/docs/installation/otp_en.md b/docs/installation/otp_en.md index 63eda63ca..f36b33c32 100644 --- a/docs/installation/otp_en.md +++ b/docs/installation/otp_en.md @@ -89,6 +89,8 @@ RUM indexes are an alternative indexing scheme that is not included in PostgreSQ #### (Optional) Performance configuration It is encouraged to check [Optimizing your PostgreSQL performance](../configuration/postgresql.md) document, for tips on PostgreSQL tuning. +Restart PostgreSQL to apply configuration changes: + === "Alpine" ``` rc-service postgresql restart @@ -99,17 +101,6 @@ It is encouraged to check [Optimizing your PostgreSQL performance](../configurat systemctl restart postgresql ``` -If you are using PostgreSQL 12 or higher, add this to your Ecto database configuration - -```elixir -# -config :pleroma, Pleroma.Repo, -prepare: :named, -parameters: [ - plan_cache_mode: "force_custom_plan" -] -``` - ### Installing Pleroma ```sh # Create a Pleroma user diff --git a/installation/apache-cache-purge.sh.example b/installation/apache-cache-purge.sh.example new file mode 100755 index 000000000..7b4262875 --- /dev/null +++ b/installation/apache-cache-purge.sh.example @@ -0,0 +1,36 @@ +#!/bin/sh + +# A simple shell script to delete a media from Apache's mod_disk_cache. +# You will likely need to setup a sudo rule like the following: +# +# Cmnd_Alias HTCACHECLEAN = /usr/local/sbin/htcacheclean +# pleroma ALL=HTCACHECLEAN, NOPASSWD: HTCACHECLEAN +# +# Please also ensure you have enabled: +# +# config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Script, url_format: :htcacheclean +# +# which will correctly format the URLs passed to this script for the htcacheclean utility. +# + +SCRIPTNAME=${0##*/} + +# mod_disk_cache directory +CACHE_DIRECTORY="/tmp/pleroma-media-cache" + +## Removes an item via the htcacheclean utility +## $1 - the filename, can be a pattern . +## $2 - the cache directory. +purge_item() { + sudo htcacheclean -v -p "${2}" "${1}" +} # purge_item + +purge() { + for url in $@ + do + echo "$SCRIPTNAME delete \`$url\` from cache ($CACHE_DIRECTORY)" + purge_item "$url" $CACHE_DIRECTORY + done +} + +purge $@ diff --git a/installation/pleroma-apache.conf b/installation/pleroma-apache.conf index 0d627f2d7..139abe9e1 100644 --- a/installation/pleroma-apache.conf +++ b/installation/pleroma-apache.conf @@ -1,73 +1,84 @@ -# default Apache site config for Pleroma -# -# needed modules: define headers proxy proxy_http proxy_wstunnel rewrite ssl -# optional modules: cache cache_disk +# Sample Apache config for Pleroma # # Simple installation instructions: -# 1. Install your TLS certificate, possibly using Let's Encrypt. -# 2. Replace 'example.tld' with your instance's domain wherever it appears. -# 3. This assumes a Debian style Apache config. Copy this file to -# /etc/apache2/sites-available/ and then add a symlink to it in -# /etc/apache2/sites-enabled/ by running 'a2ensite pleroma-apache.conf', then restart Apache. +# 1. Install your TLS certificate. We recommend using Let's Encrypt via Certbot +# 2. Replace 'example.tld' with your instance's domain. +# 3. This assumes a Debian-style Apache config. Copy this file to +# /etc/apache2/sites-available/ and then activate the site by running +# 'a2ensite pleroma-apache.conf', then restart Apache. # # Optional: enable disk-based caching for the media proxy # For details, see https://git.pleroma.social/pleroma/pleroma/wikis/How%20to%20activate%20mediaproxy # -# 1. Create the directory listed below as the CacheRoot, and make sure +# 1. Create a directory as shown below for the CacheRoot and make sure # the Apache user can write to it. # 2. Configure Apache's htcacheclean to clean the directory periodically. -# 3. Run 'a2enmod cache cache_disk' and restart Apache. +# Your OS may provide a service you can enable to do this automatically. Define servername example.tld + + LoadModule proxy_module libexec/apache24/mod_proxy.so + + + LoadModule proxy_http_module libexec/apache24/mod_proxy_http.so + + + LoadModule proxy_wstunnel_module libexec/apache24/mod_proxy_wstunnel.so + + + LoadModule rewrite_module libexec/apache24/mod_rewrite.so + + + LoadModule ssl_module libexec/apache24/mod_ssl.so + + + LoadModule cache_module libexec/apache24/mod_cache.so + + + LoadModule cache_disk_module libexec/apache24/mod_cache_disk.so + + ServerName ${servername} ServerTokens Prod -ErrorLog ${APACHE_LOG_DIR}/error.log -CustomLog ${APACHE_LOG_DIR}/access.log combined +# If you want Pleroma-specific logs +#ErrorLog /var/log/httpd-pleroma-error.log +#CustomLog /var/log/httpd-pleroma-access.log combined - Redirect permanent / https://${servername} + RewriteEngine on + RewriteCond %{SERVER_NAME} =${servername} + RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] SSLEngine on SSLCertificateFile /etc/letsencrypt/live/${servername}/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/${servername}/privkey.pem + # Make sure you have the certbot-apache module installed + Include /etc/letsencrypt/options-ssl-apache.conf - # Mozilla modern configuration, tweak to your needs - SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 - SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256 - SSLHonorCipherOrder on - SSLCompression off - SSLSessionTickets off - - # uncomment the following to enable mediaproxy caching on disk - # - # CacheRoot /var/cache/apache2/mod_cache_disk - # CacheDirLevels 1 - # CacheDirLength 2 - # CacheEnable disk /proxy - # CacheLock on - # + # Uncomment the following to enable MediaProxy caching on disk + #CacheRoot /tmp/pleroma-media-cache/ + #CacheDirLevels 1 + #CacheDirLength 2 + #CacheEnable disk /proxy + #CacheLock on + #CacheHeader on + #CacheDetailHeader on + ## 16MB max filesize for caching, configure as desired + #CacheMaxFileSize 16000000 + #CacheDefaultExpire 86400 RewriteEngine On RewriteCond %{HTTP:Connection} Upgrade [NC] RewriteCond %{HTTP:Upgrade} websocket [NC] - RewriteRule /(.*) ws://localhost:4000/$1 [P,L] + RewriteRule /(.*) ws://127.0.0.1:4000/$1 [P,L] + #ProxyRequests must be off or you open your server to abuse as an open proxy ProxyRequests off - # this is explicitly IPv4 since Pleroma.Web.Endpoint binds on IPv4 only - # and `localhost.` resolves to [::0] on some systems: see issue #930 ProxyPass / http://127.0.0.1:4000/ ProxyPassReverse / http://127.0.0.1:4000/ - - RequestHeader set Host ${servername} ProxyPreserveHost On - -# OCSP Stapling, only in httpd 2.3.3 and later -SSLUseStapling on -SSLStaplingResponderTimeout 5 -SSLStaplingReturnResponderErrors off -SSLStaplingCache shmcb:/var/run/ocsp(128000) diff --git a/lib/mix/pleroma.ex b/lib/mix/pleroma.ex index 45d0ad624..2b6c7d6bb 100644 --- a/lib/mix/pleroma.ex +++ b/lib/mix/pleroma.ex @@ -13,7 +13,8 @@ defmodule Mix.Pleroma do :flake_id, :swoosh, :timex, - :fast_html + :fast_html, + :oban ] @cachex_children ["object", "user", "scrubber", "web_resp"] @doc "Common functions to be reused in mix tasks" diff --git a/lib/mix/tasks/pleroma/email.ex b/lib/mix/tasks/pleroma/email.ex index 54f158f73..e05c207e5 100644 --- a/lib/mix/tasks/pleroma/email.ex +++ b/lib/mix/tasks/pleroma/email.ex @@ -33,8 +33,8 @@ def run(["resend_confirmation_emails"]) do Pleroma.User.Query.build(%{ local: true, - deactivated: false, - confirmation_pending: true, + is_active: true, + is_confirmed: false, invisible: false }) |> Pleroma.Repo.chunk_stream(500) diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex index f90c045fe..53d5fc6d9 100644 --- a/lib/mix/tasks/pleroma/user.ex +++ b/lib/mix/tasks/pleroma/user.ex @@ -74,7 +74,7 @@ def run(["new", nickname, email | rest]) do bio: bio } - changeset = User.register_changeset(%User{}, params, need_confirmation: false) + changeset = User.register_changeset(%User{}, params, is_confirmed: true) {:ok, _user} = User.register(changeset) shell_info("User #{nickname} created") @@ -107,21 +107,6 @@ def run(["rm", nickname]) do end end - def run(["toggle_activated", nickname]) do - start_pleroma() - - with %User{} = user <- User.get_cached_by_nickname(nickname) do - {:ok, user} = User.deactivate(user, !user.deactivated) - - shell_info( - "Activation status of #{nickname}: #{if(user.deactivated, do: "de", else: "")}activated" - ) - else - _ -> - shell_error("No user #{nickname}") - end - end - def run(["reset_password", nickname]) do start_pleroma() @@ -156,20 +141,41 @@ def run(["reset_mfa", nickname]) do end end + def run(["activate", nickname]) do + start_pleroma() + + with %User{} = user <- User.get_cached_by_nickname(nickname), + false <- user.is_active do + User.set_activation(user, true) + :timer.sleep(500) + + shell_info("Successfully activated #{nickname}") + else + true -> + shell_info("User #{nickname} already activated") + + _ -> + shell_error("No user #{nickname}") + end + end + def run(["deactivate", nickname]) do start_pleroma() - with %User{} = user <- User.get_cached_by_nickname(nickname) do - shell_info("Deactivating #{user.nickname}") - User.deactivate(user) + with %User{} = user <- User.get_cached_by_nickname(nickname), + true <- user.is_active do + User.set_activation(user, false) :timer.sleep(500) user = User.get_cached_by_id(user.id) if Enum.empty?(Enum.filter(User.get_friends(user), & &1.local)) do - shell_info("Successfully unsubscribed all local followers from #{user.nickname}") + shell_info("Successfully deactivated #{nickname} and unsubscribed all local followers") end else + false -> + shell_info("User #{nickname} already deactivated") + _ -> shell_error("No user #{nickname}") end @@ -213,7 +219,7 @@ def run(["set", nickname | rest]) do user = case Keyword.get(options, :confirmed) do nil -> user - value -> set_confirmed(user, value) + value -> set_confirmation(user, value) end user = @@ -351,7 +357,7 @@ def run(["confirm", nickname]) do with %User{} = user <- User.get_cached_by_nickname(nickname) do {:ok, user} = User.confirm(user) - message = if user.confirmation_pending, do: "needs", else: "doesn't need" + message = if !user.is_confirmed, do: "needs", else: "doesn't need" shell_info("#{nickname} #{message} confirmation.") else @@ -365,7 +371,7 @@ def run(["confirm_all"]) do Pleroma.User.Query.build(%{ local: true, - deactivated: false, + is_active: true, is_moderator: false, is_admin: false, invisible: false @@ -373,7 +379,7 @@ def run(["confirm_all"]) do |> Pleroma.Repo.chunk_stream(500, :batches) |> Stream.each(fn users -> users - |> Enum.each(fn user -> User.need_confirmation(user, false) end) + |> Enum.each(fn user -> User.set_confirmation(user, true) end) end) |> Stream.run() end @@ -383,7 +389,7 @@ def run(["unconfirm_all"]) do Pleroma.User.Query.build(%{ local: true, - deactivated: false, + is_active: true, is_moderator: false, is_admin: false, invisible: false @@ -391,7 +397,7 @@ def run(["unconfirm_all"]) do |> Pleroma.Repo.chunk_stream(500, :batches) |> Stream.each(fn users -> users - |> Enum.each(fn user -> User.need_confirmation(user, true) end) + |> Enum.each(fn user -> User.set_confirmation(user, false) end) end) |> Stream.run() end @@ -420,7 +426,7 @@ def run(["list"]) do shell_info( "#{user.nickname} moderator: #{user.is_moderator}, admin: #{user.is_admin}, locked: #{ user.is_locked - }, deactivated: #{user.deactivated}" + }, is_active: #{user.is_active}" ) end) end) @@ -454,10 +460,10 @@ defp set_locked(user, value) do user end - defp set_confirmed(user, value) do - {:ok, user} = User.need_confirmation(user, !value) + defp set_confirmation(user, value) do + {:ok, user} = User.set_confirmation(user, value) - shell_info("Confirmation pending status of #{user.nickname}: #{user.confirmation_pending}") + shell_info("Confirmation status of #{user.nickname}: #{user.is_confirmed}") user end end diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index 203a95004..9e262235e 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -297,7 +297,16 @@ defp http_children(_, _), do: [] @spec limiters_setup() :: :ok def limiters_setup do - [Pleroma.Web.RichMedia.Helpers, Pleroma.Web.MediaProxy] - |> Enum.each(&ConcurrentLimiter.new(&1, 1, 0)) + config = Config.get(ConcurrentLimiter, []) + + [Pleroma.Web.RichMedia.Helpers, Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy] + |> Enum.each(fn module -> + mod_config = Keyword.get(config, module, []) + + max_running = Keyword.get(mod_config, :max_running, 5) + max_waiting = Keyword.get(mod_config, :max_waiting, 5) + + ConcurrentLimiter.new(module, max_running, max_waiting) + end) end end diff --git a/lib/pleroma/config/deprecation_warnings.ex b/lib/pleroma/config/deprecation_warnings.ex index 382076c31..24aa5993b 100644 --- a/lib/pleroma/config/deprecation_warnings.ex +++ b/lib/pleroma/config/deprecation_warnings.ex @@ -40,7 +40,8 @@ def warn do :ok <- check_welcome_message_config(), :ok <- check_gun_pool_options(), :ok <- check_activity_expiration_config(), - :ok <- check_remote_ip_plug_name() do + :ok <- check_remote_ip_plug_name(), + :ok <- check_uploders_s3_public_endpoint() do :ok else _ -> @@ -193,4 +194,25 @@ def check_remote_ip_plug_name do warning_preface ) end + + @spec check_uploders_s3_public_endpoint() :: :ok | nil + def check_uploders_s3_public_endpoint do + s3_config = Pleroma.Config.get([Pleroma.Uploaders.S3]) + + use_old_config = Keyword.has_key?(s3_config, :public_endpoint) + + if use_old_config do + Logger.error(""" + !!!DEPRECATION WARNING!!! + Your config is using the old setting for controlling the URL of media uploaded to your S3 bucket.\n + Please make the following change at your earliest convenience.\n + \n* `config :pleroma, Pleroma.Uploaders.S3, public_endpoint` is now equal to: + \n* `config :pleroma, Pleroma.Upload, base_url` + """) + + :error + else + :ok + end + end end diff --git a/lib/pleroma/following_relationship.ex b/lib/pleroma/following_relationship.ex index 147cb9df0..a0c7e6e39 100644 --- a/lib/pleroma/following_relationship.ex +++ b/lib/pleroma/following_relationship.ex @@ -152,7 +152,7 @@ def get_follow_requests(%User{id: id}) do |> join(:inner, [r], f in assoc(r, :follower)) |> where([r], r.state == ^:follow_pending) |> where([r], r.following_id == ^id) - |> where([r, f], f.deactivated != true) + |> where([r, f], f.is_active == true) |> select([r, f], f) |> Repo.all() end diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 7a69dacde..55b513212 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -115,7 +115,7 @@ def for_user_query(user, opts \\ %{}) do |> where( [n, a], fragment( - "? not in (SELECT ap_id FROM users WHERE deactivated = 'true')", + "? not in (SELECT ap_id FROM users WHERE is_active = 'false')", a.actor ) ) diff --git a/lib/pleroma/stats.ex b/lib/pleroma/stats.ex index 77505bb04..b096a9b1e 100644 --- a/lib/pleroma/stats.ex +++ b/lib/pleroma/stats.ex @@ -75,7 +75,7 @@ def calculate_stat_data do users_query = from(u in User, - where: u.deactivated != true, + where: u.is_active == true, where: u.local == true, where: not is_nil(u.nickname), where: not u.invisible diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index 00b61ca80..654711351 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -131,12 +131,7 @@ defp get_opts(opts) do uploader: Keyword.get(opts, :uploader, Pleroma.Config.get([__MODULE__, :uploader])), filters: Keyword.get(opts, :filters, Pleroma.Config.get([__MODULE__, :filters])), description: Keyword.get(opts, :description), - base_url: - Keyword.get( - opts, - :base_url, - Pleroma.Config.get([__MODULE__, :base_url], Pleroma.Web.base_url()) - ) + base_url: base_url() } end @@ -217,14 +212,7 @@ defp url_from_spec(%__MODULE__{name: name}, base_url, {:file, path}) do "" end - prefix = - if is_nil(Pleroma.Config.get([__MODULE__, :base_url])) do - "media" - else - "" - end - - [base_url, prefix, path] + [base_url, path] |> Path.join() end @@ -241,13 +229,15 @@ def base_url do Pleroma.Uploaders.S3 -> bucket = Config.get([Pleroma.Uploaders.S3, :bucket]) + truncated_namespace = Config.get([Pleroma.Uploaders.S3, :truncated_namespace]) + namespace = Config.get([Pleroma.Uploaders.S3, :bucket_namespace]) bucket_with_namespace = cond do - truncated_namespace = Config.get([Pleroma.Uploaders.S3, :truncated_namespace]) -> + !is_nil(truncated_namespace) -> truncated_namespace - namespace = Config.get([Pleroma.Uploaders.S3, :bucket_namespace]) -> + !is_nil(namespace) -> namespace <> ":" <> bucket true -> @@ -261,7 +251,7 @@ def base_url do end _ -> - public_endpoint || upload_base_url + public_endpoint || upload_base_url || Pleroma.Web.base_url() <> "/media/" end end end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 6a81adfd6..e422b59f1 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -110,14 +110,14 @@ defmodule Pleroma.User do field(:follower_count, :integer, default: 0) field(:following_count, :integer, default: 0) field(:is_locked, :boolean, default: false) - field(:confirmation_pending, :boolean, default: false) + field(:is_confirmed, :boolean, default: true) field(:password_reset_pending, :boolean, default: false) - field(:approval_pending, :boolean, default: false) + field(:is_approved, :boolean, default: true) field(:registration_reason, :string, default: nil) field(:confirmation_token, :string, default: nil) field(:default_scope, :string, default: "public") field(:domain_blocks, {:array, :string}, default: []) - field(:deactivated, :boolean, default: false) + field(:is_active, :boolean, default: true) field(:no_rich_text, :boolean, default: false) field(:ap_enabled, :boolean, default: false) field(:is_moderator, :boolean, default: false) @@ -217,7 +217,8 @@ def unquote(:"#{outgoing_relation_target}_relation")(user, restrict_deactivated? target_users_query = assoc(user, unquote(outgoing_relation_target)) if restrict_deactivated? do - restrict_deactivated(target_users_query) + target_users_query + |> User.Query.build(%{deactivated: false}) else target_users_query end @@ -286,18 +287,10 @@ def binary_id(%User{} = user), do: binary_id(user.id) @doc "Returns status account" @spec account_status(User.t()) :: account_status() - def account_status(%User{deactivated: true}), do: :deactivated + def account_status(%User{is_active: false}), do: :deactivated def account_status(%User{password_reset_pending: true}), do: :password_reset_pending - def account_status(%User{local: true, approval_pending: true}), do: :approval_pending - - def account_status(%User{local: true, confirmation_pending: true}) do - if Config.get([:instance, :account_activation_required]) do - :confirmation_pending - else - :active - end - end - + def account_status(%User{local: true, is_approved: false}), do: :approval_pending + def account_status(%User{local: true, is_confirmed: false}), do: :confirmation_pending def account_status(%User{}), do: :active @spec visible_for(User.t(), User.t() | nil) :: @@ -386,11 +379,6 @@ def ap_followers(%User{} = user), do: "#{ap_id(user)}/followers" def ap_following(%User{following_address: fa}) when is_binary(fa), do: fa def ap_following(%User{} = user), do: "#{ap_id(user)}/following" - @spec restrict_deactivated(Ecto.Query.t()) :: Ecto.Query.t() - def restrict_deactivated(query) do - from(u in query, where: u.deactivated != ^true) - end - defp truncate_fields_param(params) do if Map.has_key?(params, :fields) do Map.put(params, :fields, Enum.map(params[:fields], &truncate_field/1)) @@ -704,23 +692,23 @@ def register_changeset(struct, params \\ %{}, opts \\ []) do reason_limit = Config.get([:instance, :registration_reason_length], 500) params = Map.put_new(params, :accepts_chat_messages, true) - need_confirmation? = - if is_nil(opts[:need_confirmation]) do - Config.get([:instance, :account_activation_required]) + confirmed? = + if is_nil(opts[:confirmed]) do + !Config.get([:instance, :account_activation_required]) else - opts[:need_confirmation] + opts[:confirmed] end - need_approval? = - if is_nil(opts[:need_approval]) do - Config.get([:instance, :account_approval_required]) + approved? = + if is_nil(opts[:approved]) do + !Config.get([:instance, :account_approval_required]) else - opts[:need_approval] + opts[:approved] end struct - |> confirmation_changeset(need_confirmation: need_confirmation?) - |> approval_changeset(need_approval: need_approval?) + |> confirmation_changeset(set_confirmation: confirmed?) + |> approval_changeset(set_approval: approved?) |> cast(params, [ :bio, :raw_bio, @@ -785,7 +773,7 @@ defp autofollow_users(user) do candidates = Config.get([:instance, :autofollowed_nicknames]) autofollowed_users = - User.Query.build(%{nickname: candidates, local: true, deactivated: false}) + User.Query.build(%{nickname: candidates, local: true, is_active: true}) |> Repo.all() follow_all(user, autofollowed_users) @@ -808,20 +796,20 @@ def register(%Ecto.Changeset{} = changeset) do end end - def post_register_action(%User{confirmation_pending: true} = user) do + def post_register_action(%User{is_confirmed: false} = user) do with {:ok, _} <- try_send_confirmation_email(user) do {:ok, user} end end - def post_register_action(%User{approval_pending: true} = user) do + def post_register_action(%User{is_approved: false} = user) do with {:ok, _} <- send_user_approval_email(user), {:ok, _} <- send_admin_approval_emails(user) do {:ok, user} end end - def post_register_action(%User{approval_pending: false, confirmation_pending: false} = user) do + def post_register_action(%User{is_approved: true, is_confirmed: true} = user) do with {:ok, user} <- autofollow_users(user), {:ok, _} <- autofollowing_users(user), {:ok, user} <- set_cache(user), @@ -882,7 +870,7 @@ def send_welcome_email(%User{email: email} = user) when is_binary(email) do def send_welcome_email(_), do: {:ok, :noop} @spec try_send_confirmation_email(User.t()) :: {:ok, :enqueued | :noop} - def try_send_confirmation_email(%User{confirmation_pending: true, email: email} = user) + def try_send_confirmation_email(%User{is_confirmed: false, email: email} = user) when is_binary(email) do if Config.get([:instance, :account_activation_required]) do send_confirmation_email(user) @@ -946,7 +934,7 @@ def follow(%User{} = follower, %User{} = followed, state \\ :follow_accept) do deny_follow_blocked = Config.get([:user, :deny_follow_blocked]) cond do - followed.deactivated -> + not followed.is_active -> {:error, "Could not follow user: #{followed.nickname} is deactivated."} deny_follow_blocked and blocks?(followed, follower) -> @@ -1181,7 +1169,7 @@ def get_or_fetch_by_nickname(nickname) do @spec get_followers_query(User.t(), pos_integer() | nil) :: Ecto.Query.t() def get_followers_query(%User{} = user, nil) do - User.Query.build(%{followers: user, deactivated: false}) + User.Query.build(%{followers: user, is_active: true}) end def get_followers_query(%User{} = user, page) do @@ -1357,7 +1345,7 @@ def update_following_count(%User{local: true} = user) do @spec get_users_from_set([String.t()], keyword()) :: [User.t()] def get_users_from_set(ap_ids, opts \\ []) do local_only = Keyword.get(opts, :local_only, true) - criteria = %{ap_id: ap_ids, deactivated: false} + criteria = %{ap_id: ap_ids, is_active: true} criteria = if local_only, do: Map.put(criteria, :local, true), else: criteria User.Query.build(criteria) @@ -1368,7 +1356,7 @@ def get_users_from_set(ap_ids, opts \\ []) do def get_recipients_from_activity(%Activity{recipients: to, actor: actor}) do to = [actor | to] - query = User.Query.build(%{recipients_from_activity: to, local: true, deactivated: false}) + query = User.Query.build(%{recipients_from_activity: to, local: true, is_active: true}) query |> Repo.all() @@ -1587,19 +1575,19 @@ defp maybe_filter_on_ap_id(query, ap_ids) when is_list(ap_ids) do defp maybe_filter_on_ap_id(query, _ap_ids), do: query - def deactivate_async(user, status \\ true) do - BackgroundWorker.enqueue("deactivate_user", %{"user_id" => user.id, "status" => status}) + def set_activation_async(user, status \\ true) do + BackgroundWorker.enqueue("user_activation", %{"user_id" => user.id, "status" => status}) end - def deactivate(user, status \\ true) - - def deactivate(users, status) when is_list(users) do + @spec set_activation([User.t()], boolean()) :: {:ok, User.t()} | {:error, Changeset.t()} + def set_activation(users, status) when is_list(users) do Repo.transaction(fn -> - for user <- users, do: deactivate(user, status) + for user <- users, do: set_activation(user, status) end) end - def deactivate(%User{} = user, status) do + @spec set_activation(User.t(), boolean()) :: {:ok, User.t()} | {:error, Changeset.t()} + def set_activation(%User{} = user, status) do with {:ok, user} <- set_activation_status(user, status) do user |> get_followers() @@ -1624,8 +1612,8 @@ def approve(users) when is_list(users) do end) end - def approve(%User{approval_pending: true} = user) do - with chg <- change(user, approval_pending: false), + def approve(%User{is_approved: false} = user) do + with chg <- change(user, is_approved: true), {:ok, user} <- update_and_set_cache(chg) do post_register_action(user) {:ok, user} @@ -1642,8 +1630,8 @@ def confirm(users) when is_list(users) do end) end - def confirm(%User{confirmation_pending: true} = user) do - with chg <- confirmation_changeset(user, need_confirmation: false), + def confirm(%User{is_confirmed: false} = user) do + with chg <- confirmation_changeset(user, set_confirmation: true), {:ok, user} <- update_and_set_cache(chg) do post_register_action(user) {:ok, user} @@ -1682,13 +1670,13 @@ def purge_user_changeset(user) do follower_count: 0, following_count: 0, is_locked: false, - confirmation_pending: false, + is_confirmed: true, password_reset_pending: false, - approval_pending: false, + is_approved: true, registration_reason: nil, confirmation_token: nil, domain_blocks: [], - deactivated: true, + is_active: false, ap_enabled: false, is_moderator: false, is_admin: false, @@ -1762,7 +1750,7 @@ def perform(:delete, %User{} = user) do delete_or_deactivate(user) end - def perform(:deactivate_async, user, status), do: deactivate(user, status) + def perform(:set_activation_async, user, status), do: set_activation(user, status) @spec external_users_query() :: Ecto.Query.t() def external_users_query do @@ -2056,7 +2044,7 @@ def error_user(ap_id) do @spec all_superusers() :: [User.t()] def all_superusers do - User.Query.build(%{super_users: true, local: true, deactivated: false}) + User.Query.build(%{super_users: true, local: true, is_active: true}) |> Repo.all() end @@ -2097,7 +2085,7 @@ def list_inactive_users_query(inactivity_threshold \\ 7) do left_join: a in Pleroma.Activity, on: u.ap_id == a.actor, where: not is_nil(u.nickname), - where: u.deactivated != ^true, + where: u.is_active == ^true, where: u.id not in ^has_read_notifications, group_by: u.id, having: @@ -2138,10 +2126,10 @@ def touch_last_digest_emailed_at(user) do updated_user end - @spec need_confirmation(User.t(), boolean()) :: {:ok, User.t()} | {:error, Changeset.t()} - def need_confirmation(%User{} = user, bool) do + @spec set_confirmation(User.t(), boolean()) :: {:ok, User.t()} | {:error, Changeset.t()} + def set_confirmation(%User{} = user, bool) do user - |> confirmation_changeset(need_confirmation: bool) + |> confirmation_changeset(set_confirmation: bool) |> update_and_set_cache() end @@ -2218,9 +2206,9 @@ def change_email(user, email) do end # Internal function; public one is `deactivate/2` - defp set_activation_status(user, deactivated) do + defp set_activation_status(user, status) do user - |> cast(%{deactivated: deactivated}, [:deactivated]) + |> cast(%{is_active: status}, [:is_active]) |> update_and_set_cache() end @@ -2309,27 +2297,26 @@ def mastodon_settings_update(user, settings) do end @spec confirmation_changeset(User.t(), keyword()) :: Changeset.t() - def confirmation_changeset(user, need_confirmation: need_confirmation?) do + def confirmation_changeset(user, set_confirmation: confirmed?) do params = - if need_confirmation? do + if confirmed? do %{ - confirmation_pending: true, - confirmation_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64() + is_confirmed: true, + confirmation_token: nil } else %{ - confirmation_pending: false, - confirmation_token: nil + is_confirmed: false, + confirmation_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64() } end - cast(user, params, [:confirmation_pending, :confirmation_token]) + cast(user, params, [:is_confirmed, :confirmation_token]) end @spec approval_changeset(User.t(), keyword()) :: Changeset.t() - def approval_changeset(user, need_approval: need_approval?) do - params = if need_approval?, do: %{approval_pending: true}, else: %{approval_pending: false} - cast(user, params, [:approval_pending]) + def approval_changeset(user, set_approval: approved?) do + cast(user, %{is_approved: approved?}, [:is_approved]) end def add_pinnned_activity(user, %Pleroma.Activity{id: id}) do diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex index ab9554bd2..fa46545da 100644 --- a/lib/pleroma/user/query.ex +++ b/lib/pleroma/user/query.ex @@ -137,8 +137,9 @@ defp compose_query({:local, _}, query), do: location_query(query, true) defp compose_query({:external, _}, query), do: location_query(query, false) defp compose_query({:active, _}, query) do - User.restrict_deactivated(query) - |> where([u], u.approval_pending == false) + where(query, [u], u.is_active == true) + |> where([u], u.is_approved == true) + |> where([u], u.is_confirmed == true) end defp compose_query({:legacy_active, _}, query) do @@ -147,23 +148,23 @@ defp compose_query({:legacy_active, _}, query) do end defp compose_query({:deactivated, false}, query) do - User.restrict_deactivated(query) + where(query, [u], u.is_active == true) end defp compose_query({:deactivated, true}, query) do - where(query, [u], u.deactivated == ^true) + where(query, [u], u.is_active == false) end defp compose_query({:confirmation_pending, bool}, query) do - where(query, [u], u.confirmation_pending == ^bool) + where(query, [u], u.is_confirmed != ^bool) end defp compose_query({:need_approval, _}, query) do - where(query, [u], u.approval_pending) + where(query, [u], u.is_approved == false) end defp compose_query({:unconfirmed, _}, query) do - where(query, [u], u.confirmation_pending) + where(query, [u], u.is_confirmed == false) end defp compose_query({:followers, %User{id: id}}, query) do diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index c5bc08153..d0bb07aab 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -56,7 +56,7 @@ defp check_actor_is_active(nil), do: true defp check_actor_is_active(actor) when is_binary(actor) do case User.get_cached_by_ap_id(actor) do - %User{deactivated: deactivated} -> not deactivated + %User{is_active: true} -> true _ -> false end end diff --git a/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex b/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex index 50d48edc8..8dbf44071 100644 --- a/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex @@ -27,7 +27,7 @@ defp prefetch(url) do if Pleroma.Config.get(:env) == :test do fetch(prefetch_url) else - ConcurrentLimiter.limit(MediaProxy, fn -> + ConcurrentLimiter.limit(__MODULE__, fn -> Task.start(fn -> fetch(prefetch_url) end) end) end diff --git a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex index f5f87ca5d..093549a45 100644 --- a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex +++ b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex @@ -35,7 +35,7 @@ def validate_actor_presence(cng, options \\ []) do cng |> validate_change(field_name, fn field_name, actor -> case User.get_cached_by_ap_id(actor) do - %User{deactivated: true} -> + %User{is_active: false} -> [{field_name, "user is deactivated"}] %User{} -> diff --git a/lib/pleroma/web/admin_api/controllers/user_controller.ex b/lib/pleroma/web/admin_api/controllers/user_controller.ex index fa710c7ec..a18b9f8d5 100644 --- a/lib/pleroma/web/admin_api/controllers/user_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/user_controller.ex @@ -172,9 +172,9 @@ def show(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do def toggle_activation(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do user = User.get_cached_by_nickname(nickname) - {:ok, updated_user} = User.deactivate(user, !user.deactivated) + {:ok, updated_user} = User.set_activation(user, !user.is_active) - action = if user.deactivated, do: "activate", else: "deactivate" + action = if !user.is_active, do: "activate", else: "deactivate" ModerationLog.insert_log(%{ actor: admin, @@ -189,7 +189,7 @@ def toggle_activation(%{assigns: %{user: admin}} = conn, %{"nickname" => nicknam def activate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do users = Enum.map(nicknames, &User.get_cached_by_nickname/1) - {:ok, updated_users} = User.deactivate(users, false) + {:ok, updated_users} = User.set_activation(users, true) ModerationLog.insert_log(%{ actor: admin, @@ -204,7 +204,7 @@ def activate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do def deactivate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do users = Enum.map(nicknames, &User.get_cached_by_nickname/1) - {:ok, updated_users} = User.deactivate(users, true) + {:ok, updated_users} = User.set_activation(users, false) ModerationLog.insert_log(%{ actor: admin, diff --git a/lib/pleroma/web/admin_api/views/account_view.ex b/lib/pleroma/web/admin_api/views/account_view.ex index 37188bfeb..d7c63d385 100644 --- a/lib/pleroma/web/admin_api/views/account_view.ex +++ b/lib/pleroma/web/admin_api/views/account_view.ex @@ -73,12 +73,12 @@ def render("show.json", %{user: user}) do "avatar" => avatar, "nickname" => user.nickname, "display_name" => display_name, - "deactivated" => user.deactivated, + "is_active" => user.is_active, "local" => user.local, "roles" => User.roles(user), "tags" => user.tags || [], - "confirmation_pending" => user.confirmation_pending, - "approval_pending" => user.approval_pending, + "is_confirmed" => user.is_confirmed, + "is_approved" => user.is_approved, "url" => user.uri || user.ap_id, "registration_reason" => user.registration_reason, "actor_type" => user.actor_type diff --git a/lib/pleroma/web/api_spec/operations/admin/report_operation.ex b/lib/pleroma/web/api_spec/operations/admin/report_operation.ex index 526698fc1..e7acfa271 100644 --- a/lib/pleroma/web/api_spec/operations/admin/report_operation.ex +++ b/lib/pleroma/web/api_spec/operations/admin/report_operation.ex @@ -182,7 +182,7 @@ defp account_admin do properties: Map.merge(Account.schema().properties, %{ nickname: %Schema{type: :string}, - deactivated: %Schema{type: :boolean}, + is_active: %Schema{type: :boolean}, local: %Schema{type: :boolean}, roles: %Schema{ type: :object, @@ -191,7 +191,7 @@ defp account_admin do moderator: %Schema{type: :boolean} } }, - confirmation_pending: %Schema{type: :boolean} + is_confirmed: %Schema{type: :boolean} }) } end diff --git a/lib/pleroma/web/api_spec/operations/admin/status_operation.ex b/lib/pleroma/web/api_spec/operations/admin/status_operation.ex index a2319bacc..34a0bce07 100644 --- a/lib/pleroma/web/api_spec/operations/admin/status_operation.ex +++ b/lib/pleroma/web/api_spec/operations/admin/status_operation.ex @@ -132,7 +132,7 @@ def admin_account do avatar: %Schema{type: :string}, nickname: %Schema{type: :string}, display_name: %Schema{type: :string}, - deactivated: %Schema{type: :boolean}, + is_active: %Schema{type: :boolean}, local: %Schema{type: :boolean}, roles: %Schema{ type: :object, @@ -142,7 +142,7 @@ def admin_account do } }, tags: %Schema{type: :string}, - confirmation_pending: %Schema{type: :string} + is_confirmed: %Schema{type: :string} } } end diff --git a/lib/pleroma/web/api_spec/operations/chat_operation.ex b/lib/pleroma/web/api_spec/operations/chat_operation.ex index a90bc4cc9..e5ee6e695 100644 --- a/lib/pleroma/web/api_spec/operations/chat_operation.ex +++ b/lib/pleroma/web/api_spec/operations/chat_operation.ex @@ -236,7 +236,7 @@ def chats_response do "account" => %{ "pleroma" => %{ "is_admin" => false, - "confirmation_pending" => false, + "is_confirmed" => true, "hide_followers_count" => false, "is_moderator" => false, "hide_favorites" => true, diff --git a/lib/pleroma/web/api_spec/operations/status_operation.ex b/lib/pleroma/web/api_spec/operations/status_operation.ex index 765fbd67b..fd29f5139 100644 --- a/lib/pleroma/web/api_spec/operations/status_operation.ex +++ b/lib/pleroma/web/api_spec/operations/status_operation.ex @@ -117,7 +117,7 @@ def reblog_operation do request_body("Parameters", %Schema{ type: :object, properties: %{ - visibility: %Schema{allOf: [VisibilityScope], default: "public"} + visibility: %Schema{allOf: [VisibilityScope]} } }), responses: %{ diff --git a/lib/pleroma/web/api_spec/schemas/account.ex b/lib/pleroma/web/api_spec/schemas/account.ex index 35158c140..4f9b564d1 100644 --- a/lib/pleroma/web/api_spec/schemas/account.ex +++ b/lib/pleroma/web/api_spec/schemas/account.ex @@ -48,7 +48,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do }, background_image: %Schema{type: :string, nullable: true, format: :uri}, chat_token: %Schema{type: :string}, - confirmation_pending: %Schema{ + is_confirmed: %Schema{ type: :boolean, description: "whether the user account is waiting on email confirmation to be activated" @@ -166,7 +166,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do "pleroma" => %{ "allow_following_move" => true, "background_image" => nil, - "confirmation_pending" => true, + "is_confirmed" => false, "hide_favorites" => true, "hide_followers" => false, "hide_followers_count" => false, diff --git a/lib/pleroma/web/api_spec/schemas/chat.ex b/lib/pleroma/web/api_spec/schemas/chat.ex index b3912c173..4afed910d 100644 --- a/lib/pleroma/web/api_spec/schemas/chat.ex +++ b/lib/pleroma/web/api_spec/schemas/chat.ex @@ -23,7 +23,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Chat do "account" => %{ "pleroma" => %{ "is_admin" => false, - "confirmation_pending" => false, + "is_confirmed" => true, "hide_followers_count" => false, "is_moderator" => false, "hide_favorites" => true, diff --git a/lib/pleroma/web/api_spec/schemas/status.ex b/lib/pleroma/web/api_spec/schemas/status.ex index 3f5870907..61ebd8089 100644 --- a/lib/pleroma/web/api_spec/schemas/status.ex +++ b/lib/pleroma/web/api_spec/schemas/status.ex @@ -256,7 +256,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do "note" => "Tester Number 6", "pleroma" => %{ "background_image" => nil, - "confirmation_pending" => false, + "is_confirmed" => true, "hide_favorites" => true, "hide_followers" => false, "hide_followers_count" => false, diff --git a/lib/pleroma/web/auth/pleroma_authenticator.ex b/lib/pleroma/web/auth/pleroma_authenticator.ex index a2121e6a7..401f23c9f 100644 --- a/lib/pleroma/web/auth/pleroma_authenticator.ex +++ b/lib/pleroma/web/auth/pleroma_authenticator.ex @@ -84,7 +84,7 @@ def create_from_registration( password_confirmation: random_password }, external: true, - need_confirmation: false + confirmed: true ) |> Repo.insert(), {:ok, _} <- diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 2768f0291..63417142f 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -266,7 +266,7 @@ defp do_render("show.json", %{user: user} = opts) do pleroma: %{ ap_id: user.ap_id, also_known_as: user.also_known_as, - confirmation_pending: user.confirmation_pending, + is_confirmed: user.is_confirmed, tags: user.tags, hide_followers_count: user.hide_followers_count, hide_follows_count: user.hide_follows_count, @@ -376,7 +376,7 @@ defp maybe_put_allow_following_move(data, %User{id: user_id} = user, %User{id: u defp maybe_put_allow_following_move(data, _, _), do: data defp maybe_put_activation_status(data, user, %User{is_admin: true}) do - Kernel.put_in(data, [:pleroma, :deactivated], user.deactivated) + Kernel.put_in(data, [:pleroma, :deactivated], !user.is_active) end defp maybe_put_activation_status(data, _, _), do: data diff --git a/lib/pleroma/web/mastodon_api/views/poll_view.ex b/lib/pleroma/web/mastodon_api/views/poll_view.ex index d6b544037..71bc8b949 100644 --- a/lib/pleroma/web/mastodon_api/views/poll_view.ex +++ b/lib/pleroma/web/mastodon_api/views/poll_view.ex @@ -11,7 +11,7 @@ def render("show.json", %{object: object, multiple: multiple, options: options} {end_time, expired} = end_time_and_expired(object) {options, votes_count} = options_and_votes_count(options) - %{ + poll = %{ # Mastodon uses separate ids for polls, but an object can't have # more than one poll embedded so object id is fine id: to_string(object.id), @@ -21,9 +21,16 @@ def render("show.json", %{object: object, multiple: multiple, options: options} votes_count: votes_count, voters_count: voters_count(object), options: options, - voted: voted?(params), emojis: Pleroma.Web.MastodonAPI.StatusView.build_emojis(object.data["emoji"]) } + + if params[:for] do + # when unauthenticated Mastodon doesn't include `voted` & `own_votes` keys in response + {voted, own_votes} = voted_and_own_votes(params, options) + Map.merge(poll, %{voted: voted, own_votes: own_votes}) + else + poll + end end def render("show.json", %{object: object} = params) do @@ -67,12 +74,29 @@ defp voters_count(%{data: %{"voters" => [_ | _] = voters}}) do defp voters_count(_), do: 0 - defp voted?(%{object: object} = opts) do - if opts[:for] do - existing_votes = Pleroma.Web.ActivityPub.Utils.get_existing_votes(opts[:for].ap_id, object) - existing_votes != [] or opts[:for].ap_id == object.data["actor"] + defp voted_and_own_votes(%{object: object} = params, options) do + if params[:for] do + existing_votes = + Pleroma.Web.ActivityPub.Utils.get_existing_votes(params[:for].ap_id, object) + + voted = existing_votes != [] or params[:for].ap_id == object.data["actor"] + + own_votes = + if voted do + titles = Enum.map(options, & &1[:title]) + + Enum.reduce(existing_votes, [], fn vote, acc -> + data = vote |> Map.get(:object) |> Map.get(:data) + index = Enum.find_index(titles, &(&1 == data["name"])) + [index | acc] + end) + else + [] + end + + {voted, own_votes} else - false + {false, []} end end end diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index cd1a85088..2cd6732fe 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -491,7 +491,7 @@ def render_content(object), do: object.data["content"] || "" def build_tags(object_tags) when is_list(object_tags) do object_tags |> Enum.filter(&is_binary/1) - |> Enum.map(&%{name: &1, url: "/tag/#{URI.encode(&1)}"}) + |> Enum.map(&%{name: &1, url: "#{Pleroma.Web.base_url()}/tag/#{URI.encode(&1)}"}) end def build_tags(_), do: [] diff --git a/lib/pleroma/web/media_proxy/invalidation/script.ex b/lib/pleroma/web/media_proxy/invalidation/script.ex index 0f66c2fe3..87a21166c 100644 --- a/lib/pleroma/web/media_proxy/invalidation/script.ex +++ b/lib/pleroma/web/media_proxy/invalidation/script.ex @@ -13,6 +13,7 @@ defmodule Pleroma.Web.MediaProxy.Invalidation.Script do def purge(urls, opts \\ []) do args = urls + |> maybe_format_urls(Keyword.get(opts, :url_format)) |> List.wrap() |> Enum.uniq() |> Enum.join(" ") @@ -40,4 +41,22 @@ defp handle_result(error, _) do Logger.error("Error while cache purge: #{inspect(error)}") {:error, inspect(error)} end + + def maybe_format_urls(urls, :htcacheclean) do + urls + |> Enum.map(fn url -> + uri = URI.parse(url) + + query = + if !is_nil(uri.query) do + "?" <> uri.query + else + "?" + end + + uri.scheme <> "://" <> uri.host <> ":#{inspect(uri.port)}" <> uri.path <> query + end) + end + + def maybe_format_urls(urls, _), do: urls end diff --git a/lib/pleroma/web/mongoose_im/mongoose_im_controller.ex b/lib/pleroma/web/mongoose_im/mongoose_im_controller.ex index e7903dde8..6ace3e0b5 100644 --- a/lib/pleroma/web/mongoose_im/mongoose_im_controller.ex +++ b/lib/pleroma/web/mongoose_im/mongoose_im_controller.ex @@ -14,7 +14,7 @@ defmodule Pleroma.Web.MongooseIM.MongooseIMController do plug(RateLimiter, [name: :authentication, params: ["user"]] when action == :check_password) def user_exists(conn, %{"user" => username}) do - with %User{} <- Repo.get_by(User, nickname: username, local: true, deactivated: false) do + with %User{} <- Repo.get_by(User, nickname: username, local: true, is_active: true) do conn |> json(true) else @@ -26,7 +26,7 @@ def user_exists(conn, %{"user" => username}) do end def check_password(conn, %{"user" => username, "pass" => password}) do - with %User{password_hash: password_hash, deactivated: false} <- + with %User{password_hash: password_hash, is_active: true} <- Repo.get_by(User, nickname: username, local: true), true <- AuthenticationPlug.checkpw(password, password_hash) do conn diff --git a/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex b/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex index 809ef9b40..c94527e6d 100644 --- a/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex +++ b/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex @@ -26,7 +26,7 @@ defp fetch_users(user_ap_ids) do user_ap_ids |> Enum.map(&Pleroma.User.get_cached_by_ap_id/1) |> Enum.filter(fn - %{deactivated: false} -> true + %{is_active: true} -> true _ -> false end) end diff --git a/lib/pleroma/web/twitter_api/controller.ex b/lib/pleroma/web/twitter_api/controller.ex index 467c19e5e..077bfa70d 100644 --- a/lib/pleroma/web/twitter_api/controller.ex +++ b/lib/pleroma/web/twitter_api/controller.ex @@ -30,7 +30,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do def confirm_email(conn, %{"user_id" => uid, "token" => token}) do with %User{} = user <- User.get_cached_by_id(uid), - true <- user.local and user.confirmation_pending and user.confirmation_token == token, + true <- user.local and !user.is_confirmed and user.confirmation_token == token, {:ok, _} <- User.confirm(user) do redirect(conn, to: "/") end diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index 1e252f7bb..940a645bb 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -150,7 +150,7 @@ def delete_account(%{assigns: %{user: user}} = conn, params) do def disable_account(%{assigns: %{user: user}} = conn, params) do case CommonAPI.Utils.confirm_current_password(user, params["password"]) do {:ok, user} -> - User.deactivate_async(user) + User.set_activation_async(user, false) json(conn, %{status: "success"}) {:error, msg} -> diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index f6d721da6..76ca82d20 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -59,7 +59,7 @@ defp create_user(params, opts) do def password_reset(nickname_or_email) do with true <- is_binary(nickname_or_email), - %User{local: true, email: email, deactivated: false} = user when is_binary(email) <- + %User{local: true, email: email, is_active: true} = user when is_binary(email) <- User.get_by_nickname_or_email(nickname_or_email), {:ok, token_record} <- Pleroma.PasswordResetToken.create_token(user) do user diff --git a/lib/pleroma/workers/background_worker.ex b/lib/pleroma/workers/background_worker.ex index e24b9c175..1e28384cb 100644 --- a/lib/pleroma/workers/background_worker.ex +++ b/lib/pleroma/workers/background_worker.ex @@ -9,9 +9,9 @@ defmodule Pleroma.Workers.BackgroundWorker do @impl Oban.Worker - def perform(%Job{args: %{"op" => "deactivate_user", "user_id" => user_id, "status" => status}}) do + def perform(%Job{args: %{"op" => "user_activation", "user_id" => user_id, "status" => status}}) do user = User.get_cached_by_id(user_id) - User.perform(:deactivate_async, user, status) + User.perform(:set_activation_async, user, status) end def perform(%Job{args: %{"op" => "delete_user", "user_id" => user_id}}) do diff --git a/mix.exs b/mix.exs index 14448f12f..489bb5729 100644 --- a/mix.exs +++ b/mix.exs @@ -123,7 +123,7 @@ defp deps do {:ecto_enum, "~> 1.4"}, {:ecto_sql, "~> 3.4.4"}, {:postgrex, ">= 0.15.5"}, - {:oban, "~> 2.1.0"}, + {:oban, "~> 2.3.4"}, {:gettext, "~> 0.18"}, {:bcrypt_elixir, "~> 2.2"}, {:trailing_format_plug, "~> 0.0.7"}, @@ -229,7 +229,9 @@ defp aliases do "ecto.reset": ["ecto.drop", "ecto.setup"], test: ["ecto.create --quiet", "ecto.migrate", "test"], docs: ["pleroma.docs", "docs"], - analyze: ["credo --strict --only=warnings,todo,fixme,consistency,readability"] + analyze: ["credo --strict --only=warnings,todo,fixme,consistency,readability"], + copyright: &add_copyright/1, + "copyright.bump": &bump_copyright/1 ] end @@ -332,4 +334,30 @@ defp version(version) do |> Enum.filter(fn string -> string && string != "" end) |> Enum.join() end + + defp add_copyright(_) do + year = NaiveDateTime.utc_now().year + template = ~s[\ +# Pleroma: A lightweight social networking server +# Copyright © 2017-#{year} Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +] |> String.replace("\n", "\\n") + + find = "find lib test priv -type f \\( -name '*.ex' -or -name '*.exs' \\) -exec " + grep = "grep -L '# Copyright © [0-9\-]* Pleroma' {} \\;" + xargs = "xargs -n1 sed -i'' '1s;^;#{template};'" + + :os.cmd(String.to_charlist("#{find}#{grep} | #{xargs}")) + end + + defp bump_copyright(_) do + year = NaiveDateTime.utc_now().year + find = "find lib test priv -type f \\( -name '*.ex' -or -name '*.exs' \\)" + + xargs = + "xargs sed -i'' 's;# Copyright © [0-9\-]* Pleroma.*$;# Copyright © 2017-#{year} Pleroma Authors ;'" + + :os.cmd(String.to_charlist("#{find} | #{xargs}")) + end end diff --git a/mix.lock b/mix.lock index 01caf319e..840a82555 100644 --- a/mix.lock +++ b/mix.lock @@ -15,7 +15,7 @@ "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, "comeonin": {:hex, :comeonin, "5.3.1", "7fe612b739c78c9c1a75186ef2d322ce4d25032d119823269d0aa1e2f1e20025", [:mix], [], "hexpm", "d6222483060c17f0977fad1b7401ef0c5863c985a64352755f366aee3799c245"}, "concurrent_limiter": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/concurrent_limiter.git", "d81be41024569330f296fc472e24198d7499ba78", [ref: "d81be41024569330f296fc472e24198d7499ba78"]}, - "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm", "4a0850c9be22a43af9920a71ab17c051f5f7d45c209e40269a1938832510e4d9"}, + "connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, "cors_plug": {:hex, :cors_plug, "2.0.2", "2b46083af45e4bc79632bd951550509395935d3e7973275b2b743bd63cc942ce", [:mix], [{:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "f0d0e13f71c51fd4ef8b2c7e051388e4dfb267522a83a22392c856de7e46465f"}, "cowboy": {:hex, :cowboy, "2.8.0", "f3dc62e35797ecd9ac1b50db74611193c29815401e53bac9a5c0577bd7bc667d", [:rebar3], [{:cowlib, "~> 2.9.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "4643e4fba74ac96d4d152c75803de6fad0b3fa5df354c71afdd6cbeeb15fac8a"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.0", "69fdb5cf92df6373e15675eb4018cf629f5d8e35e74841bb637d6596cb797bbc", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "42868c229d9a2900a1501c5d0355bfd46e24c862c322b0b4f5a6f14fe0216753"}, @@ -24,7 +24,7 @@ "crontab": {:hex, :crontab, "1.1.8", "2ce0e74777dfcadb28a1debbea707e58b879e6aa0ffbf9c9bb540887bce43617", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"}, "crypt": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/crypt.git", "cf2aa3f11632e8b0634810a15b3e612c7526f6a3", [ref: "cf2aa3f11632e8b0634810a15b3e612c7526f6a3"]}, "custom_base": {:hex, :custom_base, "0.2.1", "4a832a42ea0552299d81652aa0b1f775d462175293e99dfbe4d7dbaab785a706", [:mix], [], "hexpm", "8df019facc5ec9603e94f7270f1ac73ddf339f56ade76a721eaa57c1493ba463"}, - "db_connection": {:hex, :db_connection, "2.2.2", "3bbca41b199e1598245b716248964926303b5d4609ff065125ce98bcd368939e", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "642af240d8a8affb93b4ba5a6fcd2bbcbdc327e1a524b825d383711536f8070c"}, + "db_connection": {:hex, :db_connection, "2.3.1", "4c9f3ed1ef37471cbdd2762d6655be11e38193904d9c5c1c9389f1b891a3088e", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "abaab61780dde30301d840417890bd9f74131041afd02174cf4e10635b3a63f5"}, "decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, "earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm", "8cf8a291ebf1c7b9539e3cddb19e9cef066c2441b1640f13c34c1d3cfc825fec"}, @@ -81,7 +81,7 @@ "nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"}, "nimble_pool": {:hex, :nimble_pool, "0.1.0", "ffa9d5be27eee2b00b0c634eb649aa27f97b39186fec3c493716c2a33e784ec6", [:mix], [], "hexpm", "343a1eaa620ddcf3430a83f39f2af499fe2370390d4f785cd475b4df5acaf3f9"}, "nodex": {:git, "https://git.pleroma.social/pleroma/nodex", "cb6730f943cfc6aad674c92161be23a8411f15d1", [ref: "cb6730f943cfc6aad674c92161be23a8411f15d1"]}, - "oban": {:hex, :oban, "2.1.0", "034144686f7e76a102b5d67731f098d98a9e4a52b07c25ad580a01f83a7f1cf5", [:mix], [{:ecto_sql, ">= 3.4.3", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.14", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c6f067fa3b308ed9e0e6beb2b34277c9c4e48bf95338edabd8f4a757a26e04c2"}, + "oban": {:hex, :oban, "2.3.4", "ec7509b9af2524d55f529cb7aee93d36131ae0bf0f37706f65d2fe707f4d9fd8", [:mix], [{:ecto_sql, ">= 3.4.3", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.14", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c70ca0434758fd1805422ea4446af5e910ddc697c0c861549c8f0eb0cfbd2fdf"}, "open_api_spex": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/open_api_spex.git", "f296ac0924ba3cf79c7a588c4c252889df4c2edd", [ref: "f296ac0924ba3cf79c7a588c4c252889df4c2edd"]}, "p1_utils": {:hex, :p1_utils, "1.0.18", "3fe224de5b2e190d730a3c5da9d6e8540c96484cf4b4692921d1e28f0c32b01c", [:rebar3], [], "hexpm", "1fc8773a71a15553b179c986b22fbeead19b28fe486c332d4929700ffeb71f88"}, "parse_trans": {:git, "https://github.com/uwiger/parse_trans.git", "76abb347c3c1d00fb0ccf9e4b43e22b3d2288484", [tag: "3.3.0"]}, @@ -97,7 +97,7 @@ "plug_static_index_html": {:hex, :plug_static_index_html, "1.0.0", "840123d4d3975585133485ea86af73cb2600afd7f2a976f9f5fd8b3808e636a0", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "79fd4fcf34d110605c26560cbae8f23c603ec4158c08298bd4360fdea90bb5cf"}, "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm", "fec8660eb7733ee4117b85f55799fd3833eb769a6df71ccf8903e8dc5447cfce"}, "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"}, - "postgrex": {:hex, :postgrex, "0.15.6", "a464c72010a56e3214fe2b99c1a76faab4c2bb0255cabdef30dea763a3569aa2", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "f99268325ac8f66ffd6c4964faab9e70fbf721234ab2ad238c00f9530b8cdd55"}, + "postgrex": {:hex, :postgrex, "0.15.7", "724410acd48abac529d0faa6c2a379fb8ae2088e31247687b16cacc0e0883372", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "88310c010ff047cecd73d5ceca1d99205e4b1ab1b9abfdab7e00f5c9d20ef8f9"}, "pot": {:hex, :pot, "0.11.0", "61bad869a94534739dd4614a25a619bc5c47b9970e9a0ea5bef4628036fc7a16", [:rebar3], [], "hexpm", "57ee6ee6bdeb639661ffafb9acefe3c8f966e45394de6a766813bb9e1be4e54b"}, "prometheus": {:hex, :prometheus, "4.6.0", "20510f381db1ccab818b4cf2fac5fa6ab5cc91bc364a154399901c001465f46f", [:mix, :rebar3], [], "hexpm", "4905fd2992f8038eccd7aa0cd22f40637ed618c0bed1f75c05aacec15b7545de"}, "prometheus_ecto": {:hex, :prometheus_ecto, "1.4.3", "3dd4da1812b8e0dbee81ea58bb3b62ed7588f2eae0c9e97e434c46807ff82311", [:mix], [{:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm", "8d66289f77f913b37eda81fd287340c17e61a447549deb28efc254532b2bed82"}, diff --git a/priv/gettext/pt_PT/LC_MESSAGES/errors.po b/priv/gettext/pt_PT/LC_MESSAGES/errors.po new file mode 100644 index 000000000..16d8c971a --- /dev/null +++ b/priv/gettext/pt_PT/LC_MESSAGES/errors.po @@ -0,0 +1,594 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-18 17:19+0000\n" +"PO-Revision-Date: 2021-01-18 17:54+0000\n" +"Last-Translator: João Rodrigues \n" +"Language-Team: Portuguese (Portugal) \n" +"Language: pt_PT\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.0.4\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 "não pode estar em branco" + +## From Ecto.Changeset.unique_constraint/3 +msgid "has already been taken" +msgstr "já se encontra em utilização" + +## From Ecto.Changeset.put_change/3 +msgid "is invalid" +msgstr "é inválido" + +## From Ecto.Changeset.validate_format/3 +msgid "has invalid format" +msgstr "tem um formato inválido" + +## From Ecto.Changeset.validate_subset/3 +msgid "has an invalid entry" +msgstr "tem uma entrada inválida" + +## From Ecto.Changeset.validate_exclusion/3 +msgid "is reserved" +msgstr "é reservado" + +## From Ecto.Changeset.validate_confirmation/3 +msgid "does not match confirmation" +msgstr "não corresponde à confirmação" + +## From Ecto.Changeset.no_assoc_constraint/3 +msgid "is still associated with this entry" +msgstr "ainda se encontra associado a esta entrada" + +msgid "are still associated with this entry" +msgstr "ainda está associado a esta entrada" + +## From Ecto.Changeset.validate_length/3 +msgid "should be %{count} character(s)" +msgid_plural "should be %{count} character(s)" +msgstr[0] "deve conter %{count} caracter" +msgstr[1] "deve conter %{count} caracteres" + +msgid "should have %{count} item(s)" +msgid_plural "should have %{count} item(s)" +msgstr[0] "deve ter %{count} item" +msgstr[1] "deve ter %{count} items" + +msgid "should be at least %{count} character(s)" +msgid_plural "should be at least %{count} character(s)" +msgstr[0] "deve ter pelo menos %{count} caracter" +msgstr[1] "deve ter pelo menos %{count} caracteres" + +msgid "should have at least %{count} item(s)" +msgid_plural "should have at least %{count} item(s)" +msgstr[0] "deve ter pelo menos %{count} item" +msgstr[1] "deve ter pelo menos %{count} items" + +msgid "should be at most %{count} character(s)" +msgid_plural "should be at most %{count} character(s)" +msgstr[0] "deve ter pelo menos %{count} caracter" +msgstr[1] "deve ter pelo menos %{count} caracteres" + +msgid "should have at most %{count} item(s)" +msgid_plural "should have at most %{count} item(s)" +msgstr[0] "deve ter pelo menos %{count} item" +msgstr[1] "deve ter pelo menos %{count} items" + +## From Ecto.Changeset.validate_number/3 +msgid "must be less than %{number}" +msgstr "deve ser menor que %{number}" + +msgid "must be greater than %{number}" +msgstr "deve ser maior que %{number}" + +msgid "must be less than or equal to %{number}" +msgstr "deve ser menor ou igual que %{number}" + +msgid "must be greater than or equal to %{number}" +msgstr "deve ser maior ou igual que %{number}" + +msgid "must be equal to %{number}" +msgstr "deve ser igual a %{number}" + +#: lib/pleroma/web/common_api/common_api.ex:505 +#, elixir-format +msgid "Account not found" +msgstr "Conta não encontrada" + +#: lib/pleroma/web/common_api/common_api.ex:339 +#, elixir-format +msgid "Already voted" +msgstr "Já votou" + +#: lib/pleroma/web/oauth/oauth_controller.ex:359 +#, elixir-format +msgid "Bad request" +msgstr "Pedido inválido" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:426 +#, elixir-format +msgid "Can't delete object" +msgstr "Não é possível apagar o objeto" + +#: lib/pleroma/web/controller_helper.ex:105 +#: lib/pleroma/web/controller_helper.ex:111 +#, elixir-format +msgid "Can't display this activity" +msgstr "Não é possível exibir esta atividade" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:285 +#, elixir-format +msgid "Can't find user" +msgstr "Não foi possível encontrar o utilizador" + +#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:61 +#, elixir-format +msgid "Can't get favorites" +msgstr "Não foi possível obter os favoritos" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:438 +#, elixir-format +msgid "Can't like object" +msgstr "Não foi possível gostar do objeto" + +#: lib/pleroma/web/common_api/utils.ex:563 +#, elixir-format +msgid "Cannot post an empty status without attachments" +msgstr "Não é possível publicar um estado vazio e sem ficheiro anexados" + +#: lib/pleroma/web/common_api/utils.ex:511 +#, elixir-format +msgid "Comment must be up to %{max_size} characters" +msgstr "Comentários devem ter até %{max_size} caracteres" + +#: lib/pleroma/config/config_db.ex:191 +#, elixir-format +msgid "Config with params %{params} not found" +msgstr "Configuração com parâmetros %{params} não encontrada" + +#: 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 "Não foi possível apagar" + +#: lib/pleroma/web/common_api/common_api.ex:231 +#, elixir-format +msgid "Could not favorite" +msgstr "Não foi possível favoritar" + +#: lib/pleroma/web/common_api/common_api.ex:453 +#, elixir-format +msgid "Could not pin" +msgstr "Não foi possível fixar" + +#: lib/pleroma/web/common_api/common_api.ex:278 +#, elixir-format +msgid "Could not unfavorite" +msgstr "Não foi possível retirar favorito" + +#: lib/pleroma/web/common_api/common_api.ex:463 +#, elixir-format +msgid "Could not unpin" +msgstr "Não foi possível desafixar" + +#: lib/pleroma/web/common_api/common_api.ex:216 +#, elixir-format +msgid "Could not unrepeat" +msgstr "Não foi possível deixar de repetir" + +#: 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 "Não foi possível atualizar estado" + +#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:207 +#, elixir-format +msgid "Error." +msgstr "Erro." + +#: lib/pleroma/web/twitter_api/twitter_api.ex:106 +#, elixir-format +msgid "Invalid CAPTCHA" +msgstr "CAPTCHA Inválido" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:116 +#: lib/pleroma/web/oauth/oauth_controller.ex:568 +#, elixir-format +msgid "Invalid credentials" +msgstr "Credenciais inválidas" + +#: lib/pleroma/plugs/ensure_authenticated_plug.ex:38 +#, elixir-format +msgid "Invalid credentials." +msgstr "Credenciais inválidas." + +#: lib/pleroma/web/common_api/common_api.ex:355 +#, elixir-format +msgid "Invalid indices" +msgstr "Índices inválidos" + +#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:29 +#, elixir-format +msgid "Invalid parameters" +msgstr "Parâmetros inválidos" + +#: lib/pleroma/web/common_api/utils.ex:414 +#, elixir-format +msgid "Invalid password." +msgstr "Palavra-passe inválida." + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:220 +#, elixir-format +msgid "Invalid request" +msgstr "Pedido inválido" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:109 +#, elixir-format +msgid "Kocaptcha service unavailable" +msgstr "Serviço Kocaptcha indisponível" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:112 +#, elixir-format +msgid "Missing parameters" +msgstr "Parâmetros em falta" + +#: lib/pleroma/web/common_api/utils.ex:547 +#, elixir-format +msgid "No such conversation" +msgstr "Não existe tal conversação" + +#: 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 "Não existe permission_group" + +#: 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 "Não encontrado" + +#: lib/pleroma/web/common_api/common_api.ex:331 +#, elixir-format +msgid "Poll's author can't vote" +msgstr "O autor da sondagem não pode votar" + +#: 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 "Registo não encontrado" + +#: 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 "Algo ocorreu de errado" + +#: lib/pleroma/web/common_api/activity_draft.ex:107 +#, elixir-format +msgid "The message visibility must be direct" +msgstr "A visibilidade da mensagem deve ser direta" + +#: lib/pleroma/web/common_api/utils.ex:573 +#, elixir-format +msgid "The status is over the character limit" +msgstr "O estado está acima do limite de caracteres" + +#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31 +#, elixir-format +msgid "This resource requires authentication." +msgstr "Este recurso requer autenticação." + +#: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206 +#, elixir-format +msgid "Throttled" +msgstr "Limitado" + +#: lib/pleroma/web/common_api/common_api.ex:356 +#, elixir-format +msgid "Too many choices" +msgstr "Demasiadas opções" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:443 +#, elixir-format +msgid "Unhandled activity type" +msgstr "Tipo de atividade não controlada" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:485 +#, elixir-format +msgid "You can't revoke your own admin status." +msgstr "Não podes revogar o teu próprio estatuto de admin." + +#: 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 "A tua conta está atualmente desativada" + +#: 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 "" +"O teu início de sessão necessita que tenhas o endereço de e-mail confirmado" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:390 +#, elixir-format +msgid "can't read inbox of %{nickname} as %{as_nickname}" +msgstr "" +"não foi possível ler a caixa de entrada de %{nickname} como %{as_nickname}" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:473 +#, elixir-format +msgid "can't update outbox of %{nickname} as %{as_nickname}" +msgstr "" +"não foi possível atualizar caixa de saída de %{nickname} como %{as_nickname}" + +#: lib/pleroma/web/common_api/common_api.ex:471 +#, elixir-format +msgid "conversation is already muted" +msgstr "conversação já silenciada" + +#: 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 "erro" + +#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:32 +#, elixir-format +msgid "mascots can only be images" +msgstr "mascotes apenas podem ser imagens" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:62 +#, elixir-format +msgid "not found" +msgstr "não encontrado" + +#: lib/pleroma/web/oauth/oauth_controller.ex:394 +#, elixir-format +msgid "Bad OAuth request." +msgstr "Pedido OAuth inválido." + +#: lib/pleroma/web/twitter_api/twitter_api.ex:115 +#, elixir-format +msgid "CAPTCHA already used" +msgstr "CPATCHA já utilizado" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:112 +#, elixir-format +msgid "CAPTCHA expired" +msgstr "CAPTCHA expirado" + +#: lib/pleroma/plugs/uploaded_media.ex:57 +#, elixir-format +msgid "Failed" +msgstr "Falhou" + +#: lib/pleroma/web/oauth/oauth_controller.ex:410 +#, elixir-format +msgid "Failed to authenticate: %{message}." +msgstr "Falha ao autenticar: %{message}." + +#: lib/pleroma/web/oauth/oauth_controller.ex:441 +#, elixir-format +msgid "Failed to set up user account." +msgstr "Falha ao configurar conta de utilizador." + +#: lib/pleroma/plugs/oauth_scopes_plug.ex:38 +#, elixir-format +msgid "Insufficient permissions: %{permissions}." +msgstr "Permissões insuficientes: %{permissions}." + +#: lib/pleroma/plugs/uploaded_media.ex:104 +#, elixir-format +msgid "Internal Error" +msgstr "Erro Interno" + +#: lib/pleroma/web/oauth/fallback_controller.ex:22 +#: lib/pleroma/web/oauth/fallback_controller.ex:29 +#, elixir-format +msgid "Invalid Username/Password" +msgstr "Nome de Utilizador/Palavra-passe inválidos" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:118 +#, elixir-format +msgid "Invalid answer data" +msgstr "Informação de resposta inválida" + +#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:33 +#, elixir-format +msgid "Nodeinfo schema version not handled" +msgstr "Versão do schema de nodeinfo não tratado" + +#: lib/pleroma/web/oauth/oauth_controller.ex:172 +#, elixir-format +msgid "This action is outside the authorized scopes" +msgstr "Esta ação está fora dos escopos autorizados" + +#: lib/pleroma/web/oauth/fallback_controller.ex:14 +#, elixir-format +msgid "Unknown error, please check the details and try again." +msgstr "Erro desconhecido, verifica os detalhes e tenta novamente." + +#: lib/pleroma/web/oauth/oauth_controller.ex:119 +#: lib/pleroma/web/oauth/oauth_controller.ex:158 +#, elixir-format +msgid "Unlisted redirect_uri." +msgstr "redirect_uri não listado." + +#: lib/pleroma/web/oauth/oauth_controller.ex:390 +#, elixir-format +msgid "Unsupported OAuth provider: %{provider}." +msgstr "Portal OAuth não suportado: %{provider}." + +#: lib/pleroma/uploaders/uploader.ex:72 +#, elixir-format +msgid "Uploader callback timeout" +msgstr "Tempo expirado para callback de quem envia" + +#: lib/pleroma/web/uploader_controller.ex:23 +#, elixir-format +msgid "bad request" +msgstr "pedido inválido" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:103 +#, elixir-format +msgid "CAPTCHA Error" +msgstr "Erro de CAPTCHA" + +#: lib/pleroma/web/common_api/common_api.ex:290 +#, elixir-format +msgid "Could not add reaction emoji" +msgstr "Não foi possível adicionar reação" + +#: lib/pleroma/web/common_api/common_api.ex:301 +#, elixir-format +msgid "Could not remove reaction emoji" +msgstr "Não foi possível remover reação" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:129 +#, elixir-format +msgid "Invalid CAPTCHA (Missing parameter: %{name})" +msgstr "CAPTCHA inválido (Falta o parâmetro: %{name})" + +#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92 +#, elixir-format +msgid "List not found" +msgstr "Lista não encontrada" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:123 +#, elixir-format +msgid "Missing parameter: %{name}" +msgstr "Parâmetro em falta: %{name}" + +#: lib/pleroma/web/oauth/oauth_controller.ex:210 +#: lib/pleroma/web/oauth/oauth_controller.ex:321 +#, elixir-format +msgid "Password reset is required" +msgstr "É necessário repor palavra-passe" + +#: 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 "" +"Violação de segurança: a verificação de escopo OAuth não foi nem tratada nem " +"explicitamente ignorada." + +#: lib/pleroma/plugs/ensure_authenticated_plug.ex:28 +#, elixir-format +msgid "Two-factor authentication enabled, you must use a access token." +msgstr "" +"Autenticação de dois fatores ativada, deves utilizar uma token de acesso." + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:210 +#, elixir-format +msgid "Unexpected error occurred while adding file to pack." +msgstr "Ocorreu um erro inesperado ao adicionar ficheiro ao pack." + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:138 +#, elixir-format +msgid "Unexpected error occurred while creating pack." +msgstr "Ocorreu um erro inesperado ao criar o pack." + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:278 +#, elixir-format +msgid "Unexpected error occurred while removing file from pack." +msgstr "Ocorreu um erro inesperado ao remover ficheiro do pack." + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:250 +#, elixir-format +msgid "Unexpected error occurred while updating file in pack." +msgstr "Ocorreu um erro inesperado a atualizar ficheiro no pack." + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:179 +#, elixir-format +msgid "Unexpected error occurred while updating pack metadata." +msgstr "Ocorreu um erro inesperado a atualizar os metadados do pack." + +#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61 +#, elixir-format +msgid "Web push subscription is disabled on this Pleroma instance" +msgstr "" +"Subscrição de notificações push no browser está desativada nesta instância " +"do Pleroma" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:451 +#, elixir-format +msgid "You can't revoke your own admin/moderator status." +msgstr "Não podes revogar o teu próprio estatuto de admin/moderador." + +#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:126 +#, elixir-format +msgid "authorization required for timeline view" +msgstr "autorização necessária para visualizar cronologia" + +#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:24 +#, elixir-format +msgid "Access denied" +msgstr "Acesso negado" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:282 +#, elixir-format +msgid "This API requires an authenticated user" +msgstr "Esta API requer um utilizador autenticado" + +#: lib/pleroma/plugs/user_is_admin_plug.ex:21 +#, elixir-format +msgid "User is not an admin." +msgstr "Utilizador não é um admin." diff --git a/priv/repo/migrations/20190730055101_add_oban_jobs_table.exs b/priv/repo/migrations/20190730055101_add_oban_jobs_table.exs index 2f201bd05..5214d59cb 100644 --- a/priv/repo/migrations/20190730055101_add_oban_jobs_table.exs +++ b/priv/repo/migrations/20190730055101_add_oban_jobs_table.exs @@ -1,6 +1,9 @@ defmodule Pleroma.Repo.Migrations.AddObanJobsTable do use Ecto.Migration - defdelegate up, to: Oban.Migrations + def up do + Oban.Migrations.up(version: 2) + end + defdelegate down, to: Oban.Migrations end diff --git a/priv/repo/migrations/20190917100019_update_oban.exs b/priv/repo/migrations/20190917100019_update_oban.exs index 157dc54f9..f673675de 100644 --- a/priv/repo/migrations/20190917100019_update_oban.exs +++ b/priv/repo/migrations/20190917100019_update_oban.exs @@ -6,6 +6,6 @@ def up do end def down do - Oban.Migrations.down(version: 2) + Oban.Migrations.down(version: 3) end end diff --git a/priv/repo/migrations/20200402063221_update_oban_jobs_table.exs b/priv/repo/migrations/20200402063221_update_oban_jobs_table.exs index e7ff04008..ca6856798 100644 --- a/priv/repo/migrations/20200402063221_update_oban_jobs_table.exs +++ b/priv/repo/migrations/20200402063221_update_oban_jobs_table.exs @@ -6,6 +6,6 @@ def up do end def down do - Oban.Migrations.down(version: 7) + Oban.Migrations.down(version: 8) end end diff --git a/priv/repo/migrations/20200825061316_move_activity_expirations_to_oban.exs b/priv/repo/migrations/20200825061316_move_activity_expirations_to_oban.exs index a703af83f..096ab4ce5 100644 --- a/priv/repo/migrations/20200825061316_move_activity_expirations_to_oban.exs +++ b/priv/repo/migrations/20200825061316_move_activity_expirations_to_oban.exs @@ -6,6 +6,8 @@ defmodule Pleroma.Repo.Migrations.MoveActivityExpirationsToOban do def change do Pleroma.Config.Oban.warn() + Application.ensure_all_started(:oban) + Supervisor.start_link([{Oban, Pleroma.Config.get(Oban)}], strategy: :one_for_one, name: Pleroma.Supervisor diff --git a/priv/repo/migrations/20200907092050_move_tokens_expiration_into_oban.exs b/priv/repo/migrations/20200907092050_move_tokens_expiration_into_oban.exs index 9e49ddacb..725c5ab0b 100644 --- a/priv/repo/migrations/20200907092050_move_tokens_expiration_into_oban.exs +++ b/priv/repo/migrations/20200907092050_move_tokens_expiration_into_oban.exs @@ -6,6 +6,8 @@ defmodule Pleroma.Repo.Migrations.MoveTokensExpirationIntoOban do def change do Pleroma.Config.Oban.warn() + Application.ensure_all_started(:oban) + Supervisor.start_link([{Oban, Pleroma.Config.get(Oban)}], strategy: :one_for_one, name: Pleroma.Supervisor diff --git a/priv/repo/migrations/20201012173004_refactor_deactivated_user_field.exs b/priv/repo/migrations/20201012173004_refactor_deactivated_user_field.exs new file mode 100644 index 000000000..58b75b436 --- /dev/null +++ b/priv/repo/migrations/20201012173004_refactor_deactivated_user_field.exs @@ -0,0 +1,22 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Repo.Migrations.RefactorDeactivatedUserField do + use Ecto.Migration + + def up do + # Flip the values before we change the meaning of the column + execute("UPDATE users SET deactivated = NOT deactivated;") + execute("ALTER TABLE users RENAME COLUMN deactivated TO is_active;") + execute("ALTER TABLE users ALTER COLUMN is_active SET DEFAULT true;") + execute("ALTER INDEX users_deactivated_index RENAME TO users_is_active_index;") + end + + def down do + execute("UPDATE users SET is_active = NOT is_active;") + execute("ALTER TABLE users RENAME COLUMN is_active TO deactivated;") + execute("ALTER TABLE users ALTER COLUMN deactivated SET DEFAULT false;") + execute("ALTER INDEX users_is_active_index RENAME TO users_deactivated_index;") + end +end diff --git a/priv/repo/migrations/20201013184200_refactor_confirmation_pending_user_field.exs b/priv/repo/migrations/20201013184200_refactor_confirmation_pending_user_field.exs new file mode 100644 index 000000000..d0dc42827 --- /dev/null +++ b/priv/repo/migrations/20201013184200_refactor_confirmation_pending_user_field.exs @@ -0,0 +1,20 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Repo.Migrations.RefactorConfirmationPendingUserField do + use Ecto.Migration + + def up do + # Flip the values before we change the meaning of the column + execute("UPDATE users SET confirmation_pending = NOT confirmation_pending;") + execute("ALTER TABLE users RENAME COLUMN confirmation_pending TO is_confirmed;") + execute("ALTER TABLE users ALTER COLUMN is_confirmed SET DEFAULT true;") + end + + def down do + execute("UPDATE users SET is_confirmed = NOT is_confirmed;") + execute("ALTER TABLE users RENAME COLUMN is_confirmed TO confirmation_pending;") + execute("ALTER TABLE users ALTER COLUMN confirmation_pending SET DEFAULT false;") + end +end diff --git a/priv/repo/migrations/20201016205220_refactor_approval_pending_user_field.exs b/priv/repo/migrations/20201016205220_refactor_approval_pending_user_field.exs new file mode 100644 index 000000000..944dcf8de --- /dev/null +++ b/priv/repo/migrations/20201016205220_refactor_approval_pending_user_field.exs @@ -0,0 +1,20 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Repo.Migrations.RefactorApprovalPendingUserField do + use Ecto.Migration + + def up do + # Flip the values before we change the meaning of the column + execute("UPDATE users SET approval_pending = NOT approval_pending;") + execute("ALTER TABLE users RENAME COLUMN approval_pending TO is_approved;") + execute("ALTER TABLE users ALTER COLUMN is_approved SET DEFAULT true;") + end + + def down do + execute("UPDATE users SET is_approved = NOT is_approved;") + execute("ALTER TABLE users RENAME COLUMN is_approved TO approval_pending;") + execute("ALTER TABLE users ALTER COLUMN approval_pending SET DEFAULT false;") + end +end diff --git a/priv/repo/migrations/20201231185546_confirm_logged_in_users.exs b/priv/repo/migrations/20201231185546_confirm_logged_in_users.exs index 4372d093f..b9656c17b 100644 --- a/priv/repo/migrations/20201231185546_confirm_logged_in_users.exs +++ b/priv/repo/migrations/20201231185546_confirm_logged_in_users.exs @@ -11,9 +11,9 @@ defmodule Pleroma.Repo.Migrations.ConfirmLoggedInUsers do def up do User - |> where([u], u.confirmation_pending == true) + |> where([u], u.is_confirmed == false) |> join(:inner, [u], t in Token, on: t.user_id == u.id) - |> Repo.update_all(set: [confirmation_pending: false]) + |> Repo.update_all(set: [is_confirmed: true]) end def down do diff --git a/priv/repo/migrations/20210113225652_deprecate_public_endpoint.exs b/priv/repo/migrations/20210113225652_deprecate_public_endpoint.exs new file mode 100644 index 000000000..6f470a459 --- /dev/null +++ b/priv/repo/migrations/20210113225652_deprecate_public_endpoint.exs @@ -0,0 +1,57 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Repo.Migrations.DeprecatePublicEndpoint do + use Ecto.Migration + + def up do + with %Pleroma.ConfigDB{} = s3_config <- + Pleroma.ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Uploaders.S3}), + %Pleroma.ConfigDB{} = upload_config <- + Pleroma.ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Upload}) do + public_endpoint = s3_config.value[:public_endpoint] + + if !is_nil(public_endpoint) do + upload_value = upload_config.value |> Keyword.merge(base_url: public_endpoint) + + upload_config + |> Ecto.Changeset.change(value: upload_value) + |> Pleroma.Repo.update() + + s3_value = s3_config.value |> Keyword.delete(:public_endpoint) + + s3_config + |> Ecto.Changeset.change(value: s3_value) + |> Pleroma.Repo.update() + end + else + _ -> :ok + end + end + + def down do + with %Pleroma.ConfigDB{} = upload_config <- + Pleroma.ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Upload}), + %Pleroma.ConfigDB{} = s3_config <- + Pleroma.ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Uploaders.S3}) do + base_url = upload_config.value[:base_url] + + if !is_nil(base_url) do + s3_value = s3_config.value |> Keyword.merge(public_endpoint: base_url) + + s3_config + |> Ecto.Changeset.change(value: s3_value) + |> Pleroma.Repo.update() + + upload_value = upload_config.value |> Keyword.delete(:base_url) + + upload_config + |> Ecto.Changeset.change(value: upload_value) + |> Pleroma.Repo.update() + end + else + _ -> :ok + end + end +end diff --git a/priv/repo/migrations/20210115205649_upgrade_oban_jobs_to_v9.exs b/priv/repo/migrations/20210115205649_upgrade_oban_jobs_to_v9.exs new file mode 100644 index 000000000..bfb405579 --- /dev/null +++ b/priv/repo/migrations/20210115205649_upgrade_oban_jobs_to_v9.exs @@ -0,0 +1,15 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Repo.Migrations.UpgradeObanJobsToV9 do + use Ecto.Migration + + def up do + Oban.Migrations.up(version: 9) + end + + def down do + Oban.Migrations.down(version: 9) + end +end diff --git a/priv/static/adminfe/chunk-03c5.e6a0e2d0.css b/priv/static/adminfe/chunk-03c5.3368e00c.css similarity index 100% rename from priv/static/adminfe/chunk-03c5.e6a0e2d0.css rename to priv/static/adminfe/chunk-03c5.3368e00c.css diff --git a/priv/static/adminfe/chunk-0492.15b0611f.css b/priv/static/adminfe/chunk-0492.15b0611f.css deleted file mode 100644 index 13537842a..000000000 Binary files a/priv/static/adminfe/chunk-0492.15b0611f.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-0537.cd83e5d6.css b/priv/static/adminfe/chunk-0537.76929cff.css similarity index 100% rename from priv/static/adminfe/chunk-0537.cd83e5d6.css rename to priv/static/adminfe/chunk-0537.76929cff.css diff --git a/priv/static/adminfe/chunk-1e1e.5980e665.css b/priv/static/adminfe/chunk-1e1e.5980e665.css new file mode 100644 index 000000000..1b3a9fcab Binary files /dev/null and b/priv/static/adminfe/chunk-1e1e.5980e665.css differ diff --git a/priv/static/adminfe/chunk-1944.731ba892.css b/priv/static/adminfe/chunk-35b1.949db050.css similarity index 100% rename from priv/static/adminfe/chunk-1944.731ba892.css rename to priv/static/adminfe/chunk-35b1.949db050.css diff --git a/priv/static/adminfe/chunk-4770.20caaae1.css b/priv/static/adminfe/chunk-4770.20caaae1.css new file mode 100644 index 000000000..6f2331666 Binary files /dev/null and b/priv/static/adminfe/chunk-4770.20caaae1.css differ diff --git a/priv/static/adminfe/chunk-04b0.7e25cd78.css b/priv/static/adminfe/chunk-606c.7c5b0a08.css similarity index 100% rename from priv/static/adminfe/chunk-04b0.7e25cd78.css rename to priv/static/adminfe/chunk-606c.7c5b0a08.css diff --git a/priv/static/adminfe/chunk-68ea9.8331e95e.css b/priv/static/adminfe/chunk-68ea9.892994aa.css similarity index 100% rename from priv/static/adminfe/chunk-68ea9.8331e95e.css rename to priv/static/adminfe/chunk-68ea9.892994aa.css diff --git a/priv/static/adminfe/chunk-6e81.559b76f9.css b/priv/static/adminfe/chunk-6e81.687d5046.css similarity index 100% rename from priv/static/adminfe/chunk-6e81.559b76f9.css rename to priv/static/adminfe/chunk-6e81.687d5046.css diff --git a/priv/static/adminfe/chunk-ad1e.1a3c5339.css b/priv/static/adminfe/chunk-7041.c5f6eab7.css similarity index 100% rename from priv/static/adminfe/chunk-ad1e.1a3c5339.css rename to priv/static/adminfe/chunk-7041.c5f6eab7.css diff --git a/priv/static/adminfe/chunk-7968.283bc086.css b/priv/static/adminfe/chunk-7968.283bc086.css deleted file mode 100644 index 5d9863d3a..000000000 Binary files a/priv/static/adminfe/chunk-7968.283bc086.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-7968.613084d0.css b/priv/static/adminfe/chunk-7968.613084d0.css new file mode 100644 index 000000000..5794e0a91 Binary files /dev/null and b/priv/static/adminfe/chunk-7968.613084d0.css differ diff --git a/priv/static/adminfe/chunk-8fbb.dd321643.css b/priv/static/adminfe/chunk-8fbb.dd321643.css deleted file mode 100644 index f50d974bd..000000000 Binary files a/priv/static/adminfe/chunk-8fbb.dd321643.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-bc60.4417dd06.css b/priv/static/adminfe/chunk-bc60.4417dd06.css new file mode 100644 index 000000000..59ca45d6c Binary files /dev/null and b/priv/static/adminfe/chunk-bc60.4417dd06.css differ diff --git a/priv/static/adminfe/chunk-e660.9e75af5b.css b/priv/static/adminfe/chunk-e660.62c077ac.css similarity index 100% rename from priv/static/adminfe/chunk-e660.9e75af5b.css rename to priv/static/adminfe/chunk-e660.62c077ac.css diff --git a/priv/static/adminfe/chunk-f364.4fd16c53.css b/priv/static/adminfe/chunk-f364.4fd16c53.css new file mode 100644 index 000000000..abea7d536 Binary files /dev/null and b/priv/static/adminfe/chunk-f364.4fd16c53.css differ diff --git a/priv/static/adminfe/chunk-f364.6b5f3f0d.css b/priv/static/adminfe/chunk-f364.6b5f3f0d.css deleted file mode 100644 index ec665da84..000000000 Binary files a/priv/static/adminfe/chunk-f364.6b5f3f0d.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-f625.bcd0ea3b.css b/priv/static/adminfe/chunk-f625.bcd0ea3b.css deleted file mode 100644 index ac26ef0f5..000000000 Binary files a/priv/static/adminfe/chunk-f625.bcd0ea3b.css and /dev/null differ diff --git a/priv/static/adminfe/index.html b/priv/static/adminfe/index.html index e6af40e97..09915e8cd 100644 --- a/priv/static/adminfe/index.html +++ b/priv/static/adminfe/index.html @@ -1 +1 @@ -Admin FE
\ No newline at end of file +Admin FE
\ No newline at end of file diff --git a/priv/static/adminfe/static/js/app.1428845f.js b/priv/static/adminfe/static/js/app.1428845f.js new file mode 100644 index 000000000..cc9541168 Binary files /dev/null and b/priv/static/adminfe/static/js/app.1428845f.js differ diff --git a/priv/static/adminfe/static/js/app.1428845f.js.map b/priv/static/adminfe/static/js/app.1428845f.js.map new file mode 100644 index 000000000..3fba88015 Binary files /dev/null and b/priv/static/adminfe/static/js/app.1428845f.js.map differ diff --git a/priv/static/adminfe/static/js/app.c67f9a2f.js b/priv/static/adminfe/static/js/app.c67f9a2f.js deleted file mode 100644 index 65f9d4a29..000000000 Binary files a/priv/static/adminfe/static/js/app.c67f9a2f.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/app.c67f9a2f.js.map b/priv/static/adminfe/static/js/app.c67f9a2f.js.map deleted file mode 100644 index 41b4375aa..000000000 Binary files a/priv/static/adminfe/static/js/app.c67f9a2f.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-03c5.6de0c4c7.js b/priv/static/adminfe/static/js/chunk-03c5.1b0ab243.js similarity index 99% rename from priv/static/adminfe/static/js/chunk-03c5.6de0c4c7.js rename to priv/static/adminfe/static/js/chunk-03c5.1b0ab243.js index a89c65572..94dfce1a8 100644 Binary files a/priv/static/adminfe/static/js/chunk-03c5.6de0c4c7.js and b/priv/static/adminfe/static/js/chunk-03c5.1b0ab243.js differ diff --git a/priv/static/adminfe/static/js/chunk-03c5.6de0c4c7.js.map b/priv/static/adminfe/static/js/chunk-03c5.1b0ab243.js.map similarity index 99% rename from priv/static/adminfe/static/js/chunk-03c5.6de0c4c7.js.map rename to priv/static/adminfe/static/js/chunk-03c5.1b0ab243.js.map index 963ff6dee..acf1ba219 100644 Binary files a/priv/static/adminfe/static/js/chunk-03c5.6de0c4c7.js.map and b/priv/static/adminfe/static/js/chunk-03c5.1b0ab243.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-0492.47abe1dc.js b/priv/static/adminfe/static/js/chunk-0492.47abe1dc.js deleted file mode 100644 index 243ecde70..000000000 Binary files a/priv/static/adminfe/static/js/chunk-0492.47abe1dc.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-0492.47abe1dc.js.map b/priv/static/adminfe/static/js/chunk-0492.47abe1dc.js.map deleted file mode 100644 index f5e0d9ebc..000000000 Binary files a/priv/static/adminfe/static/js/chunk-0492.47abe1dc.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-04b0.90c6d24c.js b/priv/static/adminfe/static/js/chunk-04b0.90c6d24c.js deleted file mode 100644 index 9d0352814..000000000 Binary files a/priv/static/adminfe/static/js/chunk-04b0.90c6d24c.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-04b0.90c6d24c.js.map b/priv/static/adminfe/static/js/chunk-04b0.90c6d24c.js.map deleted file mode 100644 index a9bee3721..000000000 Binary files a/priv/static/adminfe/static/js/chunk-04b0.90c6d24c.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-0537.74db16b0.js b/priv/static/adminfe/static/js/chunk-0537.74db16b0.js deleted file mode 100644 index 35231e562..000000000 Binary files a/priv/static/adminfe/static/js/chunk-0537.74db16b0.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-0537.74db16b0.js.map b/priv/static/adminfe/static/js/chunk-0537.74db16b0.js.map deleted file mode 100644 index fa87bd76d..000000000 Binary files a/priv/static/adminfe/static/js/chunk-0537.74db16b0.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-0537.d0eef370.js b/priv/static/adminfe/static/js/chunk-0537.d0eef370.js new file mode 100644 index 000000000..f1b73a18a Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-0537.d0eef370.js differ diff --git a/priv/static/adminfe/static/js/chunk-0537.d0eef370.js.map b/priv/static/adminfe/static/js/chunk-0537.d0eef370.js.map new file mode 100644 index 000000000..e0a2f4d21 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-0537.d0eef370.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-1944.7bed0c4b.js b/priv/static/adminfe/static/js/chunk-1944.7bed0c4b.js deleted file mode 100644 index 87590c6ce..000000000 Binary files a/priv/static/adminfe/static/js/chunk-1944.7bed0c4b.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-1944.7bed0c4b.js.map b/priv/static/adminfe/static/js/chunk-1944.7bed0c4b.js.map deleted file mode 100644 index 23229293e..000000000 Binary files a/priv/static/adminfe/static/js/chunk-1944.7bed0c4b.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-1e1e.37f6f555.js b/priv/static/adminfe/static/js/chunk-1e1e.37f6f555.js new file mode 100644 index 000000000..65d0aa926 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-1e1e.37f6f555.js differ diff --git a/priv/static/adminfe/static/js/chunk-1e1e.37f6f555.js.map b/priv/static/adminfe/static/js/chunk-1e1e.37f6f555.js.map new file mode 100644 index 000000000..a0b5ca3be Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-1e1e.37f6f555.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-35b1.50c1449b.js b/priv/static/adminfe/static/js/chunk-35b1.50c1449b.js new file mode 100644 index 000000000..75a2bf0c2 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-35b1.50c1449b.js differ diff --git a/priv/static/adminfe/static/js/chunk-35b1.50c1449b.js.map b/priv/static/adminfe/static/js/chunk-35b1.50c1449b.js.map new file mode 100644 index 000000000..b5e2a27b2 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-35b1.50c1449b.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-4770.1c1fff97.js b/priv/static/adminfe/static/js/chunk-4770.1c1fff97.js new file mode 100644 index 000000000..706ede69e Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-4770.1c1fff97.js differ diff --git a/priv/static/adminfe/static/js/chunk-4770.1c1fff97.js.map b/priv/static/adminfe/static/js/chunk-4770.1c1fff97.js.map new file mode 100644 index 000000000..f1303900d Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-4770.1c1fff97.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-606c.8ac52179.js b/priv/static/adminfe/static/js/chunk-606c.8ac52179.js new file mode 100644 index 000000000..7ae3ce7b1 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-606c.8ac52179.js differ diff --git a/priv/static/adminfe/static/js/chunk-606c.8ac52179.js.map b/priv/static/adminfe/static/js/chunk-606c.8ac52179.js.map new file mode 100644 index 000000000..8c41c2755 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-606c.8ac52179.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-68ea9.2b2877d5.js b/priv/static/adminfe/static/js/chunk-68ea9.5a11341a.js similarity index 99% rename from priv/static/adminfe/static/js/chunk-68ea9.2b2877d5.js rename to priv/static/adminfe/static/js/chunk-68ea9.5a11341a.js index 60056454d..b11c19485 100644 Binary files a/priv/static/adminfe/static/js/chunk-68ea9.2b2877d5.js and b/priv/static/adminfe/static/js/chunk-68ea9.5a11341a.js differ diff --git a/priv/static/adminfe/static/js/chunk-68ea9.2b2877d5.js.map b/priv/static/adminfe/static/js/chunk-68ea9.5a11341a.js.map similarity index 99% rename from priv/static/adminfe/static/js/chunk-68ea9.2b2877d5.js.map rename to priv/static/adminfe/static/js/chunk-68ea9.5a11341a.js.map index 9e26519c3..8779a5e95 100644 Binary files a/priv/static/adminfe/static/js/chunk-68ea9.2b2877d5.js.map and b/priv/static/adminfe/static/js/chunk-68ea9.5a11341a.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-6e81.afade883.js b/priv/static/adminfe/static/js/chunk-6e81.6c4f2ce1.js similarity index 97% rename from priv/static/adminfe/static/js/chunk-6e81.afade883.js rename to priv/static/adminfe/static/js/chunk-6e81.6c4f2ce1.js index 3b5dd6c5c..6fd67c44f 100644 Binary files a/priv/static/adminfe/static/js/chunk-6e81.afade883.js and b/priv/static/adminfe/static/js/chunk-6e81.6c4f2ce1.js differ diff --git a/priv/static/adminfe/static/js/chunk-6e81.afade883.js.map b/priv/static/adminfe/static/js/chunk-6e81.6c4f2ce1.js.map similarity index 98% rename from priv/static/adminfe/static/js/chunk-6e81.afade883.js.map rename to priv/static/adminfe/static/js/chunk-6e81.6c4f2ce1.js.map index a0f7fca19..931f7521e 100644 Binary files a/priv/static/adminfe/static/js/chunk-6e81.afade883.js.map and b/priv/static/adminfe/static/js/chunk-6e81.6c4f2ce1.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-ad1e.eba9db26.js b/priv/static/adminfe/static/js/chunk-7041.390b2ec4.js similarity index 64% rename from priv/static/adminfe/static/js/chunk-ad1e.eba9db26.js rename to priv/static/adminfe/static/js/chunk-7041.390b2ec4.js index 82ddd4df2..50eb1a5f5 100644 Binary files a/priv/static/adminfe/static/js/chunk-ad1e.eba9db26.js and b/priv/static/adminfe/static/js/chunk-7041.390b2ec4.js differ diff --git a/priv/static/adminfe/static/js/chunk-7041.390b2ec4.js.map b/priv/static/adminfe/static/js/chunk-7041.390b2ec4.js.map new file mode 100644 index 000000000..401bb0b1f Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-7041.390b2ec4.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-7968.88218960.js b/priv/static/adminfe/static/js/chunk-7968.88218960.js new file mode 100644 index 000000000..44348d9d1 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-7968.88218960.js differ diff --git a/priv/static/adminfe/static/js/chunk-7968.88218960.js.map b/priv/static/adminfe/static/js/chunk-7968.88218960.js.map new file mode 100644 index 000000000..6fa0131fc Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-7968.88218960.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-7968.f51e3292.js b/priv/static/adminfe/static/js/chunk-7968.f51e3292.js deleted file mode 100644 index dc981706f..000000000 Binary files a/priv/static/adminfe/static/js/chunk-7968.f51e3292.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-7968.f51e3292.js.map b/priv/static/adminfe/static/js/chunk-7968.f51e3292.js.map deleted file mode 100644 index c2f0726b7..000000000 Binary files a/priv/static/adminfe/static/js/chunk-7968.f51e3292.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-8fbb.c847ce9d.js b/priv/static/adminfe/static/js/chunk-8fbb.c847ce9d.js deleted file mode 100644 index 74ffe9194..000000000 Binary files a/priv/static/adminfe/static/js/chunk-8fbb.c847ce9d.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-8fbb.c847ce9d.js.map b/priv/static/adminfe/static/js/chunk-8fbb.c847ce9d.js.map deleted file mode 100644 index b3c3b5fe8..000000000 Binary files a/priv/static/adminfe/static/js/chunk-8fbb.c847ce9d.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-ad1e.eba9db26.js.map b/priv/static/adminfe/static/js/chunk-ad1e.eba9db26.js.map deleted file mode 100644 index d74c2498f..000000000 Binary files a/priv/static/adminfe/static/js/chunk-ad1e.eba9db26.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-bc60.79f8c7e7.js b/priv/static/adminfe/static/js/chunk-bc60.79f8c7e7.js new file mode 100644 index 000000000..b2206aa11 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-bc60.79f8c7e7.js differ diff --git a/priv/static/adminfe/static/js/chunk-bc60.79f8c7e7.js.map b/priv/static/adminfe/static/js/chunk-bc60.79f8c7e7.js.map new file mode 100644 index 000000000..799352270 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-bc60.79f8c7e7.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-e660.feca27c4.js b/priv/static/adminfe/static/js/chunk-e660.2101cafc.js similarity index 99% rename from priv/static/adminfe/static/js/chunk-e660.feca27c4.js rename to priv/static/adminfe/static/js/chunk-e660.2101cafc.js index 5659d263e..20ecbb5a4 100644 Binary files a/priv/static/adminfe/static/js/chunk-e660.feca27c4.js and b/priv/static/adminfe/static/js/chunk-e660.2101cafc.js differ diff --git a/priv/static/adminfe/static/js/chunk-e660.feca27c4.js.map b/priv/static/adminfe/static/js/chunk-e660.2101cafc.js.map similarity index 99% rename from priv/static/adminfe/static/js/chunk-e660.feca27c4.js.map rename to priv/static/adminfe/static/js/chunk-e660.2101cafc.js.map index cfc2e08af..2ff5149ad 100644 Binary files a/priv/static/adminfe/static/js/chunk-e660.feca27c4.js.map and b/priv/static/adminfe/static/js/chunk-e660.2101cafc.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-f364.1122502b.js b/priv/static/adminfe/static/js/chunk-f364.1122502b.js deleted file mode 100644 index facad2ed5..000000000 Binary files a/priv/static/adminfe/static/js/chunk-f364.1122502b.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-f364.1122502b.js.map b/priv/static/adminfe/static/js/chunk-f364.1122502b.js.map deleted file mode 100644 index f89dabe30..000000000 Binary files a/priv/static/adminfe/static/js/chunk-f364.1122502b.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-f364.a5927f18.js b/priv/static/adminfe/static/js/chunk-f364.a5927f18.js new file mode 100644 index 000000000..9a872d819 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-f364.a5927f18.js differ diff --git a/priv/static/adminfe/static/js/chunk-f364.a5927f18.js.map b/priv/static/adminfe/static/js/chunk-f364.a5927f18.js.map new file mode 100644 index 000000000..05f67d1a5 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-f364.a5927f18.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-f625.904137fd.js b/priv/static/adminfe/static/js/chunk-f625.904137fd.js deleted file mode 100644 index 053590b28..000000000 Binary files a/priv/static/adminfe/static/js/chunk-f625.904137fd.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-f625.904137fd.js.map b/priv/static/adminfe/static/js/chunk-f625.904137fd.js.map deleted file mode 100644 index 59c1c274e..000000000 Binary files a/priv/static/adminfe/static/js/chunk-f625.904137fd.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-libs.32ea9181.js b/priv/static/adminfe/static/js/chunk-libs.5ca2c8e8.js similarity index 99% rename from priv/static/adminfe/static/js/chunk-libs.32ea9181.js rename to priv/static/adminfe/static/js/chunk-libs.5ca2c8e8.js index 29cfb2b1d..a496b679c 100644 Binary files a/priv/static/adminfe/static/js/chunk-libs.32ea9181.js and b/priv/static/adminfe/static/js/chunk-libs.5ca2c8e8.js differ diff --git a/priv/static/adminfe/static/js/chunk-libs.32ea9181.js.map b/priv/static/adminfe/static/js/chunk-libs.5ca2c8e8.js.map similarity index 99% rename from priv/static/adminfe/static/js/chunk-libs.32ea9181.js.map rename to priv/static/adminfe/static/js/chunk-libs.5ca2c8e8.js.map index c80cf9acc..3b2db293f 100644 Binary files a/priv/static/adminfe/static/js/chunk-libs.32ea9181.js.map and b/priv/static/adminfe/static/js/chunk-libs.5ca2c8e8.js.map differ diff --git a/priv/static/adminfe/static/js/runtime.6b30c658.js b/priv/static/adminfe/static/js/runtime.6b30c658.js new file mode 100644 index 000000000..ecdf93f1b Binary files /dev/null and b/priv/static/adminfe/static/js/runtime.6b30c658.js differ diff --git a/priv/static/adminfe/static/js/runtime.6b30c658.js.map b/priv/static/adminfe/static/js/runtime.6b30c658.js.map new file mode 100644 index 000000000..67a46d4bf Binary files /dev/null and b/priv/static/adminfe/static/js/runtime.6b30c658.js.map differ diff --git a/priv/static/adminfe/static/js/runtime.ba96836e.js b/priv/static/adminfe/static/js/runtime.ba96836e.js deleted file mode 100644 index 245c7fe20..000000000 Binary files a/priv/static/adminfe/static/js/runtime.ba96836e.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/runtime.ba96836e.js.map b/priv/static/adminfe/static/js/runtime.ba96836e.js.map deleted file mode 100644 index f3c5a82af..000000000 Binary files a/priv/static/adminfe/static/js/runtime.ba96836e.js.map and /dev/null differ diff --git a/priv/static/index.html b/priv/static/index.html index 9b774959a..c4dcf5d37 100644 --- a/priv/static/index.html +++ b/priv/static/index.html @@ -1 +1 @@ -Pleroma
\ No newline at end of file +
\ No newline at end of file diff --git a/priv/static/static/emoji.json b/priv/static/static/emoji.json index ae93d17e1..12b91b3f6 100644 --- a/priv/static/static/emoji.json +++ b/priv/static/static/emoji.json @@ -1,969 +1,1431 @@ { - "womans_clothes": "\ud83d\udc5a", - "cookie": "\ud83c\udf6a", - "woman_with_headscarf": "\ud83e\uddd5", - "no_smoking": "\ud83d\udead", - "e-mail": "\ud83d\udce7", - "regional_indicator_d": "\ud83c\udde9", - "oncoming_bus": "\ud83d\ude8d", - "knife": "\ud83d\udd2a", - "person_getting_haircut": "\ud83d\udc87", - "grimacing": "\ud83d\ude2c", - "ophiuchus": "\u26ce", - "regional_indicator_q": "\ud83c\uddf6", - "thinking": "\ud83e\udd14", - "signal_strength": "\ud83d\udcf6", - "cactus": "\ud83c\udf35", - "bullettrain_front": "\ud83d\ude85", - "floppy_disk": "\ud83d\udcbe", - "doughnut": "\ud83c\udf69", - "tv": "\ud83d\udcfa", - "1234": "\ud83d\udd22", - "anguished": "\ud83d\ude27", - "clock1030": "\ud83d\udd65", - "u7533": "\ud83c\ude38", - "speak_no_evil": "\ud83d\ude4a", - "chart_with_upwards_trend": "\ud83d\udcc8", - "trophy": "\ud83c\udfc6", - "musical_score": "\ud83c\udfbc", - "chestnut": "\ud83c\udf30", - "clock1130": "\ud83d\udd66", - "abcd": "\ud83d\udd21", - "syringe": "\ud83d\udc89", - "shrimp": "\ud83e\udd90", - "pisces": "\u2653", - "left_facing_fist": "\ud83e\udd1b", - "bar_chart": "\ud83d\udcca", - "eagle": "\ud83e\udd85", - "woman": "\ud83d\udc69", - "keycap_ten": "\ud83d\udd1f", - "yellow_heart": "\ud83d\udc9b", - "croissant": "\ud83e\udd50", - "mosque": "\ud83d\udd4c", - "rice_ball": "\ud83c\udf59", - "volcano": "\ud83c\udf0b", - "baggage_claim": "\ud83d\udec4", - "family": "\ud83d\udc6a", - "beetle": "\ud83d\udc1e", - "older_adult": "\ud83e\uddd3", - "clock830": "\ud83d\udd63", - "bacon": "\ud83e\udd53", - "sound": "\ud83d\udd09", - "no_bicycles": "\ud83d\udeb3", - "rewind": "\u23ea", - "adult": "\ud83e\uddd1", - "scream_cat": "\ud83d\ude40", - "person_playing_water_polo": "\ud83e\udd3d", - "blue_car": "\ud83d\ude99", - "smiley": "\ud83d\ude03", - "kaaba": "\ud83d\udd4b", - "twisted_rightwards_arrows": "\ud83d\udd00", - "last_quarter_moon": "\ud83c\udf17", - "first_place": "\ud83e\udd47", - "joy_cat": "\ud83d\ude39", - "sleeping": "\ud83d\ude34", - "basketball": "\ud83c\udfc0", - "pray": "\ud83d\ude4f", - "trumpet": "\ud83c\udfba", - "purple_heart": "\ud83d\udc9c", - "broken_heart": "\ud83d\udc94", - "astonished": "\ud83d\ude32", - "soccer": "\u26bd", - "princess": "\ud83d\udc78", - "ant": "\ud83d\udc1c", - "pig": "\ud83d\udc37", - "vhs": "\ud83d\udcfc", - "scream": "\ud83d\ude31", - "mouse": "\ud83d\udc2d", - "field_hockey": "\ud83c\udfd1", - "ab": "\ud83c\udd8e", - "tokyo_tower": "\ud83d\uddfc", - "girl": "\ud83d\udc67", - "u55b6": "\ud83c\ude3a", - "guard": "\ud83d\udc82", - "regional_indicator_s": "\ud83c\uddf8", - "tulip": "\ud83c\udf37", - "capital_abcd": "\ud83d\udd20", - "beginner": "\ud83d\udd30", - "couplekiss": "\ud83d\udc8f", - "u5408": "\ud83c\ude34", - "black_medium_small_square": "\u25fe", - "paperclip": "\ud83d\udcce", - "hedgehog": "\ud83e\udd94", - "musical_note": "\ud83c\udfb5", - "pill": "\ud83d\udc8a", - "blue_heart": "\ud83d\udc99", - "mens": "\ud83d\udeb9", - "third_place": "\ud83e\udd49", - "stew": "\ud83c\udf72", - "prince": "\ud83e\udd34", - "mortar_board": "\ud83c\udf93", - "clock6": "\ud83d\udd55", - "beer": "\ud83c\udf7a", - "person_tipping_hand": "\ud83d\udc81", - "triangular_ruler": "\ud83d\udcd0", - "regional_indicator_y": "\ud83c\uddfe", - "person_facepalming": "\ud83e\udd26", - "steam_locomotive": "\ud83d\ude82", - "fire_engine": "\ud83d\ude92", - "horse": "\ud83d\udc34", - "ribbon": "\ud83c\udf80", - "white_large_square": "\u2b1c", - "smirk": "\ud83d\ude0f", - "genie": "\ud83e\uddde", - "tangerine": "\ud83c\udf4a", - "cl": "\ud83c\udd91", - "japanese_goblin": "\ud83d\udc7a", - "regional_indicator_u": "\ud83c\uddfa", - "ring": "\ud83d\udc8d", - "roller_coaster": "\ud83c\udfa2", - "100": "\ud83d\udcaf", - "clock12": "\ud83d\udd5b", - "two_hearts": "\ud83d\udc95", - "anger": "\ud83d\udca2", - "black_circle": "\u26ab", - "revolving_hearts": "\ud83d\udc9e", - "space_invader": "\ud83d\udc7e", - "bell": "\ud83d\udd14", - "point_up_2": "\ud83d\udc46", - "person_mountain_biking": "\ud83d\udeb5", - "flags": "\ud83c\udf8f", - "pushpin": "\ud83d\udccc", - "large_blue_diamond": "\ud83d\udd37", - "fairy": "\ud83e\uddda", - "european_post_office": "\ud83c\udfe4", - "statue_of_liberty": "\ud83d\uddfd", - "man": "\ud83d\udc68", - "microphone": "\ud83c\udfa4", - "inbox_tray": "\ud83d\udce5", - "bath": "\ud83d\udec0", - "person_gesturing_ok": "\ud83d\ude46", - "clap": "\ud83d\udc4f", - "confused": "\ud83d\ude15", - "fortune_cookie": "\ud83e\udd60", - "kissing_closed_eyes": "\ud83d\ude1a", - "kissing_heart": "\ud83d\ude18", - "tropical_fish": "\ud83d\udc20", - "taco": "\ud83c\udf2e", - "kimono": "\ud83d\udc58", - "u7a7a": "\ud83c\ude33", - "rat": "\ud83d\udc00", - "taurus": "\u2649", - "shopping_cart": "\ud83d\uded2", - "womans_hat": "\ud83d\udc52", - "blossom": "\ud83c\udf3c", - "moyai": "\ud83d\uddff", - "clock130": "\ud83d\udd5c", - "telescope": "\ud83d\udd2d", - "running_shirt_with_sash": "\ud83c\udfbd", - "person_running": "\ud83c\udfc3", - "dizzy": "\ud83d\udcab", - "crescent_moon": "\ud83c\udf19", - "boom": "\ud83d\udca5", - "restroom": "\ud83d\udebb", - "fist": "\u270a", - "white_flower": "\ud83d\udcae", - "clown": "\ud83e\udd21", - "neutral_face": "\ud83d\ude10", - "id": "\ud83c\udd94", - "carrot": "\ud83e\udd55", - "rice_scene": "\ud83c\udf91", - "foggy": "\ud83c\udf01", - "turtle": "\ud83d\udc22", - "mailbox_with_mail": "\ud83d\udcec", - "baseball": "\u26be", - "grin": "\ud83d\ude01", - "bathtub": "\ud83d\udec1", - "feet": "\ud83d\udc3e", - "small_red_triangle": "\ud83d\udd3a", - "camel": "\ud83d\udc2b", - "aquarius": "\u2652", - "face_with_symbols_over_mouth": "\ud83e\udd2c", - "handbag": "\ud83d\udc5c", - "date": "\ud83d\udcc5", - "nail_care": "\ud83d\udc85", - "satellite": "\ud83d\udce1", - "candy": "\ud83c\udf6c", - "white_medium_small_square": "\u25fd", - "clock930": "\ud83d\udd64", - "fearful": "\ud83d\ude28", - "fork_and_knife": "\ud83c\udf74", - "person_wearing_turban": "\ud83d\udc73", - "confounded": "\ud83d\ude16", - "helicopter": "\ud83d\ude81", - "arrow_double_down": "\u23ec", - "convenience_store": "\ud83c\udfea", - "ghost": "\ud83d\udc7b", - "bus": "\ud83d\ude8c", - "waning_gibbous_moon": "\ud83c\udf16", - "bank": "\ud83c\udfe6", - "department_store": "\ud83c\udfec", - "hockey": "\ud83c\udfd2", - "fingers_crossed": "\ud83e\udd1e", - "blond_haired_person": "\ud83d\udc71", - "mag": "\ud83d\udd0d", - "cut_of_meat": "\ud83e\udd69", - "wink": "\ud83d\ude09", - "railway_car": "\ud83d\ude83", - "face_vomiting": "\ud83e\udd2e", - "star_struck": "\ud83e\udd29", - "first_quarter_moon_with_face": "\ud83c\udf1b", - "octagonal_sign": "\ud83d\uded1", - "hospital": "\ud83c\udfe5", - "monkey": "\ud83d\udc12", - "curly_loop": "\u27b0", - "avocado": "\ud83e\udd51", - "earth_americas": "\ud83c\udf0e", - "flashlight": "\ud83d\udd26", - "8ball": "\ud83c\udfb1", - "clock630": "\ud83d\udd61", - "boar": "\ud83d\udc17", - "birthday": "\ud83c\udf82", - "crocodile": "\ud83d\udc0a", - "confetti_ball": "\ud83c\udf8a", - "door": "\ud83d\udeaa", - "school_satchel": "\ud83c\udf92", - "peanuts": "\ud83e\udd5c", - "regional_indicator_m": "\ud83c\uddf2", - "bust_in_silhouette": "\ud83d\udc64", - "sweat_drops": "\ud83d\udca6", - "tongue": "\ud83d\udc45", - "mag_right": "\ud83d\udd0e", - "t_rex": "\ud83e\udd96", - "post_office": "\ud83c\udfe3", - "shell": "\ud83d\udc1a", - "disappointed_relieved": "\ud83d\ude25", - "card_index": "\ud83d\udcc7", - "oncoming_automobile": "\ud83d\ude98", - "passport_control": "\ud83d\udec2", - "cherry_blossom": "\ud83c\udf38", - "shallow_pan_of_food": "\ud83e\udd58", - "heart": "\u2764\ufe0f", - "heartbeat": "\ud83d\udc93", - "crazy_face": "\ud83e\udd2a", - "grapes": "\ud83c\udf47", - "symbols": "\ud83d\udd23", - "gift": "\ud83c\udf81", - "scorpion": "\ud83e\udd82", - "wedding": "\ud83d\udc92", - "last_quarter_moon_with_face": "\ud83c\udf1c", - "love_letter": "\ud83d\udc8c", - "postal_horn": "\ud83d\udcef", - "stuffed_flatbread": "\ud83e\udd59", - "heavy_dollar_sign": "\ud83d\udcb2", - "love_hotel": "\ud83c\udfe9", - "yen": "\ud83d\udcb4", - "person_in_steamy_room": "\ud83e\uddd6", - "palm_tree": "\ud83c\udf34", - "name_badge": "\ud83d\udcdb", - "clock430": "\ud83d\udd5f", - "bike": "\ud83d\udeb2", - "snail": "\ud83d\udc0c", - "bowling": "\ud83c\udfb3", - "umbrella": "\u2614", - "sleeping_accommodation": "\ud83d\udecc", - "fireworks": "\ud83c\udf86", - "closed_book": "\ud83d\udcd5", - "city_sunset": "\ud83c\udf07", - "persevere": "\ud83d\ude23", - "bento": "\ud83c\udf71", - "nut_and_bolt": "\ud83d\udd29", - "page_facing_up": "\ud83d\udcc4", - "snowman": "\u26c4", - "two_women_holding_hands": "\ud83d\udc6d", - "regional_indicator_o": "\ud83c\uddf4", - "calling": "\ud83d\udcf2", - "person_shrugging": "\ud83e\udd37", - "sneezing_face": "\ud83e\udd27", - "arrows_clockwise": "\ud83d\udd03", - "no_pedestrians": "\ud83d\udeb7", - "potato": "\ud83e\udd54", - "cheese": "\ud83e\uddc0", - "full_moon": "\ud83c\udf15", - "mount_fuji": "\ud83d\uddfb", - "sob": "\ud83d\ude2d", - "construction": "\ud83d\udea7", - "head_bandage": "\ud83e\udd15", - "sailboat": "\u26f5", - "slight_frown": "\ud83d\ude41", - "ping_pong": "\ud83c\udfd3", - "hatched_chick": "\ud83d\udc25", - "sun_with_face": "\ud83c\udf1e", - "seedling": "\ud83c\udf31", - "repeat_one": "\ud83d\udd02", - "muscle": "\ud83d\udcaa", - "bridge_at_night": "\ud83c\udf09", - "raised_hands": "\ud83d\ude4c", - "house": "\ud83c\udfe0", - "nerd": "\ud83e\udd13", - "penguin": "\ud83d\udc27", - "peach": "\ud83c\udf51", - "dumpling": "\ud83e\udd5f", - "watch": "\u231a", - "womens": "\ud83d\udeba", - "round_pushpin": "\ud83d\udccd", - "alarm_clock": "\u23f0", - "relieved": "\ud83d\ude0c", - "sagittarius": "\u2650", - "busstop": "\ud83d\ude8f", - "regional_indicator_a": "\ud83c\udde6", - "sandal": "\ud83d\udc61", - "whale2": "\ud83d\udc0b", - "book": "\ud83d\udcd6", - "sweat": "\ud83d\ude13", - "movie_camera": "\ud83c\udfa5", - "clock230": "\ud83d\udd5d", - "tiger": "\ud83d\udc2f", - "tractor": "\ud83d\ude9c", - "smile": "\ud83d\ude04", - "vertical_traffic_light": "\ud83d\udea6", - "exploding_head": "\ud83e\udd2f", - "raised_hand": "\u270b", - "smoking": "\ud83d\udeac", - "page_with_curl": "\ud83d\udcc3", - "exclamation": "\u2757", - "fish": "\ud83d\udc1f", - "mans_shoe": "\ud83d\udc5e", - "sos": "\ud83c\udd98", - "unlock": "\ud83d\udd13", - "dolls": "\ud83c\udf8e", - "ear_of_rice": "\ud83c\udf3e", - "cat2": "\ud83d\udc08", - "u7121": "\ud83c\ude1a", - "repeat": "\ud83d\udd01", - "cool": "\ud83c\udd92", - "minibus": "\ud83d\ude90", - "aerial_tramway": "\ud83d\udea1", - "key": "\ud83d\udd11", - "child": "\ud83e\uddd2", - "camera": "\ud83d\udcf7", - "sunflower": "\ud83c\udf3b", - "white_check_mark": "\u2705", - "white_square_button": "\ud83d\udd33", - "banana": "\ud83c\udf4c", - "milky_way": "\ud83c\udf0c", - "person_gesturing_no": "\ud83d\ude45", - "sushi": "\ud83c\udf63", - "heart_eyes_cat": "\ud83d\ude3b", - "guitar": "\ud83c\udfb8", - "pie": "\ud83e\udd67", - "calendar": "\ud83d\udcc6", - "bear": "\ud83d\udc3b", - "person_in_lotus_position": "\ud83e\uddd8", - "clock10": "\ud83d\udd59", - "top": "\ud83d\udd1d", - "fuelpump": "\u26fd", - "rainbow": "\ud83c\udf08", - "snowboarder": "\ud83c\udfc2", - "drum": "\ud83e\udd41", - "leaves": "\ud83c\udf43", - "first_quarter_moon": "\ud83c\udf13", - "spoon": "\ud83e\udd44", - "pouting_cat": "\ud83d\ude3e", - "shaved_ice": "\ud83c\udf67", - "unamused": "\ud83d\ude12", - "train2": "\ud83d\ude86", - "clock1230": "\ud83d\udd67", - "regional_indicator_r": "\ud83c\uddf7", - "fast_forward": "\u23e9", - "accept": "\ud83c\ude51", - "hammer": "\ud83d\udd28", - "panda_face": "\ud83d\udc3c", - "briefcase": "\ud83d\udcbc", - "package": "\ud83d\udce6", - "flag_black": "\ud83c\udff4", - "smiling_imp": "\ud83d\ude08", - "sunrise_over_mountains": "\ud83c\udf04", - "airplane_departure": "\ud83d\udeeb", - "tiger2": "\ud83d\udc05", - "non-potable_water": "\ud83d\udeb1", - "bird": "\ud83d\udc26", - "barber": "\ud83d\udc88", - "cry": "\ud83d\ude22", - "billed_cap": "\ud83e\udde2", - "pouch": "\ud83d\udc5d", - "link": "\ud83d\udd17", - "zebra": "\ud83e\udd93", - "kiss": "\ud83d\udc8b", - "scorpius": "\u264f", - "prayer_beads": "\ud83d\udcff", - "high_brightness": "\ud83d\udd06", - "kissing_smiling_eyes": "\ud83d\ude19", - "rhino": "\ud83e\udd8f", - "left_luggage": "\ud83d\udec5", - "o": "\u2b55", - "crying_cat_face": "\ud83d\ude3f", - "clock8": "\ud83d\udd57", - "dress": "\ud83d\udc57", - "clock7": "\ud83d\udd56", - "bowl_with_spoon": "\ud83e\udd63", - "rolling_eyes": "\ud83d\ude44", - "fax": "\ud83d\udce0", - "worried": "\ud83d\ude1f", - "grey_question": "\u2754", - "saxophone": "\ud83c\udfb7", - "burrito": "\ud83c\udf2f", - "salad": "\ud83e\udd57", - "regional_indicator_z": "\ud83c\uddff", - "bikini": "\ud83d\udc59", - "milk": "\ud83e\udd5b", - "stars": "\ud83c\udf20", - "lips": "\ud83d\udc44", - "cd": "\ud83d\udcbf", - "weary": "\ud83d\ude29", - "face_with_raised_eyebrow": "\ud83e\udd28", - "lizard": "\ud83e\udd8e", - "tone1": "\ud83c\udffb", - "bullettrain_side": "\ud83d\ude84", - "nose": "\ud83d\udc43", - "innocent": "\ud83d\ude07", - "wilted_rose": "\ud83e\udd40", - "mahjong": "\ud83c\udc04", - "factory": "\ud83c\udfed", - "people_wrestling": "\ud83e\udd3c", - "mailbox": "\ud83d\udceb", - "rage": "\ud83d\ude21", - "wheelchair": "\u267f", - "x": "\u274c", - "flower_playing_cards": "\ud83c\udfb4", - "nauseated_face": "\ud83e\udd22", - "underage": "\ud83d\udd1e", - "ideograph_advantage": "\ud83c\ude50", - "high_heel": "\ud83d\udc60", - "dizzy_face": "\ud83d\ude35", - "stuck_out_tongue": "\ud83d\ude1b", - "mailbox_with_no_mail": "\ud83d\udced", - "orange_heart": "\ud83e\udde1", - "raised_back_of_hand": "\ud83e\udd1a", - "footprints": "\ud83d\udc63", - "notebook_with_decorative_cover": "\ud83d\udcd4", - "mask": "\ud83d\ude37", - "sunglasses": "\ud83d\ude0e", - "pancakes": "\ud83e\udd5e", - "regional_indicator_f": "\ud83c\uddeb", - "dog": "\ud83d\udc36", - "pig2": "\ud83d\udc16", - "ng": "\ud83c\udd96", - "unicorn": "\ud83e\udd84", - "triumph": "\ud83d\ude24", - "eggplant": "\ud83c\udf46", - "egg": "\ud83e\udd5a", - "office": "\ud83c\udfe2", - "goat": "\ud83d\udc10", - "handshake": "\ud83e\udd1d", - "star": "\u2b50", - "rugby_football": "\ud83c\udfc9", - "call_me": "\ud83e\udd19", - "rice_cracker": "\ud83c\udf58", - "droplet": "\ud83d\udca7", - "badminton": "\ud83c\udff8", - "waxing_crescent_moon": "\ud83c\udf12", - "ocean": "\ud83c\udf0a", - "slot_machine": "\ud83c\udfb0", - "wine_glass": "\ud83c\udf77", - "elephant": "\ud83d\udc18", - "blowfish": "\ud83d\udc21", - "ledger": "\ud83d\udcd2", - "money_mouth": "\ud83e\udd11", - "heart_decoration": "\ud83d\udc9f", - "arrow_down_small": "\ud83d\udd3d", - "station": "\ud83d\ude89", - "man_with_chinese_cap": "\ud83d\udc72", - "vampire": "\ud83e\udddb", - "pencil": "\ud83d\udcdd", - "cyclone": "\ud83c\udf00", - "mushroom": "\ud83c\udf44", - "sandwich": "\ud83e\udd6a", - "champagne": "\ud83c\udf7e", - "expressionless": "\ud83d\ude11", - "cold_sweat": "\ud83d\ude30", - "maple_leaf": "\ud83c\udf41", - "dromedary_camel": "\ud83d\udc2a", - "vs": "\ud83c\udd9a", - "person_fencing": "\ud83e\udd3a", - "straight_ruler": "\ud83d\udccf", - "baby_bottle": "\ud83c\udf7c", - "currency_exchange": "\ud83d\udcb1", - "regional_indicator_h": "\ud83c\udded", - "stuck_out_tongue_closed_eyes": "\ud83d\ude1d", - "closed_lock_with_key": "\ud83d\udd10", - "eyes": "\ud83d\udc40", - "water_buffalo": "\ud83d\udc03", - "lock_with_ink_pen": "\ud83d\udd0f", - "heavy_plus_sign": "\u2795", - "bookmark": "\ud83d\udd16", - "soon": "\ud83d\udd1c", - "orange_book": "\ud83d\udcd9", - "pineapple": "\ud83c\udf4d", - "clock9": "\ud83d\udd58", - "small_blue_diamond": "\ud83d\udd39", - "black_large_square": "\u2b1b", - "person_surfing": "\ud83c\udfc4", - "leo": "\u264c", - "merperson": "\ud83e\udddc", - "canoe": "\ud83d\udef6", - "rooster": "\ud83d\udc13", - "hear_no_evil": "\ud83d\ude49", - "corn": "\ud83c\udf3d", - "takeout_box": "\ud83e\udd61", - "oncoming_taxi": "\ud83d\ude96", - "taxi": "\ud83d\ude95", - "chart": "\ud83d\udcb9", - "goal": "\ud83e\udd45", - "melon": "\ud83c\udf48", - "notes": "\ud83c\udfb6", - "sparkler": "\ud83c\udf87", - "dolphin": "\ud83d\udc2c", - "speedboat": "\ud83d\udea4", - "cancer": "\u264b", - "sled": "\ud83d\udef7", - "tanabata_tree": "\ud83c\udf8b", - "train": "\ud83d\ude8b", - "christmas_tree": "\ud83c\udf84", - "two_men_holding_hands": "\ud83d\udc6c", - "back": "\ud83d\udd19", - "balloon": "\ud83c\udf88", - "checkered_flag": "\ud83c\udfc1", - "loop": "\u27bf", - "wc": "\ud83d\udebe", - "jeans": "\ud83d\udc56", - "green_apple": "\ud83c\udf4f", - "crown": "\ud83d\udc51", - "cowboy": "\ud83e\udd20", - "postbox": "\ud83d\udcee", - "volleyball": "\ud83c\udfd0", - "upside_down": "\ud83d\ude43", - "cricket": "\ud83e\udd97", - "custard": "\ud83c\udf6e", - "rose": "\ud83c\udf39", - "eyeglasses": "\ud83d\udc53", - "oncoming_police_car": "\ud83d\ude94", - "atm": "\ud83c\udfe7", - "flying_saucer": "\ud83d\udef8", - "alien": "\ud83d\udc7d", - "hamster": "\ud83d\udc39", - "trident": "\ud83d\udd31", - "disappointed": "\ud83d\ude1e", - "cow": "\ud83d\udc2e", - "police_officer": "\ud83d\udc6e", - "popcorn": "\ud83c\udf7f", - "baby_chick": "\ud83d\udc24", - "video_camera": "\ud83d\udcf9", - "zzz": "\ud83d\udca4", - "person_climbing": "\ud83e\uddd7", - "star2": "\ud83c\udf1f", - "ok": "\ud83c\udd97", - "capricorn": "\u2651", - "chicken": "\ud83d\udc14", - "arrow_double_up": "\u23eb", - "zombie": "\ud83e\udddf", - "closed_umbrella": "\ud83c\udf02", - "person_walking": "\ud83d\udeb6", - "lemon": "\ud83c\udf4b", - "heartpulse": "\ud83d\udc97", - "regional_indicator_i": "\ud83c\uddee", - "sauropod": "\ud83e\udd95", - "u7981": "\ud83c\ude32", - "regional_indicator_w": "\ud83c\uddfc", - "evergreen_tree": "\ud83c\udf32", - "mobile_phone_off": "\ud83d\udcf4", - "koko": "\ud83c\ude01", - "poop": "\ud83d\udca9", - "cup_with_straw": "\ud83e\udd64", - "leopard": "\ud83d\udc06", - "radio_button": "\ud83d\udd18", - "mega": "\ud83d\udce3", - "metal": "\ud83e\udd18", - "shushing_face": "\ud83e\udd2b", - "stuck_out_tongue_winking_eye": "\ud83d\ude1c", - "octopus": "\ud83d\udc19", - "boxing_glove": "\ud83e\udd4a", - "person_juggling": "\ud83e\udd39", - "money_with_wings": "\ud83d\udcb8", - "dollar": "\ud83d\udcb5", - "bride_with_veil": "\ud83d\udc70", - "second_place": "\ud83e\udd48", - "spaghetti": "\ud83c\udf5d", - "waning_crescent_moon": "\ud83c\udf18", - "football": "\ud83c\udfc8", - "white_circle": "\u26aa", - "full_moon_with_face": "\ud83c\udf1d", - "selfie": "\ud83e\udd33", - "tone3": "\ud83c\udffd", - "rabbit": "\ud83d\udc30", - "computer": "\ud83d\udcbb", - "clock11": "\ud83d\udd5a", - "heavy_minus_sign": "\u2796", - "synagogue": "\ud83d\udd4d", - "hourglass": "\u231b", - "gem": "\ud83d\udc8e", - "person_doing_cartwheel": "\ud83e\udd38", - "new_moon_with_face": "\ud83c\udf1a", - "sunrise": "\ud83c\udf05", - "regional_indicator_x": "\ud83c\uddfd", - "open_file_folder": "\ud83d\udcc2", - "gift_heart": "\ud83d\udc9d", - "tada": "\ud83c\udf89", - "green_heart": "\ud83d\udc9a", - "battery": "\ud83d\udd0b", - "regional_indicator_t": "\ud83c\uddf9", - "wrench": "\ud83d\udd27", - "aries": "\u2648", - "man_in_tuxedo": "\ud83e\udd35", - "regional_indicator_e": "\ud83c\uddea", - "regional_indicator_l": "\ud83c\uddf1", - "cake": "\ud83c\udf70", - "clapper": "\ud83c\udfac", - "japanese_castle": "\ud83c\udfef", - "crystal_ball": "\ud83d\udd2e", - "golf": "\u26f3", - "no_mobile_phones": "\ud83d\udcf5", - "person_biking": "\ud83d\udeb4", - "icecream": "\ud83c\udf66", - "mage": "\ud83e\uddd9", - "bookmark_tabs": "\ud83d\udcd1", - "tone4": "\ud83c\udffe", - "mountain_cableway": "\ud83d\udea0", - "person_playing_handball": "\ud83e\udd3e", - "bulb": "\ud83d\udca1", - "clock330": "\ud83d\udd5e", - "metro": "\ud83d\ude87", - "wave": "\ud83d\udc4b", - "whale": "\ud83d\udc33", - "strawberry": "\ud83c\udf53", - "hatching_chick": "\ud83d\udc23", - "trolleybus": "\ud83d\ude8e", - "lollipop": "\ud83c\udf6d", - "clipboard": "\ud83d\udccb", - "point_right": "\ud83d\udc49", - "u6307": "\ud83c\ude2f", - "santa": "\ud83c\udf85", - "hibiscus": "\ud83c\udf3a", - "green_book": "\ud83d\udcd7", - "skull": "\ud83d\udc80", - "tumbler_glass": "\ud83e\udd43", - "clock2": "\ud83d\udd51", - "open_mouth": "\ud83d\ude2e", - "bouquet": "\ud83d\udc90", - "champagne_glass": "\ud83e\udd42", - "poodle": "\ud83d\udc29", - "hushed": "\ud83d\ude2f", - "earth_asia": "\ud83c\udf0f", - "face_with_monocle": "\ud83e\uddd0", - "libra": "\u264e", - "clock5": "\ud83d\udd54", - "ambulance": "\ud83d\ude91", - "u5272": "\ud83c\ude39", - "lipstick": "\ud83d\udc84", - "apple": "\ud83c\udf4e", - "headphones": "\ud83c\udfa7", - "turkey": "\ud83e\udd83", - "pretzel": "\ud83e\udd68", - "bug": "\ud83d\udc1b", - "school": "\ud83c\udfeb", - "speaker": "\ud83d\udd08", - "boot": "\ud83d\udc62", - "cat": "\ud83d\udc31", - "dancer": "\ud83d\udc83", - "no_entry": "\u26d4", - "kissing_cat": "\ud83d\ude3d", - "art": "\ud83c\udfa8", - "coat": "\ud83e\udde5", - "credit_card": "\ud83d\udcb3", - "customs": "\ud83d\udec3", - "broccoli": "\ud83e\udd66", - "point_left": "\ud83d\udc48", - "canned_food": "\ud83e\udd6b", - "sheep": "\ud83d\udc11", - "person_bowing": "\ud83d\ude47", - "scroll": "\ud83d\udcdc", - "martial_arts_uniform": "\ud83e\udd4b", - "amphora": "\ud83c\udffa", - "thought_balloon": "\ud83d\udcad", - "no_bell": "\ud83d\udd15", - "musical_keyboard": "\ud83c\udfb9", - "people_with_bunny_ears_partying": "\ud83d\udc6f", - "european_castle": "\ud83c\udff0", - "punch": "\ud83d\udc4a", - "camera_with_flash": "\ud83d\udcf8", - "regional_indicator_p": "\ud83c\uddf5", - "red_car": "\ud83d\ude97", - "regional_indicator_j": "\ud83c\uddef", - "owl": "\ud83e\udd89", - "chart_with_downwards_trend": "\ud83d\udcc9", - "older_woman": "\ud83d\udc75", - "gemini": "\u264a", - "incoming_envelope": "\ud83d\udce8", - "waxing_gibbous_moon": "\ud83c\udf14", - "toilet": "\ud83d\udebd", - "dragon_face": "\ud83d\udc32", - "koala": "\ud83d\udc28", - "tone5": "\ud83c\udfff", - "kiwi": "\ud83e\udd5d", - "dash": "\ud83d\udca8", - "imp": "\ud83d\udc7f", - "tent": "\u26fa", - "regional_indicator_b": "\ud83c\udde7", - "monorail": "\ud83d\ude9d", - "ox": "\ud83d\udc02", - "giraffe": "\ud83e\udd92", - "new": "\ud83c\udd95", - "person_raising_hand": "\ud83d\ude4b", - "japan": "\ud83d\uddfe", - "rice": "\ud83c\udf5a", - "ticket": "\ud83c\udfab", - "rotating_light": "\ud83d\udea8", - "loudspeaker": "\ud83d\udce2", - "person_getting_massage": "\ud83d\udc86", - "loud_sound": "\ud83d\udd0a", - "hugging": "\ud83e\udd17", - "herb": "\ud83c\udf3f", - "baby": "\ud83d\udc76", - "angel": "\ud83d\udc7c", - "athletic_shoe": "\ud83d\udc5f", - "euro": "\ud83d\udcb6", - "ram": "\ud83d\udc0f", - "large_orange_diamond": "\ud83d\udd36", - "red_circle": "\ud83d\udd34", - "ferris_wheel": "\ud83c\udfa1", - "drooling_face": "\ud83e\udd24", - "microscope": "\ud83d\udd2c", - "middle_finger": "\ud83d\udd95", - "pager": "\ud83d\udcdf", - "pensive": "\ud83d\ude14", - "potable_water": "\ud83d\udeb0", - "abc": "\ud83d\udd24", - "four_leaf_clover": "\ud83c\udf40", - "vulcan": "\ud83d\udd96", - "french_bread": "\ud83e\udd56", - "motor_scooter": "\ud83d\udef5", - "moneybag": "\ud83d\udcb0", - "sparkles": "\u2728", - "gloves": "\ud83e\udde4", - "envelope_with_arrow": "\ud83d\udce9", - "thumbsdown": "\ud83d\udc4e", - "regional_indicator_g": "\ud83c\uddec", - "video_game": "\ud83c\udfae", - "on": "\ud83d\udd1b", - "open_hands": "\ud83d\udc50", - "monkey_face": "\ud83d\udc35", - "mountain_railway": "\ud83d\ude9e", - "bee": "\ud83d\udc1d", - "scooter": "\ud83d\udef4", - "fishing_pole_and_fish": "\ud83c\udfa3", - "smiley_cat": "\ud83d\ude3a", - "heart_eyes": "\ud83d\ude0d", - "horse_racing": "\ud83c\udfc7", - "ear": "\ud83d\udc42", - "blue_circle": "\ud83d\udd35", - "crossed_flags": "\ud83c\udf8c", - "black_joker": "\ud83c\udccf", - "six_pointed_star": "\ud83d\udd2f", - "fountain": "\u26f2", - "free": "\ud83c\udd93", - "tennis": "\ud83c\udfbe", - "yum": "\ud83d\ude0b", - "fried_shrimp": "\ud83c\udf64", - "dragon": "\ud83d\udc09", - "purse": "\ud83d\udc5b", - "clock1": "\ud83d\udd50", - "airplane_arriving": "\ud83d\udeec", - "cucumber": "\ud83e\udd52", - "man_dancing": "\ud83d\udd7a", - "clock730": "\ud83d\udd62", - "deer": "\ud83e\udd8c", - "meat_on_bone": "\ud83c\udf56", - "bomb": "\ud83d\udca3", - "night_with_stars": "\ud83c\udf03", - "snake": "\ud83d\udc0d", - "ramen": "\ud83c\udf5c", - "end": "\ud83d\udd1a", - "do_not_litter": "\ud83d\udeaf", - "joy": "\ud83d\ude02", - "light_rail": "\ud83d\ude88", - "game_die": "\ud83c\udfb2", - "violin": "\ud83c\udfbb", - "tone2": "\ud83c\udffc", - "tropical_drink": "\ud83c\udf79", - "love_you_gesture": "\ud83e\udd1f", - "cherries": "\ud83c\udf52", - "traffic_light": "\ud83d\udea5", - "iphone": "\ud83d\udcf1", - "socks": "\ud83e\udde6", - "wind_chime": "\ud83c\udf90", - "no_entry_sign": "\ud83d\udeab", - "elf": "\ud83e\udddd", - "squid": "\ud83e\udd91", - "person_pouting": "\ud83d\ude4e", - "smile_cat": "\ud83d\ude38", - "beers": "\ud83c\udf7b", - "minidisc": "\ud83d\udcbd", - "clock4": "\ud83d\udd53", - "ice_cream": "\ud83c\udf68", - "cocktail": "\ud83c\udf78", - "clock3": "\ud83d\udd52", - "frowning": "\ud83d\ude26", - "hamburger": "\ud83c\udf54", - "brain": "\ud83e\udde0", - "heavy_division_sign": "\u2797", - "tophat": "\ud83c\udfa9", - "no_mouth": "\ud83d\ude36", - "ski": "\ud83c\udfbf", - "right_facing_fist": "\ud83e\udd1c", - "mailbox_closed": "\ud83d\udcea", - "chocolate_bar": "\ud83c\udf6b", - "rabbit2": "\ud83d\udc07", - "honey_pot": "\ud83c\udf6f", - "izakaya_lantern": "\ud83c\udfee", - "articulated_lorry": "\ud83d\ude9b", - "face_with_hand_over_mouth": "\ud83e\udd2d", - "japanese_ogre": "\ud83d\udc79", - "zap": "\u26a1", - "rocket": "\ud83d\ude80", - "pizza": "\ud83c\udf55", - "pound": "\ud83d\udcb7", - "person_swimming": "\ud83c\udfca", - "anchor": "\u2693", - "coconut": "\ud83e\udd65", - "sparkling_heart": "\ud83d\udc96", - "older_man": "\ud83d\udc74", - "mouse2": "\ud83d\udc01", - "angry": "\ud83d\ude20", - "up": "\ud83c\udd99", - "gorilla": "\ud83e\udd8d", - "children_crossing": "\ud83d\udeb8", - "smirk_cat": "\ud83d\ude3c", - "pregnant_woman": "\ud83e\udd30", - "electric_plug": "\ud83d\udd0c", - "dog2": "\ud83d\udc15", - "question": "\u2753", - "carousel_horse": "\ud83c\udfa0", - "church": "\u26ea", - "outbox_tray": "\ud83d\udce4", - "cinema": "\ud83c\udfa6", - "flushed": "\ud83d\ude33", - "blush": "\ud83d\ude0a", - "medal": "\ud83c\udfc5", - "coffee": "\u2615", - "gun": "\ud83d\udd2b", - "city_dusk": "\ud83c\udf06", - "watermelon": "\ud83c\udf49", - "cricket_game": "\ud83c\udfcf", - "shower": "\ud83d\udebf", - "mute": "\ud83d\udd07", - "breast_feeding": "\ud83e\udd31", - "sweat_smile": "\ud83d\ude05", - "construction_worker": "\ud83d\udc77", - "cow2": "\ud83d\udc04", - "arrows_counterclockwise": "\ud83d\udd04", - "u6e80": "\ud83c\ude35", - "grinning": "\ud83d\ude00", - "globe_with_meridians": "\ud83c\udf10", - "diamond_shape_with_a_dot_inside": "\ud83d\udca0", - "deciduous_tree": "\ud83c\udf33", - "shark": "\ud83e\udd88", - "tram": "\ud83d\ude8a", - "person_rowing_boat": "\ud83d\udea3", - "chopsticks": "\ud83e\udd62", - "black_heart": "\ud83d\udda4", - "seat": "\ud83d\udcba", - "kissing": "\ud83d\ude17", - "laughing": "\ud83d\ude06", - "slight_smile": "\ud83d\ude42", - "radio": "\ud83d\udcfb", - "arrow_up_small": "\ud83d\udd3c", - "dango": "\ud83c\udf61", - "rofl": "\ud83e\udd23", - "see_no_evil": "\ud83d\ude48", - "thermometer_face": "\ud83e\udd12", - "hotdog": "\ud83c\udf2d", - "virgo": "\u264d", - "poultry_leg": "\ud83c\udf57", - "hotel": "\ud83c\udfe8", - "wolf": "\ud83d\udc3a", - "curry": "\ud83c\udf5b", - "regional_indicator_v": "\ud83c\uddfb", - "crab": "\ud83e\udd80", - "tired_face": "\ud83d\ude2b", - "place_of_worship": "\ud83d\uded0", - "ok_hand": "\ud83d\udc4c", - "speech_balloon": "\ud83d\udcac", - "sleepy": "\ud83d\ude2a", - "earth_africa": "\ud83c\udf0d", - "police_car": "\ud83d\ude93", - "small_red_triangle_down": "\ud83d\udd3b", - "bearded_person": "\ud83e\uddd4", - "curling_stone": "\ud83e\udd4c", - "scarf": "\ud83e\udde3", - "fire": "\ud83d\udd25", - "file_folder": "\ud83d\udcc1", - "zipper_mouth": "\ud83e\udd10", - "new_moon": "\ud83c\udf11", - "regional_indicator_n": "\ud83c\uddf3", - "negative_squared_cross_mark": "\u274e", - "newspaper": "\ud83d\udcf0", - "dvd": "\ud83d\udcc0", - "pear": "\ud83c\udf50", - "partly_sunny": "\u26c5", - "black_square_button": "\ud83d\udd32", - "low_brightness": "\ud83d\udd05", - "sake": "\ud83c\udf76", - "bow_and_arrow": "\ud83c\udff9", - "cooking": "\ud83c\udf73", - "fish_cake": "\ud83c\udf65", - "tomato": "\ud83c\udf45", - "couple_with_heart": "\ud83d\udc91", - "telephone_receiver": "\ud83d\udcde", - "triangular_flag_on_post": "\ud83d\udea9", - "jack_o_lantern": "\ud83c\udf83", - "blue_book": "\ud83d\udcd8", - "clock530": "\ud83d\udd60", - "u6709": "\ud83c\ude36", - "palms_up_together": "\ud83e\udd32", - "lion_face": "\ud83e\udd81", - "lock": "\ud83d\udd12", - "duck": "\ud83e\udd86", - "truck": "\ud83d\ude9a", - "oden": "\ud83c\udf62", - "busts_in_silhouette": "\ud83d\udc65", - "hourglass_flowing_sand": "\u23f3", - "frog": "\ud83d\udc38", - "fox": "\ud83e\udd8a", - "bread": "\ud83c\udf5e", - "put_litter_in_its_place": "\ud83d\udeae", - "couple": "\ud83d\udc6b", - "bamboo": "\ud83c\udf8d", - "regional_indicator_c": "\ud83c\udde8", - "menorah": "\ud83d\udd4e", - "circus_tent": "\ud83c\udfaa", - "lying_face": "\ud83e\udd25", - "small_orange_diamond": "\ud83d\udd38", - "ship": "\ud83d\udea2", - "person_frowning": "\ud83d\ude4d", - "racehorse": "\ud83d\udc0e", - "thumbsup": "\ud83d\udc4d", - "cupid": "\ud83d\udc98", - "robot": "\ud83e\udd16", - "fallen_leaf": "\ud83c\udf42", - "pig_nose": "\ud83d\udc3d", - "vibration_mode": "\ud83d\udcf3", - "necktie": "\ud83d\udc54", - "boy": "\ud83d\udc66", - "house_with_garden": "\ud83c\udfe1", - "point_down": "\ud83d\udc47", - "grey_exclamation": "\u2755", - "books": "\ud83d\udcda", - "regional_indicator_k": "\ud83c\uddf0", - "shirt": "\ud83d\udc55", - "fries": "\ud83c\udf5f", - "dart": "\ud83c\udfaf", - "tea": "\ud83c\udf75", - "mrs_claus": "\ud83e\udd36", - "suspension_railway": "\ud83d\ude9f", - "baby_symbol": "\ud83d\udebc", - "sweet_potato": "\ud83c\udf60", - "butterfly": "\ud83e\udd8b", - "performing_arts": "\ud83c\udfad", - "notebook": "\ud83d\udcd3", - "bat": "\ud83e\udd87" -} + "100": "💯", + "1234": "🔢", + "1st_place_medal": "🥇", + "2nd_place_medal": "🥈", + "3rd_place_medal": "🥉", + "8ball": "🎱", + "a_button_blood_type": "🅰", + "ab": "🆎", + "abacus": "🧮", + "abc": "🔤", + "abcd": "🔡", + "accept": "🉑", + "adhesive_bandage": "🩹", + "admission_tickets": "🎟", + "adult": "🧑", + "aerial_tramway": "🚡", + "airplane": "✈", + "airplane_arriving": "🛬", + "airplane_departure": "🛫", + "alarm_clock": "⏰", + "alembic": "⚗️", + "alien": "👽", + "ambulance": "🚑", + "amphora": "🏺", + "anchor": "⚓", + "angel": "👼", + "anger": "💢", + "anger_right": "🗯", + "angry": "😠", + "anguished": "😧", + "ant": "🐜", + "apple": "🍎", + "aquarius": "♒", + "aries": "♈", + "arrow_backward": "◀️", + "arrow_double_down": "⏬", + "arrow_double_up": "⏫", + "arrow_down": "⬇️", + "arrow_down_small": "🔽", + "arrow_forward": "▶️", + "arrow_heading_down": "⤵️", + "arrow_heading_up": "⤴️", + "arrow_left": "⬅️", + "arrow_lower_left": "↙️", + "arrow_lower_right": "↘️", + "arrow_right": "➡", + "arrow_right_hook": "↪️", + "arrow_up": "⬆️", + "arrow_up_down": "↕", + "arrow_up_small": "🔼", + "arrow_upper_left": "↖", + "arrow_upper_right": "↗️", + "arrows_clockwise": "🔃", + "arrows_counterclockwise": "🔄", + "art": "🎨", + "articulated_lorry": "🚛", + "artist_palette": "🎨", + "asterisk": "*⃣", + "astonished": "😲", + "athletic_shoe": "👟", + "atm": "🏧", + "atom": "⚛", + "atom_symbol": "⚛️", + "auto_rickshaw": "🛺", + "automobile": "🚗", + "avocado": "🥑", + "axe": "🪓", + "b_button_blood_type": "🅱", + "baby": "👶", + "baby_bottle": "🍼", + "baby_chick": "🐤", + "baby_symbol": "🚼", + "back": "🔙", + "bacon": "🥓", + "badger": "🦡", + "badminton": "🏸", + "bagel": "🥯", + "baggage_claim": "🛄", + "baguette_bread": "🥖", + "balance_scale": "⚖️", + "bald": "🦲", + "ballet_shoes": "🩰", + "balloon": "🎈", + "ballot_box": "🗳", + "ballot_box_with_check": "☑️", + "bamboo": "🎍", + "banana": "🍌", + "bangbang": "‼️", + "banjo": "🪕", + "bank": "🏦", + "bar_chart": "📊", + "barber": "💈", + "baseball": "⚾", + "basket": "🧺", + "basketball": "🏀", + "basketballer": "⛹", + "bat": "🦇", + "bath": "🛀", + "bathtub": "🛁", + "battery": "🔋", + "beach_umbrella": "⛱", + "beach_with_umbrella": "🏖", + "bear": "🐻", + "beard": "🧔", + "bearded_person": "🧔", + "bed": "🛏", + "bee": "🐝", + "beer": "🍺", + "beers": "🍻", + "beetle": "🐞", + "beginner": "🔰", + "bell": "🔔", + "bellhop_bell": "🛎", + "bento": "🍱", + "beverage_box": "🧃", + "bicyclist": "🚴", + "bike": "🚲", + "bikini": "👙", + "billed_cap": "🧢", + "biohazard": "☣️", + "bird": "🐦", + "birthday": "🎂", + "black_circle": "⚫", + "black_heart": "🖤", + "black_joker": "🃏", + "black_large_square": "⬛", + "black_medium_small_square": "◾", + "black_medium_square": "◼", + "black_nib": "✒️", + "black_small_square": "▪", + "black_square_button": "🔲", + "blond_haired_person": "👱", + "blossom": "🌼", + "blowfish": "🐡", + "blue_book": "📘", + "blue_car": "🚙", + "blue_circle": "🔵", + "blue_heart": "💙", + "blue_square": "🟦", + "blush": "😊", + "boar": "🐗", + "bomb": "💣", + "bone": "🦴", + "book": "📖", + "bookmark": "🔖", + "bookmark_tabs": "📑", + "books": "📚", + "boom": "💥", + "boot": "👢", + "bouquet": "💐", + "bow": "🙇", + "bow_and_arrow": "🏹", + "bowl_with_spoon": "🥣", + "bowling": "🎳", + "boxing_glove": "🥊", + "boy": "👦", + "brain": "🧠", + "bread": "🍞", + "breast_feeding": "🤱", + "breastfeeding": "🤱", + "brick": "🧱", + "bride_with_veil": "👰", + "bridge_at_night": "🌉", + "briefcase": "💼", + "briefs": "🩲", + "broccoli": "🥦", + "broken_heart": "💔", + "broom": "🧹", + "brown_circle": "🟤", + "brown_heart": "🤎", + "bug": "🐛", + "building_construction": "🏗", + "bulb": "💡", + "bullettrain_front": "🚅", + "bullettrain_side": "🚄", + "burrito": "🌯", + "bus": "🚌", + "busstop": "🚏", + "bust_in_silhouette": "👤", + "busts_in_silhouette": "👥", + "butter": "🧈", + "butterfly": "🦋", + "cactus": "🌵", + "cake": "🍰", + "calendar": "📆", + "call_me": "🤙", + "call_me_hand": "🤙", + "calling": "📲", + "camel": "🐫", + "camera": "📷", + "camera_with_flash": "📸", + "camping": "🏕", + "cancer": "♋", + "candle": "🕯", + "candy": "🍬", + "canned_food": "🥫", + "canoe": "🛶", + "capital_abcd": "🔠", + "capricorn": "♑", + "card_file_box": "🗃", + "card_index": "📇", + "card_index_dividers": "🗂", + "carousel_horse": "🎠", + "carrot": "🥕", + "cat": "🐱", + "cat2": "🐈", + "cd": "💿", + "chains": "⛓️", + "chair": "🪑", + "champagne": "🍾", + "champagne_glass": "🥂", + "chart": "💹", + "chart_with_downwards_trend": "📉", + "chart_with_upwards_trend": "📈", + "check_box_with_check": "☑", + "check_mark": "✔", + "checkered_flag": "🏁", + "cheese": "🧀", + "cheese_wedge": "🧀", + "cherries": "🍒", + "cherry_blossom": "🌸", + "chess_pawn": "♟", + "chestnut": "🌰", + "chicken": "🐔", + "child": "🧒", + "children_crossing": "🚸", + "chipmunk": "🐿", + "chocolate_bar": "🍫", + "chopsticks": "🥢", + "christmas_tree": "🎄", + "church": "⛪", + "cinema": "🎦", + "circled_m": "Ⓜ", + "circus_tent": "🎪", + "city_dusk": "🌆", + "city_sunset": "🌇", + "cityscape": "🏙", + "cityscape_at_dusk": "🌆", + "cl": "🆑", + "clap": "👏", + "clapper": "🎬", + "classical_building": "🏛", + "clinking_glasses": "🥂", + "clipboard": "📋", + "clock1": "🕐", + "clock10": "🕙", + "clock1030": "🕥", + "clock11": "🕚", + "clock1130": "🕦", + "clock12": "🕛", + "clock1230": "🕧", + "clock130": "🕜", + "clock2": "🕑", + "clock230": "🕝", + "clock3": "🕒", + "clock330": "🕞", + "clock4": "🕓", + "clock430": "🕟", + "clock5": "🕔", + "clock530": "🕠", + "clock6": "🕕", + "clock630": "🕡", + "clock7": "🕖", + "clock730": "🕢", + "clock8": "🕗", + "clock830": "🕣", + "clock9": "🕘", + "clock930": "🕤", + "closed_book": "📕", + "closed_lock_with_key": "🔐", + "closed_umbrella": "🌂", + "cloud": "☁️", + "cloud_with_lightning": "🌩", + "cloud_with_lightning_and_rain": "⛈️", + "cloud_with_rain": "🌧", + "cloud_with_snow": "🌨", + "clown": "🤡", + "clown_face": "🤡", + "club_suit": "♣️", + "clubs": "♣", + "coat": "🧥", + "cocktail": "🍸", + "coconut": "🥥", + "coffee": "☕", + "coffin": "⚰️", + "cold_face": "🥶", + "cold_sweat": "😰", + "comet": "☄️", + "compass": "🧭", + "compression": "🗜", + "computer": "💻", + "computer_mouse": "🖱", + "confetti_ball": "🎊", + "confounded": "😖", + "confused": "😕", + "congratulations": "㊗", + "construction": "🚧", + "construction_worker": "👷", + "control_knobs": "🎛", + "convenience_store": "🏪", + "cookie": "🍪", + "cooking": "🍳", + "cool": "🆒", + "cop": "👮", + "copyright": "©", + "corn": "🌽", + "couch_and_lamp": "🛋", + "couple": "👫", + "couple_with_heart": "💑", + "couplekiss": "💏", + "cow": "🐮", + "cow2": "🐄", + "cowboy": "🤠", + "cowboy_hat_face": "🤠", + "crab": "🦀", + "crayon": "🖍", + "crazy_face": "🤪", + "credit_card": "💳", + "crescent_moon": "🌙", + "cricket": "🦗", + "cricket_game": "🏏", + "crocodile": "🐊", + "croissant": "🥐", + "cross": "✝️", + "crossed_fingers": "🤞", + "crossed_flags": "🎌", + "crossed_swords": "⚔️", + "crown": "👑", + "cry": "😢", + "crying_cat_face": "😿", + "crystal_ball": "🔮", + "cucumber": "🥒", + "cup_with_straw": "🥤", + "cupcake": "🧁", + "cupid": "💘", + "curling_stone": "🥌", + "curly_hair": "🦱", + "curly_loop": "➰", + "currency_exchange": "💱", + "curry": "🍛", + "custard": "🍮", + "customs": "🛃", + "cut_of_meat": "🥩", + "cyclone": "🌀", + "dagger": "🗡", + "dancer": "💃", + "dancers": "👯", + "dango": "🍡", + "dark_skin_tone": "🏿", + "dark_sunglasses": "🕶", + "dart": "🎯", + "dash": "💨", + "date": "📅", + "deaf_person": "🧏", + "deciduous_tree": "🌳", + "deer": "🦌", + "department_store": "🏬", + "derelict_house": "🏚", + "desert": "🏜", + "desert_island": "🏝", + "desktop_computer": "🖥", + "detective": "🕵", + "diamond_shape_with_a_dot_inside": "💠", + "diamond_suit": "♦️", + "diamonds": "♦", + "disappointed": "😞", + "disappointed_relieved": "😥", + "diving_mask": "🤿", + "diya_lamp": "🪔", + "dizzy": "💫", + "dizzy_face": "😵", + "dna": "🧬", + "do_not_litter": "🚯", + "dog": "🐶", + "dog2": "🐕", + "dollar": "💵", + "dolls": "🎎", + "dolphin": "🐬", + "door": "🚪", + "double_exclamation_mark": "‼", + "doughnut": "🍩", + "dove": "🕊", + "down_arrow": "⬇", + "downleft_arrow": "↙", + "downright_arrow": "↘", + "dragon": "🐉", + "dragon_face": "🐲", + "dress": "👗", + "dromedary_camel": "🐪", + "drooling_face": "🤤", + "drop_of_blood": "🩸", + "droplet": "💧", + "drum": "🥁", + "duck": "🦆", + "dumpling": "🥟", + "dvd": "📀", + "e-mail": "📧", + "eagle": "🦅", + "ear": "👂", + "ear_of_rice": "🌾", + "ear_with_hearing_aid": "🦻", + "earth_africa": "🌍", + "earth_americas": "🌎", + "earth_asia": "🌏", + "egg": "🥚", + "eggplant": "🍆", + "eight": "8⃣", + "eight_pointed_black_star": "✴️", + "eight_spoked_asterisk": "✳️", + "eightpointed_star": "✴", + "eightspoked_asterisk": "✳", + "eject_button": "⏏", + "electric_plug": "🔌", + "elephant": "🐘", + "elf": "🧝", + "end": "🔚", + "envelope": "✉", + "envelope_with_arrow": "📩", + "euro": "💶", + "european_castle": "🏰", + "european_post_office": "🏤", + "evergreen_tree": "🌲", + "exclamation": "❗", + "exclamation_question_mark": "⁉", + "exploding_head": "🤯", + "expressionless": "😑", + "eye": "👁", + "eyeglasses": "👓", + "eyes": "👀", + "face_vomiting": "🤮", + "face_with_hand_over_mouth": "🤭", + "face_with_headbandage": "🤕", + "face_with_monocle": "🧐", + "face_with_raised_eyebrow": "🤨", + "face_with_symbols_on_mouth": "🤬", + "face_with_symbols_over_mouth": "🤬", + "face_with_thermometer": "🤒", + "factory": "🏭", + "fairy": "🧚", + "falafel": "🧆", + "fallen_leaf": "🍂", + "family": "👪", + "fast_forward": "⏩", + "fax": "📠", + "fearful": "😨", + "feet": "🐾", + "female_sign": "♀", + "ferris_wheel": "🎡", + "ferry": "⛴️", + "field_hockey": "🏑", + "file_cabinet": "🗄", + "file_folder": "📁", + "film_frames": "🎞", + "film_projector": "📽", + "fingers_crossed": "🤞", + "fire": "🔥", + "fire_engine": "🚒", + "fire_extinguisher": "🧯", + "firecracker": "🧨", + "fireworks": "🎆", + "first_place": "🥇", + "first_quarter_moon": "🌓", + "first_quarter_moon_with_face": "🌛", + "fish": "🐟", + "fish_cake": "🍥", + "fishing_pole_and_fish": "🎣", + "fist": "✊", + "five": "5⃣", + "flag_black": "🏴", + "flag_white": "🏳", + "flags": "🎏", + "flamingo": "🦩", + "flashlight": "🔦", + "flat_shoe": "🥿", + "fleur-de-lis": "⚜", + "fleurde-lis": "⚜️", + "floppy_disk": "💾", + "flower_playing_cards": "🎴", + "flushed": "😳", + "flying_disc": "🥏", + "flying_saucer": "🛸", + "fog": "🌫", + "foggy": "🌁", + "foot": "🦶", + "football": "🏈", + "footprints": "👣", + "fork_and_knife": "🍴", + "fork_and_knife_with_plate": "🍽", + "fortune_cookie": "🥠", + "fountain": "⛲", + "fountain_pen": "🖋", + "four": "4⃣", + "four_leaf_clover": "🍀", + "fox": "🦊", + "framed_picture": "🖼", + "free": "🆓", + "french_bread": "🥖", + "fried_shrimp": "🍤", + "fries": "🍟", + "frog": "🐸", + "frowning": "😦", + "frowning_face": "☹️", + "fuelpump": "⛽", + "full_moon": "🌕", + "full_moon_with_face": "🌝", + "funeral_urn": "⚱️", + "game_die": "🎲", + "garlic": "🧄", + "gear": "⚙️", + "gem": "💎", + "gemini": "♊", + "genie": "🧞", + "ghost": "👻", + "gift": "🎁", + "gift_heart": "💝", + "giraffe": "🦒", + "girl": "👧", + "glass_of_milk": "🥛", + "globe_with_meridians": "🌐", + "gloves": "🧤", + "goal": "🥅", + "goal_net": "🥅", + "goat": "🐐", + "goggles": "🥽", + "golf": "⛳", + "golfer": "🏌", + "gorilla": "🦍", + "grapes": "🍇", + "green_apple": "🍏", + "green_book": "📗", + "green_circle": "🟢", + "green_heart": "💚", + "green_salad": "🥗", + "green_square": "🟩", + "grey_exclamation": "❕", + "grey_question": "❔", + "grimacing": "😬", + "grin": "😁", + "grinning": "😀", + "guard": "💂", + "guardsman": "💂", + "guide_dog": "🦮", + "guitar": "🎸", + "gun": "🔫", + "haircut": "💇", + "hamburger": "🍔", + "hammer": "🔨", + "hammer_and_pick": "⚒️", + "hammer_and_wrench": "🛠", + "hamster": "🐹", + "hand_with_fingers_splayed": "🖐", + "handbag": "👜", + "handshake": "🤝", + "hash": "#⃣", + "hatched_chick": "🐥", + "hatching_chick": "🐣", + "head_bandage": "🤕", + "headphones": "🎧", + "hear_no_evil": "🙉", + "heart": "❤️", + "heart_decoration": "💟", + "heart_exclamation": "❣", + "heart_eyes": "😍", + "heart_eyes_cat": "😻", + "heart_suit": "♥️", + "heartbeat": "💓", + "heartpulse": "💗", + "hearts": "♥", + "heavy_check_mark": "✔️", + "heavy_division_sign": "➗", + "heavy_dollar_sign": "💲", + "heavy_minus_sign": "➖", + "heavy_multiplication_x": "✖️", + "heavy_plus_sign": "➕", + "hedgehog": "🦔", + "helicopter": "🚁", + "herb": "🌿", + "hibiscus": "🌺", + "high_brightness": "🔆", + "high_heel": "👠", + "hiking_boot": "🥾", + "hindu_temple": "🛕", + "hippopotamus": "🦛", + "hockey": "🏒", + "hole": "🕳", + "honey_pot": "🍯", + "horse": "🐴", + "horse_racing": "🏇", + "hospital": "🏥", + "hot_face": "🥵", + "hot_pepper": "🌶", + "hot_springs": "♨", + "hotdog": "🌭", + "hotel": "🏨", + "hotsprings": "♨️", + "hourglass": "⌛", + "hourglass_flowing_sand": "⏳", + "house": "🏠", + "house_with_garden": "🏡", + "houses": "🏘", + "hugging": "🤗", + "hundred_points": "💯", + "hushed": "😯", + "ice": "🧊", + "ice_cream": "🍨", + "ice_hockey": "🏒", + "ice_skate": "⛸️", + "icecream": "🍦", + "id": "🆔", + "ideograph_advantage": "🉐", + "imp": "👿", + "inbox_tray": "📥", + "incoming_envelope": "📨", + "index_pointing_up": "☝", + "infinity": "♾", + "information": "ℹ️", + "information_desk_person": "💁", + "information_source": "ℹ", + "innocent": "😇", + "input_numbers": "🔢", + "interrobang": "⁉️", + "iphone": "📱", + "izakaya_lantern": "🏮", + "jack_o_lantern": "🎃", + "japan": "🗾", + "japanese_castle": "🏯", + "japanese_congratulations_button": "㊗️", + "japanese_free_of_charge_button": "🈚", + "japanese_goblin": "👺", + "japanese_ogre": "👹", + "japanese_reserved_button": "🈯", + "japanese_secret_button": "㊙️", + "japanese_service_charge_button": "🈂", + "jeans": "👖", + "joy": "😂", + "joy_cat": "😹", + "joystick": "🕹", + "kaaba": "🕋", + "kangaroo": "🦘", + "key": "🔑", + "keyboard": "⌨️", + "keycap_ten": "🔟", + "kick_scooter": "🛴", + "kimono": "👘", + "kiss": "💋", + "kissing": "😗", + "kissing_cat": "😽", + "kissing_closed_eyes": "😚", + "kissing_heart": "😘", + "kissing_smiling_eyes": "😙", + "kitchen_knife": "🔪", + "kite": "🪁", + "kiwi": "🥝", + "kiwi_fruit": "🥝", + "knife": "🔪", + "koala": "🐨", + "koko": "🈁", + "lab_coat": "🥼", + "label": "🏷", + "lacrosse": "🥍", + "large_blue_diamond": "🔷", + "large_orange_diamond": "🔶", + "last_quarter_moon": "🌗", + "last_quarter_moon_with_face": "🌜", + "last_track_button": "⏮️", + "latin_cross": "✝", + "laughing": "😆", + "leafy_green": "🥬", + "leaves": "🍃", + "ledger": "📒", + "left_arrow": "⬅", + "left_arrow_curving_right": "↪", + "left_facing_fist": "🤛", + "left_luggage": "🛅", + "left_right_arrow": "↔", + "leftfacing_fist": "🤛", + "leftright_arrow": "↔️", + "leftwards_arrow_with_hook": "↩️", + "leg": "🦵", + "lemon": "🍋", + "leo": "♌", + "leopard": "🐆", + "level_slider": "🎚", + "libra": "♎", + "light_rail": "🚈", + "light_skin_tone": "🏻", + "link": "🔗", + "linked_paperclips": "🖇", + "lion_face": "🦁", + "lips": "👄", + "lipstick": "💄", + "lizard": "🦎", + "llama": "🦙", + "lobster": "🦞", + "lock": "🔒", + "lock_with_ink_pen": "🔏", + "lollipop": "🍭", + "loop": "➿", + "lotion_bottle": "🧴", + "loud_sound": "🔊", + "loudspeaker": "📢", + "love_hotel": "🏩", + "love_letter": "💌", + "love_you_gesture": "🤟", + "loveyou_gesture": "🤟", + "low_brightness": "🔅", + "luggage": "🧳", + "lying_face": "🤥", + "m": "Ⓜ️", + "mag": "🔍", + "mag_right": "🔎", + "mage": "🧙", + "magnet": "🧲", + "mahjong": "🀄", + "mailbox": "📫", + "mailbox_closed": "📪", + "mailbox_with_mail": "📬", + "mailbox_with_no_mail": "📭", + "male_sign": "♂", + "man": "👨", + "man_dancing": "🕺", + "man_in_suit": "🕴", + "man_in_tuxedo": "🤵", + "man_with_chinese_cap": "👲", + "man_with_gua_pi_mao": "👲", + "man_with_turban": "👳", + "mango": "🥭", + "mans_shoe": "👞", + "mantelpiece_clock": "🕰", + "manual_wheelchair": "🦽", + "maple_leaf": "🍁", + "martial_arts_uniform": "🥋", + "mask": "😷", + "massage": "💆", + "mate": "🧉", + "meat_on_bone": "🍖", + "mechanical_arm": "🦾", + "mechanical_leg": "🦿", + "medal": "🏅", + "medical_symbol": "⚕", + "medium_skin_tone": "🏽", + "mediumdark_skin_tone": "🏾", + "mediumlight_skin_tone": "🏼", + "mega": "📣", + "melon": "🍈", + "memo": "📝", + "menorah": "🕎", + "mens": "🚹", + "merperson": "🧜", + "metal": "🤘", + "metro": "🚇", + "microbe": "🦠", + "microphone": "🎤", + "microscope": "🔬", + "middle_finger": "🖕", + "military_medal": "🎖", + "milk": "🥛", + "milky_way": "🌌", + "minibus": "🚐", + "minidisc": "💽", + "mobile_phone_off": "📴", + "money_mouth": "🤑", + "money_with_wings": "💸", + "moneybag": "💰", + "moneymouth_face": "🤑", + "monkey": "🐒", + "monkey_face": "🐵", + "monorail": "🚝", + "moon_cake": "🥮", + "mortar_board": "🎓", + "mosque": "🕌", + "mosquito": "🦟", + "motor_boat": "🛥", + "motor_scooter": "🛵", + "motorcycle": "🏍", + "motorized_wheelchair": "🦼", + "motorway": "🛣", + "mount_fuji": "🗻", + "mountain": "⛰️", + "mountain_bicyclist": "🚵", + "mountain_cableway": "🚠", + "mountain_railway": "🚞", + "mouse": "🐭", + "mouse2": "🐁", + "movie_camera": "🎥", + "moyai": "🗿", + "mrs_claus": "🤶", + "multiplication_sign": "✖", + "muscle": "💪", + "mushroom": "🍄", + "musical_keyboard": "🎹", + "musical_note": "🎵", + "musical_score": "🎼", + "mute": "🔇", + "nail_care": "💅", + "name_badge": "📛", + "national_park": "🏞", + "nauseated_face": "🤢", + "nazar_amulet": "🧿", + "necktie": "👔", + "negative_squared_cross_mark": "❎", + "nerd": "🤓", + "neutral_face": "😐", + "new": "🆕", + "new_moon": "🌑", + "new_moon_with_face": "🌚", + "newspaper": "📰", + "next_track_button": "⏭️", + "ng": "🆖", + "night_with_stars": "🌃", + "nine": "9⃣", + "no_bell": "🔕", + "no_bicycles": "🚳", + "no_entry": "⛔", + "no_entry_sign": "🚫", + "no_good": "🙅", + "no_mobile_phones": "📵", + "no_mouth": "😶", + "no_pedestrians": "🚷", + "no_smoking": "🚭", + "non-potable_water": "🚱", + "nose": "👃", + "notebook": "📓", + "notebook_with_decorative_cover": "📔", + "notes": "🎶", + "nut_and_bolt": "🔩", + "o": "⭕", + "o_button_blood_type": "🅾", + "ocean": "🌊", + "octagonal_sign": "🛑", + "octopus": "🐙", + "oden": "🍢", + "office": "🏢", + "oil_drum": "🛢", + "ok": "🆗", + "ok_hand": "👌", + "ok_woman": "🙆", + "old_key": "🗝", + "older_adult": "🧓", + "older_man": "👴", + "older_person": "🧓", + "older_woman": "👵", + "om_symbol": "🕉", + "on": "🔛", + "oncoming_automobile": "🚘", + "oncoming_bus": "🚍", + "oncoming_fist": "👊", + "oncoming_police_car": "🚔", + "oncoming_taxi": "🚖", + "one": "1⃣", + "onepiece_swimsuit": "🩱", + "onion": "🧅", + "open_file_folder": "📂", + "open_hands": "👐", + "open_mouth": "😮", + "ophiuchus": "⛎", + "orange_book": "📙", + "orange_circle": "🟠", + "orange_heart": "🧡", + "orange_square": "🟧", + "orangutan": "🦧", + "orthodox_cross": "☦️", + "otter": "🦦", + "outbox_tray": "📤", + "owl": "🦉", + "ox": "🐂", + "oyster": "🦪", + "p_button": "🅿", + "package": "📦", + "page_facing_up": "📄", + "page_with_curl": "📃", + "pager": "📟", + "paintbrush": "🖌", + "palm_tree": "🌴", + "palms_up_together": "🤲", + "pancakes": "🥞", + "panda_face": "🐼", + "paperclip": "📎", + "parachute": "🪂", + "parrot": "🦜", + "part_alternation_mark": "〽", + "partly_sunny": "⛅", + "partying_face": "🥳", + "passenger_ship": "🛳", + "passport_control": "🛂", + "pause_button": "⏸️", + "peace": "☮", + "peace_symbol": "☮️", + "peach": "🍑", + "peacock": "🦚", + "peanuts": "🥜", + "pear": "🍐", + "pen": "🖊", + "pencil": "📝", + "pencil2": "✏", + "penguin": "🐧", + "pensive": "😔", + "people_with_bunny_ears_partying": "👯", + "people_wrestling": "🤼", + "performing_arts": "🎭", + "persevere": "😣", + "person": "🧑", + "person_biking": "🚴", + "person_bouncing_ball": "⛹️", + "person_bowing": "🙇", + "person_cartwheeling": "🤸", + "person_climbing": "🧗", + "person_doing_cartwheel": "🤸", + "person_facepalming": "🤦", + "person_fencing": "🤺", + "person_frowning": "🙍", + "person_gesturing_no": "🙅", + "person_gesturing_ok": "🙆", + "person_getting_haircut": "💇", + "person_getting_massage": "💆", + "person_in_lotus_position": "🧘", + "person_in_steamy_room": "🧖", + "person_juggling": "🤹", + "person_kneeling": "🧎", + "person_mountain_biking": "🚵", + "person_playing_handball": "🤾", + "person_playing_water_polo": "🤽", + "person_pouting": "🙎", + "person_raising_hand": "🙋", + "person_rowing_boat": "🚣", + "person_running": "🏃", + "person_shrugging": "🤷", + "person_standing": "🧍", + "person_surfing": "🏄", + "person_swimming": "🏊", + "person_tipping_hand": "💁", + "person_walking": "🚶", + "person_wearing_turban": "👳", + "person_with_blond_hair": "👱", + "person_with_pouting_face": "🙎", + "petri_dish": "🧫", + "pick": "⛏️", + "pie": "🥧", + "pig": "🐷", + "pig2": "🐖", + "pig_nose": "🐽", + "pill": "💊", + "pinching_hand": "🤏", + "pineapple": "🍍", + "ping_pong": "🏓", + "pisces": "♓", + "pizza": "🍕", + "place_of_worship": "🛐", + "play_button": "▶", + "play_or_pause_button": "⏯️", + "play_pause": "⏯", + "pleading_face": "🥺", + "point_down": "👇", + "point_left": "👈", + "point_right": "👉", + "point_up": "☝️", + "point_up_2": "👆", + "police_car": "🚓", + "police_officer": "👮", + "poodle": "🐩", + "poop": "💩", + "popcorn": "🍿", + "post_office": "🏣", + "postal_horn": "📯", + "postbox": "📮", + "potable_water": "🚰", + "potato": "🥔", + "pouch": "👝", + "poultry_leg": "🍗", + "pound": "💷", + "pouting_cat": "😾", + "pray": "🙏", + "prayer_beads": "📿", + "pregnant_woman": "🤰", + "pretzel": "🥨", + "prince": "🤴", + "princess": "👸", + "printer": "🖨", + "probing_cane": "🦯", + "punch": "👊", + "purple_circle": "🟣", + "purple_heart": "💜", + "purse": "👛", + "pushpin": "📌", + "put_litter_in_its_place": "🚮", + "puzzle_piece": "🧩", + "question": "❓", + "rabbit": "🐰", + "rabbit2": "🐇", + "raccoon": "🦝", + "racehorse": "🐎", + "racing_car": "🏎", + "radio": "📻", + "radio_button": "🔘", + "radioactive": "☢️", + "rage": "😡", + "railway_car": "🚃", + "railway_track": "🛤", + "rainbow": "🌈", + "raised_back_of_hand": "🤚", + "raised_hand": "✋", + "raised_hands": "🙌", + "raising_hand": "🙋", + "ram": "🐏", + "ramen": "🍜", + "rat": "🐀", + "razor": "🪒", + "receipt": "🧾", + "record_button": "⏺️", + "recycle": "♻", + "recycling_symbol": "♻️", + "red_car": "🚗", + "red_circle": "🔴", + "red_envelope": "🧧", + "red_hair": "🦰", + "red_heart": "❤", + "red_square": "🟥", + "regional_indicator_a": "🇦", + "regional_indicator_b": "🇧", + "regional_indicator_c": "🇨", + "regional_indicator_d": "🇩", + "regional_indicator_e": "🇪", + "regional_indicator_f": "🇫", + "regional_indicator_g": "🇬", + "regional_indicator_h": "🇭", + "regional_indicator_i": "🇮", + "regional_indicator_j": "🇯", + "regional_indicator_k": "🇰", + "regional_indicator_l": "🇱", + "regional_indicator_m": "🇲", + "regional_indicator_n": "🇳", + "regional_indicator_o": "🇴", + "regional_indicator_p": "🇵", + "regional_indicator_q": "🇶", + "regional_indicator_r": "🇷", + "regional_indicator_s": "🇸", + "regional_indicator_t": "🇹", + "regional_indicator_u": "🇺", + "regional_indicator_v": "🇻", + "regional_indicator_w": "🇼", + "regional_indicator_x": "🇽", + "regional_indicator_y": "🇾", + "regional_indicator_z": "🇿", + "registered": "®", + "relieved": "😌", + "reminder_ribbon": "🎗", + "repeat": "🔁", + "repeat_one": "🔂", + "rescue_worker’s_helmet": "⛑️", + "restroom": "🚻", + "reverse_button": "◀", + "revolving_hearts": "💞", + "rewind": "⏪", + "rhino": "🦏", + "rhinoceros": "🦏", + "ribbon": "🎀", + "rice": "🍚", + "rice_ball": "🍙", + "rice_cracker": "🍘", + "rice_scene": "🎑", + "right_arrow": "➡️", + "right_arrow_curving_down": "⤵", + "right_arrow_curving_left": "↩", + "right_arrow_curving_up": "⤴", + "right_facing_fist": "🤜", + "rightfacing_fist": "🤜", + "ring": "💍", + "ringed_planet": "🪐", + "robot": "🤖", + "rocket": "🚀", + "rofl": "🤣", + "roll_of_paper": "🧻", + "rolledup_newspaper": "🗞", + "roller_coaster": "🎢", + "rolling_eyes": "🙄", + "rolling_on_the_floor_laughing": "🤣", + "rooster": "🐓", + "rose": "🌹", + "rosette": "🏵", + "rotating_light": "🚨", + "round_pushpin": "📍", + "rowboat": "🚣", + "rugby_football": "🏉", + "runner": "🏃", + "running_shirt_with_sash": "🎽", + "safety_pin": "🧷", + "safety_vest": "🦺", + "sagittarius": "♐", + "sailboat": "⛵", + "sake": "🍶", + "salad": "🥗", + "salt": "🧂", + "sandal": "👡", + "sandwich": "🥪", + "santa": "🎅", + "sari": "🥻", + "satellite": "📡", + "sauropod": "🦕", + "saxophone": "🎷", + "scales": "⚖", + "scarf": "🧣", + "school": "🏫", + "school_satchel": "🎒", + "scissors": "✂", + "scooter": "🛴", + "scorpion": "🦂", + "scorpius": "♏", + "scream": "😱", + "scream_cat": "🙀", + "scroll": "📜", + "seat": "💺", + "second_place": "🥈", + "secret": "㊙", + "see_no_evil": "🙈", + "seedling": "🌱", + "selfie": "🤳", + "seven": "7⃣", + "shallow_pan_of_food": "🥘", + "shamrock": "☘️", + "shark": "🦈", + "shaved_ice": "🍧", + "sheep": "🐑", + "shell": "🐚", + "shield": "🛡", + "shinto_shrine": "⛩️", + "ship": "🚢", + "shirt": "👕", + "shopping_bags": "🛍", + "shopping_cart": "🛒", + "shorts": "🩳", + "shower": "🚿", + "shrimp": "🦐", + "shushing_face": "🤫", + "sign_of_the_horns": "🤘", + "signal_strength": "📶", + "six": "6⃣", + "six_pointed_star": "🔯", + "skateboard": "🛹", + "ski": "🎿", + "skier": "⛷️", + "skull": "💀", + "skull_and_crossbones": "☠️", + "skull_crossbones": "☠", + "skunk": "🦨", + "sled": "🛷", + "sleeping": "😴", + "sleeping_accommodation": "🛌", + "sleepy": "😪", + "slight_frown": "🙁", + "slight_smile": "🙂", + "slightly_frowning_face": "🙁", + "slot_machine": "🎰", + "sloth": "🦥", + "small_airplane": "🛩", + "small_blue_diamond": "🔹", + "small_orange_diamond": "🔸", + "small_red_triangle": "🔺", + "small_red_triangle_down": "🔻", + "smile": "😄", + "smile_cat": "😸", + "smiley": "😃", + "smiley_cat": "😺", + "smiling": "☺️", + "smiling_face": "☺", + "smiling_face_with_hearts": "🥰", + "smiling_imp": "😈", + "smirk": "😏", + "smirk_cat": "😼", + "smoking": "🚬", + "snail": "🐌", + "snake": "🐍", + "sneezing_face": "🤧", + "snowboarder": "🏂", + "snowcapped_mountain": "🏔", + "snowflake": "❄", + "snowman": "⛄", + "soap": "🧼", + "sob": "😭", + "soccer": "⚽", + "socks": "🧦", + "softball": "🥎", + "soon": "🔜", + "sos": "🆘", + "sound": "🔉", + "space_invader": "👾", + "spade_suit": "♠️", + "spades": "♠", + "spaghetti": "🍝", + "sparkle": "❇", + "sparkler": "🎇", + "sparkles": "✨", + "sparkling_heart": "💖", + "speak_no_evil": "🙊", + "speaker": "🔈", + "speaking_head": "🗣", + "speech_balloon": "💬", + "speech_left": "🗨", + "speedboat": "🚤", + "spider": "🕷", + "spider_web": "🕸", + "spiral_calendar": "🗓", + "spiral_notepad": "🗒", + "sponge": "🧽", + "spoon": "🥄", + "squid": "🦑", + "stadium": "🏟", + "star": "⭐", + "star2": "🌟", + "star_and_crescent": "☪️", + "star_of_david": "✡", + "star_struck": "🤩", + "stars": "🌠", + "starstruck": "🤩", + "station": "🚉", + "statue_of_liberty": "🗽", + "steam_locomotive": "🚂", + "stethoscope": "🩺", + "stew": "🍲", + "stop_button": "⏹️", + "stopwatch": "⏱️", + "straight_ruler": "📏", + "strawberry": "🍓", + "stuck_out_tongue": "😛", + "stuck_out_tongue_closed_eyes": "😝", + "stuck_out_tongue_winking_eye": "😜", + "studio_microphone": "🎙", + "stuffed_flatbread": "🥙", + "sun": "☀", + "sun_behind_large_cloud": "🌥", + "sun_behind_rain_cloud": "🌦", + "sun_behind_small_cloud": "🌤", + "sun_with_face": "🌞", + "sunflower": "🌻", + "sunglasses": "😎", + "sunny": "☀️", + "sunrise": "🌅", + "sunrise_over_mountains": "🌄", + "superhero": "🦸", + "supervillain": "🦹", + "surfer": "🏄", + "sushi": "🍣", + "suspension_railway": "🚟", + "swan": "🦢", + "sweat": "😓", + "sweat_drops": "💦", + "sweat_smile": "😅", + "sweet_potato": "🍠", + "swimmer": "🏊", + "symbols": "🔣", + "synagogue": "🕍", + "syringe": "💉", + "t_rex": "🦖", + "taco": "🌮", + "tada": "🎉", + "takeout_box": "🥡", + "tanabata_tree": "🎋", + "tangerine": "🍊", + "taurus": "♉", + "taxi": "🚕", + "tea": "🍵", + "teddy_bear": "🧸", + "telephone": "☎", + "telephone_receiver": "📞", + "telescope": "🔭", + "tennis": "🎾", + "tent": "⛺", + "test_tube": "🧪", + "thermometer": "🌡", + "thermometer_face": "🤒", + "thinking": "🤔", + "third_place": "🥉", + "thought_balloon": "💭", + "thread": "🧵", + "three": "3⃣", + "thumbsdown": "👎", + "thumbsup": "👍", + "ticket": "🎫", + "tiger": "🐯", + "tiger2": "🐅", + "timer_clock": "⏲️", + "tired_face": "😫", + "tm": "™", + "toilet": "🚽", + "tokyo_tower": "🗼", + "tomato": "🍅", + "tone1": "🏻", + "tone2": "🏼", + "tone3": "🏽", + "tone4": "🏾", + "tone5": "🏿", + "tongue": "👅", + "toolbox": "🧰", + "tooth": "🦷", + "top": "🔝", + "tophat": "🎩", + "tornado": "🌪", + "track_next": "⏭", + "track_previous": "⏮", + "trackball": "🖲", + "tractor": "🚜", + "trade_mark": "™️", + "traffic_light": "🚥", + "train": "🚋", + "train2": "🚆", + "tram": "🚊", + "trex": "🦖", + "triangular_flag_on_post": "🚩", + "triangular_ruler": "📐", + "trident": "🔱", + "triumph": "😤", + "trolleybus": "🚎", + "trophy": "🏆", + "tropical_drink": "🍹", + "tropical_fish": "🐠", + "truck": "🚚", + "trumpet": "🎺", + "tulip": "🌷", + "tumbler_glass": "🥃", + "turkey": "🦃", + "turtle": "🐢", + "tv": "📺", + "twisted_rightwards_arrows": "🔀", + "two": "2⃣", + "two_hearts": "💕", + "two_men_holding_hands": "👬", + "two_women_holding_hands": "👭", + "u5272": "🈹", + "u5408": "🈴", + "u55b6": "🈺", + "u6307": "🈯", + "u6708": "🈷", + "u6709": "🈶", + "u6e80": "🈵", + "u7121": "🈚", + "u7533": "🈸", + "u7981": "🈲", + "u7a7a": "🈳", + "umbrella": "☔", + "umbrella_on_ground": "⛱️", + "unamused": "😒", + "underage": "🔞", + "unicorn": "🦄", + "unlock": "🔓", + "up": "🆙", + "up_arrow": "⬆", + "updown_arrow": "↕️", + "upleft_arrow": "↖️", + "upright_arrow": "↗", + "upside_down": "🙃", + "v": "✌️", + "vampire": "🧛", + "vertical_traffic_light": "🚦", + "vhs": "📼", + "vibration_mode": "📳", + "victory_hand": "✌", + "video_camera": "📹", + "video_game": "🎮", + "violin": "🎻", + "virgo": "♍", + "volcano": "🌋", + "volleyball": "🏐", + "vs": "🆚", + "vulcan": "🖖", + "vulcan_salute": "🖖", + "waffle": "🧇", + "walking": "🚶", + "waning_crescent_moon": "🌘", + "waning_gibbous_moon": "🌖", + "warning": "⚠", + "wastebasket": "🗑", + "watch": "⌚", + "water_buffalo": "🐃", + "watermelon": "🍉", + "wave": "👋", + "wavy_dash": "〰️", + "waxing_crescent_moon": "🌒", + "waxing_gibbous_moon": "🌔", + "wc": "🚾", + "weary": "😩", + "wedding": "💒", + "weightlifter": "🏋", + "whale": "🐳", + "whale2": "🐋", + "wheel_of_dharma": "☸️", + "wheelchair": "♿", + "white_check_mark": "✅", + "white_circle": "⚪", + "white_flower": "💮", + "white_hair": "🦳", + "white_heart": "🤍", + "white_large_square": "⬜", + "white_medium_small_square": "◽", + "white_medium_square": "◻️", + "white_small_square": "▫️", + "white_square_button": "🔳", + "wilted_flower": "🥀", + "wilted_rose": "🥀", + "wind_blowing_face": "🌬", + "wind_chime": "🎐", + "wine_glass": "🍷", + "wink": "😉", + "wolf": "🐺", + "woman": "👩", + "woman_with_headscarf": "🧕", + "womans_clothes": "👚", + "womans_hat": "👒", + "womens": "🚺", + "woozy_face": "🥴", + "world_map": "🗺", + "worried": "😟", + "wrench": "🔧", + "writing_hand": "✍️", + "x": "❌", + "yarn": "🧶", + "yawning_face": "🥱", + "yellow_circle": "🟡", + "yellow_heart": "💛", + "yellow_square": "🟨", + "yen": "💴", + "yin_yang": "☯️", + "yoyo": "🪀", + "yum": "😋", + "zany_face": "🤪", + "zap": "⚡", + "zebra": "🦓", + "zero": "0⃣", + "zipper_mouth": "🤐", + "zombie": "🧟", + "zzz": "💤" +} \ No newline at end of file diff --git a/priv/static/static/js/10.46f441b948010eda4403.js b/priv/static/static/js/10.46f441b948010eda4403.js deleted file mode 100644 index 308d124c0..000000000 Binary files a/priv/static/static/js/10.46f441b948010eda4403.js and /dev/null differ diff --git a/priv/static/static/js/10.a11a612e4c1ef51ded17.js b/priv/static/static/js/10.a11a612e4c1ef51ded17.js new file mode 100644 index 000000000..2a1ffcc2b Binary files /dev/null and b/priv/static/static/js/10.a11a612e4c1ef51ded17.js differ diff --git a/priv/static/static/js/10.46f441b948010eda4403.js.map b/priv/static/static/js/10.a11a612e4c1ef51ded17.js.map similarity index 56% rename from priv/static/static/js/10.46f441b948010eda4403.js.map rename to priv/static/static/js/10.a11a612e4c1ef51ded17.js.map index e0623e6bf..fd81b28be 100644 Binary files a/priv/static/static/js/10.46f441b948010eda4403.js.map and b/priv/static/static/js/10.a11a612e4c1ef51ded17.js.map differ diff --git a/priv/static/static/js/11.8ff1ed54814f2d34cb3e.js b/priv/static/static/js/11.22872a1f83121e70a148.js similarity index 99% rename from priv/static/static/js/11.8ff1ed54814f2d34cb3e.js rename to priv/static/static/js/11.22872a1f83121e70a148.js index cb57f2a65..a2e9cee51 100644 Binary files a/priv/static/static/js/11.8ff1ed54814f2d34cb3e.js and b/priv/static/static/js/11.22872a1f83121e70a148.js differ diff --git a/priv/static/static/js/11.8ff1ed54814f2d34cb3e.js.map b/priv/static/static/js/11.22872a1f83121e70a148.js.map similarity index 56% rename from priv/static/static/js/11.8ff1ed54814f2d34cb3e.js.map rename to priv/static/static/js/11.22872a1f83121e70a148.js.map index 4ce6d7227..6467c58a5 100644 Binary files a/priv/static/static/js/11.8ff1ed54814f2d34cb3e.js.map and b/priv/static/static/js/11.22872a1f83121e70a148.js.map differ diff --git a/priv/static/static/js/12.13204bdd0ad5703a3ea3.js b/priv/static/static/js/12.c6df5166dc6cdcf749e5.js similarity index 99% rename from priv/static/static/js/12.13204bdd0ad5703a3ea3.js rename to priv/static/static/js/12.c6df5166dc6cdcf749e5.js index a89bfeb67..441071f37 100644 Binary files a/priv/static/static/js/12.13204bdd0ad5703a3ea3.js and b/priv/static/static/js/12.c6df5166dc6cdcf749e5.js differ diff --git a/priv/static/static/js/12.13204bdd0ad5703a3ea3.js.map b/priv/static/static/js/12.c6df5166dc6cdcf749e5.js.map similarity index 56% rename from priv/static/static/js/12.13204bdd0ad5703a3ea3.js.map rename to priv/static/static/js/12.c6df5166dc6cdcf749e5.js.map index 366ec2927..c0bac6f0f 100644 Binary files a/priv/static/static/js/12.13204bdd0ad5703a3ea3.js.map and b/priv/static/static/js/12.c6df5166dc6cdcf749e5.js.map differ diff --git a/priv/static/static/js/13.e27c3eeddcc4b11c1f54.js b/priv/static/static/js/13.77214c18c6d2a9865281.js similarity index 99% rename from priv/static/static/js/13.e27c3eeddcc4b11c1f54.js rename to priv/static/static/js/13.77214c18c6d2a9865281.js index 8cd482b41..08e356de2 100644 Binary files a/priv/static/static/js/13.e27c3eeddcc4b11c1f54.js and b/priv/static/static/js/13.77214c18c6d2a9865281.js differ diff --git a/priv/static/static/js/13.e27c3eeddcc4b11c1f54.js.map b/priv/static/static/js/13.77214c18c6d2a9865281.js.map similarity index 56% rename from priv/static/static/js/13.e27c3eeddcc4b11c1f54.js.map rename to priv/static/static/js/13.77214c18c6d2a9865281.js.map index 0c61c3fca..3d7abf273 100644 Binary files a/priv/static/static/js/13.e27c3eeddcc4b11c1f54.js.map and b/priv/static/static/js/13.77214c18c6d2a9865281.js.map differ diff --git a/priv/static/static/js/14.273855b3e4e27ce80219.js.map b/priv/static/static/js/14.273855b3e4e27ce80219.js.map deleted file mode 100644 index 9ee527eaa..000000000 Binary files a/priv/static/static/js/14.273855b3e4e27ce80219.js.map and /dev/null differ diff --git a/priv/static/static/js/14.273855b3e4e27ce80219.js b/priv/static/static/js/14.e560f5e2f902b9ad2d0d.js similarity index 99% rename from priv/static/static/js/14.273855b3e4e27ce80219.js rename to priv/static/static/js/14.e560f5e2f902b9ad2d0d.js index 78c0bfebc..d2d291725 100644 Binary files a/priv/static/static/js/14.273855b3e4e27ce80219.js and b/priv/static/static/js/14.e560f5e2f902b9ad2d0d.js differ diff --git a/priv/static/static/js/14.e560f5e2f902b9ad2d0d.js.map b/priv/static/static/js/14.e560f5e2f902b9ad2d0d.js.map new file mode 100644 index 000000000..f9797f1b6 Binary files /dev/null and b/priv/static/static/js/14.e560f5e2f902b9ad2d0d.js.map differ diff --git a/priv/static/static/js/15.afbe29b6665fcd015b2d.js b/priv/static/static/js/15.2893c12f1ca2bcdc3cbf.js similarity index 98% rename from priv/static/static/js/15.afbe29b6665fcd015b2d.js rename to priv/static/static/js/15.2893c12f1ca2bcdc3cbf.js index b83752240..82318f797 100644 Binary files a/priv/static/static/js/15.afbe29b6665fcd015b2d.js and b/priv/static/static/js/15.2893c12f1ca2bcdc3cbf.js differ diff --git a/priv/static/static/js/15.2893c12f1ca2bcdc3cbf.js.map b/priv/static/static/js/15.2893c12f1ca2bcdc3cbf.js.map new file mode 100644 index 000000000..00cab138d Binary files /dev/null and b/priv/static/static/js/15.2893c12f1ca2bcdc3cbf.js.map differ diff --git a/priv/static/static/js/15.afbe29b6665fcd015b2d.js.map b/priv/static/static/js/15.afbe29b6665fcd015b2d.js.map deleted file mode 100644 index c7a0be582..000000000 Binary files a/priv/static/static/js/15.afbe29b6665fcd015b2d.js.map and /dev/null differ diff --git a/priv/static/static/js/16.5e3f20da470591d0cabf.js.map b/priv/static/static/js/16.5e3f20da470591d0cabf.js.map deleted file mode 100644 index 0c4d0e385..000000000 Binary files a/priv/static/static/js/16.5e3f20da470591d0cabf.js.map and /dev/null differ diff --git a/priv/static/static/js/16.5e3f20da470591d0cabf.js b/priv/static/static/js/16.be7f4b788716bec25023.js similarity index 98% rename from priv/static/static/js/16.5e3f20da470591d0cabf.js rename to priv/static/static/js/16.be7f4b788716bec25023.js index e90ed4ca1..ea5b554f1 100644 Binary files a/priv/static/static/js/16.5e3f20da470591d0cabf.js and b/priv/static/static/js/16.be7f4b788716bec25023.js differ diff --git a/priv/static/static/js/16.be7f4b788716bec25023.js.map b/priv/static/static/js/16.be7f4b788716bec25023.js.map new file mode 100644 index 000000000..121a49be1 Binary files /dev/null and b/priv/static/static/js/16.be7f4b788716bec25023.js.map differ diff --git a/priv/static/static/js/17.44e90ef82ee2ef12dc3f.js.map b/priv/static/static/js/17.44e90ef82ee2ef12dc3f.js.map deleted file mode 100644 index 1d191b94a..000000000 Binary files a/priv/static/static/js/17.44e90ef82ee2ef12dc3f.js.map and /dev/null differ diff --git a/priv/static/static/js/17.44e90ef82ee2ef12dc3f.js b/priv/static/static/js/17.4ddba89b4f8c284f6392.js similarity index 94% rename from priv/static/static/js/17.44e90ef82ee2ef12dc3f.js rename to priv/static/static/js/17.4ddba89b4f8c284f6392.js index 9b5adfd12..39283f245 100644 Binary files a/priv/static/static/js/17.44e90ef82ee2ef12dc3f.js and b/priv/static/static/js/17.4ddba89b4f8c284f6392.js differ diff --git a/priv/static/static/js/17.4ddba89b4f8c284f6392.js.map b/priv/static/static/js/17.4ddba89b4f8c284f6392.js.map new file mode 100644 index 000000000..322db8c6b Binary files /dev/null and b/priv/static/static/js/17.4ddba89b4f8c284f6392.js.map differ diff --git a/priv/static/static/js/18.990b88b57bf3a6809098.js b/priv/static/static/js/18.990b88b57bf3a6809098.js new file mode 100644 index 000000000..96de50c61 Binary files /dev/null and b/priv/static/static/js/18.990b88b57bf3a6809098.js differ diff --git a/priv/static/static/js/18.990b88b57bf3a6809098.js.map b/priv/static/static/js/18.990b88b57bf3a6809098.js.map new file mode 100644 index 000000000..b0fb3b629 Binary files /dev/null and b/priv/static/static/js/18.990b88b57bf3a6809098.js.map differ diff --git a/priv/static/static/js/18.9a5b877f94b2b53065e1.js b/priv/static/static/js/18.9a5b877f94b2b53065e1.js deleted file mode 100644 index c4aea5b25..000000000 Binary files a/priv/static/static/js/18.9a5b877f94b2b53065e1.js and /dev/null differ diff --git a/priv/static/static/js/18.9a5b877f94b2b53065e1.js.map b/priv/static/static/js/18.9a5b877f94b2b53065e1.js.map deleted file mode 100644 index 61d9a7d41..000000000 Binary files a/priv/static/static/js/18.9a5b877f94b2b53065e1.js.map and /dev/null differ diff --git a/priv/static/static/js/19.1fd4da643df0abf89122.js.map b/priv/static/static/js/19.1fd4da643df0abf89122.js.map deleted file mode 100644 index 010c8674d..000000000 Binary files a/priv/static/static/js/19.1fd4da643df0abf89122.js.map and /dev/null differ diff --git a/priv/static/static/js/19.1fd4da643df0abf89122.js b/priv/static/static/js/19.783715f17e3f98e8898e.js similarity index 99% rename from priv/static/static/js/19.1fd4da643df0abf89122.js rename to priv/static/static/js/19.783715f17e3f98e8898e.js index c1ca1643b..bf4fd22fd 100644 Binary files a/priv/static/static/js/19.1fd4da643df0abf89122.js and b/priv/static/static/js/19.783715f17e3f98e8898e.js differ diff --git a/priv/static/static/js/19.783715f17e3f98e8898e.js.map b/priv/static/static/js/19.783715f17e3f98e8898e.js.map new file mode 100644 index 000000000..d3bd148d5 Binary files /dev/null and b/priv/static/static/js/19.783715f17e3f98e8898e.js.map differ diff --git a/priv/static/static/js/2.422e6c756ac673a6fd44.js b/priv/static/static/js/2.422e6c756ac673a6fd44.js deleted file mode 100644 index 9fb47e2bf..000000000 Binary files a/priv/static/static/js/2.422e6c756ac673a6fd44.js and /dev/null differ diff --git a/priv/static/static/js/2.422e6c756ac673a6fd44.js.map b/priv/static/static/js/2.422e6c756ac673a6fd44.js.map deleted file mode 100644 index 92fdb4d2c..000000000 Binary files a/priv/static/static/js/2.422e6c756ac673a6fd44.js.map and /dev/null differ diff --git a/priv/static/static/js/2.88fa7ac80b2020ac2b46.js b/priv/static/static/js/2.88fa7ac80b2020ac2b46.js new file mode 100644 index 000000000..b2c2eeb25 Binary files /dev/null and b/priv/static/static/js/2.88fa7ac80b2020ac2b46.js differ diff --git a/priv/static/static/js/2.88fa7ac80b2020ac2b46.js.map b/priv/static/static/js/2.88fa7ac80b2020ac2b46.js.map new file mode 100644 index 000000000..f6aafd426 Binary files /dev/null and b/priv/static/static/js/2.88fa7ac80b2020ac2b46.js.map differ diff --git a/priv/static/static/js/20.a64fd29da59076399a27.js b/priv/static/static/js/20.96c40f6c9db8c08633bd.js similarity index 99% rename from priv/static/static/js/20.a64fd29da59076399a27.js rename to priv/static/static/js/20.96c40f6c9db8c08633bd.js index eae5b3947..a3b3d7894 100644 Binary files a/priv/static/static/js/20.a64fd29da59076399a27.js and b/priv/static/static/js/20.96c40f6c9db8c08633bd.js differ diff --git a/priv/static/static/js/20.96c40f6c9db8c08633bd.js.map b/priv/static/static/js/20.96c40f6c9db8c08633bd.js.map new file mode 100644 index 000000000..d7d40ed07 Binary files /dev/null and b/priv/static/static/js/20.96c40f6c9db8c08633bd.js.map differ diff --git a/priv/static/static/js/20.a64fd29da59076399a27.js.map b/priv/static/static/js/20.a64fd29da59076399a27.js.map deleted file mode 100644 index b2917fa10..000000000 Binary files a/priv/static/static/js/20.a64fd29da59076399a27.js.map and /dev/null differ diff --git a/priv/static/static/js/21.243d9e6ebf469a2dc740.js.map b/priv/static/static/js/21.243d9e6ebf469a2dc740.js.map deleted file mode 100644 index 3f98250fa..000000000 Binary files a/priv/static/static/js/21.243d9e6ebf469a2dc740.js.map and /dev/null differ diff --git a/priv/static/static/js/21.243d9e6ebf469a2dc740.js b/priv/static/static/js/21.5a9f8e39a7833c1aa117.js similarity index 99% rename from priv/static/static/js/21.243d9e6ebf469a2dc740.js rename to priv/static/static/js/21.5a9f8e39a7833c1aa117.js index 61633519b..4114db7db 100644 Binary files a/priv/static/static/js/21.243d9e6ebf469a2dc740.js and b/priv/static/static/js/21.5a9f8e39a7833c1aa117.js differ diff --git a/priv/static/static/js/21.5a9f8e39a7833c1aa117.js.map b/priv/static/static/js/21.5a9f8e39a7833c1aa117.js.map new file mode 100644 index 000000000..898948286 Binary files /dev/null and b/priv/static/static/js/21.5a9f8e39a7833c1aa117.js.map differ diff --git a/priv/static/static/js/22.e20ef7e5fefc0964cdd1.js b/priv/static/static/js/22.d65671b9e5e00a0eb625.js similarity index 99% rename from priv/static/static/js/22.e20ef7e5fefc0964cdd1.js rename to priv/static/static/js/22.d65671b9e5e00a0eb625.js index e8f309f8a..3748a53b2 100644 Binary files a/priv/static/static/js/22.e20ef7e5fefc0964cdd1.js and b/priv/static/static/js/22.d65671b9e5e00a0eb625.js differ diff --git a/priv/static/static/js/22.d65671b9e5e00a0eb625.js.map b/priv/static/static/js/22.d65671b9e5e00a0eb625.js.map new file mode 100644 index 000000000..110cadd41 Binary files /dev/null and b/priv/static/static/js/22.d65671b9e5e00a0eb625.js.map differ diff --git a/priv/static/static/js/22.e20ef7e5fefc0964cdd1.js.map b/priv/static/static/js/22.e20ef7e5fefc0964cdd1.js.map deleted file mode 100644 index 7780cffe6..000000000 Binary files a/priv/static/static/js/22.e20ef7e5fefc0964cdd1.js.map and /dev/null differ diff --git a/priv/static/static/js/23.614a35f9ded445292f4a.js.map b/priv/static/static/js/23.614a35f9ded445292f4a.js.map deleted file mode 100644 index 4158041f4..000000000 Binary files a/priv/static/static/js/23.614a35f9ded445292f4a.js.map and /dev/null differ diff --git a/priv/static/static/js/23.614a35f9ded445292f4a.js b/priv/static/static/js/23.bf697d60801d277815e0.js similarity index 99% rename from priv/static/static/js/23.614a35f9ded445292f4a.js rename to priv/static/static/js/23.bf697d60801d277815e0.js index a35450986..e61cf01d7 100644 Binary files a/priv/static/static/js/23.614a35f9ded445292f4a.js and b/priv/static/static/js/23.bf697d60801d277815e0.js differ diff --git a/priv/static/static/js/23.bf697d60801d277815e0.js.map b/priv/static/static/js/23.bf697d60801d277815e0.js.map new file mode 100644 index 000000000..20c74e93b Binary files /dev/null and b/priv/static/static/js/23.bf697d60801d277815e0.js.map differ diff --git a/priv/static/static/js/24.6ae9ca51e51e023afbe4.js.map b/priv/static/static/js/24.6ae9ca51e51e023afbe4.js.map deleted file mode 100644 index 7e68d5eaa..000000000 Binary files a/priv/static/static/js/24.6ae9ca51e51e023afbe4.js.map and /dev/null differ diff --git a/priv/static/static/js/24.6ae9ca51e51e023afbe4.js b/priv/static/static/js/24.914e51bfcfc620a93c0e.js similarity index 99% rename from priv/static/static/js/24.6ae9ca51e51e023afbe4.js rename to priv/static/static/js/24.914e51bfcfc620a93c0e.js index d075f3b1f..abdad101e 100644 Binary files a/priv/static/static/js/24.6ae9ca51e51e023afbe4.js and b/priv/static/static/js/24.914e51bfcfc620a93c0e.js differ diff --git a/priv/static/static/js/24.914e51bfcfc620a93c0e.js.map b/priv/static/static/js/24.914e51bfcfc620a93c0e.js.map new file mode 100644 index 000000000..1ddfced9a Binary files /dev/null and b/priv/static/static/js/24.914e51bfcfc620a93c0e.js.map differ diff --git a/priv/static/static/js/25.eadae0d48ee5be52a16c.js b/priv/static/static/js/25.eadae0d48ee5be52a16c.js deleted file mode 100644 index a0e44e1aa..000000000 Binary files a/priv/static/static/js/25.eadae0d48ee5be52a16c.js and /dev/null differ diff --git a/priv/static/static/js/25.eadae0d48ee5be52a16c.js.map b/priv/static/static/js/25.eadae0d48ee5be52a16c.js.map deleted file mode 100644 index aaa5e3a57..000000000 Binary files a/priv/static/static/js/25.eadae0d48ee5be52a16c.js.map and /dev/null differ diff --git a/priv/static/static/js/25.fa8acda1a0ba7de2ab58.js b/priv/static/static/js/25.fa8acda1a0ba7de2ab58.js new file mode 100644 index 000000000..719148fcd Binary files /dev/null and b/priv/static/static/js/25.fa8acda1a0ba7de2ab58.js differ diff --git a/priv/static/static/js/25.fa8acda1a0ba7de2ab58.js.map b/priv/static/static/js/25.fa8acda1a0ba7de2ab58.js.map new file mode 100644 index 000000000..ec5910108 Binary files /dev/null and b/priv/static/static/js/25.fa8acda1a0ba7de2ab58.js.map differ diff --git a/priv/static/static/js/26.8fd0027b982c4bcdc88f.js b/priv/static/static/js/26.5233739c17e00ab514f7.js similarity index 99% rename from priv/static/static/js/26.8fd0027b982c4bcdc88f.js rename to priv/static/static/js/26.5233739c17e00ab514f7.js index 3b149915b..9adba8a0c 100644 Binary files a/priv/static/static/js/26.8fd0027b982c4bcdc88f.js and b/priv/static/static/js/26.5233739c17e00ab514f7.js differ diff --git a/priv/static/static/js/26.5233739c17e00ab514f7.js.map b/priv/static/static/js/26.5233739c17e00ab514f7.js.map new file mode 100644 index 000000000..9aad55492 Binary files /dev/null and b/priv/static/static/js/26.5233739c17e00ab514f7.js.map differ diff --git a/priv/static/static/js/26.8fd0027b982c4bcdc88f.js.map b/priv/static/static/js/26.8fd0027b982c4bcdc88f.js.map deleted file mode 100644 index d40f1979a..000000000 Binary files a/priv/static/static/js/26.8fd0027b982c4bcdc88f.js.map and /dev/null differ diff --git a/priv/static/static/js/27.6d90a54efba08d261d69.js.map b/priv/static/static/js/27.6d90a54efba08d261d69.js.map deleted file mode 100644 index 6685474ce..000000000 Binary files a/priv/static/static/js/27.6d90a54efba08d261d69.js.map and /dev/null differ diff --git a/priv/static/static/js/27.6d90a54efba08d261d69.js b/priv/static/static/js/27.79a2337abb067d8a36ce.js similarity index 94% rename from priv/static/static/js/27.6d90a54efba08d261d69.js rename to priv/static/static/js/27.79a2337abb067d8a36ce.js index e8420a54f..07b8fbea4 100644 Binary files a/priv/static/static/js/27.6d90a54efba08d261d69.js and b/priv/static/static/js/27.79a2337abb067d8a36ce.js differ diff --git a/priv/static/static/js/27.79a2337abb067d8a36ce.js.map b/priv/static/static/js/27.79a2337abb067d8a36ce.js.map new file mode 100644 index 000000000..a55aeae77 Binary files /dev/null and b/priv/static/static/js/27.79a2337abb067d8a36ce.js.map differ diff --git a/priv/static/static/js/28.ed355decbad274c26485.js b/priv/static/static/js/28.ed355decbad274c26485.js new file mode 100644 index 000000000..e4cfd3d70 Binary files /dev/null and b/priv/static/static/js/28.ed355decbad274c26485.js differ diff --git a/priv/static/static/js/28.ed355decbad274c26485.js.map b/priv/static/static/js/28.ed355decbad274c26485.js.map new file mode 100644 index 000000000..0349f2c68 Binary files /dev/null and b/priv/static/static/js/28.ed355decbad274c26485.js.map differ diff --git a/priv/static/static/js/28.f1353aa382a104262d1a.js b/priv/static/static/js/28.f1353aa382a104262d1a.js deleted file mode 100644 index a253284f0..000000000 Binary files a/priv/static/static/js/28.f1353aa382a104262d1a.js and /dev/null differ diff --git a/priv/static/static/js/28.f1353aa382a104262d1a.js.map b/priv/static/static/js/28.f1353aa382a104262d1a.js.map deleted file mode 100644 index 3421c9511..000000000 Binary files a/priv/static/static/js/28.f1353aa382a104262d1a.js.map and /dev/null differ diff --git a/priv/static/static/js/29.39c1e87a689c840395b2.js.map b/priv/static/static/js/29.39c1e87a689c840395b2.js.map deleted file mode 100644 index 5901ce9b7..000000000 Binary files a/priv/static/static/js/29.39c1e87a689c840395b2.js.map and /dev/null differ diff --git a/priv/static/static/js/29.39c1e87a689c840395b2.js b/priv/static/static/js/29.d3d8f3c066d579644c9a.js similarity index 99% rename from priv/static/static/js/29.39c1e87a689c840395b2.js rename to priv/static/static/js/29.d3d8f3c066d579644c9a.js index ddb512279..8a8a3b51f 100644 Binary files a/priv/static/static/js/29.39c1e87a689c840395b2.js and b/priv/static/static/js/29.d3d8f3c066d579644c9a.js differ diff --git a/priv/static/static/js/29.d3d8f3c066d579644c9a.js.map b/priv/static/static/js/29.d3d8f3c066d579644c9a.js.map new file mode 100644 index 000000000..0ef69d368 Binary files /dev/null and b/priv/static/static/js/29.d3d8f3c066d579644c9a.js.map differ diff --git a/priv/static/static/js/3.a0df8a5bcd120d1f8581.js b/priv/static/static/js/3.0b1cb0c49b906b834801.js similarity index 99% rename from priv/static/static/js/3.a0df8a5bcd120d1f8581.js rename to priv/static/static/js/3.0b1cb0c49b906b834801.js index 423121114..5b79d06b1 100644 Binary files a/priv/static/static/js/3.a0df8a5bcd120d1f8581.js and b/priv/static/static/js/3.0b1cb0c49b906b834801.js differ diff --git a/priv/static/static/js/3.a0df8a5bcd120d1f8581.js.map b/priv/static/static/js/3.0b1cb0c49b906b834801.js.map similarity index 99% rename from priv/static/static/js/3.a0df8a5bcd120d1f8581.js.map rename to priv/static/static/js/3.0b1cb0c49b906b834801.js.map index 653727d10..08e6ffdfe 100644 Binary files a/priv/static/static/js/3.a0df8a5bcd120d1f8581.js.map and b/priv/static/static/js/3.0b1cb0c49b906b834801.js.map differ diff --git a/priv/static/static/js/30.04694ca04ca2fb3b9695.js b/priv/static/static/js/30.04694ca04ca2fb3b9695.js new file mode 100644 index 000000000..cc60c675d Binary files /dev/null and b/priv/static/static/js/30.04694ca04ca2fb3b9695.js differ diff --git a/priv/static/static/js/30.04694ca04ca2fb3b9695.js.map b/priv/static/static/js/30.04694ca04ca2fb3b9695.js.map new file mode 100644 index 000000000..b347f4f84 Binary files /dev/null and b/priv/static/static/js/30.04694ca04ca2fb3b9695.js.map differ diff --git a/priv/static/static/js/30.64736585965c63c2b5d4.js b/priv/static/static/js/30.64736585965c63c2b5d4.js deleted file mode 100644 index 4fdbe8c3e..000000000 Binary files a/priv/static/static/js/30.64736585965c63c2b5d4.js and /dev/null differ diff --git a/priv/static/static/js/30.64736585965c63c2b5d4.js.map b/priv/static/static/js/30.64736585965c63c2b5d4.js.map deleted file mode 100644 index 376920946..000000000 Binary files a/priv/static/static/js/30.64736585965c63c2b5d4.js.map and /dev/null differ diff --git a/priv/static/static/js/31.ef44f6a2b08f7f78dd8e.js b/priv/static/static/js/31.ef44f6a2b08f7f78dd8e.js new file mode 100644 index 000000000..886c184d1 Binary files /dev/null and b/priv/static/static/js/31.ef44f6a2b08f7f78dd8e.js differ diff --git a/priv/static/static/js/31.ef44f6a2b08f7f78dd8e.js.map b/priv/static/static/js/31.ef44f6a2b08f7f78dd8e.js.map new file mode 100644 index 000000000..1a4bd1a0a Binary files /dev/null and b/priv/static/static/js/31.ef44f6a2b08f7f78dd8e.js.map differ diff --git a/priv/static/static/js/32.044555dd7095261d9faf.js b/priv/static/static/js/32.044555dd7095261d9faf.js new file mode 100644 index 000000000..6ca50349e Binary files /dev/null and b/priv/static/static/js/32.044555dd7095261d9faf.js differ diff --git a/priv/static/static/js/32.044555dd7095261d9faf.js.map b/priv/static/static/js/32.044555dd7095261d9faf.js.map new file mode 100644 index 000000000..f7f4094ee Binary files /dev/null and b/priv/static/static/js/32.044555dd7095261d9faf.js.map differ diff --git a/priv/static/static/js/4.4cde7fdd1fe6bf2a9499.js b/priv/static/static/js/4.15e71ac865c2606c30a6.js similarity index 83% rename from priv/static/static/js/4.4cde7fdd1fe6bf2a9499.js rename to priv/static/static/js/4.15e71ac865c2606c30a6.js index 4da4c56fa..3406cc065 100644 Binary files a/priv/static/static/js/4.4cde7fdd1fe6bf2a9499.js and b/priv/static/static/js/4.15e71ac865c2606c30a6.js differ diff --git a/priv/static/static/js/4.4cde7fdd1fe6bf2a9499.js.map b/priv/static/static/js/4.15e71ac865c2606c30a6.js.map similarity index 99% rename from priv/static/static/js/4.4cde7fdd1fe6bf2a9499.js.map rename to priv/static/static/js/4.15e71ac865c2606c30a6.js.map index bc040ab9b..023d90430 100644 Binary files a/priv/static/static/js/4.4cde7fdd1fe6bf2a9499.js.map and b/priv/static/static/js/4.15e71ac865c2606c30a6.js.map differ diff --git a/priv/static/static/js/5.2e165bc072548e533dd4.js b/priv/static/static/js/5.e116ac5b71f5e62029a1.js similarity index 98% rename from priv/static/static/js/5.2e165bc072548e533dd4.js rename to priv/static/static/js/5.e116ac5b71f5e62029a1.js index cfd84226c..acd64094e 100644 Binary files a/priv/static/static/js/5.2e165bc072548e533dd4.js and b/priv/static/static/js/5.e116ac5b71f5e62029a1.js differ diff --git a/priv/static/static/js/5.2e165bc072548e533dd4.js.map b/priv/static/static/js/5.e116ac5b71f5e62029a1.js.map similarity index 57% rename from priv/static/static/js/5.2e165bc072548e533dd4.js.map rename to priv/static/static/js/5.e116ac5b71f5e62029a1.js.map index 49959c78e..0017a3bfd 100644 Binary files a/priv/static/static/js/5.2e165bc072548e533dd4.js.map and b/priv/static/static/js/5.e116ac5b71f5e62029a1.js.map differ diff --git a/priv/static/static/js/6.260ccd84f8cd2af27970.js b/priv/static/static/js/6.4e804674e0bff336a51b.js similarity index 99% rename from priv/static/static/js/6.260ccd84f8cd2af27970.js rename to priv/static/static/js/6.4e804674e0bff336a51b.js index fb4a690f4..b33bbd652 100644 Binary files a/priv/static/static/js/6.260ccd84f8cd2af27970.js and b/priv/static/static/js/6.4e804674e0bff336a51b.js differ diff --git a/priv/static/static/js/6.260ccd84f8cd2af27970.js.map b/priv/static/static/js/6.4e804674e0bff336a51b.js.map similarity index 57% rename from priv/static/static/js/6.260ccd84f8cd2af27970.js.map rename to priv/static/static/js/6.4e804674e0bff336a51b.js.map index 850fe731a..bbb049a88 100644 Binary files a/priv/static/static/js/6.260ccd84f8cd2af27970.js.map and b/priv/static/static/js/6.4e804674e0bff336a51b.js.map differ diff --git a/priv/static/static/js/7.1c41eff6cfc75a00bde4.js b/priv/static/static/js/7.e8595e0b6e063c6d9478.js similarity index 99% rename from priv/static/static/js/7.1c41eff6cfc75a00bde4.js rename to priv/static/static/js/7.e8595e0b6e063c6d9478.js index 317770a53..7622e0d7a 100644 Binary files a/priv/static/static/js/7.1c41eff6cfc75a00bde4.js and b/priv/static/static/js/7.e8595e0b6e063c6d9478.js differ diff --git a/priv/static/static/js/7.1c41eff6cfc75a00bde4.js.map b/priv/static/static/js/7.e8595e0b6e063c6d9478.js.map similarity index 57% rename from priv/static/static/js/7.1c41eff6cfc75a00bde4.js.map rename to priv/static/static/js/7.e8595e0b6e063c6d9478.js.map index 36f327b3f..40327d1fd 100644 Binary files a/priv/static/static/js/7.1c41eff6cfc75a00bde4.js.map and b/priv/static/static/js/7.e8595e0b6e063c6d9478.js.map differ diff --git a/priv/static/static/js/8.9b35c2fee24ab7481e00.js b/priv/static/static/js/8.2d08c6fbb6b6ef23752f.js similarity index 99% rename from priv/static/static/js/8.9b35c2fee24ab7481e00.js rename to priv/static/static/js/8.2d08c6fbb6b6ef23752f.js index cb7844ffc..085a9e004 100644 Binary files a/priv/static/static/js/8.9b35c2fee24ab7481e00.js and b/priv/static/static/js/8.2d08c6fbb6b6ef23752f.js differ diff --git a/priv/static/static/js/8.9b35c2fee24ab7481e00.js.map b/priv/static/static/js/8.2d08c6fbb6b6ef23752f.js.map similarity index 57% rename from priv/static/static/js/8.9b35c2fee24ab7481e00.js.map rename to priv/static/static/js/8.2d08c6fbb6b6ef23752f.js.map index 65f4d5ae9..50222e2be 100644 Binary files a/priv/static/static/js/8.9b35c2fee24ab7481e00.js.map and b/priv/static/static/js/8.2d08c6fbb6b6ef23752f.js.map differ diff --git a/priv/static/static/js/9.3a29094f1886648a0af3.js b/priv/static/static/js/9.3a29094f1886648a0af3.js deleted file mode 100644 index eb3516dcd..000000000 Binary files a/priv/static/static/js/9.3a29094f1886648a0af3.js and /dev/null differ diff --git a/priv/static/static/js/9.3a29094f1886648a0af3.js.map b/priv/static/static/js/9.3a29094f1886648a0af3.js.map deleted file mode 100644 index 1b6224a6a..000000000 Binary files a/priv/static/static/js/9.3a29094f1886648a0af3.js.map and /dev/null differ diff --git a/priv/static/static/js/9.7d9dd95c4a1c9aa47453.js b/priv/static/static/js/9.7d9dd95c4a1c9aa47453.js new file mode 100644 index 000000000..41ab62b92 Binary files /dev/null and b/priv/static/static/js/9.7d9dd95c4a1c9aa47453.js differ diff --git a/priv/static/static/js/9.7d9dd95c4a1c9aa47453.js.map b/priv/static/static/js/9.7d9dd95c4a1c9aa47453.js.map new file mode 100644 index 000000000..c215e9a03 Binary files /dev/null and b/priv/static/static/js/9.7d9dd95c4a1c9aa47453.js.map differ diff --git a/priv/static/static/js/app.45547c05212c403dd77c.js b/priv/static/static/js/app.45547c05212c403dd77c.js deleted file mode 100644 index 219a59493..000000000 Binary files a/priv/static/static/js/app.45547c05212c403dd77c.js and /dev/null differ diff --git a/priv/static/static/js/app.45547c05212c403dd77c.js.map b/priv/static/static/js/app.45547c05212c403dd77c.js.map deleted file mode 100644 index e1dd6c992..000000000 Binary files a/priv/static/static/js/app.45547c05212c403dd77c.js.map and /dev/null differ diff --git a/priv/static/static/js/app.eb8f7164fc75862a251d.js b/priv/static/static/js/app.eb8f7164fc75862a251d.js new file mode 100644 index 000000000..55414d124 Binary files /dev/null and b/priv/static/static/js/app.eb8f7164fc75862a251d.js differ diff --git a/priv/static/static/js/app.eb8f7164fc75862a251d.js.map b/priv/static/static/js/app.eb8f7164fc75862a251d.js.map new file mode 100644 index 000000000..f1dbb68bb Binary files /dev/null and b/priv/static/static/js/app.eb8f7164fc75862a251d.js.map differ diff --git a/priv/static/static/js/vendors~app.952124344a84613dbac0.js b/priv/static/static/js/vendors~app.54838a79dee084ec3dad.js similarity index 71% rename from priv/static/static/js/vendors~app.952124344a84613dbac0.js rename to priv/static/static/js/vendors~app.54838a79dee084ec3dad.js index f7943c122..38dd65643 100644 Binary files a/priv/static/static/js/vendors~app.952124344a84613dbac0.js and b/priv/static/static/js/vendors~app.54838a79dee084ec3dad.js differ diff --git a/priv/static/static/js/vendors~app.54838a79dee084ec3dad.js.map b/priv/static/static/js/vendors~app.54838a79dee084ec3dad.js.map new file mode 100644 index 000000000..35b5fd52f Binary files /dev/null and b/priv/static/static/js/vendors~app.54838a79dee084ec3dad.js.map differ diff --git a/priv/static/static/js/vendors~app.952124344a84613dbac0.js.map b/priv/static/static/js/vendors~app.952124344a84613dbac0.js.map deleted file mode 100644 index 05fc07c18..000000000 Binary files a/priv/static/static/js/vendors~app.952124344a84613dbac0.js.map and /dev/null differ diff --git a/priv/static/static/themes/redmond-xx-se.json b/priv/static/static/themes/redmond-xx-se.json index 24480d2c7..b62769dbc 100644 --- a/priv/static/static/themes/redmond-xx-se.json +++ b/priv/static/static/themes/redmond-xx-se.json @@ -267,6 +267,7 @@ }, "colors": { "bg": "#c0c0c0", + "wallpaper": "#008080", "text": "#000000", "link": "#0000ff", "accent": "#000080", diff --git a/priv/static/static/themes/redmond-xx.json b/priv/static/static/themes/redmond-xx.json index cf9010fe2..83b591091 100644 --- a/priv/static/static/themes/redmond-xx.json +++ b/priv/static/static/themes/redmond-xx.json @@ -258,6 +258,7 @@ }, "colors": { "bg": "#c0c0c0", + "wallpaper": "#008080", "text": "#000000", "link": "#0000ff", "accent": "#000080", diff --git a/priv/static/static/themes/redmond-xxi.json b/priv/static/static/themes/redmond-xxi.json index 7fdc4a6d6..60ceae7c2 100644 --- a/priv/static/static/themes/redmond-xxi.json +++ b/priv/static/static/themes/redmond-xxi.json @@ -240,6 +240,7 @@ }, "colors": { "bg": "#d6d6ce", + "wallpaper": "#396ba5", "text": "#000000", "link": "#0000ff", "accent": "#0a246a", diff --git a/priv/static/sw-pleroma.js b/priv/static/sw-pleroma.js index 385ee2f0c..25879eb45 100644 Binary files a/priv/static/sw-pleroma.js and b/priv/static/sw-pleroma.js differ diff --git a/priv/static/sw-pleroma.js.map b/priv/static/sw-pleroma.js.map index 0b6a76c2f..62cea8c08 100644 Binary files a/priv/static/sw-pleroma.js.map and b/priv/static/sw-pleroma.js.map differ diff --git a/priv/templates/sample_config.eex b/priv/templates/sample_config.eex index 2f5952ef1..42f496ded 100644 --- a/priv/templates/sample_config.eex +++ b/priv/templates/sample_config.eex @@ -49,12 +49,18 @@ config :pleroma, Pleroma.Uploaders.Local, uploads: "<%= uploads_dir %>" # sts: true # Configure S3 support if desired. -# The public S3 endpoint is different depending on region and provider, +# The public S3 endpoint (base_url) is different depending on region and provider, # consult your S3 provider's documentation for details on what to use. # +# config :pleroma, Pleroma.Upload, +# uploader: Pleroma.Uploaders.S3, +# base_url: "https://s3.amazonaws.com" +# # config :pleroma, Pleroma.Uploaders.S3, # bucket: "some-bucket", -# public_endpoint: "https://s3.amazonaws.com" +# bucket_namespace: "my-namespace", +# truncated_namespace: nil, +# streaming_enabled: true # # Configure S3 credentials: # config :ex_aws, :s3, diff --git a/test/mix/tasks/pleroma/email_test.exs b/test/mix/tasks/pleroma/email_test.exs index 78cdf178b..ce68b88de 100644 --- a/test/mix/tasks/pleroma/email_test.exs +++ b/test/mix/tasks/pleroma/email_test.exs @@ -61,18 +61,18 @@ test "Sends test email with given address" do test "Sends confirmation emails" do local_user1 = insert(:user, %{ - confirmation_pending: true, + is_confirmed: false, confirmation_token: "mytoken", - deactivated: false, + is_active: true, email: "local1@pleroma.com", local: true }) local_user2 = insert(:user, %{ - confirmation_pending: true, + is_confirmed: false, confirmation_token: "mytoken", - deactivated: false, + is_active: true, email: "local2@pleroma.com", local: true }) @@ -88,30 +88,30 @@ test "Sends confirmation emails" do test "Does not send confirmation email to inappropriate users" do # confirmed user insert(:user, %{ - confirmation_pending: false, + is_confirmed: true, confirmation_token: "mytoken", - deactivated: false, + is_active: true, email: "confirmed@pleroma.com", local: true }) # remote user insert(:user, %{ - deactivated: false, + is_active: true, email: "remote@not-pleroma.com", local: false }) # deactivated user = insert(:user, %{ - deactivated: true, + is_active: false, email: "deactivated@pleroma.com", local: false }) # invisible user insert(:user, %{ - deactivated: false, + is_active: true, email: "invisible@pleroma.com", local: true, invisible: true diff --git a/test/mix/tasks/pleroma/user_test.exs b/test/mix/tasks/pleroma/user_test.exs index 7c68b8a37..a2178bbd1 100644 --- a/test/mix/tasks/pleroma/user_test.exs +++ b/test/mix/tasks/pleroma/user_test.exs @@ -102,7 +102,7 @@ test "user is deleted" do assert_received {:mix_shell, :info, [message]} assert message =~ " deleted" - assert %{deactivated: true} = User.get_by_nickname(user.nickname) + assert %{is_active: false} = User.get_by_nickname(user.nickname) assert called(Pleroma.Web.Federator.publish(:_)) end @@ -140,7 +140,7 @@ test "a remote user's create activity is deleted when the object has been pruned assert_received {:mix_shell, :info, [message]} assert message =~ " deleted" - assert %{deactivated: true} = User.get_by_nickname(user.nickname) + assert %{is_active: false} = User.get_by_nickname(user.nickname) assert called(Pleroma.Web.Federator.publish(:_)) refute Pleroma.Repo.get(Pleroma.Activity, like_activity.id) @@ -157,41 +157,8 @@ test "no user to delete" do end end - describe "running toggle_activated" do - test "user is deactivated" do - user = insert(:user) - - Mix.Tasks.Pleroma.User.run(["toggle_activated", user.nickname]) - - assert_received {:mix_shell, :info, [message]} - assert message =~ " deactivated" - - user = User.get_cached_by_nickname(user.nickname) - assert user.deactivated - end - - test "user is activated" do - user = insert(:user, deactivated: true) - - Mix.Tasks.Pleroma.User.run(["toggle_activated", user.nickname]) - - assert_received {:mix_shell, :info, [message]} - assert message =~ " activated" - - user = User.get_cached_by_nickname(user.nickname) - refute user.deactivated - end - - test "no user to toggle" do - Mix.Tasks.Pleroma.User.run(["toggle_activated", "nonexistent"]) - - assert_received {:mix_shell, :error, [message]} - assert message =~ "No user" - end - end - describe "running deactivate" do - test "user is unsubscribed" do + test "active user is deactivated and unsubscribed" do followed = insert(:user) remote_followed = insert(:user, local: false) user = insert(:user) @@ -201,16 +168,26 @@ test "user is unsubscribed" do Mix.Tasks.Pleroma.User.run(["deactivate", user.nickname]) - assert_received {:mix_shell, :info, [message]} - assert message =~ "Deactivating" - # Note that the task has delay :timer.sleep(500) assert_received {:mix_shell, :info, [message]} - assert message =~ "Successfully unsubscribed" + + assert message == + "Successfully deactivated #{user.nickname} and unsubscribed all local followers" user = User.get_cached_by_nickname(user.nickname) assert Enum.empty?(Enum.filter(User.get_friends(user), & &1.local)) - assert user.deactivated + refute user.is_active + end + + test "user is deactivated" do + %{id: id, nickname: nickname} = insert(:user, is_active: false) + + assert :ok = Mix.Tasks.Pleroma.User.run(["deactivate", nickname]) + assert_received {:mix_shell, :info, [message]} + assert message == "User #{nickname} already deactivated" + + user = Repo.get(User, id) + refute user.is_active end test "no user to deactivate" do @@ -238,7 +215,7 @@ test "All statuses set" do assert message =~ ~r/Admin status .* true/ assert_received {:mix_shell, :info, [message]} - assert message =~ ~r/Confirmation pending .* false/ + assert message =~ ~r/Confirmation status.* true/ assert_received {:mix_shell, :info, [message]} assert message =~ ~r/Locked status .* true/ @@ -250,7 +227,7 @@ test "All statuses set" do assert user.is_moderator assert user.is_locked assert user.is_admin - refute user.confirmation_pending + assert user.is_confirmed end test "All statuses unset" do @@ -259,7 +236,7 @@ test "All statuses unset" do is_locked: true, is_moderator: true, is_admin: true, - confirmation_pending: true + is_confirmed: false ) Mix.Tasks.Pleroma.User.run([ @@ -275,7 +252,7 @@ test "All statuses unset" do assert message =~ ~r/Admin status .* false/ assert_received {:mix_shell, :info, [message]} - assert message =~ ~r/Confirmation pending .* true/ + assert message =~ ~r/Confirmation status.* false/ assert_received {:mix_shell, :info, [message]} assert message =~ ~r/Locked status .* false/ @@ -287,7 +264,7 @@ test "All statuses unset" do refute user.is_moderator refute user.is_locked refute user.is_admin - assert user.confirmation_pending + refute user.is_confirmed end test "no user to set status" do @@ -436,13 +413,6 @@ test "invite is revoked" do assert_received {:mix_shell, :info, [message]} assert message =~ "Invite for token #{invite.token} was revoked." end - - test "it prints an error message when invite is not exist" do - Mix.Tasks.Pleroma.User.run(["revoke_invite", "foo"]) - - assert_received {:mix_shell, :error, [message]} - assert message =~ "No invite found" - end end describe "running delete_activities" do @@ -464,27 +434,27 @@ test "it prints an error message when user is not exist" do describe "running confirm" do test "user is confirmed" do - %{id: id, nickname: nickname} = insert(:user, confirmation_pending: false) + %{id: id, nickname: nickname} = insert(:user, is_confirmed: true) assert :ok = Mix.Tasks.Pleroma.User.run(["confirm", nickname]) assert_received {:mix_shell, :info, [message]} assert message == "#{nickname} doesn't need confirmation." user = Repo.get(User, id) - refute user.confirmation_pending + assert user.is_confirmed refute user.confirmation_token end test "user is not confirmed" do %{id: id, nickname: nickname} = - insert(:user, confirmation_pending: true, confirmation_token: "some token") + insert(:user, is_confirmed: false, confirmation_token: "some token") assert :ok = Mix.Tasks.Pleroma.User.run(["confirm", nickname]) assert_received {:mix_shell, :info, [message]} assert message == "#{nickname} doesn't need confirmation." user = Repo.get(User, id) - refute user.confirmation_pending + assert user.is_confirmed refute user.confirmation_token end @@ -496,6 +466,37 @@ test "it prints an error message when user is not exist" do end end + describe "running activate" do + test "user is activated" do + %{id: id, nickname: nickname} = insert(:user, is_active: true) + + assert :ok = Mix.Tasks.Pleroma.User.run(["activate", nickname]) + assert_received {:mix_shell, :info, [message]} + assert message == "User #{nickname} already activated" + + user = Repo.get(User, id) + assert user.is_active + end + + test "user is not activated" do + %{id: id, nickname: nickname} = insert(:user, is_active: false) + + assert :ok = Mix.Tasks.Pleroma.User.run(["activate", nickname]) + assert_received {:mix_shell, :info, [message]} + assert message == "Successfully activated #{nickname}" + + user = Repo.get(User, id) + assert user.is_active + end + + test "no user to activate" do + Mix.Tasks.Pleroma.User.run(["activate", "foo"]) + + assert_received {:mix_shell, :error, [message]} + assert message =~ "No user" + end + end + describe "search" do test "it returns users matching" do user = insert(:user) @@ -579,29 +580,29 @@ test "it prints an error message when user is not exist" do describe "bulk confirm and unconfirm" do test "confirm all" do - user1 = insert(:user, confirmation_pending: true) - user2 = insert(:user, confirmation_pending: true) + user1 = insert(:user, is_confirmed: false) + user2 = insert(:user, is_confirmed: false) - assert user1.confirmation_pending - assert user2.confirmation_pending + refute user1.is_confirmed + refute user2.is_confirmed Mix.Tasks.Pleroma.User.run(["confirm_all"]) user1 = User.get_cached_by_nickname(user1.nickname) user2 = User.get_cached_by_nickname(user2.nickname) - refute user1.confirmation_pending - refute user2.confirmation_pending + assert user1.is_confirmed + assert user2.is_confirmed end test "unconfirm all" do - user1 = insert(:user, confirmation_pending: false) - user2 = insert(:user, confirmation_pending: false) - admin = insert(:user, is_admin: true, confirmation_pending: false) - mod = insert(:user, is_moderator: true, confirmation_pending: false) + user1 = insert(:user, is_confirmed: true) + user2 = insert(:user, is_confirmed: true) + admin = insert(:user, is_admin: true, is_confirmed: true) + mod = insert(:user, is_moderator: true, is_confirmed: true) - refute user1.confirmation_pending - refute user2.confirmation_pending + assert user1.is_confirmed + assert user2.is_confirmed Mix.Tasks.Pleroma.User.run(["unconfirm_all"]) @@ -610,10 +611,10 @@ test "unconfirm all" do admin = User.get_cached_by_nickname(admin.nickname) mod = User.get_cached_by_nickname(mod.nickname) - assert user1.confirmation_pending - assert user2.confirmation_pending - refute admin.confirmation_pending - refute mod.confirmation_pending + refute user1.is_confirmed + refute user2.is_confirmed + assert admin.is_confirmed + assert mod.is_confirmed end end end diff --git a/test/pleroma/config/deprecation_warnings_test.exs b/test/pleroma/config/deprecation_warnings_test.exs index 7dff93558..37e02fae2 100644 --- a/test/pleroma/config/deprecation_warnings_test.exs +++ b/test/pleroma/config/deprecation_warnings_test.exs @@ -94,6 +94,15 @@ test "check_activity_expiration_config/0" do end) =~ "Your config is using old namespace for activity expiration configuration." end + test "check_uploders_s3_public_endpoint/0" do + clear_config(Pleroma.Uploaders.S3, public_endpoint: "https://fake.amazonaws.com/bucket/") + + assert capture_log(fn -> + DeprecationWarnings.check_uploders_s3_public_endpoint() + end) =~ + "Your config is using the old setting for controlling the URL of media uploaded to your S3 bucket." + end + describe "check_gun_pool_options/0" do test "await_up_timeout" do config = Config.get(:connections_pool) diff --git a/test/pleroma/gun/connection_pool_test.exs b/test/pleroma/gun/connection_pool_test.exs index 459d19b11..9cbaf0978 100644 --- a/test/pleroma/gun/connection_pool_test.exs +++ b/test/pleroma/gun/connection_pool_test.exs @@ -19,7 +19,6 @@ defp gun_mock(_) do :ok end - setup :set_mox_from_context setup :gun_mock test "gives the same connection to 2 concurrent requests" do diff --git a/test/pleroma/object_test.exs b/test/pleroma/object_test.exs index 4a8d80fcc..db7678d5d 100644 --- a/test/pleroma/object_test.exs +++ b/test/pleroma/object_test.exs @@ -78,8 +78,8 @@ test "ensures cache is cleared for the object" do setup do: clear_config([:instance, :cleanup_attachments]) test "Disabled via config" do - Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) - Pleroma.Config.put([:instance, :cleanup_attachments], false) + clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) + clear_config([:instance, :cleanup_attachments], false) file = %Plug.Upload{ content_type: "image/jpeg", @@ -112,8 +112,8 @@ test "Disabled via config" do end test "in subdirectories" do - Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) - Pleroma.Config.put([:instance, :cleanup_attachments], true) + clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) + clear_config([:instance, :cleanup_attachments], true) file = %Plug.Upload{ content_type: "image/jpeg", @@ -146,9 +146,9 @@ test "in subdirectories" do end test "with dedupe enabled" do - Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) - Pleroma.Config.put([Pleroma.Upload, :filters], [Pleroma.Upload.Filter.Dedupe]) - Pleroma.Config.put([:instance, :cleanup_attachments], true) + clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) + clear_config([Pleroma.Upload, :filters], [Pleroma.Upload.Filter.Dedupe]) + clear_config([:instance, :cleanup_attachments], true) uploads_dir = Pleroma.Config.get!([Pleroma.Uploaders.Local, :uploads]) @@ -184,8 +184,8 @@ test "with dedupe enabled" do end test "with objects that have legacy data.url attribute" do - Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) - Pleroma.Config.put([:instance, :cleanup_attachments], true) + clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) + clear_config([:instance, :cleanup_attachments], true) file = %Plug.Upload{ content_type: "image/jpeg", @@ -220,9 +220,9 @@ test "with objects that have legacy data.url attribute" do end test "With custom base_url" do - Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) - Pleroma.Config.put([Pleroma.Upload, :base_url], "https://sub.domain.tld/dir/") - Pleroma.Config.put([:instance, :cleanup_attachments], true) + clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) + clear_config([Pleroma.Upload, :base_url], "https://sub.domain.tld/dir/") + clear_config([:instance, :cleanup_attachments], true) file = %Plug.Upload{ content_type: "image/jpeg", diff --git a/test/pleroma/repo/migrations/confirm_logged_in_users_test.exs b/test/pleroma/repo/migrations/confirm_logged_in_users_test.exs index b30faa257..99d17f62a 100644 --- a/test/pleroma/repo/migrations/confirm_logged_in_users_test.exs +++ b/test/pleroma/repo/migrations/confirm_logged_in_users_test.exs @@ -14,12 +14,12 @@ defmodule Pleroma.Repo.Migrations.ConfirmLoggedInUsersTest do test "up/0 confirms unconfirmed but previously-logged-in users", %{migration: migration} do insert_list(25, :oauth_token) - Repo.update_all(User, set: [confirmation_pending: true]) - insert_list(5, :user, confirmation_pending: true) + Repo.update_all(User, set: [is_confirmed: false]) + insert_list(5, :user, is_confirmed: false) count = User - |> where(confirmation_pending: true) + |> where(is_confirmed: false) |> Repo.aggregate(:count) assert count == 30 @@ -28,7 +28,7 @@ test "up/0 confirms unconfirmed but previously-logged-in users", %{migration: mi count = User - |> where(confirmation_pending: true) + |> where(is_confirmed: false) |> Repo.aggregate(:count) assert count == 5 diff --git a/test/pleroma/repo/migrations/deprecate_public_endpoint_test.exs b/test/pleroma/repo/migrations/deprecate_public_endpoint_test.exs new file mode 100644 index 000000000..2ffc1b145 --- /dev/null +++ b/test/pleroma/repo/migrations/deprecate_public_endpoint_test.exs @@ -0,0 +1,60 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Repo.Migrations.DeprecatePublicEndpointTest do + use Pleroma.DataCase + import Pleroma.Factory + import Pleroma.Tests.Helpers + alias Pleroma.ConfigDB + + setup do: clear_config(Pleroma.Upload) + setup do: clear_config(Pleroma.Uploaders.S3) + setup_all do: require_migration("20210113225652_deprecate_public_endpoint") + + test "up/0 migrates public_endpoint to base_url", %{migration: migration} do + s3_values = [ + public_endpoint: "https://coolhost.com/", + bucket: "secret_bucket" + ] + + insert(:config, group: :pleroma, key: Pleroma.Uploaders.S3, value: s3_values) + + upload_values = [ + uploader: Pleroma.Uploaders.S3 + ] + + insert(:config, group: :pleroma, key: Pleroma.Upload, value: upload_values) + + migration.up() + + assert [bucket: "secret_bucket"] == + ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Uploaders.S3}).value + + assert [uploader: Pleroma.Uploaders.S3, base_url: "https://coolhost.com/"] == + ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Upload}).value + end + + test "down/0 reverts base_url to public_endpoint", %{migration: migration} do + s3_values = [ + bucket: "secret_bucket" + ] + + insert(:config, group: :pleroma, key: Pleroma.Uploaders.S3, value: s3_values) + + upload_values = [ + uploader: Pleroma.Uploaders.S3, + base_url: "https://coolhost.com/" + ] + + insert(:config, group: :pleroma, key: Pleroma.Upload, value: upload_values) + + migration.down() + + assert [bucket: "secret_bucket", public_endpoint: "https://coolhost.com/"] == + ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Uploaders.S3}).value + + assert [uploader: Pleroma.Uploaders.S3] == + ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Upload}).value + end +end diff --git a/test/pleroma/scheduled_activity_test.exs b/test/pleroma/scheduled_activity_test.exs index b84ddcb8e..10188d116 100644 --- a/test/pleroma/scheduled_activity_test.exs +++ b/test/pleroma/scheduled_activity_test.exs @@ -4,15 +4,14 @@ defmodule Pleroma.ScheduledActivityTest do use Pleroma.DataCase - alias Pleroma.DataCase + alias Pleroma.ScheduledActivity + import Pleroma.Factory setup do: clear_config([ScheduledActivity, :enabled]) - setup context do - DataCase.ensure_local_uploader(context) - end + setup [:ensure_local_uploader] describe "creation" do test "scheduled activities with jobs when ScheduledActivity enabled" do diff --git a/test/pleroma/upload_test.exs b/test/pleroma/upload_test.exs index 8feb532d3..f1ab82a57 100644 --- a/test/pleroma/upload_test.exs +++ b/test/pleroma/upload_test.exs @@ -133,7 +133,7 @@ test "returns a media url" do assert %{"url" => [%{"href" => url}]} = data - assert String.starts_with?(url, Pleroma.Web.base_url() <> "/media/") + assert String.starts_with?(url, Pleroma.Upload.base_url()) end test "copies the file to the configured folder with deduping" do @@ -148,8 +148,8 @@ test "copies the file to the configured folder with deduping" do {:ok, data} = Upload.store(file, filters: [Pleroma.Upload.Filter.Dedupe]) assert List.first(data["url"])["href"] == - Pleroma.Web.base_url() <> - "/media/e30397b58d226d6583ab5b8b3c5defb0c682bda5c31ef07a9f57c1c4986e3781.jpg" + Pleroma.Upload.base_url() <> + "e30397b58d226d6583ab5b8b3c5defb0c682bda5c31ef07a9f57c1c4986e3781.jpg" end test "copies the file to the configured folder without deduping" do diff --git a/test/pleroma/uploaders/s3_test.exs b/test/pleroma/uploaders/s3_test.exs index 9c937d251..709631a6a 100644 --- a/test/pleroma/uploaders/s3_test.exs +++ b/test/pleroma/uploaders/s3_test.exs @@ -12,14 +12,10 @@ defmodule Pleroma.Uploaders.S3Test do import ExUnit.CaptureLog setup do - clear_config(Pleroma.Upload, - uploader: Pleroma.Uploaders.S3 - ) - - clear_config(Pleroma.Uploaders.S3, - bucket: "test_bucket", - public_endpoint: "https://s3.amazonaws.com" - ) + clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.S3) + clear_config([Pleroma.Upload, :base_url], "https://s3.amazonaws.com") + clear_config([Pleroma.Uploaders.S3]) + clear_config([Pleroma.Uploaders.S3, :bucket], "test_bucket") end describe "get_file/1" do @@ -33,10 +29,12 @@ test "it returns path to local folder for files" do test "it returns path without bucket when truncated_namespace set to ''" do Config.put([Pleroma.Uploaders.S3], bucket: "test_bucket", - public_endpoint: "https://s3.amazonaws.com", + bucket_namespace: "myaccount", truncated_namespace: "" ) + Config.put([Pleroma.Upload, :base_url], "https://s3.amazonaws.com") + assert S3.get_file("test_image.jpg") == { :ok, {:url, "https://s3.amazonaws.com/test_image.jpg"} @@ -46,7 +44,6 @@ test "it returns path without bucket when truncated_namespace set to ''" do test "it returns path with bucket namespace when namespace is set" do Config.put([Pleroma.Uploaders.S3], bucket: "test_bucket", - public_endpoint: "https://s3.amazonaws.com", bucket_namespace: "family" ) diff --git a/test/pleroma/user/backup_test.exs b/test/pleroma/user/backup_test.exs index 7fb4c5fbe..1aab25ba6 100644 --- a/test/pleroma/user/backup_test.exs +++ b/test/pleroma/user/backup_test.exs @@ -195,12 +195,8 @@ test "it creates a zip archive with user data" do describe "it uploads and deletes a backup archive" do setup do - clear_config(Pleroma.Uploaders.S3, - bucket: "test_bucket", - public_endpoint: "https://s3.amazonaws.com" - ) - - clear_config([Pleroma.Upload, :uploader]) + clear_config([Pleroma.Upload, :base_url], "https://s3.amazonaws.com") + clear_config([Pleroma.Uploaders.S3, :bucket], "test_bucket") user = insert(:user, %{nickname: "cofe", name: "Cofe", ap_id: "http://cofe.io/users/cofe"}) @@ -219,7 +215,8 @@ test "it creates a zip archive with user data" do end test "S3", %{path: path, backup: backup} do - Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.S3) + clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.S3) + clear_config([Pleroma.Uploaders.S3, :streaming_enabled], false) with_mock ExAws, request: fn @@ -229,13 +226,10 @@ test "S3", %{path: path, backup: backup} do assert {:ok, %Pleroma.Upload{}} = Backup.upload(backup, path) assert {:ok, _backup} = Backup.delete(backup) end - - with_mock ExAws, request: fn %{http_method: :delete} -> {:ok, %{status_code: 204}} end do - end end test "Local", %{path: path, backup: backup} do - Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) + clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) assert {:ok, %Pleroma.Upload{}} = Backup.upload(backup, path) assert {:ok, _backup} = Backup.delete(backup) diff --git a/test/pleroma/user_test.exs b/test/pleroma/user_test.exs index bdf17e96a..90fef34bd 100644 --- a/test/pleroma/user_test.exs +++ b/test/pleroma/user_test.exs @@ -202,11 +202,11 @@ test "doesn't return already accepted or duplicate follow requests" do test "doesn't return follow requests for deactivated accounts" do locked = insert(:user, is_locked: true) - pending_follower = insert(:user, %{deactivated: true}) + pending_follower = insert(:user, %{is_active: false}) CommonAPI.follow(pending_follower, locked) - assert true == pending_follower.deactivated + refute pending_follower.is_active assert [] = User.get_follow_requests(locked) end @@ -275,7 +275,7 @@ test "follow takes a user and another user" do test "can't follow a deactivated users" do user = insert(:user) - followed = insert(:user, %{deactivated: true}) + followed = insert(:user, %{is_active: false}) {:error, _} = User.follow(user, followed) end @@ -640,7 +640,7 @@ test "it creates a confirmed user" do {:ok, user} = Repo.insert(changeset) - refute user.confirmation_pending + assert user.is_confirmed end end @@ -661,17 +661,17 @@ test "it creates unconfirmed user" do {:ok, user} = Repo.insert(changeset) - assert user.confirmation_pending + refute user.is_confirmed assert user.confirmation_token end test "it creates confirmed user if :confirmed option is given" do - changeset = User.register_changeset(%User{}, @full_user_data, need_confirmation: false) + changeset = User.register_changeset(%User{}, @full_user_data, confirmed: true) assert changeset.valid? {:ok, user} = Repo.insert(changeset) - refute user.confirmation_pending + assert user.is_confirmed refute user.confirmation_token end end @@ -694,7 +694,7 @@ test "it creates unapproved user" do {:ok, user} = Repo.insert(changeset) - assert user.approval_pending + refute user.is_approved assert user.registration_reason == "I'm a cool guy :)" end @@ -1313,14 +1313,14 @@ test "has following" do end end - describe ".deactivate" do + describe ".set_activation" do test "can de-activate then re-activate a user" do user = insert(:user) - assert false == user.deactivated - {:ok, user} = User.deactivate(user) - assert true == user.deactivated - {:ok, user} = User.deactivate(user, false) - assert false == user.deactivated + assert user.is_active + {:ok, user} = User.set_activation(user, false) + refute user.is_active + {:ok, user} = User.set_activation(user, true) + assert user.is_active end test "hide a user from followers" do @@ -1328,7 +1328,7 @@ test "hide a user from followers" do user2 = insert(:user) {:ok, user, user2} = User.follow(user, user2) - {:ok, _user} = User.deactivate(user) + {:ok, _user} = User.set_activation(user, false) user2 = User.get_cached_by_id(user2.id) @@ -1344,7 +1344,7 @@ test "hide a user from friends" do assert user2.following_count == 1 assert User.following_count(user2) == 1 - {:ok, _user} = User.deactivate(user) + {:ok, _user} = User.set_activation(user, false) user2 = User.get_cached_by_id(user2.id) @@ -1374,7 +1374,7 @@ test "hide a user's statuses from timelines and notifications" do user: user2 }) - {:ok, _user} = User.deactivate(user) + {:ok, _user} = User.set_activation(user, false) assert [] == ActivityPub.fetch_public_activities(%{}) assert [] == Pleroma.Notification.for_user(user2) @@ -1388,17 +1388,17 @@ test "hide a user's statuses from timelines and notifications" do describe "approve" do test "approves a user" do - user = insert(:user, approval_pending: true) - assert true == user.approval_pending + user = insert(:user, is_approved: false) + refute user.is_approved {:ok, user} = User.approve(user) - assert false == user.approval_pending + assert user.is_approved end test "approves a list of users" do unapproved_users = [ - insert(:user, approval_pending: true), - insert(:user, approval_pending: true), - insert(:user, approval_pending: true) + insert(:user, is_approved: false), + insert(:user, is_approved: false), + insert(:user, is_approved: false) ] {:ok, users} = User.approve(unapproved_users) @@ -1406,7 +1406,7 @@ test "approves a list of users" do assert Enum.count(users) == 3 Enum.each(users, fn user -> - assert false == user.approval_pending + assert user.is_approved end) end @@ -1414,7 +1414,7 @@ test "it sends welcome email if it is set" do clear_config([:welcome, :email, :enabled], true) clear_config([:welcome, :email, :sender], "tester@test.me") - user = insert(:user, approval_pending: true) + user = insert(:user, is_approved: false) welcome_user = insert(:user, email: "tester@test.me") instance_name = Pleroma.Config.get([:instance, :name]) @@ -1432,7 +1432,7 @@ test "it sends welcome email if it is set" do test "approving an approved user does not trigger post-register actions" do clear_config([:welcome, :email, :enabled], true) - user = insert(:user, approval_pending: false) + user = insert(:user, is_approved: true) User.approve(user) ObanHelpers.perform_all() @@ -1443,17 +1443,17 @@ test "approving an approved user does not trigger post-register actions" do describe "confirm" do test "confirms a user" do - user = insert(:user, confirmation_pending: true) - assert true == user.confirmation_pending + user = insert(:user, is_confirmed: false) + refute user.is_confirmed {:ok, user} = User.confirm(user) - assert false == user.confirmation_pending + assert user.is_confirmed end test "confirms a list of users" do unconfirmed_users = [ - insert(:user, confirmation_pending: true), - insert(:user, confirmation_pending: true), - insert(:user, confirmation_pending: true) + insert(:user, is_confirmed: false), + insert(:user, is_confirmed: false), + insert(:user, is_confirmed: false) ] {:ok, users} = User.confirm(unconfirmed_users) @@ -1461,13 +1461,13 @@ test "confirms a list of users" do assert Enum.count(users) == 3 Enum.each(users, fn user -> - assert false == user.confirmation_pending + assert user.is_confirmed end) end - test "sends approval emails when `approval_pending: true`" do + test "sends approval emails when `is_approved: false`" do admin = insert(:user, is_admin: true) - user = insert(:user, confirmation_pending: true, approval_pending: true) + user = insert(:user, is_confirmed: false, is_approved: false) User.confirm(user) ObanHelpers.perform_all() @@ -1494,7 +1494,7 @@ test "sends approval emails when `approval_pending: true`" do end test "confirming a confirmed user does not trigger post-register actions" do - user = insert(:user, confirmation_pending: false, approval_pending: true) + user = insert(:user, is_confirmed: true, is_approved: false) User.confirm(user) ObanHelpers.perform_all() @@ -1544,7 +1544,7 @@ test "it deactivates a user, all follow relationships and all activities", %{use follower = User.get_cached_by_id(follower.id) refute User.following?(follower, user) - assert %{deactivated: true} = User.get_by_id(user.id) + assert %{is_active: false} = User.get_by_id(user.id) assert [] == User.get_follow_requests(locked_user) @@ -1563,35 +1563,19 @@ test "it deactivates a user, all follow relationships and all activities", %{use end end - describe "delete/1 when confirmation is pending" do - setup do - user = insert(:user, confirmation_pending: true) - {:ok, user: user} - end + test "delete/1 when confirmation is pending deletes the user" do + clear_config([:instance, :account_activation_required], true) + user = insert(:user, is_confirmed: false) - test "deletes user from database when activation required", %{user: user} do - clear_config([:instance, :account_activation_required], true) + {:ok, job} = User.delete(user) + {:ok, _} = ObanHelpers.perform(job) - {:ok, job} = User.delete(user) - {:ok, _} = ObanHelpers.perform(job) - - refute User.get_cached_by_id(user.id) - refute User.get_by_id(user.id) - end - - test "deactivates user when activation is not required", %{user: user} do - clear_config([:instance, :account_activation_required], false) - - {:ok, job} = User.delete(user) - {:ok, _} = ObanHelpers.perform(job) - - assert %{deactivated: true} = User.get_cached_by_id(user.id) - assert %{deactivated: true} = User.get_by_id(user.id) - end + refute User.get_cached_by_id(user.id) + refute User.get_by_id(user.id) end test "delete/1 when approval is pending deletes the user" do - user = insert(:user, approval_pending: true) + user = insert(:user, is_approved: false) {:ok, job} = User.delete(user) {:ok, _} = ObanHelpers.perform(job) @@ -1616,13 +1600,13 @@ test "delete/1 purges a user when they wouldn't be fully deleted" do follower_count: 9, following_count: 9001, is_locked: true, - confirmation_pending: true, + is_confirmed: false, password_reset_pending: true, - approval_pending: true, + is_approved: false, registration_reason: "ahhhhh", confirmation_token: "qqqq", domain_blocks: ["lain.com"], - deactivated: true, + is_active: false, ap_enabled: true, is_moderator: true, is_admin: true, @@ -1658,13 +1642,13 @@ test "delete/1 purges a user when they wouldn't be fully deleted" do follower_count: 0, following_count: 0, is_locked: false, - confirmation_pending: false, + is_confirmed: true, password_reset_pending: false, - approval_pending: false, + is_approved: true, registration_reason: nil, confirmation_token: nil, domain_blocks: [], - deactivated: true, + is_active: false, ap_enabled: false, is_moderator: false, is_admin: false, @@ -1729,13 +1713,13 @@ test "User.delete() plugs any possible zombie objects" do test "return confirmation_pending for unconfirm user" do Pleroma.Config.put([:instance, :account_activation_required], true) - user = insert(:user, confirmation_pending: true) + user = insert(:user, is_confirmed: false) assert User.account_status(user) == :confirmation_pending end test "return active for confirmed user" do Pleroma.Config.put([:instance, :account_activation_required], true) - user = insert(:user, confirmation_pending: false) + user = insert(:user, is_confirmed: true) assert User.account_status(user) == :active end @@ -1750,15 +1734,15 @@ test "returns :password_reset_pending for user with reset password" do end test "returns :deactivated for deactivated user" do - user = insert(:user, local: true, confirmation_pending: false, deactivated: true) + user = insert(:user, local: true, is_confirmed: true, is_active: false) assert User.account_status(user) == :deactivated end test "returns :approval_pending for unapproved user" do - user = insert(:user, local: true, approval_pending: true) + user = insert(:user, local: true, is_approved: false) assert User.account_status(user) == :approval_pending - user = insert(:user, local: true, confirmation_pending: true, approval_pending: true) + user = insert(:user, local: true, is_confirmed: false, is_approved: false) assert User.account_status(user) == :approval_pending end end @@ -1815,7 +1799,7 @@ test "returns true when the account is itself" do test "returns false when the account is unconfirmed and confirmation is required" do Pleroma.Config.put([:instance, :account_activation_required], true) - user = insert(:user, local: true, confirmation_pending: true) + user = insert(:user, local: true, is_confirmed: false) other_user = insert(:user, local: true) refute User.visible_for(user, other_user) == :visible @@ -1824,14 +1808,7 @@ test "returns false when the account is unconfirmed and confirmation is required test "returns true when the account is unconfirmed and confirmation is required but the account is remote" do Pleroma.Config.put([:instance, :account_activation_required], true) - user = insert(:user, local: false, confirmation_pending: true) - other_user = insert(:user, local: true) - - assert User.visible_for(user, other_user) == :visible - end - - test "returns true when the account is unconfirmed and confirmation is not required" do - user = insert(:user, local: true, confirmation_pending: true) + user = insert(:user, local: false, is_confirmed: false) other_user = insert(:user, local: true) assert User.visible_for(user, other_user) == :visible @@ -1840,7 +1817,7 @@ test "returns true when the account is unconfirmed and confirmation is not requi test "returns true when the account is unconfirmed and being viewed by a privileged account (confirmation required)" do Pleroma.Config.put([:instance, :account_activation_required], true) - user = insert(:user, local: true, confirmation_pending: true) + user = insert(:user, local: true, is_confirmed: false) other_user = insert(:user, local: true, is_admin: true) assert User.visible_for(user, other_user) == :visible @@ -1908,7 +1885,7 @@ test "Users are inactive by default" do users = Enum.map(1..total, fn _ -> - insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false) + insert(:user, last_digest_emailed_at: days_ago(20), is_active: true) end) inactive_users_ids = @@ -1926,7 +1903,7 @@ test "Only includes users who has no recent activity" do users = Enum.map(1..total, fn _ -> - insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false) + insert(:user, last_digest_emailed_at: days_ago(20), is_active: true) end) {inactive, active} = Enum.split(users, trunc(total / 2)) @@ -1959,7 +1936,7 @@ test "Only includes users with no read notifications" do users = Enum.map(1..total, fn _ -> - insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false) + insert(:user, last_digest_emailed_at: days_ago(20), is_active: true) end) [sender | recipients] = users @@ -2029,7 +2006,7 @@ test "it returns a list of AP ids for a given set of nicknames" do user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed") user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2") insert(:user, local: true) - insert(:user, local: false, deactivated: true) + insert(:user, local: false, is_active: false) {:ok, user1: user1, user2: user2} end diff --git a/test/pleroma/web/activity_pub/side_effects/delete_test.exs b/test/pleroma/web/activity_pub/side_effects/delete_test.exs index 35ced375b..20f0d4b70 100644 --- a/test/pleroma/web/activity_pub/side_effects/delete_test.exs +++ b/test/pleroma/web/activity_pub/side_effects/delete_test.exs @@ -39,7 +39,7 @@ test "it handles user deletions", %{delete_user: delete, user: user} do {:ok, _delete, _} = SideEffects.handle(delete) ObanHelpers.perform_all() - assert User.get_cached_by_ap_id(user.ap_id).deactivated + refute User.get_cached_by_ap_id(user.ap_id).is_active end end diff --git a/test/pleroma/web/activity_pub/side_effects_test.exs b/test/pleroma/web/activity_pub/side_effects_test.exs index 2d94f07c9..13167f50a 100644 --- a/test/pleroma/web/activity_pub/side_effects_test.exs +++ b/test/pleroma/web/activity_pub/side_effects_test.exs @@ -159,20 +159,12 @@ test "creates a notification", %{emoji_react: emoji_react, poster: poster} do describe "delete users with confirmation pending" do setup do - user = insert(:user, confirmation_pending: true) + user = insert(:user, is_confirmed: false) {:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id) {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true) {:ok, delete: delete_user, user: user} end - test "when activation is not required", %{delete: delete, user: user} do - clear_config([:instance, :account_activation_required], false) - {:ok, _, _} = SideEffects.handle(delete) - ObanHelpers.perform_all() - - assert User.get_cached_by_id(user.id).deactivated - end - test "when activation is required", %{delete: delete, user: user} do clear_config([:instance, :account_activation_required], true) {:ok, _, _} = SideEffects.handle(delete) diff --git a/test/pleroma/web/activity_pub/transmogrifier/chat_message_test.exs b/test/pleroma/web/activity_pub/transmogrifier/chat_message_test.exs index a2d64620d..958675835 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/chat_message_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/chat_message_test.exs @@ -134,7 +134,7 @@ test "it doesn't work for deactivated users" do ap_id: data["actor"], local: false, last_refreshed_at: DateTime.utc_now(), - deactivated: true + is_active: false ) _recipient = insert(:user, ap_id: List.first(data["to"]), local: true) diff --git a/test/pleroma/web/activity_pub/transmogrifier/delete_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/delete_handling_test.exs index 33132dff6..b7160bf58 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/delete_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/delete_handling_test.exs @@ -97,7 +97,7 @@ test "it works for incoming user deletes" do {:ok, _} = Transmogrifier.handle_incoming(data) ObanHelpers.perform_all() - assert User.get_cached_by_ap_id(ap_id).deactivated + refute User.get_cached_by_ap_id(ap_id).is_active end test "it fails for incoming user deletes with spoofed origin" do diff --git a/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs index 108f27ef7..be99ad93d 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs @@ -154,7 +154,7 @@ test "it does not crash if the object in inReplyTo can't be fetched" do test "it does not work for deactivated users" do data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!() - insert(:user, ap_id: data["actor"], deactivated: true) + insert(:user, ap_id: data["actor"], is_active: false) assert {:error, _} = Transmogrifier.handle_incoming(data) end diff --git a/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs b/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs index c54402e52..23e4bc3af 100644 --- a/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs @@ -891,10 +891,10 @@ test "GET /instances/:instance/statuses", %{conn: conn} do describe "PATCH /confirm_email" do test "it confirms emails of two users", %{conn: conn, admin: admin} do - [first_user, second_user] = insert_pair(:user, confirmation_pending: true) + [first_user, second_user] = insert_pair(:user, is_confirmed: false) - assert first_user.confirmation_pending == true - assert second_user.confirmation_pending == true + refute first_user.is_confirmed + refute second_user.is_confirmed ret_conn = patch(conn, "/api/pleroma/admin/users/confirm_email", %{ @@ -906,8 +906,11 @@ test "it confirms emails of two users", %{conn: conn, admin: admin} do assert ret_conn.status == 200 - assert first_user.confirmation_pending == true - assert second_user.confirmation_pending == true + first_user = User.get_by_id(first_user.id) + second_user = User.get_by_id(second_user.id) + + assert first_user.is_confirmed + assert second_user.is_confirmed log_entry = Repo.one(ModerationLog) @@ -920,7 +923,7 @@ test "it confirms emails of two users", %{conn: conn, admin: admin} do describe "PATCH /resend_confirmation_email" do test "it resend emails for two users", %{conn: conn, admin: admin} do - [first_user, second_user] = insert_pair(:user, confirmation_pending: true) + [first_user, second_user] = insert_pair(:user, is_confirmed: false) ret_conn = patch(conn, "/api/pleroma/admin/users/resend_confirmation_email", %{ diff --git a/test/pleroma/web/admin_api/controllers/status_controller_test.exs b/test/pleroma/web/admin_api/controllers/status_controller_test.exs index 976990d5c..3fdf23ba2 100644 --- a/test/pleroma/web/admin_api/controllers/status_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/status_controller_test.exs @@ -47,8 +47,8 @@ test "shows activity", %{conn: conn} do assert account["id"] == actor.id assert account["nickname"] == actor.nickname - assert account["deactivated"] == actor.deactivated - assert account["confirmation_pending"] == actor.confirmation_pending + assert account["is_active"] == actor.is_active + assert account["is_confirmed"] == actor.is_confirmed end end diff --git a/test/pleroma/web/admin_api/controllers/user_controller_test.exs b/test/pleroma/web/admin_api/controllers/user_controller_test.exs index 40d39aae7..ef16dede3 100644 --- a/test/pleroma/web/admin_api/controllers/user_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/user_controller_test.exs @@ -169,7 +169,7 @@ test "single user", %{admin: admin, conn: conn} do assert user.note_count == 1 assert user.follower_count == 1 assert user.following_count == 1 - refute user.deactivated + assert user.is_active with_mock Pleroma.Web.Federator, publish: fn _ -> nil end, @@ -181,7 +181,7 @@ test "single user", %{admin: admin, conn: conn} do ObanHelpers.perform_all() - assert User.get_by_nickname(user.nickname).deactivated + refute User.get_by_nickname(user.nickname).is_active log_entry = Repo.one(ModerationLog) @@ -191,7 +191,7 @@ test "single user", %{admin: admin, conn: conn} do assert json_response(conn, 200) == [user.nickname] user = Repo.get(User, user.id) - assert user.deactivated + refute user.is_active assert user.avatar == %{} assert user.banner == %{} @@ -429,7 +429,7 @@ test "allows to force-unfollow another user", %{admin: admin, conn: conn} do describe "GET /api/pleroma/admin/users" do test "renders users array for the first page", %{conn: conn, admin: admin} do user = insert(:user, local: false, tags: ["foo", "bar"]) - user2 = insert(:user, approval_pending: true, registration_reason: "I'm a chill dude") + user2 = insert(:user, is_approved: false, registration_reason: "I'm a chill dude") conn = get(conn, "/api/pleroma/admin/users?page=1") @@ -444,7 +444,7 @@ test "renders users array for the first page", %{conn: conn, admin: admin} do user2, %{ "local" => true, - "approval_pending" => true, + "is_approved" => false, "registration_reason" => "I'm a chill dude", "actor_type" => "Person" } @@ -621,7 +621,7 @@ test "only local users with no query", %{conn: conn, admin: old_admin} do "roles" => %{"admin" => true, "moderator" => false} }), user_response(old_admin, %{ - "deactivated" => false, + "is_active" => true, "roles" => %{"admin" => true, "moderator" => false} }) ] @@ -635,11 +635,11 @@ test "only local users with no query", %{conn: conn, admin: old_admin} do end test "only unconfirmed users", %{conn: conn} do - sad_user = insert(:user, nickname: "sadboy", confirmation_pending: true) - old_user = insert(:user, nickname: "oldboy", confirmation_pending: true) + sad_user = insert(:user, nickname: "sadboy", is_confirmed: false) + old_user = insert(:user, nickname: "oldboy", is_confirmed: false) - insert(:user, nickname: "happyboy", approval_pending: false) - insert(:user, confirmation_pending: false) + insert(:user, nickname: "happyboy", is_approved: true) + insert(:user, is_confirmed: true) result = conn @@ -649,8 +649,8 @@ test "only unconfirmed users", %{conn: conn} do users = Enum.map([old_user, sad_user], fn user -> user_response(user, %{ - "confirmation_pending" => true, - "approval_pending" => false + "is_confirmed" => false, + "is_approved" => true }) end) |> Enum.sort_by(& &1["nickname"]) @@ -662,18 +662,18 @@ test "only unapproved users", %{conn: conn} do user = insert(:user, nickname: "sadboy", - approval_pending: true, + is_approved: false, registration_reason: "Plz let me in!" ) - insert(:user, nickname: "happyboy", approval_pending: false) + insert(:user, nickname: "happyboy", is_approved: true) conn = get(conn, "/api/pleroma/admin/users?filters=need_approval") users = [ user_response( user, - %{"approval_pending" => true, "registration_reason" => "Plz let me in!"} + %{"is_approved" => false, "registration_reason" => "Plz let me in!"} ) ] @@ -694,11 +694,11 @@ test "load only admins", %{conn: conn, admin: admin} do users = [ user_response(admin, %{ - "deactivated" => false, + "is_active" => true, "roles" => %{"admin" => true, "moderator" => false} }), user_response(second_admin, %{ - "deactivated" => false, + "is_active" => true, "roles" => %{"admin" => true, "moderator" => false} }) ] @@ -723,7 +723,7 @@ test "load only moderators", %{conn: conn} do "page_size" => 50, "users" => [ user_response(moderator, %{ - "deactivated" => false, + "is_active" => true, "roles" => %{"admin" => false, "moderator" => true} }) ] @@ -816,8 +816,8 @@ test "load users with tags list", %{conn: conn} do end test "`active` filters out users pending approval", %{token: token} do - insert(:user, approval_pending: true) - %{id: user_id} = insert(:user, approval_pending: false) + insert(:user, is_approved: false) + %{id: user_id} = insert(:user, is_approved: true) %{id: admin_id} = token.user conn = @@ -839,10 +839,10 @@ test "`active` filters out users pending approval", %{token: token} do test "it works with multiple filters" do admin = insert(:user, nickname: "john", is_admin: true) token = insert(:oauth_admin_token, user: admin) - user = insert(:user, nickname: "bob", local: false, deactivated: true) + user = insert(:user, nickname: "bob", local: false, is_active: false) - insert(:user, nickname: "ken", local: true, deactivated: true) - insert(:user, nickname: "bobb", local: false, deactivated: false) + insert(:user, nickname: "ken", local: true, is_active: false) + insert(:user, nickname: "bobb", local: false, is_active: true) conn = build_conn() @@ -873,8 +873,8 @@ test "it omits relay user", %{admin: admin, conn: conn} do end test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do - user_one = insert(:user, deactivated: true) - user_two = insert(:user, deactivated: true) + user_one = insert(:user, is_active: false) + user_two = insert(:user, is_active: false) conn = patch( @@ -884,7 +884,7 @@ test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do ) response = json_response(conn, 200) - assert Enum.map(response["users"], & &1["deactivated"]) == [false, false] + assert Enum.map(response["users"], & &1["is_active"]) == [true, true] log_entry = Repo.one(ModerationLog) @@ -893,8 +893,8 @@ test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do end test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do - user_one = insert(:user, deactivated: false) - user_two = insert(:user, deactivated: false) + user_one = insert(:user, is_active: true) + user_two = insert(:user, is_active: true) conn = patch( @@ -904,7 +904,7 @@ test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do ) response = json_response(conn, 200) - assert Enum.map(response["users"], & &1["deactivated"]) == [true, true] + assert Enum.map(response["users"], & &1["is_active"]) == [false, false] log_entry = Repo.one(ModerationLog) @@ -913,8 +913,8 @@ test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do end test "PATCH /api/pleroma/admin/users/approve", %{admin: admin, conn: conn} do - user_one = insert(:user, approval_pending: true) - user_two = insert(:user, approval_pending: true) + user_one = insert(:user, is_approved: false) + user_two = insert(:user, is_approved: false) conn = patch( @@ -924,7 +924,7 @@ test "PATCH /api/pleroma/admin/users/approve", %{admin: admin, conn: conn} do ) response = json_response(conn, 200) - assert Enum.map(response["users"], & &1["approval_pending"]) == [false, false] + assert Enum.map(response["users"], & &1["is_approved"]) == [true, true] log_entry = Repo.one(ModerationLog) @@ -940,7 +940,7 @@ test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admi assert json_response(conn, 200) == user_response( user, - %{"deactivated" => !user.deactivated} + %{"is_active" => !user.is_active} ) log_entry = Repo.one(ModerationLog) @@ -951,7 +951,7 @@ test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admi defp user_response(user, attrs \\ %{}) do %{ - "deactivated" => user.deactivated, + "is_active" => user.is_active, "id" => user.id, "email" => user.email, "nickname" => user.nickname, @@ -960,8 +960,8 @@ defp user_response(user, attrs \\ %{}) do "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user.name || user.nickname), - "confirmation_pending" => false, - "approval_pending" => false, + "is_confirmed" => true, + "is_approved" => true, "url" => user.ap_id, "registration_reason" => nil, "actor_type" => "Person" diff --git a/test/pleroma/web/admin_api/search_test.exs b/test/pleroma/web/admin_api/search_test.exs index 307578ae0..b8eeec65b 100644 --- a/test/pleroma/web/admin_api/search_test.exs +++ b/test/pleroma/web/admin_api/search_test.exs @@ -47,9 +47,9 @@ test "it returns local/external users" do end test "it returns active/deactivated users" do - insert(:user, deactivated: true) - insert(:user, deactivated: true) - insert(:user, deactivated: false) + insert(:user, is_active: false) + insert(:user, is_active: false) + insert(:user, is_active: true) {:ok, _results, active_count} = Search.user(%{ @@ -70,7 +70,7 @@ test "it returns active/deactivated users" do test "it returns specific user" do insert(:user) insert(:user) - user = insert(:user, nickname: "bob", local: true, deactivated: false) + user = insert(:user, nickname: "bob", local: true, is_active: true) {:ok, _results, total_count} = Search.user(%{query: ""}) @@ -182,7 +182,7 @@ test "it returns user by email" do end test "it returns unapproved user" do - unapproved = insert(:user, approval_pending: true) + unapproved = insert(:user, is_approved: false) insert(:user) insert(:user) @@ -193,7 +193,7 @@ test "it returns unapproved user" do end test "it returns unconfirmed user" do - unconfirmed = insert(:user, confirmation_pending: true) + unconfirmed = insert(:user, is_confirmed: false) insert(:user) insert(:user) diff --git a/test/pleroma/web/common_api_test.exs b/test/pleroma/web/common_api_test.exs index 2ece92806..c996766ea 100644 --- a/test/pleroma/web/common_api_test.exs +++ b/test/pleroma/web/common_api_test.exs @@ -518,7 +518,7 @@ test "it adds an emoji on an external site" do end test "deactivated users can't post" do - user = insert(:user, deactivated: true) + user = insert(:user, is_active: false) assert {:error, _} = CommonAPI.post(user, %{status: "ye"}) end @@ -744,6 +744,22 @@ test "repeating a status privately" do refute Visibility.visible_for_user?(announce_activity, nil) end + test "author can repeat own private statuses" do + author = insert(:user) + follower = insert(:user) + CommonAPI.follow(follower, author) + + {:ok, activity} = CommonAPI.post(author, %{status: "cofe", visibility: "private"}) + + {:ok, %Activity{} = announce_activity} = CommonAPI.repeat(activity.id, author) + + assert Visibility.is_private?(announce_activity) + refute Visibility.visible_for_user?(announce_activity, nil) + + assert Visibility.visible_for_user?(activity, follower) + assert {:error, :not_found} = CommonAPI.repeat(activity.id, follower) + end + test "favoriting a status" do user = insert(:user) other_user = insert(:user) diff --git a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs index 7b3cc7344..1276597a4 100644 --- a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs @@ -126,7 +126,7 @@ test "returns 404 for internal.fetch actor", %{conn: conn} do end test "returns 404 for deactivated user", %{conn: conn} do - user = insert(:user, deactivated: true) + user = insert(:user, is_active: false) assert %{"error" => "Can't find user"} = conn @@ -256,7 +256,7 @@ test "works with announces that are just addressed to public", %{conn: conn} do end test "deactivated user", %{conn: conn} do - user = insert(:user, deactivated: true) + user = insert(:user, is_active: false) assert %{"error" => "Can't find user"} == conn @@ -1027,8 +1027,8 @@ test "registers and logs in without :account_activation_required / :account_appr user = Repo.preload(token_from_db, :user).user assert user - refute user.confirmation_pending - refute user.approval_pending + assert user.is_confirmed + assert user.is_approved end test "registers but does not log in with :account_activation_required", %{conn: conn} do @@ -1088,7 +1088,7 @@ test "registers but does not log in with :account_activation_required", %{conn: refute response["token_type"] user = Repo.get_by(User, email: "lain@example.org") - assert user.confirmation_pending + refute user.is_confirmed end test "registers but does not log in with :account_approval_required", %{conn: conn} do @@ -1150,7 +1150,7 @@ test "registers but does not log in with :account_approval_required", %{conn: co user = Repo.get_by(User, email: "lain@example.org") - assert user.approval_pending + refute user.is_approved assert user.registration_reason == "I'm a cool dude, bro" end diff --git a/test/pleroma/web/mastodon_api/controllers/auth_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/auth_controller_test.exs index 27c0fceff..1872dfd59 100644 --- a/test/pleroma/web/mastodon_api/controllers/auth_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/auth_controller_test.exs @@ -136,7 +136,7 @@ test "it returns 204 when user is not local", %{conn: conn, user: user} do end test "it returns 204 when user is deactivated", %{conn: conn, user: user} do - {:ok, user} = Repo.update(Ecto.Changeset.change(user, deactivated: true, local: true)) + {:ok, user} = Repo.update(Ecto.Changeset.change(user, is_active: false, local: true)) conn = post(conn, "/auth/password?email=#{user.email}") assert empty_json_response(conn) diff --git a/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs index 1d0f86e87..0d4eebb73 100644 --- a/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs @@ -57,7 +57,7 @@ test "get instance stats", %{conn: conn} do user = insert(:user, %{local: true}) user2 = insert(:user, %{local: true}) - {:ok, _user2} = User.deactivate(user2, !user2.deactivated) + {:ok, _user2} = User.set_activation(user2, false) insert(:user, %{local: false, nickname: "u@peer1.com"}) insert(:user, %{local: false, nickname: "u@peer2.com"}) diff --git a/test/pleroma/web/mastodon_api/controllers/poll_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/poll_controller_test.exs index 95df48ab0..da0a631a9 100644 --- a/test/pleroma/web/mastodon_api/controllers/poll_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/poll_controller_test.exs @@ -47,6 +47,78 @@ test "does not expose polls for private statuses", %{conn: conn} do end end + test "own_votes" do + %{conn: conn} = oauth_access(["write:statuses", "read:statuses"]) + + other_user = insert(:user) + + {:ok, activity} = + CommonAPI.post(other_user, %{ + status: "A very delicious sandwich", + poll: %{ + options: ["Lettuce", "Grilled Bacon", "Tomato"], + expires_in: 20, + multiple: true + } + }) + + object = Object.normalize(activity, fetch: false) + + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 2]}) + |> json_response_and_validate_schema(200) + + object = Object.get_by_id(object.id) + + assert [ + %{ + "name" => "Lettuce", + "replies" => %{"totalItems" => 1, "type" => "Collection"}, + "type" => "Note" + }, + %{ + "name" => "Grilled Bacon", + "replies" => %{"totalItems" => 0, "type" => "Collection"}, + "type" => "Note" + }, + %{ + "name" => "Tomato", + "replies" => %{"totalItems" => 1, "type" => "Collection"}, + "type" => "Note" + } + ] == object.data["anyOf"] + + assert %{"replies" => %{"totalItems" => 0}} = + Enum.find(object.data["anyOf"], fn %{"name" => name} -> name == "Grilled Bacon" end) + + Enum.each(["Lettuce", "Tomato"], fn title -> + %{"replies" => %{"totalItems" => total_items}} = + Enum.find(object.data["anyOf"], fn %{"name" => name} -> name == title end) + + assert total_items == 1 + end) + + assert %{ + "own_votes" => own_votes, + "voted" => true + } = + conn + |> get("/api/v1/polls/#{object.id}") + |> json_response_and_validate_schema(200) + + assert 0 in own_votes + assert 2 in own_votes + # for non authenticated user + response = + build_conn() + |> get("/api/v1/polls/#{object.id}") + |> json_response_and_validate_schema(200) + + refute Map.has_key?(response, "own_votes") + refute Map.has_key?(response, "voted") + end + describe "POST /api/v1/polls/:id/votes" do setup do: oauth_access(["write:statuses"]) @@ -65,12 +137,11 @@ test "votes are added to the poll", %{conn: conn} do object = Object.normalize(activity, fetch: false) - conn = - conn - |> put_req_header("content-type", "application/json") - |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]}) + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]}) + |> json_response_and_validate_schema(200) - assert json_response_and_validate_schema(conn, 200) object = Object.get_by_id(object.id) assert Enum.all?(object.data["anyOf"], fn %{"replies" => %{"totalItems" => total_items}} -> diff --git a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs index 8a2267099..bfb44374e 100644 --- a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs @@ -954,6 +954,23 @@ test "reblogged status for another user" do assert to_string(activity.id) == id end + + test "author can reblog own private status", %{conn: conn, user: user} do + {:ok, activity} = CommonAPI.post(user, %{status: "cofe", visibility: "private"}) + + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/#{activity.id}/reblog") + + assert %{ + "reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}, + "reblogged" => true, + "visibility" => "private" + } = json_response_and_validate_schema(conn, 200) + + assert to_string(activity.id) == id + end end describe "unreblogging" do diff --git a/test/pleroma/web/mastodon_api/mastodon_api_test.exs b/test/pleroma/web/mastodon_api/mastodon_api_test.exs index f14330908..402bfd76f 100644 --- a/test/pleroma/web/mastodon_api/mastodon_api_test.exs +++ b/test/pleroma/web/mastodon_api/mastodon_api_test.exs @@ -16,7 +16,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPITest do describe "follow/3" do test "returns error when followed user is deactivated" do follower = insert(:user) - user = insert(:user, local: true, deactivated: true) + user = insert(:user, local: true, is_active: false) assert {:error, _error} = MastodonAPI.follow(follower, user) end diff --git a/test/pleroma/web/mastodon_api/views/account_view_test.exs b/test/pleroma/web/mastodon_api/views/account_view_test.exs index 32fe08196..6de5dc859 100644 --- a/test/pleroma/web/mastodon_api/views/account_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/account_view_test.exs @@ -79,7 +79,7 @@ test "Represent a user account" do also_known_as: ["https://shitposter.zone/users/shp"], background_image: "https://example.com/images/asuka_hospital.png", favicon: nil, - confirmation_pending: false, + is_confirmed: true, tags: [], is_admin: false, is_moderator: false, @@ -178,7 +178,7 @@ test "Represent a Service(bot) account" do also_known_as: [], background_image: nil, favicon: nil, - confirmation_pending: false, + is_confirmed: true, tags: [], is_admin: false, is_moderator: false, @@ -211,7 +211,7 @@ test "Represent a Funkwhale channel" do test "Represent a deactivated user for an admin" do admin = insert(:user, is_admin: true) - deactivated_user = insert(:user, deactivated: true) + deactivated_user = insert(:user, is_active: false) represented = AccountView.render("show.json", %{user: deactivated_user, for: admin}) assert represented[:pleroma][:deactivated] == true end diff --git a/test/pleroma/web/mastodon_api/views/poll_view_test.exs b/test/pleroma/web/mastodon_api/views/poll_view_test.exs index a8600e1c2..224b26cb9 100644 --- a/test/pleroma/web/mastodon_api/views/poll_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/poll_view_test.exs @@ -42,7 +42,6 @@ test "renders a poll" do %{title: "yes", votes_count: 0}, %{title: "why are you even asking?", votes_count: 0} ], - voted: false, votes_count: 0, voters_count: 0 } @@ -124,6 +123,8 @@ test "detects vote status" do result = PollView.render("show.json", %{object: object, for: other_user}) assert result[:voted] == true + assert 1 in result[:own_votes] + assert 2 in result[:own_votes] assert Enum.at(result[:options], 1)[:votes_count] == 1 assert Enum.at(result[:options], 2)[:votes_count] == 1 end diff --git a/test/pleroma/web/mastodon_api/views/status_view_test.exs b/test/pleroma/web/mastodon_api/views/status_view_test.exs index 21a01658e..ed59cf285 100644 --- a/test/pleroma/web/mastodon_api/views/status_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/status_view_test.exs @@ -263,7 +263,7 @@ test "a note activity" do tags: [ %{ name: "#{object_data["tag"]}", - url: "/tag/#{object_data["tag"]}" + url: "http://localhost:4001/tag/#{object_data["tag"]}" } ], application: %{ @@ -585,9 +585,9 @@ test "it returns a a dictionary tags" do ] assert StatusView.build_tags(object_tags) == [ - %{name: "fediverse", url: "/tag/fediverse"}, - %{name: "mastodon", url: "/tag/mastodon"}, - %{name: "nextcloud", url: "/tag/nextcloud"} + %{name: "fediverse", url: "http://localhost:4001/tag/fediverse"}, + %{name: "mastodon", url: "http://localhost:4001/tag/mastodon"}, + %{name: "nextcloud", url: "http://localhost:4001/tag/nextcloud"} ] end end diff --git a/test/pleroma/web/media_proxy/invalidation/script_test.exs b/test/pleroma/web/media_proxy/invalidation/script_test.exs index bcb6ab73c..e9629b72b 100644 --- a/test/pleroma/web/media_proxy/invalidation/script_test.exs +++ b/test/pleroma/web/media_proxy/invalidation/script_test.exs @@ -8,7 +8,7 @@ defmodule Pleroma.Web.MediaProxy.Invalidation.ScriptTest do import ExUnit.CaptureLog - test "it logger error when script not found" do + test "it logs error when script is not found" do assert capture_log(fn -> assert Invalidation.Script.purge( ["http://example.com/media/example.jpg"], @@ -23,4 +23,30 @@ test "it logger error when script not found" do ) == {:error, "\"not found script path\""} end) end + + describe "url formatting" do + setup do + urls = [ + "https://bikeshed.party/media/foo.png", + "http://safe.millennial.space/proxy/wheeeee.gif", + "https://lain.com/proxy/mediafile.mp4?foo&bar=true", + "http://localhost:4000/media/upload.jpeg" + ] + + [urls: urls] + end + + test "with invalid formatter", %{urls: urls} do + assert urls == Invalidation.Script.maybe_format_urls(urls, nil) + end + + test "with :htcacheclean formatter", %{urls: urls} do + assert [ + "https://bikeshed.party:443/media/foo.png?", + "http://safe.millennial.space:80/proxy/wheeeee.gif?", + "https://lain.com:443/proxy/mediafile.mp4?foo&bar=true", + "http://localhost:4000/media/upload.jpeg?" + ] == Invalidation.Script.maybe_format_urls(urls, :htcacheclean) + end + end end diff --git a/test/pleroma/web/mongoose_im_controller_test.exs b/test/pleroma/web/mongoose_im_controller_test.exs index a7225d45c..43c4dfa33 100644 --- a/test/pleroma/web/mongoose_im_controller_test.exs +++ b/test/pleroma/web/mongoose_im_controller_test.exs @@ -9,7 +9,7 @@ defmodule Pleroma.Web.MongooseIMControllerTest do test "/user_exists", %{conn: conn} do _user = insert(:user, nickname: "lain") _remote_user = insert(:user, nickname: "alice", local: false) - _deactivated_user = insert(:user, nickname: "konata", deactivated: true) + _deactivated_user = insert(:user, nickname: "konata", is_active: false) res = conn @@ -46,7 +46,7 @@ test "/check_password", %{conn: conn} do _deactivated_user = insert(:user, nickname: "konata", - deactivated: true, + is_active: false, password_hash: Pleroma.Password.Pbkdf2.hash_pwd_salt("cool") ) diff --git a/test/pleroma/web/o_auth/o_auth_controller_test.exs b/test/pleroma/web/o_auth/o_auth_controller_test.exs index bf47afed8..9c7c57d48 100644 --- a/test/pleroma/web/o_auth/o_auth_controller_test.exs +++ b/test/pleroma/web/o_auth/o_auth_controller_test.exs @@ -928,7 +928,7 @@ test "rejects token exchange for valid credentials belonging to unconfirmed user {:ok, user} = insert(:user, password_hash: Pleroma.Password.Pbkdf2.hash_pwd_salt(password)) - |> User.confirmation_changeset(need_confirmation: true) + |> User.confirmation_changeset(set_confirmation: false) |> User.update_and_set_cache() refute Pleroma.User.account_status(user) == :active @@ -956,7 +956,7 @@ test "rejects token exchange for valid credentials belonging to deactivated user user = insert(:user, password_hash: Pleroma.Password.Pbkdf2.hash_pwd_salt(password), - deactivated: true + is_active: false ) app = insert(:oauth_app) @@ -1013,7 +1013,7 @@ test "rejects token exchange for user with confirmation_pending set to true" do user = insert(:user, password_hash: Pleroma.Password.Pbkdf2.hash_pwd_salt(password), - confirmation_pending: true + is_confirmed: false ) app = insert(:oauth_app, scopes: ["read", "write"]) @@ -1041,7 +1041,7 @@ test "rejects token exchange for valid credentials belonging to an unapproved us user = insert(:user, password_hash: Pleroma.Password.Pbkdf2.hash_pwd_salt(password), - approval_pending: true + is_approved: false ) refute Pleroma.User.account_status(user) == :active diff --git a/test/pleroma/web/pleroma_api/controllers/account_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/account_controller_test.exs index baf2d01ab..9f14c5577 100644 --- a/test/pleroma/web/pleroma_api/controllers/account_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/account_controller_test.exs @@ -17,10 +17,10 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do setup do {:ok, user} = insert(:user) - |> User.confirmation_changeset(need_confirmation: true) + |> User.confirmation_changeset(set_confirmation: false) |> User.update_and_set_cache() - assert user.confirmation_pending + refute user.is_confirmed [user: user] end diff --git a/test/pleroma/web/plugs/user_enabled_plug_test.exs b/test/pleroma/web/plugs/user_enabled_plug_test.exs index bee413fbf..71822305b 100644 --- a/test/pleroma/web/plugs/user_enabled_plug_test.exs +++ b/test/pleroma/web/plugs/user_enabled_plug_test.exs @@ -22,7 +22,7 @@ test "with a user that's not confirmed and a config requiring confirmation, it r %{conn: conn} do Pleroma.Config.put([:instance, :account_activation_required], true) - user = insert(:user, confirmation_pending: true) + user = insert(:user, is_confirmed: false) conn = conn @@ -33,7 +33,7 @@ test "with a user that's not confirmed and a config requiring confirmation, it r end test "with a user that is deactivated, it removes that user", %{conn: conn} do - user = insert(:user, deactivated: true) + user = insert(:user, is_active: false) conn = conn diff --git a/test/pleroma/web/twitter_api/controller_test.exs b/test/pleroma/web/twitter_api/controller_test.exs index 23884e223..583c904b2 100644 --- a/test/pleroma/web/twitter_api/controller_test.exs +++ b/test/pleroma/web/twitter_api/controller_test.exs @@ -64,10 +64,10 @@ test "with credentials, with params" do setup do {:ok, user} = insert(:user) - |> User.confirmation_changeset(need_confirmation: true) + |> User.confirmation_changeset(set_confirmation: false) |> Repo.update() - assert user.confirmation_pending + refute user.is_confirmed [user: user] end @@ -83,7 +83,7 @@ test "it confirms the user account", %{conn: conn, user: user} do user = User.get_cached_by_id(user.id) - refute user.confirmation_pending + assert user.is_confirmed refute user.confirmation_token end diff --git a/test/pleroma/web/twitter_api/remote_follow_controller_test.exs b/test/pleroma/web/twitter_api/remote_follow_controller_test.exs index 51db2fe5e..f9d9e0525 100644 --- a/test/pleroma/web/twitter_api/remote_follow_controller_test.exs +++ b/test/pleroma/web/twitter_api/remote_follow_controller_test.exs @@ -141,7 +141,7 @@ test "follows user", %{conn: conn} do end test "returns error when user is deactivated", %{conn: conn} do - user = insert(:user, deactivated: true) + user = insert(:user, is_active: false) user2 = insert(:user) response = diff --git a/test/pleroma/web/twitter_api/twitter_api_test.exs b/test/pleroma/web/twitter_api/twitter_api_test.exs index 3be4812d3..129ffdf4d 100644 --- a/test/pleroma/web/twitter_api/twitter_api_test.exs +++ b/test/pleroma/web/twitter_api/twitter_api_test.exs @@ -65,7 +65,7 @@ test "it sends confirmation email if :account_activation_required is specified i {:ok, user} = TwitterAPI.register_user(data) ObanHelpers.perform_all() - assert user.confirmation_pending + refute user.is_confirmed email = Pleroma.Emails.UserEmail.account_confirmation_email(user) @@ -97,7 +97,7 @@ test "it sends an admin email if :account_approval_required is specified in inst {:ok, user} = TwitterAPI.register_user(data) ObanHelpers.perform_all() - assert user.approval_pending + refute user.is_approved user_email = Pleroma.Emails.UserEmail.approval_pending_email(user) admin_email = Pleroma.Emails.AdminEmail.new_unapproved_registration(admin, user) diff --git a/test/pleroma/web/twitter_api/util_controller_test.exs b/test/pleroma/web/twitter_api/util_controller_test.exs index 6d007ab66..283c61678 100644 --- a/test/pleroma/web/twitter_api/util_controller_test.exs +++ b/test/pleroma/web/twitter_api/util_controller_test.exs @@ -164,7 +164,7 @@ test "with valid permissions and password, it disables the account", %{conn: con user = User.get_cached_by_id(user.id) - assert user.deactivated == true + refute user.is_active end test "with valid permissions and invalid password, it returns an error", %{conn: conn} do @@ -178,7 +178,7 @@ test "with valid permissions and invalid password, it returns an error", %{conn: assert response == %{"error" => "Invalid password."} user = User.get_cached_by_id(user.id) - refute user.deactivated + assert user.is_active end end @@ -428,7 +428,7 @@ test "with proper permissions and valid password", %{conn: conn, user: user} do assert json_response(conn, 200) == %{"status" => "success"} user = User.get_by_id(user.id) - assert user.deactivated == true + refute user.is_active assert user.name == nil assert user.bio == "" assert user.password_hash == nil diff --git a/test/support/channel_case.ex b/test/support/channel_case.ex index 6888984a2..1fbf6f100 100644 --- a/test/support/channel_case.ex +++ b/test/support/channel_case.ex @@ -30,19 +30,5 @@ defmodule Pleroma.Web.ChannelCase do end end - setup tags do - :ok = Ecto.Adapters.SQL.Sandbox.checkout(Pleroma.Repo) - - if tags[:async] do - Mox.stub_with(Pleroma.CachexMock, Pleroma.NullCache) - Mox.set_mox_private() - else - Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, {:shared, self()}) - Mox.stub_with(Pleroma.CachexMock, Pleroma.CachexProxy) - Mox.set_mox_global() - Pleroma.DataCase.clear_cachex() - end - - :ok - end + setup tags, do: Pleroma.DataCase.setup_multi_process_mode(tags) end diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index 5b7111fd3..953aa010a 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -19,6 +19,8 @@ defmodule Pleroma.Web.ConnCase do use ExUnit.CaseTemplate + alias Pleroma.DataCase + using do quote do # Import conveniences for testing with connections @@ -116,27 +118,9 @@ defp json_response_and_validate_schema(conn, _status) do end setup tags do - :ok = Ecto.Adapters.SQL.Sandbox.checkout(Pleroma.Repo) - - if tags[:async] do - Mox.stub_with(Pleroma.CachexMock, Pleroma.NullCache) - Mox.set_mox_private() - else - Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, {:shared, self()}) - Mox.stub_with(Pleroma.CachexMock, Pleroma.CachexProxy) - Mox.set_mox_global() - Pleroma.DataCase.clear_cachex() - end - - if tags[:needs_streamer] do - start_supervised(%{ - id: Pleroma.Web.Streamer.registry(), - start: - {Registry, :start_link, [[keys: :duplicate, name: Pleroma.Web.Streamer.registry()]]} - }) - end - - Pleroma.DataCase.stub_pipeline() + DataCase.setup_multi_process_mode(tags) + DataCase.setup_streamer(tags) + DataCase.stub_pipeline() Mox.verify_on_exit!() diff --git a/test/support/data_case.ex b/test/support/data_case.ex index 9db3478bc..0ee2aa4a2 100644 --- a/test/support/data_case.ex +++ b/test/support/data_case.ex @@ -18,6 +18,8 @@ defmodule Pleroma.DataCase do use ExUnit.CaseTemplate + import Pleroma.Tests.Helpers, only: [clear_config: 2] + using do quote do alias Pleroma.Repo @@ -62,7 +64,7 @@ def clear_cachex do end) end - setup tags do + def setup_multi_process_mode(tags) do :ok = Ecto.Adapters.SQL.Sandbox.checkout(Pleroma.Repo) if tags[:async] do @@ -70,11 +72,16 @@ def clear_cachex do Mox.set_mox_private() else Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, {:shared, self()}) - Mox.stub_with(Pleroma.CachexMock, Pleroma.CachexProxy) + Mox.set_mox_global() + Mox.stub_with(Pleroma.CachexMock, Pleroma.CachexProxy) clear_cachex() end + :ok + end + + def setup_streamer(tags) do if tags[:needs_streamer] do start_supervised(%{ id: Pleroma.Web.Streamer.registry(), @@ -83,6 +90,12 @@ def clear_cachex do }) end + :ok + end + + setup tags do + setup_multi_process_mode(tags) + setup_streamer(tags) stub_pipeline() Mox.verify_on_exit!() @@ -105,17 +118,10 @@ def stub_pipeline do end def ensure_local_uploader(context) do - test_uploader = Map.get(context, :uploader, Pleroma.Uploaders.Local) - uploader = Pleroma.Config.get([Pleroma.Upload, :uploader]) - filters = Pleroma.Config.get([Pleroma.Upload, :filters]) + test_uploader = Map.get(context, :uploader) || Pleroma.Uploaders.Local - Pleroma.Config.put([Pleroma.Upload, :uploader], test_uploader) - Pleroma.Config.put([Pleroma.Upload, :filters], []) - - on_exit(fn -> - Pleroma.Config.put([Pleroma.Upload, :uploader], uploader) - Pleroma.Config.put([Pleroma.Upload, :filters], filters) - end) + clear_config([Pleroma.Upload, :uploader], test_uploader) + clear_config([Pleroma.Upload, :filters], []) :ok end diff --git a/test/support/helpers.ex b/test/support/helpers.ex index 4353d5254..856a6a376 100644 --- a/test/support/helpers.ex +++ b/test/support/helpers.ex @@ -8,6 +8,8 @@ defmodule Pleroma.Tests.Helpers do """ alias Pleroma.Config + require Logger + defmacro clear_config(config_path) do quote do clear_config(unquote(config_path)) do @@ -18,6 +20,7 @@ defmacro clear_config(config_path) do defmacro clear_config(config_path, do: yield) do quote do initial_setting = Config.fetch(unquote(config_path)) + unquote(yield) on_exit(fn -> @@ -35,6 +38,15 @@ defmacro clear_config(config_path, do: yield) do end defmacro clear_config(config_path, temp_setting) do + # NOTE: `clear_config([section, key], value)` != `clear_config([section], key: value)` (!) + # Displaying a warning to prevent unintentional clearing of all but one keys in section + if Keyword.keyword?(temp_setting) and length(temp_setting) == 1 do + Logger.warn( + "Please change to `clear_config([section]); clear_config([section, key], value)`: " <> + "#{inspect(config_path)}, #{inspect(temp_setting)}" + ) + end + quote do clear_config(unquote(config_path)) do Config.put(unquote(config_path), unquote(temp_setting))