Added JSON runner; Added test script for CLI interactions
This commit is contained in:
parent
ad6ad329c9
commit
44d43ce636
4 changed files with 71 additions and 15 deletions
|
|
@ -9,7 +9,10 @@ import Config
|
||||||
|
|
||||||
config :pinchflat,
|
config :pinchflat,
|
||||||
ecto_repos: [Pinchflat.Repo],
|
ecto_repos: [Pinchflat.Repo],
|
||||||
generators: [timestamp_type: :utc_datetime]
|
generators: [timestamp_type: :utc_datetime],
|
||||||
|
backend_executables: %{
|
||||||
|
yt_dlp: "false"
|
||||||
|
}
|
||||||
|
|
||||||
# Configures the endpoint
|
# Configures the endpoint
|
||||||
config :pinchflat, PinchflatWeb.Endpoint,
|
config :pinchflat, PinchflatWeb.Endpoint,
|
||||||
|
|
|
||||||
|
|
@ -10,17 +10,26 @@ defmodule Pinchflat.DownloaderBackends.YtDlp.CommandRunner do
|
||||||
|
|
||||||
TODO: look into using a behavior for this (if I ever add other backends)
|
TODO: look into using a behavior for this (if I ever add other backends)
|
||||||
"""
|
"""
|
||||||
def run(url, command_options, config_options \\ []) do
|
def run(url, command_options) do
|
||||||
default_command = System.find_executable("yt-dlp")
|
command = Application.get_env(:pinchflat, :backend_executables)[:yt_dlp]
|
||||||
base_command = Keyword.get(config_options, :base_command, default_command)
|
|
||||||
formatted_command_options = parse_options(command_options) ++ [url]
|
formatted_command_options = parse_options(command_options) ++ [url]
|
||||||
|
|
||||||
case System.cmd(base_command, formatted_command_options, stderr_to_stdout: true) do
|
case System.cmd(command, formatted_command_options, stderr_to_stdout: true) do
|
||||||
{output, 0} -> {:ok, output}
|
{output, 0} -> {:ok, output}
|
||||||
{output, status} -> {:error, output, status}
|
{output, status} -> {:error, output, status}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Runs a yt-dlp command and returns the output as a JSON object
|
||||||
|
"""
|
||||||
|
def run_json(url, command_options) do
|
||||||
|
case run(url, command_options ++ [:dump_json]) do
|
||||||
|
{:ok, output} -> {:ok, Phoenix.json_library().decode!(output)}
|
||||||
|
res -> res
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# We want to satisfy the following behaviours:
|
# 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)
|
# 1. If the key is an atom, convert it to a string and convert it to kebab case (for convenience)
|
||||||
|
|
|
||||||
|
|
@ -3,34 +3,43 @@ defmodule Pinchflat.DownloaderBackends.YtDlp.CommandRunnerTest do
|
||||||
|
|
||||||
alias Pinchflat.DownloaderBackends.YtDlp.CommandRunner, as: Runner
|
alias Pinchflat.DownloaderBackends.YtDlp.CommandRunner, as: Runner
|
||||||
|
|
||||||
@cmd "echo"
|
@cmd Path.join([File.cwd!(), "/test/support/scripts/mock-yt-dlp-repeater.sh"])
|
||||||
@video_url "https://www.youtube.com/watch?v=9bZkp7q19f0"
|
@video_url "https://www.youtube.com/watch?v=9bZkp7q19f0"
|
||||||
|
@original_executables Application.compile_env(:pinchflat, :backend_executables)
|
||||||
|
|
||||||
describe "run/3" do
|
setup do
|
||||||
|
Application.put_env(:pinchflat, :backend_executables, %{@original_executables | yt_dlp: @cmd})
|
||||||
|
|
||||||
|
on_exit(fn ->
|
||||||
|
Application.put_env(:pinchflat, :backend_executables, @original_executables)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "run/2" do
|
||||||
test "it returns the output and status when the command succeeds" do
|
test "it returns the output and status when the command succeeds" do
|
||||||
assert {:ok, _output} = Runner.run(@video_url, [], base_command: @cmd)
|
assert {:ok, _output} = Runner.run(@video_url, [])
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it converts symbol k-v arg keys to kebab case" do
|
test "it converts symbol k-v arg keys to kebab case" do
|
||||||
assert {:ok, output} = Runner.run(@video_url, [buffer_size: 1024], base_command: @cmd)
|
assert {:ok, output} = Runner.run(@video_url, buffer_size: 1024)
|
||||||
|
|
||||||
assert String.contains?(output, "--buffer-size 1024")
|
assert String.contains?(output, "--buffer-size 1024")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it keeps string k-v arg keys untouched" do
|
test "it keeps string k-v arg keys untouched" do
|
||||||
assert {:ok, output} = Runner.run(@video_url, [{"--under_score", 1024}], base_command: @cmd)
|
assert {:ok, output} = Runner.run(@video_url, [{"--under_score", 1024}])
|
||||||
|
|
||||||
assert String.contains?(output, "--under_score 1024")
|
assert String.contains?(output, "--under_score 1024")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it converts symbol arg keys to kebab case" do
|
test "it converts symbol arg keys to kebab case" do
|
||||||
assert {:ok, output} = Runner.run(@video_url, [:ignore_errors], base_command: @cmd)
|
assert {:ok, output} = Runner.run(@video_url, [:ignore_errors])
|
||||||
|
|
||||||
assert String.contains?(output, "--ignore-errors")
|
assert String.contains?(output, "--ignore-errors")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it keeps string arg keys untouched" do
|
test "it keeps string arg keys untouched" do
|
||||||
assert {:ok, output} = Runner.run(@video_url, ["-v"], base_command: @cmd)
|
assert {:ok, output} = Runner.run(@video_url, ["-v"])
|
||||||
|
|
||||||
assert String.contains?(output, "-v")
|
assert String.contains?(output, "-v")
|
||||||
refute String.contains?(output, "--v")
|
refute String.contains?(output, "--v")
|
||||||
|
|
@ -38,19 +47,47 @@ defmodule Pinchflat.DownloaderBackends.YtDlp.CommandRunnerTest do
|
||||||
|
|
||||||
test "it places arg keys (flags) at the beginning of the command" do
|
test "it places arg keys (flags) at the beginning of the command" do
|
||||||
assert {:ok, output} =
|
assert {:ok, output} =
|
||||||
Runner.run(@video_url, [{"--under_score", 1024}, :ignore_errors], base_command: @cmd)
|
Runner.run(@video_url, [{"--under_score", 1024}, :ignore_errors])
|
||||||
|
|
||||||
assert String.contains?(output, "--ignore-errors --under_score 1024")
|
assert String.contains?(output, "--ignore-errors --under_score 1024")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it includes the video url as the last argument" do
|
test "it includes the video url as the last argument" do
|
||||||
assert {:ok, output} = Runner.run(@video_url, [:ignore_errors], base_command: @cmd)
|
assert {:ok, output} = Runner.run(@video_url, [:ignore_errors])
|
||||||
|
|
||||||
assert String.contains?(output, "--ignore-errors #{@video_url}\n")
|
assert String.contains?(output, "--ignore-errors #{@video_url}\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns the output and status when the command fails" do
|
test "it returns the output and status when the command fails" do
|
||||||
assert {:error, "", 1} = Runner.run(@video_url, [], base_command: "/bin/false")
|
Application.put_env(:pinchflat, :backend_executables, %{
|
||||||
|
@original_executables
|
||||||
|
| yt_dlp: "/bin/false"
|
||||||
|
})
|
||||||
|
|
||||||
|
assert {:error, "", 1} = Runner.run(@video_url, [])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "run_json/2" do
|
||||||
|
test "it returns decoded JSON when the command succeeds" do
|
||||||
|
assert {:ok, output} = Runner.run_json(@video_url, [])
|
||||||
|
|
||||||
|
assert is_map(output)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it adds the --dump-json flag automatically" do
|
||||||
|
assert {:ok, %{"args" => output}} = Runner.run_json(@video_url, [])
|
||||||
|
|
||||||
|
assert String.contains?(output, "--dump-json")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it returns errors when the command fails" do
|
||||||
|
Application.put_env(:pinchflat, :backend_executables, %{
|
||||||
|
@original_executables
|
||||||
|
| yt_dlp: "/bin/false"
|
||||||
|
})
|
||||||
|
|
||||||
|
assert {:error, "", 1} = Runner.run_json(@video_url, [])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
7
test/support/scripts/mock-yt-dlp-repeater.sh
Executable file
7
test/support/scripts/mock-yt-dlp-repeater.sh
Executable file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [[ "$@" == *"--dump-json"* ]]; then
|
||||||
|
echo '{ "args": "'$@'"}'
|
||||||
|
else
|
||||||
|
echo $@
|
||||||
|
fi
|
||||||
Loading…
Reference in a new issue