defmodule Mobilizon.GraphQL.API.Participations do @moduledoc """ Common API to join events and groups. """ alias Mobilizon.Actors.Actor alias Mobilizon.Events alias Mobilizon.Events.{Event, Participant} alias Mobilizon.Federation.ActivityPub.{Actions, Activity} alias Mobilizon.Service.Notifications.Scheduler alias Mobilizon.Web.Email.Participation @spec join(Event.t(), Actor.t(), map()) :: {:ok, Activity.t(), Participant.t()} | {:error, :already_participant} def join(%Event{id: event_id} = event, %Actor{id: actor_id} = actor, args \\ %{}) do case Mobilizon.Events.get_participant(event_id, actor_id, args) do {:ok, %Participant{}} -> {:error, :already_participant} {:error, :participant_not_found} -> Actions.Join.join(event, actor, Map.get(args, :local, true), %{metadata: args}) end end @spec leave(Event.t(), Actor.t(), map()) :: {:ok, Activity.t(), Participant.t()} | {:error, :is_only_organizer | :participant_not_found | Ecto.Changeset.t()} def leave(%Event{} = event, %Actor{} = actor, args \\ %{}), do: Actions.Leave.leave(event, actor, Map.get(args, :local, true), %{metadata: args}) @doc """ Update participation status """ @spec update(Participant.t(), Actor.t(), atom()) :: {:ok, Activity.t(), Participant.t()} | {:error, Ecto.Changeset.t()} def update(%Participant{} = participation, %Actor{} = moderator, :participant), do: accept(participation, moderator) def update(%Participant{} = participation, %Actor{} = _moderator, :not_approved) do with {:ok, %Participant{} = participant} <- Events.update_participant(participation, %{role: :not_approved}) do Scheduler.pending_participation_notification(participation.event) {:ok, nil, participant} end end def update(%Participant{} = participation, %Actor{} = moderator, :rejected), do: reject(participation, moderator) @spec accept(Participant.t(), Actor.t()) :: {:ok, Activity.t(), Participant.t()} | {:error, Ecto.Changeset.t()} defp accept( %Participant{} = participation, %Actor{} = moderator ) do case Actions.Accept.accept( :join, participation, true, %{"actor" => moderator.url} ) do {:ok, activity, %Participant{role: :participant} = participation} -> Participation.send_emails_to_local_user(participation) {:ok, activity, participation} {:error, err} -> {:error, err} end end @spec reject(Participant.t(), Actor.t()) :: {:ok, Activity.t(), Participant.t()} defp reject( %Participant{} = participation, %Actor{} = moderator ) do with {:ok, activity, %Participant{role: :rejected} = participation} <- Actions.Reject.reject( :join, participation, true, %{"actor" => moderator.url} ), :ok <- Participation.send_emails_to_local_user(participation) do {:ok, activity, participation} end end end