Merge 00fff278b5 into 67d8bd5598
This commit is contained in:
commit
7ebb9e522f
6 changed files with 58 additions and 8 deletions
|
|
@ -177,6 +177,7 @@ If you change this setting and it works well for you, please leave a comment on
|
||||||
| `TZ_DATA_DIR` | No | `/etc/elixir_tzdata_data` | The container path where the timezone database is stored |
|
| `TZ_DATA_DIR` | No | `/etc/elixir_tzdata_data` | The container path where the timezone database is stored |
|
||||||
| `BASE_ROUTE_PATH` | No | `/` | The base path for route generation. Useful when running behind certain reverse proxies - prefixes must be stripped. |
|
| `BASE_ROUTE_PATH` | No | `/` | The base path for route generation. Useful when running behind certain reverse proxies - prefixes must be stripped. |
|
||||||
| `YT_DLP_WORKER_CONCURRENCY` | No | `2` | The number of concurrent workers that use `yt-dlp` _per queue_. Set to 1 if you're getting IP limited, otherwise don't touch it |
|
| `YT_DLP_WORKER_CONCURRENCY` | No | `2` | The number of concurrent workers that use `yt-dlp` _per queue_. Set to 1 if you're getting IP limited, otherwise don't touch it |
|
||||||
|
| `YT_DLP_VERSION` | No | `stable` | Controls yt-dlp updates: `stable`, `nightly`, `master`, `pinned`/`none` (disable), or a specific version like `2025.12.08` |
|
||||||
| `ENABLE_PROMETHEUS` | No | `false` | Setting to _any_ non-blank value will enable Prometheus. See [docs](https://github.com/kieraneglin/pinchflat/wiki/Prometheus-and-Grafana) |
|
| `ENABLE_PROMETHEUS` | No | `false` | Setting to _any_ non-blank value will enable Prometheus. See [docs](https://github.com/kieraneglin/pinchflat/wiki/Prometheus-and-Grafana) |
|
||||||
|
|
||||||
### Reverse Proxies
|
### Reverse Proxies
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,18 @@ config :pinchflat, Pinchflat.Repo,
|
||||||
# Some users may want to increase the number of workers that use yt-dlp to improve speeds
|
# Some users may want to increase the number of workers that use yt-dlp to improve speeds
|
||||||
# Others may want to decrease the number of these workers to lessen the chance of an IP ban
|
# Others may want to decrease the number of these workers to lessen the chance of an IP ban
|
||||||
{yt_dlp_worker_count, _} = Integer.parse(System.get_env("YT_DLP_WORKER_CONCURRENCY", "2"))
|
{yt_dlp_worker_count, _} = Integer.parse(System.get_env("YT_DLP_WORKER_CONCURRENCY", "2"))
|
||||||
|
|
||||||
|
# Controls yt-dlp version management. Supported values:
|
||||||
|
# - "stable" (default) - updates to latest stable release daily
|
||||||
|
# - "nightly" - updates to latest nightly build daily
|
||||||
|
# - "master" - updates to latest master build daily
|
||||||
|
# - "pinned" or "none" - disables automatic updates entirely
|
||||||
|
# - A specific version like "2025.12.08" - pins to that exact version
|
||||||
|
yt_dlp_version_channel = System.get_env("YT_DLP_VERSION", "stable")
|
||||||
|
|
||||||
|
config :pinchflat,
|
||||||
|
yt_dlp_version_channel: yt_dlp_version_channel
|
||||||
|
|
||||||
# Used to set the cron for the yt-dlp update worker. The reason for this is
|
# Used to set the cron for the yt-dlp update worker. The reason for this is
|
||||||
# to avoid all instances of PF updating yt-dlp at the same time, which 1)
|
# to avoid all instances of PF updating yt-dlp at the same time, which 1)
|
||||||
# could result in rate limiting and 2) gives me time to react if an update
|
# could result in rate limiting and 2) gives me time to react if an update
|
||||||
|
|
|
||||||
|
|
@ -77,15 +77,22 @@ defmodule Pinchflat.YtDlp.CommandRunner do
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Updates yt-dlp to the latest version
|
Updates yt-dlp to the specified version channel or specific version.
|
||||||
|
|
||||||
|
The version_target can be:
|
||||||
|
- "stable" - updates to latest stable release (default)
|
||||||
|
- "nightly" - updates to latest nightly build
|
||||||
|
- "master" - updates to latest master build
|
||||||
|
- A specific version like "2025.12.08" - pins to that exact version
|
||||||
|
|
||||||
Returns {:ok, binary()} | {:error, binary()}
|
Returns {:ok, binary()} | {:error, binary()}
|
||||||
"""
|
"""
|
||||||
@impl YtDlpCommandRunner
|
@impl YtDlpCommandRunner
|
||||||
def update do
|
def update(version_target \\ "stable") do
|
||||||
command = backend_executable()
|
command = backend_executable()
|
||||||
|
args = build_update_args(version_target)
|
||||||
|
|
||||||
case CliUtils.wrap_cmd(command, ["--update"]) do
|
case CliUtils.wrap_cmd(command, args) do
|
||||||
{output, 0} ->
|
{output, 0} ->
|
||||||
{:ok, String.trim(output)}
|
{:ok, String.trim(output)}
|
||||||
|
|
||||||
|
|
@ -94,6 +101,11 @@ defmodule Pinchflat.YtDlp.CommandRunner do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp build_update_args("stable"), do: ["--update"]
|
||||||
|
defp build_update_args("nightly"), do: ["--update-to", "nightly"]
|
||||||
|
defp build_update_args("master"), do: ["--update-to", "master"]
|
||||||
|
defp build_update_args(specific_version), do: ["--update-to", "yt-dlp/yt-dlp@#{specific_version}"]
|
||||||
|
|
||||||
defp generate_output_filepath(addl_opts) do
|
defp generate_output_filepath(addl_opts) do
|
||||||
case Keyword.get(addl_opts, :output_filepath) do
|
case Keyword.get(addl_opts, :output_filepath) do
|
||||||
nil -> FSUtils.generate_metadata_tmpfile(:json)
|
nil -> FSUtils.generate_metadata_tmpfile(:json)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,14 @@
|
||||||
defmodule Pinchflat.YtDlp.UpdateWorker do
|
defmodule Pinchflat.YtDlp.UpdateWorker do
|
||||||
@moduledoc false
|
@moduledoc """
|
||||||
|
Handles automatic yt-dlp updates based on the YT_DLP_VERSION environment variable.
|
||||||
|
|
||||||
|
Supported values for YT_DLP_VERSION:
|
||||||
|
- "stable" (default) - updates to latest stable release daily
|
||||||
|
- "nightly" - updates to latest nightly build daily
|
||||||
|
- "master" - updates to latest master build daily
|
||||||
|
- "pinned" or "none" - disables automatic updates entirely
|
||||||
|
- A specific version like "2025.12.08" - pins to that exact version
|
||||||
|
"""
|
||||||
|
|
||||||
use Oban.Worker,
|
use Oban.Worker,
|
||||||
queue: :local_data,
|
queue: :local_data,
|
||||||
|
|
@ -23,14 +32,22 @@ defmodule Pinchflat.YtDlp.UpdateWorker do
|
||||||
Updates yt-dlp and saves the version to the settings.
|
Updates yt-dlp and saves the version to the settings.
|
||||||
|
|
||||||
This worker is scheduled to run via the Oban Cron plugin as well as on app boot.
|
This worker is scheduled to run via the Oban Cron plugin as well as on app boot.
|
||||||
|
The update behavior is controlled by the YT_DLP_VERSION environment variable.
|
||||||
|
|
||||||
Returns :ok
|
Returns :ok
|
||||||
"""
|
"""
|
||||||
@impl Oban.Worker
|
@impl Oban.Worker
|
||||||
def perform(%Oban.Job{}) do
|
def perform(%Oban.Job{}) do
|
||||||
Logger.info("Updating yt-dlp")
|
version_setting = get_version_setting()
|
||||||
|
|
||||||
yt_dlp_runner().update()
|
case version_setting do
|
||||||
|
setting when setting in ["pinned", "none"] ->
|
||||||
|
Logger.info("yt-dlp auto-update disabled (YT_DLP_VERSION=#{setting})")
|
||||||
|
|
||||||
|
version_target ->
|
||||||
|
Logger.info("Updating yt-dlp to #{version_target}")
|
||||||
|
yt_dlp_runner().update(version_target)
|
||||||
|
end
|
||||||
|
|
||||||
{:ok, yt_dlp_version} = yt_dlp_runner().version()
|
{:ok, yt_dlp_version} = yt_dlp_runner().version()
|
||||||
Settings.set(yt_dlp_version: yt_dlp_version)
|
Settings.set(yt_dlp_version: yt_dlp_version)
|
||||||
|
|
@ -38,6 +55,13 @@ defmodule Pinchflat.YtDlp.UpdateWorker do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Returns the configured yt-dlp version setting from environment.
|
||||||
|
"""
|
||||||
|
def get_version_setting do
|
||||||
|
Application.get_env(:pinchflat, :yt_dlp_version_channel, "stable")
|
||||||
|
end
|
||||||
|
|
||||||
defp yt_dlp_runner do
|
defp yt_dlp_runner do
|
||||||
Application.get_env(:pinchflat, :yt_dlp_runner)
|
Application.get_env(:pinchflat, :yt_dlp_runner)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,5 @@ defmodule Pinchflat.YtDlp.YtDlpCommandRunner do
|
||||||
@callback run(binary(), atom(), keyword(), binary(), keyword()) :: {:ok, binary()} | {:error, binary(), integer()}
|
@callback run(binary(), atom(), keyword(), binary(), keyword()) :: {:ok, binary()} | {:error, binary(), integer()}
|
||||||
@callback version() :: {:ok, binary()} | {:error, binary()}
|
@callback version() :: {:ok, binary()} | {:error, binary()}
|
||||||
@callback update() :: {:ok, binary()} | {:error, binary()}
|
@callback update() :: {:ok, binary()} | {:error, binary()}
|
||||||
|
@callback update(binary()) :: {:ok, binary()} | {:error, binary()}
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,14 @@ defmodule Pinchflat.YtDlp.UpdateWorkerTest do
|
||||||
|
|
||||||
describe "perform/1" do
|
describe "perform/1" do
|
||||||
test "calls the yt-dlp runner to update yt-dlp" do
|
test "calls the yt-dlp runner to update yt-dlp" do
|
||||||
expect(YtDlpRunnerMock, :update, fn -> {:ok, ""} end)
|
expect(YtDlpRunnerMock, :update, fn _version -> {:ok, ""} end)
|
||||||
expect(YtDlpRunnerMock, :version, fn -> {:ok, ""} end)
|
expect(YtDlpRunnerMock, :version, fn -> {:ok, ""} end)
|
||||||
|
|
||||||
perform_job(UpdateWorker, %{})
|
perform_job(UpdateWorker, %{})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "saves the new version to the database" do
|
test "saves the new version to the database" do
|
||||||
expect(YtDlpRunnerMock, :update, fn -> {:ok, ""} end)
|
expect(YtDlpRunnerMock, :update, fn _version -> {:ok, ""} end)
|
||||||
expect(YtDlpRunnerMock, :version, fn -> {:ok, "1.2.3"} end)
|
expect(YtDlpRunnerMock, :version, fn -> {:ok, "1.2.3"} end)
|
||||||
|
|
||||||
perform_job(UpdateWorker, %{})
|
perform_job(UpdateWorker, %{})
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue