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",
"value" => "sc:value",
"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.EventMetadata, as: EventMetadataConverter
alias Mobilizon.Federation.ActivityStream.Converter.Media, as: MediaConverter
alias Mobilizon.Service.TimezoneDetector
alias Mobilizon.Web.Endpoint
import Mobilizon.Federation.ActivityStream.Converter.Utils,
@ -49,11 +50,11 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
def as_to_model_data(object) do
case maybe_fetch_actor_and_attributed_to_id(object) do
{:ok, %Actor{id: actor_id}, attributed_to} ->
address_id = get_address(object["location"])
address = get_address(object["location"])
tags = fetch_tags(object["tag"])
mentions = fetch_mentions(object["tag"])
visibility = get_visibility(object)
options = get_options(object)
options = get_options(object, address)
metadata = get_metdata(object)
[description: description, picture_id: picture_id, medias: medias] =
@ -82,7 +83,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
uuid: object["uuid"],
tags: tags,
mentions: mentions,
physical_address_id: address_id,
physical_address_id: if(address, do: address.id, else: nil),
updated_at: object["updated"],
publish_at: object["published"],
language: object["inLanguage"]
@ -118,9 +119,9 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
"published" => (event.publish_at || event.inserted_at) |> date_to_string(),
"updated" => event.updated_at |> date_to_string(),
"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),
"endTime" => event.ends_on |> date_to_string(),
"endTime" => event.ends_on |> shift_tz(event.options.timezone) |> date_to_string(),
"tag" => event.tags |> build_tags(),
"maximumAttendeeCapacity" => event.options.maximum_attendee_capacity,
"repliesModerationOption" => event.options.comment_moderation,
@ -131,7 +132,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
"ical:status" => event.status |> to_string |> String.upcase(),
"id" => event.url,
"url" => event.url,
"inLanguage" => event.language
"inLanguage" => event.language,
"timezone" => event.options.timezone
}
|> maybe_add_physical_address(event)
|> maybe_add_event_picture(event)
@ -149,8 +151,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
end
# Get only elements that we have in EventOptions
@spec get_options(map) :: map
defp get_options(object) do
@spec get_options(map, Address.t() | nil) :: map
defp get_options(object, address) do
%{
maximum_attendee_capacity: object["maximumAttendeeCapacity"],
anonymous_participation: object["anonymousParticipationEnabled"],
@ -159,10 +161,29 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
object,
"repliesModerationOption",
if(Map.get(object, "commentsEnabled", true), do: :allow_all, else: :closed)
)
),
timezone: calculate_timezone(object, address)
}
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
attachments
|> Enum.filter(&(&1["type"] == "PropertyValue"))
@ -171,7 +192,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event 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
get_address(%{"id" => address_url})
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")
case Addresses.get_address_by_url(url) do
%Address{id: address_id} ->
address_id
%Address{} = address ->
address
_ ->
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
@spec do_get_address(map) :: integer | nil
@spec do_get_address(map) :: Address.t() | nil
defp do_get_address(map) do
map = AddressConverter.as_to_model_data(map)
case Addresses.create_address(map) do
{:ok, %Address{id: address_id}} ->
address_id
{:ok, %Address{} = address} ->
address
_ ->
nil
@ -217,6 +238,13 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
defp date_to_string(nil), do: nil
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
Enum.find_value(attachments, fn attachment ->
case attachment do