Compare commits

...

4 Commits

Author SHA1 Message Date
Haelwenn (lanodan) Monnier
5fb9d5b761
Transmogrifier: Clean out unused functions 2021-07-23 07:10:16 +02:00
Haelwenn (lanodan) Monnier
def4fd9a15
Move Utils json-ld header and date to Builder 2021-07-23 07:10:14 +02:00
Haelwenn (lanodan) Monnier
bb5cc8b390
Ingestion Pipeline: Listen 2021-07-23 06:34:07 +02:00
Haelwenn (lanodan) Monnier
f5fdc5dc63
object_validator: Simplify Add/Remove 2021-07-21 21:03:40 +02:00
16 changed files with 251 additions and 684 deletions

View File

@ -51,23 +51,6 @@ defmodule Pleroma.Object.Fetcher do
end end
end end
defp reinject_object(%Object{} = object, new_data) do
Logger.debug("Reinjecting object #{new_data["id"]}")
with new_data <- Transmogrifier.fix_object(new_data),
data <- maybe_reinject_internal_fields(object, new_data),
changeset <- Object.change(object, %{data: data}),
changeset <- touch_changeset(changeset),
{:ok, object} <- Repo.insert_or_update(changeset),
{:ok, object} <- Object.set_cache(object) do
{:ok, object}
else
e ->
Logger.error("Error while processing object: #{inspect(e)}")
{:error, e}
end
end
def refetch_object(%Object{data: %{"id" => id}} = object) do def refetch_object(%Object{data: %{"id" => id}} = object) do
with {:local, false} <- {:local, Object.local?(object)}, with {:local, false} <- {:local, Object.local?(object)},
{:ok, new_data} <- fetch_and_contain_remote_object_from_id(id), {:ok, new_data} <- fetch_and_contain_remote_object_from_id(id),

View File

@ -20,6 +20,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.Upload alias Pleroma.Upload
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.MRF alias Pleroma.Web.ActivityPub.MRF
alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.Streamer alias Pleroma.Web.Streamer
@ -310,7 +311,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
published = params[:published] published = params[:published]
listen_data = listen_data =
make_listen_data( Builder.listen(
%{to: to, actor: actor, published: published, context: context, object: object}, %{to: to, actor: actor, published: published, context: context, object: object},
additional additional
) )

View File

@ -120,7 +120,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
"to" => recipients, "to" => recipients,
"object" => object, "object" => object,
"type" => "Create", "type" => "Create",
"published" => DateTime.utc_now() |> DateTime.to_iso8601() "published" => date()
} }
|> Pleroma.Maps.put_if_present("context", context), []} |> Pleroma.Maps.put_if_present("context", context), []}
end end
@ -132,7 +132,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
"type" => "ChatMessage", "type" => "ChatMessage",
"to" => [recipient], "to" => [recipient],
"content" => content, "content" => content,
"published" => DateTime.utc_now() |> DateTime.to_iso8601(), "published" => date(),
"emoji" => Emoji.Formatter.get_emoji_map(content) "emoji" => Emoji.Formatter.get_emoji_map(content)
} }
@ -160,7 +160,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
"name" => name, "name" => name,
"inReplyTo" => object.data["id"], "inReplyTo" => object.data["id"],
"context" => object.data["context"], "context" => object.data["context"],
"published" => DateTime.utc_now() |> DateTime.to_iso8601(), "published" => date(),
"id" => Utils.generate_object_id() "id" => Utils.generate_object_id()
}, []} }, []}
end end
@ -240,7 +240,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
"to" => to, "to" => to,
"context" => object.data["context"], "context" => object.data["context"],
"type" => "Announce", "type" => "Announce",
"published" => Utils.make_date() "published" => date()
}, []} }, []}
end end
@ -305,4 +305,33 @@ defmodule Pleroma.Web.ActivityPub.Builder do
defp pinned_url(nickname) when is_binary(nickname) do defp pinned_url(nickname) when is_binary(nickname) do
Pleroma.Web.Router.Helpers.activity_pub_url(Pleroma.Web.Endpoint, :pinned, nickname) Pleroma.Web.Router.Helpers.activity_pub_url(Pleroma.Web.Endpoint, :pinned, nickname)
end end
def listen(params, additional) do
%{
"type" => "Listen",
"id" => Utils.generate_activity_id(),
"to" => params.to |> Enum.uniq(),
"actor" => params.actor.ap_id,
"object" => params.object,
"published" => params.published || date(),
"context" => params.context
}
|> Map.merge(additional)
end
def json_ld_header do
%{
"@context" => [
"https://www.w3.org/ns/activitystreams",
"#{Pleroma.Web.Endpoint.url()}/schemas/litepub-0.1.jsonld",
%{
"@language" => "und"
}
]
}
end
def date do
DateTime.utc_now() |> DateTime.to_iso8601()
end
end end

View File

