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