Merge branch 'develop' into issue/1383
authorMaksim Pechnikov <parallel588@gmail.com>
Sat, 21 Dec 2019 17:37:29 +0000 (20:37 +0300)
committerMaksim Pechnikov <parallel588@gmail.com>
Sat, 21 Dec 2019 17:38:59 +0000 (20:38 +0300)
40 files changed:
.gitlab-ci.yml
CHANGELOG.md
config/config.exs
config/prod.exs
config/releases.exs
config/test.exs
docs/API/pleroma_api.md
docs/configuration/cheatsheet.md
lib/pleroma/application.ex
lib/pleroma/html.ex
lib/pleroma/object/fetcher.ex
lib/pleroma/utils.ex [new file with mode: 0644]
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/activity_pub/activity_pub_controller.ex
lib/pleroma/web/activity_pub/mrf/drop_policy.ex
lib/pleroma/web/activity_pub/mrf/mediaproxy_warming_policy.ex
lib/pleroma/web/activity_pub/publisher.ex
lib/pleroma/web/activity_pub/transmogrifier.ex
lib/pleroma/web/activity_pub/utils.ex
lib/pleroma/web/activity_pub/views/user_view.ex
lib/pleroma/web/endpoint.ex
lib/pleroma/web/federator/federator.ex
lib/pleroma/web/federator/publisher.ex
lib/pleroma/web/mastodon_api/views/status_view.ex
lib/pleroma/web/metadata/twitter_card.ex
lib/pleroma/web/twitter_api/controllers/util_controller.ex
test/conversation/participation_test.exs
test/fixtures/modules/runtime_module.ex [new file with mode: 0644]
test/fixtures/tesla_mock/mobilizon.org-event.json [new file with mode: 0644]
test/fixtures/tesla_mock/mobilizon.org-user.json [new file with mode: 0644]
test/object/fetcher_test.exs
test/plugs/rate_limiter_test.exs
test/runtime_test.exs [new file with mode: 0644]
test/support/http_request_mock.ex
test/web/activity_pub/activity_pub_test.exs
test/web/activity_pub/views/user_view_test.exs
test/web/mastodon_api/views/status_view_test.exs
test/web/metadata/twitter_card_test.exs
test/web/streamer/streamer_test.exs
test/web/twitter_api/util_controller_test.exs

index 88789035d43952032792e453a5d9d3238ed382af..dc85eaba21338e19be41f4b88987698b00e4c6a2 100644 (file)
@@ -1,13 +1,13 @@
 image: elixir:1.8.1
 
-variables:
+variables: &global_variables
   POSTGRES_DB: pleroma_test
   POSTGRES_USER: postgres
   POSTGRES_PASSWORD: postgres
   DB_HOST: postgres
   MIX_ENV: test
 
-cache:
+cache: &global_cache_policy
   key: ${CI_COMMIT_REF_SLUG}
   paths:
           - deps
@@ -46,6 +46,10 @@ benchmark:
 
 unit-testing:
   stage: test
+  cache: &testing_cache_policy
+    <<: *global_cache_policy
+    policy: pull
+
   services:
   - name: postgres:9.6
     alias: postgres
@@ -58,6 +62,7 @@ unit-testing:
 
 federated-testing:
   stage: test
+  cache: *testing_cache_policy
   services:
   - name: minibikini/postgres-with-rum:12
     alias: postgres
@@ -71,11 +76,13 @@ federated-testing:
 
 unit-testing-rum:
   stage: test
+  cache: *testing_cache_policy
   services:
   - name: minibikini/postgres-with-rum:12
     alias: postgres
     command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
   variables:
+    <<: *global_variables
     RUM_ENABLED: "true"
   script:
     - mix deps.get
@@ -86,17 +93,20 @@ unit-testing-rum:
 
 lint:
   stage: test
+  cache: *testing_cache_policy
   script:
     - mix format --check-formatted
 
 analysis:
   stage: test
+  cache: *testing_cache_policy
   script:
     - mix deps.get
     - mix credo --strict --only=warnings,todo,fixme,consistency,readability
 
 docs-deploy:
   stage: deploy
+  cache: *testing_cache_policy
   image: alpine:latest
   only:
   - stable@pleroma/pleroma
index c133cd9ec4f3335f9132c025f5822bb457ffe7c7..22f199b3d14f4614b3e8f79f8e8ae459dcd604fd 100644 (file)
@@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Deprecated `User.Info` embedded schema (fields moved to `User`)
 - Store status data inside Flag activity
 - Deprecated (reorganized as `UserRelationship` entity) User fields with user AP IDs (`blocks`, `mutes`, `muted_reblogs`, `muted_notifications`, `subscribers`).
+- Logger: default log level changed from `warn` to `info`.
 <details>
   <summary>API Changes</summary>
 
@@ -51,6 +52,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Support for `X-Forwarded-For` and similar HTTP headers which used by reverse proxies to pass a real user IP address to the backend. Must not be enabled unless your instance is behind at least one reverse proxy (such as Nginx, Apache HTTPD or Varnish Cache).
 - MRF: New module which handles incoming posts based on their age. By default, all incoming posts that are older than 2 days will be unlisted and not shown to their followers.
 - User notification settings: Add `privacy_option` option.
+- Support for custom Elixir modules (such as MRF policies)
 - User settings: Add _This account is a_ option.
 - OAuth: admin scopes support (relevant setting: `[:auth, :enforce_oauth_admin_scope_usage]`).
 <details>
index a737c98af40ed30941c184d34d7e696be88636d8..bbd8f7d781d4088229ab55d954e1b5d09c84975d 100644 (file)
@@ -56,6 +56,8 @@ config :pleroma, Pleroma.Captcha,
   seconds_valid: 60,
   method: Pleroma.Captcha.Native
 
