Extract status actions from `MastodonAPIController` into `StatusController`
authorEgor Kislitsyn <egor@kislitsyn.com>
Mon, 9 Sep 2019 14:49:02 +0000 (21:49 +0700)
committerEgor Kislitsyn <egor@kislitsyn.com>
Fri, 27 Sep 2019 03:51:15 +0000 (10:51 +0700)
13 files changed:
lib/pleroma/bbs/handler.ex
lib/pleroma/web/admin_api/admin_api_controller.ex
lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex
lib/pleroma/web/mastodon_api/controllers/status_controller.ex [new file with mode: 0644]
lib/pleroma/web/mastodon_api/views/conversation_view.ex
lib/pleroma/web/mastodon_api/views/notification_view.ex
lib/pleroma/web/mastodon_api/views/status_view.ex
lib/pleroma/web/router.ex
lib/pleroma/web/views/streamer_view.ex
test/integration/mastodon_websocket_test.exs
test/web/admin_api/views/report_view_test.exs
test/web/mastodon_api/views/notification_view_test.exs
test/web/mastodon_api/views/status_view_test.exs

index 0a381f5920c954517b3dfdf1a31bf022cb0b4601..fa838a4e49bc41450fb2e376dba331526c8e840b 100644 (file)
@@ -42,7 +42,7 @@ defmodule Pleroma.BBS.Handler do
   end
 
   def puts_activity(activity) do
-    status = Pleroma.Web.MastodonAPI.StatusView.render("status.json", %{activity: activity})
+    status = Pleroma.Web.MastodonAPI.StatusView.render("show.json", %{activity: activity})
     IO.puts("-- #{status.id} by #{status.account.display_name} (#{status.account.acct})")
     IO.puts(HtmlSanitizeEx.strip_tags(status.content))
     IO.puts("")
index 90aef99f7857d921e92055f980adb5810fc08bef..21da8a7ff1e933adc24b71ca196eeeb3face5bc1 100644 (file)
@@ -513,7 +513,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
 
       conn
       |> put_view(StatusView)
-      |> render("status.json", %{activity: activity})
+      |> render("show.json", %{activity: activity})
     else
       true ->
         {:param_cast, nil}
@@ -537,7 +537,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
 
       conn
       |> put_view(StatusView)
-      |> render("status.json", %{activity: activity})
+      |> render("show.json", %{activity: activity})
     end
   end
 
index e4ae632312a1da57d2312950d38d18c9b3afbbd0..82bba43e51e1326bbfa31d3b6df708fd5660acbb 100644 (file)
@@ -51,28 +51,12 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
 
   @rate_limited_relations_actions ~w(follow unfollow)a
 
-  @rate_limited_status_actions ~w(reblog_status unreblog_status fav_status unfav_status
-    post_status delete_status)a
-
-  plug(
-    RateLimiter,
-    {:status_id_action, bucket_name: "status_id_action:reblog_unreblog", params: ["id"]}
-    when action in ~w(reblog_status unreblog_status)a
-  )
-
-  plug(
-    RateLimiter,
-    {:status_id_action, bucket_name: "status_id_action:fav_unfav", params: ["id"]}
-    when action in ~w(fav_status unfav_status)a
-  )
-
   plug(
     RateLimiter,
     {:relations_id_action, params: ["id", "uri"]} when action in @rate_limited_relations_actions
   )
 
   plug(RateLimiter, :relations_actions when action in @rate_limited_relations_actions)
-  plug(RateLimiter, :statuses_actions when action in @rate_limited_status_actions)
   plug(RateLimiter, :app_account_creation when action == :account_register)
   plug(RateLimiter, :search when action in [:search, :search2, :account_search])
   plug(RateLimiter, :password_reset when action == :password_reset)
@@ -362,63 +346,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
     end
   end
 
-  def get_statuses(%{assigns: %{user: user}} = conn, %{"ids" => ids}) do
-    limit = 100
-
-    activities =
-      ids
-      |> Enum.take(limit)
-      |> Activity.all_by_ids_with_object()
-      |> Enum.filter(&Visibility.visible_for_user?(&1, user))
-
-    conn
-    |> put_view(StatusView)
-    |> render("index.json", activities: activities, for: user, as: :activity)
-  end
-
-  def get_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
-    with %Activity{} = activity <- Activity.get_by_id_with_object(id),
-         true <- Visibility.visible_for_user?(activity, user) do
-      conn
-      |> put_view(StatusView)
-      |> try_render("status.json", %{activity: activity, for: user})
-    end
-  end
-
-  def get_context(%{assigns: %{user: user}} = conn, %{"id" => id}) do
-    with %Activity{} = activity <- Activity.get_by_id(id),
-         activities <-
-           ActivityPub.fetch_activities_for_context(activity.data["context"], %{
-             "blocking_user" => user,
-             "user" => user,
-             "exclude_id" => activity.id
-           }),
-         grouped_activities <- Enum.group_by(activities, fn %{id: id} -> id < activity.id end) do
-      result = %{
-        ancestors:
-          StatusView.render(
-            "index.json",
-            for: user,
-            activities: grouped_activities[true] || [],
-            as: :activity
-          )
-          |> Enum.reverse(),
-        # credo:disable-for-previous-line Credo.Check.Refactor.PipeChainStart
-        descendants:
-          StatusView.render(
-            "index.json",
-            for: user,
-            activities: grouped_activities[false] || [],
-            as: :activity
-          )
-          |> Enum.reverse()
-        # credo:disable-for-previous-line Credo.Check.Refactor.PipeChainStart
-      }
-
-      json(conn, result)
-    end
-  end
-
   def get_poll(%{assigns: %{user: user}} = conn, %{"id" => id}) do
     with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
          %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
