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