Added ability to pass additional yt-dlp options to indexing step

This commit is contained in:
Kieran Eglin 2024-11-07 11:21:50 -08:00
parent 8c0dd0bb6b
commit 28da8db466
No known key found for this signature in database
GPG key ID: 193984967FCF432D
6 changed files with 35 additions and 11 deletions

View file

@ -68,7 +68,7 @@ defmodule Pinchflat.FastIndexing.FastIndexingHelpers do
defp create_media_item_from_media_id(source, media_id) do defp create_media_item_from_media_id(source, media_id) do
url = "https://www.youtube.com/watch?v=#{media_id}" url = "https://www.youtube.com/watch?v=#{media_id}"
case YtDlpMedia.get_media_attributes(url, use_cookies: source.use_cookies) do case YtDlpMedia.get_media_attributes(url, [], use_cookies: source.use_cookies) do
{:ok, media_attrs} -> {:ok, media_attrs} ->
Media.create_media_item_from_backend_attrs(source, media_attrs) Media.create_media_item_from_backend_attrs(source, media_attrs)

View file

@ -95,7 +95,7 @@ defmodule Pinchflat.SlowIndexing.SlowIndexingHelpers do
handler = fn filepath -> setup_file_follower_watcher(pid, filepath, source) end handler = fn filepath -> setup_file_follower_watcher(pid, filepath, source) end
runner_opts = [file_listener_handler: handler, use_cookies: source.use_cookies] runner_opts = [file_listener_handler: handler, use_cookies: source.use_cookies]
result = MediaCollection.get_media_attributes_for_collection(source.original_url, runner_opts) result = MediaCollection.get_media_attributes_for_collection(source.original_url, [], runner_opts)
FileFollowerServer.stop(pid) FileFollowerServer.stop(pid)

View file

@ -63,15 +63,17 @@ defmodule Pinchflat.YtDlp.Media do
@doc """ @doc """
Returns a map representing the media at the given URL. Returns a map representing the media at the given URL.
Optionally takes a list of additional command options to pass to yt-dlp
or configuration-related options to pass to the runner.
Returns {:ok, %Media{}} | {:error, any, ...}. Returns {:ok, %Media{}} | {:error, any, ...}.
""" """
def get_media_attributes(url, addl_opts \\ []) do def get_media_attributes(url, command_opts \\ [], addl_opts \\ []) do
runner = Application.get_env(:pinchflat, :yt_dlp_runner) runner = Application.get_env(:pinchflat, :yt_dlp_runner)
command_opts = [:simulate, :skip_download] all_command_opts = [:simulate, :skip_download] ++ command_opts
output_template = indexing_output_template() output_template = indexing_output_template()
case runner.run(url, command_opts, output_template, addl_opts) do case runner.run(url, all_command_opts, output_template, addl_opts) do
{:ok, output} -> {:ok, output} ->
output output
|> Phoenix.json_library().decode!() |> Phoenix.json_library().decode!()

View file

