Compare commits
4 Commits
feature/sa
...
chores/non
Author | SHA1 | Date | |
---|---|---|---|
|
5fb9d5b761 | ||
|
def4fd9a15 | ||
|
bb5cc8b390 | ||
|
f5fdc5dc63 |
@ -51,23 +51,6 @@ defmodule Pleroma.Object.Fetcher do
|
||||
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
|
||||
with {:local, false} <- {:local, Object.local?(object)},
|
||||
{:ok, new_data} <- fetch_and_contain_remote_object_from_id(id),
|
||||
|
@ -20,6 +20,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Upload
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Builder
|
||||
alias Pleroma.Web.ActivityPub.MRF
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.Streamer
|
||||
@ -310,7 +311,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
published = params[:published]
|
||||
|
||||
listen_data =
|
||||
make_listen_data(
|
||||
Builder.listen(
|
||||
%{to: to, actor: actor, published: published, context: context, object: object},
|
||||
additional
|
||||
)
|
||||
|
@ -120,7 +120,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
|
||||
"to" => recipients,
|
||||
"object" => object,
|
||||
"type" => "Create",
|
||||
"published" => DateTime.utc_now() |> DateTime.to_iso8601()
|
||||
"published" => date()
|
||||
}
|
||||
|> Pleroma.Maps.put_if_present("context", context), []}
|
||||
end
|
||||
@ -132,7 +132,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
|
||||
"type" => "ChatMessage",
|
||||
"to" => [recipient],
|
||||
"content" => content,
|
||||
"published" => DateTime.utc_now() |> DateTime.to_iso8601(),
|
||||
"published" => date(),
|
||||
"emoji" => Emoji.Formatter.get_emoji_map(content)
|
||||
}
|
||||
|
||||
@ -160,7 +160,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
|
||||
"name" => name,
|
||||
"inReplyTo" => object.data["id"],
|
||||
"context" => object.data["context"],
|
||||
"published" => DateTime.utc_now() |> DateTime.to_iso8601(),
|
||||
"published" => date(),
|
||||
"id" => Utils.generate_object_id()
|
||||
}, []}
|
||||
end
|
||||
@ -240,7 +240,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
|
||||
"to" => to,
|
||||
"context" => object.data["context"],
|
||||
"type" => "Announce",
|
||||
"published" => Utils.make_date()
|
||||
"published" => date()
|
||||
}, []}
|
||||
end
|
||||
|
||||
@ -305,4 +305,33 @@ defmodule Pleroma.Web.ActivityPub.Builder do
|
||||
defp pinned_url(nickname) when is_binary(nickname) do
|
||||
Pleroma.Web.Router.Helpers.activity_pub_url(Pleroma.Web.Endpoint, :pinned, nickname)
|
||||
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
|
||||
|
@ -31,6 +31,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.EventValidator
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.ListenValidator
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.UpdateValidator
|
||||
@ -99,6 +100,21 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
|
||||
end
|
||||
|
||||
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,
|
||||
meta
|
||||
)
|
||||
@ -143,7 +159,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
|
||||
|
||||
def validate(%{"type" => type} = object, meta)
|
||||
when type in ~w[Accept Reject Follow Update Like EmojiReact Announce
|
||||
ChatMessage Answer] do
|
||||
ChatMessage Answer Add Remove] do
|
||||
validator =
|
||||
case type do
|
||||
"Accept" -> AcceptRejectValidator
|
||||
@ -155,6 +171,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
|
||||
"Announce" -> AnnounceValidator
|
||||
"ChatMessage" -> ChatMessageValidator
|
||||
"Answer" -> AnswerValidator
|
||||
"Add" -> AddRemoveValidator
|
||||
"Remove" -> AddRemoveValidator
|
||||
end
|
||||
|
||||
with {:ok, object} <-
|
||||
@ -166,16 +184,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
|
||||
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 cast_and_apply(%{"type" => "ChatMessage"} = object) do
|
||||
|
@ -50,6 +50,12 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioVideoValidator do
|
||||
|
||||
field(:likes, {: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
|
||||
|
||||
def cast_and_apply(data) do
|
||||
|
@ -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
|
@ -231,6 +231,18 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
||||
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:
|
||||
# - Add announce to object
|
||||
# - Set up notification
|
||||
|
@ -10,7 +10,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
alias Pleroma.EctoType.ActivityPub.ObjectValidators
|
||||
alias Pleroma.Maps
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Object.Containment
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
@ -27,73 +26,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
require Logger
|
||||
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
|
||||
# so that the activities will be delivered to local users.
|
||||
def fix_implicit_addressing(%{"to" => to, "cc" => cc} = object, followers_collection) do
|
||||
@ -117,33 +49,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
end
|
||||
end
|
||||
|
||||
def fix_addressing(object) do
|
||||
{:ok, %User{follower_address: follower_collection}} =
|
||||
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)
|
||||
defp 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)
|
||||
depth = (options[:depth] || 0) + 1
|
||||
@ -165,7 +71,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
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
|
||||
cond do
|
||||
@ -183,100 +89,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
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
|
||||
emoji =
|
||||
tags
|
||||
@ -299,26 +111,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
|
||||
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.
|
||||
def fix_content_map(%{"contentMap" => content_map} = object) do
|
||||
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,
|
||||
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 %{
|
||||
"like" => "👍",
|
||||
"love" => "❤️",
|
||||
@ -429,7 +190,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
"star" => "⭐"
|
||||
}
|
||||
|
||||
@doc "Rewrite misskey likes into EmojiReacts"
|
||||
# Rewrite misskey likes into EmojiReacts
|
||||
def handle_incoming(
|
||||
%{
|
||||
"type" => "Like",
|
||||
@ -493,6 +254,17 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
end
|
||||
|
||||
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,
|
||||
_options
|
||||
) do
|
||||
@ -595,30 +367,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
end
|
||||
end
|
||||
|
||||
@spec get_embedded_obj_helper(String.t() | Object.t(), User.t()) :: {:ok, Object.t()} | nil
|
||||
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
|
||||
defp 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)
|
||||
@ -627,13 +376,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
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_.
|
||||
Based on Mastodon's ActivityPub::NoteSerializer#replies.
|
||||
"""
|
||||
def set_replies(obj_data) do
|
||||
# Serialized Mastodon-compatible `replies` collection containing _self-replies_.
|
||||
# Based on Mastodon's ActivityPub::NoteSerializer#replies.
|
||||
defp set_replies(obj_data) do
|
||||
replies_uris =
|
||||
with limit when 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})
|
||||
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.
|
||||
def prepare_object(object) do
|
||||
object
|
||||
@ -689,11 +426,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
|> set_type
|
||||
end
|
||||
|
||||
# @doc
|
||||
# """
|
||||
# internal -> Mastodon
|
||||
# """
|
||||
|
||||
def prepare_outgoing(%{"type" => activity_type, "object" => object_id} = data)
|
||||
when activity_type in ["Create", "Listen"] do
|
||||
object =
|
||||
@ -705,7 +437,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
data =
|
||||
data
|
||||
|> Map.put("object", object)
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
|> Map.merge(Builder.json_ld_header())
|
||||
|> Map.delete("bcc")
|
||||
|
||||
{:ok, data}
|
||||
@ -726,7 +458,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
data =
|
||||
data
|
||||
|> strip_internal_fields
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
|> Map.merge(Builder.json_ld_header())
|
||||
|> Map.delete("bcc")
|
||||
|
||||
{:ok, data}
|
||||
@ -746,7 +478,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
data =
|
||||
data
|
||||
|> Map.put("object", object)
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
|> Map.merge(Builder.json_ld_header())
|
||||
|
||||
{:ok, data}
|
||||
end
|
||||
@ -764,7 +496,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
data =
|
||||
data
|
||||
|> Map.put("object", object)
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
|> Map.merge(Builder.json_ld_header())
|
||||
|
||||
{:ok, data}
|
||||
end
|
||||
@ -775,7 +507,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
data
|
||||
|> strip_internal_fields
|
||||
|> maybe_fix_object_url
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
|> Map.merge(Builder.json_ld_header())
|
||||
|
||||
{:ok, data}
|
||||
end
|
||||
@ -798,7 +530,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
|
||||
def maybe_fix_object_url(data), do: data
|
||||
|
||||
def add_hashtags(object) do
|
||||
defp add_hashtags(object) do
|
||||
tags =
|
||||
(object["tag"] || [])
|
||||
|> 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
|
||||
# sense to regenerate these all the time
|
||||
def add_mention_tags(object) do
|
||||
defp add_mention_tags(object) do
|
||||
to = object["to"] || []
|
||||
cc = object["cc"] || []
|
||||
mentioned = User.get_users_from_set(to ++ cc, local_only: false)
|
||||
@ -842,7 +574,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
end
|
||||
|
||||
# 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"] || []
|
||||
|
||||
out = Enum.map(emoji, &build_emoji_tag/1)
|
||||
@ -850,7 +582,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
Map.put(object, "tag", tags ++ out)
|
||||
end
|
||||
|
||||
def add_emoji_tags(object), do: object
|
||||
defp add_emoji_tags(object), do: object
|
||||
|
||||
defp build_emoji_tag({name, url}) do
|
||||
%{
|
||||
@ -862,25 +594,25 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
}
|
||||
end
|
||||
|
||||
def set_conversation(object) do
|
||||
defp set_conversation(object) do
|
||||
Map.put(object, "conversation", object["context"])
|
||||
end
|
||||
|
||||
def set_type(%{"type" => "Answer"} = object) do
|
||||
defp set_type(%{"type" => "Answer"} = object) do
|
||||
Map.put(object, "type", "Note")
|
||||
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"]
|
||||
Map.put(object, "attributedTo", attributed_to)
|
||||
end
|
||||
|
||||
# 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 =
|
||||
object
|
||||
|> Map.get("attachment", [])
|
||||
@ -954,11 +686,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
|> User.update_and_set_cache()
|
||||
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"])
|
||||
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)
|
||||
end
|
||||
|
@ -13,6 +13,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Builder
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.AdminAPI.AccountView
|
||||
alias Pleroma.Web.Endpoint
|
||||
@ -107,22 +108,6 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||
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
|
||||
generate_id("activities")
|
||||
end
|
||||
@ -199,7 +184,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||
def lazy_put_activity_defaults(map, true) do
|
||||
map
|
||||
|> 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_id", -1)
|
||||
|> lazy_put_object_defaults(true)
|
||||
@ -210,7 +195,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||
|
||||
map
|
||||
|> 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_id", context_id)
|
||||
|> lazy_put_object_defaults(false)
|
||||
@ -224,7 +209,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||
object =
|
||||
map
|
||||
|> 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_id", activity["context_id"])
|
||||
|> Map.put_new("fake", true)
|
||||
@ -237,7 +222,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||
object =
|
||||
map
|
||||
|> 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_id", activity["context_id"])
|
||||
|
||||
@ -662,7 +647,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||
#### Create-related helpers
|
||||
|
||||
def make_create_data(params, additional) do
|
||||
published = params.published || make_date()
|
||||
published = params.published || Builder.date()
|
||||
|
||||
%{
|
||||
"type" => "Create",
|
||||
@ -675,21 +660,6 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||
|> Map.merge(additional)
|
||||
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
|
||||
@spec make_flag_data(map(), map()) :: map()
|
||||
def make_flag_data(%{actor: actor, context: context, content: content} = params, additional) do
|
||||
|
@ -6,10 +6,11 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do
|
||||
use Pleroma.Web, :view
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.Builder
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
|
||||
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)
|
||||
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})
|
||||
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)
|
||||
|
||||
additional =
|
||||
@ -28,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do
|
||||
end
|
||||
|
||||
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)
|
||||
|
||||
additional =
|
||||
|
@ -9,9 +9,9 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Builder
|
||||
alias Pleroma.Web.ActivityPub.ObjectView
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.Endpoint
|
||||
alias Pleroma.Web.Router.Helpers
|
||||
|
||||
@ -60,7 +60,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||
"endpoints" => endpoints,
|
||||
"invisible" => User.invisible?(user)
|
||||
}
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
|> Map.merge(Builder.json_ld_header())
|
||||
end
|
||||
|
||||
# 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.banner_url/2, "image", user))
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
|> Map.merge(Builder.json_ld_header())
|
||||
end
|
||||
|
||||
def render("following.json", %{user: user, page: page} = opts) do
|
||||
@ -139,7 +139,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||
end
|
||||
|
||||
collection(following, "#{user.ap_id}/following", page, showing_items, total)
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
|> Map.merge(Builder.json_ld_header())
|
||||
end
|
||||
|
||||
def render("following.json", %{user: user} = opts) do
|
||||
@ -168,7 +168,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||
"#{user.ap_id}/following?page=1"
|
||||
end
|
||||
}
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
|> Map.merge(Builder.json_ld_header())
|
||||
end
|
||||
|
||||
def render("followers.json", %{user: user, page: page} = opts) do
|
||||
@ -187,7 +187,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||
end
|
||||
|
||||
collection(followers, "#{user.ap_id}/followers", page, showing_items, total)
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
|> Map.merge(Builder.json_ld_header())
|
||||
end
|
||||
|
||||
def render("followers.json", %{user: user} = opts) do
|
||||
@ -216,7 +216,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||
end
|
||||
}
|
||||
|> maybe_put_total_items(showing_count, total)
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
|> Map.merge(Builder.json_ld_header())
|
||||
end
|
||||
|
||||
def render("activity_collection.json", %{iri: iri}) do
|
||||
@ -225,7 +225,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||
"type" => "OrderedCollection",
|
||||
"first" => "#{iri}?page=true"
|
||||
}
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
|> Map.merge(Builder.json_ld_header())
|
||||
end
|
||||
|
||||
def render("activity_collection_page.json", %{
|
||||
@ -244,7 +244,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||
"partOf" => iri,
|
||||
"orderedItems" => collection
|
||||
}
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
|> Map.merge(Builder.json_ld_header())
|
||||
|> Map.merge(pagination)
|
||||
end
|
||||
|
||||
@ -264,7 +264,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||
"orderedItems" => objects,
|
||||
"totalItems" => length(objects)
|
||||
}
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
|> Map.merge(Builder.json_ld_header())
|
||||
end
|
||||
|
||||
defp maybe_put_total_items(map, false, _total), do: map
|
||||
|
@ -12,39 +12,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AudioHandlingTest do
|
||||
|
||||
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
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://channels.tests.funkwhale.audio/federation/actors/compositions"} ->
|
||||
|
@ -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
|
@ -499,128 +499,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
|
||||
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
|
||||
test "returns not modified object when object not contains tags" do
|
||||
data = Jason.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
|
||||
@ -652,48 +530,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
|
||||
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
|
||||
user = insert(:user, %{emoji: %{"firefox" => "https://example.org/firefox.png"}})
|
||||
|
||||
|
@ -10,13 +10,12 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Builder
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.AdminAPI.AccountView
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
import ExUnit.CaptureLog
|
||||
|
||||
setup_all do
|
||||
@ -160,7 +159,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
{: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"]
|
||||
end
|
||||
@ -424,91 +423,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
||||
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
|
||||
test "returns nil when cannot normalize object" do
|
||||
assert capture_log(fn ->
|
||||
|
@ -138,18 +138,6 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
||||
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
|
||||
test "fetches existing votes" do
|
||||
user = insert(:user)
|
||||
|
Loading…
Reference in New Issue
Block a user