Merge remote-tracking branch 'origin/develop' into global-status-expiration
[akkoma] / lib / pleroma / web / common_api / common_api.ex
index e5734562145769ab205f3ecd3249b291ea8caf54..6b41c387c72a1f8123b51fee46f5c6145c618d6a 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.CommonAPI do
@@ -10,6 +10,7 @@ defmodule Pleroma.Web.CommonAPI do
   alias Pleroma.Object
   alias Pleroma.ThreadMute
   alias Pleroma.User
+  alias Pleroma.UserRelationship
   alias Pleroma.Web.ActivityPub.ActivityPub
   alias Pleroma.Web.ActivityPub.Utils
   alias Pleroma.Web.ActivityPub.Visibility
@@ -32,7 +33,7 @@ defmodule Pleroma.Web.CommonAPI do
   def unfollow(follower, unfollowed) do
     with {:ok, follower, _follow_activity} <- User.unfollow(follower, unfollowed),
          {:ok, _activity} <- ActivityPub.unfollow(follower, unfollowed),
-         {:ok, _unfollowed} <- User.unsubscribe(follower, unfollowed) do
+         {:ok, _subscription} <- User.unsubscribe(follower, unfollowed) do
       {:ok, follower}
     end
   end
@@ -69,57 +70,89 @@ defmodule Pleroma.Web.CommonAPI do
   end
 
   def delete(activity_id, user) do
-    with %Activity{data: %{"object" => _}} = activity <-
-           Activity.get_by_id_with_object(activity_id),
+    with {_, %Activity{data: %{"object" => _}} = activity} <-
+           {:find_activity, Activity.get_by_id_with_object(activity_id)},
          %Object{} = object <- Object.normalize(activity),
          true <- User.superuser?(user) || user.ap_id == object.data["actor"],
          {:ok, _} <- unpin(activity_id, user),
          {:ok, delete} <- ActivityPub.delete(object) do
       {:ok, delete}
     else
+      {:find_activity, _} -> {:error, :not_found}
       _ -> {:error, dgettext("errors", "Could not delete")}
     end
   end
 
   def repeat(id_or_ap_id, user, params \\ %{}) do
-    with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
+    with {_, %Activity{} = activity} <- {:find_activity, get_by_id_or_ap_id(id_or_ap_id)},
          object <- Object.normalize(activity),
-         nil <- Utils.get_existing_announce(user.ap_id, object),
+         announce_activity <- Utils.get_existing_announce(user.ap_id, object),
          public <- public_announce?(object, params) do
-      ActivityPub.announce(user, object, nil, true, public)
+      if announce_activity do
+        {:ok, announce_activity, object}
+      else
+        ActivityPub.announce(user, object, nil, true, public)
+      end
     else
+      {:find_activity, _} -> {:error, :not_found}
       _ -> {:error, dgettext("errors", "Could not repeat")}
     end
   end
 
   def unrepeat(id_or_ap_id, user) do
-    with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id) do
+    with {_, %Activity{} = activity} <- {:find_activity, get_by_id_or_ap_id(id_or_ap_id)} do
       object = Object.normalize(activity)
       ActivityPub.unannounce(user, object)
     else
+      {:find_activity, _} -> {:error, :not_found}
       _ -> {:error, dgettext("errors", "Could not unrepeat")}
     end
   end
 
   def favorite(id_or_ap_id, user) do
-    with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
+    with {_, %Activity{} = activity} <- {:find_activity, get_by_id_or_ap_id(id_or_ap_id)},
          object <- Object.normalize(activity),
-         nil <- Utils.get_existing_like(user.ap_id, object) do
-      ActivityPub.like(user, object)
+         like_activity <- Utils.get_existing_like(user.ap_id, object) do
+      if like_activity do
+        {:ok, like_activity, object}
+      else
+        ActivityPub.like(user, object)
+      end
     else
+      {:find_activity, _} -> {:error, :not_found}
       _ -> {:error, dgettext("errors", "Could not favorite")}
     end
   end
 
   def unfavorite(id_or_ap_id, user) do