@ -11,20 +11,23 @@ defmodule Pinchflat.YtDlp.MediaCollection do
@doc """ @doc """
Returns a list of maps representing the media in the collection. Returns a list of maps representing the media in the collection.
Optionally takes a list of additional command options to pass to yt-dlp
or configuration-related options to pass to the runner.
Options: Runner Options:
- :file_listener_handler - a function that will be called with the path to the - :file_listener_handler - a function that will be called with the path to the
file that will be written to when yt-dlp is done. This is useful for file that will be written to when yt-dlp is done. This is useful for
setting up a file watcher to know when the file is ready to be read. setting up a file watcher to know when the file is ready to be read.
- :use_cookies - whether or not to use user-provided cookies when fetching the media details
Returns {:ok, [map()]} | {:error, any, ...}. Returns {:ok, [map()]} | {:error, any, ...}.
""" """
def get_media_attributes_for_collection(url, addl_opts \\ []) do def get_media_attributes_for_collection(url, command_opts \\ [], addl_opts \\ []) do
runner = Application.get_env(:pinchflat, :yt_dlp_runner) runner = Application.get_env(:pinchflat, :yt_dlp_runner)
# `ignore_no_formats_error` is necessary because yt-dlp will error out if # `ignore_no_formats_error` is necessary because yt-dlp will error out if
# the first video has not released yet (ie: is a premier). We don't care about # the first video has not released yet (ie: is a premier). We don't care about
# available formats since we're just getting the media details # available formats since we're just getting the media details
command_opts = [:simulate, :skip_download, :ignore_no_formats_error, :no_warnings] all_command_opts = [:simulate, :skip_download, :ignore_no_formats_error, :no_warnings] ++ command_opts
use_cookies = Keyword.get(addl_opts, :use_cookies, false) use_cookies = Keyword.get(addl_opts, :use_cookies, false)
output_template = YtDlpMedia.indexing_output_template() output_template = YtDlpMedia.indexing_output_template()
output_filepath = FilesystemUtils.generate_metadata_tmpfile(:json) output_filepath = FilesystemUtils.generate_metadata_tmpfile(:json)
@ -35,7 +38,7 @@ defmodule Pinchflat.YtDlp.MediaCollection do
file_listener_handler.(output_filepath) file_listener_handler.(output_filepath)
end end
case runner.run(url, command_opts, output_template, runner_opts) do case runner.run(url, all_command_opts, output_template, runner_opts) do
{:ok, output} -> {:ok, output} ->
parsed_lines = parsed_lines =
output output

View file

@ -35,6 +35,16 @@ defmodule Pinchflat.YtDlp.MediaCollectionTest do
assert {:error, "Big issue", 1} = MediaCollection.get_media_attributes_for_collection(@channel_url) assert {:error, "Big issue", 1} = MediaCollection.get_media_attributes_for_collection(@channel_url)
end end
test "passes long additional command options" do
expect(YtDlpRunnerMock, :run, fn _url, opts, _ot, _addl_opts ->
assert :foo in opts
{:ok, ""}
end)
assert {:ok, _} = MediaCollection.get_media_attributes_for_collection(@channel_url, [:foo])
end
test "passes additional args to runner" do test "passes additional args to runner" do
expect(YtDlpRunnerMock, :run, fn _url, _opts, _ot, addl_opts -> expect(YtDlpRunnerMock, :run, fn _url, _opts, _ot, addl_opts ->
assert [{:output_filepath, filepath} | _] = addl_opts assert [{:output_filepath, filepath} | _] = addl_opts
@ -56,7 +66,7 @@ defmodule Pinchflat.YtDlp.MediaCollectionTest do
end end
assert {:ok, _} = assert {:ok, _} =
MediaCollection.get_media_attributes_for_collection(@channel_url, file_listener_handler: handler) MediaCollection.get_media_attributes_for_collection(@channel_url, [], file_listener_handler: handler)
assert_receive {:handler, filename} assert_receive {:handler, filename}
assert String.ends_with?(filename, ".json") assert String.ends_with?(filename, ".json")

View file

@ -120,13 +120,22 @@ defmodule Pinchflat.YtDlp.MediaTest do
assert {:ok, _} = Media.get_media_attributes(@media_url) assert {:ok, _} = Media.get_media_attributes(@media_url)
end end
test "passes along additional command options" do
expect(YtDlpRunnerMock, :run, fn _url, opts, _ot, _addl ->
assert [:simulate, :skip_download, :custom_arg] = opts
{:ok, media_attributes_return_fixture()}
end)
assert {:ok, _} = Media.get_media_attributes(@media_url, [:custom_arg])
end
test "passes along additional options" do test "passes along additional options" do
expect(YtDlpRunnerMock, :run, fn _url, _opts, _ot, addl -> expect(YtDlpRunnerMock, :run, fn _url, _opts, _ot, addl ->
assert [addl_arg: true] = addl assert [addl_arg: true] = addl
{:ok, media_attributes_return_fixture()} {:ok, media_attributes_return_fixture()}
end) end)
assert {:ok, _} = Media.get_media_attributes(@media_url, addl_arg: true) assert {:ok, _} = Media.get_media_attributes(@media_url, [], addl_arg: true)
end end
test "returns the error straight through when the command fails" do test "returns the error straight through when the command fails" do