Merge branch 'develop' into 'develop'
authorlain <lain@soykaf.club>
Tue, 7 Jul 2020 11:41:56 +0000 (11:41 +0000)
committerlain <lain@soykaf.club>
Tue, 7 Jul 2020 11:41:56 +0000 (11:41 +0000)
added hyper:// to default protocols

See merge request pleroma/pleroma!2727

15 files changed:
CHANGELOG.md
benchmarks/load_testing/activities.ex
benchmarks/load_testing/fetcher.ex
lib/pleroma/filter.ex
lib/pleroma/notification.ex
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/activity_pub/transmogrifier.ex
test/filter_test.exs
test/fixtures/tesla_mock/framatube.org-video.json [new file with mode: 0644]
test/fixtures/tesla_mock/https___framatube.org_accounts_framasoft.json [new file with mode: 0644]
test/notification_test.exs
test/support/factory.ex
test/support/http_request_mock.ex
test/web/activity_pub/activity_pub_test.exs
test/web/activity_pub/transmogrifier_test.exs

index c4077c85d89240fef74e7493e09da9ee841c286a..0e2b549163407cbf8d3aeff420a3085861a3f5ec 100644 (file)
@@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Streaming: Repeats of a user's posts will no longer be pushed to the user's stream.
 - Mastodon API: Added `pleroma.metadata.fields_limits` to /api/v1/instance
 - Mastodon API: On deletion, returns the original post text.
+- Mastodon API: Add `pleroma.unread_count` to the Marker entity.
 </details>
 
 <details>
@@ -59,8 +60,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Mastodon API: Extended `/api/v1/instance`.
 - Mastodon API: Support for `include_types` in `/api/v1/notifications`.
 - Mastodon API: Added `/api/v1/notifications/:id/dismiss` endpoint.
-- Mastodon API: Add support for filtering replies in public and home timelines
-- Mastodon API: Support for `bot` field in `/api/v1/accounts/update_credentials`
+- Mastodon API: Add support for filtering replies in public and home timelines.
+- Mastodon API: Support for `bot` field in `/api/v1/accounts/update_credentials`.
+- Mastodon API: Support irreversible property for filters.
 - Admin API: endpoints for create/update/delete OAuth Apps.
 - Admin API: endpoint for status view.
 - OTP: Add command to reload emoji packs
@@ -215,7 +217,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Mastodon API: `pleroma.thread_muted` to the Status entity
 - Mastodon API: Mark the direct conversation as read for the author when they send a new direct message
 - Mastodon API, streaming: Add `pleroma.direct_conversation_id` to the `conversation` stream event payload.
-- Mastodon API: Add `pleroma.unread_count` to the Marker entity
 - Admin API: Render whole status in grouped reports
 - Mastodon API: User timelines will now respect blocks, unless you are getting the user timeline of somebody you blocked (which would be empty otherwise).
 - Mastodon API: Favoriting / Repeating a post multiple times will now return the identical response every time. Before, executing that action twice would return an error ("already favorited") on the second try.
index 074ded45709139da3896ec503412eefc6a45e011..f5c7bfce845856c79d216e263d11f30a34a9e449 100644 (file)
@@ -24,6 +24,7 @@ defmodule Pleroma.LoadTesting.Activities do
   @visibility ~w(public private direct unlisted)
   @types [
     :simple,
+    :simple_filtered,
     :emoji,
     :mentions,
     :hell_thread,
@@ -242,6 +243,15 @@ defmodule Pleroma.LoadTesting.Activities do
     insert_local_activity(visibility, group, users, "Simple status")
   end
 
+  defp insert_activity(:simple_filtered, visibility, group, users, _opts)
+       when group in @remote_groups do
+    insert_remote_activity(visibility, group, users, "Remote status which must be filtered")
+  end
+
+  defp insert_activity(:simple_filtered, visibility, group, users, _opts) do
+    insert_local_activity(visibility, group, users, "Simple status which must be filtered")
+  end
+
   defp insert_activity(:emoji, visibility, group, users, _opts)
        when group in @remote_groups do
     insert_remote_activity(visibility, group, users, "Remote status with emoji :firefox:")
index 15fd06c3d262a0189f7ed473025989799a817dd0..dfbd916bef3757ef988803a2e20fe82139705e4b 100644 (file)
@@ -32,10 +32,22 @@ defmodule Pleroma.LoadTesting.Fetcher do
     )
   end
 
+  defp create_filter(user) do
+    Pleroma.Filter.create(%Pleroma.Filter{
+      user_id: user.id,
+      phrase: "must be filtered",
+      hide: true
+    })
+  end
+
+  defp delete_filter(filter), do: Repo.delete(filter)
+
   defp fetch_timelines(user) do
     fetch_home_timeline(user)
+    fetch_home_timeline_with_filter(user)
     fetch_direct_timeline(user)
     fetch_public_timeline(user)
+    fetch_public_timeline_with_filter(user)
     fetch_public_timeline(user, :with_blocks)
     fetch_public_timeline(user, :local)
     fetch_public_timeline(user, :tag)
@@ -61,7 +73,7 @@ defmodule Pleroma.LoadTesting.Fetcher do
     }
   end
 
-  defp fetch_home_timeline(user) do
+  defp fetch_home_timeline(user, title_end \\ "") do
     opts = opts_for_home_timeline(user)
 
     recipients = [user.ap_id | User.following(user)]
@@ -84,9 +96,11 @@ defmodule Pleroma.LoadTesting.Fetcher do
       |> Enum.reverse()
       |> List.last()
 
