From b949577472d5e4db1aeacb9ff2162eb89440130c Mon Sep 17 00:00:00 2001 From: Francis Dinh Date: Sat, 14 Apr 2018 03:39:16 -0400 Subject: [PATCH] Add unrepeat functionality --- lib/pleroma/web/activity_pub/activity_pub.ex | 10 ++++++++ lib/pleroma/web/activity_pub/utils.ex | 25 +++++++++++++++++++ lib/pleroma/web/common_api/common_api.ex | 10 ++++++++ .../mastodon_api/mastodon_api_controller.ex | 6 +++++ lib/pleroma/web/router.ex | 1 + lib/pleroma/web/twitter_api/twitter_api.ex | 7 ++++++ .../web/twitter_api/twitter_api_controller.ex | 6 +++++ 7 files changed, 65 insertions(+) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 04b50c1cc..b3154ea99 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -140,6 +140,16 @@ def announce( end end + def unannounce(%User{} = actor, %Object{} = object) do + with %Activity{} = activity <- get_existing_announce(actor.ap_id, object), + {:ok, _activity} <- Repo.delete(activity), + {:ok, object} <- remove_announce_from_object(activity, object) do + {:ok, 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 7a0762e9f..c7c876670 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -239,6 +239,25 @@ def fetch_latest_follow(%User{ap_id: follower_id}, %User{ap_id: followed_id}) do @doc """ Make announce activity data for the given actor and object """ + 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 + def make_announce_data( %User{ap_id: ap_id} = user, %Object{data: %{"id" => id}} = object, @@ -262,6 +281,12 @@ def add_announce_to_object(%Activity{data: %{"actor" => actor}}, object) do 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 21225c3b7..8889b9b42 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -24,6 +24,16 @@ def repeat(id_or_ap_id, user) 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 21a3660c8..1825e156f 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -296,6 +296,12 @@ def reblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do end end + def unreblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do + with {:ok, announce, _activity} = CommonAPI.unrepeat(ap_id_or_id, user) do + render(conn, StatusView, "status.json", %{activity: announce, 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 8ee27e63c..5a32cf7b4 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -110,6 +110,7 @@ def user_fetcher(username) 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..1791feb3a 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -64,6 +64,13 @@ def repeat(%User{} = user, ap_id_or_id) do end end + def unrepeat(%User{} = user, ap_id_or_id) do + with {:ok, _announce, %{data: %{"id" => id}}} = CommonAPI.unrepeat(ap_id_or_id, user), + %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) 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 5f44e46c0..986436326 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -229,6 +229,12 @@ def retweet(%{assigns: %{user: user}} = conn, %{"id" => id}) do end end + def unretweet(%{assigns: %{user: user}} = conn, %{"id" => id}) do + with {:ok, activity} <- TwitterAPI.unrepeat(user, id) do + render(conn, ActivityView, "activity.json", %{activity: activity, for: user}) + end + end + def register(conn, params) do with {:ok, user} <- TwitterAPI.register_user(params) do render(conn, UserView, "show.json", %{user: user})