@@ -518,143 +445,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
     end
   end
 
-  def post_status(
-        %{assigns: %{user: user}} = conn,
-        %{"status" => _, "scheduled_at" => scheduled_at} = params
-      ) do
-    if ScheduledActivity.far_enough?(scheduled_at) do
-      with {:ok, scheduled_activity} <-
-             ScheduledActivity.create(user, %{"params" => params, "scheduled_at" => scheduled_at}) do
-        conn
-        |> put_view(ScheduledActivityView)
-        |> render("show.json", %{scheduled_activity: scheduled_activity})
-      end
-    else
-      post_status(conn, Map.drop(params, ["scheduled_at"]))
-    end
-  end
-
-  def post_status(%{assigns: %{user: user}} = conn, %{"status" => _} = params) do
-    case CommonAPI.post(user, params) do
-      {:ok, activity} ->
-        conn
-        |> put_view(StatusView)
-        |> try_render("status.json", %{
-          activity: activity,
-          for: user,
-          as: :activity,
-          with_direct_conversation_id: true
-        })
-
-      {:error, message} ->
-        conn
-        |> put_status(:unprocessable_entity)
-        |> json(%{error: message})
-    end
-  end
-
-  def delete_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
-    with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
-      json(conn, %{})
-    else
-      _e -> render_error(conn, :forbidden, "Can't delete this post")
-    end
-  end
-
-  def reblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
-    with {:ok, announce, _activity} <- CommonAPI.repeat(ap_id_or_id, user),
-         %Activity{} = announce <- Activity.normalize(announce.data) do
-      conn
-      |> put_view(StatusView)
-      |> try_render("status.json", %{activity: announce, for: user, as: :activity})
-    end
-  end
-
-  def unreblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
-    with {:ok, _unannounce, %{data: %{"id" => id}}} <- CommonAPI.unrepeat(ap_id_or_id, user),
-         %Activity{} = activity <- Activity.get_create_by_object_ap_id_with_object(id) do
-      conn
-      |> put_view(StatusView)
-      |> try_render("status.json", %{activity: activity, for: user, as: :activity})
-    end
-  end
-
-  def fav_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
-    with {:ok, _fav, %{data: %{"id" => id}}} <- CommonAPI.favorite(ap_id_or_id, user),
-         %Activity{} = activity <- Activity.get_create_by_object_ap_id(id) do
-      conn
-      |> put_view(StatusView)
-      |> try_render("status.json", %{activity: activity, for: user, as: :activity})
-    end
-  end
-
-  def unfav_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
-    with {:ok, _, _, %{data: %{"id" => id}}} <- CommonAPI.unfavorite(ap_id_or_id, user),
-         %Activity{} = activity <- Activity.get_create_by_object_ap_id(id) do
-      conn
-      |> put_view(StatusView)
-      |> try_render("status.json", %{activity: activity, for: user, as: :activity})
-    end
-  end
-
-  def pin_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
-    with {:ok, activity} <- CommonAPI.pin(ap_id_or_id, user) do
-      conn
-      |> put_view(StatusView)
-      |> try_render("status.json", %{activity: activity, for: user, as: :activity})
-    end
-  end
-
-  def unpin_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
-    with {:ok, activity} <- CommonAPI.unpin(ap_id_or_id, user) do
-      conn
-      |> put_view(StatusView)
-      |> try_render("status.json", %{activity: activity, for: user, as: :activity})
-    end
-  end
-
-  def bookmark_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
-    with %Activity{} = activity <- Activity.get_by_id_with_object(id),
-         %User{} = user <- User.get_cached_by_nickname(user.nickname),
-         true <- Visibility.visible_for_user?(activity, user),
-         {:ok, _bookmark} <- Bookmark.create(user.id, activity.id) do
-      conn
-      |> put_view(StatusView)
-      |> try_render("status.json", %{activity: activity, for: user, as: :activity})
-    end
-  end
-
-  def unbookmark_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
-    with %Activity{} = activity <- Activity.get_by_id_with_object(id),
-         %User{} = user <- User.get_cached_by_nickname(user.nickname),
-         true <- Visibility.visible_for_user?(activity, user),
-         {:ok, _bookmark} <- Bookmark.destroy(user.id, activity.id) do
-      conn
-      |> put_view(StatusView)
-      |> try_render("status.json", %{activity: activity, for: user, as: :activity})
-    end
-  end
-
-  def mute_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
-    activity = Activity.get_by_id(id)
-
-    with {:ok, activity} <- CommonAPI.add_mute(user, activity) do
-      conn
-      |> put_view(StatusView)
-      |> try_render("status.json", %{activity: activity, for: user, as: :activity})
-    end
-  end
-
-  def unmute_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
-    activity = Activity.get_by_id(id)
-
-    with {:ok, activity} <- CommonAPI.remove_mute(user, activity) do
-      conn
-      |> put_view(StatusView)
-      |> try_render("status.json", %{activity: activity, for: user, as: :activity})
-    end
-  end
-
   def relationships(%{assigns: %{user: user}} = conn, %{"id" => id}) do
     id = List.wrap(id)
     q = from(u in User, where: u.id in ^id)
