Merge remote-tracking branch 'upstream/develop' into feature/move-activity
[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"]} when action in [:conversation, :conversation_statuses]
26 )
27
28 plug(
29 OAuthScopesPlug,
30 %{scopes: ["write:conversations"]} when action == :update_conversation
31 )
32
33 plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action == :read_notification)
34
35 plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
36
37 def emoji_reactions_by(%{assigns: %{user: user}} = conn, %{"id" => activity_id}) do
38 with %Activity{} = activity <- Activity.get_by_id_with_object(activity_id),
39 %Object{data: %{"reactions" => emoji_reactions}} <- Object.normalize(activity) do
40 reactions =
41 emoji_reactions
42 |> Enum.map(fn {emoji, users} ->
43 users = Enum.map(users, &User.get_cached_by_ap_id/1)
44 {emoji, AccountView.render("index.json", %{users: users, for: user, as: :user})}
45 end)
46 |> Enum.into(%{})
47
48 conn
49 |> json(reactions)
50 else
51 _e ->
52 conn
53 |> json(%{})
54 end
55 end
56
57 def react_with_emoji(%{assigns: %{user: user}} = conn, %{"id" => activity_id, "emoji" => emoji}) do
58 with {:ok, _activity, _object} <- CommonAPI.react_with_emoji(activity_id, user, emoji),
59 activity <- Activity.get_by_id(activity_id) do
60 conn
61 |> put_view(StatusView)
62 |> render("show.json", %{activity: activity, for: user, as: :activity})
63 end
64 end
65
66 def unreact_with_emoji(%{assigns: %{user: user}} = conn, %{
67 "id" => activity_id,
68 "emoji" => emoji
69 }) do
70 with {:ok, _activity, _object} <- CommonAPI.unreact_with_emoji(activity_id, user, emoji),
71 activity <- Activity.get_by_id(activity_id) do
72 conn
73 |> put_view(StatusView)
74 |> render("show.json", %{activity: activity, for: user, as: :activity})
75 end
76 end
77
78 def conversation(%{assigns: %{user: user}} = conn, %{"id" => participation_id}) do
79 with %Participation{} = participation <- Participation.get(participation_id),
80 true <- user.id == participation.user_id do
81 conn
82 |> put_view(ConversationView)
83 |> render("participation.json", %{participation: participation, for: user})
84 end
85 end
86
87 def conversation_statuses(
88 %{assigns: %{user: user}} = conn,
89 %{"id" => participation_id} = params
90 ) do
91 participation = Participation.get(participation_id, preload: [:conversation])
92
93 if user.id == participation.user_id do
94 params =
95 params
96 |> Map.put("blocking_user", user)
97 |> Map.put("muting_user", user)
98 |> Map.put("user", user)
99
100 activities =
101 participation.conversation.ap_id
102 |> ActivityPub.fetch_activities_for_context(params)
103 |> Enum.reverse()
104
105 conn
106 |> add_link_headers(activities)
107 |> put_view(StatusView)
108 |> render("index.json", %{activities: activities, for: user, as: :activity})
109 end
110 end
111
112 def update_conversation(
113 %{assigns: %{user: user}} = conn,
114 %{"id" => participation_id, "recipients" => recipients}
115 ) do
116 participation =
117 participation_id
118 |> Participation.get()
119
120 with true <- user.id == participation.user_id,
121 {:ok, participation} <- Participation.set_recipients(participation, recipients) do
122 conn
123 |> put_view(ConversationView)
124 |> render("participation.json", %{participation: participation, for: user})
125 end
126 end
127
128 def read_conversations(%{assigns: %{user: user}} = conn, _params) do
129 with {:ok, _, participations} <- Participation.mark_all_as_read(user) do
130 conn
131 |> add_link_headers(participations)
132 |> put_view(ConversationView)
133 |> render("participations.json", participations: participations, for: user)
134 end
135 end
136
137 def read_notification(%{assigns: %{user: user}} = conn, %{"id" => notification_id}) do
138 with {:ok, notification} <- Notification.read_one(user, notification_id) do
139 conn
140 |> put_view(NotificationView)
141 |> render("show.json", %{notification: notification, for: user})
142 else
143 {:error, message} ->
144 conn
145 |> put_status(:bad_request)
146 |> json(%{"error" => message})
147 end
148 end
149
150 def read_notification(%{assigns: %{user: user}} = conn, %{"max_id" => max_id}) do
151 with notifications <- Notification.set_read_up_to(user, max_id) do
152 notifications = Enum.take(notifications, 80)
153
154 conn
155 |> put_view(NotificationView)
156 |> render("index.json", %{notifications: notifications, for: user})
157 end
158 end
159 end