You've already forked tribes-plugin-sender
forked from tribes/tribes-plugin-template
3e288a7e95
Rename Sender plugin identity to tribe-one-sender across manifest, runtime API routes, metrics, e2e fixtures, and tests.
109 lines
2.9 KiB
Elixir
109 lines
2.9 KiB
Elixir
defmodule TribeOne.TribesPlugin.SenderWeb.StreamingAPIPlug do
|
|
@moduledoc false
|
|
|
|
import Plug.Conn
|
|
|
|
alias TribeOne.TribesPlugin.Sender.{Playback, Stats}
|
|
alias Tribes.RequestInfo
|
|
|
|
def init(opts), do: opts
|
|
|
|
def call(
|
|
%{
|
|
method: "GET",
|
|
path_info: ["plugins-api", "tribe-one-sender", "streams", stream_id, "playback"]
|
|
} =
|
|
conn,
|
|
_opts
|
|
) do
|
|
case Playback.playback_info(stream_id) do
|
|
{:ok, payload} -> json(conn, 200, payload)
|
|
{:error, :not_live} -> json(conn, 404, %{"error" => "not_live"})
|
|
{:error, _reason} -> json(conn, 404, %{"error" => "not_found"})
|
|
end
|
|
end
|
|
|
|
def call(
|
|
%{method: "POST", path_info: ["plugins-api", "tribe-one-sender", "player-events"]} = conn,
|
|
_opts
|
|
) do
|
|
{event, body, conn} = read_event(conn)
|
|
request_info = RequestInfo.fetch(conn)
|
|
record_result = record_player_event(event, request_info)
|
|
|
|
:telemetry.execute(
|
|
[:sender, :player, :event],
|
|
%{count: 1},
|
|
%{
|
|
body: body,
|
|
event: event,
|
|
remote_ip: conn.remote_ip,
|
|
request_ip: request_info.ip,
|
|
trusted_proxy?: request_info.trusted_proxy?
|
|
}
|
|
)
|
|
|
|
json(conn, 202, player_event_response(record_result))
|
|
end
|
|
|
|
def call(conn, _opts) do
|
|
json(conn, 404, %{"error" => "not_found"})
|
|
end
|
|
|
|
defp json(conn, status, payload) do
|
|
conn
|
|
|> put_resp_content_type("application/json")
|
|
|> send_resp(status, JSON.encode!(payload))
|
|
end
|
|
|
|
defp read_event(conn) do
|
|
cond do
|
|
event_params?(conn.body_params) ->
|
|
{conn.body_params, JSON.encode!(conn.body_params), conn}
|
|
|
|
event_params?(conn.params) ->
|
|
{conn.params, JSON.encode!(conn.params), conn}
|
|
|
|
true ->
|
|
read_raw_event(conn)
|
|
end
|
|
end
|
|
|
|
defp read_raw_event(conn) do
|
|
{:ok, body, conn} = read_body(conn)
|
|
{decode_body(body), body, conn}
|
|
end
|
|
|
|
defp decode_body(body) do
|
|
case JSON.decode(body) do
|
|
{:ok, decoded} when is_map(decoded) -> decoded
|
|
_other -> %{}
|
|
end
|
|
end
|
|
|
|
defp record_player_event(
|
|
%{
|
|
"event" => event,
|
|
"stream_id" => stream_id,
|
|
"generation_id" => generation_id,
|
|
"viewer_session_id" => viewer_session_id
|
|
},
|
|
%RequestInfo{trusted_proxy?: false, ip: remote_ip}
|
|
)
|
|
when event in ["heartbeat", "playback.started"] do
|
|
Stats.record_viewer_heartbeat(stream_id, generation_id, viewer_session_id, remote_ip)
|
|
end
|
|
|
|
defp record_player_event(_event, _request_info), do: :ignored
|
|
|
|
defp event_params?(%Plug.Conn.Unfetched{}), do: false
|
|
defp event_params?(params) when is_map(params), do: map_size(params) > 0
|
|
defp event_params?(_params), do: false
|
|
|
|
defp player_event_response(viewer_count) when is_integer(viewer_count) do
|
|
%{"ok" => true, "viewer_count" => viewer_count}
|
|
end
|
|
|
|
defp player_event_response(_record_result), do: %{"ok" => true}
|
|
end
|