Use mediaproxy for emoji notifications if enabled
[akkoma] / lib / pleroma / web / mastodon_api / views / notification_view.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.MastodonAPI.NotificationView do
6 use Pleroma.Web, :view
7
8 alias Pleroma.Activity
9 alias Pleroma.Chat.MessageReference
10 alias Pleroma.Notification
11 alias Pleroma.Object
12 alias Pleroma.User
13 alias Pleroma.UserRelationship
14 alias Pleroma.Web.AdminAPI.Report
15 alias Pleroma.Web.AdminAPI.ReportView
16 alias Pleroma.Web.CommonAPI
17 alias Pleroma.Web.MediaProxy
18 alias Pleroma.Web.MastodonAPI.AccountView
19 alias Pleroma.Web.MastodonAPI.NotificationView
20 alias Pleroma.Web.MastodonAPI.StatusView
21 alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView
22
23 @parent_types ~w{Like Announce EmojiReact}
24
25 def render("index.json", %{notifications: notifications, for: reading_user} = opts) do
26 activities = Enum.map(notifications, & &1.activity)
27
28 parent_activities =
29 activities
30 |> Enum.filter(fn
31 %{data: %{"type" => type}} ->
32 type in @parent_types
33 end)
34 |> Enum.map(& &1.data["object"])
35 |> Activity.create_by_object_ap_id()
36 |> Activity.with_preloaded_object(:left)
37 |> Pleroma.Repo.all()
38
39 relationships_opt =
40 cond do
41 Map.has_key?(opts, :relationships) ->
42 opts[:relationships]
43
44 is_nil(reading_user) ->
45 UserRelationship.view_relationships_option(nil, [])
46
47 true ->
48 move_activities_targets =
49 activities
50 |> Enum.filter(&(&1.data["type"] == "Move"))
51 |> Enum.map(&User.get_cached_by_ap_id(&1.data["target"]))
52 |> Enum.filter(& &1)
53
54 actors =
55 activities
56 |> Enum.map(fn a -> User.get_cached_by_ap_id(a.data["actor"]) end)
57 |> Enum.filter(& &1)
58 |> Kernel.++(move_activities_targets)
59
60 UserRelationship.view_relationships_option(reading_user, actors, subset: :source_mutes)
61 end
62
63 opts =
64 opts
65 |> Map.put(:parent_activities, parent_activities)
66 |> Map.put(:relationships, relationships_opt)
67
68 safe_render_many(notifications, NotificationView, "show.json", opts)
69 end
70
71 def render(
72 "show.json",
73 %{
74 notification: %Notification{activity: activity} = notification,
75 for: reading_user
76 } = opts
77 ) do
78 actor = User.get_cached_by_ap_id(activity.data["actor"])
79
80 parent_activity_fn = fn ->
81 if opts[:parent_activities] do
82 Activity.Queries.find_by_object_ap_id(opts[:parent_activities], activity.data["object"])
83 else
84 Activity.get_create_by_object_ap_id(activity.data["object"])
85 end
86 end
87
88 # Note: :relationships contain user mutes (needed for :muted flag in :status)
89 status_render_opts = %{relationships: opts[:relationships]}
90 account = AccountView.render("show.json", %{user: actor, for: reading_user})
91
92 response = %{
93 id: to_string(notification.id),
94 type: notification.type,
95 created_at: CommonAPI.Utils.to_masto_date(notification.inserted_at),
96 account: account,
97 pleroma: %{
98 is_muted: User.mutes?(reading_user, actor),
99 is_seen: notification.seen
100 }
101 }
102
103 case notification.type do
104 "mention" ->
105 put_status(response, activity, reading_user, status_render_opts)
106
107 "favourite" ->
108 put_status(response, parent_activity_fn.(), reading_user, status_render_opts)
109
110 "reblog" ->
111 put_status(response, parent_activity_fn.(), reading_user, status_render_opts)
112
113 "move" ->
114 put_target(response, activity, reading_user, %{})
115
116 "poll" ->
117 put_status(response, activity, reading_user, status_render_opts)
118
119 "pleroma:emoji_reaction" ->
120 response
121 |> put_status(parent_activity_fn.(), reading_user, status_render_opts)
122 |> put_emoji(activity)
123
124 "pleroma:chat_mention" ->
125 put_chat_message(response, activity, reading_user, status_render_opts)
126
127 "pleroma:report" ->
128 put_report(response, activity)
129
130 type when type in ["follow", "follow_request"] ->
131 response
132 end
133 end
134
135 defp put_report(response, activity) do
136 report_render = ReportView.render("show.json", Report.extract_report_info(activity))
137
138 Map.put(response, :report, report_render)
139 end
140
141 defp put_emoji(response, activity) do
142 response
143 |> Map.put(:emoji, activity.data["content"])
144 |> Map.put(:emoji_url, MediaProxy.url(Pleroma.Emoji.emoji_url(activity.data)))
145 end
146
147 defp put_chat_message(response, activity, reading_user, opts) do
148 object = Object.normalize(activity, fetch: false)
149 author = User.get_cached_by_ap_id(object.data["actor"])
150 chat = Pleroma.Chat.get(reading_user.id, author.ap_id)
151 cm_ref = MessageReference.for_chat_and_object(chat, object)
152 render_opts = Map.merge(opts, %{for: reading_user, chat_message_reference: cm_ref})
153 chat_message_render = MessageReferenceView.render("show.json", render_opts)
154
155 Map.put(response, :chat_message, chat_message_render)
156 end
157
158 defp put_status(response, activity, reading_user, opts) do
159 status_render_opts = Map.merge(opts, %{activity: activity, for: reading_user})
160 status_render = StatusView.render("show.json", status_render_opts)
161
162 Map.put(response, :status, status_render)
163 end
164
165 defp put_target(response, activity, reading_user, opts) do
166 target_user = User.get_cached_by_ap_id(activity.data["target"])
167 target_render_opts = Map.merge(opts, %{user: target_user, for: reading_user})
168 target_render = AccountView.render("show.json", target_render_opts)
169
170 Map.put(response, :target, target_render)
171 end
172 end