Embed json-ld metadata on events in emails

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2021-10-13 12:57:54 +02:00
parent 555ae867ea
commit 676fab7871
No known key found for this signature in database
GPG key ID: A061B9DDE0CA0773
5 changed files with 60 additions and 3 deletions

View file

@ -18,6 +18,7 @@ defmodule Mobilizon.Web.Email do
|> put_header("Reply-To", Config.instance_email_reply_to()) |> put_header("Reply-To", Config.instance_email_reply_to())
|> maybe_put_date_header() |> maybe_put_date_header()
|> maybe_put_message_id() |> maybe_put_message_id()
|> assign(:jsonLDMetadata, nil)
|> assign(:instance_name, Config.instance_name()) |> assign(:instance_name, Config.instance_name())
|> put_html_layout({EmailView, "email.html"}) |> put_html_layout({EmailView, "email.html"})
|> put_text_layout({EmailView, "email.text"}) |> put_text_layout({EmailView, "email.text"})

View file

@ -47,6 +47,11 @@ defmodule Mobilizon.Web.Email.Event do
title: old_event.title title: old_event.title
) )
json_ld =
"participation.json"
|> ObjectView.render(%{participant: %Participant{participant | event: event, actor: actor}})
|> Jason.encode!()
Email.base_email(to: {Actor.display_name(actor), email}, subject: subject) Email.base_email(to: {Actor.display_name(actor), email}, subject: subject)
|> assign(:locale, locale) |> assign(:locale, locale)
|> assign(:event, event) |> assign(:event, event)
@ -54,6 +59,7 @@ defmodule Mobilizon.Web.Email.Event do
|> assign(:changes, changes) |> assign(:changes, changes)
|> assign(:subject, subject) |> assign(:subject, subject)
|> assign(:timezone, timezone) |> assign(:timezone, timezone)
|> assign(:jsonLDMetadata, json_ld)
|> Email.add_event_attachment(event) |> Email.add_event_attachment(event)
|> render(:event_updated) |> render(:event_updated)
end end

View file

@ -8,11 +8,11 @@ defmodule Mobilizon.Web.Email.Participation do
import Mobilizon.Web.Gettext import Mobilizon.Web.Gettext
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Config alias Mobilizon.{Config, Events, Users}
alias Mobilizon.Events.{Event, Participant} alias Mobilizon.Events.{Event, Participant}
alias Mobilizon.Users
alias Mobilizon.Users.User alias Mobilizon.Users.User
alias Mobilizon.Web.Email alias Mobilizon.Web.Email
alias Mobilizon.Web.JsonLD.ObjectView
@doc """ @doc """
Send participation emails to local user Send participation emails to local user
@ -117,6 +117,7 @@ defmodule Mobilizon.Web.Email.Participation do
|> assign(:locale, locale) |> assign(:locale, locale)
|> assign(:event, event) |> assign(:event, event)
|> assign(:subject, subject) |> assign(:subject, subject)
|> assign(:jsonLDMetadata, json_ld(participant))
|> Email.add_event_attachment(event) |> Email.add_event_attachment(event)
|> render(:event_participation_approved) |> render(:event_participation_approved)
end end
@ -139,7 +140,16 @@ defmodule Mobilizon.Web.Email.Participation do
Email.base_email(to: email, subject: subject) Email.base_email(to: email, subject: subject)
|> assign(:locale, locale) |> assign(:locale, locale)
|> assign(:participant, participant) |> assign(:participant, participant)
|> assign(:jsonLDMetadata, json_ld(participant))
|> assign(:subject, subject) |> assign(:subject, subject)
|> render(:anonymous_participation_confirmation) |> render(:anonymous_participation_confirmation)
end end
defp json_ld(participant) do
event = Events.get_event_with_preload!(participant.event_id)
"participation.json"
|> ObjectView.render(%{participant: %Participant{participant | event: event}})
|> Jason.encode!()
end
end end

View file

@ -41,6 +41,9 @@
/* ANDROID CENTER FIX */ /* ANDROID CENTER FIX */
div[style*="margin: 16px 0;"] { margin: 0 !important; } div[style*="margin: 16px 0;"] { margin: 0 !important; }
</style> </style>
<%= if @jsonLDMetadata do %>
<script type="application/ld+json"><%= @jsonLDMetadata |> raw %></script>
<% end %>
</head> </head>
<body style="background-color: #ECEBF2; margin: 0 !important; padding: 0 !important;mso-line-height-rule: exactly;"> <body style="background-color: #ECEBF2; margin: 0 !important; padding: 0 !important;mso-line-height-rule: exactly;">
<table border="0" cellpadding="0" cellspacing="0" width="100%"> <table border="0" cellpadding="0" cellspacing="0" width="100%">

View file

@ -3,10 +3,11 @@ defmodule Mobilizon.Web.JsonLD.ObjectView do
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Addresses.Address alias Mobilizon.Addresses.Address
alias Mobilizon.Events.Event alias Mobilizon.Events.{Event, Participant, ParticipantRole}
alias Mobilizon.Posts.Post alias Mobilizon.Posts.Post
alias Mobilizon.Web.Endpoint alias Mobilizon.Web.Endpoint
alias Mobilizon.Web.JsonLD.ObjectView alias Mobilizon.Web.JsonLD.ObjectView
alias Mobilizon.Web.Router.Helpers, as: Routes
@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
@ -25,6 +26,13 @@ defmodule Mobilizon.Web.JsonLD.ObjectView do
"name" => Actor.display_name(event.organizer_actor) "name" => Actor.display_name(event.organizer_actor)
} }
organizer =
if event.organizer_actor.avatar do
Map.put(organizer, "image", event.organizer_actor.avatar.url)
else
organizer
end
json_ld = %{ json_ld = %{
"@context" => "https://schema.org", "@context" => "https://schema.org",
"@type" => "Event", "@type" => "Event",
@ -94,6 +102,35 @@ defmodule Mobilizon.Web.JsonLD.ObjectView do
} }
end end
def render("participation.json", %{
participant: %Participant{} = participant
}) do
res = %{
"@context" => "http://schema.org",
"@type" => "EventReservation",
"underName" => %{
"@type" => "Person",
"name" => participant.actor.name || participant.actor.preferred_username
},
"reservationFor" => render("event.json", %{event: participant.event}),
"reservationStatus" => reservation_status(participant.role),
"modifiedTime" => participant.updated_at,
"modifyReservationUrl" => Routes.page_url(Endpoint, :event, participant.event.uuid)
}
if participant.code do
Map.put(res, "reservationNumber", participant.code)
else
res
end
end
@spec reservation_status(ParticipantRole.t()) :: String.t()
defp reservation_status(:rejected), do: "https://schema.org/ReservationCancelled"
defp reservation_status(:not_confirmed), do: "https://schema.org/ReservationPending"
defp reservation_status(:not_approved), do: "https://schema.org/ReservationHold"
defp reservation_status(_), do: "https://schema.org/ReservationConfirmed"
@spec render_location(map()) :: map() | nil @spec render_location(map()) :: map() | nil
defp render_location(%{physical_address: %Address{} = address}), defp render_location(%{physical_address: %Address{} = address}),
do: render_one(address, ObjectView, "place.json", as: :address) do: render_one(address, ObjectView, "place.json", as: :address)