logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma

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