Skip to content

Commit

Permalink
Change Channel to Source (#12)
Browse files Browse the repository at this point in the history
* Ensure channel detail lookup doesn't download the video - oops

* Ran the needful migrations for replacing channels with sources

* got media source test back working

* channel tasks test

* Media indexing worker test

* media tests

* Got all tests working except controller tests

* got all tests working

* Renamed Channel struct to Source

* renamed ChannelTasks

* More renaming; renamed channel details module

* Removed Channel yt-dlp module, instead throwing things in the VideoCollection module

* Renamed what looks like the last of the outstanding data
  • Loading branch information
kieraneglin authored Feb 3, 2024
1 parent 977b69b commit 366fd80
Show file tree
Hide file tree
Showing 46 changed files with 806 additions and 763 deletions.
4 changes: 2 additions & 2 deletions .iex.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ alias Pinchflat.Repo
alias Pinchflat.Tasks.Task
alias Pinchflat.Media.MediaItem
alias Pinchflat.Media.MediaMetadata
alias Pinchflat.MediaSource.Channel
alias Pinchflat.MediaSource.Source
alias Pinchflat.Profiles.MediaProfile

alias Pinchflat.Tasks
alias Pinchflat.Media
alias Pinchflat.Profiles
alias Pinchflat.MediaSource

alias Pinchflat.MediaClient.{ChannelDetails, VideoDownloader}
alias Pinchflat.MediaClient.{SourceDetails, VideoDownloader}
8 changes: 4 additions & 4 deletions lib/pinchflat/media.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule Pinchflat.Media do
alias Pinchflat.Repo
alias Pinchflat.Tasks
alias Pinchflat.Media.MediaItem
alias Pinchflat.MediaSource.Channel
alias Pinchflat.MediaSource.Source

@doc """
Returns the list of media_items. Returns [%MediaItem{}, ...].
Expand All @@ -18,15 +18,15 @@ defmodule Pinchflat.Media do
end

@doc """
Returns a list of pending media_items for a given channel, where
Returns a list of pending media_items for a given source, where
pending means the `media_filepath` is `nil`.
Returns [%MediaItem{}, ...].
"""
def list_pending_media_items_for(%Channel{} = channel) do
def list_pending_media_items_for(%Source{} = source) do
from(
m in MediaItem,
where: m.channel_id == ^channel.id and is_nil(m.media_filepath)
where: m.source_id == ^source.id and is_nil(m.media_filepath)
)
|> Repo.all()
end
Expand Down
10 changes: 5 additions & 5 deletions lib/pinchflat/media/media_item.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ defmodule Pinchflat.Media.MediaItem do
import Ecto.Changeset

alias Pinchflat.Tasks.Task
alias Pinchflat.MediaSource.Channel
alias Pinchflat.MediaSource.Source
alias Pinchflat.Media.MediaMetadata

@required_fields ~w(media_id channel_id)a
@allowed_fields ~w(title media_id media_filepath channel_id subtitle_filepaths)a
@required_fields ~w(media_id source_id)a
@allowed_fields ~w(title media_id media_filepath source_id subtitle_filepaths)a

schema "media_items" do
field :title, :string
Expand All @@ -22,7 +22,7 @@ defmodule Pinchflat.Media.MediaItem do
# Will very likely revisit because I can't leave well-enough alone.
field :subtitle_filepaths, {:array, {:array, :string}}, default: []

belongs_to :channel, Channel
belongs_to :source, Source

has_one :metadata, MediaMetadata, on_replace: :update

Expand All @@ -37,6 +37,6 @@ defmodule Pinchflat.Media.MediaItem do
|> cast(attrs, @allowed_fields)
|> cast_assoc(:metadata, with: &MediaMetadata.changeset/2, required: false)
|> validate_required(@required_fields)
|> unique_constraint([:media_id, :channel_id])
|> unique_constraint([:media_id, :source_id])
end
end
32 changes: 0 additions & 32 deletions lib/pinchflat/media_client/backends/yt_dlp/channel.ex

This file was deleted.

59 changes: 39 additions & 20 deletions lib/pinchflat/media_client/backends/yt_dlp/video_collection.ex
Original file line number Diff line number Diff line change
@@ -1,28 +1,47 @@
defmodule Pinchflat.MediaClient.Backends.YtDlp.VideoCollection do
@moduledoc """
Contains utilities for working with collections of videos (ie: channels, playlists).
Contains utilities for working with collections of
videos (aka: a source [ie: channels, playlists]).
"""

alias Pinchflat.MediaClient.SourceDetails

@doc """
Returns a list of strings representing the video ids in the collection.
Returns {:ok, [binary()]} | {:error, any, ...}.
"""
def get_video_ids(url, command_opts \\ []) do
runner = Application.get_env(:pinchflat, :yt_dlp_runner)
opts = command_opts ++ [:simulate, :skip_download]

case runner.run(url, opts, "%(id)s") do
{:ok, output} -> {:ok, String.split(output, "\n", trim: true)}
res -> res
end
end

@doc """
Gets a source's ID and name from its URL.
Meant to be included in other modules but can be used on its own. Channels and playlists
will have many of their own methods, but also share a lot of methods. This module is for
those shared methods.
yt-dlp does not _really_ have source-specific functions, so
instead we're fetching just the first video (using playlist_end: 1)
and parsing the source ID and name from _its_ metadata
Returns {:ok, %SourceDetails{}} | {:error, any, ...}.
"""
def get_source_details(source_url) do
opts = [:skip_download, playlist_end: 1]

defmacro __using__(_) do
quote do
@doc """
Returns a list of strings representing the video ids in the collection.
Returns {:ok, [binary()]} | {:error, any, ...}.
"""
def get_video_ids(url, command_opts \\ []) do
runner = Application.get_env(:pinchflat, :yt_dlp_runner)
opts = command_opts ++ [:simulate, :skip_download]

case runner.run(url, opts, "%(id)s") do
{:ok, output} -> {:ok, String.split(output, "\n", trim: true)}
res -> res
end
end
with {:ok, output} <- backend_runner().run(source_url, opts, "%(.{channel,channel_id})j"),
{:ok, parsed_json} <- Phoenix.json_library().decode(output) do
{:ok, SourceDetails.new(parsed_json["channel_id"], parsed_json["channel"])}
else
err -> err
end
end

defp backend_runner do
Application.get_env(:pinchflat, :yt_dlp_runner)
end
end
41 changes: 0 additions & 41 deletions lib/pinchflat/media_client/channel_details.ex

This file was deleted.

41 changes: 41 additions & 0 deletions lib/pinchflat/media_client/source_details.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
defmodule Pinchflat.MediaClient.SourceDetails do
@moduledoc """
This is the integration layer for actually working with sources.
Technically hardcodes the yt-dlp backend for now, but should leave
it open-ish for future expansion (just in case).
"""
@enforce_keys [:id, :name]
defstruct [:id, :name]

alias Pinchflat.MediaClient.Backends.YtDlp.VideoCollection, as: YtDlpSource

@doc false
def new(id, name) do
%__MODULE__{id: id, name: name}
end

@doc """
Gets a source's ID and name from its URL, using the given backend.
Returns {:ok, map()} | {:error, any, ...}.
"""
def get_source_details(source_url, backend \\ :yt_dlp) do
source_module(backend).get_source_details(source_url)
end

@doc """
Returns a list of video IDs for the given source URL, using the given backend.
Returns {:ok, list(binary())} | {:error, any, ...}.
"""
def get_video_ids(source_url, backend \\ :yt_dlp) do
source_module(backend).get_video_ids(source_url)
end

defp source_module(backend) do
case backend do
:yt_dlp -> YtDlpSource
end
end
end
4 changes: 2 additions & 2 deletions lib/pinchflat/media_client/video_downloader.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ defmodule Pinchflat.MediaClient.VideoDownloader do
Returns {:ok, %MediaItem{}} | {:error, any, ...any}
"""
def download_for_media_item(%MediaItem{} = media_item, backend \\ :yt_dlp) do
item_with_preloads = Repo.preload(media_item, [:metadata, channel: :media_profile])
media_profile = item_with_preloads.channel.media_profile
item_with_preloads = Repo.preload(media_item, [:metadata, source: :media_profile])
media_profile = item_with_preloads.source.media_profile

case download_for_media_profile(media_item.media_id, media_profile, backend) do
{:ok, parsed_json} ->
Expand Down
Loading

0 comments on commit 366fd80

Please sign in to comment.