X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Factivity_pub%2Ftransmogrifier.ex;h=c2ced51d813587a6fd6478e63b3f949e12ed6f36;hb=de0fb88a9cf587b9613e267d5dddfe55b0f414b7;hp=5864855b0bb8a8f420ec90c2fa3adc00f4b621ec;hpb=d73c7cc0caf322316541fe8daf72ec34d95e1520;p=akkoma diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 5864855b0..c2ced51d8 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -1,3 +1,7 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + defmodule Pleroma.Web.ActivityPub.Transmogrifier do @moduledoc """ A module to handle coding from internal to wire ActivityPub and back. @@ -37,9 +41,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do @doc """ Checks that an imported AP object's actor matches the domain it came from. """ - def contain_origin(id, %{"actor" => nil}), do: :error + def contain_origin(_id, %{"actor" => nil}), do: :error - def contain_origin(id, %{"actor" => actor} = params) do + def contain_origin(id, %{"actor" => _actor} = params) do id_uri = URI.parse(id) actor_uri = URI.parse(get_actor(params)) @@ -50,9 +54,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end end - def contain_origin_from_id(id, %{"id" => nil}), do: :error + def contain_origin_from_id(_id, %{"id" => nil}), do: :error - def contain_origin_from_id(id, %{"id" => other_id} = params) do + def contain_origin_from_id(id, %{"id" => other_id} = _params) do id_uri = URI.parse(id) other_uri = URI.parse(other_id) @@ -69,8 +73,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def fix_object(object) do object |> fix_actor - |> fix_attachments |> fix_url + |> fix_attachments |> fix_context |> fix_in_reply_to |> fix_emoji @@ -89,12 +93,47 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end end - def fix_addressing(map) do - map + def fix_explicit_addressing(%{"to" => to, "cc" => cc} = object, explicit_mentions) do + explicit_to = + to + |> Enum.filter(fn x -> x in explicit_mentions end) + + explicit_cc = + to + |> Enum.filter(fn x -> x not in explicit_mentions end) + + final_cc = + (cc ++ explicit_cc) + |> Enum.uniq() + + object + |> Map.put("to", explicit_to) + |> Map.put("cc", final_cc) + end + + def fix_explicit_addressing(object, _explicit_mentions), do: object + + # if directMessage flag is set to true, leave the addressing alone + def fix_explicit_addressing(%{"directMessage" => true} = object), do: object + + def fix_explicit_addressing(object) do + explicit_mentions = + object + |> Utils.determine_explicit_mentions() + + explicit_mentions = explicit_mentions ++ ["https://www.w3.org/ns/activitystreams#Public"] + + object + |> fix_explicit_addressing(explicit_mentions) + end + + def fix_addressing(object) do + object |> fix_addressing_list("to") |> fix_addressing_list("cc") |> fix_addressing_list("bto") |> fix_addressing_list("bcc") + |> fix_explicit_addressing end def fix_actor(%{"attributedTo" => actor} = object) do @@ -102,11 +141,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> Map.put("actor", get_actor(%{"actor" => actor})) end - def fix_likes(%{"likes" => likes} = object) - when is_bitstring(likes) do - # Check for standardisation - # This is what Peertube does - # curl -H 'Accept: application/activity+json' $likes | jq .totalItems + # Check for standardisation + # This is what Peertube does + # curl -H 'Accept: application/activity+json' $likes | jq .totalItems + # Prismo returns only an integer (count) as "likes" + def fix_likes(%{"likes" => likes} = object) when not is_map(likes) do object |> Map.put("likes", []) |> Map.put("like_count", 0) @@ -137,7 +176,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do case fetch_obj_helper(in_reply_to_id) do {:ok, replied_object} -> with %Activity{} = activity <- - Activity.get_create_activity_by_object_ap_id(replied_object.data["id"]) do + Activity.get_create_by_object_ap_id(replied_object.data["id"]) do object |> Map.put("inReplyTo", replied_object.data["id"]) |> Map.put("inReplyToAtomUri", object["inReplyToAtomUri"] || in_reply_to_id) @@ -170,8 +209,14 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do attachments = attachment |> Enum.map(fn data -> - url = [%{"type" => "Link", "mediaType" => data["mediaType"], "href" => data["url"]}] - Map.put(data, "url", url) + media_type = data["mediaType"] || data["mimeType"] + href = data["url"] || data["href"] + + url = [%{"type" => "Link", "mediaType" => media_type, "href" => href}] + + data + |> Map.put("mediaType", media_type) + |> Map.put("url", url) end) object @@ -190,7 +235,22 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> Map.put("url", url["href"]) end - def fix_url(%{"url" => url} = object) when is_list(url) do + def fix_url(%{"type" => "Video", "url" => url} = object) when is_list(url) do + first_element = Enum.at(url, 0) + + link_element = + url + |> Enum.filter(fn x -> is_map(x) end) + |> Enum.filter(fn x -> x["mimeType"] == "text/html" end) + |> Enum.at(0) + + object + |> Map.put("attachment", [first_element]) + |> Map.put("url", link_element["href"]) + end + + def fix_url(%{"type" => object_type, "url" => url} = object) + when object_type != "Video" and is_list(url) do first_element = Enum.at(url, 0) url_string = @@ -266,6 +326,32 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def fix_content_map(object), do: object + defp mastodon_follow_hack(%{"id" => id, "actor" => follower_id}, followed) do + with true <- id =~ "follows", + %User{local: true} = follower <- User.get_cached_by_ap_id(follower_id), + %Activity{} = activity <- Utils.fetch_latest_follow(follower, followed) do + {:ok, activity} + else + _ -> {:error, nil} + end + end + + defp mastodon_follow_hack(_, _), do: {:error, nil} + + defp get_follow_activity(follow_object, followed) do + with object_id when not is_nil(object_id) <- Utils.get_ap_id(follow_object), + {_, %Activity{} = activity} <- {:activity, Activity.get_by_ap_id(object_id)} do + {:ok, activity} + else + # Can't find the activity. This might a Mastodon 2.3 "Accept" + {:activity, nil} -> + mastodon_follow_hack(follow_object, followed) + + _ -> + {:error, nil} + end + end + # disallow objects with bogus IDs def handle_incoming(%{"id" => nil}), do: :error def handle_incoming(%{"id" => ""}), do: :error @@ -283,7 +369,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do Map.put(data, "actor", actor) |> fix_addressing - with nil <- Activity.get_create_activity_by_object_ap_id(object["id"]), + with nil <- Activity.get_create_by_object_ap_id(object["id"]), %User{} = user <- User.get_or_fetch_by_ap_id(data["actor"]) do object = fix_object(data["object"]) @@ -297,6 +383,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do additional: Map.take(data, [ "cc", + "directMessage", "id" ]) } @@ -331,34 +418,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end end - defp mastodon_follow_hack(%{"id" => id, "actor" => follower_id}, followed) do - with true <- id =~ "follows", - %User{local: true} = follower <- User.get_cached_by_ap_id(follower_id), - %Activity{} = activity <- Utils.fetch_latest_follow(follower, followed) do - {:ok, activity} - else - _ -> {:error, nil} - end - end - - defp mastodon_follow_hack(_), do: {:error, nil} - - defp get_follow_activity(follow_object, followed) do - with object_id when not is_nil(object_id) <- Utils.get_ap_id(follow_object), - {_, %Activity{} = activity} <- {:activity, Activity.get_by_ap_id(object_id)} do - {:ok, activity} - else - # Can't find the activity. This might a Mastodon 2.3 "Accept" - {:activity, nil} -> - mastodon_follow_hack(follow_object, followed) - - _ -> - {:error, nil} - end - end - def handle_incoming( - %{"type" => "Accept", "object" => follow_object, "actor" => actor, "id" => id} = data + %{"type" => "Accept", "object" => follow_object, "actor" => _actor, "id" => _id} = data ) do with actor <- get_actor(data), %User{} = followed <- User.get_or_fetch_by_ap_id(actor), @@ -374,7 +435,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do local: false }) do if not User.following?(follower, followed) do - {:ok, follower} = User.follow(follower, followed) + {:ok, _follower} = User.follow(follower, followed) end {:ok, activity} @@ -384,7 +445,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end def handle_incoming( - %{"type" => "Reject", "object" => follow_object, "actor" => actor, "id" => id} = data + %{"type" => "Reject", "object" => follow_object, "actor" => _actor, "id" => _id} = data ) do with actor <- get_actor(data), %User{} = followed <- User.get_or_fetch_by_ap_id(actor), @@ -408,7 +469,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end def handle_incoming( - %{"type" => "Like", "object" => object_id, "actor" => actor, "id" => id} = data + %{"type" => "Like", "object" => object_id, "actor" => _actor, "id" => id} = data ) do with actor <- get_actor(data), %User{} = actor <- User.get_or_fetch_by_ap_id(actor), @@ -421,12 +482,13 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end def handle_incoming( - %{"type" => "Announce", "object" => object_id, "actor" => actor, "id" => id} = data + %{"type" => "Announce", "object" => object_id, "actor" => _actor, "id" => id} = data ) 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), - {:ok, activity, _object} <- ActivityPub.announce(actor, object, id, false) do + public <- ActivityPub.is_public?(data), + {:ok, activity, _object} <- ActivityPub.announce(actor, object, id, false, public) do {:ok, activity} else _e -> :error @@ -447,7 +509,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do update_data = new_user_data |> Map.take([:name, :bio, :avatar]) - |> Map.put(:info, Map.merge(actor.info, %{"banner" => banner, "locked" => locked})) + |> Map.put(:info, %{"banner" => banner, "locked" => locked}) actor |> User.upgrade_changeset(update_data) @@ -492,7 +554,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do %{ "type" => "Undo", "object" => %{"type" => "Announce", "object" => object_id}, - "actor" => actor, + "actor" => _actor, "id" => id } = data ) do @@ -520,7 +582,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do User.unfollow(follower, followed) {:ok, activity} else - e -> :error + _e -> :error end end @@ -539,12 +601,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do User.unblock(blocker, blocked) {:ok, activity} else - e -> :error + _e -> :error end end def handle_incoming( - %{"type" => "Block", "object" => blocked, "actor" => blocker, "id" => id} = data + %{"type" => "Block", "object" => blocked, "actor" => blocker, "id" => id} = _data ) do with true <- Pleroma.Config.get([:activitypub, :accept_blocks]), %User{local: true} = blocked = User.get_cached_by_ap_id(blocked), @@ -554,7 +616,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do User.block(blocker, blocked) {:ok, activity} else - e -> :error + _e -> :error end end @@ -562,7 +624,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do %{ "type" => "Undo", "object" => %{"type" => "Like", "object" => object_id}, - "actor" => actor, + "actor" => _actor, "id" => id } = data ) do @@ -604,6 +666,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> add_mention_tags |> add_emoji_tags |> add_attributed_to + |> add_likes |> prepare_attachments |> set_conversation |> set_reply_to_uri @@ -616,7 +679,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do # internal -> Mastodon # """ - def prepare_outgoing(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do + def prepare_outgoing(%{"type" => "Create", "object" => object} = data) do object = object |> prepare_object @@ -763,6 +826,22 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> Map.put("attributedTo", attributedTo) end + def add_likes(%{"id" => id, "like_count" => likes} = object) do + likes = %{ + "id" => "#{id}/likes", + "first" => "#{id}/likes?page=1", + "type" => "OrderedCollection", + "totalItems" => likes + } + + object + |> Map.put("likes", likes) + end + + def add_likes(object) do + object + end + def prepare_attachments(object) do attachments = (object["attachment"] || []) @@ -778,7 +857,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do defp strip_internal_fields(object) do object |> Map.drop([ - "likes", "like_count", "announcements", "announcement_count", @@ -822,15 +900,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do maybe_retire_websub(user.ap_id) - # Only do this for recent activties, don't go through the whole db. - # Only look at the last 1000 activities. - since = (Repo.aggregate(Activity, :max, :id) || 0) - 1_000 - q = from( a in Activity, where: ^old_follower_address in a.recipients, - where: a.id > ^since, update: [ set: [ recipients: @@ -850,10 +923,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def upgrade_user_from_ap_id(ap_id, async \\ true) do with %User{local: false} = user <- User.get_by_ap_id(ap_id), {:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id) do - data = - data - |> Map.put(:info, Map.merge(user.info, data[:info])) - already_ap = User.ap_enabled?(user) {:ok, user} =