@ -31,6 +31,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
alias Pleroma.Web.ActivityPub.ObjectValidators.EventValidator alias Pleroma.Web.ActivityPub.ObjectValidators.EventValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator alias Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.ListenValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator alias Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.UpdateValidator alias Pleroma.Web.ActivityPub.ObjectValidators.UpdateValidator
@ -99,6 +100,21 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
end end
def validate( def validate(
%{"type" => "Listen", "object" => %{"type" => "Audio"} = object} = activity,
meta
) do
with {:ok, object_data} <- cast_and_apply(object),
meta = Keyword.put(meta, :object_data, object_data |> stringify_keys),
{:ok, activity} <-
activity
|> ListenValidator.cast_and_validate(meta)
|> Ecto.Changeset.apply_action(:insert) do
activity = stringify_keys(activity)
{:ok, activity, meta}
end
end
def validate(
%{"type" => "Create", "object" => %{"type" => objtype} = object} = create_activity, %{"type" => "Create", "object" => %{"type" => objtype} = object} = create_activity,
meta meta
) )
@ -143,7 +159,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
def validate(%{"type" => type} = object, meta) def validate(%{"type" => type} = object, meta)
when type in ~w[Accept Reject Follow Update Like EmojiReact Announce when type in ~w[Accept Reject Follow Update Like EmojiReact Announce
ChatMessage Answer] do ChatMessage Answer Add Remove] do
validator = validator =
case type do case type do
"Accept" -> AcceptRejectValidator "Accept" -> AcceptRejectValidator
@ -155,6 +171,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
"Announce" -> AnnounceValidator "Announce" -> AnnounceValidator
"ChatMessage" -> ChatMessageValidator "ChatMessage" -> ChatMessageValidator
"Answer" -> AnswerValidator "Answer" -> AnswerValidator
"Add" -> AddRemoveValidator
"Remove" -> AddRemoveValidator
end end
with {:ok, object} <- with {:ok, object} <-
@ -166,16 +184,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
end end
end end
def validate(%{"type" => type} = object, meta) when type in ~w(Add Remove) do
with {:ok, object} <-
object
|> AddRemoveValidator.cast_and_validate()
|> Ecto.Changeset.apply_action(:insert) do
object = stringify_keys(object)
{:ok, object, meta}
end
end
def validate(o, m), do: {:error, {:validator_not_set, {o, m}}} def validate(o, m), do: {:error, {:validator_not_set, {o, m}}}
def cast_and_apply(%{"type" => "ChatMessage"} = object) do def cast_and_apply(%{"type" => "ChatMessage"} = object) do

View File

@ -50,6 +50,12 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioVideoValidator do
field(:likes, {:array, ObjectValidators.ObjectID}, default: []) field(:likes, {:array, ObjectValidators.ObjectID}, default: [])
field(:announcements, {:array, ObjectValidators.ObjectID}, default: []) field(:announcements, {:array, ObjectValidators.ObjectID}, default: [])
# Used by Pleroma's Listen-Audio Scrobbler
field(:title, :string)
field(:artist, :string)
field(:album, :string)
field(:length, :integer)
end end
def cast_and_apply(data) do def cast_and_apply(data) do

View File

@ -0,0 +1,61 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.ListenValidator do
use Ecto.Schema
alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
import Ecto.Changeset
@primary_key false
embedded_schema do
field(:id, ObjectValidators.ObjectID, primary_key: true)
field(:type, :string)
field(:published, ObjectValidators.DateTime)
field(:object, ObjectValidators.ObjectID)
field(:actor, ObjectValidators.ObjectID)
field(:context, :string)
field(:to, ObjectValidators.Recipients, default: [])
field(:cc, ObjectValidators.Recipients, default: [])
field(:bto, ObjectValidators.Recipients, default: [])
field(:bcc, ObjectValidators.Recipients, default: [])
end
def changeset(struct, data) do
struct
|> cast(data, __schema__(:fields))
end
def cast_data(data, meta \\ []) do
data = fix(data, meta)
%__MODULE__{}
|> changeset(data)
end
def cast_and_validate(data, meta \\ []) do
data
|> cast_data(meta)
|> validate_data(meta)
end
defp fix(data, _meta) do
data
|> CommonFixes.fix_actor()
|> CommonFixes.fix_activity_addressing()
end
defp validate_data(data_cng, _meta) do
# TODO: Restrict to Audio objects
data_cng
|> validate_inclusion(:type, ["Listen"])
|> validate_required([:id, :type, :object, :actor, :to, :cc])
|> CommonValidations.validate_actor_presence()
end
end

View File

@ -231,6 +231,18 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
end end
end end
# Tasks this handles
# - Actually create object
# - Rollback if we couldn't create it
@impl true
def handle(%{data: %{"type" => "Listen"}} = activity, meta) do
with {:ok, _object, meta} <- handle_object_creation(meta[:object_data], meta) do
{:ok, activity, meta}
else
e -> Repo.rollback(e)
end
end
# Tasks this handles: # Tasks this handles:
# - Add announce to object # - Add announce to object
# - Set up notification # - Set up notification

View File

