Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement how many people are currently watching a video #13

Merged
merged 2 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,18 @@ An example response:
}
```

### `/api/v1/watching` (POST or GET)

Watching is a very simple request to determine how many people are currently watching a video. You can specify the video(s) by using the identifier or by querying for metadata.

The response will show you how many viewers are currently watching your request, here's an example response:

```json
{
"watching": 231
}
```

### `/api/v1/sources` (POST or GET)

Retrieve the number of plays per source using the video's `identifier` and/or `query` for metadata. A source refers to the location where your video is placed, which can be particularly useful when embedding the same video across multiple pages/sites.
Expand Down
15 changes: 15 additions & 0 deletions server/lib/mave_metrics/api.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,26 @@ defmodule MaveMetrics.API do
import Ecto.Query, warn: false
import EctoCase
alias MaveMetrics.{Repo, Video, Duration}
alias MaveMetricsWeb.Presence

@default_timeframe "7 days"
@default_interval "12 months"
@default_minimum_watch_seconds 1

def get_watching(%{"video" => query}) do
video_ids =
Video
|> where([v], fragment("? @> ?", v.metadata, ^query))
|> select([v], v.id)
|> Repo.all()

if video_ids == [] do
0
else
video_ids |> Enum.map(&map_size(Presence.list("video:#{&1}"))) |> Enum.sum()
end
end

def get_plays(%{"video" => query}, interval, timeframe, minimum_watch_seconds) do
interval = interval || @default_interval
timeframe = timeframe || @default_timeframe
Expand Down
2 changes: 2 additions & 0 deletions server/lib/mave_metrics/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ defmodule MaveMetrics.Application do
{Task.Supervisor, name: MaveMetrics.TaskSupervisor},
# Start the PubSub system
{Phoenix.PubSub, name: MaveMetrics.PubSub},
# Presence
MaveMetricsWeb.Presence,
# Start Finch
{Finch, name: MaveMetrics.Finch},
# Start cluster
Expand Down
9 changes: 9 additions & 0 deletions server/lib/mave_metrics_web/channels/session_channel.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule MaveMetricsWeb.SessionChannel do
use MaveMetricsWeb, :channel
alias MaveMetricsWeb.Presence

alias MaveMetrics.{Stats, Keys, Pipeline}

Expand Down Expand Up @@ -69,6 +70,8 @@ defmodule MaveMetricsWeb.SessionChannel do
video_id: video.id
})

Presence.track(self(), "video:#{video.id}", "#{session.id}", %{})

{
:noreply,
socket
Expand Down Expand Up @@ -97,6 +100,8 @@ defmodule MaveMetricsWeb.SessionChannel do
video_id: video_id
})

Presence.track(self(), "video:#{video_id}", "#{session_id}", %{})

{:noreply, socket}
end

Expand All @@ -116,6 +121,8 @@ defmodule MaveMetricsWeb.SessionChannel do
video_id: video_id
})

Presence.untrack(self(), "video:#{video_id}", "#{session_id}")

{:noreply, socket}
end

Expand Down Expand Up @@ -145,6 +152,8 @@ defmodule MaveMetricsWeb.SessionChannel do
session_id: session_id,
video_id: video_id
})

Presence.untrack(self(), "video:#{video_id}", "#{session_id}")
end

defp on_disconnect(_, _) do
Expand Down
27 changes: 27 additions & 0 deletions server/lib/mave_metrics_web/controllers/api/watching_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule MaveMetricsWeb.API.WatchingController do
use MaveMetricsWeb, :controller

alias MaveMetrics.API

def get_watching(conn, _params) do
{:ok, body, _conn} = Plug.Conn.read_body(conn)
params = Jason.decode!(body)
conn |> watching(params)
end

def watching(conn, %{"query" => filters} = params) do
result =
API.get_watching(filters)

conn
|> json(%{watching: result})
|> halt
end

def watching(conn, _params) do
conn
|> put_status(400)
|> json(%{error: "Requires a valid JSON query struct."})
|> halt
end
end
5 changes: 5 additions & 0 deletions server/lib/mave_metrics_web/presence.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule MaveMetricsWeb.Presence do
use Phoenix.Presence,
otp_app: :mave_metrics,
pubsub_server: MaveMetrics.PubSub
end
2 changes: 2 additions & 0 deletions server/lib/mave_metrics_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ defmodule MaveMetricsWeb.Router do
scope "/api/v1", MaveMetricsWeb do
pipe_through([:api, :require_api_authentication?])

post("/watching", API.WatchingController, :watching)
get("/watching", API.WatchingController, :get_watching)
post("/views", API.ViewsController, :views)
get("/views", API.ViewsController, :get_views)
post("/sources", API.SourcesController, :sources)
Expand Down
Loading