-    with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id) do
+    with {_, %Activity{} = activity} <- {:find_activity, get_by_id_or_ap_id(id_or_ap_id)} do
       object = Object.normalize(activity)
       ActivityPub.unlike(user, object)
     else
+      {:find_activity, _} -> {:error, :not_found}
       _ -> {:error, dgettext("errors", "Could not unfavorite")}
     end
   end
 
+  def react_with_emoji(id, user, emoji) do
+    with %Activity{} = activity <- Activity.get_by_id(id),
+         object <- Object.normalize(activity) do
+      ActivityPub.react_with_emoji(user, object, emoji)
+    else
+      _ ->
+        {:error, dgettext("errors", "Could not add reaction emoji")}
+    end
+  end
+
+  def unreact_with_emoji(id, user, emoji) do
+    with %Activity{} = reaction_activity <- Utils.get_latest_reaction(id, user, emoji) do
+      ActivityPub.unreact_with_emoji(user, reaction_activity.data["id"])
+    else
+      _ ->
+        {:error, dgettext("errors", "Could not remove reaction emoji")}
+    end
+  end
+
   def vote(user, %{data: %{"type" => "Question"}} = object, choices) do
     with :ok <- validate_not_author(object, user),
          :ok <- validate_existing_votes(user, object),
@@ -249,20 +282,10 @@ defmodule Pleroma.Web.CommonAPI do
 
   def post(user, %{"status" => _} = data) do
     with {:ok, draft} <- Pleroma.Web.CommonAPI.ActivityDraft.create(user, data) do
-      draft.changes
-      |> ActivityPub.create(draft.preview?)
-      |> maybe_create_activity_expiration(draft.expires_at)
+      ActivityPub.create(draft.changes, draft.preview?)
     end
   end
 
-  defp maybe_create_activity_expiration({:ok, activity}, %NaiveDateTime{} = expires_at) do
-    with {:ok, _} <- ActivityExpiration.create(activity, expires_at) do
-      {:ok, activity}
-    end
-  end
-
-  defp maybe_create_activity_expiration(result, _), do: result
-
   # Updates the emojis for a user based on their profile
   def update(user) do
     emoji = emoji_from_profile(user)
@@ -287,8 +310,9 @@ defmodule Pleroma.Web.CommonAPI do
     with %Activity{
            actor: ^user_ap_id,
            data: %{"type" => "Create"},
-           object: %Object{data: %{"type" => "Note"}}
+           object: %Object{data: %{"type" => object_type}}
          } = activity <- get_by_id_or_ap_id(id_or_ap_id),
+         true <- object_type in ["Note", "Article", "Question"],
          true <- Visibility.is_public?(activity),
          {:ok, _user} <- User.add_pinnned_activity(user, activity) do
       {:ok, activity}
@@ -351,6 +375,13 @@ defmodule Pleroma.Web.CommonAPI do
     end
   end
 
+  def update_report_state(activity_ids, state) when is_list(activity_ids) do
+    case Utils.update_report_state(activity_ids, state) do
+      :ok -> {:ok, activity_ids}
+      _ -> {:error, dgettext("errors", "Could not update state")}
+    end
+  end
+
   def update_report_state(activity_id, state) do
     with %Activity{} = activity <- Activity.get_by_id(activity_id) do
       Utils.update_report_state(activity, state)
@@ -394,15 +425,11 @@ defmodule Pleroma.Web.CommonAPI do
 
   defp set_visibility(activity, _), do: {:ok, activity}
 
-  def hide_reblogs(user, %{ap_id: ap_id} = _muted) do
-    if ap_id not in user.muted_reblogs do
-      User.add_reblog_mute(user, ap_id)
-    end
+  def hide_reblogs(%User{} = user, %User{} = target) do
+    UserRelationship.create_reblog_mute(user, target)
   end
 
-  def show_reblogs(user, %{ap_id: ap_id} = _muted) do
-    if ap_id in user.muted_reblogs do
-      User.remove_reblog_mute(user, ap_id)
-    end
+  def show_reblogs(%User{} = user, %User{} = target) do
+    UserRelationship.delete_reblog_mute(user, target)
   end
 end