diff --git a/lib/mobilizon_web/views/json_ld/object_view.ex b/lib/mobilizon_web/views/json_ld/object_view.ex new file mode 100644 index 000000000..7d2686056 --- /dev/null +++ b/lib/mobilizon_web/views/json_ld/object_view.ex @@ -0,0 +1,57 @@ +defmodule MobilizonWeb.JsonLD.ObjectView do + use MobilizonWeb, :view + + alias Mobilizon.Events.{Event, Comment} + alias Mobilizon.Actors.Actor + alias Mobilizon.Addresses.Address + alias MobilizonWeb.JsonLD.ObjectView + + def render("event.json", %{event: %Event{} = event}) do + # TODO: event.description is actually markdown! + json_ld = %{ + "@context" => "https://schema.org", + "@type" => "Event", + "name" => event.title, + "description" => event.description, + "image" => [ + event.thumbnail, + event.large_image + ], + "performer" => %{ + "@type" => + if(event.organizer_actor.type == :Group, do: "PerformingGroup", else: "Person"), + "name" => Actor.display_name(event.organizer_actor) + }, + "location" => render_one(event.physical_address, ObjectView, "place.json", as: :address) + } + + json_ld = + if event.begins_on, + do: Map.put(json_ld, "startDate", DateTime.to_iso8601(event.begins_on)), + else: json_ld + + json_ld = + if event.ends_on, + do: Map.put(json_ld, "endDate", DateTime.to_iso8601(event.ends_on)), + else: json_ld + + json_ld + end + + def render("place.json", %{address: %Address{} = address}) do + %{ + "@type" => "Place", + "name" => address.description, + "address" => %{ + "@type" => "PostalAddress", + "streetAddress" => address.streetAddress, + "addressLocality" => address.addressLocality, + "postalCode" => address.postalCode, + "addressRegion" => address.addressRegion, + "addressCountry" => address.addressCountry + } + } + end + + def render("place.json", nil), do: %{} +end diff --git a/lib/service/metadata/event.ex b/lib/service/metadata/event.ex index 8a63d7b84..17fdc56ff 100644 --- a/lib/service/metadata/event.ex +++ b/lib/service/metadata/event.ex @@ -2,14 +2,17 @@ defimpl Mobilizon.Service.Metadata, for: Mobilizon.Events.Event do alias Phoenix.HTML alias Phoenix.HTML.Tag alias Mobilizon.Events.Event + alias MobilizonWeb.JsonLD.ObjectView def build_tags(%Event{} = event) do event |> do_build_tags() |> Enum.map(&HTML.safe_to_string/1) |> Enum.reduce("", fn tag, acc -> acc <> tag end) + |> Kernel.<>(build_json_ld_schema(event)) end + # Build OpenGraph & Twitter Tags defp do_build_tags(%Event{} = event) do [ Tag.tag(:meta, property: "og:title", content: event.title), @@ -21,4 +24,11 @@ defimpl Mobilizon.Service.Metadata, for: Mobilizon.Events.Event do Tag.tag(:meta, property: "twitter:card", content: "summary_large_image") ] end + + # Insert JSON-LD schema by hand because Tag.content_tag wants to escape it + defp build_json_ld_schema(%Event{} = event) do + "" + end end