35c636d4e8c24679ae5be3a5c87ecbd703d49272
[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 Map.put(response, :emoji, activity.data["content"])
142 end
143
144 defp put_chat_message(response, activity, reading_user, opts) do
145 object = Object.normalize(activity, fetch: false)
146 author = User.get_cached_by_ap_id(object.data["actor"])
147 chat = Pleroma.Chat.get(reading_user.id, author.ap_id)
148 cm_ref = MessageReference.for_chat_and_object(chat, object)
149 render_opts = Map.merge(opts, %{for: reading_user, chat_message_reference: cm_ref})
150 chat_message_render = MessageReferenceView.render("show.json", render_opts)
151
152 Map.put(response, :chat_message, chat_message_render)
153 end
154
155 defp put_status(response, activity, reading_user, opts) do
156 status_render_opts = Map.merge(opts, %{activity: activity, for: reading_user})
157 status_render = StatusView.render("show.json", status_render_opts)
158
159 Map.put(response, :status, status_render)
160 end
161
162 defp put_target(response, activity, reading_user, opts) do
163 target_user = User.get_cached_by_ap_id(activity.data["target"])
164 target_render_opts = Map.merge(opts, %{user: target_user, for: reading_user})
165 target_render = AccountView.render("show.json", target_render_opts)
166
167 Map.put(response, :target, target_render)
168 end
169 end