@@ -726,44 +516,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
     |> json(mascot)
   end
 
-  def favourited_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
-    with %Activity{} = activity <- Activity.get_by_id_with_object(id),
-         {:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
-         %Object{data: %{"likes" => likes}} <- Object.normalize(activity) do
-      q = from(u in User, where: u.ap_id in ^likes)
-
-      users =
-        Repo.all(q)
-        |> Enum.filter(&(not User.blocks?(user, &1)))
-
-      conn
-      |> put_view(AccountView)
-      |> render("accounts.json", %{for: user, users: users, as: :user})
-    else
-      {:visible, false} -> {:error, :not_found}
-      _ -> json(conn, [])
-    end
-  end
-
-  def reblogged_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
-    with %Activity{} = activity <- Activity.get_by_id_with_object(id),
-         {:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
-         %Object{data: %{"announcements" => announces}} <- Object.normalize(activity) do
-      q = from(u in User, where: u.ap_id in ^announces)
-
-      users =
-        Repo.all(q)
-        |> Enum.filter(&(not User.blocks?(user, &1)))
-
-      conn
-      |> put_view(AccountView)
-      |> render("accounts.json", %{for: user, users: users, as: :user})
-    else
-      {:visible, false} -> {:error, :not_found}
-      _ -> json(conn, [])
-    end
-  end
-
   def followers(%{assigns: %{user: for_user}} = conn, %{"id" => id} = params) do
     with %User{} = user <- User.get_cached_by_id(id),
          followers <- MastodonAPI.get_followers(user, params) do
@@ -1394,22 +1146,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
     end
   end
 
-  def status_card(%{assigns: %{user: user}} = conn, %{"id" => status_id}) do
-    with %Activity{} = activity <- Activity.get_by_id(status_id),
-         true <- Visibility.visible_for_user?(activity, user) do
-      data =
-        StatusView.render(
-          "card.json",
-          Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)
-        )
-
-      json(conn, data)
-    else
-      _e ->
-        %{}
-    end
-  end
-
   def reports(%{assigns: %{user: user}} = conn, params) do
     case CommonAPI.report(user, params) do
       {:ok, activity} ->
diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
new file mode 100644 (file)
index 0000000..89869bd
--- /dev/null
@@ -0,0 +1,294 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.StatusController do
+  use Pleroma.Web, :controller
+
+  import Pleroma.Web.MastodonAPI.MastodonAPIController, only: [try_render: 3]
+
+  require Ecto.Query
+
+  alias Pleroma.Activity
+  alias Pleroma.Bookmark
+  alias Pleroma.Object
+  alias Pleroma.Plugs.RateLimiter
+  alias Pleroma.Repo
+  alias Pleroma.ScheduledActivity
+  alias Pleroma.User
+  alias Pleroma.Web.ActivityPub.ActivityPub
+  alias Pleroma.Web.ActivityPub.Visibility
+  alias Pleroma.Web.CommonAPI
+  alias Pleroma.Web.MastodonAPI.AccountView
+  alias Pleroma.Web.MastodonAPI.ScheduledActivityView
+  alias Pleroma.Web.MastodonAPI.StatusView
+
+  @rate_limited_status_actions ~w(reblog unreblog favourite unfavourite create delete)a
+
+  plug(
+    RateLimiter,
+    {:status_id_action, bucket_name: "status_id_action:reblog_unreblog", params: ["id"]}
+    when action in ~w(reblog unreblog)a
+  )
+
+  plug(
+    RateLimiter,
+    {:status_id_action, bucket_name: "status_id_action:fav_unfav", params: ["id"]}
+    when action in ~w(favourite unfavourite)a
+  )
+
+  plug(RateLimiter, :statuses_actions when action in @rate_limited_status_actions)
+
+  action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
+
+  @doc """
+  GET `/api/v1/statuses?ids[]=1&ids[]=2`
+
+  `ids` query param is required
+  """
+  def index(%{assigns: %{user: user}} = conn, %{"ids" => ids}) do
+    limit = 100
+
+    activities =
+      ids
+      |> Enum.take(limit)
+      |> Activity.all_by_ids_with_object()
+      |> Enum.filter(&Visibility.visible_for_user?(&1, user))
+
+    render(conn, "index.json", activities: activities, for: user, as: :activity)
+  end
+
+  @doc """
+  POST /api/v1/statuses
+
+  Creates a scheduled status when `scheduled_at` param is present and it's far enough
+  """
+  def create(
+        %{assigns: %{user: user}} = conn,
+        %{"status" => _, "scheduled_at" => scheduled_at} = params
+      ) do
+    params = Map.put(params, "in_reply_to_status_id", params["in_reply_to_id"])
+
+    if ScheduledActivity.far_enough?(scheduled_at) do
+      with {:ok, scheduled_activity} <-
+             ScheduledActivity.create(user, %{"params" => params, "scheduled_at" => scheduled_at}) do
+        conn
+        |> put_view(ScheduledActivityView)
+        |> render("show.json", scheduled_activity: scheduled_activity)
+      end
+    else
+      create(conn, Map.drop(params, ["scheduled_at"]))
+    end
+  end
+
+  @doc """
+  POST /api/v1/statuses
+
+  Creates a regular status
+  """
+  def create(%{assigns: %{user: user}} = conn, %{"status" => _} = params) do
+    params = Map.put(params, "in_reply_to_status_id", params["in_reply_to_id"])
+
+    with {:ok, activity} <- CommonAPI.post(user, params) do
+      try_render(conn, "show.json",
+        activity: activity,
+        for: user,
+        as: :activity,
+        with_direct_conversation_id: true
+      )
+    else
+      {:error, message} ->
+        conn
+        |> put_status(:unprocessable_entity)
+        |> json(%{error: message})
+    end
+  end
+
+  @doc "GET /api/v1/statuses/:id"
+  def show(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+    with %Activity{} = activity <- Activity.get_by_id_with_object(id),
+         true <- Visibility.visible_for_user?(activity, user) do
+      try_render(conn, "show.json", activity: activity, for: user)
+    end
+  end
+
+  @doc "DELETE /api/v1/statuses/:id"
+  def delete(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+    with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
+      json(conn, %{})
+    else
+      _e -> render_error(conn, :forbidden, "Can't delete this post")
+    end
+  end
+
+  @doc "POST /api/v1/statuses/:id/reblog"
+  def reblog(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
+    with {:ok, announce, _activity} <- CommonAPI.repeat(ap_id_or_id, user),
+         %Activity{} = announce <- Activity.normalize(announce.data) do
+      try_render(conn, "show.json", %{activity: announce, for: user, as: :activity})
+    end
+  end
+
+  @doc "POST /api/v1/statuses/:id/unreblog"
+  def unreblog(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
+    with {:ok, _unannounce, %{data: %{"id" => id}}} <- CommonAPI.unrepeat(ap_id_or_id, user),
+         %Activity{} = activity <- Activity.get_create_by_object_ap_id_with_object(id) do
+      try_render(conn, "show.json", %{activity: activity, for: user, as: :activity})
+    end
+  end
+
+  @doc "POST /api/v1/statuses/:id/favourite"
+  def favourite(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
+    with {:ok, _fav, %{data: %{"id" => id}}} <- CommonAPI.favorite(ap_id_or_id, user),
+         %Activity{} = activity <- Activity.get_create_by_object_ap_id(id) do
+      try_render(conn, "show.json", activity: activity, for: user, as: :activity)
+    end
+  end
+
+  @doc "POST /api/v1/statuses/:id/unfavourite"
+  def unfavourite(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
+    with {:ok, _, _, %{data: %{"id" => id}}} <- CommonAPI.unfavorite(ap_id_or_id, user),
+         %Activity{} = activity <- Activity.get_create_by_object_ap_id(id) do
+      try_render(conn, "show.json", activity: activity, for: user, as: :activity)
+    end
+  end
+
+  @doc "POST /api/v1/statuses/:id/pin"
+  def pin(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
+    with {:ok, activity} <- CommonAPI.pin(ap_id_or_id, user) do
+      try_render(conn, "show.json", activity: activity, for: user, as: :activity)
+    end
+  end
+
+  @doc "POST /api/v1/statuses/:id/unpin"
+  def unpin(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
+    with {:ok, activity} <- CommonAPI.unpin(ap_id_or_id, user) do
+      try_render(conn, "show.json", activity: activity, for: user, as: :activity)
+    end
+  end
+
+  @doc "POST /api/v1/statuses/:id/bookmark"
+  def bookmark(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+    with %Activity{} = activity <- Activity.get_by_id_with_object(id),
+         %User{} = user <- User.get_cached_by_nickname(user.nickname),
+         true <- Visibility.visible_for_user?(activity, user),
+         {:ok, _bookmark} <- Bookmark.create(user.id, activity.id) do
+      try_render(conn, "show.json", activity: activity, for: user, as: :activity)
+    end
+  end
+
+  @doc "POST /api/v1/statuses/:id/unbookmark"
+  def unbookmark(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+    with %Activity{} = activity <- Activity.get_by_id_with_object(id),
+         %User{} = user <- User.get_cached_by_nickname(user.nickname),
+         true <- Visibility.visible_for_user?(activity, user),
+         {:ok, _bookmark} <- Bookmark.destroy(user.id, activity.id) do
+      try_render(conn, "show.json", activity: activity, for: user, as: :activity)
+    end
+  end
+
+  @doc "POST /api/v1/statuses/:id/mute"
+  def mute_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+    with %Activity{} = activity <- Activity.get_by_id(id),
+         {:ok, activity} <- CommonAPI.add_mute(user, activity) do
+      try_render(conn, "show.json", activity: activity, for: user, as: :activity)
+    end
+  end
+
+  @doc "POST /api/v1/statuses/:id/unmute"
+  def unmute_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+    with %Activity{} = activity <- Activity.get_by_id(id),
+         {:ok, activity} <- CommonAPI.remove_mute(user, activity) do
+      try_render(conn, "show.json", activity: activity, for: user, as: :activity)
+    end
+  end
+
+  @doc "GET /api/v1/statuses/:id/card"
+  def card(%{assigns: %{user: user}} = conn, %{"id" => status_id}) do
+    with %Activity{} = activity <- Activity.get_by_id(status_id),
+         true <- Visibility.visible_for_user?(activity, user) do
+      data = Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)
+      render(conn, "card.json", data)
+    else
+      _ -> render_error(conn, :not_found, "Record not found")
+    end
+  end
+
+  @doc "GET /api/v1/statuses/:id/favourited_by"
+  def favourited_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+    with %Activity{} = activity <- Activity.get_by_id_with_object(id),
+         {:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
+         %Object{data: %{"likes" => likes}} <- Object.normalize(activity) do
+      users =
+        User
+        |> Ecto.Query.where([u], u.ap_id in ^likes)
+        |> Repo.all()
+        |> Enum.filter(&(not User.blocks?(user, &1)))
+
+      conn
+      |> put_view(AccountView)
+      |> render("accounts.json", for: user, users: users, as: :user)
+    else
+      {:visible, false} -> {:error, :not_found}
+      _ -> json(conn, [])
+    end
+  end
+
+  @doc "GET /api/v1/statuses/:id/reblogged_by"
+  def reblogged_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+    with %Activity{} = activity <- Activity.get_by_id_with_object(id),
+         {:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
+         %Object{data: %{"announcements" => announces}} <- Object.normalize(activity) do
+      users =
+        User
+        |> Ecto.Query.where([u], u.ap_id in ^announces)
+        |> Repo.all()
+        |> Enum.filter(&(not User.blocks?(user, &1)))
+
+      conn
+      |> put_view(AccountView)
+      |> render("accounts.json", for: user, users: users, as: :user)
+    else
+      {:visible, false} -> {:error, :not_found}
+      _ -> json(conn, [])
+    end
+  end
+
+  @doc "GET /api/v1/statuses/:id/context"
+  def context(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+    with %Activity{} = activity <- Activity.get_by_id(id) do
+      activities =
+        ActivityPub.fetch_activities_for_context(activity.data["context"], %{
+          "blocking_user" => user,
+          "user" => user,
+          "exclude_id" => activity.id
+        })
+
+      # TODO: Move to view
+      grouped_activities = Enum.group_by(activities, fn %{id: id} -> id < activity.id end)
+
+      result = %{
+        ancestors:
+          StatusView.render(
+            "index.json",
+            for: user,
+            activities: grouped_activities[true] || [],
+            as: :activity
+          )
+          |> Enum.reverse(),
+        # credo:disable-for-previous-line Credo.Check.Refactor.PipeChainStart
+        descendants:
+          StatusView.render(
+            "index.json",
+            for: user,
+            activities: grouped_activities[false] || [],
+            as: :activity
+          )
+          |> Enum.reverse()
+        # credo:disable-for-previous-line Credo.Check.Refactor.PipeChainStart
+      }
+
+      json(conn, result)
+    end
+  end
+end
index 40acc07b3bade2bef4fbe8b6335eb067fbd44983..4aeb79d81dc313ea0c49743622ef10f044d2d7c9 100644 (file)
@@ -24,7 +24,7 @@ defmodule Pleroma.Web.MastodonAPI.ConversationView do
 
     activity = Activity.get_by_id_with_object(last_activity_id)
 
-    last_status = StatusView.render("status.json", %{activity: activity, for: user})
+    last_status = StatusView.render("show.json", %{activity: activity, for: user})
 
     # Conversations return all users except the current user.
     users =
index ec8eadcaab88af0d648db975670fa0179fedaeb8..05110a1921a1617a99c77354c8b6a31e0c1c3ec6 100644 (file)
@@ -39,19 +39,19 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do
       "mention" ->
         response
         |> Map.merge(%{
-          status: StatusView.render("status.json", %{activity: activity, for: user})
+          status: StatusView.render("show.json", %{activity: activity, for: user})
         })
 
       "favourite" ->
         response
         |> Map.merge(%{
-          status: StatusView.render("status.json", %{activity: parent_activity, for: user})
+          status: StatusView.render("show.json", %{activity: parent_activity, for: user})
         })
 
       "reblog" ->
         response
         |> Map.merge(%{
-          status: StatusView.render("status.json", %{activity: parent_activity, for: user})
+          status: StatusView.render("show.json", %{activity: parent_activity, for: user})
         })
 
       "follow" ->
index ef796cddd2b0645d46293a2b1f4ea70537bb89fb..59bef30f2aa7998fac1213e5bd933a862ecaeee6 100644 (file)
@@ -73,17 +73,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
 
   def render("index.json", opts) do
     replied_to_activities = get_replied_to_activities(opts.activities)
+    opts = Map.put(opts, :replied_to_activities, replied_to_activities)
 
-    opts.activities
-    |> safe_render_many(
-      StatusView,
-      "status.json",
-      Map.put(opts, :replied_to_activities, replied_to_activities)
-    )
+    safe_render_many(opts.activities, StatusView, "show.json", opts)
   end
 
   def render(
-        "status.json",
+        "show.json",
         %{activity: %{data: %{"type" => "Announce", "object" => _object}} = activity} = opts
       ) do
     user = get_user(activity.data["actor"])
@@ -96,7 +92,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
       |> Activity.with_set_thread_muted_field(opts[:for])
       |> Repo.one()
 
-    reblogged = render("status.json", Map.put(opts, :activity, reblogged_activity))
+    reblogged = render("show.json", Map.put(opts, :activity, reblogged_activity))
 
     favorited = opts[:for] && opts[:for].ap_id in (activity_object.data["likes"] || [])
 
@@ -144,7 +140,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
     }
   end
 
-  def render("status.json", %{activity: %{data: %{"object" => _object}} = activity} = opts) do
+  def render("show.json", %{activity: %{data: %{"object" => _object}} = activity} = opts) do
     object = Object.normalize(activity)
 
     user = get_user(activity.data["actor"])
@@ -303,7 +299,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
     }
   end
 
-  def render("status.json", _) do
+  def render("show.json", _) do
     nil
   end
 
index 2575481ff50021fe9b2f285863d2ef9d3f11833a..7a20b6d75de983c80577bbd50348da74d464d1b8 100644 (file)
@@ -355,19 +355,19 @@ defmodule Pleroma.Web.Router do
 
       patch("/accounts/update_credentials", MastodonAPIController, :update_credentials)
 
-      post("/statuses", MastodonAPIController, :post_status)
-      delete("/statuses/:id", MastodonAPIController, :delete_status)
-
-      post("/statuses/:id/reblog", MastodonAPIController, :reblog_status)
-      post("/statuses/:id/unreblog", MastodonAPIController, :unreblog_status)
-      post("/statuses/:id/favourite", MastodonAPIController, :fav_status)
-      post("/statuses/:id/unfavourite", MastodonAPIController, :unfav_status)
-      post("/statuses/:id/pin", MastodonAPIController, :pin_status)
-      post("/statuses/:id/unpin", MastodonAPIController, :unpin_status)
-      post("/statuses/:id/bookmark", MastodonAPIController, :bookmark_status)
-      post("/statuses/:id/unbookmark", MastodonAPIController, :unbookmark_status)
-      post("/statuses/:id/mute", MastodonAPIController, :mute_conversation)
-      post("/statuses/:id/unmute", MastodonAPIController, :unmute_conversation)
+      post("/statuses", StatusController, :create)
+      delete("/statuses/:id", StatusController, :delete)
+
+      post("/statuses/:id/reblog", StatusController, :reblog)
+      post("/statuses/:id/unreblog", StatusController, :unreblog)
+      post("/statuses/:id/favourite", StatusController, :favourite)
+      post("/statuses/:id/unfavourite", StatusController, :unfavourite)
+      post("/statuses/:id/pin", StatusController, :pin)
+      post("/statuses/:id/unpin", StatusController, :unpin)
+      post("/statuses/:id/bookmark", StatusController, :bookmark)
+      post("/statuses/:id/unbookmark", StatusController, :unbookmark)
+      post("/statuses/:id/mute", StatusController, :mute_conversation)
+      post("/statuses/:id/unmute", StatusController, :unmute_conversation)
 
       put("/scheduled_statuses/:id", MastodonAPIController, :update_scheduled_status)
       delete("/scheduled_statuses/:id", MastodonAPIController, :delete_scheduled_status)
@@ -448,10 +448,10 @@ defmodule Pleroma.Web.Router do
     get("/apps/verify_credentials", MastodonAPIController, :verify_app_credentials)
     get("/custom_emojis", MastodonAPIController, :custom_emojis)
 
-    get("/statuses/:id/card", MastodonAPIController, :status_card)
+    get("/statuses/:id/card", StatusController, :card)
 
-    get("/statuses/:id/favourited_by", MastodonAPIController, :favourited_by)
-    get("/statuses/:id/reblogged_by", MastodonAPIController, :reblogged_by)
+    get("/statuses/:id/favourited_by", StatusController, :favourited_by)
+    get("/statuses/:id/reblogged_by", StatusController, :reblogged_by)
 
     get("/trends", MastodonAPIController, :empty_array)
 
@@ -470,9 +470,9 @@ defmodule Pleroma.Web.Router do
       get("/timelines/tag/:tag", TimelineController, :hashtag)
       get("/timelines/list/:list_id", TimelineController, :list)
 
-      get("/statuses", MastodonAPIController, :get_statuses)
-      get("/statuses/:id", MastodonAPIController, :get_status)
-      get("/statuses/:id/context", MastodonAPIController, :get_context)
+      get("/statuses", StatusController, :index)
+      get("/statuses/:id", StatusController, :show)
+      get("/statuses/:id/context", StatusController, :context)
 
       get("/polls/:id", MastodonAPIController, :get_poll)
 
index b13030fa0a13ba2a78634f4cc7263558b58a0ba4..a9f14d09ac0de09af00b51946e4bb6a2b192d4aa 100644 (file)
@@ -16,7 +16,7 @@ defmodule Pleroma.Web.StreamerView do
       event: "update",
       payload:
         Pleroma.Web.MastodonAPI.StatusView.render(
-          "status.json",
+          "show.json",
           activity: activity,
           for: user
         )
@@ -43,7 +43,7 @@ defmodule Pleroma.Web.StreamerView do
       event: "update",
       payload:
         Pleroma.Web.MastodonAPI.StatusView.render(
-          "status.json",
+          "show.json",
           activity: activity
         )
         |> Jason.encode!()
index ed7ce8fe036849bcfac98fee481789a07fc9752f..63fce07bbbda39549c98e119207ca3ec8cbb60c6 100644 (file)
@@ -68,7 +68,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
     assert {:ok, json} = Jason.decode(json["payload"])
 
     view_json =
-      Pleroma.Web.MastodonAPI.StatusView.render("status.json", activity: activity, for: nil)
+      Pleroma.Web.MastodonAPI.StatusView.render("show.json", activity: activity, for: nil)
       |> Jason.encode!()
       |> Jason.decode!()
 
index 40df011015d8a2350e0c97986e4856c699f8c56f..35b6947a0fc07c27a8220caa9ac2c62a1c113ac2 100644 (file)
@@ -61,7 +61,7 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
           AccountView.render("account.json", %{user: other_user}),
           Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: other_user})
         ),
-      statuses: [StatusView.render("status.json", %{activity: activity})],
+      statuses: [StatusView.render("show.json", %{activity: activity})],
       state: "open",
       id: report_activity.id
     }
index 9231aaec87654fcdeb8c60bf24260add1a0f93bc..86268fcfa650bd3c3a1e6dbfece4186ba033f628 100644 (file)
@@ -28,7 +28,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
       pleroma: %{is_seen: false},
       type: "mention",
       account: AccountView.render("account.json", %{user: user, for: mentioned_user}),
-      status: StatusView.render("status.json", %{activity: activity, for: mentioned_user}),
+      status: StatusView.render("show.json", %{activity: activity, for: mentioned_user}),
       created_at: Utils.to_masto_date(notification.inserted_at)
     }
 
@@ -51,7 +51,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
       pleroma: %{is_seen: false},
       type: "favourite",
       account: AccountView.render("account.json", %{user: another_user, for: user}),
-      status: StatusView.render("status.json", %{activity: create_activity, for: user}),
+      status: StatusView.render("show.json", %{activity: create_activity, for: user}),
       created_at: Utils.to_masto_date(notification.inserted_at)
     }
 
@@ -73,7 +73,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
       pleroma: %{is_seen: false},
       type: "reblog",
       account: AccountView.render("account.json", %{user: another_user, for: user}),
-      status: StatusView.render("status.json", %{activity: reblog_activity, for: user}),
+      status: StatusView.render("show.json", %{activity: reblog_activity, for: user}),
       created_at: Utils.to_masto_date(notification.inserted_at)
     }
 
index 51f8434fad2f7bc24637a89361d235bf49bfc797..c17d0ef958c92a57e535331244721b770d620392 100644 (file)
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
     {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
 
     status =
-      StatusView.render("status.json",
+      StatusView.render("show.json",
         activity: activity,
         with_direct_conversation_id: true,
         for: user
@@ -46,7 +46,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
     Repo.delete(user)
     Cachex.clear(:user_cache)
 
-    %{account: ms_user} = StatusView.render("status.json", activity: activity)
+    %{account: ms_user} = StatusView.render("show.json", activity: activity)
 
     assert ms_user.acct == "erroruser@example.com"
   end
@@ -63,7 +63,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
 
     Cachex.clear(:user_cache)
 
-    result = StatusView.render("status.json", activity: activity)
+    result = StatusView.render("show.json", activity: activity)
 
     assert result[:account][:id] == to_string(user.id)
   end
@@ -81,7 +81,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
 
     User.get_cached_by_ap_id(note.data["actor"])
 
-    status = StatusView.render("status.json", %{activity: note})
+    status = StatusView.render("show.json", %{activity: note})
 
     assert status.content == ""
   end
@@ -93,7 +93,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
 
     convo_id = Utils.context_to_conversation_id(object_data["context"])
 
-    status = StatusView.render("status.json", %{activity: note})
+    status = StatusView.render("show.json", %{activity: note})
 
     created_at =
       (object_data["published"] || "")
@@ -165,11 +165,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
     {:ok, user} = User.mute(user, other_user)
 
     {:ok, activity} = CommonAPI.post(other_user, %{"status" => "test"})
-    status = StatusView.render("status.json", %{activity: activity})
+    status = StatusView.render("show.json", %{activity: activity})
 
     assert status.muted == false
 
-    status = StatusView.render("status.json", %{activity: activity, for: user})
+    status = StatusView.render("show.json", %{activity: activity, for: user})
 
     assert status.muted == true
   end
@@ -181,13 +181,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
     {:ok, user} = User.mute(user, other_user)
 
     {:ok, activity} = CommonAPI.post(other_user, %{"status" => "test"})
-    status = StatusView.render("status.json", %{activity: activity, for: user})
+    status = StatusView.render("show.json", %{activity: activity, for: user})
 
     assert status.pleroma.thread_muted == false
 
     {:ok, activity} = CommonAPI.add_mute(user, activity)
 
-    status = StatusView.render("status.json", %{activity: activity, for: user})
+    status = StatusView.render("show.json", %{activity: activity, for: user})
 
     assert status.pleroma.thread_muted == true
   end
@@ -196,11 +196,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
     user = insert(:user)
 
     {:ok, activity} = CommonAPI.post(user, %{"status" => "Cute girls doing cute things"})
-    status = StatusView.render("status.json", %{activity: activity})
+    status = StatusView.render("show.json", %{activity: activity})
 
     assert status.bookmarked == false
 
-    status = StatusView.render("status.json", %{activity: activity, for: user})
+    status = StatusView.render("show.json", %{activity: activity, for: user})
 
     assert status.bookmarked == false
 
@@ -208,7 +208,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
 
     activity = Activity.get_by_id_with_object(activity.id)
 
-    status = StatusView.render("status.json", %{activity: activity, for: user})
+    status = StatusView.render("show.json", %{activity: activity, for: user})
 
     assert status.bookmarked == true
   end
@@ -220,7 +220,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
     {:ok, activity} =
       CommonAPI.post(user, %{"status" => "he", "in_reply_to_status_id" => note.id})
 
-    status = StatusView.render("status.json", %{activity: activity})
+    status = StatusView.render("show.json", %{activity: activity})
 
     assert status.in_reply_to_id == to_string(note.id)
 
@@ -237,7 +237,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
 
     {:ok, [activity]} = OStatus.handle_incoming(incoming)
 
-    status = StatusView.render("status.json", %{activity: activity})
+    status = StatusView.render("show.json", %{activity: activity})
 
     assert status.mentions ==
              Enum.map([user], fn u -> AccountView.render("mention.json", %{user: u}) end)
@@ -263,7 +263,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
 
     assert length(activity.recipients) == 3
 
-    %{mentions: [mention] = mentions} = StatusView.render("status.json", %{activity: activity})
+    %{mentions: [mention] = mentions} = StatusView.render("show.json", %{activity: activity})
 
     assert length(mentions) == 1
     assert mention.url == recipient_ap_id
@@ -300,7 +300,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
 
     assert length(activity.recipients) == 3
 
-    %{mentions: [mention] = mentions} = StatusView.render("status.json", %{activity: activity})
+    %{mentions: [mention] = mentions} = StatusView.render("show.json", %{activity: activity})
 
     assert length(mentions) == 1
     assert mention.url == recipient.ap_id
@@ -340,7 +340,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
     id = "https://wedistribute.org/wp-json/pterotype/v1/object/85810"
     [activity] = Activity.search(nil, id)
 
-    status = StatusView.render("status.json", %{activity: activity})
+    status = StatusView.render("show.json", %{activity: activity})
 
     assert status.uri == id
     assert status.url == "https://wedistribute.org/2019/07/mastodon-drops-ostatus/"
@@ -352,7 +352,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
 
     {:ok, reblog, _} = CommonAPI.repeat(activity.id, user)
 
-    represented = StatusView.render("status.json", %{for: user, activity: reblog})
+    represented = StatusView.render("show.json", %{for: user, activity: reblog})
 
     assert represented[:id] == to_string(reblog.id)
     assert represented[:reblog][:id] == to_string(activity.id)
@@ -369,7 +369,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
 
     %Activity{} = activity = Activity.get_create_by_object_ap_id(object.data["id"])
 
-    represented = StatusView.render("status.json", %{for: user, activity: activity})
+    represented = StatusView.render("show.json", %{for: user, activity: activity})
 
     assert represented[:id] == to_string(activity.id)
     assert length(represented[:media_attachments]) == 1
@@ -570,7 +570,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
         "status" => "drink more water"
       })
 
-    result = StatusView.render("status.json", %{activity: activity, for: other_user})
+    result = StatusView.render("show.json", %{activity: activity, for: other_user})
 
     assert result[:account][:pleroma][:relationship] ==
              AccountView.render("relationship.json", %{user: other_user, target: user})
@@ -587,7 +587,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
 
     {:ok, activity, _object} = CommonAPI.repeat(activity.id, other_user)
 
-    result = StatusView.render("status.json", %{activity: activity, for: user})
+    result = StatusView.render("show.json", %{activity: activity, for: user})
 
     assert result[:account][:pleroma][:relationship] ==
              AccountView.render("relationship.json", %{user: user, target: other_user})
@@ -604,7 +604,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
     {:ok, activity} =
       CommonAPI.post(user, %{"status" => "foobar", "visibility" => "list:#{list.id}"})
 
-    status = StatusView.render("status.json", activity: activity)
+    status = StatusView.render("show.json", activity: activity)
 
     assert status.visibility == "list"
   end