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
|
||||
alias Philomena.Repo
|
||||
|
||||
alias Philomena.Channels.AutomaticUpdater
|
||||
alias Philomena.Channels.Channel
|
||||
alias Philomena.Channels.PicartoChannel
|
||||
alias Philomena.Channels.PiczelChannel
|
||||
alias Philomena.Notifications
|
||||
|
||||
@doc """
|
||||
Updates all the tracked channels for which an update
|
||||
scheme is known.
|
||||
Updates all the tracked channels for which an update scheme is known.
|
||||
"""
|
||||
def update_tracked_channels! do
|
||||
now = DateTime.utc_now() |> DateTime.truncate(:second)
|
||||
|
||||
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)
|
||||
AutomaticUpdater.update_tracked_channels!()
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
@ -103,6 +69,24 @@ defmodule Philomena.Channels do
|
|||
|> Repo.update()
|
||||
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 """
|
||||
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
|
||||
@api_online "https://api.picarto.tv/api/v1/online?adult=true&gaming=true"
|
||||
|
||||
@spec live_channels(DateTime.t()) :: map()
|
||||
def live_channels(now) do
|
||||
@spec live_channels() :: map()
|
||||
def live_channels do
|
||||
@api_online
|
||||
|> PhilomenaProxy.Http.get()
|
||||
|> case do
|
||||
{:ok, %{body: body, status: 200}} ->
|
||||
body
|
||||
|> Jason.decode!()
|
||||
|> Map.new(&{&1["name"], fetch(&1, now)})
|
||||
|> Map.new(&{&1["name"], fetch(&1)})
|
||||
|
||||
_error ->
|
||||
%{}
|
||||
end
|
||||
end
|
||||
|
||||
defp fetch(api, now) do
|
||||
defp fetch(api) do
|
||||
%{
|
||||
title: api["title"],
|
||||
is_live: true,
|
||||
nsfw: api["adult"],
|
||||
viewers: api["viewers"],
|
||||
thumbnail_url: api["thumbnails"]["web"],
|
||||
last_fetched_at: now,
|
||||
last_live_at: now,
|
||||
description: nil
|
||||
}
|
||||
end
|
||||
|
|
|
@ -1,30 +1,28 @@
|
|||
defmodule Philomena.Channels.PiczelChannel do
|
||||
@api_online "https://api.piczel.tv/api/streams"
|
||||
|
||||
@spec live_channels(DateTime.t()) :: map()
|
||||
def live_channels(now) do
|
||||
@spec live_channels() :: map()
|
||||
def live_channels do
|
||||
@api_online
|
||||
|> PhilomenaProxy.Http.get()
|
||||
|> case do
|
||||
{:ok, %{body: body, status: 200}} ->
|
||||
body
|
||||
|> Jason.decode!()
|
||||
|> Map.new(&{&1["slug"], fetch(&1, now)})
|
||||
|> Map.new(&{&1["slug"], fetch(&1)})
|
||||
|
||||
_error ->
|
||||
%{}
|
||||
end
|
||||
end
|
||||
|
||||
defp fetch(api, now) do
|
||||
defp fetch(api) do
|
||||
%{
|
||||
title: api["title"],
|
||||
is_live: api["live"],
|
||||
nsfw: api["adult"],
|
||||
viewers: api["viewers"],
|
||||
thumbnail_url: api["user"]["avatar"]["avatar"]["url"],
|
||||
last_fetched_at: now,
|
||||
last_live_at: now
|
||||
thumbnail_url: api["user"]["avatar"]["avatar"]["url"]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue