diff options
author | lambda <pleromagit@rogerbraun.net> | 2018-05-24 19:52:24 +0000 |
---|---|---|
committer | lambda <pleromagit@rogerbraun.net> | 2018-05-24 19:52:24 +0000 |
commit | c2dcd767cf4abaa88da946e12ca643840b65e184 (patch) | |
tree | 93d394f2e1fc6d892c1eba85e9b39f9870d2b9b3 /lib | |
parent | 6b9a6838331210dd514d5ecda52783c183bd1bbf (diff) | |
parent | 1197ec10a83c2e61251abe383bea2bcc690d9c09 (diff) | |
download | pleroma-c2dcd767cf4abaa88da946e12ca643840b65e184.tar.gz |
Merge branch 'feature/incoming-remote-unfollow' into 'develop'
Add support for incoming remote unfollows and blocks/unblocks
See merge request pleroma/pleroma!158
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 30 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/transmogrifier.ex | 51 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/utils.ex | 49 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 17 | ||||
-rw-r--r-- | lib/pleroma/web/ostatus/activity_representer.ex | 51 | ||||
-rw-r--r-- | lib/pleroma/web/ostatus/handlers/unfollow_handler.ex | 17 | ||||
-rw-r--r-- | lib/pleroma/web/ostatus/ostatus.ex | 5 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/representers/activity_representer.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api.ex | 15 |
9 files changed, 179 insertions, 58 deletions
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 24b4f045a..8485a8009 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -192,12 +192,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do end end - def unfollow(follower, followed, local \\ true) do + def unfollow(follower, followed, activity_id \\ nil, local \\ true) do with %Activity{} = follow_activity <- fetch_latest_follow(follower, followed), - unfollow_data <- make_unfollow_data(follower, followed, follow_activity), + unfollow_data <- make_unfollow_data(follower, followed, follow_activity, activity_id), {:ok, activity} <- insert(unfollow_data, local), - :ok, - maybe_federate(activity) do + :ok <- maybe_federate(activity) do {:ok, activity} end end @@ -221,6 +220,29 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do end end + def block(blocker, blocked, activity_id \\ nil, local \\ true) do + follow_activity = fetch_latest_follow(blocker, blocked) + + if follow_activity do + unfollow(blocker, blocked, nil, local) + end + + with block_data <- make_block_data(blocker, blocked, activity_id), + {:ok, activity} <- insert(block_data, local), + :ok <- maybe_federate(activity) do + {:ok, activity} + end + end + + def unblock(blocker, blocked, activity_id \\ nil, local \\ true) do + with %Activity{} = block_activity <- fetch_latest_block(blocker, blocked), + unblock_data <- make_unblock_data(blocker, blocked, block_activity, activity_id), + {:ok, activity} <- insert(unblock_data, local), + :ok <- maybe_federate(activity) do + {:ok, activity} + end + end + def fetch_activities_for_context(context, opts \\ %{}) do public = ["https://www.w3.org/ns/activitystreams#Public"] diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 7d6fd8632..803445011 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -244,6 +244,56 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def handle_incoming( %{ "type" => "Undo", + "object" => %{"type" => "Follow", "object" => followed}, + "actor" => follower, + "id" => id + } = _data + ) do + with %User{local: true} = followed <- User.get_cached_by_ap_id(followed), + %User{} = follower <- User.get_or_fetch_by_ap_id(follower), + {:ok, activity} <- ActivityPub.unfollow(follower, followed, id, false) do + User.unfollow(follower, followed) + {:ok, activity} + else + e -> :error + end + end + + def handle_incoming( + %{ + "type" => "Undo", + "object" => %{"type" => "Block", "object" => blocked}, + "actor" => blocker, + "id" => id + } = _data + ) do + with %User{local: true} = blocked <- User.get_cached_by_ap_id(blocked), + %User{} = blocker <- User.get_or_fetch_by_ap_id(blocker), + {:ok, activity} <- ActivityPub.unblock(blocker, blocked, id, false) do + User.unblock(blocker, blocked) + {:ok, activity} + else + e -> :error + end + end + + def handle_incoming( + %{"type" => "Block", "object" => blocked, "actor" => blocker, "id" => id} = data + ) do + with %User{local: true} = blocked = User.get_cached_by_ap_id(blocked), + %User{} = blocker = User.get_or_fetch_by_ap_id(blocker), + {:ok, activity} <- ActivityPub.block(blocker, blocked, id, false) do + User.unfollow(blocker, blocked) + User.block(blocker, blocked) + {:ok, activity} + else + e -> :error + end + end + + def handle_incoming( + %{ + "type" => "Undo", "object" => %{"type" => "Like", "object" => object_id}, "actor" => actor, "id" => id @@ -261,7 +311,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do # TODO # Accept - # Undo for non-Announce def handle_incoming(_), do: :error diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index a3feca480..831e13b7e 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -347,13 +347,56 @@ defmodule Pleroma.Web.ActivityPub.Utils do #### Unfollow-related helpers - def make_unfollow_data(follower, followed, follow_activity) do - %{ + def make_unfollow_data(follower, followed, follow_activity, activity_id) do + data = %{ "type" => "Undo", "actor" => follower.ap_id, "to" => [followed.ap_id], - "object" => follow_activity.data["id"] + "object" => follow_activity.data + } + + if activity_id, do: Map.put(data, "id", activity_id), else: data + end + + #### Block-related helpers + def fetch_latest_block(%User{ap_id: blocker_id}, %User{ap_id: blocked_id}) do + query = + from( + activity in Activity, + where: + fragment( + "? @> ?", + activity.data, + ^%{type: "Block", object: blocked_id} + ), + where: activity.actor == ^blocker_id, + order_by: [desc: :id], + limit: 1 + ) + + Repo.one(query) + end + + def make_block_data(blocker, blocked, activity_id) do + data = %{ + "type" => "Block", + "actor" => blocker.ap_id, + "to" => [blocked.ap_id], + "object" => blocked.ap_id + } + + if activity_id, do: Map.put(data, "id", activity_id), else: data + end + + def make_unblock_data(blocker, blocked, block_activity, activity_id) do + data = %{ + "type" => "Undo", + "actor" => blocker.ap_id, + "to" => [blocked.ap_id], + "object" => block_activity.data } + + if activity_id, do: Map.put(data, "id", activity_id), else: data end #### Create-related helpers diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index e6365620e..2c0277124 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -453,24 +453,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} -> @@ -482,7 +476,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} -> diff --git a/lib/pleroma/web/ostatus/activity_representer.ex b/lib/pleroma/web/ostatus/activity_representer.ex index 64cadba1b..4179d86c9 100644 --- a/lib/pleroma/web/ostatus/activity_representer.ex +++ b/lib/pleroma/web/ostatus/activity_representer.ex @@ -232,7 +232,12 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenter do end # Only undos of follow for now. Will need to get redone once there are more - def to_simple_form(%{data: %{"type" => "Undo"}} = activity, user, with_author) do + def to_simple_form( + %{data: %{"type" => "Undo", "object" => %{"type" => "Follow"} = follow_activity}} = + activity, + user, + with_author + ) do h = fn str -> [to_charlist(str)] end updated_at = activity.data["published"] @@ -240,34 +245,26 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenter do author = if with_author, do: [{:author, UserRepresenter.to_simple_form(user)}], else: [] - follow_activity = - if is_map(activity.data["object"]) do - Activity.get_by_ap_id(activity.data["object"]["id"]) - else - Activity.get_by_ap_id(activity.data["object"]) - end - mentions = (activity.recipients || []) |> get_mentions + follow_activity = Activity.get_by_ap_id(follow_activity["id"]) - if follow_activity do - [ - {:"activity:object-type", ['http://activitystrea.ms/schema/1.0/activity']}, - {:"activity:verb", ['http://activitystrea.ms/schema/1.0/unfollow']}, - {:id, h.(activity.data["id"])}, - {:title, ['#{user.nickname} stopped following #{follow_activity.data["object"]}']}, - {:content, [type: 'html'], - ['#{user.nickname} stopped following #{follow_activity.data["object"]}']}, - {:published, h.(inserted_at)}, - {:updated, h.(updated_at)}, - {:"activity:object", - [ - {:"activity:object-type", ['http://activitystrea.ms/schema/1.0/person']}, - {:id, h.(follow_activity.data["object"])}, - {:uri, h.(follow_activity.data["object"])} - ]}, - {:link, [rel: 'self', type: ['application/atom+xml'], href: h.(activity.data["id"])], []} - ] ++ mentions ++ author - end + [ + {:"activity:object-type", ['http://activitystrea.ms/schema/1.0/activity']}, + {:"activity:verb", ['http://activitystrea.ms/schema/1.0/unfollow']}, + {:id, h.(activity.data["id"])}, + {:title, ['#{user.nickname} stopped following #{follow_activity.data["object"]}']}, + {:content, [type: 'html'], + ['#{user.nickname} stopped following #{follow_activity.data["object"]}']}, + {:published, h.(inserted_at)}, + {:updated, h.(updated_at)}, + {:"activity:object", + [ + {:"activity:object-type", ['http://activitystrea.ms/schema/1.0/person']}, + {:id, h.(follow_activity.data["object"])}, + {:uri, h.(follow_activity.data["object"])} + ]}, + {:link, [rel: 'self', type: ['application/atom+xml'], href: h.(activity.data["id"])], []} + ] ++ mentions ++ author end def to_simple_form(%{data: %{"type" => "Delete"}} = activity, user, with_author) do diff --git a/lib/pleroma/web/ostatus/handlers/unfollow_handler.ex b/lib/pleroma/web/ostatus/handlers/unfollow_handler.ex new file mode 100644 index 000000000..a115bf4c8 --- /dev/null +++ b/lib/pleroma/web/ostatus/handlers/unfollow_handler.ex @@ -0,0 +1,17 @@ +defmodule Pleroma.Web.OStatus.UnfollowHandler do + alias Pleroma.Web.{XML, OStatus} + alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.User + + def handle(entry, doc) do + with {:ok, actor} <- OStatus.find_make_or_update_user(doc), + id when not is_nil(id) <- XML.string_from_xpath("/entry/id", entry), + followed_uri when not is_nil(followed_uri) <- + XML.string_from_xpath("/entry/activity:object/id", entry), + {:ok, followed} <- OStatus.find_or_make_user(followed_uri), + {:ok, activity} <- ActivityPub.unfollow(actor, followed, id, false) do + User.unfollow(actor, followed) + {:ok, activity} + end + end +end diff --git a/lib/pleroma/web/ostatus/ostatus.ex b/lib/pleroma/web/ostatus/ostatus.ex index 5c4a1fd69..f0ff0624f 100644 --- a/lib/pleroma/web/ostatus/ostatus.ex +++ b/lib/pleroma/web/ostatus/ostatus.ex @@ -8,7 +8,7 @@ defmodule Pleroma.Web.OStatus do alias Pleroma.{Repo, User, Web, Object, Activity} alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.{WebFinger, Websub} - alias Pleroma.Web.OStatus.{FollowHandler, NoteHandler, DeleteHandler} + alias Pleroma.Web.OStatus.{FollowHandler, UnfollowHandler, NoteHandler, DeleteHandler} alias Pleroma.Web.ActivityPub.Transmogrifier def feed_path(user) do @@ -47,6 +47,9 @@ defmodule Pleroma.Web.OStatus do 'http://activitystrea.ms/schema/1.0/follow' -> with {:ok, activity} <- FollowHandler.handle(entry, doc), do: activity + 'http://activitystrea.ms/schema/1.0/unfollow' -> + with {:ok, activity} <- UnfollowHandler.handle(entry, doc), do: activity + 'http://activitystrea.ms/schema/1.0/share' -> with {:ok, activity, retweeted_activity} <- handle_share(entry, doc), do: [activity, retweeted_activity] diff --git a/lib/pleroma/web/twitter_api/representers/activity_representer.ex b/lib/pleroma/web/twitter_api/representers/activity_representer.ex index c2e1f07a5..57837205e 100644 --- a/lib/pleroma/web/twitter_api/representers/activity_representer.ex +++ b/lib/pleroma/web/twitter_api/representers/activity_representer.ex @@ -99,7 +99,7 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do ) do created_at = created_at |> Utils.date_to_asctime() - text = "#{user.nickname} undid the action at #{undid_activity}" + text = "#{user.nickname} undid the action at #{undid_activity["id"]}" %{ "id" => activity.id, diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index 722e436e2..3ccdaed6f 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -36,14 +36,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do def unfollow(%User{} = follower, params) do with {:ok, %User{} = unfollowed} <- get_user(params), {:ok, follower, follow_activity} <- User.unfollow(follower, unfollowed), - {:ok, _activity} <- - ActivityPub.insert(%{ - "type" => "Undo", - "actor" => follower.ap_id, - # get latest Follow for these users - "object" => follow_activity.data["id"], - "published" => make_date() - }) do + {:ok, _activity} <- ActivityPub.unfollow(follower, unfollowed) do {:ok, follower, unfollowed} else err -> err @@ -52,7 +45,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do def block(%User{} = blocker, params) do with {:ok, %User{} = blocked} <- get_user(params), - {:ok, blocker} <- User.block(blocker, blocked) do + {:ok, blocker} <- User.block(blocker, blocked), + {:ok, _activity} <- ActivityPub.block(blocker, blocked) do {:ok, blocker, blocked} else err -> err @@ -61,7 +55,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do def unblock(%User{} = blocker, params) do with {:ok, %User{} = blocked} <- get_user(params), - {:ok, blocker} <- User.unblock(blocker, blocked) do + {:ok, blocker} <- User.unblock(blocker, blocked), + {:ok, _activity} <- ActivityPub.unblock(blocker, blocked) do {:ok, blocker, blocked} else err -> err |