total rebase
[anni] / lib / pleroma / web / activity_pub / object_validators / common_fixes.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
6   alias Pleroma.EctoType.ActivityPub.ObjectValidators
7   alias Pleroma.Maps
8   alias Pleroma.Object
9   alias Pleroma.Object.Containment
10   alias Pleroma.User
11   alias Pleroma.Web.ActivityPub.Transmogrifier
12   alias Pleroma.Web.ActivityPub.Utils
13
14   require Pleroma.Constants
15
16   def cast_and_filter_recipients(message, field, follower_collection, field_fallback \\ []) do
17     {:ok, data} = ObjectValidators.Recipients.cast(message[field] || field_fallback)
18
19     data =
20       Enum.reject(data, fn x ->
21         String.ends_with?(x, "/followers") and x != follower_collection
22       end)
23
24     Map.put(message, field, data)
25   end
26
27   def fix_object_defaults(data) do
28     data = Maps.filter_empty_values(data)
29
30     context =
31       Utils.maybe_create_context(
32         data["context"] || data["conversation"] || data["inReplyTo"] || data["id"]
33       )
34
35     %User{follower_address: follower_collection} = User.get_cached_by_ap_id(data["attributedTo"])
36
37     data
38     |> Map.put("context", context)
39     |> cast_and_filter_recipients("to", follower_collection)
40     |> cast_and_filter_recipients("cc", follower_collection)
41     |> cast_and_filter_recipients("bto", follower_collection)
42     |> cast_and_filter_recipients("bcc", follower_collection)
43     |> Transmogrifier.fix_implicit_addressing(follower_collection)
44   end
45
46   def fix_activity_addressing(activity) do
47     %User{follower_address: follower_collection} = User.get_cached_by_ap_id(activity["actor"])
48
49     activity
50     |> cast_and_filter_recipients("to", follower_collection)
51     |> cast_and_filter_recipients("cc", follower_collection)
52     |> cast_and_filter_recipients("bto", follower_collection)
53     |> cast_and_filter_recipients("bcc", follower_collection)
54     |> Transmogrifier.fix_implicit_addressing(follower_collection)
55   end
56
57   def fix_actor(data) do
58     actor =
59       data
60       |> Map.put_new("actor", data["attributedTo"])
61       |> Containment.get_actor()
62
63     data
64     |> Map.put("actor", actor)
65     |> Map.put("attributedTo", actor)
66   end
67
68   def fix_activity_context(data, %Object{data: %{"context" => object_context}}) do
69     data
70     |> Map.put("context", object_context)
71   end
72
73   def fix_object_action_recipients(%{"actor" => actor} = data, %Object{data: %{"actor" => actor}}) do
74     to = ((data["to"] || []) -- [actor]) |> Enum.uniq()
75
76     Map.put(data, "to", to)
77   end
78
79   def fix_object_action_recipients(data, %Object{data: %{"actor" => actor}}) do
80     to = ((data["to"] || []) ++ [actor]) |> Enum.uniq()
81
82     Map.put(data, "to", to)
83   end
84
85   def fix_quote_url(%{"quoteUrl" => _quote_url} = data), do: data
86
87   # Fedibird
88   # https://github.com/fedibird/mastodon/commit/dbd7ae6cf58a92ec67c512296b4daaea0d01e6ac
89   def fix_quote_url(%{"quoteUri" => quote_url} = data) do
90     Map.put(data, "quoteUrl", quote_url)
91   end
92
93   # Old Fedibird (bug)
94   # https://github.com/fedibird/mastodon/issues/9
95   def fix_quote_url(%{"quoteURL" => quote_url} = data) do
96     Map.put(data, "quoteUrl", quote_url)
97   end
98
99   # Misskey fallback
100   def fix_quote_url(%{"_misskey_quote" => quote_url} = data) do
101     Map.put(data, "quoteUrl", quote_url)
102   end
103
104   def fix_quote_url(%{"tag" => [_ | _] = tags} = data) do
105     tag = Enum.find(tags, &object_link_tag?/1)
106
107     if not is_nil(tag) do
108       data
109       |> Map.put("quoteUrl", tag["href"])
110     else
111       data
112     end
113   end
114
115   def fix_quote_url(data), do: data
116
117   # https://codeberg.org/fediverse/fep/src/branch/main/fep/e232/fep-e232.md
118   def object_link_tag?(%{
119         "type" => "Link",
120         "mediaType" => media_type,
121         "href" => href
122       })
123       when media_type in Pleroma.Constants.activity_json_mime_types() and is_binary(href) do
124     true
125   end
126
127   def object_link_tag?(_), do: false
128 end