pleroma_api_controller.ex (6768B)
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.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: ["read:statuses"], fallback: :proceed_unauthenticated} 32 when action == :emoji_reactions_by 33 ) 34 35 plug( 36 OAuthScopesPlug, 37 %{scopes: ["write:statuses"]} 38 when action in [:react_with_emoji, :unreact_with_emoji] 39 ) 40 41 plug( 42 OAuthScopesPlug, 43 %{scopes: ["write:conversations"]} 44 when action in [:update_conversation, :mark_conversations_as_read] 45 ) 46 47 plug( 48 OAuthScopesPlug, 49 %{scopes: ["write:notifications"]} when action == :mark_notifications_as_read 50 ) 51 52 def emoji_reactions_by(%{assigns: %{user: user}} = conn, %{"id" => activity_id} = params) do 53 with %Activity{} = activity <- Activity.get_by_id_with_object(activity_id), 54 %Object{data: %{"reactions" => emoji_reactions}} when is_list(emoji_reactions) <- 55 Object.normalize(activity) do 56 reactions = 57 emoji_reactions 58 |> Enum.map(fn [emoji, user_ap_ids] -> 59 if params["emoji"] && params["emoji"] != emoji do 60 nil 61 else 62 users = 63 Enum.map(user_ap_ids, &User.get_cached_by_ap_id/1) 64 |> Enum.filter(fn 65 %{deactivated: false} -> true 66 _ -> false 67 end) 68 69 %{ 70 name: emoji, 71 count: length(users), 72 accounts: 73 AccountView.render("index.json", %{ 74 users: users, 75 for: user, 76 as: :user 77 }), 78 me: !!(user && user.ap_id in user_ap_ids) 79 } 80 end 81 end) 82 |> Enum.filter(& &1) 83 84 conn 85 |> json(reactions) 86 else 87 _e -> 88 conn 89 |> json([]) 90 end 91 end 92 93 def react_with_emoji(%{assigns: %{user: user}} = conn, %{"id" => activity_id, "emoji" => emoji}) do 94 with {:ok, _activity} <- CommonAPI.react_with_emoji(activity_id, user, emoji), 95 activity <- Activity.get_by_id(activity_id) do 96 conn 97 |> put_view(StatusView) 98 |> render("show.json", %{activity: activity, for: user, as: :activity}) 99 end 100 end 101 102 def unreact_with_emoji(%{assigns: %{user: user}} = conn, %{ 103 "id" => activity_id, 104 "emoji" => emoji 105 }) do 106 with {:ok, _activity} <- 107 CommonAPI.unreact_with_emoji(activity_id, user, emoji), 108 activity <- Activity.get_by_id(activity_id) do 109 conn 110 |> put_view(StatusView) 111 |> render("show.json", %{activity: activity, for: user, as: :activity}) 112 end 113 end 114 115 def conversation(%{assigns: %{user: user}} = conn, %{"id" => participation_id}) do 116 with %Participation{} = participation <- Participation.get(participation_id), 117 true <- user.id == participation.user_id do 118 conn 119 |> put_view(ConversationView) 120 |> render("participation.json", %{participation: participation, for: user}) 121 else 122 _error -> 123 conn 124 |> put_status(404) 125 |> json(%{"error" => "Unknown conversation id"}) 126 end 127 end 128 129 def conversation_statuses( 130 %{assigns: %{user: %{id: user_id} = user}} = conn, 131 %{"id" => participation_id} = params 132 ) do 133 with %Participation{user_id: ^user_id} = participation <- 134 Participation.get(participation_id, preload: [:conversation]) do 135 params = 136 params 137 |> Map.put("blocking_user", user) 138 |> Map.put("muting_user", user) 139 |> Map.put("user", user) 140 141 activities = 142 participation.conversation.ap_id 143 |> ActivityPub.fetch_activities_for_context_query(params) 144 |> Pleroma.Pagination.fetch_paginated(Map.put(params, "total", false)) 145 |> Enum.reverse() 146 147 conn 148 |> add_link_headers(activities) 149 |> put_view(StatusView) 150 |> render("index.json", 151 activities: activities, 152 for: user, 153 as: :activity 154 ) 155 else 156 _error -> 157 conn 158 |> put_status(404) 159 |> json(%{"error" => "Unknown conversation id"}) 160 end 161 end 162 163 def update_conversation( 164 %{assigns: %{user: user}} = conn, 165 %{"id" => participation_id, "recipients" => recipients} 166 ) do 167 with %Participation{} = participation <- Participation.get(participation_id), 168 true <- user.id == participation.user_id, 169 {:ok, participation} <- Participation.set_recipients(participation, recipients) do 170 conn 171 |> put_view(ConversationView) 172 |> render("participation.json", %{participation: participation, for: user}) 173 else 174 {:error, message} -> 175 conn 176 |> put_status(:bad_request) 177 |> json(%{"error" => message}) 178 179 _error -> 180 conn 181 |> put_status(404) 182 |> json(%{"error" => "Unknown conversation id"}) 183 end 184 end 185 186 def mark_conversations_as_read(%{assigns: %{user: user}} = conn, _params) do 187 with {:ok, _, participations} <- Participation.mark_all_as_read(user) do 188 conn 189 |> add_link_headers(participations) 190 |> put_view(ConversationView) 191 |> render("participations.json", participations: participations, for: user) 192 end 193 end 194 195 def mark_notifications_as_read(%{assigns: %{user: user}} = conn, %{"id" => notification_id}) do 196 with {:ok, notification} <- Notification.read_one(user, notification_id) do 197 conn 198 |> put_view(NotificationView) 199 |> render("show.json", %{notification: notification, for: user}) 200 else 201 {:error, message} -> 202 conn 203 |> put_status(:bad_request) 204 |> json(%{"error" => message}) 205 end 206 end 207 208 def mark_notifications_as_read(%{assigns: %{user: user}} = conn, %{"max_id" => max_id}) do 209 with notifications <- Notification.set_read_up_to(user, max_id) do 210 notifications = Enum.take(notifications, 80) 211 212 conn 213 |> put_view(NotificationView) 214 |> render("index.json", 215 notifications: notifications, 216 for: user 217 ) 218 end 219 end 220 end