Federate metadata
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
d2cdde2d42
commit
d3a05b5568
@ -88,7 +88,10 @@ defmodule Mobilizon.Federation.ActivityPub.Utils do
|
|||||||
"participationMessage" => %{
|
"participationMessage" => %{
|
||||||
"@id" => "mz:participationMessage",
|
"@id" => "mz:participationMessage",
|
||||||
"@type" => "sc:Text"
|
"@type" => "sc:Text"
|
||||||
}
|
},
|
||||||
|
"PropertyValue" => "sc:PropertyValue",
|
||||||
|
"value" => "sc:value",
|
||||||
|
"propertyID" => "sc:propertyID"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,11 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
|||||||
alias Mobilizon.Addresses
|
alias Mobilizon.Addresses
|
||||||
alias Mobilizon.Addresses.Address
|
alias Mobilizon.Addresses.Address
|
||||||
alias Mobilizon.Events.Event, as: EventModel
|
alias Mobilizon.Events.Event, as: EventModel
|
||||||
|
alias Mobilizon.Medias.Media
|
||||||
|
|
||||||
alias Mobilizon.Federation.ActivityStream.{Converter, Convertible}
|
alias Mobilizon.Federation.ActivityStream.{Converter, Convertible}
|
||||||
alias Mobilizon.Federation.ActivityStream.Converter.Address, as: AddressConverter
|
alias Mobilizon.Federation.ActivityStream.Converter.Address, as: AddressConverter
|
||||||
|
alias Mobilizon.Federation.ActivityStream.Converter.EventMetadata, as: EventMetadataConverter
|
||||||
alias Mobilizon.Federation.ActivityStream.Converter.Media, as: MediaConverter
|
alias Mobilizon.Federation.ActivityStream.Converter.Media, as: MediaConverter
|
||||||
alias Mobilizon.Web.Endpoint
|
alias Mobilizon.Web.Endpoint
|
||||||
|
|
||||||
@ -53,6 +55,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
|||||||
{:mentions, mentions} <- {:mentions, fetch_mentions(object["tag"])},
|
{:mentions, mentions} <- {:mentions, fetch_mentions(object["tag"])},
|
||||||
{:visibility, visibility} <- {:visibility, get_visibility(object)},
|
{:visibility, visibility} <- {:visibility, get_visibility(object)},
|
||||||
{:options, options} <- {:options, get_options(object)},
|
{:options, options} <- {:options, get_options(object)},
|
||||||
|
{:metadata, metadata} <- {:metadata, get_metdata(object)},
|
||||||
[description: description, picture_id: picture_id, medias: medias] <-
|
[description: description, picture_id: picture_id, medias: medias] <-
|
||||||
process_pictures(object, actor_id) do
|
process_pictures(object, actor_id) do
|
||||||
%{
|
%{
|
||||||
@ -69,6 +72,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
|||||||
join_options: Map.get(object, "joinMode", "free"),
|
join_options: Map.get(object, "joinMode", "free"),
|
||||||
local: is_local(object["id"]),
|
local: is_local(object["id"]),
|
||||||
options: options,
|
options: options,
|
||||||
|
metadata: metadata,
|
||||||
status: object |> Map.get("ical:status", "CONFIRMED") |> String.downcase(),
|
status: object |> Map.get("ical:status", "CONFIRMED") |> String.downcase(),
|
||||||
online_address: object |> Map.get("attachment", []) |> get_online_address(),
|
online_address: object |> Map.get("attachment", []) |> get_online_address(),
|
||||||
phone_address: object["phoneAddress"],
|
phone_address: object["phoneAddress"],
|
||||||
@ -120,7 +124,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
|||||||
"repliesModerationOption" => event.options.comment_moderation,
|
"repliesModerationOption" => event.options.comment_moderation,
|
||||||
"commentsEnabled" => event.options.comment_moderation == :allow_all,
|
"commentsEnabled" => event.options.comment_moderation == :allow_all,
|
||||||
"anonymousParticipationEnabled" => event.options.anonymous_participation,
|
"anonymousParticipationEnabled" => event.options.anonymous_participation,
|
||||||
"attachment" => [],
|
"attachment" => Enum.map(event.metadata, &EventMetadataConverter.metadata_to_as/1),
|
||||||
"draft" => event.draft,
|
"draft" => event.draft,
|
||||||
"ical:status" => event.status |> to_string |> String.upcase(),
|
"ical:status" => event.status |> to_string |> String.upcase(),
|
||||||
"id" => event.url,
|
"id" => event.url,
|
||||||
@ -132,8 +136,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
|||||||
|> maybe_add_inline_media(event)
|
|> maybe_add_inline_media(event)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec attributed_to_or_default(Event.t()) :: Actor.t()
|
@spec attributed_to_or_default(EventModel.t()) :: Actor.t()
|
||||||
defp attributed_to_or_default(event) do
|
defp attributed_to_or_default(%EventModel{} = event) do
|
||||||
if(is_nil(event.attributed_to) or not Ecto.assoc_loaded?(event.attributed_to),
|
if(is_nil(event.attributed_to) or not Ecto.assoc_loaded?(event.attributed_to),
|
||||||
do: nil,
|
do: nil,
|
||||||
else: event.attributed_to
|
else: event.attributed_to
|
||||||
@ -156,6 +160,14 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp get_metdata(%{"attachment" => attachments}) do
|
||||||
|
attachments
|
||||||
|
|> Enum.filter(&(&1["type"] == "PropertyValue"))
|
||||||
|
|> Enum.map(&EventMetadataConverter.as_to_metadata/1)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp get_metdata(_), do: []
|
||||||
|
|
||||||
@spec get_address(map | binary | nil) :: integer | nil
|
@spec get_address(map | binary | nil) :: integer | nil
|
||||||
defp get_address(address_url) when is_binary(address_url) do
|
defp get_address(address_url) when is_binary(address_url) do
|
||||||
get_address(%{"id" => address_url})
|
get_address(%{"id" => address_url})
|
||||||
@ -219,55 +231,56 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec maybe_add_physical_address(map(), Event.t()) :: map()
|
@spec maybe_add_physical_address(map(), EventModel.t()) :: map()
|
||||||
defp maybe_add_physical_address(res, event) do
|
defp maybe_add_physical_address(res, %EventModel{
|
||||||
if is_nil(event.physical_address),
|
physical_address: %Address{} = physical_address
|
||||||
do: res,
|
}) do
|
||||||
else: Map.put(res, "location", AddressConverter.model_to_as(event.physical_address))
|
Map.put(res, "location", AddressConverter.model_to_as(physical_address))
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec maybe_add_event_picture(map(), Event.t()) :: map()
|
defp maybe_add_physical_address(res, %EventModel{physical_address: _}), do: res
|
||||||
defp maybe_add_event_picture(res, event) do
|
|
||||||
if is_nil(event.picture),
|
@spec maybe_add_event_picture(map(), EventModel.t()) :: map()
|
||||||
do: res,
|
defp maybe_add_event_picture(res, %EventModel{picture: %Media{} = picture}) do
|
||||||
else:
|
Map.update(
|
||||||
Map.update(
|
res,
|
||||||
res,
|
"attachment",
|
||||||
"attachment",
|
[],
|
||||||
[],
|
&(&1 ++
|
||||||
&(&1 ++
|
[
|
||||||
[
|
picture
|
||||||
event.picture
|
|> MediaConverter.model_to_as()
|
||||||
|> MediaConverter.model_to_as()
|
|> Map.put("name", @banner_picture_name)
|
||||||
|> Map.put("name", @banner_picture_name)
|
])
|
||||||
])
|
)
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec maybe_add_online_address(map(), Event.t()) :: map()
|
defp maybe_add_event_picture(res, %EventModel{picture: _}), do: res
|
||||||
defp maybe_add_online_address(res, event) do
|
|
||||||
if is_nil(event.online_address),
|
@spec maybe_add_online_address(map(), EventModel.t()) :: map()
|
||||||
do: res,
|
defp maybe_add_online_address(res, %EventModel{online_address: online_address})
|
||||||
else:
|
when is_binary(online_address) do
|
||||||
Map.update(
|
Map.update(
|
||||||
res,
|
res,
|
||||||
"attachment",
|
"attachment",
|
||||||
[],
|
[],
|
||||||
&(&1 ++
|
&(&1 ++
|
||||||
[
|
[
|
||||||
%{
|
%{
|
||||||
"type" => "Link",
|
"type" => "Link",
|
||||||
"href" => event.online_address,
|
"href" => online_address,
|
||||||
"mediaType" => "text/html",
|
"mediaType" => "text/html",
|
||||||
"name" => @online_address_name
|
"name" => @online_address_name
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec maybe_add_inline_media(map(), Event.t()) :: map()
|
defp maybe_add_online_address(res, %EventModel{online_address: _}), do: res
|
||||||
defp maybe_add_inline_media(res, event) do
|
|
||||||
medias = Enum.map(event.media, &MediaConverter.model_to_as/1)
|
@spec maybe_add_inline_media(map(), EventModel.t()) :: map()
|
||||||
|
defp maybe_add_inline_media(res, %EventModel{media: media}) do
|
||||||
|
medias = Enum.map(media, &MediaConverter.model_to_as/1)
|
||||||
|
|
||||||
Map.update(
|
Map.update(
|
||||||
res,
|
res,
|
||||||
|
70
lib/federation/activity_stream/converter/event_metadata.ex
Normal file
70
lib/federation/activity_stream/converter/event_metadata.ex
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
defmodule Mobilizon.Federation.ActivityStream.Converter.EventMetadata do
|
||||||
|
@moduledoc """
|
||||||
|
Module to convert and validate event metadata
|
||||||
|
"""
|
||||||
|
|
||||||
|
alias Mobilizon.Events.EventMetadata
|
||||||
|
|
||||||
|
@property_value "PropertyValue"
|
||||||
|
|
||||||
|
def metadata_to_as(%EventMetadata{type: :boolean, value: value, key: key})
|
||||||
|
when value in ["true", "false"] do
|
||||||
|
%{
|
||||||
|
"type" => @property_value,
|
||||||
|
"propertyID" => key,
|
||||||
|
"value" => String.to_existing_atom(value)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def metadata_to_as(%EventMetadata{type: :integer, value: value, key: key}) do
|
||||||
|
%{
|
||||||
|
"type" => @property_value,
|
||||||
|
"propertyID" => key,
|
||||||
|
"value" => String.to_integer(value)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def metadata_to_as(%EventMetadata{type: :float, value: value, key: key}) do
|
||||||
|
{value, _} = Float.parse(value)
|
||||||
|
|
||||||
|
%{
|
||||||
|
"type" => @property_value,
|
||||||
|
"propertyID" => key,
|
||||||
|
"value" => value
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def metadata_to_as(%EventMetadata{type: :string, value: value, key: key} = metadata) do
|
||||||
|
additional = if is_nil(metadata.title), do: %{}, else: %{"name" => metadata.title}
|
||||||
|
|
||||||
|
Map.merge(
|
||||||
|
%{
|
||||||
|
"type" => @property_value,
|
||||||
|
"propertyID" => key,
|
||||||
|
"value" => value
|
||||||
|
},
|
||||||
|
additional
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def as_to_metadata(%{"type" => @property_value, "propertyID" => key, "value" => value})
|
||||||
|
when is_boolean(value) do
|
||||||
|
%{type: :boolean, key: key, value: to_string(value)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def as_to_metadata(%{"type" => @property_value, "propertyID" => key, "value" => value})
|
||||||
|
when is_float(value) do
|
||||||
|
%{type: :float, key: key, value: to_string(value)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def as_to_metadata(%{"type" => @property_value, "propertyID" => key, "value" => value})
|
||||||
|
when is_integer(value) do
|
||||||
|
%{type: :integer, key: key, value: to_string(value)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def as_to_metadata(%{"type" => @property_value, "propertyID" => key, "value" => value} = args)
|
||||||
|
when is_binary(value) do
|
||||||
|
additional = if Map.has_key?(args, "name"), do: %{title: Map.get(args, "name")}, else: %{}
|
||||||
|
Map.merge(%{type: :string, key: key, value: value}, additional)
|
||||||
|
end
|
||||||
|
end
|
@ -7,7 +7,7 @@ defmodule Mobilizon.Events.EventMetadata do
|
|||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
import EctoEnum
|
import EctoEnum
|
||||||
|
|
||||||
defenum(EventMetadataTypeEnum, string: 0, integer: 1, boolean: 2)
|
defenum(EventMetadataTypeEnum, string: 0, integer: 1, boolean: 2, float: 3)
|
||||||
|
|
||||||
@type t :: %__MODULE__{
|
@type t :: %__MODULE__{
|
||||||
key: String.t(),
|
key: String.t(),
|
||||||
|
@ -0,0 +1,101 @@
|
|||||||
|
defmodule Mobilizon.Federation.ActivityStream.Converter.EventMetadataTest do
|
||||||
|
@moduledoc """
|
||||||
|
Module to test converting from EventMetadata to AS
|
||||||
|
"""
|
||||||
|
use Mobilizon.DataCase
|
||||||
|
import Mobilizon.Factory
|
||||||
|
alias Mobilizon.Events.EventMetadata
|
||||||
|
alias Mobilizon.Federation.ActivityStream.Converter.EventMetadata, as: EventMetadataConverter
|
||||||
|
|
||||||
|
@property_value "PropertyValue"
|
||||||
|
|
||||||
|
describe "metadata_to_as/1" do
|
||||||
|
test "convert a simple metadata" do
|
||||||
|
%EventMetadata{} = metadata = build(:event_metadata)
|
||||||
|
|
||||||
|
assert %{"propertyID" => metadata.key, "value" => metadata.value, "type" => @property_value} ==
|
||||||
|
EventMetadataConverter.metadata_to_as(metadata)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "convert a boolean" do
|
||||||
|
%EventMetadata{} = metadata = build(:event_metadata, type: :boolean, value: "false")
|
||||||
|
|
||||||
|
assert %{"propertyID" => metadata.key, "value" => false, "type" => @property_value} ==
|
||||||
|
EventMetadataConverter.metadata_to_as(metadata)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "convert an integer" do
|
||||||
|
%EventMetadata{} = metadata = build(:event_metadata, type: :integer, value: "36")
|
||||||
|
|
||||||
|
assert %{"propertyID" => metadata.key, "value" => 36, "type" => @property_value} ==
|
||||||
|
EventMetadataConverter.metadata_to_as(metadata)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "convert a float" do
|
||||||
|
%EventMetadata{} = metadata = build(:event_metadata, type: :float, value: "36.53")
|
||||||
|
|
||||||
|
assert %{"propertyID" => metadata.key, "value" => 36.53, "type" => @property_value} ==
|
||||||
|
EventMetadataConverter.metadata_to_as(metadata)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "convert custom metadata with title" do
|
||||||
|
%EventMetadata{} = metadata = build(:event_metadata, title: "hello")
|
||||||
|
|
||||||
|
assert %{
|
||||||
|
"propertyID" => metadata.key,
|
||||||
|
"value" => metadata.value,
|
||||||
|
"name" => "hello",
|
||||||
|
"type" => @property_value
|
||||||
|
} ==
|
||||||
|
EventMetadataConverter.metadata_to_as(metadata)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "as_to_metadata/1" do
|
||||||
|
test "parse a simple metadata" do
|
||||||
|
assert %{key: "somekey", value: "somevalue", type: :string} ==
|
||||||
|
EventMetadataConverter.as_to_metadata(%{
|
||||||
|
"propertyID" => "somekey",
|
||||||
|
"value" => "somevalue",
|
||||||
|
"type" => @property_value
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "parse a boolean metadata" do
|
||||||
|
assert %{key: "somekey", value: "false", type: :boolean} ==
|
||||||
|
EventMetadataConverter.as_to_metadata(%{
|
||||||
|
"propertyID" => "somekey",
|
||||||
|
"value" => false,
|
||||||
|
"type" => @property_value
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "parse an integer metadata" do
|
||||||
|
assert %{key: "somekey", value: "4", type: :integer} ==
|
||||||
|
EventMetadataConverter.as_to_metadata(%{
|
||||||
|
"propertyID" => "somekey",
|
||||||
|
"value" => 4,
|
||||||
|
"type" => @property_value
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "parse a float metadata" do
|
||||||
|
assert %{key: "somekey", value: "4.36", type: :float} ==
|
||||||
|
EventMetadataConverter.as_to_metadata(%{
|
||||||
|
"propertyID" => "somekey",
|
||||||
|
"value" => 4.36,
|
||||||
|
"type" => @property_value
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "parse a custom metadata with title" do
|
||||||
|
assert %{key: "somekey", value: "somevalue", type: :string, title: "title"} ==
|
||||||
|
EventMetadataConverter.as_to_metadata(%{
|
||||||
|
"propertyID" => "somekey",
|
||||||
|
"value" => "somevalue",
|
||||||
|
"name" => "title",
|
||||||
|
"type" => @property_value
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -183,6 +183,7 @@ defmodule Mobilizon.Factory do
|
|||||||
visibility: :public,
|
visibility: :public,
|
||||||
tags: build_list(3, :tag),
|
tags: build_list(3, :tag),
|
||||||
mentions: [],
|
mentions: [],
|
||||||
|
metadata: build_list(2, :event_metadata),
|
||||||
local: true,
|
local: true,
|
||||||
publish_at: DateTime.utc_now(),
|
publish_at: DateTime.utc_now(),
|
||||||
url: Routes.page_url(Endpoint, :event, uuid),
|
url: Routes.page_url(Endpoint, :event, uuid),
|
||||||
@ -458,4 +459,12 @@ defmodule Mobilizon.Factory do
|
|||||||
uri: sequence("https://someshare.uri/p/12")
|
uri: sequence("https://someshare.uri/p/12")
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def event_metadata_factory do
|
||||||
|
%Mobilizon.Events.EventMetadata{
|
||||||
|
key: sequence("mz:custom:something"),
|
||||||
|
value: sequence("a value"),
|
||||||
|
type: :string
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user