@@ -49,7 +49,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Actor do
|
||||
banner: banner,
|
||||
name: data["name"],
|
||||
preferred_username: data["preferredUsername"],
|
||||
summary: data["summary"],
|
||||
summary: data["summary"] || "",
|
||||
keys: data["publicKey"]["publicKeyPem"],
|
||||
inbox_url: data["inbox"],
|
||||
outbox_url: data["outbox"],
|
||||
@@ -57,6 +57,10 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Actor do
|
||||
followers_url: data["followers"],
|
||||
members_url: data["members"],
|
||||
resources_url: data["resources"],
|
||||
todos_url: data["todos"],
|
||||
events_url: data["events"],
|
||||
posts_url: data["posts"],
|
||||
discussions_url: data["discussions"],
|
||||
shared_inbox_url: data["endpoints"]["sharedInbox"],
|
||||
domain: URI.parse(data["id"]).host,
|
||||
manually_approves_followers: data["manuallyApprovesFollowers"],
|
||||
@@ -77,12 +81,15 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Actor do
|
||||
"type" => actor.type,
|
||||
"preferredUsername" => actor.preferred_username,
|
||||
"name" => actor.name,
|
||||
"summary" => actor.summary,
|
||||
"summary" => actor.summary || "",
|
||||
"following" => actor.following_url,
|
||||
"followers" => actor.followers_url,
|
||||
"members" => actor.members_url,
|
||||
"resources" => actor.resources_url,
|
||||
"todos" => actor.todos_url,
|
||||
"posts" => actor.posts_url,
|
||||
"events" => actor.events_url,
|
||||
"discussions" => actor.discussions_url,
|
||||
"inbox" => actor.inbox_url,
|
||||
"outbox" => actor.outbox_url,
|
||||
"url" => actor.url,
|
||||
|
||||
@@ -7,22 +7,30 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Comment do
|
||||
"""
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Conversations.Comment, as: CommentModel
|
||||
alias Mobilizon.Discussions
|
||||
alias Mobilizon.Discussions.Comment, as: CommentModel
|
||||
alias Mobilizon.Discussions.Discussion
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Tombstone, as: TombstoneModel
|
||||
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityPub.Visibility
|
||||
alias Mobilizon.Federation.ActivityStream.{Converter, Convertible}
|
||||
alias Mobilizon.Federation.ActivityStream.Converter.Utils, as: ConverterUtils
|
||||
alias Mobilizon.Federation.ActivityStream.Converter.Comment, as: CommentConverter
|
||||
alias Mobilizon.Tombstone, as: TombstoneModel
|
||||
|
||||
import Mobilizon.Federation.ActivityStream.Converter.Utils,
|
||||
only: [
|
||||
fetch_tags: 1,
|
||||
fetch_mentions: 1,
|
||||
build_tags: 1,
|
||||
build_mentions: 1,
|
||||
maybe_fetch_actor_and_attributed_to_id: 1
|
||||
]
|
||||
|
||||
require Logger
|
||||
|
||||
@behaviour Converter
|
||||
|
||||
defimpl Convertible, for: CommentModel do
|
||||
alias Mobilizon.Federation.ActivityStream.Converter.Comment, as: CommentConverter
|
||||
|
||||
defdelegate model_to_as(comment), to: CommentConverter
|
||||
end
|
||||
|
||||
@@ -35,61 +43,35 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Comment do
|
||||
Logger.debug("We're converting raw ActivityStream data to a comment entity")
|
||||
Logger.debug(inspect(object))
|
||||
|
||||
with author_url <- Map.get(object, "actor") || Map.get(object, "attributedTo"),
|
||||
{:ok, %Actor{id: actor_id, domain: domain, suspended: false}} <-
|
||||
ActivityPub.get_or_fetch_actor_by_url(author_url),
|
||||
{:tags, tags} <- {:tags, ConverterUtils.fetch_tags(Map.get(object, "tag", []))},
|
||||
with {%Actor{id: actor_id, domain: actor_domain}, attributed_to} <-
|
||||
maybe_fetch_actor_and_attributed_to_id(object),
|
||||
{:tags, tags} <- {:tags, fetch_tags(Map.get(object, "tag", []))},
|
||||
{:mentions, mentions} <-
|
||||
{:mentions, ConverterUtils.fetch_mentions(Map.get(object, "tag", []))} do
|
||||
{:mentions, fetch_mentions(Map.get(object, "tag", []))},
|
||||
discussion <-
|
||||
Discussions.get_discussion_by_url(Map.get(object, "context")) do
|
||||
Logger.debug("Inserting full comment")
|
||||
Logger.debug(inspect(object))
|
||||
|
||||
data = %{
|
||||
text: object["content"],
|
||||
url: object["id"],
|
||||
# Will be used in conversations, ignored in basic comments
|
||||
title: object["name"],
|
||||
context: object["context"],
|
||||
actor_id: actor_id,
|
||||
attributed_to_id: if(is_nil(attributed_to), do: nil, else: attributed_to.id),
|
||||
in_reply_to_comment_id: nil,
|
||||
event_id: nil,
|
||||
uuid: object["uuid"],
|
||||
discussion_id: if(is_nil(discussion), do: nil, else: discussion.id),
|
||||
tags: tags,
|
||||
mentions: mentions,
|
||||
local: is_nil(domain),
|
||||
local: is_nil(actor_domain),
|
||||
visibility: if(Visibility.is_public?(object), do: :public, else: :private)
|
||||
}
|
||||
|
||||
# We fetch the parent object
|
||||
Logger.debug("We're fetching the parent object")
|
||||
|
||||
if Map.has_key?(object, "inReplyTo") && object["inReplyTo"] != nil &&
|
||||
object["inReplyTo"] != "" do
|
||||
Logger.debug(fn -> "Object has inReplyTo #{object["inReplyTo"]}" end)
|
||||
|
||||
case ActivityPub.fetch_object_from_url(object["inReplyTo"]) do
|
||||
# Reply to an event (Event)
|
||||
{:ok, %Event{id: id}} ->
|
||||
Logger.debug("Parent object is an event")
|
||||
data |> Map.put(:event_id, id)
|
||||
|
||||
# Reply to a comment (Comment)
|
||||
{:ok, %CommentModel{id: id} = comment} ->
|
||||
Logger.debug("Parent object is another comment")
|
||||
|
||||
data
|
||||
|> Map.put(:in_reply_to_comment_id, id)
|
||||
|> Map.put(:origin_comment_id, comment |> CommentModel.get_thread_id())
|
||||
|> Map.put(:event_id, comment.event_id)
|
||||
|
||||
# Anything else is kind of a MP
|
||||
{:error, parent} ->
|
||||
Logger.warn("Parent object is something we don't handle")
|
||||
Logger.debug(inspect(parent))
|
||||
data
|
||||
end
|
||||
else
|
||||
Logger.debug("No parent object for this comment")
|
||||
|
||||
data
|
||||
end
|
||||
maybe_fetch_parent_object(object, data)
|
||||
else
|
||||
{:ok, %Actor{suspended: true}} ->
|
||||
:error
|
||||
@@ -102,10 +84,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Comment do
|
||||
@impl Converter
|
||||
@spec model_to_as(CommentModel.t()) :: map
|
||||
def model_to_as(%CommentModel{deleted_at: nil} = comment) do
|
||||
to =
|
||||
if comment.visibility == :public,
|
||||
do: ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
else: [comment.actor.followers_url]
|
||||
to = determine_to(comment)
|
||||
|
||||
object = %{
|
||||
"type" => "Note",
|
||||
@@ -114,13 +93,19 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Comment do
|
||||
"content" => comment.text,
|
||||
"mediaType" => "text/html",
|
||||
"actor" => comment.actor.url,
|
||||
"attributedTo" => comment.actor.url,
|
||||
"attributedTo" =>
|
||||
if(is_nil(comment.attributed_to), do: nil, else: comment.attributed_to.url) ||
|
||||
comment.actor.url,
|
||||
"uuid" => comment.uuid,
|
||||
"id" => comment.url,
|
||||
"tag" =>
|
||||
ConverterUtils.build_mentions(comment.mentions) ++ ConverterUtils.build_tags(comment.tags)
|
||||
"tag" => build_mentions(comment.mentions) ++ build_tags(comment.tags)
|
||||
}
|
||||
|
||||
object =
|
||||
if comment.discussion_id,
|
||||
do: Map.put(object, "context", comment.discussion.url),
|
||||
else: object
|
||||
|
||||
cond do
|
||||
comment.in_reply_to_comment ->
|
||||
Map.put(object, "inReplyTo", comment.in_reply_to_comment.url)
|
||||
@@ -133,15 +118,78 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Comment do
|
||||
end
|
||||
end
|
||||
|
||||
@impl Converter
|
||||
@spec model_to_as(CommentModel.t()) :: map
|
||||
@doc """
|
||||
A "soft-deleted" comment is a tombstone
|
||||
"""
|
||||
@impl Converter
|
||||
@spec model_to_as(CommentModel.t()) :: map
|
||||
def model_to_as(%CommentModel{} = comment) do
|
||||
Convertible.model_to_as(%TombstoneModel{
|
||||
uri: comment.url,
|
||||
inserted_at: comment.deleted_at
|
||||
})
|
||||
end
|
||||
|
||||
@spec determine_to(CommentModel.t()) :: [String.t()]
|
||||
defp determine_to(%CommentModel{} = comment) do
|
||||
cond do
|
||||
not is_nil(comment.attributed_to) ->
|
||||
[comment.attributed_to.url]
|
||||
|
||||
comment.visibility == :public ->
|
||||
["https://www.w3.org/ns/activitystreams#Public"]
|
||||
|
||||
true ->
|
||||
[comment.actor.followers_url]
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_fetch_parent_object(object, data) do
|
||||
# We fetch the parent object
|
||||
Logger.debug("We're fetching the parent object")
|
||||
|
||||
if Map.has_key?(object, "inReplyTo") && object["inReplyTo"] != nil &&
|
||||
object["inReplyTo"] != "" do
|
||||
Logger.debug(fn -> "Object has inReplyTo #{object["inReplyTo"]}" end)
|
||||
|
||||
case ActivityPub.fetch_object_from_url(object["inReplyTo"]) do
|
||||
# Reply to an event (Event)
|
||||
{:ok, %Event{id: id}} ->
|
||||
Logger.debug("Parent object is an event")
|
||||
data |> Map.put(:event_id, id)
|
||||
|
||||
# Reply to a comment (Comment)
|
||||
{:ok, %CommentModel{id: id} = comment} ->
|
||||
Logger.debug("Parent object is another comment")
|
||||
|
||||
data
|
||||
|> Map.put(:in_reply_to_comment_id, id)
|
||||
|> Map.put(:origin_comment_id, comment |> CommentModel.get_thread_id())
|
||||
|> Map.put(:event_id, comment.event_id)
|
||||
|
||||
# Reply to a discucssion (Discussion)
|
||||
{:ok,
|
||||
%Discussion{
|
||||
id: discussion_id,
|
||||
last_comment: %CommentModel{id: last_comment_id, origin_comment_id: origin_comment_id}
|
||||
} = _discussion} ->
|
||||
Logger.debug("Parent object is a discussion")
|
||||
|
||||
data
|
||||
|> Map.put(:in_reply_to_comment_id, last_comment_id)
|
||||
|> Map.put(:origin_comment_id, origin_comment_id)
|
||||
|> Map.put(:discussion_id, discussion_id)
|
||||
|
||||
# Anything else is kind of a MP
|
||||
{:error, parent} ->
|
||||
Logger.warn("Parent object is something we don't handle")
|
||||
Logger.debug(inspect(parent))
|
||||
data
|
||||
end
|
||||
else
|
||||
Logger.debug("No parent object for this comment")
|
||||
|
||||
data
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,6 +6,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter do
|
||||
one, and back.
|
||||
"""
|
||||
|
||||
@callback as_to_model_data(map) :: map
|
||||
@callback model_to_as(struct) :: map
|
||||
@type model_data :: map()
|
||||
|
||||
@callback as_to_model_data(as_data :: ActivityStream.t()) :: model_data()
|
||||
@callback model_to_as(model :: struct()) :: ActivityStream.t()
|
||||
end
|
||||
|
||||
63
lib/federation/activity_stream/converter/discussion.ex
Normal file
63
lib/federation/activity_stream/converter/discussion.ex
Normal file
@@ -0,0 +1,63 @@
|
||||
defmodule Mobilizon.Federation.ActivityStream.Converter.Discussion do
|
||||
@moduledoc """
|
||||
Comment converter.
|
||||
|
||||
This module allows to convert events from ActivityStream format to our own
|
||||
internal one, and back.
|
||||
"""
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Discussions.Discussion
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityStream.{Converter, Convertible}
|
||||
alias Mobilizon.Federation.ActivityStream.Converter.Discussion, as: DiscussionConverter
|
||||
alias Mobilizon.Storage.Repo
|
||||
|
||||
require Logger
|
||||
|
||||
@behaviour Converter
|
||||
|
||||
defimpl Convertible, for: Discussion do
|
||||
defdelegate model_to_as(comment), to: DiscussionConverter
|
||||
end
|
||||
|
||||
@doc """
|
||||
Make an AS comment object from an existing `discussion` structure.
|
||||
"""
|
||||
@impl Converter
|
||||
@spec model_to_as(Discussion.t()) :: map
|
||||
def model_to_as(%Discussion{} = discussion) do
|
||||
discussion = Repo.preload(discussion, [:last_comment, :actor, :creator])
|
||||
|
||||
%{
|
||||
"type" => "Note",
|
||||
"to" => [discussion.actor.followers_url],
|
||||
"cc" => [],
|
||||
"name" => discussion.title,
|
||||
"content" => discussion.last_comment.text,
|
||||
"mediaType" => "text/html",
|
||||
"actor" => discussion.creator.url,
|
||||
"attributedTo" => discussion.actor.url,
|
||||
"id" => discussion.url,
|
||||
"context" => discussion.url
|
||||
}
|
||||
end
|
||||
|
||||
@impl Converter
|
||||
@spec as_to_model_data(map) :: {:ok, map} | {:error, any()}
|
||||
def as_to_model_data(%{"type" => "Note", "name" => name} = object) when not is_nil(name) do
|
||||
with creator_url <- Map.get(object, "actor"),
|
||||
{:ok, %Actor{id: creator_id, suspended: false}} <-
|
||||
ActivityPub.get_or_fetch_actor_by_url(creator_url),
|
||||
actor_url <- Map.get(object, "attributedTo"),
|
||||
{:ok, %Actor{id: actor_id, suspended: false}} <-
|
||||
ActivityPub.get_or_fetch_actor_by_url(actor_url) do
|
||||
%{
|
||||
title: name,
|
||||
actor_id: actor_id,
|
||||
creator_id: creator_id,
|
||||
url: object["id"]
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -12,11 +12,17 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
||||
alias Mobilizon.Events.Event, as: EventModel
|
||||
alias Mobilizon.Media.Picture
|
||||
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityStream.{Converter, Convertible}
|
||||
alias Mobilizon.Federation.ActivityStream.Converter.Address, as: AddressConverter
|
||||
alias Mobilizon.Federation.ActivityStream.Converter.Picture, as: PictureConverter
|
||||
alias Mobilizon.Federation.ActivityStream.Converter.Utils, as: ConverterUtils
|
||||
|
||||
import Mobilizon.Federation.ActivityStream.Converter.Utils,
|
||||
only: [
|
||||
fetch_tags: 1,
|
||||
fetch_mentions: 1,
|
||||
build_tags: 1,
|
||||
maybe_fetch_actor_and_attributed_to_id: 1
|
||||
]
|
||||
|
||||
require Logger
|
||||
|
||||
@@ -34,16 +40,12 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
||||
@impl Converter
|
||||
@spec as_to_model_data(map) :: {:ok, map()} | {:error, any()}
|
||||
def as_to_model_data(object) do
|
||||
Logger.debug("event as_to_model_data")
|
||||
Logger.debug(inspect(object))
|
||||
|
||||
with author_url <- Map.get(object, "actor") || Map.get(object, "attributedTo"),
|
||||
{:actor, {:ok, %Actor{id: actor_id, domain: actor_domain, suspended: false}}} <-
|
||||
{:actor, ActivityPub.get_or_fetch_actor_by_url(author_url)},
|
||||
with {%Actor{id: actor_id, domain: actor_domain}, attributed_to} <-
|
||||
maybe_fetch_actor_and_attributed_to_id(object),
|
||||
{:address, address_id} <-
|
||||
{:address, get_address(object["location"])},
|
||||
{:tags, tags} <- {:tags, ConverterUtils.fetch_tags(object["tag"])},
|
||||
{:mentions, mentions} <- {:mentions, ConverterUtils.fetch_mentions(object["tag"])},
|
||||
{:tags, tags} <- {:tags, fetch_tags(object["tag"])},
|
||||
{:mentions, mentions} <- {:mentions, fetch_mentions(object["tag"])},
|
||||
{:visibility, visibility} <- {:visibility, get_visibility(object)},
|
||||
{:options, options} <- {:options, get_options(object)} do
|
||||
attachments =
|
||||
@@ -67,6 +69,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
||||
title: object["name"],
|
||||
description: object["content"],
|
||||
organizer_actor_id: actor_id,
|
||||
attributed_to_id: if(is_nil(attributed_to), do: nil, else: attributed_to.id),
|
||||
picture_id: picture_id,
|
||||
begins_on: object["startTime"],
|
||||
ends_on: object["endTime"],
|
||||
@@ -108,7 +111,9 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
||||
"type" => "Event",
|
||||
"to" => to,
|
||||
"cc" => [],
|
||||
"attributedTo" => event.organizer_actor.url,
|
||||
"attributedTo" =>
|
||||
if(is_nil(event.attributed_to), do: nil, else: event.attributed_to.url) ||
|
||||
event.organizer_actor.url,
|
||||
"name" => event.title,
|
||||
"actor" => event.organizer_actor.url,
|
||||
"uuid" => event.uuid,
|
||||
@@ -120,7 +125,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
||||
"startTime" => event.begins_on |> date_to_string(),
|
||||
"joinMode" => to_string(event.join_options),
|
||||
"endTime" => event.ends_on |> date_to_string(),
|
||||
"tag" => event.tags |> ConverterUtils.build_tags(),
|
||||
"tag" => event.tags |> build_tags(),
|
||||
"maximumAttendeeCapacity" => event.options.maximum_attendee_capacity,
|
||||
"repliesModerationOption" => event.options.comment_moderation,
|
||||
"commentsEnabled" => event.options.comment_moderation == :allow_all,
|
||||
|
||||
@@ -9,7 +9,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Flag do
|
||||
"""
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Conversations
|
||||
alias Mobilizon.Discussions
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Reports.Report
|
||||
@@ -92,7 +92,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Flag do
|
||||
Enum.filter(objects, fn url ->
|
||||
!(url == reported.url || (!is_nil(event) && event.url == url))
|
||||
end),
|
||||
comments <- Enum.map(comments, &Conversations.get_comment_from_url/1) do
|
||||
comments <- Enum.map(comments, &Discussions.get_comment_from_url/1) do
|
||||
%{
|
||||
"reporter" => reporter,
|
||||
"uri" => object["id"],
|
||||
|
||||
@@ -39,7 +39,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Picture do
|
||||
actor_id
|
||||
)
|
||||
when is_bitstring(picture_url) do
|
||||
with {:ok, %HTTPoison.Response{body: body}} <- HTTPoison.get(picture_url, [], @http_options),
|
||||
with {:ok, %{body: body}} <- Tesla.get(picture_url, opts: @http_options),
|
||||
{:ok, %{name: name, url: url, content_type: content_type, size: size}} <-
|
||||
Upload.store(%{body: body, name: name}),
|
||||
{:picture_exists, nil} <- {:picture_exists, Media.get_picture_by_url(url)} do
|
||||
|
||||
70
lib/federation/activity_stream/converter/post.ex
Normal file
70
lib/federation/activity_stream/converter/post.ex
Normal file
@@ -0,0 +1,70 @@
|
||||
defmodule Mobilizon.Federation.ActivityStream.Converter.Post do
|
||||
@moduledoc """
|
||||
Post converter.
|
||||
|
||||
This module allows to convert posts from ActivityStream format to our own
|
||||
internal one, and back.
|
||||
"""
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityPub.Utils
|
||||
alias Mobilizon.Federation.ActivityStream.{Converter, Convertible}
|
||||
alias Mobilizon.Posts.Post
|
||||
require Logger
|
||||
|
||||
@behaviour Converter
|
||||
|
||||
defimpl Convertible, for: Post do
|
||||
alias Mobilizon.Federation.ActivityStream.Converter.Post, as: PostConverter
|
||||
|
||||
defdelegate model_to_as(post), to: PostConverter
|
||||
end
|
||||
|
||||
@doc """
|
||||
Convert an post struct to an ActivityStream representation
|
||||
"""
|
||||
@impl Converter
|
||||
@spec model_to_as(Post.t()) :: map
|
||||
def model_to_as(
|
||||
%Post{author: %Actor{url: actor_url}, attributed_to: %Actor{url: creator_url}} = post
|
||||
) do
|
||||
%{
|
||||
"type" => "Article",
|
||||
"actor" => actor_url,
|
||||
"id" => post.url,
|
||||
"name" => post.title,
|
||||
"content" => post.body,
|
||||
"attributedTo" => creator_url,
|
||||
"published" => post.publish_at || post.inserted_at
|
||||
}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Converts an AP object data to our internal data structure.
|
||||
"""
|
||||
@impl Converter
|
||||
@spec as_to_model_data(map) :: {:ok, map} | {:error, any()}
|
||||
def as_to_model_data(
|
||||
%{"type" => "Article", "actor" => creator, "attributedTo" => group} = object
|
||||
) do
|
||||
with {:ok, %Actor{id: attributed_to_id}} <- get_actor(group),
|
||||
{:ok, %Actor{id: author_id}} <- get_actor(creator) do
|
||||
%{
|
||||
title: object["name"],
|
||||
body: object["content"],
|
||||
url: object["id"],
|
||||
attributed_to_id: attributed_to_id,
|
||||
author_id: author_id,
|
||||
local: false,
|
||||
publish_at: object["published"]
|
||||
}
|
||||
else
|
||||
{:error, err} -> {:error, err}
|
||||
err -> {:error, err}
|
||||
end
|
||||
end
|
||||
|
||||
@spec get_actor(String.t() | map() | nil) :: {:ok, Actor.t()} | {:error, String.t()}
|
||||
defp get_actor(nil), do: {:error, "nil property found for actor data"}
|
||||
defp get_actor(actor), do: actor |> Utils.get_url() |> ActivityPub.get_or_fetch_actor_by_url()
|
||||
end
|
||||
@@ -28,7 +28,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.TodoList do
|
||||
"type" => "TodoList",
|
||||
"actor" => group_url,
|
||||
"id" => todo_list.url,
|
||||
"title" => todo_list.title
|
||||
"name" => todo_list.title
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Tombstone do
|
||||
%{
|
||||
"type" => "Tombstone",
|
||||
"id" => tombstone.uri,
|
||||
"actor" => tombstone.actor.url,
|
||||
"deleted" => tombstone.inserted_at
|
||||
}
|
||||
end
|
||||
|
||||
@@ -23,6 +23,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Utils do
|
||||
tags |> Enum.flat_map(&fetch_tag/1) |> Enum.uniq() |> Enum.map(&existing_tag_or_data/1)
|
||||
end
|
||||
|
||||
def fetch_tags(_), do: []
|
||||
|
||||
@spec fetch_mentions([map()]) :: [map()]
|
||||
def fetch_mentions(mentions) when is_list(mentions) do
|
||||
Logger.debug("fetching mentions")
|
||||
@@ -30,6 +32,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Utils do
|
||||
Enum.reduce(mentions, [], fn mention, acc -> create_mention(mention, acc) end)
|
||||
end
|
||||
|
||||
def fetch_mentions(_), do: []
|
||||
|
||||
def fetch_address(%{id: id}) do
|
||||
with {id, ""} <- Integer.parse(id), do: %{id: id}
|
||||
end
|
||||
@@ -38,7 +42,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Utils do
|
||||
address
|
||||
end
|
||||
|
||||
@spec build_tags([Tag.t()]) :: [Map.t()]
|
||||
@spec build_tags([Tag.t()]) :: [map()]
|
||||
def build_tags(tags) do
|
||||
Enum.map(tags, fn %Tag{} = tag ->
|
||||
%{
|
||||
@@ -111,4 +115,51 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Utils do
|
||||
defp create_mention({_, mention}, acc) when is_map(mention) do
|
||||
create_mention(mention, acc)
|
||||
end
|
||||
|
||||
@spec maybe_fetch_actor_and_attributed_to_id(map()) :: {Actor.t() | nil, Actor.t() | nil}
|
||||
def maybe_fetch_actor_and_attributed_to_id(%{
|
||||
"actor" => actor_url,
|
||||
"attributedTo" => attributed_to_url
|
||||
})
|
||||
when is_nil(attributed_to_url) do
|
||||
{fetch_actor(actor_url), nil}
|
||||
end
|
||||
|
||||
@spec maybe_fetch_actor_and_attributed_to_id(map()) :: {Actor.t() | nil, Actor.t() | nil}
|
||||
def maybe_fetch_actor_and_attributed_to_id(%{
|
||||
"actor" => actor_url,
|
||||
"attributedTo" => attributed_to_url
|
||||
})
|
||||
when is_nil(actor_url) do
|
||||
{fetch_actor(attributed_to_url), nil}
|
||||
end
|
||||
|
||||
# Only when both actor and attributedTo fields are both filled is when we can return both
|
||||
def maybe_fetch_actor_and_attributed_to_id(%{
|
||||
"actor" => actor_url,
|
||||
"attributedTo" => attributed_to_url
|
||||
})
|
||||
when actor_url != attributed_to_url do
|
||||
with actor <- fetch_actor(actor_url),
|
||||
attributed_to <- fetch_actor(attributed_to_url) do
|
||||
{actor, attributed_to}
|
||||
end
|
||||
end
|
||||
|
||||
# If we only have attributedTo and no actor, take attributedTo as the actor
|
||||
def maybe_fetch_actor_and_attributed_to_id(%{
|
||||
"attributedTo" => attributed_to_url
|
||||
}) do
|
||||
{fetch_actor(attributed_to_url), nil}
|
||||
end
|
||||
|
||||
def maybe_fetch_actor_and_attributed_to_id(_), do: {nil, nil}
|
||||
|
||||
@spec fetch_actor(String.t()) :: Actor.t()
|
||||
defp fetch_actor(actor_url) do
|
||||
with {:ok, %Actor{suspended: false} = actor} <-
|
||||
ActivityPub.get_or_fetch_actor_by_url(actor_url) do
|
||||
actor
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,8 +3,9 @@ defprotocol Mobilizon.Federation.ActivityStream.Convertible do
|
||||
Convertible protocol.
|
||||
"""
|
||||
|
||||
@type activity_streams :: map
|
||||
@type t :: struct()
|
||||
@type activity_streams :: map()
|
||||
|
||||
@spec model_to_as(t) :: activity_streams
|
||||
@spec model_to_as(t()) :: activity_streams()
|
||||
def model_to_as(convertible)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user