+    title = "home timeline " <> title_end
+
     Benchee.run(
       %{
-        "home timeline" => fn opts -> ActivityPub.fetch_activities(recipients, opts) end
+        title => fn opts -> ActivityPub.fetch_activities(recipients, opts) end
       },
       inputs: %{
         "1 page" => opts,
@@ -108,6 +122,14 @@ defmodule Pleroma.LoadTesting.Fetcher do
     )
   end
 
+  defp fetch_home_timeline_with_filter(user) do
+    {:ok, filter} = create_filter(user)
+
+    fetch_home_timeline(user, "with filters")
+
+    delete_filter(filter)
+  end
+
   defp opts_for_direct_timeline(user) do
     %{
       visibility: "direct",
@@ -210,6 +232,14 @@ defmodule Pleroma.LoadTesting.Fetcher do
     fetch_public_timeline(opts, "public timeline")
   end
 
+  defp fetch_public_timeline_with_filter(user) do
+    {:ok, filter} = create_filter(user)
+    opts = opts_for_public_timeline(user)
+
+    fetch_public_timeline(opts, "public timeline with filters")
+    delete_filter(filter)
+  end
+
   defp fetch_public_timeline(user, :local) do
     opts = opts_for_public_timeline(user, :local)
 
index 4d61b36502911679f4a8e9146af4ff761bdab726..5d6df95306ef768256b10f3585bfe3074199f745 100644 (file)
@@ -34,10 +34,18 @@ defmodule Pleroma.Filter do
     Repo.one(query)
   end
 
-  def get_filters(%User{id: user_id} = _user) do
+  def get_active(query) do
+    from(f in query, where: is_nil(f.expires_at) or f.expires_at > ^NaiveDateTime.utc_now())
+  end
+
+  def get_irreversible(query) do
+    from(f in query, where: f.hide)
+  end
+
+  def get_filters(query \\ __MODULE__, %User{id: user_id}) do
     query =
       from(
-        f in Pleroma.Filter,
+        f in query,
         where: f.user_id == ^user_id,
         order_by: [desc: :id]
       )
@@ -95,4 +103,34 @@ defmodule Pleroma.Filter do
     |> validate_required([:phrase, :context])
     |> Repo.update()
   end
+
+  def compose_regex(user_or_filters, format \\ :postgres)
+
+  def compose_regex(%User{} = user, format) do
+    __MODULE__
+    |> get_active()
+    |> get_irreversible()
+    |> get_filters(user)
+    |> compose_regex(format)
+  end
+
+  def compose_regex([_ | _] = filters, format) do
+    phrases =
+      filters
+      |> Enum.map(& &1.phrase)
+      |> Enum.join("|")
+
+    case format do
+      :postgres ->
+        "\\y(#{phrases})\\y"
+
+      :re ->
+        ~r/\b#{phrases}\b/i
+
+      _ ->
+        nil
+    end
+  end
+
+  def compose_regex(_, _), do: nil
 end
index 2ef1a80c5746a27013282f63cc91f39eb3724c2b..fcb2144ae24ac5e922556086c21de79ef2c6fc5d 100644 (file)
@@ -130,6 +130,7 @@ defmodule Pleroma.Notification do
     |> preload([n, a, o], activity: {a, object: o})
     |> exclude_notification_muted(user, exclude_notification_muted_opts)
     |> exclude_blocked(user, exclude_blocked_opts)
+    |> exclude_filtered(user)
     |> exclude_visibility(opts)
   end
 
@@ -158,6 +159,20 @@ defmodule Pleroma.Notification do
     |> where([n, a, o, tm], is_nil(tm.user_id))
   end
 
+  defp exclude_filtered(query, user) do
+    case Pleroma.Filter.compose_regex(user) do
+      nil ->
+        query
+
+      regex ->
+        from([_n, a, o] in query,
+          where:
+            fragment("not(?->>'content' ~* ?)", o.data, ^regex) or
+              fragment("?->>'actor' = ?", o.data, ^user.ap_id)
+        )
+    end
+  end
+
   @valid_visibilities ~w[direct unlisted public private]
 
   defp exclude_visibility(query, %{exclude_visibilities: visibility})
@@ -337,6 +352,7 @@ defmodule Pleroma.Notification do
     end
   end
 
+  @spec create_notifications(Activity.t(), keyword()) :: {:ok, [Notification.t()] | []}
   def create_notifications(activity, options \\ [])
 
   def create_notifications(%Activity{data: %{"to" => _, "type" => "Create"}} = activity, options) do
@@ -555,7 +571,8 @@ defmodule Pleroma.Notification do
       :follows,
       :non_followers,
       :non_follows,
-      :recently_followed
+      :recently_followed,
+      :filtered
     ]
     |> Enum.find(&skip?(&1, activity, user))
   end
@@ -624,6 +641,26 @@ defmodule Pleroma.Notification do
     end)
   end
 
+  def skip?(:filtered, %{data: %{"type" => type}}, _) when type in ["Follow", "Move"], do: false
+
+  def skip?(:filtered, activity, user) do
+    object = Object.normalize(activity)
+
+    cond do
+      is_nil(object) ->
+        false
+
+      object.data["actor"] == user.ap_id ->
+        false
+
+      not is_nil(regex = Pleroma.Filter.compose_regex(user, :re)) ->
+        Regex.match?(regex, object.data["content"])
+
+      true ->
+        false
+    end
+  end
+
   def skip?(_, _, _), do: false
 
   def for_user_and_activity(user, activity) do
index 94117202c25a003d6db769b2be48c159e9a17d56..8abbef487fb0b70d6a0d1da465b64392a0c4cf32 100644 (file)
@@ -10,6 +10,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
   alias Pleroma.Constants
   alias Pleroma.Conversation
   alias Pleroma.Conversation.Participation
+  alias Pleroma.Filter
   alias Pleroma.Maps
   alias Pleroma.Notification
   alias Pleroma.Object
@@ -446,6 +447,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     |> maybe_set_thread_muted_field(opts)
     |> restrict_blocked(opts)
     |> restrict_recipients(recipients, opts[:user])
