diff options
Diffstat (limited to 'lib')
6 files changed, 202 insertions, 171 deletions
| diff --git a/lib/pleroma/web/api_spec/operations/emoji_reaction_operation.ex b/lib/pleroma/web/api_spec/operations/emoji_reaction_operation.ex new file mode 100644 index 000000000..7c08fbaa7 --- /dev/null +++ b/lib/pleroma/web/api_spec/operations/emoji_reaction_operation.ex @@ -0,0 +1,102 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ApiSpec.EmojiReactionOperation do +  alias OpenApiSpex.Operation +  alias OpenApiSpex.Schema +  alias Pleroma.Web.ApiSpec.Schemas.Account +  alias Pleroma.Web.ApiSpec.Schemas.FlakeID +  alias Pleroma.Web.ApiSpec.Schemas.Status + +  def open_api_operation(action) do +    operation = String.to_existing_atom("#{action}_operation") +    apply(__MODULE__, operation, []) +  end + +  def index_operation do +    %Operation{ +      tags: ["Emoji Reactions"], +      summary: +        "Get an object of emoji to account mappings with accounts that reacted to the post", +      parameters: [ +        Operation.parameter(:id, :path, FlakeID, "Status ID", required: true), +        Operation.parameter(:emoji, :path, :string, "Filter by a single unicode emoji", +          required: false +        ) +      ], +      security: [%{"oAuth" => ["read:statuses"]}], +      operationId: "EmojiReactionController.index", +      responses: %{ +        200 => array_of_reactions_response() +      } +    } +  end + +  def create_operation do +    %Operation{ +      tags: ["Emoji Reactions"], +      summary: "React to a post with a unicode emoji", +      parameters: [ +        Operation.parameter(:id, :path, FlakeID, "Status ID", required: true), +        Operation.parameter(:emoji, :path, :string, "A single character unicode emoji", +          required: true +        ) +      ], +      security: [%{"oAuth" => ["write:statuses"]}], +      operationId: "EmojiReactionController.create", +      responses: %{ +        200 => Operation.response("Status", "application/json", Status) +      } +    } +  end + +  def delete_operation do +    %Operation{ +      tags: ["Emoji Reactions"], +      summary: "Remove a reaction to a post with a unicode emoji", +      parameters: [ +        Operation.parameter(:id, :path, FlakeID, "Status ID", required: true), +        Operation.parameter(:emoji, :path, :string, "A single character unicode emoji", +          required: true +        ) +      ], +      security: [%{"oAuth" => ["write:statuses"]}], +      operationId: "EmojiReactionController.delete", +      responses: %{ +        200 => Operation.response("Status", "application/json", Status) +      } +    } +  end + +  defp array_of_reactions_response do +    Operation.response("Array of Emoji Reactions", "application/json", %Schema{ +      type: :array, +      items: emoji_reaction(), +      example: [emoji_reaction().example] +    }) +  end + +  defp emoji_reaction do +    %Schema{ +      title: "EmojiReaction", +      type: :object, +      properties: %{ +        name: %Schema{type: :string, description: "Emoji"}, +        count: %Schema{type: :integer, description: "Count of reactions with this emoji"}, +        me: %Schema{type: :boolean, description: "Did I react with this emoji?"}, +        accounts: %Schema{ +          type: :array, +          items: Account, +          description: "Array of accounts reacted with this emoji" +        } +      }, +      example: %{ +        "name" => "😱", +        "count" => 1, +        "me" => false, +        "accounts" => [Account.schema().example] +      } +    } +  end +end diff --git a/lib/pleroma/web/api_spec/operations/pleroma_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_operation.ex index c6df5c854..7e46ba553 100644 --- a/lib/pleroma/web/api_spec/operations/pleroma_operation.ex +++ b/lib/pleroma/web/api_spec/operations/pleroma_operation.ex @@ -5,13 +5,11 @@  defmodule Pleroma.Web.ApiSpec.PleromaOperation do    alias OpenApiSpex.Operation    alias OpenApiSpex.Schema -  alias Pleroma.Web.ApiSpec.Schemas.Account +  alias Pleroma.Web.ApiSpec.NotificationOperation    alias Pleroma.Web.ApiSpec.Schemas.ApiError -  alias Pleroma.Web.ApiSpec.Schemas.FlakeID -  alias Pleroma.Web.ApiSpec.Schemas.Status    alias Pleroma.Web.ApiSpec.Schemas.Conversation +  alias Pleroma.Web.ApiSpec.Schemas.FlakeID    alias Pleroma.Web.ApiSpec.StatusOperation -  alias Pleroma.Web.ApiSpec.NotificationOperation    import Pleroma.Web.ApiSpec.Helpers @@ -20,92 +18,6 @@ defmodule Pleroma.Web.ApiSpec.PleromaOperation do      apply(__MODULE__, operation, [])    end -  def emoji_reactions_by_operation do -    %Operation{ -      tags: ["Emoji Reactions"], -      summary: -        "Get an object of emoji to account mappings with accounts that reacted to the post", -      parameters: [ -        Operation.parameter(:id, :path, FlakeID, "Status ID", required: true), -        Operation.parameter(:emoji, :path, :string, "Filter by a single unicode emoji", -          required: false -        ) -      ], -      security: [%{"oAuth" => ["read:statuses"]}], -      operationId: "PleromaController.emoji_reactions_by", -      responses: %{ -        200 => array_of_reactions_response() -      } -    } -  end - -  def react_with_emoji_operation do -    %Operation{ -      tags: ["Emoji Reactions"], -      summary: "React to a post with a unicode emoji", -      parameters: [ -        Operation.parameter(:id, :path, FlakeID, "Status ID", required: true), -        Operation.parameter(:emoji, :path, :string, "A single character unicode emoji", -          required: true -        ) -      ], -      security: [%{"oAuth" => ["write:statuses"]}], -      operationId: "PleromaController.react_with_emoji", -      responses: %{ -        200 => Operation.response("Status", "application/json", Status) -      } -    } -  end - -  def unreact_with_emoji_operation do -    %Operation{ -      tags: ["Emoji Reactions"], -      summary: "Remove a reaction to a post with a unicode emoji", -      parameters: [ -        Operation.parameter(:id, :path, FlakeID, "Status ID", required: true), -        Operation.parameter(:emoji, :path, :string, "A single character unicode emoji", -          required: true -        ) -      ], -      security: [%{"oAuth" => ["write:statuses"]}], -      operationId: "PleromaController.unreact_with_emoji", -      responses: %{ -        200 => Operation.response("Status", "application/json", Status) -      } -    } -  end - -  defp array_of_reactions_response do -    Operation.response("Array of Emoji Reactions", "application/json", %Schema{ -      type: :array, -      items: emoji_reaction(), -      example: [emoji_reaction().example] -    }) -  end - -  defp emoji_reaction do -    %Schema{ -      title: "EmojiReaction", -      type: :object, -      properties: %{ -        name: %Schema{type: :string, description: "Emoji"}, -        count: %Schema{type: :integer, description: "Count of reactions with this emoji"}, -        me: %Schema{type: :boolean, description: "Did I react with this emoji?"}, -        accounts: %Schema{ -          type: :array, -          items: Account, -          description: "Array of accounts reacted with this emoji" -        } -      }, -      example: %{ -        "name" => "😱", -        "count" => 1, -        "me" => false, -        "accounts" => [Account.schema().example] -      } -    } -  end -    def conversation_operation do      %Operation{        tags: ["Conversations"], diff --git a/lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex b/lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex new file mode 100644 index 000000000..a002912f3 --- /dev/null +++ b/lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex @@ -0,0 +1,61 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.PleromaAPI.EmojiReactionController do +  use Pleroma.Web, :controller + +  alias Pleroma.Activity +  alias Pleroma.Object +  alias Pleroma.Plugs.OAuthScopesPlug +  alias Pleroma.Web.CommonAPI +  alias Pleroma.Web.MastodonAPI.StatusView + +  plug(Pleroma.Web.ApiSpec.CastAndValidate) +  plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action in [:create, :delete]) + +  plug( +    OAuthScopesPlug, +    %{scopes: ["read:statuses"], fallback: :proceed_unauthenticated} +    when action == :index +  ) + +  defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.EmojiReactionOperation + +  def index(%{assigns: %{user: user}} = conn, %{id: activity_id} = params) do +    with %Activity{} = activity <- Activity.get_by_id_with_object(activity_id), +         %Object{data: %{"reactions" => reactions}} when is_list(reactions) <- +           Object.normalize(activity) do +      reactions = filter(reactions, params) +      render(conn, "index.json", emoji_reactions: reactions, user: user) +    else +      _e -> json(conn, []) +    end +  end + +  defp filter(reactions, %{emoji: emoji}) when is_binary(emoji) do +    Enum.filter(reactions, fn [e, _] -> e == emoji end) +  end + +  defp filter(reactions, _), do: reactions + +  def create(%{assigns: %{user: user}} = conn, %{id: activity_id, emoji: emoji}) do +    with {:ok, _activity} <- CommonAPI.react_with_emoji(activity_id, user, emoji) do +      activity = Activity.get_by_id(activity_id) + +      conn +      |> put_view(StatusView) +      |> render("show.json", activity: activity, for: user, as: :activity) +    end +  end + +  def delete(%{assigns: %{user: user}} = conn, %{id: activity_id, emoji: emoji}) do +    with {:ok, _activity} <- CommonAPI.unreact_with_emoji(activity_id, user, emoji) do +      activity = Activity.get_by_id(activity_id) + +      conn +      |> put_view(StatusView) +      |> render("show.json", activity: activity, for: user, as: :activity) +    end +  end +end diff --git a/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex b/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex index 8220d13bc..61273f7ee 100644 --- a/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex @@ -7,15 +7,10 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do    import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2] -  alias Pleroma.Activity    alias Pleroma.Conversation.Participation    alias Pleroma.Notification -  alias Pleroma.Object    alias Pleroma.Plugs.OAuthScopesPlug -  alias Pleroma.User    alias Pleroma.Web.ActivityPub.ActivityPub -  alias Pleroma.Web.CommonAPI -  alias Pleroma.Web.MastodonAPI.AccountView    alias Pleroma.Web.MastodonAPI.ConversationView    alias Pleroma.Web.MastodonAPI.NotificationView    alias Pleroma.Web.MastodonAPI.StatusView @@ -30,18 +25,6 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do    plug(      OAuthScopesPlug, -    %{scopes: ["read:statuses"], fallback: :proceed_unauthenticated} -    when action == :emoji_reactions_by -  ) - -  plug( -    OAuthScopesPlug, -    %{scopes: ["write:statuses"]} -    when action in [:react_with_emoji, :unreact_with_emoji] -  ) - -  plug( -    OAuthScopesPlug,      %{scopes: ["write:conversations"]}      when action in [:update_conversation, :mark_conversations_as_read]    ) @@ -53,66 +36,6 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do    defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaOperation -  def emoji_reactions_by(%{assigns: %{user: user}} = conn, %{id: activity_id} = params) do -    with %Activity{} = activity <- Activity.get_by_id_with_object(activity_id), -         %Object{data: %{"reactions" => emoji_reactions}} when is_list(emoji_reactions) <- -           Object.normalize(activity) do -      reactions = -        emoji_reactions -        |> Enum.map(fn [emoji, user_ap_ids] -> -          if params[:emoji] && params[:emoji] != emoji do -            nil -          else -            users = -              Enum.map(user_ap_ids, &User.get_cached_by_ap_id/1) -              |> Enum.filter(fn -                %{deactivated: false} -> true -                _ -> false -              end) - -            %{ -              name: emoji, -              count: length(users), -              accounts: -                AccountView.render("index.json", %{ -                  users: users, -                  for: user, -                  as: :user -                }), -              me: !!(user && user.ap_id in user_ap_ids) -            } -          end -        end) -        |> Enum.reject(&is_nil/1) - -      conn -      |> json(reactions) -    else -      _e -> -        conn -        |> json([]) -    end -  end - -  def react_with_emoji(%{assigns: %{user: user}} = conn, %{id: activity_id, emoji: emoji}) do -    with {:ok, _activity} <- CommonAPI.react_with_emoji(activity_id, user, emoji), -         activity <- Activity.get_by_id(activity_id) do -      conn -      |> put_view(StatusView) -      |> render("show.json", %{activity: activity, for: user, as: :activity}) -    end -  end - -  def unreact_with_emoji(%{assigns: %{user: user}} = conn, %{id: activity_id, emoji: emoji}) do -    with {:ok, _activity} <- -           CommonAPI.unreact_with_emoji(activity_id, user, emoji), -         activity <- Activity.get_by_id(activity_id) do -      conn -      |> put_view(StatusView) -      |> render("show.json", %{activity: activity, for: user, as: :activity}) -    end -  end -    def conversation(%{assigns: %{user: user}} = conn, %{id: participation_id}) do      with %Participation{} = participation <- Participation.get(participation_id),           true <- user.id == participation.user_id do diff --git a/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex b/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex new file mode 100644 index 000000000..84d2d303d --- /dev/null +++ b/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex @@ -0,0 +1,33 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.PleromaAPI.EmojiReactionView do +  use Pleroma.Web, :view + +  alias Pleroma.Web.MastodonAPI.AccountView + +  def render("index.json", %{emoji_reactions: emoji_reactions} = opts) do +    render_many(emoji_reactions, __MODULE__, "show.json", opts) +  end + +  def render("show.json", %{emoji_reaction: [emoji, user_ap_ids], user: user}) do +    users = fetch_users(user_ap_ids) + +    %{ +      name: emoji, +      count: length(users), +      accounts: render(AccountView, "index.json", users: users, for: user, as: :user), +      me: !!(user && user.ap_id in user_ap_ids) +    } +  end + +  defp fetch_users(user_ap_ids) do +    user_ap_ids +    |> Enum.map(&Pleroma.User.get_cached_by_ap_id/1) +    |> Enum.filter(fn +      %{deactivated: false} -> true +      _ -> false +    end) +  end +end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 369c54cf4..12381511e 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -297,8 +297,8 @@ defmodule Pleroma.Web.Router do    scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do      pipe_through(:api) -    get("/statuses/:id/reactions/:emoji", PleromaAPIController, :emoji_reactions_by) -    get("/statuses/:id/reactions", PleromaAPIController, :emoji_reactions_by) +    get("/statuses/:id/reactions/:emoji", EmojiReactionController, :index) +    get("/statuses/:id/reactions", EmojiReactionController, :index)    end    scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do @@ -314,8 +314,8 @@ defmodule Pleroma.Web.Router do        pipe_through(:authenticated_api)        patch("/conversations/:id", PleromaAPIController, :update_conversation) -      put("/statuses/:id/reactions/:emoji", PleromaAPIController, :react_with_emoji) -      delete("/statuses/:id/reactions/:emoji", PleromaAPIController, :unreact_with_emoji) +      put("/statuses/:id/reactions/:emoji", EmojiReactionController, :create) +      delete("/statuses/:id/reactions/:emoji", EmojiReactionController, :delete)        post("/notifications/read", PleromaAPIController, :mark_notifications_as_read)        patch("/accounts/update_avatar", AccountController, :update_avatar) | 
