Attach event ics files to event-related emails

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2020-12-21 15:47:26 +01:00
parent 37c6742660
commit b69daa7b54
No known key found for this signature in database
GPG Key ID: A061B9DDE0CA0773
7 changed files with 33 additions and 4 deletions

View File

@ -3,7 +3,7 @@ defmodule Mobilizon.Service.Export.ICalendar do
Export an event to iCalendar format. Export an event to iCalendar format.
""" """
alias Mobilizon.{Actors, Events, Users} alias Mobilizon.{Actors, Config, Events, Users}
alias Mobilizon.Actors.Actor alias Mobilizon.Actors.Actor
alias Mobilizon.Addresses.Address alias Mobilizon.Addresses.Address
alias Mobilizon.Events.{Event, FeedToken} alias Mobilizon.Events.{Event, FeedToken}
@ -11,6 +11,8 @@ defmodule Mobilizon.Service.Export.ICalendar do
alias Mobilizon.Storage.Page alias Mobilizon.Storage.Page
alias Mobilizon.Users.User alias Mobilizon.Users.User
@vendor "Mobilizon #{Config.instance_version()}"
@doc """ @doc """
Export a public event to iCalendar format. Export a public event to iCalendar format.
@ -19,12 +21,19 @@ defmodule Mobilizon.Service.Export.ICalendar do
@spec export_public_event(Event.t()) :: {:ok, String.t()} @spec export_public_event(Event.t()) :: {:ok, String.t()}
def export_public_event(%Event{visibility: visibility} = event) def export_public_event(%Event{visibility: visibility} = event)
when visibility in [:public, :unlisted] do when visibility in [:public, :unlisted] do
{:ok, %ICalendar{events: [do_export_event(event)]} |> ICalendar.to_ics(vendor: "Mobilizon")} export_event(event)
end end
@spec export_public_event(Event.t()) :: {:error, :event_not_public} @spec export_public_event(Event.t()) :: {:error, :event_not_public}
def export_public_event(%Event{}), do: {:error, :event_not_public} def export_public_event(%Event{}), do: {:error, :event_not_public}
@doc """
Export an event to iCalendar format
"""
def export_event(%Event{} = event) do
{:ok, %ICalendar{events: [do_export_event(event)]} |> ICalendar.to_ics(vendor: @vendor)}
end
@spec do_export_event(Event.t()) :: ICalendar.Event.t() @spec do_export_event(Event.t()) :: ICalendar.Event.t()
defp do_export_event(%Event{} = event) do defp do_export_event(%Event{} = event) do
%ICalendar.Event{ %ICalendar.Event{

View File

@ -6,7 +6,9 @@ defmodule Mobilizon.Web.Email do
use Bamboo.Phoenix, view: Mobilizon.Web.EmailView use Bamboo.Phoenix, view: Mobilizon.Web.EmailView
alias Ecto.UUID alias Ecto.UUID
alias Mobilizon.Config alias Mobilizon.{Config, Events}
alias Mobilizon.Events.Event
alias Mobilizon.Service.Export.ICalendar
alias Mobilizon.Web.EmailView alias Mobilizon.Web.EmailView
@spec base_email(keyword()) :: Bamboo.Email.t() @spec base_email(keyword()) :: Bamboo.Email.t()
@ -40,4 +42,18 @@ defmodule Mobilizon.Web.Email do
Timex.format!(DateTime.utc_now(), "{WDshort}, {D} {Mshort} {YYYY} {h24}:{m}:{s} {Z}") Timex.format!(DateTime.utc_now(), "{WDshort}, {D} {Mshort} {YYYY} {h24}:{m}:{s} {Z}")
end end
end end
def add_event_attachment(%Bamboo.Email{} = email, %Event{id: event_id}) do
with {:ok, %Event{} = event} <- Events.get_event_with_preload(event_id),
{:ok, event_ics_data} <- ICalendar.export_event(event) do
put_attachment(email, %Bamboo.Attachment{
filename: Slugger.slugify_downcase(event.title),
content_type: "text/calendar",
data: event_ics_data
})
else
_ ->
email
end
end
end end

View File

@ -46,6 +46,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)
|> Email.add_event_attachment(event)
|> render(:event_updated) |> render(:event_updated)
end end

View File

@ -30,6 +30,7 @@ defmodule Mobilizon.Web.Email.Notification do
|> assign(:locale, locale) |> assign(:locale, locale)
|> assign(:participant, participant) |> assign(:participant, participant)
|> assign(:subject, subject) |> assign(:subject, subject)
|> Email.add_event_attachment(event)
|> render(:before_event_notification) |> render(:before_event_notification)
end end

View File

@ -118,6 +118,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)
|> Email.add_event_attachment(event)
|> render(:event_participation_approved) |> render(:event_participation_approved)
end end

View File

@ -133,6 +133,7 @@ defmodule Mobilizon.Mixfile do
{:xml_builder, "~> 2.1.1", override: true}, {:xml_builder, "~> 2.1.1", override: true},
{:remote_ip, "~> 0.2.0"}, {:remote_ip, "~> 0.2.0"},
{:ex_cldr_languages, "~> 0.2.1"}, {:ex_cldr_languages, "~> 0.2.1"},
{:slugger, "~> 0.3"},
# Dev and test dependencies # Dev and test dependencies
{:phoenix_live_reload, "~> 1.2", only: [:dev, :e2e]}, {:phoenix_live_reload, "~> 1.2", only: [:dev, :e2e]},
{:ex_machina, "~> 2.3", only: [:dev, :test]}, {:ex_machina, "~> 2.3", only: [:dev, :test]},

View File

@ -17,7 +17,7 @@ defmodule Mobilizon.Service.ICalendarTest do
BEGIN:VCALENDAR BEGIN:VCALENDAR
CALSCALE:GREGORIAN CALSCALE:GREGORIAN
VERSION:2.0 VERSION:2.0
PRODID:-//ICalendar//Mobilizon//EN PRODID:-//ICalendar//Mobilizon #{Mobilizon.Config.instance_version()}//EN
BEGIN:VEVENT BEGIN:VEVENT
CATEGORIES:#{event.tags |> Enum.map(& &1.title) |> Enum.join(",")} CATEGORIES:#{event.tags |> Enum.map(& &1.title) |> Enum.join(",")}
DESCRIPTION:Ceci est une description avec une première phrase assez longue\\,\\n puis sur une seconde ligne DESCRIPTION:Ceci est une description avec une première phrase assez longue\\,\\n puis sur une seconde ligne