Improve json-ld metadata on event live streams

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2021-11-15 12:11:29 +01:00
parent bcf17fe30b
commit 85ceb1de47
No known key found for this signature in database
GPG Key ID: A061B9DDE0CA0773
2 changed files with 54 additions and 22 deletions

View File

@ -29,7 +29,7 @@ defmodule Mobilizon.Service.Metadata.Utils do
* Slices it to a limit and add an ellipsis character * Slices it to a limit and add an ellipsis character
* Returns a default description if text is empty * Returns a default description if text is empty
""" """
@spec process_description(String.t(), String.t(), integer()) :: String.t() @spec process_description(String.t(), String.t(), integer() | nil) :: String.t()
def process_description(description, locale \\ "en", limit \\ @slice_limit) def process_description(description, locale \\ "en", limit \\ @slice_limit)
def process_description(nil, locale, limit), do: process_description("", locale, limit) def process_description(nil, locale, limit), do: process_description("", locale, limit)
@ -56,6 +56,8 @@ defmodule Mobilizon.Service.Metadata.Utils do
defdelegate datetime_to_string(datetime, locale \\ "en", format \\ :medium), to: DateTime defdelegate datetime_to_string(datetime, locale \\ "en", format \\ :medium), to: DateTime
defdelegate render_address(address), to: Address defdelegate render_address(address), to: Address
defp maybe_slice(description, nil), do: description
defp maybe_slice(description, limit) do defp maybe_slice(description, limit) do
if String.length(description) > limit do if String.length(description) > limit do
description description

View File

@ -9,6 +9,9 @@ defmodule Mobilizon.Web.JsonLD.ObjectView do
alias Mobilizon.Web.JsonLD.ObjectView alias Mobilizon.Web.JsonLD.ObjectView
alias Mobilizon.Web.Router.Helpers, as: Routes alias Mobilizon.Web.Router.Helpers, as: Routes
import Mobilizon.Service.Metadata.Utils,
only: [process_description: 3]
@spec render(String.t(), map()) :: map() @spec render(String.t(), map()) :: map()
def render("group.json", %{group: %Actor{} = group}) do def render("group.json", %{group: %Actor{} = group}) do
res = %{ res = %{
@ -54,12 +57,12 @@ defmodule Mobilizon.Web.JsonLD.ObjectView do
"@context" => "https://schema.org", "@context" => "https://schema.org",
"@type" => "Event", "@type" => "Event",
"name" => event.title, "name" => event.title,
"description" => event.description, "description" => process_description(event.description, "en", nil),
# We assume for now performer == organizer # We assume for now performer == organizer
"performer" => organizer, "performer" => organizer,
"organizer" => organizer, "organizer" => organizer,
"location" => render_location(event), "location" => render_all_locations(event),
"eventAttendanceMode" => eventAttendanceMode(event), "eventAttendanceMode" => event |> attendance_mode() |> event_attendance_mode(),
"eventStatus" => "eventStatus" =>
if(event.status == :cancelled, if(event.status == :cancelled,
do: "https://schema.org/EventCancelled", do: "https://schema.org/EventCancelled",
@ -164,39 +167,66 @@ defmodule Mobilizon.Web.JsonLD.ObjectView do
defp reservation_status(:not_approved), do: "https://schema.org/ReservationHold" defp reservation_status(:not_approved), do: "https://schema.org/ReservationHold"
defp reservation_status(_), do: "https://schema.org/ReservationConfirmed" defp reservation_status(_), do: "https://schema.org/ReservationConfirmed"
@spec render_location(map()) :: map() | nil defp render_all_locations(%Event{} = event) do
defp render_location(%{physical_address: %Address{} = address}), []
do: render_one(address, ObjectView, "place.json", as: :address) |> render_location(event)
|> render_virtual_location(event)
end
@spec render_location(list(), map()) :: list()
defp render_location(locations, %{physical_address: %Address{} = address}),
do: locations ++ [render_one(address, ObjectView, "place.json", as: :address)]
defp render_location(locations, _), do: locations
# For now the Virtual Location of an event is it's own URL, # For now the Virtual Location of an event is it's own URL,
# but in the future it will be a special field # but in the future it will be a special field
defp render_location(%Event{url: event_url}) do defp render_virtual_location(locations, %Event{
%{ url: event_url,
metadata: metadata,
options: %EventOptions{is_online: is_online}
}) do
links = virtual_location_links(metadata)
fallback_links = if is_online, do: [event_url], else: []
links = if length(links) > 0, do: Enum.map(links, & &1.value), else: fallback_links
locations ++
Enum.map(
links,
&%{
"@type" => "VirtualLocation", "@type" => "VirtualLocation",
"url" => event_url "url" => &1
} }
)
end end
defp render_location(_), do: nil defp render_virtual_location(locations, _), do: locations
defp render_address(%{physical_address: %Address{} = address}), defp render_address(%{physical_address: %Address{} = address}),
do: render_one(address, ObjectView, "address.json", as: :address) do: render_one(address, ObjectView, "address.json", as: :address)
defp render_address(_), do: nil defp render_address(_), do: nil
@livestream_keys ["mz:live", "mz:visio"] defp event_attendance_mode(:online), do: "https://schema.org/OnlineEventAttendanceMode"
defp event_attendance_mode(:offline), do: "https://schema.org/OfflineEventAttendanceMode"
defp event_attendance_mode(:mixed), do: "https://schema.org/MixedEventAttendanceMode"
defp eventAttendanceMode(%Event{options: %EventOptions{is_online: true}}), defp attendance_mode(%Event{options: %EventOptions{is_online: true}}),
do: "https://schema.org/OnlineEventAttendanceMode" do: :online
defp eventAttendanceMode(%Event{physical_address: %Address{}, metadata: metadata}) do defp attendance_mode(%Event{physical_address: %Address{}, metadata: metadata}) do
if Enum.any?(metadata, &String.contains?(&1["key"], @livestream_keys)) do if metadata |> virtual_location_links() |> length() > 0 do
"https://schema.org/MixedEventAttendanceMode" :mixed
else else
"https://schema.org/OfflineEventAttendanceMode" :offline
end end
end end
defp eventAttendanceMode(%Event{}), defp attendance_mode(%Event{}),
do: "https://schema.org/OfflineEventAttendanceMode" do: :offline
@livestream_keys ["mz:live", "mz:visio"]
@spec virtual_location_links(list()) :: list()
defp virtual_location_links(metadata),
do: Enum.filter(metadata, &String.contains?(&1.key, @livestream_keys))
end end