+config :pleroma, Pleroma.Captcha.Kocaptcha, endpoint: "https://captcha.kotobank.ch"
+
 config :pleroma, :hackney_pools,
   federation: [
     max_connections: 50,
@@ -609,6 +611,8 @@ config :pleroma, :web_cache_ttl,
   activity_pub: nil,
   activity_pub_question: 30_000
 
+config :pleroma, :modules, runtime_dir: "instance/modules"
+
 # 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"
index 25873f360eabbebced42d3f3af5e08530d0944a9..adbce56066682508c0902086afe86bc2f38c8bec 100644 (file)
@@ -20,8 +20,8 @@ config :pleroma, Pleroma.Web.Endpoint,
 config :phoenix, serve_endpoints: true
 
 # Do not print debug messages in production
-config :logger, :console, level: :warn
-config :logger, :ex_syslogger, level: :warn
+config :logger, :console, level: :info
+config :logger, :ex_syslogger, level: :info
 
 # ## SSL Support
 #
index 98c5ceccd54a5501dfefcd8a845d148aedca390f..b224960dbff578a365455902e8a544d9edbb501e 100644 (file)
@@ -2,6 +2,7 @@ import Config
 
 config :pleroma, :instance, static_dir: "/var/lib/pleroma/static"
 config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads"
+config :pleroma, :modules, runtime_dir: "/var/lib/pleroma/modules"
 
 config_path = System.get_env("PLEROMA_CONFIG_PATH") || "/etc/pleroma/config.exs"
 
index c204bf37fbb0129a0753141049cf9d4a9b30a62b..ce4586c7b62e80c3dc0925b0760ff1e3def7c925 100644 (file)
@@ -91,7 +91,7 @@ config :joken, default_signer: "yU8uHKq+yyAkZ11Hx//jcdacWc8yQ1bxAAGrplzB0Zwwjkp3
 
 config :pleroma, Pleroma.ReverseProxy.Client, Pleroma.ReverseProxy.ClientMock
 
-config :pleroma, Pleroma.Captcha.Kocaptcha, endpoint: "https://captcha.kotobank.ch"
+config :pleroma, :modules, runtime_dir: "test/fixtures/modules"
 
 if File.exists?("./config/test.secret.exs") do
   import_config "test.secret.exs"
index 7228d805b5a7e850628f9b9168febf3ce7f8c9c5..689edbcc21e28082dadcb7f9ad07a6c64459d780 100644 (file)
@@ -70,59 +70,6 @@ Request parameters can be passed via [query strings](https://en.wikipedia.org/wi
 * Response: JSON. Returns `{"status": "success"}` if the account was successfully disabled, `{"error": "[error message]"}` otherwise
 * Example response: `{"error": "Invalid password."}`
 
-## `/api/account/register`
-### Register a new user
-* Method `POST`
-* Authentication: not required
-* Params:
-    * `nickname`
-    * `fullname`
-    * `bio`
-    * `email`
-    * `password`
-    * `confirm`
-    * `captcha_solution`: optional, contains provider-specific captcha solution,
-    * `captcha_token`: optional, contains provider-specific captcha token
-    * `token`: invite token required when the registrations aren't public.
-* Response: JSON. Returns a user object on success, otherwise returns `{"error": "error_msg"}`
-* Example response:
-```json
-{
-       "background_image": null,
-       "cover_photo": "https://pleroma.soykaf.com/images/banner.png",
-       "created_at": "Tue Dec 18 16:55:56 +0000 2018",
-       "default_scope": "public",
-       "description": "blushy-crushy fediverse idol + pleroma dev\nlet's be friends \nぷれろまの生徒会長。謎の外人。日本語OK. \n公主病.",
-       "description_html": "blushy-crushy fediverse idol + pleroma dev.<br />let's be friends <br />ぷれろまの生徒会長。謎の外人。日本語OK. <br />公主病.",
-       "favourites_count": 0,
-       "fields": [],
-       "followers_count": 0,
-       "following": false,
-       "follows_you": false,
-       "friends_count": 0,
-       "id": 6,
-       "is_local": true,
-       "locked": false,
-       "name": "lain",
-       "name_html": "lain",
-       "no_rich_text": false,
-       "pleroma": {
-               "tags": []
-       },
-       "profile_image_url": "https://pleroma.soykaf.com/images/avi.png",
-       "profile_image_url_https": "https://pleroma.soykaf.com/images/avi.png",
-       "profile_image_url_original": "https://pleroma.soykaf.com/images/avi.png",
-       "profile_image_url_profile_size": "https://pleroma.soykaf.com/images/avi.png",
-       "rights": {
-               "delete_others_notice": false
-       },
-       "screen_name": "lain",
-       "statuses_count": 0,
-       "statusnet_blocking": false,
-       "statusnet_profile_url": "https://pleroma.soykaf.com/users/lain"
-}
-```
-
 ## `/api/pleroma/admin/`…
 See [Admin-API](admin_api.md)
 
index 824edda77ba493747a7d47a89be0ea0ba77f1ecf..8f5d7f51274914a997a32bddfca43e7c8967f1d2 100644 (file)
@@ -845,3 +845,7 @@ config :auto_linker,
     rel: "ugc"
   ]
 ```
+
+## Custom Runtime Modules (`:modules`)
+
+* `runtime_dir`: A path to custom Elixir modules (such as MRF policies).
index ab7f6d50215f2307641b2a23222b2b481af494ea..98d7a6e867b5ad6e0bbcc7df3ab17c12dbd117f7 100644 (file)
@@ -5,6 +5,7 @@
 defmodule Pleroma.Application do
   import Cachex.Spec
   use Application
+  require Logger
 
   @name Mix.Project.config()[:name]
   @version Mix.Project.config()[:version]
@@ -33,6 +34,7 @@ defmodule Pleroma.Application do
     Pleroma.HTML.compile_scrubbers()
     Pleroma.Config.DeprecationWarnings.warn()
     setup_instrumenters()
+    load_custom_modules()
 
     # Define workers and child supervisors to be supervised
     children =
@@ -64,6 +66,28 @@ defmodule Pleroma.Application do
     Supervisor.start_link(children, opts)
   end
 
+  def load_custom_modules do
+    dir = Pleroma.Config.get([:modules, :runtime_dir])
+
+    if dir && File.exists?(dir) do
+      dir
+      |> Pleroma.Utils.compile_dir()
+      |> case do
+        {:error, _errors, _warnings} ->
+          raise "Invalid custom modules"
+
+        {:ok, modules, _warnings} ->
+          if @env != :test do
+            Enum.each(modules, fn mod ->
+              Logger.info("Custom module loaded: #{inspect(mod)}")
+            end)
+          end
+
+          :ok
+      end
+    end
+  end
+
   defp setup_instrumenters do
     require Prometheus.Registry
 
index 2cae29f35170fe5b952551b405db677c8baba9f2..11513106eb643769c72701865459cd9eb70a22dc 100644 (file)
@@ -10,9 +10,7 @@ defmodule Pleroma.HTML do
     dir = Path.join(:code.priv_dir(:pleroma), "scrubbers")
 
     dir
-    |> File.ls!()
-    |> Enum.map(&Path.join(dir, &1))
-    |> Kernel.ParallelCompiler.compile()
+    |> Pleroma.Utils.compile_dir()
     |> case do
       {:error, _errors, _warnings} ->
         raise "Compiling scrubbers failed"
index 4d71c91a80be38f5470690048495c3d4f8ba227c..a1bde90f1d77a9c12868427fecde1b524c708732 100644 (file)
@@ -154,7 +154,7 @@ defmodule Pleroma.Object.Fetcher do
   end
 
   def fetch_and_contain_remote_object_from_id(id) when is_binary(id) do
-    Logger.info("Fetching object #{id} via AP")
+    Logger.debug("Fetching object #{id} via AP")
 
     date = Pleroma.Signature.signed_date()
 
diff --git a/lib/pleroma/utils.ex b/lib/pleroma/utils.ex
new file mode 100644 (file)
index 0000000..8d36a00
--- /dev/null
@@ -0,0 +1,12 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Utils do
+  def compile_dir(dir) when is_binary(dir) do
+    dir
+    |> File.ls!()
+    |> Enum.map(&Path.join(dir, &1))
+    |> Kernel.ParallelCompiler.compile()
+  end
+end
index 16e6b00572257d5c7615c707388e4bd63fe97f4e..60c9e7e64f2a03283c8f81acb2de31da0e703eb3 100644 (file)
@@ -1298,28 +1298,26 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
   def fetch_follow_information_for_user(user) do
     with {:ok, following_data} <-
            Fetcher.fetch_and_contain_remote_object_from_id(user.following_address),
-         following_count when is_integer(following_count) <- following_data["totalItems"],
          {:ok, hide_follows} <- collection_private(following_data),
          {:ok, followers_data} <-
            Fetcher.fetch_and_contain_remote_object_from_id(user.follower_address),
-         followers_count when is_integer(followers_count) <- followers_data["totalItems"],
          {:ok, hide_followers} <- collection_private(followers_data) do
       {:ok,
        %{
          hide_follows: hide_follows,
-         follower_count: followers_count,
-         following_count: following_count,
+         follower_count: normalize_counter(followers_data["totalItems"]),
+         following_count: normalize_counter(following_data["totalItems"]),
          hide_followers: hide_followers
        }}
     else
-      {:error, _} = e ->
-        e
-
-      e ->
-        {:error, e}
+      {:error, _} = e -> e
+      e -> {:error, e}
     end
   end
 
+  defp normalize_counter(counter) when is_integer(counter), do: counter
+  defp normalize_counter(_), do: 0
+
   defp maybe_update_follow_information(data) do
     with {:enabled, true} <-
            {:enabled, Pleroma.Config.get([:instance, :external_user_synchronization])},
@@ -1339,24 +1337,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     end
   end
 
+  defp collection_private(%{"first" => %{"type" => type}})
+       when type in ["CollectionPage", "OrderedCollectionPage"],
+       do: {:ok, false}
+
   defp collection_private(%{"first" => first}) do
-    if is_map(first) and
-         first["type"] in ["CollectionPage", "OrderedCollectionPage"] do
+    with {:ok, %{"type" => type}} when type in ["CollectionPage", "OrderedCollectionPage"] <-
+           Fetcher.fetch_and_contain_remote_object_from_id(first) do
       {:ok, false}
     else
-      with {:ok, %{"type" => type}} when type in ["CollectionPage", "OrderedCollectionPage"] <-
-             Fetcher.fetch_and_contain_remote_object_from_id(first) do
-        {:ok, false}
-      else
-        {:error, {:ok, %{status: code}}} when code in [401, 403] ->
-          {:ok, true}
-
-        {:error, _} = e ->
-          e
-
-        e ->
-          {:error, e}
-      end
+      {:error, {:ok, %{status: code}}} when code in [401, 403] -> {:ok, true}
+      {:error, _} = e -> e
+      e -> {:error, e}
     end
   end
 
index dec5da0d3aea6ea4572bcf6ab100d3136a398c86..5059e398417149f0fd24d03cd14465052a5e1356 100644 (file)
@@ -257,7 +257,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
 
   # only accept relayed Creates
   def inbox(conn, %{"type" => "Create"} = params) do
-    Logger.info(
+    Logger.debug(
       "Signature missing or not from author, relayed Create message, fetching object from source"
     )
 
@@ -270,11 +270,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
     headers = Enum.into(conn.req_headers, %{})
 
     if String.contains?(headers["signature"], params["actor"]) do
-      Logger.info(
+      Logger.debug(
         "Signature validation error for: #{params["actor"]}, make sure you are forwarding the HTTP Host header!"
       )
 
-      Logger.info(inspect(conn.req_headers))
+      Logger.debug(inspect(conn.req_headers))
     end
 
     json(conn, dgettext("errors", "error"))
index f7831bc3e69407209a4973f9d11cd896df20c427..4a57099748061a8d6ef0c095cf060d06264b6f3b 100644 (file)
@@ -9,7 +9,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.DropPolicy do
 
   @impl true
   def filter(object) do
-    Logger.info("REJECTING #{inspect(object)}")
+    Logger.debug("REJECTING #{inspect(object)}")
     {:reject, object}
   end
 
index 26b8539fe43283b652f67512bf4e00a575bf116c..df774b0f7a471c9cc00c957d5ff8050dc3181f2a 100644 (file)
@@ -18,7 +18,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy do
   ]
 
   def perform(:prefetch, url) do
-    Logger.info("Prefetching #{inspect(url)}")
+    Logger.debug("Prefetching #{inspect(url)}")
 
     url
     |> MediaProxy.url()
index 4073d3d63455ffa3e4aa7b1a9f554ebd630b6ed2..db072bad2fd4d9256b29453a4ab9009b8c4a0f40 100644 (file)
@@ -48,7 +48,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
   * `id`: the ActivityStreams URI of the message
   """
   def publish_one(%{inbox: inbox, json: json, actor: %User{} = actor, id: id} = params) do
-    Logger.info("Federating #{id} to #{inbox}")
+    Logger.debug("Federating #{id} to #{inbox}")
     %{host: host, path: path} = URI.parse(inbox)
 
     digest = "SHA-256=" <> (:crypto.hash(:sha256, json) |> Base.encode64())
@@ -228,7 +228,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
     public = is_public?(activity)
 
     if public && Config.get([:instance, :allow_relay]) do
-      Logger.info(fn -> "Relaying #{activity.data["id"]} out" end)
+      Logger.debug(fn -> "Relaying #{activity.data["id"]} out" end)
       Relay.publish(activity)
     end
 
index ecba27bef439060af70ed417d4f080b1af9a56cf..3fa789d53b3ce2f9836932b095f10d2b0810e441 100644 (file)
@@ -397,7 +397,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
         %{"type" => "Create", "object" => %{"type" => objtype} = object} = data,
         options
       )
-      when objtype in ["Article", "Note", "Video", "Page", "Question", "Answer"] do
+      when objtype in ["Article", "Event", "Note", "Video", "Page", "Question", "Answer"] do
     actor = Containment.get_actor(data)
 
     data =
index e87d09134508ad2ad8a0bc9d94b24a5e565dcb8e..db70842461c29f5376b56db5337affc2d54c24e8 100644 (file)
@@ -22,7 +22,16 @@ defmodule Pleroma.Web.ActivityPub.Utils do
   require Logger
   require Pleroma.Constants
 
-  @supported_object_types ["Article", "Note", "Video", "Page", "Question", "Answer", "Audio"]
+  @supported_object_types [
+    "Article",
+    "Note",
+    "Event",
+    "Video",
+    "Page",
+    "Question",
+    "Answer",
+    "Audio"
+  ]
   @strip_status_report_states ~w(closed resolved)
   @supported_report_states ~w(open closed resolved)
   @valid_visibilities ~w(public unlisted private direct)
index 9059aa6349de969a79b321d2820f475a195f024e..350c4391d09b24bdcedf22947a432fd975ab5ac8 100644 (file)
@@ -201,7 +201,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do
     %{
       "id" => "#{user.ap_id}/followers",
       "type" => "OrderedCollection",
-      "totalItems" => total,
       "first" =>
         if showing_items do
           collection(followers, "#{user.ap_id}/followers", 1, showing_items, total)
@@ -209,6 +208,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
           "#{user.ap_id}/followers?page=1"
         end
     }
+    |> maybe_put_total_items(showing_count, total)
     |> Map.merge(Utils.make_json_ld_header())
   end
 
@@ -251,6 +251,12 @@ defmodule Pleroma.Web.ActivityPub.UserView do
     |> Map.merge(Utils.make_json_ld_header())
   end
 
+  defp maybe_put_total_items(map, false, _total), do: map
+
+  defp maybe_put_total_items(map, true, total) do
+    Map.put(map, "totalItems", total)
+  end
+
   def collection(collection, iri, page, show_items \\ true, total \\ nil) do
     offset = (page - 1) * 10
     items = Enum.slice(collection, offset, 10)
index bbea31682c1f6533eb95f53011774df6f6c8f0cc..d32c38a05fb4b07c7fdaebc6dc86a2e2d3440706 100644 (file)
@@ -59,7 +59,7 @@ defmodule Pleroma.Web.Endpoint do
 
   plug(Pleroma.Plugs.TrailingFormatPlug)
   plug(Plug.RequestId)
-  plug(Plug.Logger)
+  plug(Plug.Logger, log: :debug)
 
   plug(Pleroma.Plugs.Parsers)
 
index e8a56ebd706d7f243328c7cad05202bcf1b5a626..f506a7d245eace7c06bff5bcb2dde6a22e6a84b0 100644 (file)
@@ -58,7 +58,7 @@ defmodule Pleroma.Web.Federator do
   end
 
   def perform(:incoming_ap_doc, params) do
-    Logger.info("Handling incoming AP activity")
+    Logger.debug("Handling incoming AP activity")
 
     params = Utils.normalize_params(params)
 
@@ -71,13 +71,13 @@ defmodule Pleroma.Web.Federator do
       {:ok, activity}
     else
       %Activity{} ->
-        Logger.info("Already had #{params["id"]}")
+        Logger.debug("Already had #{params["id"]}")
         :error
 
       _e ->
         # Just drop those for now
-        Logger.info("Unhandled activity")
-        Logger.info(Jason.encode!(params, pretty: true))
+        Logger.debug("Unhandled activity")
+        Logger.debug(Jason.encode!(params, pretty: true))
         :error
     end
   end
index fb9b26649b5a3a0dff1b3c60907fb244a970ac71..1d045c64417063191cd73377375eaedd4db39858 100644 (file)
@@ -47,7 +47,7 @@ defmodule Pleroma.Web.Federator.Publisher do
     Config.get([:instance, :federation_publisher_modules])
     |> Enum.each(fn module ->
       if module.is_representable?(activity) do
-        Logger.info("Publishing #{activity.data["id"]} using #{inspect(module)}")
+        Logger.debug("Publishing #{activity.data["id"]} using #{inspect(module)}")
         module.publish(user, activity)
       end
     end)
index a0257dfa6a0ee1705edf57ecb549e5270476aeba..e9590224b75e94399e4e54aca21472084c5799d9 100644 (file)
@@ -421,7 +421,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
     end
   end
 
-  def render_content(%{data: %{"type" => "Video"}} = object) do
+  def render_content(%{data: %{"type" => object_type}} = object)
+      when object_type in ["Video", "Event"] do
     with name when not is_nil(name) and name != "" <- object.data["name"] do
       "<p><a href=\"#{object.data["id"]}\">#{name}</a></p>#{object.data["content"]}"
     else
index d6a6049b3f8d9841410fa07012fecebb7504b6b0..67419a666878d2848099f423fce021bd84220e1f 100644 (file)
@@ -31,7 +31,7 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
       if attachments == [] or Metadata.activity_nsfw?(object) do
         [
           image_tag(user),
-          {:meta, [property: "twitter:card", content: "summary_large_image"], []}
+          {:meta, [property: "twitter:card", content: "summary"], []}
         ]
       else
         attachments
index 2305bb41334202badc82890d3e5e0bfaeab97eb9..799dd17aef6b7febd6b0f2751015b3f814135678 100644 (file)
@@ -104,7 +104,8 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
 
   defp is_status?(acct) do
     case Pleroma.Object.Fetcher.fetch_and_contain_remote_object_from_id(acct) do
-      {:ok, %{"type" => type}} when type in ["Article", "Note", "Video", "Page", "Question"] ->
+      {:ok, %{"type" => type}}
+      when type in ["Article", "Event", "Note", "Video", "Page", "Question"] ->
         true
 
       _ ->
index 9b2c97963a8c56b1f9d7d677a6f9dee6ae2e7c7c..ba81c0d4bb2eb42025fcb07eb6996ffebfa94954 100644 (file)
@@ -5,7 +5,9 @@
 defmodule Pleroma.Conversation.ParticipationTest do
   use Pleroma.DataCase
   import Pleroma.Factory
+  alias Pleroma.Conversation
   alias Pleroma.Conversation.Participation
+  alias Pleroma.Repo
   alias Pleroma.User
   alias Pleroma.Web.CommonAPI
 
@@ -98,7 +100,9 @@ defmodule Pleroma.Conversation.ParticipationTest do
     assert participation.user_id == user.id
     assert participation.conversation_id == conversation.id
 
+    # Needed because updated_at is accurate down to a second
     :timer.sleep(1000)
+
     # Creating again returns the same participation
     {:ok, %Participation{} = participation_two} =
       Participation.create_for_user_and_conversation(user, conversation)
@@ -150,9 +154,7 @@ defmodule Pleroma.Conversation.ParticipationTest do
   test "gets all the participations for a user, ordered by updated at descending" do
     user = insert(:user)
     {:ok, activity_one} = CommonAPI.post(user, %{"status" => "x", "visibility" => "direct"})
-    :timer.sleep(1000)
     {:ok, activity_two} = CommonAPI.post(user, %{"status" => "x", "visibility" => "direct"})
-    :timer.sleep(1000)
 
     {:ok, activity_three} =
       CommonAPI.post(user, %{
@@ -161,6 +163,17 @@ defmodule Pleroma.Conversation.ParticipationTest do
         "in_reply_to_status_id" => activity_one.id
       })
 
+    # Offset participations because the accuracy of updated_at is down to a second
+
+    for {activity, offset} <- [{activity_two, 1}, {activity_three, 2}] do
+      conversation = Conversation.get_for_ap_id(activity.data["context"])
+      participation = Participation.for_user_and_conversation(user, conversation)
+      updated_at = NaiveDateTime.add(Map.get(participation, :updated_at), offset)
+
+      Ecto.Changeset.change(participation, %{updated_at: updated_at})
+      |> Repo.update!()
+    end
+
     assert [participation_one, participation_two] = Participation.for_user(user)
 
     object2 = Pleroma.Object.normalize(activity_two)
diff --git a/test/fixtures/modules/runtime_module.ex b/test/fixtures/modules/runtime_module.ex
new file mode 100644 (file)
index 0000000..4711c35
--- /dev/null
@@ -0,0 +1,9 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule RuntimeModule do
+  @moduledoc """
+  This is a dummy module to test custom runtime modules.
+  """
+end
diff --git a/test/fixtures/tesla_mock/mobilizon.org-event.json b/test/fixtures/tesla_mock/mobilizon.org-event.json
new file mode 100644 (file)
index 0000000..7411cf8
--- /dev/null
@@ -0,0 +1 @@
+{"@context":["https://www.w3.org/ns/activitystreams","https://litepub.social/litepub/context.jsonld",{"GeoCoordinates":"sc:GeoCoordinates","Hashtag":"as:Hashtag","Place":"sc:Place","PostalAddress":"sc:PostalAddress","address":{"@id":"sc:address","@type":"sc:PostalAddress"},"addressCountry":"sc:addressCountry","addressLocality":"sc:addressLocality","addressRegion":"sc:addressRegion","category":"sc:category","commentsEnabled":{"@id":"pt:commentsEnabled","@type":"sc:Boolean"},"geo":{"@id":"sc:geo","@type":"sc:GeoCoordinates"},"ical":"http://www.w3.org/2002/12/cal/ical#","joinMode":{"@id":"mz:joinMode","@type":"mz:joinModeType"},"joinModeType":{"@id":"mz:joinModeType","@type":"rdfs:Class"},"location":{"@id":"sc:location","@type":"sc:Place"},"maximumAttendeeCapacity":"sc:maximumAttendeeCapacity","mz":"https://joinmobilizon.org/ns#","postalCode":"sc:postalCode","pt":"https://joinpeertube.org/ns#","repliesModerationOption":{"@id":"mz:repliesModerationOption","@type":"mz:repliesModerationOptionType"},"repliesModerationOptionType":{"@id":"mz:repliesModerationOptionType","@type":"rdfs:Class"},"sc":"http://schema.org#","streetAddress":"sc:streetAddress","uuid":"sc:identifier"}],"actor":"https://mobilizon.org/@tcit","attributedTo":"https://mobilizon.org/@tcit","category":"meeting","cc":[],"commentsEnabled":true,"content":"<p>Mobilizon is now federated! 🎉</p><p></p><p>You can view this event from other instances if they are subscribed to mobilizon.org, and soon directly from Mastodon and Pleroma. It is possible that you may see some comments from other instances, including Mastodon ones, just below.</p><p></p><p>With a Mobilizon account on an instance, you may <strong>participate</strong> at events from other instances and <strong>add comments</strong> on events.</p><p></p><p>Of course, it's still <u>a work in progress</u>: if reports made from an instance on events and comments can be federated, you can't block people right now, and moderators actions are rather limited, but this <strong>will definitely get fixed over time</strong> until first stable version next year.</p><p></p><p>Anyway, if you want to come up with some feedback, head over to our forum or - if you feel you have technical skills and are familiar with it - on our Gitlab repository.</p><p></p><p>Also, to people that want to set Mobilizon themselves even though we really don't advise to do that for now, we have a little documentation but it's quite the early days and you'll probably need some help. No worries, you can chat with us on our Forum or though our Matrix channel.</p><p></p><p>Check our website for more informations and follow us on Twitter or Mastodon.</p>","endTime":"2019-12-18T14:00:00Z","ical:status":"CONFIRMED","id":"https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39","joinMode":"free","location":{"address":{"addressCountry":"France","addressLocality":"Nantes","addressRegion":"Pays de la Loire","postalCode":null,"streetAddress":" ","type":"PostalAddress"},"geo":{"latitude":-1.54939699141711,"longitude":47.21617415,"type":"GeoCoordinates"},"id":"https://mobilizon.org/address/1368fdab-1e2c-4de6-bcff-a90c84abdee1","name":"Cour du Château des Ducs de Bretagne","type":"Place"},"maximumAttendeeCapacity":0,"mediaType":"text/html","name":"Mobilizon Launching Party","published":"2019-12-17T11:33:56Z","repliesModerationOption":"allow_all","startTime":"2019-12-18T13:00:00Z","tag":[{"href":"https://mobilizon.org/tags/mobilizon","name":"#Mobilizon","type":"Hashtag"},{"href":"https://mobilizon.org/tags/federation","name":"#Federation","type":"Hashtag"},{"href":"https://mobilizon.org/tags/activitypub","name":"#ActivityPub","type":"Hashtag"},{"href":"https://mobilizon.org/tags/party","name":"#Party","type":"Hashtag"}],"to":["https://www.w3.org/ns/activitystreams#Public"],"type":"Event","updated":"2019-12-17T12:25:01Z","url":"https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39","uuid":"252d5816-00a3-4a89-a66f-15bf65c33e39"}
\ No newline at end of file
diff --git a/test/fixtures/tesla_mock/mobilizon.org-user.json b/test/fixtures/tesla_mock/mobilizon.org-user.json
new file mode 100644 (file)
index 0000000..f948ae5
--- /dev/null
@@ -0,0 +1 @@
+{"@context":["https://www.w3.org/ns/activitystreams","https://litepub.social/litepub/context.jsonld",{"GeoCoordinates":"sc:GeoCoordinates","Hashtag":"as:Hashtag","Place":"sc:Place","PostalAddress":"sc:PostalAddress","address":{"@id":"sc:address","@type":"sc:PostalAddress"},"addressCountry":"sc:addressCountry","addressLocality":"sc:addressLocality","addressRegion":"sc:addressRegion","category":"sc:category","commentsEnabled":{"@id":"pt:commentsEnabled","@type":"sc:Boolean"},"geo":{"@id":"sc:geo","@type":"sc:GeoCoordinates"},"ical":"http://www.w3.org/2002/12/cal/ical#","joinMode":{"@id":"mz:joinMode","@type":"mz:joinModeType"},"joinModeType":{"@id":"mz:joinModeType","@type":"rdfs:Class"},"location":{"@id":"sc:location","@type":"sc:Place"},"maximumAttendeeCapacity":"sc:maximumAttendeeCapacity","mz":"https://joinmobilizon.org/ns#","postalCode":"sc:postalCode","pt":"https://joinpeertube.org/ns#","repliesModerationOption":{"@id":"mz:repliesModerationOption","@type":"mz:repliesModerationOptionType"},"repliesModerationOptionType":{"@id":"mz:repliesModerationOptionType","@type":"rdfs:Class"},"sc":"http://schema.org#","streetAddress":"sc:streetAddress","uuid":"sc:identifier"}],"endpoints":{"sharedInbox":"https://mobilizon.org/inbox"},"followers":"https://mobilizon.org/@tcit/followers","following":"https://mobilizon.org/@tcit/following","icon":{"mediaType":null,"type":"Image","url":"https://mobilizon.org/media/3a5f18c058a8193b1febfaf561f94ae8b91f85ac64c01ddf5ad7b251fb43baf5.jpg?name=profil.jpg"},"id":"https://mobilizon.org/@tcit","inbox":"https://mobilizon.org/@tcit/inbox","manuallyApprovesFollowers":false,"name":"Thomas Citharel","outbox":"https://mobilizon.org/@tcit/outbox","preferredUsername":"tcit","publicKey":{"id":"https://mobilizon.org/@tcit#main-key","owner":"https://mobilizon.org/@tcit","publicKeyPem":"-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAtzuZFviv5f12SuA0wZFMuwKS8RIlT3IjPCMLRDhiorZeV3UJ1lik\nDYO6mEh22KDXYgJtNVSYGF0Q5LJivgcvuvU+VQ048iTB1B2x0rHMr47KPByPjfVb\nKDeHt6fkHcLY0JK8UkIxW542wXAg4jX5w3gJi3pgTQrCT8VNyPbH1CaA0uW//9jc\nqzZQVFzpfdJoVOM9E3Urc/u58HC4xOptlM7+B/594ZI9drYwy5m+ZxHwlQUYCva4\n34dvwsfOGxkQyIrzXoep80EnWnFpYCLMcCiz+sEhPYxqLgNE+Cmn/6pv7SIscz6p\neVlQXIchdw+J4yl07paJDkFc6CNTCmaIHQIDAQAB\n-----END RSA PUBLIC KEY-----\n\n"},"summary":"Main profile","type":"Person","url":"https://mobilizon.org/@tcit"}
\ No newline at end of file
index 9ae6b015d6f74ef3e4efa57a8ccd18034408dbed..2aad7a5883b3811726d05e5f666c547019030171 100644 (file)
@@ -77,6 +77,15 @@ defmodule Pleroma.Object.FetcherTest do
       assert object
     end
 
+    test "it can fetch Mobilizon events" do
+      {:ok, object} =
+        Fetcher.fetch_object_from_id(
+          "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"
+        )
+
+      assert object
+    end
+
     test "it can fetch wedistribute articles" do
       {:ok, object} =
         Fetcher.fetch_object_from_id("https://wedistribute.org/wp-json/pterotype/v1/object/85810")
index 49f63c424aa08079479646bdff8ae5b0a7802f2c..78f1ea9e46c83079c59667a7cf058cb9846ee0d5 100644 (file)
@@ -145,9 +145,9 @@ defmodule Pleroma.Plugs.RateLimiterTest do
     test "can have limits seperate from unauthenticated connections" do
       limiter_name = :test_authenticated
 
-      scale = 1000
+      scale = 50
       limit = 5
-      Pleroma.Config.put([:rate_limit, limiter_name], [{1, 10}, {scale, limit}])
+      Pleroma.Config.put([:rate_limit, limiter_name], [{1000, 1}, {scale, limit}])
 
       opts = RateLimiter.init(name: limiter_name)
 
@@ -164,16 +164,6 @@ defmodule Pleroma.Plugs.RateLimiterTest do
 
       assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests)
       assert conn.halted
-
-      Process.sleep(1550)
-
-      conn = conn(:get, "/") |> assign(:user, user)
-      conn = RateLimiter.call(conn, opts)
-      assert {1, 4} = RateLimiter.inspect_bucket(conn, limiter_name, opts)
-
-      refute conn.status == Plug.Conn.Status.code(:too_many_requests)
-      refute conn.resp_body
-      refute conn.halted
     end
 
     test "diffrerent users are counted independently" do
diff --git a/test/runtime_test.exs b/test/runtime_test.exs
new file mode 100644 (file)
index 0000000..f7b6f23
--- /dev/null
@@ -0,0 +1,11 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.RuntimeTest do
+  use ExUnit.Case, async: true
+
+  test "it loads custom runtime modules" do
+    assert Code.ensure_compiled?(RuntimeModule)
+  end
+end
index e3a621f49ac0fcabc08fc51cda0109d116fc1114..f43de700d98a210bb4f2f98340d3d88879277587 100644 (file)
@@ -308,6 +308,24 @@ defmodule HttpRequestMock do
      }}
   end
 
+  def get("https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39", _, _,
+        Accept: "application/activity+json"
+      ) do
+    {:ok,
+     %Tesla.Env{
+       status: 200,
+       body: File.read!("test/fixtures/tesla_mock/mobilizon.org-event.json")
+     }}
+  end
+
+  def get("https://mobilizon.org/@tcit", _, _, Accept: "application/activity+json") do
+    {:ok,
+     %Tesla.Env{
+       status: 200,
+       body: File.read!("test/fixtures/tesla_mock/mobilizon.org-user.json")
+     }}
+  end
+
   def get("https://baptiste.gelez.xyz/@/BaptisteGelez", _, _, _) do
     {:ok,
      %Tesla.Env{
index ad1fb6d02ff7c2161d7a08d040ffb8367e35d8d9..ad6b9810cf71e0fe9ec4d81871b53a11c48db14f 100644 (file)
@@ -1623,6 +1623,44 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
       assert follow_info.following_count == 32
       assert follow_info.hide_follows == true
     end
+
+    test "doesn't crash when follower and following counters are hidden" do
+      mock(fn env ->
+        case env.url do
+          "http://localhost:4001/users/masto_hidden_counters/following" ->
+            json(%{
+              "@context" => "https://www.w3.org/ns/activitystreams",
+              "id" => "http://localhost:4001/users/masto_hidden_counters/followers"
+            })
+
+          "http://localhost:4001/users/masto_hidden_counters/following?page=1" ->
+            %Tesla.Env{status: 403, body: ""}
+
+          "http://localhost:4001/users/masto_hidden_counters/followers" ->
+            json(%{
+              "@context" => "https://www.w3.org/ns/activitystreams",
+              "id" => "http://localhost:4001/users/masto_hidden_counters/following"
+            })
+
+          "http://localhost:4001/users/masto_hidden_counters/followers?page=1" ->
+            %Tesla.Env{status: 403, body: ""}
+        end
+      end)
+
+      user =
+        insert(:user,
+          local: false,
+          follower_address: "http://localhost:4001/users/masto_hidden_counters/followers",
+          following_address: "http://localhost:4001/users/masto_hidden_counters/following"
+        )
+
+      {:ok, follow_info} = ActivityPub.fetch_follow_information_for_user(user)
+
+      assert follow_info.hide_followers == true
+      assert follow_info.follower_count == 0
+      assert follow_info.hide_follows == true
+      assert follow_info.following_count == 0
+    end
   end
 
   describe "fetch_favourites/3" do
@@ -1639,13 +1677,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
 
       {:ok, _, _} = CommonAPI.favorite(a4.id, user)
       {:ok, _, _} = CommonAPI.favorite(a3.id, other_user)
-      Process.sleep(1000)
       {:ok, _, _} = CommonAPI.favorite(a3.id, user)
       {:ok, _, _} = CommonAPI.favorite(a5.id, other_user)
-      Process.sleep(1000)
       {:ok, _, _} = CommonAPI.favorite(a5.id, user)
       {:ok, _, _} = CommonAPI.favorite(a4.id, other_user)
-      Process.sleep(1000)
       {:ok, _, _} = CommonAPI.favorite(a1.id, user)
       {:ok, _, _} = CommonAPI.favorite(a1.id, other_user)
       result = ActivityPub.fetch_favourites(user)
index 3299be2d51530b1503ac6415f5f112128271b298..8374b8d236ed2f4b327657e11d9f3d246e594f48 100644 (file)
@@ -126,7 +126,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
       {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
       assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user})
       user = Map.merge(user, %{hide_followers_count: true, hide_followers: true})
-      assert %{"totalItems" => 0} = UserView.render("followers.json", %{user: user})
+      refute UserView.render("followers.json", %{user: user}) |> Map.has_key?("totalItems")
     end
 
     test "sets correct totalItems when followers are hidden but the follower counter is not" do
index bdd87a79e6296339530f3a73b62430f10c3a03a2..17b6ebcbcacbb756ff16147461a707308a5bb6cb 100644 (file)
@@ -394,6 +394,21 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
     assert length(represented[:media_attachments]) == 1
   end
 
+  test "a Mobilizon event" do
+    user = insert(:user)
+
+    {:ok, object} =
+      Pleroma.Object.Fetcher.fetch_object_from_id(
+        "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"
+      )
+
+    %Activity{} = activity = Activity.get_create_by_object_ap_id(object.data["id"])
+
+    represented = StatusView.render("show.json", %{for: user, activity: activity})
+
+    assert represented[:id] == to_string(activity.id)
+  end
+
   describe "build_tags/1" do
     test "it returns a a dictionary tags" do
       object_tags = [
index 0814006d206841cfbc7b572f9d19ad55f7124720..85a654f52caa9b39a4ed27f68d963e44aa0842be 100644 (file)
@@ -26,7 +26,32 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCardTest do
            ]
   end
 
-  test "it does not render attachments if post is nsfw" do
+  test "it uses summary twittercard if post has no attachment" do
+    user = insert(:user, name: "Jimmy Hendriks", bio: "born 19 March 1994")
+    {:ok, activity} = CommonAPI.post(user, %{"status" => "HI"})
+
+    note =
+      insert(:note, %{
+        data: %{
+          "actor" => user.ap_id,
+          "tag" => [],
+          "id" => "https://pleroma.gov/objects/whatever",
+          "content" => "pleroma in a nutshell"
+        }
+      })
+
+    result = TwitterCard.build_tags(%{object: note, user: user, activity_id: activity.id})
+
+    assert [
+             {:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []},
+             {:meta, [property: "twitter:description", content: "“pleroma in a nutshell”"], []},
+             {:meta, [property: "twitter:image", content: "http://localhost:4001/images/avi.png"],
+              []},
+             {:meta, [property: "twitter:card", content: "summary"], []}
+           ] == result
+  end
+
+  test "it renders avatar not attachment if post is nsfw and unfurl_nsfw is disabled" do
     Pleroma.Config.put([Pleroma.Web.Metadata, :unfurl_nsfw], false)
     user = insert(:user, name: "Jimmy Hendriks", bio: "born 19 March 1994")
     {:ok, activity} = CommonAPI.post(user, %{"status" => "HI"})
@@ -67,7 +92,7 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCardTest do
              {:meta, [property: "twitter:description", content: "“pleroma in a nutshell”"], []},
              {:meta, [property: "twitter:image", content: "http://localhost:4001/images/avi.png"],
               []},
-             {:meta, [property: "twitter:card", content: "summary_large_image"], []}
+             {:meta, [property: "twitter:card", content: "summary"], []}
            ] == result
   end
 
index 8911c46b190bdd62e2ccc328697ea2c5d2cf3e40..7166d6f0ba3d70a22405160965d2ade8ef9e4e12 100644 (file)
@@ -16,6 +16,10 @@ defmodule Pleroma.Web.StreamerTest do
   alias Pleroma.Web.Streamer.Worker
 
   @moduletag needs_streamer: true, capture_log: true
+
+  @streamer_timeout 150
+  @streamer_start_wait 10
+
   clear_config_all([:instance, :skip_thread_containment])
 
   describe "user streams" do
@@ -28,7 +32,7 @@ defmodule Pleroma.Web.StreamerTest do
     test "it sends notify to in the 'user' stream", %{user: user, notify: notify} do
       task =
         Task.async(fn ->
-          assert_receive {:text, _}, 4_000
+          assert_receive {:text, _}, @streamer_timeout
         end)
 
       Streamer.add_socket(
@@ -43,7 +47,7 @@ defmodule Pleroma.Web.StreamerTest do
     test "it sends notify to in the 'user:notification' stream", %{user: user, notify: notify} do
       task =
         Task.async(fn ->
-          assert_receive {:text, _}, 4_000
+          assert_receive {:text, _}, @streamer_timeout
         end)
 
       Streamer.add_socket(
@@ -61,7 +65,7 @@ defmodule Pleroma.Web.StreamerTest do
       blocked = insert(:user)
       {:ok, _user_relationship} = User.block(user, blocked)
 
-      task = Task.async(fn -> refute_receive {:text, _}, 4_000 end)
+      task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
 
       Streamer.add_socket(
         "user:notification",
@@ -79,7 +83,7 @@ defmodule Pleroma.Web.StreamerTest do
       user: user
     } do
       user2 = insert(:user)
-      task = Task.async(fn -> refute_receive {:text, _}, 4_000 end)
+      task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
 
       Streamer.add_socket(
         "user:notification",
@@ -97,7 +101,7 @@ defmodule Pleroma.Web.StreamerTest do
       user: user
     } do
       user2 = insert(:user, %{ap_id: "https://hecking-lewd-place.com/user/meanie"})
-      task = Task.async(fn -> refute_receive {:text, _}, 4_000 end)
+      task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
 
       Streamer.add_socket(
         "user:notification",
@@ -116,7 +120,9 @@ defmodule Pleroma.Web.StreamerTest do
       user: user
     } do
       user2 = insert(:user)
-      task = Task.async(fn -> assert_receive {:text, _}, 4_000 end)
+      task = Task.async(fn -> assert_receive {:text, _}, @streamer_timeout end)
+
+      Process.sleep(@streamer_start_wait)
 
       Streamer.add_socket(
         "user:notification",
@@ -137,7 +143,7 @@ defmodule Pleroma.Web.StreamerTest do
 
     task =
       Task.async(fn ->
-        assert_receive {:text, _}, 4_000
+        assert_receive {:text, _}, @streamer_timeout
       end)
 
     fake_socket = %StreamerSocket{
@@ -164,7 +170,7 @@ defmodule Pleroma.Web.StreamerTest do
           }
           |> Jason.encode!()
 
-        assert_receive {:text, received_event}, 4_000
+        assert_receive {:text, received_event}, @streamer_timeout
         assert received_event == expected_event
       end)
 
@@ -458,9 +464,7 @@ defmodule Pleroma.Web.StreamerTest do
 
     {:ok, activity} = CommonAPI.add_mute(user2, activity)
 
-    task = Task.async(fn -> refute_receive {:text, _}, 4_000 end)
-
-    Process.sleep(4000)
+    task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
 
     Streamer.add_socket(
       "user",
@@ -482,7 +486,7 @@ defmodule Pleroma.Web.StreamerTest do
 
       task =
         Task.async(fn ->
-          assert_receive {:text, received_event}, 4_000
+          assert_receive {:text, received_event}, @streamer_timeout
 
           assert %{"event" => "conversation", "payload" => received_payload} =
                    Jason.decode!(received_event)
@@ -518,13 +522,13 @@ defmodule Pleroma.Web.StreamerTest do
 
       task =
         Task.async(fn ->
-          assert_receive {:text, received_event}, 4_000
+          assert_receive {:text, received_event}, @streamer_timeout
           assert %{"event" => "delete", "payload" => _} = Jason.decode!(received_event)
 
-          refute_receive {:text, _}, 4_000
+          refute_receive {:text, _}, @streamer_timeout
         end)
 
-      Process.sleep(1000)
+      Process.sleep(@streamer_start_wait)
 
       Streamer.add_socket(
         "direct",
@@ -555,10 +559,10 @@ defmodule Pleroma.Web.StreamerTest do
 
       task =
         Task.async(fn ->
-          assert_receive {:text, received_event}, 4_000
+          assert_receive {:text, received_event}, @streamer_timeout
           assert %{"event" => "delete", "payload" => _} = Jason.decode!(received_event)
 
-          assert_receive {:text, received_event}, 4_000
+          assert_receive {:text, received_event}, @streamer_timeout
 
           assert %{"event" => "conversation", "payload" => received_payload} =
                    Jason.decode!(received_event)
@@ -567,7 +571,7 @@ defmodule Pleroma.Web.StreamerTest do
           assert last_status["id"] == to_string(create_activity.id)
         end)
 
-      Process.sleep(1000)
+      Process.sleep(@streamer_start_wait)
 
       Streamer.add_socket(
         "direct",
index 734cd221199554898ef40bbec79c0b658a4b139a..43299e147b3f5d9ec67035dda40215fd16457f33 100644 (file)
@@ -898,8 +898,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
         |> post("/api/pleroma/delete_account", %{"password" => "test"})
 
       assert json_response(conn, 200) == %{"status" => "success"}
-      # Wait a second for the started task to end
-      :timer.sleep(1000)
     end
   end
 end