media_type =
cond do
- is_map(url) && MIME.valid?(url["mediaType"]) -> url["mediaType"]
- MIME.valid?(data["mediaType"]) -> data["mediaType"]
- MIME.valid?(data["mimeType"]) -> data["mimeType"]
- true -> nil
+ 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 =
end)
end
- # Compatibility wrapper for Mastodon votes
- defp handle_create(%{"object" => %{"type" => "Answer"}} = data, _user) do
- handle_incoming(data)
- end
-
- defp handle_create(%{"object" => object} = data, user) do
- %{
- to: data["to"],
- object: object,
- actor: user,
- context: object["context"],
- local: false,
- published: data["published"],
- additional:
- Map.take(data, [
- "cc",
- "directMessage",
- "id"
- ])
- }
- |> ActivityPub.create()
- end
-
def handle_incoming(data, options \\ [])
# Flag objects are placed ahead of the ID check because Mastodon 2.8 and earlier send them
def handle_incoming(%{"id" => id}, _options) when is_binary(id) and byte_size(id) < 8,
do: :error
- # TODO: validate those with a Ecto scheme
- # - tags
- # - emoji
- def handle_incoming(
- %{"type" => "Create", "object" => %{"type" => "Page"} = object} = data,
- options
- ) do
- actor = Containment.get_actor(data)
-
- with nil <- Activity.get_create_by_object_ap_id(object["id"]),
- {:ok, %User{} = user} <- User.get_or_fetch_by_ap_id(actor) do
- data =
- data
- |> Map.put("object", fix_object(object, options))
- |> Map.put("actor", actor)
- |> fix_addressing()
-
- with {:ok, created_activity} <- handle_create(data, user) do
- reply_depth = (options[:depth] || 0) + 1
-
- if Federator.allowed_thread_distance?(reply_depth) do
- for reply_id <- replies(object) do
- Pleroma.Workers.RemoteFetcherWorker.enqueue("fetch_remote", %{
- "id" => reply_id,
- "depth" => reply_depth
- })
- end
- end
-
- {:ok, created_activity}
- end
- else
- %Activity{} = activity -> {:ok, activity}
- _e -> :error
- end
- end
-
+ @doc "Rewrite misskey likes into EmojiReacts"
def handle_incoming(
- %{"type" => "Listen", "object" => %{"type" => "Audio"} = object} = data,
+ %{
+ "type" => "Like",
+ "_misskey_reaction" => reaction,
+ "tag" => _
+ } = 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
+ data
+ |> Map.put("type", "EmojiReact")
+ |> Map.put("content", reaction)
+ |> handle_incoming(options)
end
- @misskey_reactions %{
- "like" => "👍",
- "love" => "❤️",
- "laugh" => "😆",
- "hmm" => "🤔",
- "surprise" => "😮",
- "congrats" => "🎉",
- "angry" => "💢",
- "confused" => "😥",
- "rip" => "😇",
- "pudding" => "🍮",
- "star" => "⭐"
- }
-
- @doc "Rewrite misskey likes into EmojiReacts"
def handle_incoming(
%{
"type" => "Like",
) do
data
|> Map.put("type", "EmojiReact")
- |> Map.put("content", @misskey_reactions[reaction] || reaction)
+ |> Map.put("content", reaction)
|> handle_incoming(options)
end
%{"type" => "Create", "object" => %{"type" => objtype, "id" => obj_id}} = data,
options
)
- when objtype in ~w{Question Answer ChatMessage Audio Video Event Article Note} do
+ when objtype in ~w{Question Answer Audio Video Event Article Note Page} do
fetch_options = Keyword.put(options, :depth, (options[:depth] || 0) + 1)
object =
def handle_incoming(%{"type" => type} = data, _options)
when type in ~w{Like EmojiReact Announce Add Remove} do
with :ok <- ObjectValidator.fetch_actor_and_object(data),
- {:ok, activity, _meta} <-
- Pipeline.common_pipeline(data, local: false) do
+ {:ok, activity, _meta} <- Pipeline.common_pipeline(data, local: false) do
{:ok, activity}
else
- e -> {:error, e}
+ e ->
+ {:error, e}
end
end
# """
def prepare_outgoing(%{"type" => activity_type, "object" => object_id} = data)
- when activity_type in ["Create", "Listen"] do
+ when activity_type in ["Create"] do
object =
object_id
|> Object.normalize(fetch: false)
Map.put(object, "attributedTo", attributed_to)
end
- # TODO: Revisit this
- def prepare_attachments(%{"type" => "ChatMessage"} = object), do: object
-
def prepare_attachments(object) do
attachments =
object