Merge branch 'release/2.3.0' into 'stable'
[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 "pleroma:emoji_reaction" ->
116 response
117 |> put_status(parent_activity_fn.(), reading_user, status_render_opts)
118 |> put_emoji(activity)
119
120 "pleroma:chat_mention" ->
121 put_chat_message(response, activity, reading_user, status_render_opts)
122
123 "pleroma:report" ->
124 put_report(response, activity)
125
126 type when type in ["follow", "follow_request"] ->
127 response
128 end
129 end
130
131 defp put_report(response, activity) do
132 report_render = ReportView.render("show.json", Report.extract_report_info(activity))
133
134 Map.put(response, :report, report_render)
135 end
136
137 defp put_emoji(response, activity) do
138 Map.put(response, :emoji, activity.data["content"])
139 end
140
141 defp put_chat_message(response, activity, reading_user, opts) do
142 object = Object.normalize(activity, fetch: false)
143 author = User.get_cached_by_ap_id(object.data["actor"])
144 chat = Pleroma.Chat.get(reading_user.id, author.ap_id)
145 cm_ref = MessageReference.for_chat_and_object(chat, object)
146 render_opts = Map.merge(opts, %{for: reading_user, chat_message_reference: cm_ref})
147 chat_message_render = MessageReferenceView.render("show.json", render_opts)
148
149 Map.put(response, :chat_message, chat_message_render)
150 end
151
152 defp put_status(response, activity, reading_user, opts) do
153 status_render_opts = Map.merge(opts, %{activity: activity, for: reading_user})
154 status_render = StatusView.render("show.json", status_render_opts)
155
156 Map.put(response, :status, status_render)
157 end
158
159 defp put_target(response, activity, reading_user, opts) do
160 target_user = User.get_cached_by_ap_id(activity.data["target"])
161 target_render_opts = Map.merge(opts, %{user: target_user, for: reading_user})
162 target_render = AccountView.render("show.json", target_render_opts)
163
164 Map.put(response, :target, target_render)
165 end
166 end