diff --git a/lib/pinchflat/downloading/download_option_builder.ex b/lib/pinchflat/downloading/download_option_builder.ex index ab2b56a..be73d64 100644 --- a/lib/pinchflat/downloading/download_option_builder.ex +++ b/lib/pinchflat/downloading/download_option_builder.ex @@ -6,8 +6,10 @@ defmodule Pinchflat.Downloading.DownloadOptionBuilder do alias Pinchflat.Sources alias Pinchflat.Sources.Source alias Pinchflat.Media.MediaItem + alias Pinchflat.Media.MediaQuery alias Pinchflat.Downloading.OutputPathBuilder alias Pinchflat.Downloading.QualityOptionBuilder + alias Pinchflat.Repo alias Pinchflat.Utils.FilesystemUtils, as: FSUtils @@ -209,10 +211,28 @@ defmodule Pinchflat.Downloading.DownloadOptionBuilder do "source_collection_name" => source.collection_name, "source_collection_type" => to_string(source.collection_type), "media_playlist_index" => pad_int(media_item_with_preloads.playlist_index), + "media_playlist_index_reversed" => pad_int(calculate_reversed_playlist_index(media_item_with_preloads)), "media_upload_date_index" => pad_int(media_item_with_preloads.upload_date_index) } end + defp calculate_reversed_playlist_index(media_item_with_preloads) do + source = media_item_with_preloads.source + current_index = media_item_with_preloads.playlist_index || 0 + + max_index = + MediaQuery.new() + |> where(^MediaQuery.for_source(source)) + |> Repo.aggregate(:max, :playlist_index) + + case {max_index, current_index} do + {nil, _} -> 0 + {max, _} when max <= 0 -> 0 + {max, current} when current > 0 -> max - current + 1 + _ -> 0 + 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. diff --git a/lib/pinchflat/downloading/output_path_builder.ex b/lib/pinchflat/downloading/output_path_builder.ex index 1c1392f..1d56606 100644 --- a/lib/pinchflat/downloading/output_path_builder.ex +++ b/lib/pinchflat/downloading/output_path_builder.ex @@ -56,6 +56,7 @@ defmodule Pinchflat.Downloading.OutputPathBuilder do "season_episode_index_from_date" => "s%(upload_date>%Y)Se%(upload_date>%m%d)S{{ media_upload_date_index }}", "artist_name" => "%(artist,creator,uploader,uploader_id)S", "static_season__episode_by_index" => "Season 1/s01e{{ media_playlist_index }}", + "static_season__episode_by_index_reversed" => "Season 1/s01e{{ media_playlist_index_reversed }}", "static_season__episode_by_date" => "Season 1/s01e%(upload_date>%y%m%d)S", "season_by_year__episode_by_date" => "Season %(upload_date>%Y)S/s%(upload_date>%Y)Se%(upload_date>%m%d)S", "season_by_year__episode_by_date_and_index" => diff --git a/lib/pinchflat_web/controllers/media_profiles/media_profile_html.ex b/lib/pinchflat_web/controllers/media_profiles/media_profile_html.ex index 72beafe..32d7523 100644 --- a/lib/pinchflat_web/controllers/media_profiles/media_profile_html.ex +++ b/lib/pinchflat_web/controllers/media_profiles/media_profile_html.ex @@ -63,6 +63,8 @@ defmodule PinchflatWeb.MediaProfiles.MediaProfileHTML do "same as the above but it handles dates better. This is the recommended option", static_season__episode_by_index: "Season 1/s01eXX where XX is the video's position in the playlist. Only recommended for playlists (not channels) that don't change", + static_season__episode_by_index_reversed: + "Season 1/s01eXX where XX is the video's position in the playlist in reversed order (last video is episode 1).", static_season__episode_by_date: "Season 1/s01eYYMMDD. Recommended for playlists that might change or where order isn't important" ] @@ -86,6 +88,8 @@ defmodule PinchflatWeb.MediaProfiles.MediaProfileHTML do "the upload date formatted as sYYYYeMMDDII where II is an index to prevent date collisions", media_playlist_index: "the place of the media item in the playlist. Do not use with channels. May not work if the playlist is updated", + media_playlist_index_reversed: + "the place of the media item in the playlist in reversed order (last video is 1). Do not use with channels. May not work if the playlist is updated", media_item_id: "the ID of the media item in Pinchflat's database", source_id: "the ID of the source in Pinchflat's database", media_profile_id: "the ID of the media profile in Pinchflat's database"