Hook up unfollow and (un)block to MastoAPI + tests
[akkoma] / lib / pleroma / web / mastodon_api / mastodon_api_controller.ex
index 6ddfc8b7514680d32ac56ebbb49648db2e6d57f6..b21f5de208c08f2acfa004fb8a01b099c794f626 100644 (file)
@@ -112,7 +112,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
       version: "#{@mastodon_api_level} (compatible; #{Keyword.get(@instance, :version)})",
       email: Keyword.get(@instance, :email),
       urls: %{
-        streaming_api: String.replace(Web.base_url(), ["http", "https"], "wss")
+        streaming_api: String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws")
       },
       stats: Stats.get_stats(),
       thumbnail: Web.base_url() <> "/instance/thumbnail.jpeg",
@@ -204,22 +204,15 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
     |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity})
   end
 
-  def user_statuses(%{assigns: %{user: user}} = conn, params) do
-    with %User{ap_id: ap_id} <- Repo.get(User, params["id"]) do
-      params =
-        params
-        |> Map.put("type", ["Create", "Announce"])
-        |> Map.put("actor_id", ap_id)
-        |> Map.put("whole_db", true)
-
-      if params["pinned"] == "true" do
-        # Since Pleroma has no "pinned" posts feature, we'll just set an empty list here
-        activities = []
-      else
-        activities =
-         ActivityPub.fetch_public_activities(params)
-         |> Enum.reverse()
-      end
+  def user_statuses(%{assigns: %{user: reading_user}} = conn, params) do
+    with %User{} = user <- Repo.get(User, params["id"]) do
+      # Since Pleroma has no "pinned" posts feature, we'll just set an empty list here
+      activities =
+        if params["pinned"] == "true" do
+          []
+        else
+          ActivityPub.fetch_user_activities(user, reading_user, params)
+        end
 
       conn
       |> add_link_headers(:user_statuses, activities, params["id"])
@@ -275,7 +268,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
       |> Map.put("in_reply_to_status_id", params["in_reply_to_id"])
       |> Map.put("no_attachment_links", true)
 
-    {:ok, activity} = CommonAPI.post(user, params)
+    idempotency_key =
+      case get_req_header(conn, "idempotency-key") do
+        [key] -> key
+        _ -> Ecto.UUID.generate()
+      end
+
+    {:ok, activity} =
+      Cachex.get!(
+        :idempotency_cache,
+        idempotency_key,
+        fallback: fn _ -> CommonAPI.post(user, params) end
+      )
+
     render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity})
   end
 
@@ -297,7 +302,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
   end
 
   def unreblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
-    with {:ok, %{data: %{"id" => id}}} = CommonAPI.unrepeat(ap_id_or_id, user),
+    with {:ok, _, _, %{data: %{"id" => id}}} = CommonAPI.unrepeat(ap_id_or_id, user),
          %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do
       render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity})
     end
@@ -311,7 +316,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
   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),
+    with {:ok, _, _, %{data: %{"id" => id}}} = CommonAPI.unfavorite(ap_id_or_id, user),
          %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do
       render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity})
     end
@@ -452,24 +457,18 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
     end
   end
 
-  # TODO: Clean up and unify
   def unfollow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
     with %User{} = followed <- Repo.get(User, id),
-         {:ok, follower, follow_activity} <- User.unfollow(follower, followed),
-         {:ok, _activity} <-
-           ActivityPub.insert(%{
-             "type" => "Undo",
-             "actor" => follower.ap_id,
-             # get latest Follow for these users
-             "object" => follow_activity.data["id"]
-           }) do
+         {:ok, _activity} <- ActivityPub.unfollow(follower, followed),
+         {:ok, follower, _} <- User.unfollow(follower, followed) do
       render(conn, AccountView, "relationship.json", %{user: follower, target: followed})
     end
   end
 
   def block(%{assigns: %{user: blocker}} = conn, %{"id" => id}) do
     with %User{} = blocked <- Repo.get(User, id),
-         {:ok, blocker} <- User.block(blocker, blocked) do
+         {:ok, blocker} <- User.block(blocker, blocked),
+         {:ok, _activity} <- ActivityPub.block(blocker, blocked) do
       render(conn, AccountView, "relationship.json", %{user: blocker, target: blocked})
     else
       {:error, message} ->
@@ -481,7 +480,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
 
   def unblock(%{assigns: %{user: blocker}} = conn, %{"id" => id}) do
     with %User{} = blocked <- Repo.get(User, id),
-         {:ok, blocker} <- User.unblock(blocker, blocked) do
+         {:ok, blocker} <- User.unblock(blocker, blocked),
+         {:ok, _activity} <- ActivityPub.unblock(blocker, blocked) do
       render(conn, AccountView, "relationship.json", %{user: blocker, target: blocked})
     else
       {:error, message} ->
@@ -528,7 +528,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
             ^query
           ),
         limit: 20,
-        order_by: [desc: :inserted_at]
+        order_by: [desc: :id]
       )
 
     statuses = Repo.all(q) ++ fetched
@@ -700,7 +700,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
   end
 
   def login_post(conn, %{"authorization" => %{"name" => name, "password" => password}}) do
-    with %User{} = user <- User.get_cached_by_nickname(name),
+    with %User{} = user <- User.get_by_nickname_or_email(name),
          true <- Pbkdf2.checkpw(password, user.password_hash),
          {:ok, app} <- get_or_make_app(),
          {:ok, auth} <- Authorization.create_authorization(app, user),