+    |> restrict_filtered(opts)
     |> where(
       [activity],
       fragment(
@@ -961,6 +963,26 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
 
   defp restrict_instance(query, _), do: query
 
+  defp restrict_filtered(query, %{user: %User{} = user}) do
+    case Filter.compose_regex(user) do
+      nil ->
+        query
+
+      regex ->
+        from([activity, object] in query,
+          where:
+            fragment("not(?->>'content' ~* ?)", object.data, ^regex) or
+              activity.actor == ^user.ap_id
+        )
+    end
+  end
+
+  defp restrict_filtered(query, %{blocking_user: %User{} = user}) do
+    restrict_filtered(query, %{user: user})
+  end
+
+  defp restrict_filtered(query, _), do: query
+
   defp exclude_poll_votes(query, %{include_poll_votes: true}), do: query
 
   defp exclude_poll_votes(query, _) do
@@ -1091,6 +1113,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     |> restrict_favorited_by(opts)
     |> restrict_blocked(restrict_blocked_opts)
     |> restrict_muted(restrict_muted_opts)
+    |> restrict_filtered(opts)
     |> restrict_media(opts)
     |> restrict_visibility(opts)
     |> restrict_thread_visibility(opts, config)
@@ -1099,6 +1122,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     |> restrict_muted_reblogs(restrict_muted_reblogs_opts)
     |> restrict_instance(opts)
     |> restrict_announce_object_actor(opts)
+    |> restrict_filtered(opts)
     |> Activity.restrict_deactivated_users()
     |> exclude_poll_votes(opts)
     |> exclude_chat_messages(opts)
index bc6fc4bd837c772df7191482a75bf7adc29c4612..117e930b37a0a73a85bc4c3429760c0f14c1a3a2 100644 (file)
@@ -233,18 +233,24 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
             is_map(url) && is_binary(url["href"]) -> url["href"]
             is_binary(data["url"]) -> data["url"]
             is_binary(data["href"]) -> data["href"]
+            true -> nil
           end
 
-        attachment_url =
-          %{"href" => href}
-          |> Maps.put_if_present("mediaType", media_type)
-          |> Maps.put_if_present("type", Map.get(url || %{}, "type"))
+        if href do
+          attachment_url =
+            %{"href" => href}
+            |> Maps.put_if_present("mediaType", media_type)
+            |> Maps.put_if_present("type", Map.get(url || %{}, "type"))
 
-        %{"url" => [attachment_url]}
-        |> Maps.put_if_present("mediaType", media_type)
-        |> Maps.put_if_present("type", data["type"])
-        |> Maps.put_if_present("name", data["name"])
+          %{"url" => [attachment_url]}
+          |> Maps.put_if_present("mediaType", media_type)
+          |> Maps.put_if_present("type", data["type"])
+          |> Maps.put_if_present("name", data["name"])
+        else
+          nil
+        end
       end)
+      |> Enum.filter(& &1)
 
     Map.put(object, "attachment", attachments)
   end
@@ -263,12 +269,18 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
 
   def fix_url(%{"type" => object_type, "url" => url} = object)
       when object_type in ["Video", "Audio"] and is_list(url) do
-    first_element = Enum.at(url, 0)
+    attachment =
+      Enum.find(url, fn x ->
+        media_type = x["mediaType"] || x["mimeType"] || ""
+
+        is_map(x) and String.starts_with?(media_type, ["audio/", "video/"])
+      end)
 
-    link_element = Enum.find(url, fn x -> is_map(x) and x["mimeType"] == "text/html" end)
+    link_element =
+      Enum.find(url, fn x -> is_map(x) and (x["mediaType"] || x["mimeType"]) == "text/html" end)
 
     object
-    |> Map.put("attachment", [first_element])
+    |> Map.put("attachment", [attachment])
     |> Map.put("url", link_element["href"])
   end
 
index 63a30c736d0c6aed72cb29eb54c68e580cda6d40..0a5c4426aaf69a2849816ef18cad8033a0044fd6 100644 (file)
@@ -3,37 +3,39 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.FilterTest do
-  alias Pleroma.Repo
   use Pleroma.DataCase
 
   import Pleroma.Factory
 
+  alias Pleroma.Filter
+  alias Pleroma.Repo
+
   describe "creating filters" do
     test "creating one filter" do
       user = insert(:user)
 
-      query = %Pleroma.Filter{
+      query = %Filter{
         user_id: user.id,
         filter_id: 42,
         phrase: "knights",
         context: ["home"]
       }
 
-      {:ok, %Pleroma.Filter{} = filter} = Pleroma.Filter.create(query)
-      result = Pleroma.Filter.get(filter.filter_id, user)
+      {:ok, %Filter{} = filter} = Filter.create(query)
+      result = Filter.get(filter.filter_id, user)
       assert query.phrase == result.phrase
     end
 
     test "creating one filter without a pre-defined filter_id" do
       user = insert(:user)
 
-      query = %Pleroma.Filter{
+      query = %Filter{
         user_id: user.id,
         phrase: "knights",
         context: ["home"]
       }
 
-      {:ok, %Pleroma.Filter{} = filter} = Pleroma.Filter.create(query)
+      {:ok, %Filter{} = filter} = Filter.create(query)
       # Should start at 1
       assert filter.filter_id == 1
     end
@@ -41,23 +43,23 @@ defmodule Pleroma.FilterTest do
     test "creating additional filters uses previous highest filter_id + 1" do
       user = insert(:user)
 
-      query_one = %Pleroma.Filter{
+      query_one = %Filter{
         user_id: user.id,
         filter_id: 42,
         phrase: "knights",
         context: ["home"]
       }
 
-      {:ok, %Pleroma.Filter{} = filter_one} = Pleroma.Filter.create(query_one)
+      {:ok, %Filter{} = filter_one} = Filter.create(query_one)
 
-      query_two = %Pleroma.Filter{
+      query_two = %Filter{
         user_id: user.id,
         # No filter_id
         phrase: "who",
         context: ["home"]
       }
 
-      {:ok, %Pleroma.Filter{} = filter_two} = Pleroma.Filter.create(query_two)
+      {:ok, %Filter{} = filter_two} = Filter.create(query_two)
       assert filter_two.filter_id == filter_one.filter_id + 1
     end
 
@@ -65,29 +67,29 @@ defmodule Pleroma.FilterTest do
       user_one = insert(:user)
       user_two = insert(:user)
 
-      query_one = %Pleroma.Filter{
+      query_one = %Filter{
         user_id: user_one.id,
         phrase: "knights",
         context: ["home"]
       }
 
-      {:ok, %Pleroma.Filter{} = filter_one} = Pleroma.Filter.create(query_one)
+      {:ok, %Filter{} = filter_one} = Filter.create(query_one)
 
-      query_two = %Pleroma.Filter{
+      query_two = %Filter{
         user_id: user_two.id,
         phrase: "who",
         context: ["home"]
       }
 
-      {:ok, %Pleroma.Filter{} = filter_two} = Pleroma.Filter.create(query_two)
+      {:ok, %Filter{} = filter_two} = Filter.create(query_two)
 
       assert filter_one.filter_id == 1
       assert filter_two.filter_id == 1
 
-      result_one = Pleroma.Filter.get(filter_one.filter_id, user_one)
+      result_one = Filter.get(filter_one.filter_id, user_one)
       assert result_one.phrase == filter_one.phrase
 
-      result_two = Pleroma.Filter.get(filter_two.filter_id, user_two)
+      result_two = Filter.get(filter_two.filter_id, user_two)
       assert result_two.phrase == filter_two.phrase
     end
   end
@@ -95,38 +97,38 @@ defmodule Pleroma.FilterTest do
   test "deleting a filter" do
     user = insert(:user)
 
-    query = %Pleroma.Filter{
+    query = %Filter{
       user_id: user.id,
       filter_id: 0,
       phrase: "knights",
       context: ["home"]
     }
 
-    {:ok, _filter} = Pleroma.Filter.create(query)
-    {:ok, filter} = Pleroma.Filter.delete(query)
-    assert is_nil(Repo.get(Pleroma.Filter, filter.filter_id))
+    {:ok, _filter} = Filter.create(query)
+    {:ok, filter} = Filter.delete(query)
+    assert is_nil(Repo.get(Filter, filter.filter_id))
   end
 
   test "getting all filters by an user" do
     user = insert(:user)
 
-    query_one = %Pleroma.Filter{
+    query_one = %Filter{
       user_id: user.id,
       filter_id: 1,
       phrase: "knights",
       context: ["home"]
     }
 
-    query_two = %Pleroma.Filter{
+    query_two = %Filter{
       user_id: user.id,
       filter_id: 2,
       phrase: "who",
       context: ["home"]
     }
 
-    {:ok, filter_one} = Pleroma.Filter.create(query_one)
-    {:ok, filter_two} = Pleroma.Filter.create(query_two)
-    filters = Pleroma.Filter.get_filters(user)
+    {:ok, filter_one} = Filter.create(query_one)
+    {:ok, filter_two} = Filter.create(query_two)
+    filters = Filter.get_filters(user)
     assert filter_one in filters
     assert filter_two in filters
   end
@@ -134,7 +136,7 @@ defmodule Pleroma.FilterTest do
   test "updating a filter" do
     user = insert(:user)
 
-    query_one = %Pleroma.Filter{
+    query_one = %Filter{
       user_id: user.id,
       filter_id: 1,
       phrase: "knights",
@@ -146,8 +148,9 @@ defmodule Pleroma.FilterTest do
       context: ["home", "timeline"]
     }
 
-    {:ok, filter_one} = Pleroma.Filter.create(query_one)
-    {:ok, filter_two} = Pleroma.Filter.update(filter_one, changes)
+    {:ok, filter_one} = Filter.create(query_one)
+    {:ok, filter_two} = Filter.update(filter_one, changes)
+
     assert filter_one != filter_two
     assert filter_two.phrase == changes.phrase
     assert filter_two.context == changes.context
diff --git a/test/fixtures/tesla_mock/framatube.org-video.json b/test/fixtures/tesla_mock/framatube.org-video.json
new file mode 100644 (file)
index 0000000..3d53f0c
--- /dev/null
@@ -0,0 +1 @@
+{"type":"Video","id":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206","name":"Déframasoftisons Internet [Framasoft]","duration":"PT3622S","uuid":"6050732a-8a7a-43d4-a6cd-809525a1d206","tag":[{"type":"Hashtag","name":"déframasoftisons"},{"type":"Hashtag","name":"EPN23"},{"type":"Hashtag","name":"framaconf"},{"type":"Hashtag","name":"Framasoft"},{"type":"Hashtag","name":"pyg"}],"category":{"identifier":"15","name":"Science & Technology"},"views":122,"sensitive":false,"waitTranscoding":false,"state":1,"commentsEnabled":true,"downloadEnabled":true,"published":"2020-05-24T18:34:31.569Z","originallyPublishedAt":"2019-11-30T23:00:00.000Z","updated":"2020-07-05T09:01:01.720Z","mediaType":"text/markdown","content":"Après avoir mené avec un certain succès la campagne « Dégooglisons Internet » en 2014, l’association Framasoft annonce fin 2019 arrêter progressivement un certain nombre de ses services alternatifs aux GAFAM. Pourquoi ?\r\n\r\nTranscription par @april...","support":null,"subtitleLanguage":[],"icon":{"type":"Image","url":"https://framatube.org/static/thumbnails/6050732a-8a7a-43d4-a6cd-809525a1d206.jpg","mediaType":"image/jpeg","width":223,"height":122},"url":[{"type":"Link","mediaType":"text/html","href":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206"},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4","height":1080,"size":1157359410,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309939","height":1080,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.torrent","height":1080},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.torrent&xt=urn:btih:381c9429900552e23a4eb506318f1fa01e4d63a8&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4","height":1080},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4","height":480,"size":250095131,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309941","height":480,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-480.torrent","height":480},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.torrent&xt=urn:btih:a181dcbb5368ab5c31cc9ff07634becb72c344ee&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4","height":480},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4","height":360,"size":171357733,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309942","height":360,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-360.torrent","height":360},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.torrent&xt=urn:btih:aedfa9479ea04a175eee0b0bd0bda64076308746&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4","height":360},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4","height":720,"size":497100839,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309943","height":720,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-720.torrent","height":720},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.torrent&xt=urn:btih:71971668f82a3b24ac71bc3a982848dd8dc5a5f5&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4","height":720},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4","height":240,"size":113038439,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309944","height":240,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-240.torrent","height":240},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.torrent&xt=urn:btih:c42aa6c95efb28d9f114ebd98537f7b00fa72246&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4","height":240},{"type":"Link","mediaType":"application/x-mpegURL","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/master.m3u8","tag":[{"type":"Infohash","name":"f7428214539626e062f300f2ca4cf9154575144e"},{"type":"Infohash","name":"46e236dffb1ea6b9123a5396cbe88e97dd94cc6c"},{"type":"Infohash","name":"11f1045830b5d786c788f2594d19f128764e7d87"},{"type":"Infohash","name":"4327ad3e0d84de100130a27e9ab6fe40c4284f0e"},{"type":"Infohash","name":"41e2eee8e7b23a63c23a77c40a46de11492a4831"},{"type":"Link","name":"sha256","mediaType":"application/json","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/segments-sha256.json"},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-1080-fragmented.mp4","height":1080,"size":1156777472,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309940","height":1080,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-1080-hls.torrent","height":1080},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080-hls.torrent&xt=urn:btih:0204d780ebfab0d5d9d3476a038e812ad792deeb&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080-fragmented.mp4","height":1080},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-480-fragmented.mp4","height":480,"size":249562889,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309945","height":480,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-480-hls.torrent","height":480},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480-hls.torrent&xt=urn:btih:5d14f38ded29de629668fe1cfc61a75f4cce2628&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480-fragmented.mp4","height":480},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-360-fragmented.mp4","height":360,"size":170836415,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309946","height":360,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-360-hls.torrent","height":360},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360-hls.torrent&xt=urn:btih:30125488789080ad405ebcee6c214945f31b8f30&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360-fragmented.mp4","height":360},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-720-fragmented.mp4","height":720,"size":496533741,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309947","height":720,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-720-hls.torrent","height":720},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720-hls.torrent&xt=urn:btih:8ed1e8bccde709901c26e315fc8f53bfd26d1ba6&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720-fragmented.mp4","height":720},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-240-fragmented.mp4","height":240,"size":112529249,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309948","height":240,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-240-hls.torrent","height":240},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240-hls.torrent&xt=urn:btih:8b452bf4e70b9078d4e74ca8b5523cc9dc70d10a&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240-fragmented.mp4","height":240}]}],"likes":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/likes","dislikes":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/dislikes","shares":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/announces","comments":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/comments","attributedTo":[{"type":"Person","id":"https://framatube.org/accounts/framasoft"},{"type":"Group","id":"https://framatube.org/video-channels/bf54d359-cfad-4935-9d45-9d6be93f63e8"}],"to":["https://www.w3.org/ns/activitystreams#Public"],"cc":["https://framatube.org/accounts/framasoft/followers"],"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"RsaSignature2017":"https://w3id.org/security#RsaSignature2017"},{"pt":"https://joinpeertube.org/ns#","sc":"http://schema.org#","Hashtag":"as:Hashtag","uuid":"sc:identifier","category":"sc:category","licence":"sc:license","subtitleLanguage":"sc:subtitleLanguage","sensitive":"as:sensitive","language":"sc:inLanguage","Infohash":"pt:Infohash","Playlist":"pt:Playlist","PlaylistElement":"pt:PlaylistElement","originallyPublishedAt":"sc:datePublished","views":{"@type":"sc:Number","@id":"pt:views"},"state":{"@type":"sc:Number","@id":"pt:state"},"size":{"@type":"sc:Number","@id":"pt:size"},"fps":{"@type":"sc:Number","@id":"pt:fps"},"startTimestamp":{"@type":"sc:Number","@id":"pt:startTimestamp"},"stopTimestamp":{"@type":"sc:Number","@id":"pt:stopTimestamp"},"position":{"@type":"sc:Number","@id":"pt:position"},"commentsEnabled":{"@type":"sc:Boolean","@id":"pt:commentsEnabled"},"downloadEnabled":{"@type":"sc:Boolean","@id":"pt:downloadEnabled"},"waitTranscoding":{"@type":"sc:Boolean","@id":"pt:waitTranscoding"},"support":{"@type":"sc:Text","@id":"pt:support"},"likes":{"@id":"as:likes","@type":"@id"},"dislikes":{"@id":"as:dislikes","@type":"@id"},"playlists":{"@id":"pt:playlists","@type":"@id"},"shares":{"@id":"as:shares","@type":"@id"},"comments":{"@id":"as:comments","@type":"@id"}}]}
\ No newline at end of file
diff --git a/test/fixtures/tesla_mock/https___framatube.org_accounts_framasoft.json b/test/fixtures/tesla_mock/https___framatube.org_accounts_framasoft.json
new file mode 100644 (file)
index 0000000..1c3f779
--- /dev/null
@@ -0,0 +1 @@
+{"type":"Person","id":"https://framatube.org/accounts/framasoft","following":"https://framatube.org/accounts/framasoft/following","followers":"https://framatube.org/accounts/framasoft/followers","playlists":"https://framatube.org/accounts/framasoft/playlists","inbox":"https://framatube.org/accounts/framasoft/inbox","outbox":"https://framatube.org/accounts/framasoft/outbox","preferredUsername":"framasoft","url":"https://framatube.org/accounts/framasoft","name":"Framasoft","endpoints":{"sharedInbox":"https://framatube.org/inbox"},"publicKey":{"id":"https://framatube.org/accounts/framasoft#main-key","owner":"https://framatube.org/accounts/framasoft","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuRh3frgIg866D0y0FThp\nSUkJImMcHGkUvpYQYv2iUgarZZtEbwT8PfQf0bJazy+cP8KqQmMDf5PBhT7dfdny\nf/GKGMw9Olc+QISeKDj3sqZ3Csrm4KV4avMGCfth6eSU7LozojeSGCXdUFz/8UgE\nfhV4mJjEX/FbwRYoKlagv5rY9mkX5XomzZU+z9j6ZVXyofwOwJvmI1hq0SYDv2bc\neB/RgIh/H0nyMtF8o+0CT42FNEET9j9m1BKOBtPzwZHmitKRkEmui5cK256s1laB\nT61KHpcD9gQKkQ+I3sFEzCBUJYfVo6fUe+GehBZuAfq4qDhd15SfE4K9veDscDFI\nTwIDAQAB\n-----END PUBLIC KEY-----"},"icon":{"type":"Image","mediaType":"image/png","url":"https://framatube.org/lazy-static/avatars/f73876f5-1d45-4f8a-942a-d3d5d5ac5dc1.png"},"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"RsaSignature2017":"https://w3id.org/security#RsaSignature2017","pt":"https://joinpeertube.org/ns#","sc":"http://schema.org#","Hashtag":"as:Hashtag","uuid":"sc:identifier","category":"sc:category","licence":"sc:license","subtitleLanguage":"sc:subtitleLanguage","sensitive":"as:sensitive","language":"sc:inLanguage","expires":"sc:expires","CacheFile":"pt:CacheFile","Infohash":"pt:Infohash","originallyPublishedAt":"sc:datePublished","views":{"@type":"sc:Number","@id":"pt:views"},"state":{"@type":"sc:Number","@id":"pt:state"},"size":{"@type":"sc:Number","@id":"pt:size"},"fps":{"@type":"sc:Number","@id":"pt:fps"},"startTimestamp":{"@type":"sc:Number","@id":"pt:startTimestamp"},"stopTimestamp":{"@type":"sc:Number","@id":"pt:stopTimestamp"},"position":{"@type":"sc:Number","@id":"pt:position"},"commentsEnabled":{"@type":"sc:Boolean","@id":"pt:commentsEnabled"},"downloadEnabled":{"@type":"sc:Boolean","@id":"pt:downloadEnabled"},"waitTranscoding":{"@type":"sc:Boolean","@id":"pt:waitTranscoding"},"support":{"@type":"sc:Text","@id":"pt:support"}},{"likes":{"@id":"as:likes","@type":"@id"},"dislikes":{"@id":"as:dislikes","@type":"@id"},"playlists":{"@id":"pt:playlists","@type":"@id"},"shares":{"@id":"as:shares","@type":"@id"},"comments":{"@id":"as:comments","@type":"@id"}}],"summary":null}
\ No newline at end of file
index 6add3f7eba39c9cc4287fcc2c62a6717e13981d6..13e82ab2a7bca7a7f290b067f7ec580c4bdd149b 100644 (file)
@@ -324,6 +324,44 @@ defmodule Pleroma.NotificationTest do
       {:ok, status} = CommonAPI.post(author, %{status: "hey @#{user.nickname}"})
       refute Notification.create_notification(status, user)
     end
+
+    test "it doesn't create notifications if content matches with an irreversible filter" do
+      user = insert(:user)
+      subscriber = insert(:user)
+
+      User.subscribe(subscriber, user)
+      insert(:filter, user: subscriber, phrase: "cofe", hide: true)
+
+      {:ok, status} = CommonAPI.post(user, %{status: "got cofe?"})
+
+      assert {:ok, []} == Notification.create_notifications(status)
+    end
+
+    test "it creates notifications if content matches with a not irreversible filter" do
+      user = insert(:user)
+      subscriber = insert(:user)
+
+      User.subscribe(subscriber, user)
+      insert(:filter, user: subscriber, phrase: "cofe", hide: false)
+
+      {:ok, status} = CommonAPI.post(user, %{status: "got cofe?"})
+      {:ok, [notification]} = Notification.create_notifications(status)
+
+      assert notification
+    end
+
+    test "it creates notifications when someone likes user's status with a filtered word" do
+      user = insert(:user)
+      other_user = insert(:user)
+      insert(:filter, user: user, phrase: "tesla", hide: true)
+
+      {:ok, activity_one} = CommonAPI.post(user, %{status: "wow tesla"})
+      {:ok, activity_two} = CommonAPI.favorite(other_user, activity_one.id)
+
+      {:ok, [notification]} = Notification.create_notifications(activity_two)
+
+      assert notification
+    end
   end
 
   describe "follow / follow_request notifications" do
@@ -990,8 +1028,13 @@ defmodule Pleroma.NotificationTest do
   end
 
   describe "for_user" do
-    test "it returns notifications for muted user without notifications" do
+    setup do
       user = insert(:user)
+
+      {:ok, %{user: user}}
+    end
+
+    test "it returns notifications for muted user without notifications", %{user: user} do
       muted = insert(:user)
       {:ok, _user_relationships} = User.mute(user, muted, false)
 
@@ -1002,8 +1045,7 @@ defmodule Pleroma.NotificationTest do
       assert notification.activity.object
     end
 
-    test "it doesn't return notifications for muted user with notifications" do
-      user = insert(:user)
+    test "it doesn't return notifications for muted user with notifications", %{user: user} do
       muted = insert(:user)
       {:ok, _user_relationships} = User.mute(user, muted)
 
@@ -1012,8 +1054,7 @@ defmodule Pleroma.NotificationTest do
       assert Notification.for_user(user) == []
     end
 
-    test "it doesn't return notifications for blocked user" do
-      user = insert(:user)
+    test "it doesn't return notifications for blocked user", %{user: user} do
       blocked = insert(:user)
       {:ok, _user_relationship} = User.block(user, blocked)
 
@@ -1022,8 +1063,7 @@ defmodule Pleroma.NotificationTest do
       assert Notification.for_user(user) == []
     end
 
-    test "it doesn't return notifications for domain-blocked non-followed user" do
-      user = insert(:user)
+    test "it doesn't return notifications for domain-blocked non-followed user", %{user: user} do
       blocked = insert(:user, ap_id: "http://some-domain.com")
       {:ok, user} = User.block_domain(user, "some-domain.com")
 
@@ -1044,8 +1084,7 @@ defmodule Pleroma.NotificationTest do
       assert length(Notification.for_user(user)) == 1
     end
 
-    test "it doesn't return notifications for muted thread" do
-      user = insert(:user)
+    test "it doesn't return notifications for muted thread", %{user: user} do
       another_user = insert(:user)
 
       {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
@@ -1054,8 +1093,7 @@ defmodule Pleroma.NotificationTest do
       assert Notification.for_user(user) == []
     end
 
-    test "it returns notifications from a muted user when with_muted is set" do
-      user = insert(:user)
+    test "it returns notifications from a muted user when with_muted is set", %{user: user} do
       muted = insert(:user)
       {:ok, _user_relationships} = User.mute(user, muted)
 
@@ -1064,8 +1102,9 @@ defmodule Pleroma.NotificationTest do
       assert length(Notification.for_user(user, %{with_muted: true})) == 1
     end
 
-    test "it doesn't return notifications from a blocked user when with_muted is set" do
-      user = insert(:user)
+    test "it doesn't return notifications from a blocked user when with_muted is set", %{
+      user: user
+    } do
       blocked = insert(:user)
       {:ok, _user_relationship} = User.block(user, blocked)
 
@@ -1075,8 +1114,8 @@ defmodule Pleroma.NotificationTest do
     end
 
     test "when with_muted is set, " <>
-           "it doesn't return notifications from a domain-blocked non-followed user" do
-      user = insert(:user)
+           "it doesn't return notifications from a domain-blocked non-followed user",
+         %{user: user} do
       blocked = insert(:user, ap_id: "http://some-domain.com")
       {:ok, user} = User.block_domain(user, "some-domain.com")
 
@@ -1085,8 +1124,7 @@ defmodule Pleroma.NotificationTest do
       assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
     end
 
-    test "it returns notifications from muted threads when with_muted is set" do
-      user = insert(:user)
+    test "it returns notifications from muted threads when with_muted is set", %{user: user} do
       another_user = insert(:user)
 
       {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
@@ -1094,5 +1132,33 @@ defmodule Pleroma.NotificationTest do
       {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
       assert length(Notification.for_user(user, %{with_muted: true})) == 1
     end
+
+    test "it doesn't return notifications about mentions with filtered word", %{user: user} do
+      insert(:filter, user: user, phrase: "cofe", hide: true)
+      another_user = insert(:user)
+
+      {:ok, _activity} = CommonAPI.post(another_user, %{status: "@#{user.nickname} got cofe?"})
+
+      assert Enum.empty?(Notification.for_user(user))
+    end
+
+    test "it returns notifications about mentions with not hidden filtered word", %{user: user} do
+      insert(:filter, user: user, phrase: "test", hide: false)
+      another_user = insert(:user)
+
+      {:ok, _} = CommonAPI.post(another_user, %{status: "@#{user.nickname} test"})
+
+      assert length(Notification.for_user(user)) == 1
+    end
+
+    test "it returns notifications about favorites with filtered word", %{user: user} do
+      insert(:filter, user: user, phrase: "cofe", hide: true)
+      another_user = insert(:user)
+
+      {:ok, activity} = CommonAPI.post(user, %{status: "Give me my cofe!"})
+      {:ok, _} = CommonAPI.favorite(another_user, activity.id)
+
+      assert length(Notification.for_user(user)) == 1
+    end
   end
 end
index af580021c9ba46ecd16867ee047ca84ddd05909b..635d83650b9fec2525ce305dcaeb85cf9f0ab96a 100644 (file)
@@ -428,4 +428,12 @@ defmodule Pleroma.Factory do
       user: build(:user)
     }
   end
+
+  def filter_factory do
+    %Pleroma.Filter{
+      user: build(:user),
+      filter_id: sequence(:filter_id, & &1),
+      phrase: "cofe"
+    }
+  end
 end
index 3d5128835be17f12f0c4c1e0ecb3cbac28e81f3e..da04ac6f1e6617981c48cde5eccd9902a3df6e3c 100644 (file)
@@ -308,6 +308,22 @@ defmodule HttpRequestMock do
      }}
   end
 
+  def get("https://framatube.org/accounts/framasoft", _, _, _) do
+    {:ok,
+     %Tesla.Env{
+       status: 200,
+       body: File.read!("test/fixtures/tesla_mock/https___framatube.org_accounts_framasoft.json")
+     }}
+  end
+
+  def get("https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206", _, _, _) do
+    {:ok,
+     %Tesla.Env{
+       status: 200,
+       body: File.read!("test/fixtures/tesla_mock/framatube.org-video.json")
+     }}
+  end
+
   def get("https://peertube.social/accounts/craigmaloney", _, _, _) do
     {:ok,
      %Tesla.Env{
index 575e0c5db0b6b19b3acebc3d85500b6b365c00b5..17e12a1a72aec61eaa11c207f570b77c71f3cecd 100644 (file)
@@ -507,6 +507,33 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
       activities = ActivityPub.fetch_activities_for_context("2hu", %{blocking_user: user})
       assert activities == [activity_two, activity]
     end
+
+    test "doesn't return activities with filtered words" do
+      user = insert(:user)
+      user_two = insert(:user)
+      insert(:filter, user: user, phrase: "test", hide: true)
+
+      {:ok, %{id: id1, data: %{"context" => context}}} = CommonAPI.post(user, %{status: "1"})
+
+      {:ok, %{id: id2}} = CommonAPI.post(user_two, %{status: "2", in_reply_to_status_id: id1})
+
+      {:ok, %{id: id3} = user_activity} =
+        CommonAPI.post(user, %{status: "3 test?", in_reply_to_status_id: id2})
+
+      {:ok, %{id: id4} = filtered_activity} =
+        CommonAPI.post(user_two, %{status: "4 test!", in_reply_to_status_id: id3})
+
+      {:ok, _} = CommonAPI.post(user, %{status: "5", in_reply_to_status_id: id4})
+
+      activities =
+        context
+        |> ActivityPub.fetch_activities_for_context(%{user: user})
+        |> Enum.map(& &1.id)
+
+      assert length(activities) == 4
+      assert user_activity.id in activities
+      refute filtered_activity.id in activities
+    end
   end
 
   test "doesn't return blocked activities" do
@@ -785,6 +812,75 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
     assert activity == expected_activity
   end
 
+  describe "irreversible filters" do
+    setup do
+      user = insert(:user)
+      user_two = insert(:user)
+
+      insert(:filter, user: user_two, phrase: "cofe", hide: true)
+      insert(:filter, user: user_two, phrase: "ok boomer", hide: true)
+      insert(:filter, user: user_two, phrase: "test", hide: false)
+
+      params = %{
+        type: ["Create", "Announce"],
+        user: user_two
+      }
+
+      {:ok, %{user: user, user_two: user_two, params: params}}
+    end
+
+    test "it returns statuses if they don't contain exact filter words", %{
+      user: user,
+      params: params
+    } do
+      {:ok, _} = CommonAPI.post(user, %{status: "hey"})
+      {:ok, _} = CommonAPI.post(user, %{status: "got cofefe?"})
+      {:ok, _} = CommonAPI.post(user, %{status: "I am not a boomer"})
+      {:ok, _} = CommonAPI.post(user, %{status: "ok boomers"})
+      {:ok, _} = CommonAPI.post(user, %{status: "ccofee is not a word"})
+      {:ok, _} = CommonAPI.post(user, %{status: "this is a test"})
+
+      activities = ActivityPub.fetch_activities([], params)
+
+      assert Enum.count(activities) == 6
+    end
+
+    test "it does not filter user's own statuses", %{user_two: user_two, params: params} do
+      {:ok, _} = CommonAPI.post(user_two, %{status: "Give me some cofe!"})
+      {:ok, _} = CommonAPI.post(user_two, %{status: "ok boomer"})
+
+      activities = ActivityPub.fetch_activities([], params)
+
+      assert Enum.count(activities) == 2
+    end
+
+    test "it excludes statuses with filter words", %{user: user, params: params} do
+      {:ok, _} = CommonAPI.post(user, %{status: "Give me some cofe!"})
+      {:ok, _} = CommonAPI.post(user, %{status: "ok boomer"})
+      {:ok, _} = CommonAPI.post(user, %{status: "is it a cOfE?"})
+      {:ok, _} = CommonAPI.post(user, %{status: "cofe is all I need"})
+      {:ok, _} = CommonAPI.post(user, %{status: "— ok BOOMER\n"})
+
+      activities = ActivityPub.fetch_activities([], params)
+
+      assert Enum.empty?(activities)
+    end
+
+    test "it returns all statuses if user does not have any filters" do
+      another_user = insert(:user)
+      {:ok, _} = CommonAPI.post(another_user, %{status: "got cofe?"})
+      {:ok, _} = CommonAPI.post(another_user, %{status: "test!"})
+
+      activities =
+        ActivityPub.fetch_activities([], %{
+          type: ["Create", "Announce"],
+          user: another_user
+        })
+
+      assert Enum.count(activities) == 2
+    end
+  end
+
   describe "public fetch activities" do
     test "doesn't retrieve unlisted activities" do
       user = insert(:user)
index 6a53fd3f09050262f9af1f67b83a516680faa1ab..01179206c0e8001f48a698f34d99e65c022f4ad3 100644 (file)
@@ -659,22 +659,44 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
           "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
         )
 
-      attachment = %{
-        "type" => "Link",
-        "mediaType" => "video/mp4",
-        "url" => [
-          %{
-            "href" =>
-              "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4",
-            "mediaType" => "video/mp4"
-          }
-        ]
-      }
-
       assert object.data["url"] ==
                "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
 
-      assert object.data["attachment"] == [attachment]
+      assert object.data["attachment"] == [
+               %{
+                 "type" => "Link",
+                 "mediaType" => "video/mp4",
+                 "url" => [
+                   %{
+                     "href" =>
+                       "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4",
+                     "mediaType" => "video/mp4"
+                   }
+                 ]
+               }
+             ]
+
+      {:ok, object} =
+        Fetcher.fetch_object_from_id(
+          "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206"
+        )
+
+      assert object.data["attachment"] == [
+               %{
+                 "type" => "Link",
+                 "mediaType" => "video/mp4",
+                 "url" => [
+                   %{
+                     "href" =>
+                       "https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4",
+                     "mediaType" => "video/mp4"
+                   }
+                 ]
+               }
+             ]
+
+      assert object.data["url"] ==
+               "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206"
     end
 
     test "it accepts Flag activities" do