Append -thumb to thumbnails when downloading (#87)
* Appended -thumb to thumbnails when downloading * Added code to compensate for yt-dlp bug
This commit is contained in:
parent
b734fc73c0
commit
52e260fd57
7 changed files with 110 additions and 17 deletions
|
|
@ -18,7 +18,7 @@ defmodule Pinchflat.Downloading.DownloadOptionBuilder do
|
||||||
built_options =
|
built_options =
|
||||||
default_options() ++
|
default_options() ++
|
||||||
subtitle_options(media_profile) ++
|
subtitle_options(media_profile) ++
|
||||||
thumbnail_options(media_profile) ++
|
thumbnail_options(media_item_with_preloads) ++
|
||||||
metadata_options(media_profile) ++
|
metadata_options(media_profile) ++
|
||||||
quality_options(media_profile) ++
|
quality_options(media_profile) ++
|
||||||
output_options(media_item_with_preloads)
|
output_options(media_item_with_preloads)
|
||||||
|
|
@ -57,13 +57,16 @@ defmodule Pinchflat.Downloading.DownloadOptionBuilder do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp thumbnail_options(media_profile) do
|
defp thumbnail_options(media_item_with_preloads) do
|
||||||
|
media_profile = media_item_with_preloads.source.media_profile
|
||||||
mapped_struct = Map.from_struct(media_profile)
|
mapped_struct = Map.from_struct(media_profile)
|
||||||
|
|
||||||
Enum.reduce(mapped_struct, [], fn attr, acc ->
|
Enum.reduce(mapped_struct, [], fn attr, acc ->
|
||||||
case attr do
|
case attr do
|
||||||
{:download_thumbnail, true} ->
|
{:download_thumbnail, true} ->
|
||||||
acc ++ [:write_thumbnail, convert_thumbnail: "jpg"]
|
thumbnail_save_location = determine_thumbnail_location(media_item_with_preloads)
|
||||||
|
|
||||||
|
acc ++ [:write_thumbnail, convert_thumbnail: "jpg", output: "thumbnail:#{thumbnail_save_location}"]
|
||||||
|
|
||||||
{:embed_thumbnail, true} ->
|
{:embed_thumbnail, true} ->
|
||||||
acc ++ [:embed_thumbnail, convert_thumbnail: "jpg"]
|
acc ++ [:embed_thumbnail, convert_thumbnail: "jpg"]
|
||||||
|
|
@ -102,15 +105,20 @@ defmodule Pinchflat.Downloading.DownloadOptionBuilder do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp output_options(media_item_with_preloads) do
|
defp output_options(media_item_with_preloads) do
|
||||||
media_profile = media_item_with_preloads.source.media_profile
|
output_path_template = media_item_with_preloads.source.media_profile.output_path_template
|
||||||
additional_options_map = output_options_map(media_item_with_preloads)
|
|
||||||
{:ok, output_path} = OutputPathBuilder.build(media_profile.output_path_template, additional_options_map)
|
|
||||||
|
|
||||||
[
|
[
|
||||||
output: Path.join(base_directory(), output_path)
|
output: build_output_path(output_path_template, media_item_with_preloads)
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp build_output_path(string, media_item_with_preloads) do
|
||||||
|
additional_options_map = output_options_map(media_item_with_preloads)
|
||||||
|
{:ok, output_path} = OutputPathBuilder.build(string, additional_options_map)
|
||||||
|
|
||||||
|
Path.join(base_directory(), output_path)
|
||||||
|
end
|
||||||
|
|
||||||
defp output_options_map(media_item_with_preloads) do
|
defp output_options_map(media_item_with_preloads) do
|
||||||
source = media_item_with_preloads.source
|
source = media_item_with_preloads.source
|
||||||
|
|
||||||
|
|
@ -120,6 +128,19 @@ defmodule Pinchflat.Downloading.DownloadOptionBuilder do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# I don't love the string manipulation here, but what can ya' do.
|
||||||
|
# It's dependent on the output_path_template being a string ending `.{{ ext }}`
|
||||||
|
# (or equivalent), but that's validated by the MediaProfile schema.
|
||||||
|
defp determine_thumbnail_location(media_item_with_preloads) do
|
||||||
|
output_path_template = media_item_with_preloads.source.media_profile.output_path_template
|
||||||
|
|
||||||
|
output_path_template
|
||||||
|
|> String.split(~r{\.}, include_captures: true)
|
||||||
|
|> List.insert_at(-3, "-thumb")
|
||||||
|
|> Enum.join()
|
||||||
|
|> build_output_path(media_item_with_preloads)
|
||||||
|
end
|
||||||
|
|
||||||
defp base_directory do
|
defp base_directory do
|
||||||
Application.get_env(:pinchflat, :media_directory)
|
Application.get_env(:pinchflat, :media_directory)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,22 @@ defmodule Pinchflat.Metadata.MetadataParser do
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
|> Enum.find_value(fn attrs -> attrs["filepath"] end)
|
|> Enum.find_value(fn attrs -> attrs["filepath"] end)
|
||||||
|
|
||||||
%{
|
if thumbnail_filepath do
|
||||||
thumbnail_filepath: thumbnail_filepath
|
# NOTE: whole ordeal needed due to a bug I found in yt-dlp
|
||||||
}
|
# https://github.com/yt-dlp/yt-dlp/issues/9445
|
||||||
|
# Can be reverted to remove this entire conditional once fixed
|
||||||
|
%{
|
||||||
|
thumbnail_filepath:
|
||||||
|
thumbnail_filepath
|
||||||
|
|> String.split(~r{\.}, include_captures: true)
|
||||||
|
|> List.insert_at(-3, "-thumb")
|
||||||
|
|> Enum.join()
|
||||||
|
}
|
||||||
|
else
|
||||||
|
%{
|
||||||
|
thumbnail_filepath: thumbnail_filepath
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp parse_infojson_metadata(metadata) do
|
defp parse_infojson_metadata(metadata) do
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,12 @@ defmodule Pinchflat.Profiles.MediaProfile do
|
||||||
media_profile
|
media_profile
|
||||||
|> cast(attrs, @allowed_fields)
|
|> cast(attrs, @allowed_fields)
|
||||||
|> validate_required(@required_fields)
|
|> validate_required(@required_fields)
|
||||||
|
# Ensures it ends with `.{{ ext }}` or `.%(ext)s` or similar (with a little wiggle room)
|
||||||
|
|> validate_format(:output_path_template, ext_regex(), message: "must end with .{{ ext }}")
|
||||||
|> unique_constraint(:name)
|
|> unique_constraint(:name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp ext_regex do
|
||||||
|
~r/\.({{ ?ext ?}}|%\( ?ext ?\)[sS])$/
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,15 @@ defmodule Pinchflat.Downloading.DownloadOptionBuilderTest do
|
||||||
assert :write_thumbnail in res
|
assert :write_thumbnail in res
|
||||||
end
|
end
|
||||||
|
|
||||||
test "convertes thumbnail to jpg when download_thumbnail is true", %{media_item: media_item} do
|
test "appends -thumb to the thumbnail name when download_thumbnail is true", %{media_item: media_item} do
|
||||||
|
media_item = update_media_profile_attribute(media_item, %{download_thumbnail: true})
|
||||||
|
|
||||||
|
assert {:ok, res} = DownloadOptionBuilder.build(media_item)
|
||||||
|
|
||||||
|
assert {:output, "thumbnail:/tmp/test/media/%(title)S-thumb.%(ext)s"} in res
|
||||||
|
end
|
||||||
|
|
||||||
|
test "converts thumbnail to jpg when download_thumbnail is true", %{media_item: media_item} do
|
||||||
media_item = update_media_profile_attribute(media_item, %{download_thumbnail: true})
|
media_item = update_media_profile_attribute(media_item, %{download_thumbnail: true})
|
||||||
|
|
||||||
assert {:ok, res} = DownloadOptionBuilder.build(media_item)
|
assert {:ok, res} = DownloadOptionBuilder.build(media_item)
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,15 @@ defmodule Pinchflat.Metadata.MetadataParserTest do
|
||||||
assert String.ends_with?(result.thumbnail_filepath, ".webp")
|
assert String.ends_with?(result.thumbnail_filepath, ".webp")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# NOTE: this can be removed once this bug is fixed
|
||||||
|
# https://github.com/yt-dlp/yt-dlp/issues/9445
|
||||||
|
# and the associated conditional in the parser is removed
|
||||||
|
test "automatically appends `-thumb` to the thumbnail filename", %{metadata: metadata} do
|
||||||
|
result = Parser.parse_for_media_item(metadata)
|
||||||
|
|
||||||
|
assert String.contains?(result.thumbnail_filepath, "-thumb.webp")
|
||||||
|
end
|
||||||
|
|
||||||
test "doesn't freak out if the media has no thumbnails", %{metadata: metadata} do
|
test "doesn't freak out if the media has no thumbnails", %{metadata: metadata} do
|
||||||
metadata = Map.put(metadata, "thumbnails", %{})
|
metadata = Map.put(metadata, "thumbnails", %{})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,11 @@ defmodule Pinchflat.ProfilesTest do
|
||||||
|
|
||||||
describe "create_media_profile/1" do
|
describe "create_media_profile/1" do
|
||||||
test "creation with valid data creates a media_profile" do
|
test "creation with valid data creates a media_profile" do
|
||||||
valid_attrs = %{name: "some name", output_path_template: "some output_path_template"}
|
valid_attrs = %{name: "some name", output_path_template: "output_template.{{ ext }}"}
|
||||||
|
|
||||||
assert {:ok, %MediaProfile{} = media_profile} = Profiles.create_media_profile(valid_attrs)
|
assert {:ok, %MediaProfile{} = media_profile} = Profiles.create_media_profile(valid_attrs)
|
||||||
assert media_profile.name == "some name"
|
assert media_profile.name == "some name"
|
||||||
assert media_profile.output_path_template == "some output_path_template"
|
assert media_profile.output_path_template == "output_template.{{ ext }}"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "creation with invalid data returns error changeset" do
|
test "creation with invalid data returns error changeset" do
|
||||||
|
|
@ -44,14 +44,14 @@ defmodule Pinchflat.ProfilesTest do
|
||||||
|
|
||||||
update_attrs = %{
|
update_attrs = %{
|
||||||
name: "some updated name",
|
name: "some updated name",
|
||||||
output_path_template: "some updated output_path_template"
|
output_path_template: "new_output_template.{{ ext }}"
|
||||||
}
|
}
|
||||||
|
|
||||||
assert {:ok, %MediaProfile{} = media_profile} =
|
assert {:ok, %MediaProfile{} = media_profile} =
|
||||||
Profiles.update_media_profile(media_profile, update_attrs)
|
Profiles.update_media_profile(media_profile, update_attrs)
|
||||||
|
|
||||||
assert media_profile.name == "some updated name"
|
assert media_profile.name == "some updated name"
|
||||||
assert media_profile.output_path_template == "some updated output_path_template"
|
assert media_profile.output_path_template == "new_output_template.{{ ext }}"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "updating with invalid data returns error changeset" do
|
test "updating with invalid data returns error changeset" do
|
||||||
|
|
@ -132,5 +132,41 @@ defmodule Pinchflat.ProfilesTest do
|
||||||
media_profile = media_profile_fixture()
|
media_profile = media_profile_fixture()
|
||||||
assert %Ecto.Changeset{} = Profiles.change_media_profile(media_profile)
|
assert %Ecto.Changeset{} = Profiles.change_media_profile(media_profile)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it ensures the media profile's output template ends with an extension" do
|
||||||
|
valid_templates = [
|
||||||
|
"output_template.{{ ext }}",
|
||||||
|
"output_template.{{ext}}",
|
||||||
|
"output_template.%(ext)s",
|
||||||
|
"output_template.%(ext)S",
|
||||||
|
"output_template.%( ext )s",
|
||||||
|
"output_template.%( ext )S"
|
||||||
|
]
|
||||||
|
|
||||||
|
for template <- valid_templates do
|
||||||
|
cs = Profiles.change_media_profile(%MediaProfile{}, %{name: "a", output_path_template: template})
|
||||||
|
|
||||||
|
assert cs.valid?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it does not allow invalid output templates" do
|
||||||
|
invalid_templates = [
|
||||||
|
"output_template.{{ ext }}.something",
|
||||||
|
"output_template.{{ ext }}",
|
||||||
|
"output_template{{ ext }}",
|
||||||
|
"output_template.%(ext)s.something",
|
||||||
|
"output_template.txt",
|
||||||
|
"output_template%(ext)s",
|
||||||
|
"output_template.%(nope)s",
|
||||||
|
"output_template"
|
||||||
|
]
|
||||||
|
|
||||||
|
for template <- invalid_templates do
|
||||||
|
cs = Profiles.change_media_profile(%MediaProfile{}, %{name: "a", output_path_template: template})
|
||||||
|
|
||||||
|
refute cs.valid?
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,10 @@ defmodule PinchflatWeb.MediaProfileControllerTest do
|
||||||
alias Pinchflat.Repo
|
alias Pinchflat.Repo
|
||||||
alias Pinchflat.Settings
|
alias Pinchflat.Settings
|
||||||
|
|
||||||
@create_attrs %{name: "some name", output_path_template: "some output_path_template"}
|
@create_attrs %{name: "some name", output_path_template: "output_template.{{ ext }}"}
|
||||||
@update_attrs %{
|
@update_attrs %{
|
||||||
name: "some updated name",
|
name: "some updated name",
|
||||||
output_path_template: "some updated output_path_template"
|
output_path_template: "new_output_template.{{ ext }}"
|
||||||
}
|
}
|
||||||
@invalid_attrs %{name: nil, output_path_template: nil}
|
@invalid_attrs %{name: nil, output_path_template: nil}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue