X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Factivity_pub%2Ftransmogrifier.ex;h=9d536f7f5fd9bbb381cabb536267e3e3952b8d7f;hb=d487b753c3116e7a4261404b2357f337acc2d64d;hp=c2ced51d813587a6fd6478e63b3f949e12ed6f36;hpb=d03a116654bd7c4329b698a0f175e37aea8c2caa;p=akkoma diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index c2ced51d8..9d536f7f5 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -6,12 +6,13 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do @moduledoc """ A module to handle coding from internal to wire ActivityPub and back. """ - alias Pleroma.User - alias Pleroma.Object alias Pleroma.Activity + alias Pleroma.Object alias Pleroma.Repo + alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Utils + alias Pleroma.Web.ActivityPub.Visibility import Ecto.Query @@ -85,11 +86,15 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end def fix_addressing_list(map, field) do - if is_binary(map[field]) do - map - |> Map.put(field, [map[field]]) - else - map + cond do + is_binary(map[field]) -> + Map.put(map, field, [map[field]]) + + is_nil(map[field]) -> + Map.put(map, field, []) + + true -> + map end end @@ -127,13 +132,42 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> fix_explicit_addressing(explicit_mentions) end + # if as:Public is addressed, then make sure the followers collection is also addressed + # so that the activities will be delivered to local users. + def fix_implicit_addressing(%{"to" => to, "cc" => cc} = object, followers_collection) do + recipients = to ++ cc + + if followers_collection not in recipients do + cond do + "https://www.w3.org/ns/activitystreams#Public" in cc -> + to = to ++ [followers_collection] + Map.put(object, "to", to) + + "https://www.w3.org/ns/activitystreams#Public" in to -> + cc = cc ++ [followers_collection] + Map.put(object, "cc", cc) + + true -> + object + end + else + object + end + end + + def fix_implicit_addressing(object, _), do: object + def fix_addressing(object) do + %User{} = user = User.get_cached_by_ap_id(object["actor"]) + followers_collection = User.ap_followers(user) + object |> fix_addressing_list("to") |> fix_addressing_list("cc") |> fix_addressing_list("bto") |> fix_addressing_list("bcc") |> fix_explicit_addressing + |> fix_implicit_addressing(followers_collection) end def fix_actor(%{"attributedTo" => actor} = object) do @@ -313,6 +347,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> Map.put("tag", combined) end + def fix_tag(%{"tag" => %{} = tag} = object), do: Map.put(object, "tag", [tag]) + def fix_tag(object), do: object # content map usually only has one language so this will do for now. @@ -352,6 +388,40 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end end + # Flag objects are placed ahead of the ID check because Mastodon 2.8 and earlier send them + # with nil ID. + def handle_incoming(%{"type" => "Flag", "object" => objects, "actor" => actor} = data) do + with context <- data["context"] || Utils.generate_context_id(), + content <- data["content"] || "", + %User{} = actor <- User.get_cached_by_ap_id(actor), + + # Reduce the object list to find the reported user. + %User{} = account <- + Enum.reduce_while(objects, nil, fn ap_id, _ -> + with %User{} = user <- User.get_cached_by_ap_id(ap_id) do + {:halt, user} + else + _ -> {:cont, nil} + end + end), + + # Remove the reported user from the object list. + statuses <- Enum.filter(objects, fn ap_id -> ap_id != account.ap_id end) do + params = %{ + actor: actor, + context: context, + account: account, + statuses: statuses, + content: content, + additional: %{ + "cc" => [account.ap_id] + } + } + + ActivityPub.flag(params) + end + end + # disallow objects with bogus IDs def handle_incoming(%{"id" => nil}), do: :error def handle_incoming(%{"id" => ""}), do: :error @@ -404,7 +474,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do if not User.locked?(followed) do ActivityPub.accept(%{ to: [follower.ap_id], - actor: followed.ap_id, + actor: followed, object: data, local: true }) @@ -430,7 +500,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do ActivityPub.accept(%{ to: follow_activity.data["to"], type: "Accept", - actor: followed.ap_id, + actor: followed, object: follow_activity.data["id"], local: false }) do @@ -453,10 +523,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "reject"), %User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]), {:ok, activity} <- - ActivityPub.accept(%{ + ActivityPub.reject(%{ to: follow_activity.data["to"], - type: "Accept", - actor: followed.ap_id, + type: "Reject", + actor: followed, object: follow_activity.data["id"], local: false }) do @@ -487,7 +557,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do with actor <- get_actor(data), %User{} = actor <- User.get_or_fetch_by_ap_id(actor), {:ok, object} <- get_obj_helper(object_id) || fetch_obj_helper(object_id), - public <- ActivityPub.is_public?(data), + public <- Visibility.is_public?(data), {:ok, activity, _object} <- ActivityPub.announce(actor, object, id, false, public) do {:ok, activity} else @@ -647,10 +717,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do if object = Object.normalize(id), do: {:ok, object}, else: nil end - def set_reply_to_uri(%{"inReplyTo" => inReplyTo} = object) do - with false <- String.starts_with?(inReplyTo, "http"), - {:ok, %{data: replied_to_object}} <- get_obj_helper(inReplyTo) do - Map.put(object, "inReplyTo", replied_to_object["external_url"] || inReplyTo) + def set_reply_to_uri(%{"inReplyTo" => in_reply_to} = object) when is_binary(in_reply_to) do + with false <- String.starts_with?(in_reply_to, "http"), + {:ok, %{data: replied_to_object}} <- get_obj_helper(in_reply_to) do + Map.put(object, "inReplyTo", replied_to_object["external_url"] || in_reply_to) else _e -> object end @@ -733,6 +803,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def prepare_outgoing(%{"type" => _type} = data) do data = data + |> strip_internal_fields |> maybe_fix_object_url |> Map.merge(Utils.make_json_ld_header()) @@ -763,12 +834,18 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def add_hashtags(object) do tags = (object["tag"] || []) - |> Enum.map(fn tag -> - %{ - "href" => Pleroma.Web.Endpoint.url() <> "/tags/#{tag}", - "name" => "##{tag}", - "type" => "Hashtag" - } + |> Enum.map(fn + # Expand internal representation tags into AS2 tags. + tag when is_binary(tag) -> + %{ + "href" => Pleroma.Web.Endpoint.url() <> "/tags/#{tag}", + "name" => "##{tag}", + "type" => "Hashtag" + } + + # Do not process tags which are already AS2 tag objects. + tag when is_map(tag) -> + tag end) object @@ -820,10 +897,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end def add_attributed_to(object) do - attributedTo = object["attributedTo"] || object["actor"] + attributed_to = object["attributedTo"] || object["actor"] object - |> Map.put("attributedTo", attributedTo) + |> Map.put("attributedTo", attributed_to) end def add_likes(%{"id" => id, "like_count" => likes} = object) do @@ -861,7 +938,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do "announcements", "announcement_count", "emoji", - "context_id" + "context_id", + "deleted_activity_id" ]) end