defmodule Fishjam.Notification do @moduledoc false alias Fishjam.{Component, Peer, Room, Track} alias Fishjam.ServerMessage.{TrackAdded, TrackMetadataUpdated, TrackRemoved} defmodule RoomCreated do @moduledoc nil @enforce_keys [:room_id] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id() } end defmodule RoomDeleted do @moduledoc nil @enforce_keys [:room_id] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id() } end defmodule RoomCrashed do @moduledoc nil @enforce_keys [:room_id] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id() } end defmodule PeerAdded do @moduledoc nil @enforce_keys [:room_id, :peer_id] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id(), peer_id: Peer.id() } end defmodule PeerDeleted do @moduledoc nil @enforce_keys [:room_id, :peer_id] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id(), peer_id: Peer.id() } end defmodule PeerConnected do @moduledoc nil @enforce_keys [:room_id, :peer_id] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id(), peer_id: Peer.id() } end defmodule PeerDisconnected do @moduledoc nil @enforce_keys [:room_id, :peer_id] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id(), peer_id: Peer.id() } end defmodule PeerMetadataUpdated do @moduledoc nil @enforce_keys [:room_id, :peer_id, :metadata] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id(), peer_id: Peer.id(), metadata: any() } end defmodule PeerCrashed do @moduledoc nil @enforce_keys [:room_id, :peer_id] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id(), peer_id: Peer.id() } end defmodule ComponentCrashed do @moduledoc nil @enforce_keys [:room_id, :component_id] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id(), component_id: Component.id() } end defmodule HlsPlayable do @moduledoc nil @enforce_keys [:room_id, :component_id] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id(), component_id: Component.id() } end defmodule HlsUploaded do @moduledoc nil @enforce_keys [:room_id] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id() } end defmodule HlsUploadCrashed do @moduledoc nil @enforce_keys [:room_id] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id() } end defmodule ComponentTrackAdded do @moduledoc nil @enforce_keys [:room_id, :component_id, :track] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id(), component_id: Component.id(), track: Track.t() } end defmodule ComponentTrackMetadataUpdated do @moduledoc nil @enforce_keys [:room_id, :component_id, :track] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id(), component_id: Component.id(), track: Track.t() } end defmodule ComponentTrackRemoved do @moduledoc nil @enforce_keys [:room_id, :component_id, :track] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id(), component_id: Component.id(), track: Track.t() } end defmodule PeerTrackAdded do @moduledoc nil @enforce_keys [:room_id, :peer_id, :track] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id(), peer_id: Peer.id(), track: Track.t() } end defmodule PeerTrackMetadataUpdated do @moduledoc nil @enforce_keys [:room_id, :peer_id, :track] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id(), peer_id: Peer.id(), track: Track.t() } end defmodule PeerTrackRemoved do @moduledoc nil @enforce_keys [:room_id, :peer_id, :track] defstruct @enforce_keys @type t :: %__MODULE__{ room_id: Room.id(), peer_id: Peer.id(), track: Track.t() } end @discarded_fields [:__unknown_fields__] @doc false def to_notification(%module{} = message) when module in [TrackAdded, TrackMetadataUpdated, TrackRemoved] do {endpoint_type, endpoint_id} = message.endpoint_info notification_module = case {endpoint_type, module} do {:component_id, TrackAdded} -> ComponentTrackAdded {:component_id, TrackMetadataUpdated} -> ComponentTrackMetadataUpdated {:component_id, TrackRemoved} -> ComponentTrackRemoved {:peer_id, TrackAdded} -> PeerTrackAdded {:peer_id, TrackMetadataUpdated} -> PeerTrackMetadataUpdated {:peer_id, TrackRemoved} -> PeerTrackRemoved end discarded_fields = @discarded_fields ++ [:endpoint_info] message |> Map.from_struct() |> Map.drop(discarded_fields) |> Map.merge(%{ endpoint_type => endpoint_id, :track => from_proto_track(message.track) }) |> then(&struct!(notification_module, &1)) end def to_notification(%module{} = message) do notification_module = module |> Module.split() |> List.last() |> then(&Module.concat(__MODULE__, &1)) message |> Map.from_struct() |> Map.drop(@discarded_fields) |> then(&struct!(notification_module, &1)) end defp from_proto_track(track) do %Track{ id: track.id, type: from_proto_track_type(track.type), metadata: Jason.decode!(track.metadata) } end defp from_proto_track_type(:TRACK_TYPE_VIDEO), do: :video defp from_proto_track_type(:TRACK_TYPE_AUDIO), do: :audio end