Refactor media upload
Use Upload Media logic from Pleroma Backend changes for picture upload Move AS <-> Model conversion to separate module Front changes Downgrade apollo-client: https://github.com/Akryum/vue-apollo/issues/577 Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -468,10 +468,24 @@ defmodule Mobilizon.Service.ActivityPub do
|
||||
"""
|
||||
@spec actor_data_from_actor_object(map()) :: {:ok, map()}
|
||||
def actor_data_from_actor_object(data) when is_map(data) do
|
||||
avatar =
|
||||
data["icon"]["url"] &&
|
||||
%{
|
||||
"name" => data["icon"]["name"] || "avatar",
|
||||
"url" => data["icon"]["url"]
|
||||
}
|
||||
|
||||
banner =
|
||||
data["image"]["url"] &&
|
||||
%{
|
||||
"name" => data["image"]["name"] || "banner",
|
||||
"url" => data["image"]["url"]
|
||||
}
|
||||
|
||||
actor_data = %{
|
||||
url: data["id"],
|
||||
avatar_url: data["icon"]["url"],
|
||||
banner_url: data["image"]["url"],
|
||||
avatar: avatar,
|
||||
banner: banner,
|
||||
name: data["name"],
|
||||
preferred_username: data["preferredUsername"],
|
||||
summary: data["summary"],
|
||||
@@ -512,7 +526,7 @@ defmodule Mobilizon.Service.ActivityPub do
|
||||
%Activity{
|
||||
recipients: ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
actor: event.organizer_actor.url,
|
||||
data: event |> make_event_data,
|
||||
data: event |> Mobilizon.Service.ActivityPub.Converters.Event.model_to_as(),
|
||||
local: local
|
||||
}
|
||||
end
|
||||
@@ -523,7 +537,7 @@ defmodule Mobilizon.Service.ActivityPub do
|
||||
%Activity{
|
||||
recipients: ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
actor: comment.actor.url,
|
||||
data: comment |> make_comment_data,
|
||||
data: comment |> Mobilizon.Service.ActivityPub.Converters.Comment.model_to_as(),
|
||||
local: local
|
||||
}
|
||||
end
|
||||
|
||||
9
lib/service/activity_pub/converter.ex
Normal file
9
lib/service/activity_pub/converter.ex
Normal file
@@ -0,0 +1,9 @@
|
||||
defmodule Mobilizon.Service.ActivityPub.Converter do
|
||||
@moduledoc """
|
||||
Converter behaviour
|
||||
|
||||
This module allows to convert from ActivityStream format to our own internal one, and back
|
||||
"""
|
||||
@callback as_to_model_data(map()) :: map()
|
||||
@callback model_to_as(struct()) :: map()
|
||||
end
|
||||
47
lib/service/activity_pub/converters/actor.ex
Normal file
47
lib/service/activity_pub/converters/actor.ex
Normal file
@@ -0,0 +1,47 @@
|
||||
defmodule Mobilizon.Service.ActivityPub.Converters.Actor do
|
||||
@moduledoc """
|
||||
Actor converter
|
||||
|
||||
This module allows to convert events from ActivityStream format to our own internal one, and back
|
||||
"""
|
||||
alias Mobilizon.Actors.Actor, as: ActorModel
|
||||
alias Mobilizon.Service.ActivityPub.Converter
|
||||
|
||||
@behaviour Converter
|
||||
|
||||
@doc """
|
||||
Converts an AP object data to our internal data structure
|
||||
"""
|
||||
@impl Converter
|
||||
@spec as_to_model_data(map()) :: map()
|
||||
def as_to_model_data(object) do
|
||||
%{
|
||||
"type" => String.to_existing_atom(object["type"]),
|
||||
"preferred_username" => object["preferred_username"],
|
||||
"summary" => object["summary"],
|
||||
"url" => object["url"],
|
||||
"name" => object["name"]
|
||||
}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Convert an actor struct to an ActivityStream representation
|
||||
"""
|
||||
@impl Converter
|
||||
@spec model_to_as(ActorModel.t()) :: map()
|
||||
def model_to_as(%ActorModel{} = actor) do
|
||||
%{
|
||||
"type" => Atom.to_string(actor.type),
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"preferred_username" => actor.preferred_username,
|
||||
"name" => actor.name,
|
||||
"summary" => actor.summary,
|
||||
"following" => ActorModel.build_url(actor.preferred_username, :following),
|
||||
"followers" => ActorModel.build_url(actor.preferred_username, :followers),
|
||||
"inbox" => ActorModel.build_url(actor.preferred_username, :inbox),
|
||||
"outbox" => ActorModel.build_url(actor.preferred_username, :outbox),
|
||||
"id" => ActorModel.build_url(actor.preferred_username, :page),
|
||||
"url" => actor.url
|
||||
}
|
||||
end
|
||||
end
|
||||
96
lib/service/activity_pub/converters/comment.ex
Normal file
96
lib/service/activity_pub/converters/comment.ex
Normal file
@@ -0,0 +1,96 @@
|
||||
defmodule Mobilizon.Service.ActivityPub.Converters.Comment do
|
||||
@moduledoc """
|
||||
Comment converter
|
||||
|
||||
This module allows to convert events from ActivityStream format to our own internal one, and back
|
||||
"""
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events.Comment, as: CommentModel
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Service.ActivityPub.Converter
|
||||
alias Mobilizon.Service.ActivityPub
|
||||
alias MobilizonWeb.Router.Helpers, as: Routes
|
||||
alias MobilizonWeb.Endpoint
|
||||
require Logger
|
||||
|
||||
@behaviour Converter
|
||||
|
||||
@doc """
|
||||
Converts an AP object data to our internal data structure
|
||||
"""
|
||||
@impl Converter
|
||||
@spec as_to_model_data(map()) :: map()
|
||||
def as_to_model_data(object) do
|
||||
{:ok, %Actor{id: actor_id}} = Actors.get_or_fetch_by_url(object["actor"])
|
||||
Logger.debug("Inserting full comment")
|
||||
Logger.debug(inspect(object))
|
||||
|
||||
data = %{
|
||||
"text" => object["content"],
|
||||
"url" => object["id"],
|
||||
"actor_id" => actor_id,
|
||||
"in_reply_to_comment_id" => nil,
|
||||
"event_id" => nil,
|
||||
"uuid" => object["uuid"]
|
||||
}
|
||||
|
||||
# We fetch the parent object
|
||||
Logger.debug("We're fetching the parent object")
|
||||
|
||||
data =
|
||||
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())
|
||||
|
||||
# Anything else is kind of a MP
|
||||
{:error, parent} ->
|
||||
Logger.debug("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
|
||||
|
||||
data
|
||||
end
|
||||
|
||||
@doc """
|
||||
Make an AS comment object from an existing `Comment` structure.
|
||||
"""
|
||||
@impl Converter
|
||||
@spec model_to_as(CommentModel.t()) :: map()
|
||||
def model_to_as(%CommentModel{} = comment) do
|
||||
object = %{
|
||||
"type" => "Note",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"content" => comment.text,
|
||||
"actor" => comment.actor.url,
|
||||
"attributedTo" => comment.actor.url,
|
||||
"uuid" => comment.uuid,
|
||||
"id" => Routes.page_url(Endpoint, :comment, comment.uuid)
|
||||
}
|
||||
|
||||
if comment.in_reply_to_comment do
|
||||
object |> Map.put("inReplyTo", comment.in_reply_to_comment.url || comment.event.url)
|
||||
else
|
||||
object
|
||||
end
|
||||
end
|
||||
end
|
||||
70
lib/service/activity_pub/converters/event.ex
Normal file
70
lib/service/activity_pub/converters/event.ex
Normal file
@@ -0,0 +1,70 @@
|
||||
defmodule Mobilizon.Service.ActivityPub.Converters.Event do
|
||||
@moduledoc """
|
||||
Event converter
|
||||
|
||||
This module allows to convert events from ActivityStream format to our own internal one, and back
|
||||
"""
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Media
|
||||
alias Mobilizon.Media.Picture
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events.Event, as: EventModel
|
||||
alias Mobilizon.Service.ActivityPub.Converter
|
||||
|
||||
@behaviour Converter
|
||||
|
||||
@doc """
|
||||
Converts an AP object data to our internal data structure
|
||||
"""
|
||||
@impl Converter
|
||||
@spec as_to_model_data(map()) :: map()
|
||||
def as_to_model_data(object) do
|
||||
with {:ok, %Actor{id: actor_id}} <- Actors.get_actor_by_url(object["actor"]) do
|
||||
picture_id =
|
||||
with true <- Map.has_key?(object, "attachment"),
|
||||
%Picture{id: picture_id} <-
|
||||
Media.get_picture_by_url(
|
||||
object["attachment"]
|
||||
|> hd
|
||||
|> Map.get("url")
|
||||
|> hd
|
||||
|> Map.get("href")
|
||||
) do
|
||||
picture_id
|
||||
else
|
||||
_ -> nil
|
||||
end
|
||||
|
||||
%{
|
||||
"title" => object["name"],
|
||||
"description" => object["content"],
|
||||
"organizer_actor_id" => actor_id,
|
||||
"picture_id" => picture_id,
|
||||
"begins_on" => object["begins_on"],
|
||||
"category" => object["category"],
|
||||
"url" => object["id"],
|
||||
"uuid" => object["uuid"]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Convert an event struct to an ActivityStream representation
|
||||
"""
|
||||
@impl Converter
|
||||
@spec model_to_as(EventModel.t()) :: map()
|
||||
def model_to_as(%EventModel{} = event) do
|
||||
%{
|
||||
"type" => "Event",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"title" => event.title,
|
||||
"actor" => event.organizer_actor.url,
|
||||
"uuid" => event.uuid,
|
||||
"category" => event.category,
|
||||
"summary" => event.description,
|
||||
"publish_at" => (event.publish_at || event.inserted_at) |> DateTime.to_iso8601(),
|
||||
"updated_at" => event.updated_at |> DateTime.to_iso8601(),
|
||||
"id" => event.url
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -15,9 +15,9 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Events.Comment
|
||||
alias Mobilizon.Media.Picture
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Activity
|
||||
alias Mobilizon.Service.ActivityPub
|
||||
alias Ecto.Changeset
|
||||
require Logger
|
||||
alias MobilizonWeb.Router.Helpers, as: Routes
|
||||
@@ -108,23 +108,6 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
|
||||
Map.put_new_lazy(map, "published", &make_date/0)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Converts an AP object data to our internal data structure
|
||||
"""
|
||||
def object_to_event_data(object) do
|
||||
{:ok, %Actor{id: actor_id}} = Actors.get_actor_by_url(object["actor"])
|
||||
|
||||
%{
|
||||
"title" => object["name"],
|
||||
"description" => object["content"],
|
||||
"organizer_actor_id" => actor_id,
|
||||
"begins_on" => object["begins_on"],
|
||||
"category" => object["category"],
|
||||
"url" => object["id"],
|
||||
"uuid" => object["uuid"]
|
||||
}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Inserts a full object if it is contained in an activity.
|
||||
"""
|
||||
@@ -135,7 +118,8 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
|
||||
"""
|
||||
def insert_full_object(%{"object" => %{"type" => "Event"} = object_data})
|
||||
when is_map(object_data) do
|
||||
with object_data <- object_to_event_data(object_data),
|
||||
with object_data <-
|
||||
Mobilizon.Service.ActivityPub.Converters.Event.as_to_model_data(object_data),
|
||||
{:ok, _} <- Events.create_event(object_data) do
|
||||
:ok
|
||||
end
|
||||
@@ -155,60 +139,14 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
|
||||
"""
|
||||
def insert_full_object(%{"object" => %{"type" => "Note"} = object_data})
|
||||
when is_map(object_data) do
|
||||
Logger.debug("Inserting full comment")
|
||||
Logger.debug(inspect(object_data))
|
||||
|
||||
with {:ok, %Actor{id: actor_id}} <- Actors.get_or_fetch_by_url(object_data["actor"]) do
|
||||
data = %{
|
||||
"text" => object_data["content"],
|
||||
"url" => object_data["id"],
|
||||
"actor_id" => actor_id,
|
||||
"in_reply_to_comment_id" => nil,
|
||||
"event_id" => nil,
|
||||
"uuid" => object_data["uuid"]
|
||||
}
|
||||
|
||||
# We fetch the parent object
|
||||
Logger.debug("We're fetching the parent object")
|
||||
|
||||
data =
|
||||
if Map.has_key?(object_data, "inReplyTo") && object_data["inReplyTo"] != nil &&
|
||||
object_data["inReplyTo"] != "" do
|
||||
Logger.debug(fn -> "Object has inReplyTo #{object_data["inReplyTo"]}" end)
|
||||
|
||||
case ActivityPub.fetch_object_from_url(object_data["inReplyTo"]) do
|
||||
# Reply to an event (Comment)
|
||||
{:ok, %Event{id: id}} ->
|
||||
Logger.debug("Parent object is an event")
|
||||
data |> Map.put("event_id", id)
|
||||
|
||||
# Reply to a comment (Comment)
|
||||
{:ok, %Comment{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 |> Comment.get_thread_id())
|
||||
|
||||
# Anything else is kind of a MP
|
||||
{:error, object} ->
|
||||
Logger.debug("Parent object is something we don't handle")
|
||||
Logger.debug(inspect(object))
|
||||
data
|
||||
end
|
||||
else
|
||||
Logger.debug("No parent object for this comment")
|
||||
data
|
||||
end
|
||||
|
||||
with {:ok, _comment} <- Events.create_comment(data) do
|
||||
:ok
|
||||
else
|
||||
err ->
|
||||
Logger.error("Error while inserting a remote comment inside database")
|
||||
Logger.error(inspect(err))
|
||||
{:error, err}
|
||||
end
|
||||
with data <- Mobilizon.Service.ActivityPub.Converters.Comment.as_to_model_data(object_data),
|
||||
{:ok, _comment} <- Events.create_comment(data) do
|
||||
:ok
|
||||
else
|
||||
err ->
|
||||
Logger.error("Error while inserting a remote comment inside database")
|
||||
Logger.error(inspect(err))
|
||||
{:error, err}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -238,6 +176,43 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
|
||||
# Repo.one(query)
|
||||
# end
|
||||
|
||||
def make_picture_data(%Plug.Upload{} = picture) do
|
||||
with {:ok, picture} <- MobilizonWeb.Upload.store(picture) do
|
||||
picture
|
||||
else
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
|
||||
def make_picture_data(%Picture{file: file} = _picture) do
|
||||
%{
|
||||
"type" => "Document",
|
||||
"url" => [
|
||||
%{
|
||||
"type" => "Link",
|
||||
"mediaType" => file.content_type,
|
||||
"href" => file.url
|
||||
}
|
||||
],
|
||||
"name" => file.name
|
||||
}
|
||||
end
|
||||
|
||||
def make_picture_data(%{picture: picture}) do
|
||||
with {:ok, %{"url" => [%{"href" => url}]}} <- MobilizonWeb.Upload.store(picture.file),
|
||||
{:ok, %Picture{file: _file} = pic} <-
|
||||
Mobilizon.Media.create_picture(%{
|
||||
"file" => %{
|
||||
"url" => url,
|
||||
"name" => picture.name
|
||||
}
|
||||
}) do
|
||||
make_picture_data(pic)
|
||||
end
|
||||
end
|
||||
|
||||
def make_picture_data(nil), do: nil
|
||||
|
||||
@doc """
|
||||
Make an AP event object from an set of values
|
||||
"""
|
||||
@@ -246,6 +221,7 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
|
||||
String.t(),
|
||||
String.t(),
|
||||
String.t(),
|
||||
map(),
|
||||
list(),
|
||||
list(),
|
||||
map(),
|
||||
@@ -256,7 +232,7 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
|
||||
to,
|
||||
title,
|
||||
content_html,
|
||||
# attachments,
|
||||
picture \\ nil,
|
||||
tags \\ [],
|
||||
# _cw \\ nil,
|
||||
cc \\ [],
|
||||
@@ -266,14 +242,13 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
|
||||
Logger.debug("Making event data")
|
||||
uuid = Ecto.UUID.generate()
|
||||
|
||||
%{
|
||||
res = %{
|
||||
"type" => "Event",
|
||||
"to" => to,
|
||||
"cc" => cc,
|
||||
"content" => content_html,
|
||||
"name" => title,
|
||||
# "summary" => cw,
|
||||
# "attachment" => attachments,
|
||||
"begins_on" => metadata.begins_on,
|
||||
"category" => category,
|
||||
"actor" => actor,
|
||||
@@ -281,55 +256,8 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
|
||||
"uuid" => uuid,
|
||||
"tag" => tags |> Enum.map(fn {_, tag} -> tag end) |> Enum.uniq()
|
||||
}
|
||||
end
|
||||
|
||||
@spec make_event_data(Event.t(), list(String.t())) :: map()
|
||||
def make_event_data(
|
||||
%Event{} = event,
|
||||
to \\ ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
) do
|
||||
%{
|
||||
"type" => "Event",
|
||||
"to" => to,
|
||||
"title" => event.title,
|
||||
"actor" => event.organizer_actor.url,
|
||||
"uuid" => event.uuid,
|
||||
"category" => event.category,
|
||||
"summary" => event.description,
|
||||
"publish_at" => (event.publish_at || event.inserted_at) |> DateTime.to_iso8601(),
|
||||
"updated_at" => event.updated_at |> DateTime.to_iso8601(),
|
||||
"id" => Routes.page_url(Endpoint, :event, event.uuid)
|
||||
}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Make an AP comment object from an existing `Comment` structure.
|
||||
"""
|
||||
def make_comment_data(
|
||||
%Comment{
|
||||
text: text,
|
||||
actor: actor,
|
||||
uuid: uuid,
|
||||
in_reply_to_comment: reply_to,
|
||||
event: event
|
||||
},
|
||||
to \\ ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
) do
|
||||
object = %{
|
||||
"type" => "Note",
|
||||
"to" => to,
|
||||
"content" => text,
|
||||
"actor" => actor.url,
|
||||
"attributedTo" => actor.url,
|
||||
"uuid" => uuid,
|
||||
"id" => Routes.page_url(Endpoint, :comment, uuid)
|
||||
}
|
||||
|
||||
if reply_to do
|
||||
object |> Map.put("inReplyTo", reply_to.url || event.url)
|
||||
else
|
||||
object
|
||||
end
|
||||
if is_nil(picture), do: res, else: Map.put(res, "attachment", [make_picture_data(picture)])
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
||||
@@ -74,12 +74,19 @@ defmodule Mobilizon.Service.Export.Feed do
|
||||
|> Feed.generator("Mobilizon", uri: "https://joinmobilizon.org", version: version())
|
||||
|> Feed.entries(Enum.map(events, &get_entry/1))
|
||||
|
||||
feed = if actor.avatar_url, do: Feed.icon(feed, actor.avatar_url), else: feed
|
||||
feed =
|
||||
if actor.avatar do
|
||||
Feed.icon(feed, actor.avatar.url)
|
||||
else
|
||||
feed
|
||||
end
|
||||
|
||||
feed =
|
||||
if actor.banner_url,
|
||||
do: Feed.logo(feed, actor.banner_url),
|
||||
else: feed
|
||||
if actor.banner do
|
||||
Feed.logo(feed, actor.banner.url)
|
||||
else
|
||||
feed
|
||||
end
|
||||
|
||||
feed
|
||||
|> Feed.build()
|
||||
@@ -113,7 +120,8 @@ defmodule Mobilizon.Service.Export.Feed do
|
||||
|
||||
@spec fetch_events_from_token(String.t()) :: String.t()
|
||||
defp fetch_events_from_token(token) do
|
||||
with %FeedToken{actor: actor, user: %User{} = user} <- Events.get_feed_token(token) do
|
||||
with {:ok, _uuid} <- Ecto.UUID.cast(token),
|
||||
%FeedToken{actor: actor, user: %User{} = user} <- Events.get_feed_token(token) do
|
||||
case actor do
|
||||
%Actor{} = actor ->
|
||||
events = fetch_identity_going_to_events(actor)
|
||||
|
||||
@@ -65,7 +65,7 @@ defmodule Mobilizon.Service.Formatter do
|
||||
|
||||
@link_regex ~r/[0-9a-z+\-\.]+:[0-9a-z$-_.+!*'(),]+/ui
|
||||
|
||||
@uri_schemes Application.get_env(:pleroma, :uri_schemes, [])
|
||||
@uri_schemes Application.get_env(:mobilizon, :uri_schemes, [])
|
||||
@valid_schemes Keyword.get(@uri_schemes, :valid_schemes, [])
|
||||
|
||||
# # TODO: make it use something other than @link_regex
|
||||
|
||||
@@ -3,14 +3,19 @@ defimpl Mobilizon.Service.Metadata, for: Mobilizon.Actors.Actor do
|
||||
alias Mobilizon.Actors.Actor
|
||||
|
||||
def build_tags(%Actor{} = actor) do
|
||||
[
|
||||
tags = [
|
||||
Tag.tag(:meta, property: "og:title", content: Actor.display_name_and_username(actor)),
|
||||
Tag.tag(:meta, property: "og:url", content: actor.url),
|
||||
Tag.tag(:meta, property: "og:description", content: actor.summary),
|
||||
Tag.tag(:meta, property: "og:type", content: "profile"),
|
||||
Tag.tag(:meta, property: "profile:username", content: actor.preferred_username),
|
||||
Tag.tag(:meta, property: "og:image", content: actor.avatar_url),
|
||||
Tag.tag(:meta, property: "twitter:card", content: "summary")
|
||||
]
|
||||
|
||||
if is_nil(actor.avatar) do
|
||||
tags
|
||||
else
|
||||
tags ++ [Tag.tag(:meta, property: "og:image", content: actor.avatar.url)]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,16 +5,28 @@ defimpl Mobilizon.Service.Metadata, for: Mobilizon.Events.Event do
|
||||
alias MobilizonWeb.JsonLD.ObjectView
|
||||
|
||||
def build_tags(%Event{} = event) do
|
||||
[
|
||||
tags = [
|
||||
Tag.tag(:meta, property: "og:title", content: event.title),
|
||||
Tag.tag(:meta, property: "og:url", content: event.url),
|
||||
Tag.tag(:meta, property: "og:description", content: event.description),
|
||||
Tag.tag(:meta, property: "og:type", content: "website"),
|
||||
Tag.tag(:meta, property: "og:image", content: event.thumbnail),
|
||||
Tag.tag(:meta, property: "og:image", content: event.large_image),
|
||||
Tag.tag(:meta, property: "twitter:card", content: "summary_large_image"),
|
||||
~s{<script type="application/ld+json">#{json(event)}</script>} |> HTML.raw()
|
||||
Tag.tag(:meta, property: "og:type", content: "website")
|
||||
]
|
||||
|
||||
tags =
|
||||
if is_nil(event.picture) do
|
||||
tags
|
||||
else
|
||||
tags ++
|
||||
[
|
||||
Tag.tag(:meta, property: "og:image", content: event.picture.file.url)
|
||||
]
|
||||
end
|
||||
|
||||
tags ++
|
||||
[
|
||||
Tag.tag(:meta, property: "twitter:card", content: "summary_large_image"),
|
||||
~s{<script type="application/ld+json">#{json(event)}</script>} |> HTML.raw()
|
||||
]
|
||||
end
|
||||
|
||||
# Insert JSON-LD schema by hand because Tag.content_tag wants to escape it
|
||||
|
||||
Reference in New Issue
Block a user