e6e2385b21e2faa65e8a3a9573d2afc4986f7b47
[akkoma] / lib / pleroma / web / pleroma_api / controllers / pleroma_api_controller.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
6 use Pleroma.Web, :controller
7
8 import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
9
10 alias Pleroma.Activity
11 alias Pleroma.Conversation.Participation
12 alias Pleroma.Notification
13 alias Pleroma.Object
14 alias Pleroma.Plugs.OAuthScopesPlug
15 alias Pleroma.User
16 alias Pleroma.Web.ActivityPub.ActivityPub
17 alias Pleroma.Web.CommonAPI
18 alias Pleroma.Web.MastodonAPI.AccountView
19 alias Pleroma.Web.MastodonAPI.ConversationView
20 alias Pleroma.Web.MastodonAPI.NotificationView
21 alias Pleroma.Web.MastodonAPI.StatusView
22
23 plug(
24 OAuthScopesPlug,
25 %{scopes: ["read:statuses"]}
26 when action in [:conversation, :conversation_statuses]
27 )
28
29 plug(
30 OAuthScopesPlug,
31 %{scopes: ["write:statuses"]}
32 when action in [:react_with_emoji, :unreact_with_emoji]
33 )
34
35 plug(
36 OAuthScopesPlug,
37 %{scopes: ["write:conversations"]} when action == :update_conversation
38 )
39
40 plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action == :read_notification)
41
42 plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
43
44 def emoji_reactions_by(%{assigns: %{user: user}} = conn, %{"id" => activity_id}) do
45 with %Activity{} = activity <- Activity.get_by_id_with_object(activity_id),
46 %Object{data: %{"reactions" => emoji_reactions}} when is_list(emoji_reactions) <-
47 Object.normalize(activity) do
48 reactions =
49 emoji_reactions
50 |> Enum.map(fn [emoji, user_ap_ids] ->
51 users = Enum.map(user_ap_ids, &User.get_cached_by_ap_id/1)
52
53 %{
54 emoji: emoji,
55 count: length(users),
56 accounts: AccountView.render("index.json", %{users: users, for: user, as: :user}),
57 reacted: !!(user && user.ap_id in user_ap_ids)
58 }
59 end)
60
61 conn
62 |> json(reactions)
63 else
64 _e ->
65 conn
66 |> json([])
67 end
68 end
69
70 def react_with_emoji(%{assigns: %{user: user}} = conn, %{"id" => activity_id, "emoji" => emoji}) do
71 with {:ok, _activity, _object} <- CommonAPI.react_with_emoji(activity_id, user, emoji),
72 activity <- Activity.get_by_id(activity_id) do
73 conn
74 |> put_view(StatusView)
75 |> render("show.json", %{activity: activity, for: user, as: :activity})
76 end
77 end
78
79 def unreact_with_emoji(%{assigns: %{user: user}} = conn, %{
80 "id" => activity_id,
81 "emoji" => emoji
82 }) do
83 with {:ok, _activity, _object} <- CommonAPI.unreact_with_emoji(activity_id, user, emoji),
84 activity <- Activity.get_by_id(activity_id) do
85 conn
86 |> put_view(StatusView)
87 |> render("show.json", %{activity: activity, for: user, as: :activity})
88 end
89 end
90
91 def conversation(%{assigns: %{user: user}} = conn, %{"id" => participation_id}) do
92 with %Participation{} = participation <- Participation.get(participation_id),
93 true <- user.id == participation.user_id do
94 conn
95 |> put_view(ConversationView)
96 |> render("participation.json", %{participation: participation, for: user})
97 end
98 end
99
100 def conversation_statuses(
101 %{assigns: %{user: user}} = conn,
102 %{"id" => participation_id} = params
103 ) do
104 participation = Participation.get(participation_id, preload: [:conversation])
105
106 if user.id == participation.user_id do
107 params =
108 params
109 |> Map.put("blocking_user", user)
110 |> Map.put("muting_user", user)
111 |> Map.put("user", user)
112
113 activities =
114 participation.conversation.ap_id
115 |> ActivityPub.fetch_activities_for_context(params)
116 |> Enum.reverse()
117
118 conn
119 |> add_link_headers(activities)
120 |> put_view(StatusView)
121 |> render("index.json", %{activities: activities, for: user, as: :activity})
122 end
123 end
124
125 def update_conversation(
126 %{assigns: %{user: user}} = conn,
127 %{"id" => participation_id, "recipients" => recipients}
128 ) do
129 participation =
130 participation_id
131 |> Participation.get()
132
133 with true <- user.id == participation.user_id,
134 {:ok, participation} <- Participation.set_recipients(participation, recipients) do
135 conn
136 |> put_view(ConversationView)
137 |> render("participation.json", %{participation: participation, for: user})
138 end
139 end
140
141 def read_conversations(%{assigns: %{user: user}} = conn, _params) do
142 with {:ok, _, participations} <- Participation.mark_all_as_read(user) do
143 conn
144 |> add_link_headers(participations)
145 |> put_view(ConversationView)
146 |> render("participations.json", participations: participations, for: user)
147 end
148 end
149
150 def read_notification(%{assigns: %{user: user}} = conn, %{"id" => notification_id}) do
151 with {:ok, notification} <- Notification.read_one(user, notification_id) do
152 conn
153 |> put_view(NotificationView)
154 |> render("show.json", %{notification: notification, for: user})
155 else
156 {:error, message} ->
157 conn
158 |> put_status(:bad_request)
159 |> json(%{"error" => message})
160 end
161 end
162
163 def read_notification(%{assigns: %{user: user}} = conn, %{"max_id" => max_id}) do
164 with notifications <- Notification.set_read_up_to(user, max_id) do
165 notifications = Enum.take(notifications, 80)
166
167 conn
168 |> put_view(NotificationView)
169 |> render("index.json", %{notifications: notifications, for: user})
170 end
171 end
172 end