@ -10,7 +10,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Maps alias Pleroma.Maps
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Object.Containment
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
@ -27,73 +26,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
require Logger require Logger
require Pleroma.Constants require Pleroma.Constants
@doc """
Modifies an incoming AP object (mastodon format) to our internal format.
"""
def fix_object(object, options \\ []) do
object
|> strip_internal_fields()
|> fix_actor()
|> fix_url()
|> fix_attachments()
|> fix_context()
|> fix_in_reply_to(options)
|> fix_emoji()
|> fix_tag()
|> fix_content_map()
|> fix_addressing()
|> fix_summary()
end
def fix_summary(%{"summary" => nil} = object) do
Map.put(object, "summary", "")
end
def fix_summary(%{"summary" => _} = object) do
# summary is present, nothing to do
object
end
def fix_summary(object), do: Map.put(object, "summary", "")
def fix_addressing_list(map, field) do
addrs = map[field]
cond do
is_list(addrs) ->
Map.put(map, field, Enum.filter(addrs, &is_binary/1))
is_binary(addrs) ->
Map.put(map, field, [addrs])
true ->
Map.put(map, field, [])
end
end
# if directMessage flag is set to true, leave the addressing alone
def fix_explicit_addressing(%{"directMessage" => true} = object, _follower_collection),
do: object
def fix_explicit_addressing(%{"to" => to, "cc" => cc} = object, follower_collection) do
explicit_mentions =
Utils.determine_explicit_mentions(object) ++
[Pleroma.Constants.as_public(), follower_collection]
explicit_to = Enum.filter(to, fn x -> x in explicit_mentions end)
explicit_cc = Enum.filter(to, fn x -> x not in explicit_mentions end)
final_cc =
(cc ++ explicit_cc)
|> Enum.filter(& &1)
|> Enum.reject(fn x -> String.ends_with?(x, "/followers") and x != follower_collection end)
|> Enum.uniq()
object
|> Map.put("to", explicit_to)
|> Map.put("cc", final_cc)
end
# if as:Public is addressed, then make sure the followers collection is also addressed # if as:Public is addressed, then make sure the followers collection is also addressed
# so that the activities will be delivered to local users. # so that the activities will be delivered to local users.
def fix_implicit_addressing(%{"to" => to, "cc" => cc} = object, followers_collection) do def fix_implicit_addressing(%{"to" => to, "cc" => cc} = object, followers_collection) do
@ -117,34 +49,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end end
end end
def fix_addressing(object) do defp fix_in_reply_to(%{"inReplyTo" => in_reply_to} = object, options)
{:ok, %User{follower_address: follower_collection}} = when not is_nil(in_reply_to) do
object
|> Containment.get_actor()
|> User.get_or_fetch_by_ap_id()
object
|> fix_addressing_list("to")
|> fix_addressing_list("cc")
|> fix_addressing_list("bto")
|> fix_addressing_list("bcc")
|> fix_explicit_addressing(follower_collection)
|> fix_implicit_addressing(follower_collection)
end
def fix_actor(%{"attributedTo" => actor} = object) do
actor = Containment.get_actor(%{"actor" => actor})
# TODO: Remove actor field for Objects
object
|> Map.put("actor", actor)
|> Map.put("attributedTo", actor)
end
def fix_in_reply_to(object, options \\ [])
def fix_in_reply_to(%{"inReplyTo" => in_reply_to} = object, options)
when not is_nil(in_reply_to) do
in_reply_to_id = prepare_in_reply_to(in_reply_to) in_reply_to_id = prepare_in_reply_to(in_reply_to)
depth = (options[:depth] || 0) + 1 depth = (options[:depth] || 0) + 1
@ -165,7 +71,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end end
end end
def fix_in_reply_to(object, _options), do: object defp fix_in_reply_to(object, _options), do: object
defp prepare_in_reply_to(in_reply_to) do defp prepare_in_reply_to(in_reply_to) do
cond do cond do
@ -183,100 +89,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end end
end end
def fix_context(object) do
context = object["context"] || object["conversation"] || Utils.generate_context_id()
object
|> Map.put("context", context)
|> Map.drop(["conversation"])
end
def fix_attachments(%{"attachment" => attachment} = object) when is_list(attachment) do
attachments =
Enum.map(attachment, fn data ->
url =
cond do
is_list(data["url"]) -> List.first(data["url"])
is_map(data["url"]) -> data["url"]
true -> nil
end
media_type =
cond do
is_map(url) && MIME.extensions(url["mediaType"]) != [] ->
url["mediaType"]
is_bitstring(data["mediaType"]) && MIME.extensions(data["mediaType"]) != [] ->
data["mediaType"]
is_bitstring(data["mimeType"]) && MIME.extensions(data["mimeType"]) != [] ->
data["mimeType"]
true ->
nil
end
href =
cond do
is_map(url) && is_binary(url["href"]) -> url["href"]
is_binary(data["url"]) -> data["url"]
is_binary(data["href"]) -> data["href"]
true -> nil
end
if href do
attachment_url =
%{
"href" => href,
"type" => Map.get(url || %{}, "type", "Link")
}
|> Maps.put_if_present("mediaType", media_type)
|> Maps.put_if_present("width", (url || %{})["width"] || data["width"])
|> Maps.put_if_present("height", (url || %{})["height"] || data["height"])
%{
"url" => [attachment_url],
"type" => data["type"] || "Document"
}
|> Maps.put_if_present("mediaType", media_type)
|> Maps.put_if_present("name", data["name"])
|> Maps.put_if_present("blurhash", data["blurhash"])
else
nil
end
end)
|> Enum.filter(& &1)
Map.put(object, "attachment", attachments)
end
def fix_attachments(%{"attachment" => attachment} = object) when is_map(attachment) do
object
|> Map.put("attachment", [attachment])
|> fix_attachments()
end
def fix_attachments(object), do: object
def fix_url(%{"url" => url} = object) when is_map(url) do
Map.put(object, "url", url["href"])
end
def fix_url(%{"url" => url} = object) when is_list(url) do
first_element = Enum.at(url, 0)
url_string =
cond do
is_bitstring(first_element) -> first_element
is_map(first_element) -> first_element["href"] || ""
true -> ""
end
Map.put(object, "url", url_string)
end
def fix_url(object), do: object
def fix_emoji(%{"tag" => tags} = object) when is_list(tags) do def fix_emoji(%{"tag" => tags} = object) when is_list(tags) do
emoji = emoji =
tags tags
@ -299,26 +111,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def fix_emoji(object), do: object def fix_emoji(object), do: object
def fix_tag(%{"tag" => tag} = object) when is_list(tag) do
tags =
tag
|> Enum.filter(fn data -> data["type"] == "Hashtag" and data["name"] end)
|> Enum.map(fn
%{"name" => "#" <> hashtag} -> String.downcase(hashtag)
%{"name" => hashtag} -> String.downcase(hashtag)
end)
Map.put(object, "tag", tag ++ tags)
end
def fix_tag(%{"tag" => %{} = tag} = object) do
object
|> Map.put("tag", [tag])
|> fix_tag
end
def fix_tag(object), do: object
# content map usually only has one language so this will do for now. # content map usually only has one language so this will do for now.
def fix_content_map(%{"contentMap" => content_map} = object) do def fix_content_map(%{"contentMap" => content_map} = object) do
content_groups = Map.to_list(content_map) content_groups = Map.to_list(content_map)
@ -384,37 +176,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def handle_incoming(%{"id" => id}, _options) when is_binary(id) and byte_size(id) < 8, def handle_incoming(%{"id" => id}, _options) when is_binary(id) and byte_size(id) < 8,
do: :error do: :error
def handle_incoming(
%{"type" => "Listen", "object" => %{"type" => "Audio"} = object} = data,
options
) do
actor = Containment.get_actor(data)
data =
Map.put(data, "actor", actor)
|> fix_addressing
with {:ok, %User{} = user} <- User.get_or_fetch_by_ap_id(data["actor"]) do
reply_depth = (options[:depth] || 0) + 1
options = Keyword.put(options, :depth, reply_depth)
object = fix_object(object, options)
params = %{
to: data["to"],
object: object,
actor: user,
context: nil,
local: false,
published: data["published"],
additional: Map.take(data, ["cc", "id"])
}
ActivityPub.listen(params)
else
_e -> :error
end
end
@misskey_reactions %{ @misskey_reactions %{
"like" => "👍", "like" => "👍",
"love" => "❤️", "love" => "❤️",
@ -429,7 +190,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
"star" => "" "star" => ""
} }
@doc "Rewrite misskey likes into EmojiReacts" # Rewrite misskey likes into EmojiReacts
def handle_incoming( def handle_incoming(
%{ %{
"type" => "Like", "type" => "Like",
@ -493,6 +254,17 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end end
def handle_incoming( def handle_incoming(
%{"type" => "Listen", "object" => %{"type" => "Audio"}} = data,
_options
) do
with {:ok, %User{}} <- ObjectValidator.fetch_actor(data),
{:ok, activity, _} <-
Pipeline.common_pipeline(data, local: false) do
{:ok, activity}
end
end
def handle_incoming(
%{"type" => "Delete"} = data, %{"type" => "Delete"} = data,
_options _options
) do ) do
@ -595,30 +367,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end end
end end
@spec get_embedded_obj_helper(String.t() | Object.t(), User.t()) :: {:ok, Object.t()} | nil defp set_reply_to_uri(%{"inReplyTo" => in_reply_to} = object) when is_binary(in_reply_to) do
def get_embedded_obj_helper(%{"attributedTo" => attributed_to, "id" => object_id} = data, %User{
ap_id: ap_id
})
when attributed_to == ap_id do
with {:ok, activity} <-
handle_incoming(%{
"type" => "Create",
"to" => data["to"],
"cc" => data["cc"],
"actor" => attributed_to,
"object" => data
}) do
{:ok, Object.normalize(activity, fetch: false)}
else
_ -> get_obj_helper(object_id)
end
end
def get_embedded_obj_helper(object_id, _) do
get_obj_helper(object_id)
end
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"), with false <- String.starts_with?(in_reply_to, "http"),
{:ok, %{data: replied_to_object}} <- get_obj_helper(in_reply_to) do {:ok, %{data: replied_to_object}} <- get_obj_helper(in_reply_to) do
Map.put(object, "inReplyTo", replied_to_object["external_url"] || in_reply_to) Map.put(object, "inReplyTo", replied_to_object["external_url"] || in_reply_to)
@ -627,13 +376,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end end
end end
def set_reply_to_uri(obj), do: obj defp set_reply_to_uri(obj), do: obj
@doc """ # Serialized Mastodon-compatible `replies` collection containing _self-replies_.
Serialized Mastodon-compatible `replies` collection containing _self-replies_. # Based on Mastodon's ActivityPub::NoteSerializer#replies.
Based on Mastodon's ActivityPub::NoteSerializer#replies. defp set_replies(obj_data) do
"""
def set_replies(obj_data) do
replies_uris = replies_uris =
with limit when limit > 0 <- with limit when limit > 0 <-
Pleroma.Config.get([:activitypub, :note_replies_output_limit], 0), Pleroma.Config.get([:activitypub, :note_replies_output_limit], 0),
@ -663,16 +410,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
Map.merge(obj, %{"replies" => replies_collection}) Map.merge(obj, %{"replies" => replies_collection})
end end
def replies(%{"replies" => %{"first" => %{"items" => items}}}) when not is_nil(items) do
items
end
def replies(%{"replies" => %{"items" => items}}) when not is_nil(items) do
items
end
def replies(_), do: []
# Prepares the object of an outgoing create activity. # Prepares the object of an outgoing create activity.
def prepare_object(object) do def prepare_object(object) do
object object
@ -689,11 +426,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> set_type |> set_type
end end
# @doc
# """
# internal -> Mastodon
# """
def prepare_outgoing(%{"type" => activity_type, "object" => object_id} = data) def prepare_outgoing(%{"type" => activity_type, "object" => object_id} = data)
when activity_type in ["Create", "Listen"] do when activity_type in ["Create", "Listen"] do
object = object =
@ -705,7 +437,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
data = data =
data data
|> Map.put("object", object) |> Map.put("object", object)
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Builder.json_ld_header())
|> Map.delete("bcc") |> Map.delete("bcc")
{:ok, data} {:ok, data}
@ -726,7 +458,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
data = data =
data data
|> strip_internal_fields |> strip_internal_fields
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Builder.json_ld_header())
|> Map.delete("bcc") |> Map.delete("bcc")
{:ok, data} {:ok, data}
@ -746,7 +478,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
data = data =
data data
|> Map.put("object", object) |> Map.put("object", object)
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Builder.json_ld_header())
{:ok, data} {:ok, data}
end end
@ -764,7 +496,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
data = data =
data data
|> Map.put("object", object) |> Map.put("object", object)
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Builder.json_ld_header())
{:ok, data} {:ok, data}
end end
@ -775,7 +507,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
data data
|> strip_internal_fields |> strip_internal_fields
|> maybe_fix_object_url |> maybe_fix_object_url
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Builder.json_ld_header())
{:ok, data} {:ok, data}
end end
@ -798,7 +530,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def maybe_fix_object_url(data), do: data def maybe_fix_object_url(data), do: data
def add_hashtags(object) do defp add_hashtags(object) do
tags = tags =
(object["tag"] || []) (object["tag"] || [])
|> Enum.map(fn |> Enum.map(fn
@ -820,7 +552,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
# TODO These should be added on our side on insertion, it doesn't make much # TODO These should be added on our side on insertion, it doesn't make much
# sense to regenerate these all the time # sense to regenerate these all the time
def add_mention_tags(object) do defp add_mention_tags(object) do
to = object["to"] || [] to = object["to"] || []
cc = object["cc"] || [] cc = object["cc"] || []
mentioned = User.get_users_from_set(to ++ cc, local_only: false) mentioned = User.get_users_from_set(to ++ cc, local_only: false)
@ -842,7 +574,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end end
# TODO: we should probably send mtime instead of unix epoch time for updated # TODO: we should probably send mtime instead of unix epoch time for updated
def add_emoji_tags(%{"emoji" => emoji} = object) do defp add_emoji_tags(%{"emoji" => emoji} = object) do
tags = object["tag"] || [] tags = object["tag"] || []
out = Enum.map(emoji, &build_emoji_tag/1) out = Enum.map(emoji, &build_emoji_tag/1)
@ -850,7 +582,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
Map.put(object, "tag", tags ++ out) Map.put(object, "tag", tags ++ out)
end end
def add_emoji_tags(object), do: object defp add_emoji_tags(object), do: object
defp build_emoji_tag({name, url}) do defp build_emoji_tag({name, url}) do
%{ %{
@ -862,25 +594,25 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
} }
end end
def set_conversation(object) do defp set_conversation(object) do
Map.put(object, "conversation", object["context"]) Map.put(object, "conversation", object["context"])
end end
def set_type(%{"type" => "Answer"} = object) do defp set_type(%{"type" => "Answer"} = object) do
Map.put(object, "type", "Note") Map.put(object, "type", "Note")
end end
def set_type(object), do: object defp set_type(object), do: object
def add_attributed_to(object) do defp add_attributed_to(object) do
attributed_to = object["attributedTo"] || object["actor"] attributed_to = object["attributedTo"] || object["actor"]
Map.put(object, "attributedTo", attributed_to) Map.put(object, "attributedTo", attributed_to)
end end
# TODO: Revisit this # TODO: Revisit this
def prepare_attachments(%{"type" => "ChatMessage"} = object), do: object defp prepare_attachments(%{"type" => "ChatMessage"} = object), do: object
def prepare_attachments(object) do defp prepare_attachments(object) do
attachments = attachments =
object object
|> Map.get("attachment", []) |> Map.get("attachment", [])
@ -954,11 +686,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> User.update_and_set_cache() |> User.update_and_set_cache()
end end
def maybe_fix_user_url(%{"url" => url} = data) when is_map(url) do defp maybe_fix_user_url(%{"url" => url} = data) when is_map(url) do
Map.put(data, "url", url["href"]) Map.put(data, "url", url["href"])
end end
def maybe_fix_user_url(data), do: data defp maybe_fix_user_url(data), do: data
def maybe_fix_user_object(data), do: maybe_fix_user_url(data) def maybe_fix_user_object(data), do: maybe_fix_user_url(data)
end end

View File

@ -13,6 +13,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.AdminAPI.AccountView alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.Endpoint alias Pleroma.Web.Endpoint
@ -107,22 +108,6 @@ defmodule Pleroma.Web.ActivityPub.Utils do
end end
end end
def make_json_ld_header do
%{
"@context" => [
"https://www.w3.org/ns/activitystreams",
"#{Endpoint.url()}/schemas/litepub-0.1.jsonld",
%{
"@language" => "und"
}
]
}
end
def make_date do
DateTime.utc_now() |> DateTime.to_iso8601()
end
def generate_activity_id do def generate_activity_id do
generate_id("activities") generate_id("activities")
end end
@ -199,7 +184,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
def lazy_put_activity_defaults(map, true) do def lazy_put_activity_defaults(map, true) do
map map
|> Map.put_new("id", "pleroma:fakeid") |> Map.put_new("id", "pleroma:fakeid")
|> Map.put_new_lazy("published", &make_date/0) |> Map.put_new_lazy("published", &Builder.date/0)
|> Map.put_new("context", "pleroma:fakecontext") |> Map.put_new("context", "pleroma:fakecontext")
|> Map.put_new("context_id", -1) |> Map.put_new("context_id", -1)
|> lazy_put_object_defaults(true) |> lazy_put_object_defaults(true)
@ -210,7 +195,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
map map
|> Map.put_new_lazy("id", &generate_activity_id/0) |> Map.put_new_lazy("id", &generate_activity_id/0)
|> Map.put_new_lazy("published", &make_date/0) |> Map.put_new_lazy("published", &Builder.date/0)
|> Map.put_new("context", context) |> Map.put_new("context", context)
|> Map.put_new("context_id", context_id) |> Map.put_new("context_id", context_id)
|> lazy_put_object_defaults(false) |> lazy_put_object_defaults(false)
@ -224,7 +209,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
object = object =
map map
|> Map.put_new("id", "pleroma:fake_object_id") |> Map.put_new("id", "pleroma:fake_object_id")
|> Map.put_new_lazy("published", &make_date/0) |> Map.put_new_lazy("published", &Builder.date/0)
|> Map.put_new("context", activity["context"]) |> Map.put_new("context", activity["context"])
|> Map.put_new("context_id", activity["context_id"]) |> Map.put_new("context_id", activity["context_id"])
|> Map.put_new("fake", true) |> Map.put_new("fake", true)
@ -237,7 +222,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
object = object =
map map
|> Map.put_new_lazy("id", &generate_object_id/0) |> Map.put_new_lazy("id", &generate_object_id/0)
|> Map.put_new_lazy("published", &make_date/0) |> Map.put_new_lazy("published", &Builder.date/0)
|> Map.put_new("context", activity["context"]) |> Map.put_new("context", activity["context"])
|> Map.put_new("context_id", activity["context_id"]) |> Map.put_new("context_id", activity["context_id"])
@ -662,7 +647,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
#### Create-related helpers #### Create-related helpers
def make_create_data(params, additional) do def make_create_data(params, additional) do
published = params.published || make_date() published = params.published || Builder.date()
%{ %{
"type" => "Create", "type" => "Create",
@ -675,21 +660,6 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|> Map.merge(additional) |> Map.merge(additional)
end end
#### Listen-related helpers
def make_listen_data(params, additional) do
published = params.published || make_date()
%{
"type" => "Listen",
"to" => params.to |> Enum.uniq(),
"actor" => params.actor.ap_id,
"object" => params.object,
"published" => published,
"context" => params.context
}
|> Map.merge(additional)
end
#### Flag-related helpers #### Flag-related helpers
@spec make_flag_data(map(), map()) :: map() @spec make_flag_data(map(), map()) :: map()
def make_flag_data(%{actor: actor, context: context, content: content} = params, additional) do def make_flag_data(%{actor: actor, context: context, content: content} = params, additional) do

View File

@ -6,10 +6,11 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do
use Pleroma.Web, :view use Pleroma.Web, :view
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.ActivityPub.Transmogrifier
def render("object.json", %{object: %Object{} = object}) do def render("object.json", %{object: %Object{} = object}) do
base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header() base = Builder.json_ld_header()
additional = Transmogrifier.prepare_object(object.data) additional = Transmogrifier.prepare_object(object.data)
Map.merge(base, additional) Map.merge(base, additional)
@ -17,7 +18,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do
def render("object.json", %{object: %Activity{data: %{"type" => activity_type}} = activity}) def render("object.json", %{object: %Activity{data: %{"type" => activity_type}} = activity})
when activity_type in ["Create", "Listen"] do when activity_type in ["Create", "Listen"] do
base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header() base = Builder.json_ld_header()
object = Object.normalize(activity, fetch: false) object = Object.normalize(activity, fetch: false)
additional = additional =
@ -28,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do
end end
def render("object.json", %{object: %Activity{} = activity}) do def render("object.json", %{object: %Activity{} = activity}) do
base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header() base = Builder.json_ld_header()
object = Object.normalize(activity, fetch: false) object = Object.normalize(activity, fetch: false)
additional = additional =

View File

@ -9,9 +9,9 @@ defmodule Pleroma.Web.ActivityPub.UserView do
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.ObjectView alias Pleroma.Web.ActivityPub.ObjectView
alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.Endpoint alias Pleroma.Web.Endpoint
alias Pleroma.Web.Router.Helpers alias Pleroma.Web.Router.Helpers
@ -60,7 +60,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"endpoints" => endpoints, "endpoints" => endpoints,
"invisible" => User.invisible?(user) "invisible" => User.invisible?(user)
} }
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Builder.json_ld_header())
end end
# the instance itself is not a Person, but instead an Application # the instance itself is not a Person, but instead an Application
@ -120,7 +120,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
} }
|> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user)) |> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user))
|> Map.merge(maybe_make_image(&User.banner_url/2, "image", user)) |> Map.merge(maybe_make_image(&User.banner_url/2, "image", user))
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Builder.json_ld_header())
end end
def render("following.json", %{user: user, page: page} = opts) do def render("following.json", %{user: user, page: page} = opts) do
@ -139,7 +139,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
end end
collection(following, "#{user.ap_id}/following", page, showing_items, total) collection(following, "#{user.ap_id}/following", page, showing_items, total)
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Builder.json_ld_header())
end end
def render("following.json", %{user: user} = opts) do def render("following.json", %{user: user} = opts) do
@ -168,7 +168,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"#{user.ap_id}/following?page=1" "#{user.ap_id}/following?page=1"
end end
} }
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Builder.json_ld_header())
end end
def render("followers.json", %{user: user, page: page} = opts) do def render("followers.json", %{user: user, page: page} = opts) do
@ -187,7 +187,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
end end
collection(followers, "#{user.ap_id}/followers", page, showing_items, total) collection(followers, "#{user.ap_id}/followers", page, showing_items, total)
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Builder.json_ld_header())
end end
def render("followers.json", %{user: user} = opts) do def render("followers.json", %{user: user} = opts) do
@ -216,7 +216,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
end end
} }
|> maybe_put_total_items(showing_count, total) |> maybe_put_total_items(showing_count, total)
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Builder.json_ld_header())
end end
def render("activity_collection.json", %{iri: iri}) do def render("activity_collection.json", %{iri: iri}) do
@ -225,7 +225,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"type" => "OrderedCollection", "type" => "OrderedCollection",
"first" => "#{iri}?page=true" "first" => "#{iri}?page=true"
} }
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Builder.json_ld_header())
end end
def render("activity_collection_page.json", %{ def render("activity_collection_page.json", %{
@ -244,7 +244,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"partOf" => iri, "partOf" => iri,
"orderedItems" => collection "orderedItems" => collection
} }
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Builder.json_ld_header())
|> Map.merge(pagination) |> Map.merge(pagination)
end end
@ -264,7 +264,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"orderedItems" => objects, "orderedItems" => objects,
"totalItems" => length(objects) "totalItems" => length(objects)
} }
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Builder.json_ld_header())
end end
defp maybe_put_total_items(map, false, _total), do: map defp maybe_put_total_items(map, false, _total), do: map

