diff options
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 | 
