Federate timezone

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2021-10-12 11:10:16 +02:00
parent 38cb9d3c9f
commit 4ca831a5b3
No known key found for this signature in database
GPG Key ID: A061B9DDE0CA0773
2 changed files with 48 additions and 16 deletions

View File

@ -114,7 +114,11 @@ defmodule Mobilizon.Federation.ActivityPub.Utils do
"PropertyValue" => "sc:PropertyValue", "PropertyValue" => "sc:PropertyValue",
"value" => "sc:value", "value" => "sc:value",
"propertyID" => "sc:propertyID", "propertyID" => "sc:propertyID",
"inLanguage" => "sc:inLanguage" "inLanguage" => "sc:inLanguage",
"timezone" => %{
"@id" => "mz:timezone",
"@type" => "sc:Text"
}
} }
] ]
} }

View File

@ -16,6 +16,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
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.EventMetadata, as: EventMetadataConverter
alias Mobilizon.Federation.ActivityStream.Converter.Media, as: MediaConverter alias Mobilizon.Federation.ActivityStream.Converter.Media, as: MediaConverter
alias Mobilizon.Service.TimezoneDetector
alias Mobilizon.Web.Endpoint alias Mobilizon.Web.Endpoint
import Mobilizon.Federation.ActivityStream.Converter.Utils, import Mobilizon.Federation.ActivityStream.Converter.Utils,
@ -49,11 +50,11 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
def as_to_model_data(object) do def as_to_model_data(object) do
case maybe_fetch_actor_and_attributed_to_id(object) do case maybe_fetch_actor_and_attributed_to_id(object) do
{:ok, %Actor{id: actor_id}, attributed_to} -> {:ok, %Actor{id: actor_id}, attributed_to} ->
address_id = get_address(object["location"]) address = get_address(object["location"])
tags = fetch_tags(object["tag"]) tags = fetch_tags(object["tag"])
mentions = fetch_mentions(object["tag"]) mentions = fetch_mentions(object["tag"])
visibility = get_visibility(object) visibility = get_visibility(object)
options = get_options(object) options = get_options(object, address)
metadata = get_metdata(object) metadata = get_metdata(object)
[description: description, picture_id: picture_id, medias: medias] = [description: description, picture_id: picture_id, medias: medias] =
@ -82,7 +83,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
uuid: object["uuid"], uuid: object["uuid"],
tags: tags, tags: tags,
mentions: mentions, mentions: mentions,
physical_address_id: address_id, physical_address_id: if(address, do: address.id, else: nil),
updated_at: object["updated"], updated_at: object["updated"],
publish_at: object["published"], publish_at: object["published"],
language: object["inLanguage"] language: object["inLanguage"]
@ -118,9 +119,9 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
"published" => (event.publish_at || event.inserted_at) |> date_to_string(), "published" => (event.publish_at || event.inserted_at) |> date_to_string(),
"updated" => event.updated_at |> date_to_string(), "updated" => event.updated_at |> date_to_string(),
"mediaType" => "text/html", "mediaType" => "text/html",
"startTime" => event.begins_on |> date_to_string(), "startTime" => event.begins_on |> shift_tz(event.options.timezone) |> date_to_string(),
"joinMode" => to_string(event.join_options), "joinMode" => to_string(event.join_options),
"endTime" => event.ends_on |> date_to_string(), "endTime" => event.ends_on |> shift_tz(event.options.timezone) |> date_to_string(),
"tag" => event.tags |> build_tags(), "tag" => event.tags |> build_tags(),
"maximumAttendeeCapacity" => event.options.maximum_attendee_capacity, "maximumAttendeeCapacity" => event.options.maximum_attendee_capacity,
"repliesModerationOption" => event.options.comment_moderation, "repliesModerationOption" => event.options.comment_moderation,
@ -131,7 +132,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
"ical:status" => event.status |> to_string |> String.upcase(), "ical:status" => event.status |> to_string |> String.upcase(),
"id" => event.url, "id" => event.url,
"url" => event.url, "url" => event.url,
"inLanguage" => event.language "inLanguage" => event.language,
"timezone" => event.options.timezone
} }
|> maybe_add_physical_address(event) |> maybe_add_physical_address(event)
|> maybe_add_event_picture(event) |> maybe_add_event_picture(event)
@ -149,8 +151,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
end end
# Get only elements that we have in EventOptions # Get only elements that we have in EventOptions
@spec get_options(map) :: map @spec get_options(map, Address.t() | nil) :: map
defp get_options(object) do defp get_options(object, address) do
%{ %{
maximum_attendee_capacity: object["maximumAttendeeCapacity"], maximum_attendee_capacity: object["maximumAttendeeCapacity"],
anonymous_participation: object["anonymousParticipationEnabled"], anonymous_participation: object["anonymousParticipationEnabled"],
@ -159,10 +161,29 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
object, object,
"repliesModerationOption", "repliesModerationOption",
if(Map.get(object, "commentsEnabled", true), do: :allow_all, else: :closed) if(Map.get(object, "commentsEnabled", true), do: :allow_all, else: :closed)
) ),
timezone: calculate_timezone(object, address)
} }
end end
defp calculate_timezone(%{"timezone" => timezone}, %Address{geom: geom}) do
TimezoneDetector.detect(
timezone,
geom,
"Etc/UTC"
)
end
defp calculate_timezone(_object, nil), do: nil
defp calculate_timezone(_object, %Address{geom: geom}) do
TimezoneDetector.detect(
nil,
geom,
"Etc/UTC"
)
end
defp get_metdata(%{"attachment" => attachments}) do defp get_metdata(%{"attachment" => attachments}) do
attachments attachments
|> Enum.filter(&(&1["type"] == "PropertyValue")) |> Enum.filter(&(&1["type"] == "PropertyValue"))
@ -171,7 +192,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
defp get_metdata(_), do: [] defp get_metdata(_), do: []
@spec get_address(map | binary | nil) :: integer | nil @spec get_address(map | binary | nil) :: Address.t() | 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})
end end
@ -180,8 +201,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
Logger.debug("Address with an URL, let's check against our own database") Logger.debug("Address with an URL, let's check against our own database")
case Addresses.get_address_by_url(url) do case Addresses.get_address_by_url(url) do
%Address{id: address_id} -> %Address{} = address ->
address_id address
_ -> _ ->
Logger.debug("not in our database, let's try to create it") Logger.debug("not in our database, let's try to create it")
@ -196,13 +217,13 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
defp get_address(nil), do: nil defp get_address(nil), do: nil
@spec do_get_address(map) :: integer | nil @spec do_get_address(map) :: Address.t() | nil
defp do_get_address(map) do defp do_get_address(map) do
map = AddressConverter.as_to_model_data(map) map = AddressConverter.as_to_model_data(map)
case Addresses.create_address(map) do case Addresses.create_address(map) do
{:ok, %Address{id: address_id}} -> {:ok, %Address{} = address} ->
address_id address
_ -> _ ->
nil nil
@ -217,6 +238,13 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
defp date_to_string(nil), do: nil defp date_to_string(nil), do: nil
defp date_to_string(%DateTime{} = date), do: DateTime.to_iso8601(date) defp date_to_string(%DateTime{} = date), do: DateTime.to_iso8601(date)
@spec shift_tz(DateTime.t(), String.t() | nil) :: DateTime.t()
defp shift_tz(%DateTime{} = date, timezone) when is_binary(timezone) do
DateTime.shift_zone!(date, timezone)
end
defp shift_tz(datetime, _tz), do: datetime
defp get_online_address(attachments) do defp get_online_address(attachments) do
Enum.find_value(attachments, fn attachment -> Enum.find_value(attachments, fn attachment ->
case attachment do case attachment do