Merge branch 'fix/credo-issues' into 'develop'
[akkoma] / lib / pleroma / web / twitter_api / representers / activity_representer.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 # FIXME: Remove this module?
6 # THIS MODULE IS DEPRECATED! DON'T USE IT!
7 # USE THE Pleroma.Web.TwitterAPI.Views.ActivityView MODULE!
8 defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do
9 use Pleroma.Web.TwitterAPI.Representers.BaseRepresenter
10 alias Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter
11 alias Pleroma.Activity
12 alias Pleroma.Formatter
13 alias Pleroma.HTML
14 alias Pleroma.User
15 alias Pleroma.Web.TwitterAPI.ActivityView
16 alias Pleroma.Web.TwitterAPI.TwitterAPI
17 alias Pleroma.Web.TwitterAPI.UserView
18 alias Pleroma.Web.CommonAPI.Utils
19 alias Pleroma.Web.MastodonAPI.StatusView
20
21 defp user_by_ap_id(user_list, ap_id) do
22 Enum.find(user_list, fn %{ap_id: user_id} -> ap_id == user_id end)
23 end
24
25 def to_map(
26 %Activity{data: %{"type" => "Announce", "actor" => actor, "published" => created_at}} =
27 activity,
28 %{users: users, announced_activity: announced_activity} = opts
29 ) do
30 user = user_by_ap_id(users, actor)
31 created_at = created_at |> Utils.date_to_asctime()
32
33 text = "#{user.nickname} retweeted a status."
34
35 announced_user = user_by_ap_id(users, announced_activity.data["actor"])
36 retweeted_status = to_map(announced_activity, Map.merge(%{user: announced_user}, opts))
37
38 %{
39 "id" => activity.id,
40 "user" => UserView.render("show.json", %{user: user, for: opts[:for]}),
41 "statusnet_html" => text,
42 "text" => text,
43 "is_local" => activity.local,
44 "is_post_verb" => false,
45 "uri" => "tag:#{activity.data["id"]}:objectType=note",
46 "created_at" => created_at,
47 "retweeted_status" => retweeted_status,
48 "statusnet_conversation_id" => conversation_id(announced_activity),
49 "external_url" => activity.data["id"],
50 "activity_type" => "repeat"
51 }
52 end
53
54 def to_map(
55 %Activity{data: %{"type" => "Like", "published" => created_at}} = activity,
56 %{user: user, liked_activity: liked_activity} = opts
57 ) do
58 created_at = created_at |> Utils.date_to_asctime()
59
60 text = "#{user.nickname} favorited a status."
61
62 %{
63 "id" => activity.id,
64 "user" => UserView.render("show.json", %{user: user, for: opts[:for]}),
65 "statusnet_html" => text,
66 "text" => text,
67 "is_local" => activity.local,
68 "is_post_verb" => false,
69 "uri" => "tag:#{activity.data["id"]}:objectType=Favourite",
70 "created_at" => created_at,
71 "in_reply_to_status_id" => liked_activity.id,
72 "external_url" => activity.data["id"],
73 "activity_type" => "like"
74 }
75 end
76
77 def to_map(
78 %Activity{data: %{"type" => "Follow", "object" => followed_id}} = activity,
79 %{user: user} = opts
80 ) do
81 created_at = activity.data["published"] || DateTime.to_iso8601(activity.inserted_at)
82 created_at = created_at |> Utils.date_to_asctime()
83
84 followed = User.get_cached_by_ap_id(followed_id)
85 text = "#{user.nickname} started following #{followed.nickname}"
86
87 %{
88 "id" => activity.id,
89 "user" => UserView.render("show.json", %{user: user, for: opts[:for]}),
90 "attentions" => [],
91 "statusnet_html" => text,
92 "text" => text,
93 "is_local" => activity.local,
94 "is_post_verb" => false,
95 "created_at" => created_at,
96 "in_reply_to_status_id" => nil,
97 "external_url" => activity.data["id"],
98 "activity_type" => "follow"
99 }
100 end
101
102 # TODO:
103 # Make this more proper. Just a placeholder to not break the frontend.
104 def to_map(
105 %Activity{
106 data: %{"type" => "Undo", "published" => created_at, "object" => undid_activity}
107 } = activity,
108 %{user: user} = opts
109 ) do
110 created_at = created_at |> Utils.date_to_asctime()
111
112 text = "#{user.nickname} undid the action at #{undid_activity["id"]}"
113
114 %{
115 "id" => activity.id,
116 "user" => UserView.render("show.json", %{user: user, for: opts[:for]}),
117 "attentions" => [],
118 "statusnet_html" => text,
119 "text" => text,
120 "is_local" => activity.local,
121 "is_post_verb" => false,
122 "created_at" => created_at,
123 "in_reply_to_status_id" => nil,
124 "external_url" => activity.data["id"],
125 "activity_type" => "undo"
126 }
127 end
128
129 def to_map(
130 %Activity{data: %{"type" => "Delete", "published" => created_at, "object" => _}} =
131 activity,
132 %{user: user} = opts
133 ) do
134 created_at = created_at |> Utils.date_to_asctime()
135
136 %{
137 "id" => activity.id,
138 "uri" => activity.data["object"],
139 "user" => UserView.render("show.json", %{user: user, for: opts[:for]}),
140 "attentions" => [],
141 "statusnet_html" => "deleted notice {{tag",
142 "text" => "deleted notice {{tag",
143 "is_local" => activity.local,
144 "is_post_verb" => false,
145 "created_at" => created_at,
146 "in_reply_to_status_id" => nil,
147 "external_url" => activity.data["id"],
148 "activity_type" => "delete"
149 }
150 end
151
152 def to_map(
153 %Activity{data: %{"object" => %{"content" => _content} = object}} = activity,
154 %{user: user} = opts
155 ) do
156 created_at = object["published"] |> Utils.date_to_asctime()
157 like_count = object["like_count"] || 0
158 announcement_count = object["announcement_count"] || 0
159 favorited = opts[:for] && opts[:for].ap_id in (object["likes"] || [])
160 repeated = opts[:for] && opts[:for].ap_id in (object["announcements"] || [])
161 pinned = activity.id in user.info.pinned_activities
162
163 mentions = opts[:mentioned] || []
164
165 attentions =
166 []
167 |> Utils.maybe_notify_to_recipients(activity)
168 |> Utils.maybe_notify_mentioned_recipients(activity)
169 |> Enum.map(fn ap_id -> Enum.find(mentions, fn user -> ap_id == user.ap_id end) end)
170 |> Enum.filter(& &1)
171 |> Enum.map(fn user -> UserView.render("show.json", %{user: user, for: opts[:for]}) end)
172
173 conversation_id = conversation_id(activity)
174
175 tags = activity.data["object"]["tag"] || []
176 possibly_sensitive = activity.data["object"]["sensitive"] || Enum.member?(tags, "nsfw")
177
178 tags = if possibly_sensitive, do: Enum.uniq(["nsfw" | tags]), else: tags
179
180 {_summary, content} = ActivityView.render_content(object)
181
182 html =
183 HTML.filter_tags(content, User.html_filter_policy(opts[:for]))
184 |> Formatter.emojify(object["emoji"])
185
186 attachments = object["attachment"] || []
187
188 reply_parent = Activity.get_in_reply_to_activity(activity)
189
190 reply_user = reply_parent && User.get_cached_by_ap_id(reply_parent.actor)
191
192 summary = HTML.strip_tags(object["summary"])
193
194 card =
195 StatusView.render(
196 "card.json",
197 Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)
198 )
199
200 %{
201 "id" => activity.id,
202 "uri" => activity.data["object"]["id"],
203 "user" => UserView.render("show.json", %{user: user, for: opts[:for]}),
204 "statusnet_html" => html,
205 "text" => HTML.strip_tags(content),
206 "is_local" => activity.local,
207 "is_post_verb" => true,
208 "created_at" => created_at,
209 "in_reply_to_status_id" => object["inReplyToStatusId"],
210 "in_reply_to_screen_name" => reply_user && reply_user.nickname,
211 "in_reply_to_profileurl" => User.profile_url(reply_user),
212 "in_reply_to_ostatus_uri" => reply_user && reply_user.ap_id,
213 "in_reply_to_user_id" => reply_user && reply_user.id,
214 "statusnet_conversation_id" => conversation_id,
215 "attachments" => attachments |> ObjectRepresenter.enum_to_list(opts),
216 "attentions" => attentions,
217 "fave_num" => like_count,
218 "repeat_num" => announcement_count,
219 "favorited" => to_boolean(favorited),
220 "repeated" => to_boolean(repeated),
221 "pinned" => pinned,
222 "external_url" => object["external_url"] || object["id"],
223 "tags" => tags,
224 "activity_type" => "post",
225 "possibly_sensitive" => possibly_sensitive,
226 "visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object),
227 "summary" => summary,
228 "summary_html" => summary |> Formatter.emojify(object["emoji"]),
229 "card" => card
230 }
231 end
232
233 def conversation_id(activity) do
234 with context when not is_nil(context) <- activity.data["context"] do
235 TwitterAPI.context_to_conversation_id(context)
236 else
237 _e -> nil
238 end
239 end
240
241 defp to_boolean(false) do
242 false
243 end
244
245 defp to_boolean(nil) do
246 false
247 end
248
249 defp to_boolean(_) do
250 true
251 end
252 end