Merge branch '1851-favorites-pagination' into 'develop'
[akkoma] / lib / pleroma / web / mastodon_api / views / notification_view.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 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.CommonAPI
15 alias Pleroma.Web.MastodonAPI.AccountView
16 alias Pleroma.Web.MastodonAPI.NotificationView
17 alias Pleroma.Web.MastodonAPI.StatusView
18 alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView
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
50 actors =
51 activities
52 |> Enum.map(fn a -> User.get_cached_by_ap_id(a.data["actor"]) end)
53 |> Enum.filter(& &1)
54 |> Kernel.++(move_activities_targets)
55
56 UserRelationship.view_relationships_option(reading_user, actors, subset: :source_mutes)
57 end
58
59 opts =
60 opts
61 |> Map.put(:parent_activities, parent_activities)
62 |> Map.put(:relationships, relationships_opt)
63
64 safe_render_many(notifications, NotificationView, "show.json", opts)
65 end
66
67 def render(
68 "show.json",
69 %{
70 notification: %Notification{activity: activity} = notification,
71 for: reading_user
72 } = opts
73 ) do
74 actor = User.get_cached_by_ap_id(activity.data["actor"])
75
76 parent_activity_fn = fn ->
77 if opts[:parent_activities] do
78 Activity.Queries.find_by_object_ap_id(opts[:parent_activities], activity.data["object"])
79 else
80 Activity.get_create_by_object_ap_id(activity.data["object"])
81 end
82 end
83
84 # Note: :relationships contain user mutes (needed for :muted flag in :status)
85 status_render_opts = %{relationships: opts[:relationships]}
86
87 with %{id: _} = account <-
88 AccountView.render(
89 "show.json",
90 %{user: actor, for: reading_user}
91 ) do
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_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 type when type in ["follow", "follow_request"] ->
124 response
125
126 _ ->
127 nil
128 end
129 else
130 _ -> nil
131 end
132 end
133
134 defp put_emoji(response, activity) do
135 Map.put(response, :emoji, activity.data["content"])
136 end
137
138 defp put_chat_message(response, activity, reading_user, opts) do
139 object = Object.normalize(activity)
140 author = User.get_cached_by_ap_id(object.data["actor"])
141 chat = Pleroma.Chat.get(reading_user.id, author.ap_id)
142 cm_ref = MessageReference.for_chat_and_object(chat, object)
143 render_opts = Map.merge(opts, %{for: reading_user, chat_message_reference: cm_ref})
144 chat_message_render = MessageReferenceView.render("show.json", render_opts)
145
146 Map.put(response, :chat_message, chat_message_render)
147 end
148
149 defp put_status(response, activity, reading_user, opts) do
150 status_render_opts = Map.merge(opts, %{activity: activity, for: reading_user})
151 status_render = StatusView.render("show.json", status_render_opts)
152
153 Map.put(response, :status, status_render)
154 end
155
156 defp put_target(response, activity, reading_user, opts) do
157 target_user = User.get_cached_by_ap_id(activity.data["target"])
158 target_render_opts = Map.merge(opts, %{user: target_user, for: reading_user})
159 target_render = AccountView.render("show.json", target_render_opts)
160
161 Map.put(response, :target, target_render)
162 end
163 end