mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-27 13:47:58 +01:00
Merge pull request #312 from philomena-dev/channel-extraction
Channel automatic update move
This commit is contained in:
commit
d799c9d1bd
4 changed files with 94 additions and 50 deletions
|
@ -6,49 +6,15 @@ defmodule Philomena.Channels do
|
||||||
import Ecto.Query, warn: false
|
import Ecto.Query, warn: false
|
||||||
alias Philomena.Repo
|
alias Philomena.Repo
|
||||||
|
|
||||||
|
alias Philomena.Channels.AutomaticUpdater
|
||||||
alias Philomena.Channels.Channel
|
alias Philomena.Channels.Channel
|
||||||
alias Philomena.Channels.PicartoChannel
|
|
||||||
alias Philomena.Channels.PiczelChannel
|
|
||||||
alias Philomena.Notifications
|
alias Philomena.Notifications
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Updates all the tracked channels for which an update
|
Updates all the tracked channels for which an update scheme is known.
|
||||||
scheme is known.
|
|
||||||
"""
|
"""
|
||||||
def update_tracked_channels! do
|
def update_tracked_channels! do
|
||||||
now = DateTime.utc_now() |> DateTime.truncate(:second)
|
AutomaticUpdater.update_tracked_channels!()
|
||||||
|
|
||||||
picarto_channels = PicartoChannel.live_channels(now)
|
|
||||||
live_picarto_channels = Map.keys(picarto_channels)
|
|
||||||
|
|
||||||
piczel_channels = PiczelChannel.live_channels(now)
|
|
||||||
live_piczel_channels = Map.keys(piczel_channels)
|
|
||||||
|
|
||||||
# Update all channels which are offline to reflect offline status
|
|
||||||
offline_query =
|
|
||||||
from c in Channel,
|
|
||||||
where: c.type == "PicartoChannel" and c.short_name not in ^live_picarto_channels,
|
|
||||||
or_where: c.type == "PiczelChannel" and c.short_name not in ^live_piczel_channels
|
|
||||||
|
|
||||||
Repo.update_all(offline_query, set: [is_live: false, updated_at: now])
|
|
||||||
|
|
||||||
# Update all channels which are online to reflect online status using
|
|
||||||
# changeset functions
|
|
||||||
online_query =
|
|
||||||
from c in Channel,
|
|
||||||
where: c.type == "PicartoChannel" and c.short_name in ^live_picarto_channels,
|
|
||||||
or_where: c.type == "PiczelChannel" and c.short_name in ^live_picarto_channels
|
|
||||||
|
|
||||||
online_query
|
|
||||||
|> Repo.all()
|
|
||||||
|> Enum.map(fn
|
|
||||||
%{type: "PicartoChannel", short_name: name} = channel ->
|
|
||||||
Channel.update_changeset(channel, Map.get(picarto_channels, name, []))
|
|
||||||
|
|
||||||
%{type: "PiczelChannel", short_name: name} = channel ->
|
|
||||||
Channel.update_changeset(channel, Map.get(piczel_channels, name, []))
|
|
||||||
end)
|
|
||||||
|> Enum.map(&Repo.update!/1)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -103,6 +69,24 @@ defmodule Philomena.Channels do
|
||||||
|> Repo.update()
|
|> Repo.update()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Updates a channel's state when it goes live.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> update_channel_state(channel, %{field: new_value})
|
||||||
|
{:ok, %Channel{}}
|
||||||
|
|
||||||
|
iex> update_channel_state(channel, %{field: bad_value})
|
||||||
|
{:error, %Ecto.Changeset{}}
|
||||||
|
|
||||||
|
"""
|
||||||
|
def update_channel_state(%Channel{} = channel, attrs) do
|
||||||
|
channel
|
||||||
|
|> Channel.update_changeset(attrs)
|
||||||
|
|> Repo.update()
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Deletes a Channel.
|
Deletes a Channel.
|
||||||
|
|
||||||
|
|
64
lib/philomena/channels/automatic_updater.ex
Normal file
64
lib/philomena/channels/automatic_updater.ex
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
defmodule Philomena.Channels.AutomaticUpdater do
|
||||||
|
@moduledoc """
|
||||||
|
Automatic update routine for streams.
|
||||||
|
|
||||||
|
Calls APIs for each stream provider to remove channels which are no longer online,
|
||||||
|
and to restore channels which are currently online.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import Ecto.Query, warn: false
|
||||||
|
alias Philomena.Repo
|
||||||
|
|
||||||
|
alias Philomena.Channels
|
||||||
|
alias Philomena.Channels.Channel
|
||||||
|
alias Philomena.Channels.PicartoChannel
|
||||||
|
alias Philomena.Channels.PiczelChannel
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Updates all the tracked channels for which an update scheme is known.
|
||||||
|
"""
|
||||||
|
def update_tracked_channels! do
|
||||||
|
now = DateTime.utc_now(:second)
|
||||||
|
Enum.each(providers(), &update_provider(&1, now))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp providers do
|
||||||
|
[
|
||||||
|
{"PicartoChannel", PicartoChannel.live_channels()},
|
||||||
|
{"PiczelChannel", PiczelChannel.live_channels()}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
defp update_provider({provider_name, live_channels}, now) do
|
||||||
|
channel_names = Map.keys(live_channels)
|
||||||
|
|
||||||
|
provider_name
|
||||||
|
|> update_offline_query(channel_names, now)
|
||||||
|
|> Repo.update_all([])
|
||||||
|
|
||||||
|
provider_name
|
||||||
|
|> online_query(channel_names)
|
||||||
|
|> Repo.all()
|
||||||
|
|> Enum.each(&update_online_channel(&1, live_channels, now))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp update_offline_query(provider_name, channel_names, now) do
|
||||||
|
from c in Channel,
|
||||||
|
where: c.type == ^provider_name and c.short_name not in ^channel_names,
|
||||||
|
update: [set: [is_live: false, updated_at: ^now]]
|
||||||
|
end
|
||||||
|
|
||||||
|
defp online_query(provider_name, channel_names) do
|
||||||
|
from c in Channel,
|
||||||
|
where: c.type == ^provider_name and c.short_name in ^channel_names
|
||||||
|
end
|
||||||
|
|
||||||
|
defp update_online_channel(channel, live_channels, now) do
|
||||||
|
attrs =
|
||||||
|
live_channels
|
||||||
|
|> Map.get(channel.short_name, %{})
|
||||||
|
|> Map.merge(%{last_live_at: now, last_fetched_at: now})
|
||||||
|
|
||||||
|
Channels.update_channel_state(channel, attrs)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,30 +1,28 @@
|
||||||
defmodule Philomena.Channels.PicartoChannel do
|
defmodule Philomena.Channels.PicartoChannel do
|
||||||
@api_online "https://api.picarto.tv/api/v1/online?adult=true&gaming=true"
|
@api_online "https://api.picarto.tv/api/v1/online?adult=true&gaming=true"
|
||||||
|
|
||||||
@spec live_channels(DateTime.t()) :: map()
|
@spec live_channels() :: map()
|
||||||
def live_channels(now) do
|
def live_channels do
|
||||||
@api_online
|
@api_online
|
||||||
|> PhilomenaProxy.Http.get()
|
|> PhilomenaProxy.Http.get()
|
||||||
|> case do
|
|> case do
|
||||||
{:ok, %{body: body, status: 200}} ->
|
{:ok, %{body: body, status: 200}} ->
|
||||||
body
|
body
|
||||||
|> Jason.decode!()
|
|> Jason.decode!()
|
||||||
|> Map.new(&{&1["name"], fetch(&1, now)})
|
|> Map.new(&{&1["name"], fetch(&1)})
|
||||||
|
|
||||||
_error ->
|
_error ->
|
||||||
%{}
|
%{}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp fetch(api, now) do
|
defp fetch(api) do
|
||||||
%{
|
%{
|
||||||
title: api["title"],
|
title: api["title"],
|
||||||
is_live: true,
|
is_live: true,
|
||||||
nsfw: api["adult"],
|
nsfw: api["adult"],
|
||||||
viewers: api["viewers"],
|
viewers: api["viewers"],
|
||||||
thumbnail_url: api["thumbnails"]["web"],
|
thumbnail_url: api["thumbnails"]["web"],
|
||||||
last_fetched_at: now,
|
|
||||||
last_live_at: now,
|
|
||||||
description: nil
|
description: nil
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,30 +1,28 @@
|
||||||
defmodule Philomena.Channels.PiczelChannel do
|
defmodule Philomena.Channels.PiczelChannel do
|
||||||
@api_online "https://api.piczel.tv/api/streams"
|
@api_online "https://api.piczel.tv/api/streams"
|
||||||
|
|
||||||
@spec live_channels(DateTime.t()) :: map()
|
@spec live_channels() :: map()
|
||||||
def live_channels(now) do
|
def live_channels do
|
||||||
@api_online
|
@api_online
|
||||||
|> PhilomenaProxy.Http.get()
|
|> PhilomenaProxy.Http.get()
|
||||||
|> case do
|
|> case do
|
||||||
{:ok, %{body: body, status: 200}} ->
|
{:ok, %{body: body, status: 200}} ->
|
||||||
body
|
body
|
||||||
|> Jason.decode!()
|
|> Jason.decode!()
|
||||||
|> Map.new(&{&1["slug"], fetch(&1, now)})
|
|> Map.new(&{&1["slug"], fetch(&1)})
|
||||||
|
|
||||||
_error ->
|
_error ->
|
||||||
%{}
|
%{}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp fetch(api, now) do
|
defp fetch(api) do
|
||||||
%{
|
%{
|
||||||
title: api["title"],
|
title: api["title"],
|
||||||
is_live: api["live"],
|
is_live: api["live"],
|
||||||
nsfw: api["adult"],
|
nsfw: api["adult"],
|
||||||
viewers: api["viewers"],
|
viewers: api["viewers"],
|
||||||
thumbnail_url: api["user"]["avatar"]["avatar"]["url"],
|
thumbnail_url: api["user"]["avatar"]["avatar"]["url"]
|
||||||
last_fetched_at: now,
|
|
||||||
last_live_at: now
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue