Transmogrifier: Extract user update handling tests.
[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 |> 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
88 account =
89 AccountView.render(
90 "show.json",
91 %{user: actor, for: reading_user}
92 )
93
94 response = %{
95 id: to_string(notification.id),
96 type: notification.type,
97 created_at: CommonAPI.Utils.to_masto_date(notification.inserted_at),
98 account: account,
99 pleroma: %{
100 is_seen: notification.seen
101 }
102 }
103
104 case notification.type do
105 "mention" ->
106 put_status(response, activity, reading_user, status_render_opts)
107
108 "favourite" ->
109 put_status(response, parent_activity_fn.(), reading_user, status_render_opts)
110
111 "reblog" ->
112 put_status(response, parent_activity_fn.(), reading_user, status_render_opts)
113
114 "move" ->
115 put_target(response, activity, reading_user, %{})
116
117 "pleroma:emoji_reaction" ->
118 response
119 |> put_status(parent_activity_fn.(), reading_user, status_render_opts)
120 |> put_emoji(activity)
121
122 "pleroma:chat_mention" ->
123 put_chat_message(response, activity, reading_user, status_render_opts)
124
125 type when type in ["follow", "follow_request"] ->
126 response
127 end
128 end
129
130 defp put_emoji(response, activity) do
131 Map.put(response, :emoji, activity.data["content"])
132 end
133
134 defp put_chat_message(response, activity, reading_user, opts) do
135 object = Object.normalize(activity)
136 author = User.get_cached_by_ap_id(object.data["actor"])
137 chat = Pleroma.Chat.get(reading_user.id, author.ap_id)
138 cm_ref = MessageReference.for_chat_and_object(chat, object)
139 render_opts = Map.merge(opts, %{for: reading_user, chat_message_reference: cm_ref})
140 chat_message_render = MessageReferenceView.render("show.json", render_opts)
141
142 Map.put(response, :chat_message, chat_message_render)
143 end
144
145 defp put_status(response, activity, reading_user, opts) do
146 status_render_opts = Map.merge(opts, %{activity: activity, for: reading_user})
147 status_render = StatusView.render("show.json", status_render_opts)
148
149 Map.put(response, :status, status_render)
150 end
151
152 defp put_target(response, activity, reading_user, opts) do
153 target_user = User.get_cached_by_ap_id(activity.data["target"])
154 target_render_opts = Map.merge(opts, %{user: target_user, for: reading_user})
155 target_render = AccountView.render("show.json", target_render_opts)
156
157 Map.put(response, :target, target_render)
158 end
159 end