summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex13
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex45
-rw-r--r--lib/pleroma/web/common_api/common_api.ex10
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex7
-rw-r--r--lib/pleroma/web/router.ex1
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api.ex18
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api_controller.ex4
7 files changed, 96 insertions, 2 deletions
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 99c169034..ec161074d 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -145,6 +145,19 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end
+ def unannounce(%User{} = actor, %Object{} = object, local \\ true) do
+ with %Activity{} = activity <- get_existing_announce(actor.ap_id, object),
+ unannounce_data <- make_unannounce_data(actor, activity),
+ {:ok, unannounce_activity} <- insert(unannounce_data, local),
+ :ok <- maybe_federate(activity),
+ {:ok, _activity} <- Repo.delete(activity),
+ {:ok, object} <- remove_announce_from_object(activity, object) do
+ {:ok, unannounce_activity, activity, object}
+ else
+ _e -> {:ok, object}
+ end
+ end
+
def follow(follower, followed, activity_id \\ nil, local \\ true) do
with data <- make_follow_data(follower, followed, activity_id),
{:ok, activity} <- insert(data, local),
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index 7b2bf8fa7..c9d0e45b2 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -238,6 +238,28 @@ defmodule Pleroma.Web.ActivityPub.Utils do
#### Announce-related helpers
@doc """
+ Retruns an existing announce activity if the notice has already been announced
+ """
+ def get_existing_announce(actor, %{data: %{"id" => id}}) do
+ query =
+ from(
+ activity in Activity,
+ where: fragment("(?)->>'actor' = ?", activity.data, ^actor),
+ # this is to use the index
+ where:
+ fragment(
+ "coalesce((?)->'object'->>'id', (?)->>'object') = ?",
+ activity.data,
+ activity.data,
+ ^id
+ ),
+ where: fragment("(?)->>'type' = 'Announce'", activity.data)
+ )
+
+ Repo.one(query)
+ end
+
+ @doc """
Make announce activity data for the given actor and object
"""
def make_announce_data(
@@ -257,12 +279,35 @@ defmodule Pleroma.Web.ActivityPub.Utils do
if activity_id, do: Map.put(data, "id", activity_id), else: data
end
+ @doc """
+ Make unannounce activity data for the given actor and object
+ """
+ def make_unannounce_data(
+ %User{ap_id: ap_id} = user,
+ %Activity{data: %{"id" => id, "context" => context}} = activity
+ ) do
+ %{
+ "type" => "Undo",
+ "actor" => ap_id,
+ "object" => id,
+ "to" => [user.follower_address, activity.data["actor"]],
+ "cc" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "context" => context
+ }
+ end
+
def add_announce_to_object(%Activity{data: %{"actor" => actor}}, object) do
with announcements <- [actor | object.data["announcements"] || []] |> Enum.uniq() do
update_element_in_object("announcement", announcements, object)
end
end
+ def remove_announce_from_object(%Activity{data: %{"actor" => actor}}, object) do
+ with announcements <- (object.data["announcements"] || []) |> List.delete(actor) do
+ update_element_in_object("announcement", announcements, object)
+ end
+ end
+
#### Unfollow-related helpers
def make_unfollow_data(follower, followed, follow_activity) do
diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex
index 2c4b591d4..ef1170010 100644
--- a/lib/pleroma/web/common_api/common_api.ex
+++ b/lib/pleroma/web/common_api/common_api.ex
@@ -24,6 +24,16 @@ defmodule Pleroma.Web.CommonAPI do
end
end
+ def unrepeat(id_or_ap_id, user) do
+ with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
+ object <- Object.get_by_ap_id(activity.data["object"]["id"]) do
+ ActivityPub.unannounce(user, object)
+ else
+ _ ->
+ {:error, "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),
false <- activity.data["actor"] == user.ap_id,
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index c84c226e8..d506c4a41 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -296,6 +296,13 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
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),
+ %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do
+ render(conn, StatusView, "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_activity_by_object_ap_id(id) do
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 8f63fdc70..56dc6533b 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -110,6 +110,7 @@ defmodule Pleroma.Web.Router do
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)
diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex
index c12cd7f8a..5477211dc 100644
--- a/lib/pleroma/web/twitter_api/twitter_api.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api.ex
@@ -12,6 +12,18 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
CommonAPI.post(user, data)
end
+ def delete(%User{} = user, id) do
+ # TwitterAPI does not have an "unretweet" endpoint; instead this is done
+ # via the "destroy" endpoint. Therefore, we need to handle
+ # when the status to "delete" is actually an Announce (repeat) object.
+ with %Activity{data: %{"type" => type}} <- Repo.get(Activity, id) do
+ case type do
+ "Announce" -> unrepeat(user, id)
+ _ -> CommonAPI.delete(id, user)
+ end
+ end
+ end
+
def follow(%User{} = follower, params) do
with {:ok, %User{} = followed} <- get_user(params),
{:ok, follower} <- User.follow(follower, followed),
@@ -64,6 +76,12 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
end
end
+ defp unrepeat(%User{} = user, ap_id_or_id) do
+ with {:ok, _unannounce, activity, _object} <- CommonAPI.unrepeat(ap_id_or_id, user) do
+ {:ok, activity}
+ end
+ end
+
def fav(%User{} = user, ap_id_or_id) do
with {:ok, _announce, %{data: %{"id" => id}}} = CommonAPI.favorite(ap_id_or_id, user),
%Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do
diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
index 6cf8682b8..429a0b7ac 100644
--- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
@@ -157,8 +157,8 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
end
def delete_post(%{assigns: %{user: user}} = conn, %{"id" => id}) do
- with {:ok, delete} <- CommonAPI.delete(id, user) do
- render(conn, ActivityView, "activity.json", %{activity: delete, for: user})
+ with {:ok, activity} <- TwitterAPI.delete(user, id) do
+ render(conn, ActivityView, "activity.json", %{activity: activity, for: user})
end
end