Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d97c8c1c4 | |||
| 030f5fbdfe | |||
| ee2db3e9b7 | |||
| 4554648ba7 |
@@ -15,7 +15,9 @@ defmodule Pinchflat.Settings.Setting do
|
||||
:video_codec_preference,
|
||||
:audio_codec_preference,
|
||||
:youtube_api_key,
|
||||
:extractor_sleep_interval_seconds
|
||||
:extractor_sleep_interval_seconds,
|
||||
:download_throughput_limit,
|
||||
:restrict_filenames
|
||||
]
|
||||
|
||||
@required_fields [
|
||||
@@ -35,6 +37,9 @@ defmodule Pinchflat.Settings.Setting do
|
||||
field :youtube_api_key, :string
|
||||
field :route_token, :string
|
||||
field :extractor_sleep_interval_seconds, :integer, default: 0
|
||||
# This is a string because it accepts values like "100K" or "4.2M"
|
||||
field :download_throughput_limit, :string
|
||||
field :restrict_filenames, :boolean, default: false
|
||||
|
||||
field :video_codec_preference, :string
|
||||
field :audio_codec_preference, :string
|
||||
|
||||
@@ -35,7 +35,7 @@ defmodule Pinchflat.YtDlp.CommandRunner do
|
||||
|
||||
output_filepath = generate_output_filepath(addl_opts)
|
||||
print_to_file_opts = [{:print_to_file, output_template}, output_filepath]
|
||||
user_configured_opts = cookie_file_options(addl_opts) ++ sleep_interval_opts(addl_opts)
|
||||
user_configured_opts = cookie_file_options(addl_opts) ++ rate_limit_options(addl_opts) ++ misc_options()
|
||||
# These must stay in exactly this order, hence why I'm giving it its own variable.
|
||||
all_opts = command_opts ++ print_to_file_opts ++ user_configured_opts ++ global_options()
|
||||
formatted_command_opts = [url] ++ CliUtils.parse_options(all_opts)
|
||||
@@ -116,20 +116,6 @@ defmodule Pinchflat.YtDlp.CommandRunner do
|
||||
end
|
||||
end
|
||||
|
||||
defp sleep_interval_opts(addl_opts) do
|
||||
sleep_interval = Settings.get!(:extractor_sleep_interval_seconds)
|
||||
|
||||
if sleep_interval <= 0 || Keyword.get(addl_opts, :skip_sleep_interval) do
|
||||
[]
|
||||
else
|
||||
[
|
||||
sleep_requests: NumberUtils.add_jitter(sleep_interval),
|
||||
sleep_interval: NumberUtils.add_jitter(sleep_interval),
|
||||
sleep_subtitles: NumberUtils.add_jitter(sleep_interval)
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
defp add_cookie_file do
|
||||
base_dir = Application.get_env(:pinchflat, :extras_directory)
|
||||
filename_options_map = %{cookies: "cookies.txt"}
|
||||
@@ -145,6 +131,32 @@ defmodule Pinchflat.YtDlp.CommandRunner do
|
||||
end)
|
||||
end
|
||||
|
||||
defp rate_limit_options(addl_opts) do
|
||||
throughput_limit = Settings.get!(:download_throughput_limit)
|
||||
sleep_interval_opts = sleep_interval_opts(addl_opts)
|
||||
throughput_option = if throughput_limit, do: [limit_rate: throughput_limit], else: []
|
||||
|
||||
throughput_option ++ sleep_interval_opts
|
||||
end
|
||||
|
||||
defp sleep_interval_opts(addl_opts) do
|
||||
sleep_interval = Settings.get!(:extractor_sleep_interval_seconds)
|
||||
|
||||
if sleep_interval <= 0 || Keyword.get(addl_opts, :skip_sleep_interval) do
|
||||
[]
|
||||
else
|
||||
[
|
||||
sleep_requests: NumberUtils.add_jitter(sleep_interval),
|
||||
sleep_interval: NumberUtils.add_jitter(sleep_interval),
|
||||
sleep_subtitles: NumberUtils.add_jitter(sleep_interval)
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
defp misc_options do
|
||||
if Settings.get!(:restrict_filenames), do: [:restrict_filenames], else: []
|
||||
end
|
||||
|
||||
defp backend_executable do
|
||||
Application.get_env(:pinchflat, :yt_dlp_executable)
|
||||
end
|
||||
|
||||
@@ -47,7 +47,21 @@
|
||||
placeholder="0"
|
||||
type="number"
|
||||
label="Sleep Interval (seconds)"
|
||||
help="Sleep interval in seconds between each extractor request. Must be a positive whole number (or set to 0 to disable)"
|
||||
help="Sleep interval in seconds between each extractor request. Must be a positive whole number. Set to 0 to disable"
|
||||
/>
|
||||
|
||||
<.input
|
||||
field={f[:download_throughput_limit]}
|
||||
placeholder="4.2M"
|
||||
label="Download Throughput"
|
||||
help="Sets the max bytes-per-second throughput when downloading media. Examples: '50K' or '4.2M'. Leave blank to disable"
|
||||
/>
|
||||
|
||||
<.input
|
||||
field={f[:restrict_filenames]}
|
||||
type="toggle"
|
||||
label="Restrict Filenames"
|
||||
help="Restrict filenames to only ASCII characters and avoid ampersands/spaces in filenames"
|
||||
/>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -39,7 +39,10 @@ defmodule PinchflatWeb.Endpoint do
|
||||
cookie_key: "request_logger"
|
||||
|
||||
plug Plug.RequestId
|
||||
plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]
|
||||
|
||||
plug Plug.Telemetry,
|
||||
event_prefix: [:phoenix, :endpoint],
|
||||
log: {__MODULE__, :log_level, []}
|
||||
|
||||
plug Plug.Parsers,
|
||||
parsers: [:urlencoded, :multipart, :json],
|
||||
@@ -55,6 +58,10 @@ defmodule PinchflatWeb.Endpoint do
|
||||
|
||||
plug PinchflatWeb.Router
|
||||
|
||||
# Disables logging in Plug.Telemetry for healthcheck requests
|
||||
def log_level(%Plug.Conn{path_info: ["healthcheck"]}), do: false
|
||||
def log_level(_), do: :info
|
||||
|
||||
# URLs need to be generated using the host of the current page being accessed
|
||||
# for things like Podcast RSS feeds to contain links to the right location.
|
||||
#
|
||||
|
||||
@@ -68,7 +68,7 @@ defmodule PinchflatWeb.Router do
|
||||
scope "/", PinchflatWeb do
|
||||
pipe_through :api
|
||||
|
||||
get "/healthcheck", HealthController, :check
|
||||
get "/healthcheck", HealthController, :check, log: false
|
||||
end
|
||||
|
||||
scope "/dev" do
|
||||
|
||||
@@ -4,7 +4,7 @@ defmodule Pinchflat.MixProject do
|
||||
def project do
|
||||
[
|
||||
app: :pinchflat,
|
||||
version: "2025.3.6",
|
||||
version: "2025.3.17",
|
||||
elixir: "~> 1.17",
|
||||
elixirc_paths: elixirc_paths(Mix.env()),
|
||||
start_permanent: Mix.env() == :prod,
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 497 KiB After Width: | Height: | Size: 506 KiB |
@@ -0,0 +1,9 @@
|
||||
defmodule Pinchflat.Repo.Migrations.AddRateLimitSpeedToSettings do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
alter table(:settings) do
|
||||
add :download_throughput_limit, :string
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
defmodule Pinchflat.Repo.Migrations.AddRestrictFilenamesToSettings do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
alter table(:settings) do
|
||||
add :restrict_filenames, :boolean, default: false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -96,7 +96,7 @@ defmodule Pinchflat.YtDlp.CommandRunnerTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "run/4 when testing sleep interval options" do
|
||||
describe "run/4 when testing rate limit options" do
|
||||
test "includes sleep interval options by default" do
|
||||
Settings.set(extractor_sleep_interval_seconds: 5)
|
||||
|
||||
@@ -124,6 +124,22 @@ defmodule Pinchflat.YtDlp.CommandRunnerTest do
|
||||
refute String.contains?(output, "--sleep-requests")
|
||||
refute String.contains?(output, "--sleep-subtitles")
|
||||
end
|
||||
|
||||
test "includes limit_rate option when specified" do
|
||||
Settings.set(download_throughput_limit: "100K")
|
||||
|
||||
assert {:ok, output} = Runner.run(@media_url, :foo, [], "")
|
||||
|
||||
assert String.contains?(output, "--limit-rate 100K")
|
||||
end
|
||||
|
||||
test "doesn't include limit_rate option when download_throughput_limit is nil" do
|
||||
Settings.set(download_throughput_limit: nil)
|
||||
|
||||
assert {:ok, output} = Runner.run(@media_url, :foo, [], "")
|
||||
|
||||
refute String.contains?(output, "--limit-rate")
|
||||
end
|
||||
end
|
||||
|
||||
describe "run/4 when testing global options" do
|
||||
@@ -146,6 +162,24 @@ defmodule Pinchflat.YtDlp.CommandRunnerTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "run/4 when testing misc options" do
|
||||
test "includes --restrict-filenames when enabled" do
|
||||
Settings.set(restrict_filenames: true)
|
||||
|
||||
assert {:ok, output} = Runner.run(@media_url, :foo, [], "")
|
||||
|
||||
assert String.contains?(output, "--restrict-filenames")
|
||||
end
|
||||
|
||||
test "doesn't include --restrict-filenames when disabled" do
|
||||
Settings.set(restrict_filenames: false)
|
||||
|
||||
assert {:ok, output} = Runner.run(@media_url, :foo, [], "")
|
||||
|
||||
refute String.contains?(output, "--restrict-filenames")
|
||||
end
|
||||
end
|
||||
|
||||
describe "version/0" do
|
||||
test "adds the version arg" do
|
||||
assert {:ok, output} = Runner.version()
|
||||
|
||||
Reference in New Issue
Block a user