Initial yt-dlp implementation (#3)
* Added basic runner for yt-dlp commands * Updated formatting rules * Added JSON runner; Added test script for CLI interactions * Reworked yt-dlp runner; added proper test mocks
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
defmodule Pinchflat.DownloaderBackends.BackendCommandRunner do
|
||||
@moduledoc """
|
||||
A behaviour for running CLI commands against a downloader backend
|
||||
"""
|
||||
|
||||
@callback run(binary(), keyword()) :: {:ok, binary()} | {:error, binary(), integer()}
|
||||
end
|
||||
@@ -0,0 +1,58 @@
|
||||
defmodule Pinchflat.DownloaderBackends.YtDlp.CommandRunner do
|
||||
@moduledoc """
|
||||
Runs yt-dlp commands using the `System.cmd/3` function
|
||||
"""
|
||||
|
||||
alias Pinchflat.Utils.StringUtils
|
||||
alias Pinchflat.DownloaderBackends.BackendCommandRunner
|
||||
|
||||
@behaviour BackendCommandRunner
|
||||
|
||||
@doc """
|
||||
Runs a yt-dlp command and returns the string output
|
||||
"""
|
||||
@impl BackendCommandRunner
|
||||
def run(url, command_opts) do
|
||||
command = backend_executable()
|
||||
formatted_command_opts = parse_options(command_opts) ++ [url]
|
||||
|
||||
case System.cmd(command, formatted_command_opts, stderr_to_stdout: true) do
|
||||
{output, 0} -> {:ok, output}
|
||||
{output, status} -> {:error, output, status}
|
||||
end
|
||||
end
|
||||
|
||||
# We want to satisfy the following behaviours:
|
||||
#
|
||||
# 1. If the key is an atom, convert it to a string and convert it to kebab case (for convenience)
|
||||
# 2. If the key is a string, assume we want it as-is and don't convert it
|
||||
# 3. If the key is accompanied by a value, append the value to the list
|
||||
# 4. If the key is not accompanied by a value, assume it's a flag and PREpend it to the list
|
||||
defp parse_options(command_opts) do
|
||||
Enum.reduce(command_opts, [], &parse_option/2)
|
||||
end
|
||||
|
||||
defp parse_option({k, v}, acc) when is_atom(k) do
|
||||
stringified_key = StringUtils.to_kebab_case(Atom.to_string(k))
|
||||
|
||||
parse_option({"--#{stringified_key}", v}, acc)
|
||||
end
|
||||
|
||||
defp parse_option({k, v}, acc) when is_binary(k) do
|
||||
acc ++ [k, to_string(v)]
|
||||
end
|
||||
|
||||
defp parse_option(arg, acc) when is_atom(arg) do
|
||||
stringified_arg = StringUtils.to_kebab_case(Atom.to_string(arg))
|
||||
|
||||
parse_option("--#{stringified_arg}", acc)
|
||||
end
|
||||
|
||||
defp parse_option(arg, acc) when is_binary(arg) do
|
||||
[arg | acc]
|
||||
end
|
||||
|
||||
defp backend_executable do
|
||||
Application.get_env(:pinchflat, :yt_dlp_executable)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
defmodule Pinchflat.DownloaderBackends.YtDlp.VideoCollection do
|
||||
@moduledoc """
|
||||
Contains utilities for working with collections of videos (ie: channels, playlists)
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Returns a list of strings representing the video ids in the collection
|
||||
"""
|
||||
def get_video_ids(url, command_opts \\ []) do
|
||||
opts = command_opts ++ [:simulate, :skip_download, :get_id]
|
||||
|
||||
case backend_runner().run(url, opts) do
|
||||
{:ok, output} -> {:ok, String.split(output, "\n", trim: true)}
|
||||
res -> res
|
||||
end
|
||||
end
|
||||
|
||||
defp backend_runner do
|
||||
Application.get_env(:pinchflat, :yt_dlp_runner)
|
||||
end
|
||||
end
|
||||
@@ -614,8 +614,7 @@ defmodule PinchflatWeb.CoreComponents do
|
||||
to: selector,
|
||||
time: 200,
|
||||
transition:
|
||||
{"transition-all transform ease-in duration-200",
|
||||
"opacity-100 translate-y-0 sm:scale-100",
|
||||
{"transition-all transform ease-in duration-200", "opacity-100 translate-y-0 sm:scale-100",
|
||||
"opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"}
|
||||
)
|
||||
end
|
||||
|
||||
@@ -70,8 +70,7 @@ defmodule PinchflatWeb.Telemetry do
|
||||
),
|
||||
summary("pinchflat.repo.query.idle_time",
|
||||
unit: {:native, :millisecond},
|
||||
description:
|
||||
"The time the connection spent waiting before being checked out for the query"
|
||||
description: "The time the connection spent waiting before being checked out for the query"
|
||||
),
|
||||
|
||||
# VM Metrics
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
defmodule Pinchflat.Utils.StringUtils do
|
||||
@moduledoc """
|
||||
Utility functions for working with strings
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Converts a string to kebab-case (ie: `hello world` -> `hello-world`)
|
||||
"""
|
||||
def to_kebab_case(string) do
|
||||
string
|
||||
|> String.replace(~r/[\s_]/, "-")
|
||||
|> String.downcase()
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user