View File

@ -12,39 +12,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AudioHandlingTest do
import Pleroma.Factory import Pleroma.Factory
test "it works for incoming listens" do
_user = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
data = %{
"@context" => "https://www.w3.org/ns/activitystreams",
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"cc" => [],
"type" => "Listen",
"id" => "http://mastodon.example.org/users/admin/listens/1234/activity",
"actor" => "http://mastodon.example.org/users/admin",
"object" => %{
"type" => "Audio",
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"cc" => [],
"id" => "http://mastodon.example.org/users/admin/listens/1234",
"attributedTo" => "http://mastodon.example.org/users/admin",
"title" => "lain radio episode 1",
"artist" => "lain",
"album" => "lain radio",
"length" => 180_000
}
}
{:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
object = Object.normalize(activity, fetch: false)
assert object.data["title"] == "lain radio episode 1"
assert object.data["artist"] == "lain"
assert object.data["album"] == "lain radio"
assert object.data["length"] == 180_000
end
test "Funkwhale Audio object" do test "Funkwhale Audio object" do
Tesla.Mock.mock(fn Tesla.Mock.mock(fn
%{url: "https://channels.tests.funkwhale.audio/federation/actors/compositions"} -> %{url: "https://channels.tests.funkwhale.audio/federation/actors/compositions"} ->

View File

@ -0,0 +1,59 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.Transmogrifier.ListenHandlingTest do
use Pleroma.DataCase, async: true
alias Pleroma.Activity
alias Pleroma.Object
alias Pleroma.Web.ActivityPub.Transmogrifier
import Pleroma.Factory
test "it works for incoming listens" do
_user = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
audio_data = %{
"type" => "Audio",
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"cc" => [],
"id" => "http://mastodon.example.org/users/admin/listens/1234",
"attributedTo" => "http://mastodon.example.org/users/admin",
"title" => "lain radio episode 1",
"artist" => "lain",
"album" => "lain radio",
"length" => 180_000
}
data = %{
"@context" => "https://www.w3.org/ns/activitystreams",
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"cc" => [],
"type" => "Listen",
"id" => "http://mastodon.example.org/users/admin/listens/1234/activity",
"actor" => "http://mastodon.example.org/users/admin",
"object" => audio_data
}
Tesla.Mock.mock(fn
%{url: "http://mastodon.example.org/users/admin/listens/1234"} ->
%Tesla.Env{
status: 200,
body: audio_data,
headers: HttpRequestMock.activitypub_object_headers()
}
end)
{:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
assert activity.data["type"] == "Listen"
object = Object.normalize(activity, fetch: false)
assert object.data["title"] == "lain radio episode 1"
assert object.data["artist"] == "lain"
assert object.data["album"] == "lain radio"
assert object.data["length"] == 180_000
end
end

View File

@ -499,128 +499,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
end end
end end
describe "fix_in_reply_to/2" do
setup do: clear_config([:instance, :federation_incoming_replies_max_depth])
setup do
data = Jason.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
[data: data]
end
test "returns not modified object when hasn't containts inReplyTo field", %{data: data} do
assert Transmogrifier.fix_in_reply_to(data) == data
end
test "returns object with inReplyTo when denied incoming reply", %{data: data} do
clear_config([:instance, :federation_incoming_replies_max_depth], 0)
object_with_reply =
Map.put(data["object"], "inReplyTo", "https://shitposter.club/notice/2827873")
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
assert modified_object["inReplyTo"] == "https://shitposter.club/notice/2827873"
object_with_reply =
Map.put(data["object"], "inReplyTo", %{"id" => "https://shitposter.club/notice/2827873"})
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
assert modified_object["inReplyTo"] == %{"id" => "https://shitposter.club/notice/2827873"}
object_with_reply =
Map.put(data["object"], "inReplyTo", ["https://shitposter.club/notice/2827873"])
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
assert modified_object["inReplyTo"] == ["https://shitposter.club/notice/2827873"]
object_with_reply = Map.put(data["object"], "inReplyTo", [])
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
assert modified_object["inReplyTo"] == []
end
@tag capture_log: true
test "returns modified object when allowed incoming reply", %{data: data} do
object_with_reply =
Map.put(
data["object"],
"inReplyTo",
"https://mstdn.io/users/mayuutann/statuses/99568293732299394"
)
clear_config([:instance, :federation_incoming_replies_max_depth], 5)
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
assert modified_object["inReplyTo"] ==
"https://mstdn.io/users/mayuutann/statuses/99568293732299394"
assert modified_object["context"] ==
"tag:shitposter.club,2018-02-22:objectType=thread:nonce=e5a7c72d60a9c0e4"
end
end
describe "fix_attachments/1" do
test "returns not modified object" do
data = Jason.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
assert Transmogrifier.fix_attachments(data) == data
end
test "returns modified object when attachment is map" do
assert Transmogrifier.fix_attachments(%{
"attachment" => %{
"mediaType" => "video/mp4",
"url" => "https://peertube.moe/stat-480.mp4"
}
}) == %{
"attachment" => [
%{
"mediaType" => "video/mp4",
"type" => "Document",
"url" => [
%{
"href" => "https://peertube.moe/stat-480.mp4",
"mediaType" => "video/mp4",
"type" => "Link"
}
]
}
]
}
end
test "returns modified object when attachment is list" do
assert Transmogrifier.fix_attachments(%{
"attachment" => [
%{"mediaType" => "video/mp4", "url" => "https://pe.er/stat-480.mp4"},
%{"mimeType" => "video/mp4", "href" => "https://pe.er/stat-480.mp4"}
]
}) == %{
"attachment" => [
%{
"mediaType" => "video/mp4",
"type" => "Document",
"url" => [
%{
"href" => "https://pe.er/stat-480.mp4",
"mediaType" => "video/mp4",
"type" => "Link"
}
]
},
%{
"mediaType" => "video/mp4",
"type" => "Document",
"url" => [
%{
"href" => "https://pe.er/stat-480.mp4",
"mediaType" => "video/mp4",
"type" => "Link"
}
]
}
]
}
end
end
describe "fix_emoji/1" do describe "fix_emoji/1" do
test "returns not modified object when object not contains tags" do test "returns not modified object when object not contains tags" do
data = Jason.decode!(File.read!("test/fixtures/mastodon-post-activity.json")) data = Jason.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
@ -652,48 +530,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
end end
end end
describe "set_replies/1" do
setup do: clear_config([:activitypub, :note_replies_output_limit], 2)
test "returns unmodified object if activity doesn't have self-replies" do
data = Jason.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
assert Transmogrifier.set_replies(data) == data
end
test "sets `replies` collection with a limited number of self-replies" do
[user, another_user] = insert_list(2, :user)
{:ok, %{id: id1} = activity} = CommonAPI.post(user, %{status: "1"})
{:ok, %{id: id2} = self_reply1} =
CommonAPI.post(user, %{status: "self-reply 1", in_reply_to_status_id: id1})
{:ok, self_reply2} =
CommonAPI.post(user, %{status: "self-reply 2", in_reply_to_status_id: id1})
# Assuming to _not_ be present in `replies` due to :note_replies_output_limit is set to 2
{:ok, _} = CommonAPI.post(user, %{status: "self-reply 3", in_reply_to_status_id: id1})
{:ok, _} =
CommonAPI.post(user, %{
status: "self-reply to self-reply",
in_reply_to_status_id: id2
})
{:ok, _} =
CommonAPI.post(another_user, %{
status: "another user's reply",
in_reply_to_status_id: id1
})
object = Object.normalize(activity, fetch: false)
replies_uris = Enum.map([self_reply1, self_reply2], fn a -> a.object.data["id"] end)
assert %{"type" => "Collection", "items" => ^replies_uris} =
Transmogrifier.set_replies(object.data)["replies"]
end
end
test "take_emoji_tags/1" do test "take_emoji_tags/1" do
user = insert(:user, %{emoji: %{"firefox" => "https://example.org/firefox.png"}}) user = insert(:user, %{emoji: %{"firefox" => "https://example.org/firefox.png"}})

View File

@ -10,13 +10,12 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Tests.ObanHelpers alias Pleroma.Tests.ObanHelpers
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.AdminAPI.AccountView alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
import Mock import Mock
import Pleroma.Factory
import ExUnit.CaptureLog import ExUnit.CaptureLog
setup_all do setup_all do
@ -160,7 +159,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
{:ok, activity} = CommonAPI.post(user, %{status: "hey"}) {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
assert modified["@context"] == Utils.make_json_ld_header()["@context"] assert modified["@context"] == Builder.json_ld_header()["@context"]
assert modified["object"]["conversation"] == modified["context"] assert modified["object"]["conversation"] == modified["context"]
end end
@ -424,91 +423,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
end end
end end
describe "fix_explicit_addressing" do
setup do
user = insert(:user)
[user: user]
end
test "moves non-explicitly mentioned actors to cc", %{user: user} do
explicitly_mentioned_actors = [
"https://pleroma.gold/users/user1",
"https://pleroma.gold/user2"
]
object = %{
"actor" => user.ap_id,
"to" => explicitly_mentioned_actors ++ ["https://social.beepboop.ga/users/dirb"],
"cc" => [],
"tag" =>
Enum.map(explicitly_mentioned_actors, fn href ->
%{"type" => "Mention", "href" => href}
end)
}
fixed_object = Transmogrifier.fix_explicit_addressing(object, user.follower_address)
assert Enum.all?(explicitly_mentioned_actors, &(&1 in fixed_object["to"]))
refute "https://social.beepboop.ga/users/dirb" in fixed_object["to"]
assert "https://social.beepboop.ga/users/dirb" in fixed_object["cc"]
end
test "does not move actor's follower collection to cc", %{user: user} do
object = %{
"actor" => user.ap_id,
"to" => [user.follower_address],
"cc" => []
}
fixed_object = Transmogrifier.fix_explicit_addressing(object, user.follower_address)
assert user.follower_address in fixed_object["to"]
refute user.follower_address in fixed_object["cc"]
end
test "removes recipient's follower collection from cc", %{user: user} do
recipient = insert(:user)
object = %{
"actor" => user.ap_id,
"to" => [recipient.ap_id, "https://www.w3.org/ns/activitystreams#Public"],
"cc" => [user.follower_address, recipient.follower_address]
}
fixed_object = Transmogrifier.fix_explicit_addressing(object, user.follower_address)
assert user.follower_address in fixed_object["cc"]
refute recipient.follower_address in fixed_object["cc"]
refute recipient.follower_address in fixed_object["to"]
end
end
describe "fix_summary/1" do
test "returns fixed object" do
assert Transmogrifier.fix_summary(%{"summary" => nil}) == %{"summary" => ""}
assert Transmogrifier.fix_summary(%{"summary" => "ok"}) == %{"summary" => "ok"}
assert Transmogrifier.fix_summary(%{}) == %{"summary" => ""}
end
end
describe "fix_url/1" do
test "fixes data for object when url is map" do
object = %{
"url" => %{
"type" => "Link",
"mimeType" => "video/mp4",
"href" => "https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4"
}
}
assert Transmogrifier.fix_url(object) == %{
"url" => "https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4"
}
end
test "returns non-modified object" do
assert Transmogrifier.fix_url(%{"type" => "Text"}) == %{"type" => "Text"}
end
end
describe "get_obj_helper/2" do describe "get_obj_helper/2" do
test "returns nil when cannot normalize object" do test "returns nil when cannot normalize object" do
assert capture_log(fn -> assert capture_log(fn ->

View File

@ -138,18 +138,6 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
end end
end end
test "make_json_ld_header/0" do
assert Utils.make_json_ld_header() == %{
"@context" => [
"https://www.w3.org/ns/activitystreams",
"http://localhost:4001/schemas/litepub-0.1.jsonld",
%{
"@language" => "und"
}
]
}
end
describe "get_existing_votes" do describe "get_existing_votes" do
test "fetches existing votes" do test "fetches existing votes" do
user = insert(:user) user = insert(:user)