diff --git a/.gitignore b/.gitignore index d467a238..20d1b188 100644 --- a/.gitignore +++ b/.gitignore @@ -145,5 +145,7 @@ docker/testing/volumes .local/ +.ytdl-sub-working-directory + ffmpeg.exe -ffprobe.exe \ No newline at end of file +ffprobe.exe diff --git a/examples/music_audio_config.yaml b/examples/music_audio_config.yaml deleted file mode 100644 index 7338a67d..00000000 --- a/examples/music_audio_config.yaml +++ /dev/null @@ -1,194 +0,0 @@ -# This config builds presets to download and format the following use-cases: -# - YouTube -# - Songs -# - From a single video -# - Albums -# - From a video, where each song is represented by chapters -# - From a playlist where each video is a song on the album -# - Discographies -# - From a channel or a channel's set of playlists -# - Bandcamp -# - Track, Album, Artist URL as a Discography -# - Soundcloud -# - Track, Album, Artist URL as a Discography -# -# All files will look like: -# -# music_directory/ -# Artist/ -# [2022] Some Single/ -# 01 - Some Single.mp3 -# folder.jpg -# [2023] Latest Album/ -# 01 - Track Title.mp3 -# 02 - Another Track.mp3 -# folder.jpg -# -# The idea is to format files under music_directory as `Artist/Album/Song`. Singles that do not -# belong to an album will be represented like albums with a single track. -# -# Each file will be properly tagged regardless of file extension (suppers flac, ogg, mp3, etc) -# and should show up nicely in music players that take advantage of tags. -configuration: - working_directory: '.ytdl-sub-downloads' - umask: "002" - -presets: - - # The `base` preset that represents how all files will be structured after downloading. - # Every other preset afterwards will inherit this preset. - base: - # Store all music under our music_directory (to be set as an override variable). - # Store each resulting file with its full track path, and treat thumbnails as the album covers. - # - # Maintain a download archive. This will produce a hidden file in your music directory - # containing an archive of all audio previously downloaded. This makes it so we do not - # re-download files we already have. - output_options: - output_directory: "{music_directory}" - file_name: "{track_full_path}" - thumbnail_name: "{album_cover_path}" - maintain_download_archive: True - - # Set break_on_existing to True. This will stop fetching any more metadata once we - # hit a video/audio that we already have downloaded. - ytdl_options: - break_on_existing: True - - # Extract any audio from files using this codec and quality. - audio_extract: - codec: "mp3" - quality: 320 - - # Set these music tags on every resulting audio file. - # It is recommended to keep most of this as-is, and use override - # variables to set them to be what you want. - music_tags: - artist: "{track_artist}" - artists: "{track_artist}" - albumartist: "{track_artist}" - albumartists: "{track_artist}" - title: "{track_title}" - album: "{track_album}" - track: "{track_number}" - tracktotal: "{track_total}" - year: "{track_year}" - genre: "{track_genre}" - - # Optionally embed the thumbnail into the track - embed_thumbnail: False - - # For every configurable field, make it an override variable, - # so we can carefully tune different use-cases by only modifying override variables. - overrides: - # Track Overrides. By default, set overrides to make each song its own album - track_title: "{title}" - track_album: "{title}" - track_artist: "{channel}" - track_number: "1" - track_number_padded: "01" - track_total: "1" - track_year: "{upload_year}" - track_genre: "Unset" - # Filename Overrides - track_file_name: "{track_number_padded} - {track_title_sanitized}.{ext}" - album_file_name: "folder.{thumbnail_ext}" - # Directory Name Overrides - music_directory: "OVERRIDE THIS WITH YOUR MUSIC DIRECTORY" - artist_dir: "{track_artist_sanitized}" - album_dir: "[{track_year}] {track_album_sanitized}" - # Full Filepath Overrides - track_full_path: "{artist_dir}/{album_dir}/{track_file_name}" - album_cover_path: "{artist_dir}/{album_dir}/{album_file_name}" - -#################################################################################################### - - # Make the 'single` preset accept a single URL using the override variable 'url' - # Each audio file will reside in its own album. - single: - # Inherit from `base` - preset: "base" - - download: - url: "{url}" - -#################################################################################################### - - # Make the 'albums_from_playlists' preset format audio files to reside under albums, where - # each album is a playlist. If a file downloaded using this preset is not part of a playlist, - # it will default to how it'd look as a `single`. - albums_from_playlists: - # Inherit from single - preset: "single" - - # Override various track properties using playlist variables. - overrides: - track_album: "{playlist_title}" - track_number: "{playlist_index}" - track_number_padded: "{playlist_index_padded}" - track_total: "{playlist_count}" - track_year: "{playlist_max_upload_year}" - -#################################################################################################### - - # Make the 'albums_from_chapters' preset format audio files to reside under an album, where the - # video itself is an album containing all the songs in it represented by chapters. - albums_from_chapters: - # Inherit from single - preset: "single" - - # Embed chapters if present. If no chapters are present, allow parsing comments that contain - # timestamps to each song, and use those as chapters. - chapters: - embed_chapters: True - allow_chapters_from_comments: True - - # Split each file by its chapters. If a file does not have chapters, simply 'pass' on it and - # process the next audio/video file. - split_by_chapters: - when_no_chapters: "pass" - - # Override various track properties using chapter variables. - overrides: - track_title: "{chapter_title}" # Chapter title is the track title - track_album: "{title}" # Video's title is the album title - track_number: "{chapter_index}" - track_number_padded: "{chapter_index_padded}" - track_total: "{chapter_count}" - -#################################################################################################### - - # Make the 'soundcloud_discography' preset specially made for ripping SoundCloud artists. - # We will use the 'multi_url' approach to download both albums and non-album tracks - soundcloud_discography: - preset: "base" - - # Download using the multi_url strategy - download: - # The first URL will be all the artist's tracks. - # Treat these as singles - an album with a single track - - url: "{sc_artist_url}/tracks" - variables: - sc_track_album: "{title}" - sc_track_number: "1" - sc_track_number_padded: "01" - sc_track_total: "1" - sc_track_year: "{upload_year}" - # Set the second URL to the artist's albums. If a track belongs to both - # to an album and tracks (in the URL above), it will resolve to this - # URL and include the album metadata we set below. - - url: "{sc_artist_url}/albums" - variables: - sc_track_album: "{playlist_title}" - sc_track_number: "{playlist_index}" - sc_track_number_padded: "{playlist_index_padded}" - sc_track_total: "{playlist_count}" - sc_track_year: "{playlist_max_upload_year}" - - # Override various track properties using playlist variables. - overrides: - track_album: "{sc_track_album}" - track_number: "{sc_track_number}" - track_number_padded: "{sc_track_number_padded}" - track_total: "{sc_track_total}" - track_year: "{sc_track_year}" \ No newline at end of file diff --git a/examples/music_audio_subscriptions.yaml b/examples/music_audio_subscriptions.yaml deleted file mode 100644 index e627fa9d..00000000 --- a/examples/music_audio_subscriptions.yaml +++ /dev/null @@ -1,137 +0,0 @@ -# Define any number of subscriptions in a single file, or use multiple -# files to organize (i.e by use-case, website, genre, etc) -# -# Each example show-cases every use case: -# - YouTube -# - Songs -# - From a single video -# - Albums -# - From a video, where each song is represented by chapters -# - From a playlist where each video is a song on the album -# - Discographies -# - From a channel or a channel's set of playlists -# - Bandcamp -# - Track, Album, Artist URL as a Discography -# - Soundcloud -# - Track, Album, Artist URL as a Discography -# -#################################################################################################### -# YOUTUBE - PLAYLIST OF ALBUMS -# See https://www.youtube.com/playlist?list=PLBsm_SagFMmdWnCnrNtLjA9kzfrRkto4i -# -# Downloads the GameChops Albums' playlist. Each video in the playlist is an album with -# chapters representing songs. -game_chops: - preset: "albums_from_chapters" - - # Perform regex to extract title from the chapter's title to not include the track number. - # Configuring this hard is a bit overkill, but I'm a perfectionist :-) - regex: - from: - chapter_title: - match: - - "^\\d+\\.\\.(.*)" # Captures 'title' from '1..title' - capture_group_names: - - "captured_track_title" - capture_group_defaults: - - "{chapter_title}" - - # Explicitly set the URL, track artist, and genre. - # Override various track properties using the regex variables we extracted. - overrides: - url: "https://www.youtube.com/playlist?list=PLBsm_SagFMmdWnCnrNtLjA9kzfrRkto4i" - track_artist: "GameChops" - track_genre: "Lofi" - track_title: "{captured_track_title}" - - -#################################################################################################### -# YOUTUBE - MANY ALBUMS FROM MANY ARTISTS UPLOADED BY A CHANNEL -# See https://www.youtube.com/@heavymetalofeasternbloc -# -# Downloads the entire 'Heavy Metal from the Eastern Bloc' channel. Each video they upload -# is an album from Eastern Europe with chapters representing songs. -eastern_bloc: - # Inherit albums from chapters - preset: "albums_from_chapters" - - # Perform regex on many fields (title, description, chapter title) to extract as much - # metadata as possible - regex: - skip_if_match_fails: False # Error if regex match fails - from: - title: - match: - - "^(.*) - (.*) \\|\\|.*" # Captures artist, album from 'artist - album ||...' - - "^(.*) - (.*) \\[.*" # Captures artist, ablum from 'artist - album [...' - - "^(.*) - (.*)" # Captures artist, ablum from 'artist - album' - capture_group_names: - - "captured_track_artist" - - "captured_track_album" - description: - match: - - "Genre:\\s*(.*)\\s*\n(?:Rec.+|Year):\\s*.*(\\d{4})\\s*\\n" # Captures genre and recorded year - capture_group_names: - - "captured_track_genre" - - "captured_track_year" - chapter_title: - match: - - "^(?:\\d+\\.\\s*|)(.*)" # Captures title from '1. title' - capture_group_names: - - "captured_track_title" - capture_group_defaults: - - "{chapter_title}" - - # Explicitly set the URL. - # Override various track properties using the regex variables we extracted. - overrides: - url: "https://www.youtube.com/@heavymetalofeasternbloc" - track_artist: "{captured_track_artist}" - track_album: "{captured_track_album}" - track_title: "{captured_track_title}" - track_year: "{captured_track_year}" - track_genre: "Eastern Bloc {captured_track_genre}" - - -#################################################################################################### -# BANDCAMP - DISCOGRAPHY -# See https://emilyharpist.bandcamp.com/ -# -# Downloads Emily's entire bandcamp discography. yt-dlp represents albums as playlist. -emily_hopkins: - preset: "albums_from_playlists" - regex: - from: - title: - match: - - "^Emily Hopkins - (.*)" # Captures 'title' from 'Emily Hopkins - title' - capture_group_names: - - "captured_track_title" - capture_group_defaults: - - "{title}" - - # Explicitly set the URL, track artist, and genre. - # Override various track properties using the regex variables we extracted. - overrides: - url: "https://emilyharpist.bandcamp.com/" - track_artist: "Emily Hopkins" - track_genre: "Lofi" - track_title: "{captured_track_title}" - - -#################################################################################################### -# SOUNDCLOUD - DISCOGRAPHY -# See https://soundcloud.com/jessebannon -# -# Downloads my acoustic 'album' and various tracks from SoundCloud using the soundcloud -# discography preset. I'm not very good so keep your expectations low :-) -jmbannon: - # Inherit soundcloud_discography preset - preset: "soundcloud_discography" - - # Explicitly set the SoundCloud artist url, track artist, and genre. - overrides: - sc_artist_url: "sc_artist_url" - track_artist: "jmbannon" - track_genre: "Acoustic" - diff --git a/examples/music_subscriptions.yaml b/examples/music_subscriptions.yaml new file mode 100644 index 00000000..d0c1a184 --- /dev/null +++ b/examples/music_subscriptions.yaml @@ -0,0 +1,52 @@ +# Files will be stored in the form of: +# +# music_directory/ +# Artist/ +# [2022] Some Single/ +# 01 - Some Single.mp3 +# folder.jpg +# [2023] Latest Album/ +# 01 - Track Title.mp3 +# 02 - Another Track.mp3 +# folder.jpg + +# Overrides to the prebuilt presets +__preset__: + overrides: + music_directory: "/music" + +# Supports downloading YouTube /releases tab. Also works for any playlist (or playlist of playlists) +# where each video is a single track. +YouTube Releases: + = Jazz: # Sets genre tag to "Jazz" + "Lester Young": "https://www.youtube.com/channel/UCsItMF6_fP754ihIsSRLk5A/playlists" + "Thelonious Monk": "https://www.youtube.com/@theloniousmonk3870/releases" + "Stan Getz": "https://www.youtube.com/@stangetzofficial/releases" + "Art Blakey": "https://www.youtube.com/channel/UCMki-b0zfAQiMQ0nbsrIuBQ/playlists" + +# Supports downloading playlists or individual videos where a single video is a full album. +# ytdl-sub will split the album based on video chapters, and make each chapter a track. +YouTube Full Albums: + = Lofi: + "Game Chops": "https://www.youtube.com/playlist?list=PLBsm_SagFMmdWnCnrNtLjA9kzfrRkto4i" + +# Supports downloading a SoundCloud's artists albums + singles. Be sure to not include +# any extension after the SoundCloud artist's name in the URL. +SoundCloud Discography: + = Chill Hop: + "UKNOWY": "https://soundcloud.com/uknowymunich" + = Electronic: + "Italo Brutalo": "https://soundcloud.com/italobrutalo" + "SURVIVE": "https://soundcloud.com/s-u-r-v-i-v-e" + "French79": "https://soundcloud.com/french79music" + "VHS Dreams": "https://soundcloud.com/vhsdreamsofficial" + = Synthwave: + "Lazerdiscs Records": "https://soundcloud.com/lazerdiscsrecords" + "Earmake": "https://soundcloud.com/earmake" + "Poly Poly": "https://soundcloud.com/poly_poly" + +# Supports downloading a Bandcamp artist +Bandcamp: + = Lofi: + "Emily Hopkins": "https://emilyharpist.bandcamp.com/" + diff --git a/examples/tv_show_subscriptions.yaml b/examples/tv_show_subscriptions.yaml index dcae3470..5c287227 100644 --- a/examples/tv_show_subscriptions.yaml +++ b/examples/tv_show_subscriptions.yaml @@ -22,15 +22,3 @@ TV Show Full Archive: TV Show Only Recent: = News | TV-14: "BBC": "https://www.youtube.com/@BBCNews" - - -# ADVANCED USAGE: -# Subscriptions can use the same format as a preset found within a config. -"Equivalent to BBC": - preset: - - "TV Show Only Recent" - overrides: - tv_show_name: "BBC" - url: "https://www.youtube.com/@BBCNews" - tv_show_genre: "News" - tv_show_content_rating: "TV-14" diff --git a/src/ytdl_sub/cli/entrypoint.py b/src/ytdl_sub/cli/entrypoint.py index 442d04c3..9332df66 100644 --- a/src/ytdl_sub/cli/entrypoint.py +++ b/src/ytdl_sub/cli/entrypoint.py @@ -200,7 +200,7 @@ def main() -> List[Subscription]: config = ConfigFile.from_file_path(DEFAULT_CONFIG_FILE_NAME) else: logger.info("No config specified, using defaults.") - config = ConfigFile(name="default_config", value={}) + config = ConfigFile.default() subscriptions: List[Subscription] = [] diff --git a/src/ytdl_sub/config/config_file.py b/src/ytdl_sub/config/config_file.py index da79e93f..67a906cc 100644 --- a/src/ytdl_sub/config/config_file.py +++ b/src/ytdl_sub/config/config_file.py @@ -84,6 +84,15 @@ class ConfigFile(ConfigValidator): return ConfigFile.from_dict(name=config_path, config_dict=config_dict) + @classmethod + def default(cls) -> "ConfigFile": + """ + Returns + ------- + Config initialized with all defaults + """ + return ConfigFile(name="default_config", value={}) + def as_dict(self) -> Dict[str, Any]: """ Returns diff --git a/src/ytdl_sub/prebuilt_presets/__init__.py b/src/ytdl_sub/prebuilt_presets/__init__.py index 43ae2433..036159a0 100644 --- a/src/ytdl_sub/prebuilt_presets/__init__.py +++ b/src/ytdl_sub/prebuilt_presets/__init__.py @@ -5,8 +5,6 @@ from typing import Set import mergedeep -from ytdl_sub.prebuilt_presets.tv_show import TvShowByDatePresets -from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionPresets from ytdl_sub.utils.yaml import load_yaml @@ -27,3 +25,7 @@ PREBUILT_PRESET_NAMES: Set[str] = set(PREBUILT_PRESETS.keys()) PUBLISHED_PRESET_NAMES: Set[str] = { name for name in PREBUILT_PRESET_NAMES if not name.startswith("_") } + + +class PrebuiltPresets: + preset_names: Set[str] diff --git a/src/ytdl_sub/prebuilt_presets/music/__init__.py b/src/ytdl_sub/prebuilt_presets/music/__init__.py new file mode 100644 index 00000000..69603e05 --- /dev/null +++ b/src/ytdl_sub/prebuilt_presets/music/__init__.py @@ -0,0 +1,11 @@ +from ytdl_sub.prebuilt_presets import PrebuiltPresets + + +class MusicPresets(PrebuiltPresets): + preset_names = { + "Single", + "SoundCloud Discography", + "YouTube Releases", + "YouTube Full Albums", + "Bandcamp", + } diff --git a/src/ytdl_sub/prebuilt_presets/music/music.yaml b/src/ytdl_sub/prebuilt_presets/music/music.yaml new file mode 100644 index 00000000..ca6683b9 --- /dev/null +++ b/src/ytdl_sub/prebuilt_presets/music/music.yaml @@ -0,0 +1,150 @@ +presets: + + _music_base: + output_options: + output_directory: "{music_directory}" + file_name: "{track_full_path}" + thumbnail_name: "{album_cover_path}" + maintain_download_archive: True + + ytdl_options: + break_on_existing: True + + format: "ba[ext=webm]/ba" + + audio_extract: + codec: "best" + + music_tags: + artist: "{track_artist}" + albumartist: "{track_album_artist}" + title: "{track_title}" + album: "{track_album}" + track: "{track_number}" + tracktotal: "{track_total}" + year: "{track_year}" + # multi-tags + artists: + - "{track_artist}" + albumartists: + - "{track_album_artist}" + genre: + - "{track_genre}" + + overrides: + # Subscription overrides + subscription_indent_1: "Unset" # genre + url: "{subscription_value}" + + # Track Overrides + track_title: "{title}" + track_album: "{title}" + track_artist: "{subscription_name}" + track_album_artist: "{track_artist}" + track_number: "1" + track_number_padded: "01" + track_total: "1" + track_year: "{upload_year}" + track_genre: "{subscription_indent_1}" + + # Directory Overrides + music_directory: "/music" + artist_dir: "{track_artist_sanitized}" + album_dir: "[{track_year}] {track_album_sanitized}" + track_file_name: "{track_number_padded} - {track_title_sanitized}.{ext}" + track_full_path: "{artist_dir}/{album_dir}/{track_file_name}" + album_cover_path: "{artist_dir}/{album_dir}/folder.{thumbnail_ext}" + + + "Single": + preset: + - "_music_base" + + download: + - "{url}" + + + _albums_from_playlists: + preset: + - "Single" + + overrides: + track_album: "{playlist_title}" + track_number: "{playlist_index}" + track_number_padded: "{playlist_index_padded}" + track_total: "{playlist_count}" + track_year: "{playlist_max_upload_year}" + + + _albums_from_chapters: + preset: "Single" + + chapters: + embed_chapters: True + split_by_chapters: + when_no_chapters: "pass" + + overrides: + track_title: "{chapter_title}" # Chapter title is the track title + track_album: "{title}" # Video's title is the album title + track_number: "{chapter_index}" + track_number_padded: "{chapter_index_padded}" + track_total: "{chapter_count}" + + "SoundCloud Discography": + preset: "_music_base" + + # Download using the multi_url strategy + download: + download_strategy: "multi_url" + urls: + # The first URL will be all the artist's tracks. + # Treat these as singles - an album with a single track + - url: "{url}/tracks" + variables: + sc_track_album: "{title}" + sc_track_number: "1" + sc_track_number_padded: "01" + sc_track_total: "1" + sc_track_year: "{upload_year}" + # Set the second URL to the artist's albums. If a track belongs to both + # to an album and tracks (in the URL above), it will resolve to this + # URL and include the album metadata we set below. + - url: "{url}/albums" + variables: + sc_track_album: "{playlist_title}" + sc_track_number: "{playlist_index}" + sc_track_number_padded: "{playlist_index_padded}" + sc_track_total: "{playlist_count}" + sc_track_year: "{playlist_max_upload_year}" + + # Override various track properties using playlist variables. + overrides: + track_album: "{sc_track_album}" + track_number: "{sc_track_number}" + track_number_padded: "{sc_track_number_padded}" + track_total: "{sc_track_total}" + track_year: "{sc_track_year}" + + "YouTube Releases": + preset: + - "_albums_from_playlists" + + "YouTube Full Albums": + preset: + - "_albums_from_chapters" + + "Bandcamp": + preset: + - "_albums_from_playlists" + regex: + from: + title: + match: + - ".*? - (.*)" # Captures 'Some - Song' from 'Emily Hopkins - Some - Song' + capture_group_names: + - "captured_track_title" + capture_group_defaults: + - "{title}" + overrides: + track_title: "{captured_track_title}" diff --git a/src/ytdl_sub/prebuilt_presets/tv_show/__init__.py b/src/ytdl_sub/prebuilt_presets/tv_show/__init__.py index e2210061..b2604726 100644 --- a/src/ytdl_sub/prebuilt_presets/tv_show/__init__.py +++ b/src/ytdl_sub/prebuilt_presets/tv_show/__init__.py @@ -1,26 +1,4 @@ -from typing import Set - - -class PrebuiltPreset: - """placeholder""" - - -_ = PrebuiltPreset() - - -class PrebuiltPresets: - @classmethod - def get_preset_names(cls) -> Set[str]: - """ - Returns - ------- - Preset names in the set - """ - return set( - preset_name - for preset_name in dir(cls) - if isinstance(getattr(cls, preset_name), PrebuiltPreset) - ) +from ytdl_sub.prebuilt_presets import PrebuiltPresets class TvShowByDatePresets(PrebuiltPresets): @@ -29,38 +7,44 @@ class TvShowByDatePresets(PrebuiltPresets): numbers. """ - kodi_tv_show_by_date = _ - jellyfin_tv_show_by_date = _ - plex_tv_show_by_date = _ + preset_names = { + "kodi_tv_show_by_date", + "jellyfin_tv_show_by_date", + "plex_tv_show_by_date", + } class TvShowByDateEpisodeFormattingPresets(PrebuiltPresets): - season_by_year__episode_by_month_day = _ - season_by_year__episode_by_month_day_reversed = _ - season_by_year_month__episode_by_day = _ - season_by_year__episode_by_download_index = _ + preset_names = { + "season_by_year__episode_by_month_day", + "season_by_year__episode_by_month_day_reversed", + "season_by_year_month__episode_by_day", + "season_by_year__episode_by_download_index", + } class TvShowCollectionPresets(PrebuiltPresets): - """ - Docstring for all TV SHOW URL presets - """ - - kodi_tv_show_collection = _ - jellyfin_tv_show_collection = _ - plex_tv_show_collection = _ + preset_names = { + "kodi_tv_show_collection", + "jellyfin_tv_show_collection", + "plex_tv_show_collection", + } class TvShowCollectionEpisodeFormattingPresets(PrebuiltPresets): - season_by_collection__episode_by_year_month_day = _ - season_by_collection__episode_by_year_month_day_reversed = _ - season_by_collection__episode_by_playlist_index = _ - season_by_collection__episode_by_playlist_index_reversed = _ + preset_names = { + "season_by_collection__episode_by_year_month_day", + "season_by_collection__episode_by_year_month_day_reversed", + "season_by_collection__episode_by_playlist_index", + "season_by_collection__episode_by_playlist_index_reversed", + } class TvShowCollectionSeasonPresets(PrebuiltPresets): - collection_season_1 = _ - collection_season_2 = _ - collection_season_3 = _ - collection_season_4 = _ - collection_season_5 = _ + preset_names = { + "collection_season_1", + "collection_season_2", + "collection_season_3", + "collection_season_4", + "collection_season_5", + } diff --git a/tests/conftest.py b/tests/conftest.py index c9d64608..5e2c4af7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -186,6 +186,9 @@ def tv_show_subscriptions_path() -> Path: @pytest.fixture() def music_audio_config(working_directory) -> ConfigFile: - return _load_config( - config_path=Path("examples/music_audio_config.yaml"), working_directory=working_directory - ) + return ConfigFile.from_dict({"configuration": {"working_directory": working_directory}}) + + +@pytest.fixture() +def music_subscriptions_path() -> Path: + return Path("examples/music_subscriptions.yaml") diff --git a/tests/e2e/bandcamp/test_bandcamp.py b/tests/e2e/bandcamp/test_bandcamp.py index 2b1fb3f0..b3eeb37e 100644 --- a/tests/e2e/bandcamp/test_bandcamp.py +++ b/tests/e2e/bandcamp/test_bandcamp.py @@ -10,27 +10,15 @@ from ytdl_sub.subscriptions.subscription import Subscription @pytest.fixture def subscription_dict(output_directory): return { - "preset": "albums_from_playlists", - "regex": { - "skip_if_match_fails": False, # Error if regex match fails - "from": { - "title": { - "match": ["^(.*) - (.*)"], # Captures 'title' from 'Emily Hopkins - title' - "capture_group_names": [ - "captured_track_artist", - "captured_track_title", - ], - } - }, - }, + "preset": "Bandcamp", "ytdl_options": { "max_downloads": 15, }, - "date_range": {"before": "20230101"}, + "audio_extract": {"codec": "mp3", "quality": 320}, + "date_range": {"after": "20210110"}, "overrides": { - "url": "https://funkypselicave.bandcamp.com/", - "track_title": "{captured_track_title}", - "track_artist": "{captured_track_artist}", + "subscription_value": "https://sithuayemusic.bandcamp.com/", + "subscription_indent_1": "Progressive Metal", "music_directory": output_directory, }, } @@ -38,7 +26,7 @@ def subscription_dict(output_directory): class TestBandcamp: @pytest.mark.parametrize("dry_run", [True, False]) - def test_download_artist_url( + def test_prebuilt_preset_download( self, subscription_dict, music_audio_config, @@ -47,7 +35,7 @@ class TestBandcamp: ): discography_subscription = Subscription.from_dict( preset_dict=subscription_dict, - preset_name="jb", + preset_name="Sithu Aye", config=music_audio_config, ) transaction_log = discography_subscription.download(dry_run=dry_run) diff --git a/tests/e2e/plugins/test_audio_extract.py b/tests/e2e/plugins/test_audio_extract.py index 52277921..bd796b21 100644 --- a/tests/e2e/plugins/test_audio_extract.py +++ b/tests/e2e/plugins/test_audio_extract.py @@ -6,16 +6,18 @@ from ytdl_sub.subscriptions.subscription import Subscription @pytest.fixture -def single_song_preset_dict_old_format(output_directory): +def single_preset_dict_old_format(output_directory): return { - "preset": "single", + "preset": "Single", # test multi-tags "music_tags": {"embed_thumbnail": True, "tags": {"genres": ["multi_tag_1", "multi_tag_2"]}}, - "format": "worst[ext=mp4]", # download the worst format so it is fast + "format": "worst[ext=mp4]", + "audio_extract": {"codec": "mp3", "quality": 320}, "ytdl_options": { "postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility }, "overrides": { + "track_artist": "YouTube", "url": "https://www.youtube.com/watch?v=2lAe1cqCOXo", "music_directory": output_directory, }, @@ -23,18 +25,20 @@ def single_song_preset_dict_old_format(output_directory): @pytest.fixture -def single_song_preset_dict(output_directory): +def single_preset_dict(output_directory): return { - "preset": "single", + "preset": "Single", # test multi-tags "music_tags": {"genres": ["multi_tag_1", "multi_tag_2"]}, # test the new embed_thumbnail plugin "embed_thumbnail": True, - "format": "worst[ext=mp4]", # download the worst format so it is fast + "format": "worst[ext=mp4]", + "audio_extract": {"codec": "mp3", "quality": 320}, "ytdl_options": { "postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility }, "overrides": { + "track_artist": "YouTube", "url": "https://www.youtube.com/watch?v=2lAe1cqCOXo", "music_directory": output_directory, }, @@ -42,20 +46,21 @@ def single_song_preset_dict(output_directory): @pytest.fixture -def single_song_best_format_preset_dict(single_song_preset_dict): - return dict(single_song_preset_dict, **{"audio_extract": {"codec": "best"}}) +def single_best_format_preset_dict(single_preset_dict): + return dict(single_preset_dict, **{"audio_extract": {"codec": "best"}}) @pytest.fixture -def multiple_songs_preset_dict(output_directory): +def youtube_release_preset_dict(output_directory): return { - "preset": "albums_from_playlists", + "preset": "YouTube Releases", "audio_extract": {"codec": "vorbis", "quality": 140}, "format": "worst[ext=mp4]", # download the worst format so it is fast "ytdl_options": { "postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility }, "overrides": { + "track_artist": "Project Zombie", "url": "https://youtube.com/playlist?list=PL5BC0FC26BECA5A35", "music_directory": output_directory, }, @@ -67,14 +72,14 @@ class TestAudioExtract: def test_audio_extract_single_song_old_format( self, music_audio_config, - single_song_preset_dict_old_format, + single_preset_dict_old_format, output_directory, dry_run, ): subscription = Subscription.from_dict( config=music_audio_config, preset_name="single_song_test", - preset_dict=single_song_preset_dict_old_format, + preset_dict=single_preset_dict_old_format, ) transaction_log = subscription.download(dry_run=dry_run) @@ -93,14 +98,14 @@ class TestAudioExtract: def test_audio_extract_single_song( self, music_audio_config, - single_song_preset_dict, + single_preset_dict, output_directory, dry_run, ): subscription = Subscription.from_dict( config=music_audio_config, preset_name="single_song_test", - preset_dict=single_song_preset_dict, + preset_dict=single_preset_dict, ) transaction_log = subscription.download(dry_run=dry_run) @@ -119,14 +124,14 @@ class TestAudioExtract: def test_audio_extract_single_song_best_format( self, music_audio_config, - single_song_best_format_preset_dict, + single_best_format_preset_dict, output_directory, dry_run, ): subscription = Subscription.from_dict( config=music_audio_config, preset_name="single_song_best_test", - preset_dict=single_song_best_format_preset_dict, + preset_dict=single_best_format_preset_dict, ) transaction_log = subscription.download(dry_run=dry_run) @@ -145,14 +150,14 @@ class TestAudioExtract: def test_audio_extract_multiple_songs( self, music_audio_config, - multiple_songs_preset_dict, + youtube_release_preset_dict, output_directory, dry_run, ): subscription = Subscription.from_dict( config=music_audio_config, preset_name="multiple_songs_test", - preset_dict=multiple_songs_preset_dict, + preset_dict=youtube_release_preset_dict, ) transaction_log = subscription.download(dry_run=dry_run) diff --git a/tests/e2e/plugins/test_split_by_chapters.py b/tests/e2e/plugins/test_split_by_chapters.py index a7a39ae9..b718a134 100644 --- a/tests/e2e/plugins/test_split_by_chapters.py +++ b/tests/e2e/plugins/test_split_by_chapters.py @@ -12,13 +12,14 @@ from ytdl_sub.utils.exceptions import ValidationException @pytest.fixture def yt_album_as_chapters_preset_dict(output_directory): return { - "preset": "albums_from_chapters", - "format": "worst[ext=mp4]", # download the worst format so it is fast + "preset": "YouTube Full Albums", + "format": "worst[ext=mp4]", + "audio_extract": {"codec": "mp3", "quality": 320}, "ytdl_options": { "postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility }, "overrides": { - "url": "https://www.youtube.com/watch?v=zeR2_YjlXWA", + "subscription_value": "https://www.youtube.com/watch?v=zeR2_YjlXWA", "music_directory": output_directory, }, } @@ -76,7 +77,7 @@ class TestSplitByChapters: ): subscription = Subscription.from_dict( config=music_audio_config, - preset_name="split_by_chapters_video", + preset_name="Proved Records", preset_dict=yt_album_as_chapters_preset_dict, ) @@ -106,7 +107,7 @@ class TestSplitByChapters: ): subscription = Subscription.from_dict( config=music_audio_config, - preset_name="split_by_chapters_with_regex_video", + preset_name="split_by_chapters_with_regex_video_preset", preset_dict=yt_album_as_chapters_with_regex_preset_dict, ) @@ -142,7 +143,7 @@ class TestSplitByChapters: subscription = Subscription.from_dict( config=music_audio_config, - preset_name="split_by_chapters_with_regex_video", + preset_name="split_by_chapters_with_regex_video_no_chapters", preset_dict=yt_album_as_chapters_with_regex_preset_dict, ) diff --git a/tests/e2e/soundcloud/test_soundcloud_discography.py b/tests/e2e/soundcloud/test_soundcloud_discography.py index 6788118d..0d003f2b 100644 --- a/tests/e2e/soundcloud/test_soundcloud_discography.py +++ b/tests/e2e/soundcloud/test_soundcloud_discography.py @@ -8,11 +8,11 @@ from ytdl_sub.subscriptions.subscription import Subscription @pytest.fixture def subscription_dict(output_directory): return { - "preset": "soundcloud_discography", - "format": "worst[ext=mp3]", # download the worst format so it is fast + "preset": "SoundCloud Discography", + "audio_extract": {"codec": "mp3", "quality": 320}, "overrides": { - "track_artist": "j_b", - "sc_artist_url": "https://soundcloud.com/jessebannon", + "subscription_value": "https://soundcloud.com/jessebannon", + "subscription_indent_1": "Acoustic", "music_directory": output_directory, }, } @@ -34,7 +34,7 @@ class TestSoundcloudDiscography: ): discography_subscription = Subscription.from_dict( preset_dict=subscription_dict, - preset_name="jb", + preset_name="j_b", config=music_audio_config, ) transaction_log = discography_subscription.download(dry_run=dry_run) diff --git a/tests/resources/expected_downloads_summaries/bandcamp/test_artist_url.json b/tests/resources/expected_downloads_summaries/bandcamp/test_artist_url.json index 13425b10..0df27606 100644 --- a/tests/resources/expected_downloads_summaries/bandcamp/test_artist_url.json +++ b/tests/resources/expected_downloads_summaries/bandcamp/test_artist_url.json @@ -1,19 +1,20 @@ { - ".ytdl-sub-jb-download-archive.json": "9f5ca17dc0d842ac4c296054c0011ace", - "El Jazzy Chavo/[2022] S950 Funk/01 - Spark it.mp3": "f1fcc87884ced84be016391e3989b5c1", - "El Jazzy Chavo/[2022] S950 Funk/02 - Astronomikal Funk.mp3": "d07701404b8ddaa2e38eb51f7e2ac2d8", - "El Jazzy Chavo/[2022] S950 Funk/03 - Impulse.mp3": "43118db203e1d9427036102cfb39a1e3", - "El Jazzy Chavo/[2022] S950 Funk/04 - September.mp3": "3d75c5068e3dbb93dd86fc650c7ca84d", - "El Jazzy Chavo/[2022] S950 Funk/05 - Interlune.mp3": "63897d8af920f31af2183a17bc697c11", - "El Jazzy Chavo/[2022] S950 Funk/06 - Ninjutsu Techniques.mp3": "a500409583ee30e4cb68d64af2b32596", - "El Jazzy Chavo/[2022] S950 Funk/07 - Space Funk Flow.mp3": "1e1a12a5a42a607abf342ec4f301f471", - "El Jazzy Chavo/[2022] S950 Funk/08 - Cellar Groove.mp3": "a18ceff8785e8849d166eb2710caafa4", - "El Jazzy Chavo/[2022] S950 Funk/09 - Solar Wind.mp3": "a41665337e3fe05d7c7d9d8e6ddde737", - "El Jazzy Chavo/[2022] S950 Funk/10 - Interlune II.mp3": "8d2f3158ac9bac51aafbdbe6eb43154b", - "El Jazzy Chavo/[2022] S950 Funk/11 - Ghetto Anthem.mp3": "39085bae1b0f8544acd08f74f88cacfd", - "El Jazzy Chavo/[2022] S950 Funk/12 - Street Degree.mp3": "561f0d8fbc62f87f2149c17ee0a53ce2", - "El Jazzy Chavo/[2022] S950 Funk/13 - Trouble World.mp3": "1ad07dc6a2d6ced78449bc46a2909335", - "El Jazzy Chavo/[2022] S950 Funk/14 - Relaxation.mp3": "ba8addb0d59f26a84bbb79a6cdd1af11", - "El Jazzy Chavo/[2022] S950 Funk/15 - Journey From Within.mp3": "bd97135290482c6bbe6eac7d3a700f11", - "El Jazzy Chavo/[2022] S950 Funk/folder.jpg": "62e51365dd309e76a6323f927f6fcc94" + ".ytdl-sub-Sithu Aye-download-archive.json": "0c58919b660f699f6aea2ec523c812c5", + "Sithu Aye/[2021] 10 Years: Remixes and Reimaginings/01 - Double Helix Reimagined.mp3": "a627cfc0964be6a7e668fd8289326140", + "Sithu Aye/[2021] 10 Years: Remixes and Reimaginings/02 - Skye Reimagined.mp3": "94127e3d82f5d33d920b82f90d4f9657", + "Sithu Aye/[2021] 10 Years: Remixes and Reimaginings/03 - Baryofusion.mp3": "dcf4b30e3fdeb29154b3888838986c1e", + "Sithu Aye/[2021] 10 Years: Remixes and Reimaginings/04 - Mandalay Reimagined.mp3": "8304b012a8a8306c80e3f7f7cb0f35e7", + "Sithu Aye/[2021] 10 Years: Remixes and Reimaginings/05 - Messenger EDM Remix.mp3": "0a7e4c613a055e571142182717fc684e", + "Sithu Aye/[2021] 10 Years: Remixes and Reimaginings/folder.jpg": "bf6f70d51557a71b69fed85b2cb476f0", + "Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/01 - Invent the Universe.mp3": "d723a2e1f2ec75b3d20f1a0de616a191", + "Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/02 - Grand Unification (feat. David Maxim Micic).mp3": "0e550ebe93f8b5349eb07c7554ad22d9", + "Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/03 - Expansion.mp3": "6324f012f09a2e7028ca923fdff3a89a", + "Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/04 - Baryogenesis.mp3": "d30de9d811f56c2179fd86c6bede2fc5", + "Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/05 - Particles Collide (feat. Plini).mp3": "f869f1948b376f2ad98381b0c77d447f", + "Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/06 - Nucleosynthesis.mp3": "23d6ceb9865d6d6030d8659a2eed5698", + "Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/07 - Recombination.mp3": "4ae97dc8457e48fa7aad9a64b927bf1d", + "Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/08 - Dark Ages.mp3": "922e8a54e3e543bbf9b866e2f4a53607", + "Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/09 - Formation.mp3": "fd7ce4553df5323355bc95e6528e1515", + "Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/10 - Pale Blue Dot.mp3": "6328960f01a118d84fa1f1ab3565bf90", + "Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/folder.jpg": "d8cffeca026afaa619f641a95143f803" } \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/plugins/split_by_chapters_video.json b/tests/resources/expected_downloads_summaries/plugins/split_by_chapters_video.json index 7b3e68c1..59e5e982 100644 --- a/tests/resources/expected_downloads_summaries/plugins/split_by_chapters_video.json +++ b/tests/resources/expected_downloads_summaries/plugins/split_by_chapters_video.json @@ -1,5 +1,5 @@ { - ".ytdl-sub-split_by_chapters_video-download-archive.json": "c3fb0b4f31caaa10ac7954ea93da33c4", + ".ytdl-sub-Proved Records-download-archive.json": "c3fb0b4f31caaa10ac7954ea93da33c4", "Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3": "8827ac62201abeb94f44a46d91628aa8", "Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/02 - 02. Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3": "f17e02119bf073c4ed98da2a960b85d3", "Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/03 - 03. Blaze (Feat. Kaya Thomas - Dyke).mp3": "63c0bc97cbdaf35203011378b1860418", diff --git a/tests/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt b/tests/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt index f5f25165..d7fe2bf3 100644 --- a/tests/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt +++ b/tests/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt @@ -1,5 +1,5 @@ { - ".ytdl-sub-split_by_chapters_with_regex_video-download-archive.json": "4008e43668447f1a3a6a55520a6ff475", + ".ytdl-sub-split_by_chapters_with_regex_video_no_chapters-download-archive.json": "4008e43668447f1a3a6a55520a6ff475", "Project Zombie/[2010] Oblivion Mod "Falcor" p.1/01 - Oblivion Mod "Falcor" p.1.mp3": "8fc765ce55304814942c1f38fe9e38e2", "Project Zombie/[2010] Oblivion Mod "Falcor" p.1/folder.jpg": "fb95b510681676e81c321171fc23143e" } \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_video.json b/tests/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_video.json index 3daa3ef8..8e83d780 100644 --- a/tests/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_video.json +++ b/tests/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_video.json @@ -1,5 +1,5 @@ { - ".ytdl-sub-split_by_chapters_with_regex_video-download-archive.json": "9798e8289742586d0efd295a97c6c906", + ".ytdl-sub-split_by_chapters_with_regex_video_preset-download-archive.json": "9798e8289742586d0efd295a97c6c906", "Alfa Mist/[2017] Nocturne/01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3": "c10cff170976c3c5139f6073eeb3e25e", "Alfa Mist/[2017] Nocturne/02 - Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3": "881ecdbee4a0d565c0ec6eacf03115df", "Alfa Mist/[2017] Nocturne/03 - Blaze (Feat. Kaya Thomas - Dyke).mp3": "aa5c6fbab58dd2be2660bfb65be6a172", diff --git a/tests/resources/expected_downloads_summaries/soundcloud/test_soundcloud_discography.json b/tests/resources/expected_downloads_summaries/soundcloud/test_soundcloud_discography.json index 54b5e340..3984497b 100644 --- a/tests/resources/expected_downloads_summaries/soundcloud/test_soundcloud_discography.json +++ b/tests/resources/expected_downloads_summaries/soundcloud/test_soundcloud_discography.json @@ -1,19 +1,19 @@ { - ".ytdl-sub-jb-download-archive.json": "1a99156e9ece62539fb2608416a07200", - "j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.mp3": "317a9ee75431d6020e3cad0883c7392f", + ".ytdl-sub-j_b-download-archive.json": "1a99156e9ece62539fb2608416a07200", + "j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.mp3": "6325a6b14684f9df2d482ce27ff4d455", "j_b/[2021] Baby Santana's Dorian Groove/folder.jpg": "967892be44b8c47e1be73f055a7c6f08", - "j_b/[2021] Purple Clouds/01 - Purple Clouds.mp3": "4a5971c12ca6fdc335b0185a14e829f2", + "j_b/[2021] Purple Clouds/01 - Purple Clouds.mp3": "d7ece3072374c7cf88f44ba03a27bd26", "j_b/[2021] Purple Clouds/folder.jpg": "967892be44b8c47e1be73f055a7c6f08", - "j_b/[2022] Acoustic Treats/01 - 20160426 184214.mp3": "bcc88eb579311b59ede4c13cdf24bcb9", - "j_b/[2022] Acoustic Treats/02 - 20160502 123150.mp3": "239d10c17047662c760cce834548d91d", - "j_b/[2022] Acoustic Treats/03 - 20160504 143832.mp3": "2d6e977e3e665012fdeaa0e8c2ee7375", - "j_b/[2022] Acoustic Treats/04 - 20160601 221234.mp3": "9da5b26fc231dfd0c8f09a2a3d2fe116", - "j_b/[2022] Acoustic Treats/05 - 20160601 222440.mp3": "8fb1cb262175921dbdddd6783664fa65", - "j_b/[2022] Acoustic Treats/06 - 20170604 190236.mp3": "529846e26a18be616deb3f12d858b8ea", - "j_b/[2022] Acoustic Treats/07 - 20170612 193646.mp3": "ba2be1ace7b0c31964bf0b8b15781b27", - "j_b/[2022] Acoustic Treats/08 - 20170628 215206.mp3": "ad248c0392ced4f6d548a4852fd99f1f", - "j_b/[2022] Acoustic Treats/09 - Finding Home.mp3": "52326cbd96e6f243cae77b0f68f00ef6", - "j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.mp3": "a265ed7e4d3a014d09e79ac5f4fe3fc7", - "j_b/[2022] Acoustic Treats/11 - Untold History.mp3": "94d548773dded0089e73b26e6f923d9a", + "j_b/[2022] Acoustic Treats/01 - 20160426 184214.mp3": "2a0232454e2ef2a12e74496d3389f1ca", + "j_b/[2022] Acoustic Treats/02 - 20160502 123150.mp3": "cd4276f72de542b03d6e193352565603", + "j_b/[2022] Acoustic Treats/03 - 20160504 143832.mp3": "80d9152600faca9d0dc8dee41a028cf8", + "j_b/[2022] Acoustic Treats/04 - 20160601 221234.mp3": "2ee3c7f489ffc961e6ebc8d2ab4af000", + "j_b/[2022] Acoustic Treats/05 - 20160601 222440.mp3": "0aeb9c6165ecdaa993de4d7958ae9b5f", + "j_b/[2022] Acoustic Treats/06 - 20170604 190236.mp3": "eeb122552f13533a647828435dcac99e", + "j_b/[2022] Acoustic Treats/07 - 20170612 193646.mp3": "1c387d318152e3783c06fbe040c4abf0", + "j_b/[2022] Acoustic Treats/08 - 20170628 215206.mp3": "97a5689681217fb6da82f21953f63ffb", + "j_b/[2022] Acoustic Treats/09 - Finding Home.mp3": "5440e42341549d2ade910ef44baf44d4", + "j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.mp3": "4029bdf1d78995aa6a961fd2ea671f41", + "j_b/[2022] Acoustic Treats/11 - Untold History.mp3": "3687b16d0cefde103f80b76ba8490632", "j_b/[2022] Acoustic Treats/folder.jpg": "967892be44b8c47e1be73f055a7c6f08" } \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/unit/music/Bandcamp.json b/tests/resources/expected_downloads_summaries/unit/music/Bandcamp.json new file mode 100644 index 00000000..d051d7d5 --- /dev/null +++ b/tests/resources/expected_downloads_summaries/unit/music/Bandcamp.json @@ -0,0 +1,9 @@ +{ + ".ytdl-sub-subscription_test-download-archive.json": "36b3c7143ac4257489791309d802af82", + "subscription_test/[2020] Download First/02 - Mock Entry 20-1.mp3": "7b0ff394bc1fbb8419735914692cb2e4", + "subscription_test/[2020] Download First/03 - Mock Entry 20-2.mp3": "e3b5de70c625eb55d0eb7cacf0429fa5", + "subscription_test/[2020] Download First/04 - Mock Entry 20-3.mp3": "31fd8d0d38139aafb74ec94ba34a53dc", + "subscription_test/[2020] Download First/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/[2021] Download First/01 - Mock Entry 21-1.mp3": "3459b2735afa7e41a32c34198e780a5e", + "subscription_test/[2021] Download First/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7" +} \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/unit/music/Single.json b/tests/resources/expected_downloads_summaries/unit/music/Single.json new file mode 100644 index 00000000..d01861de --- /dev/null +++ b/tests/resources/expected_downloads_summaries/unit/music/Single.json @@ -0,0 +1,11 @@ +{ + ".ytdl-sub-subscription_test-download-archive.json": "9f6f4458d42da4561db236473896fe71", + "subscription_test/[2020] Mock Entry 20-1/01 - Mock Entry 20-1.mp3": "97320d70b1ccf04d4900b95b3c3645bc", + "subscription_test/[2020] Mock Entry 20-1/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/[2020] Mock Entry 20-2/01 - Mock Entry 20-2.mp3": "b3ceb9fc194b524c77287e248d5860aa", + "subscription_test/[2020] Mock Entry 20-2/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/[2020] Mock Entry 20-3/01 - Mock Entry 20-3.mp3": "55202bc60302d8475a3eaebc0902a253", + "subscription_test/[2020] Mock Entry 20-3/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/[2021] Mock Entry 21-1/01 - Mock Entry 21-1.mp3": "2ad0d8ee1e28a2ecc726197cda67248d", + "subscription_test/[2021] Mock Entry 21-1/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7" +} \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/unit/music/SoundCloud Discography.json b/tests/resources/expected_downloads_summaries/unit/music/SoundCloud Discography.json new file mode 100644 index 00000000..73dc4dd1 --- /dev/null +++ b/tests/resources/expected_downloads_summaries/unit/music/SoundCloud Discography.json @@ -0,0 +1,17 @@ +{ + ".ytdl-sub-subscription_test-download-archive.json": "71c01e840f508dad1f7cf2b533bdb9d3", + "subscription_test/[2020] Download First/02 - Mock Entry 20-1.mp3": "7b0ff394bc1fbb8419735914692cb2e4", + "subscription_test/[2020] Download First/03 - Mock Entry 20-2.mp3": "e3b5de70c625eb55d0eb7cacf0429fa5", + "subscription_test/[2020] Download First/04 - Mock Entry 20-3.mp3": "31fd8d0d38139aafb74ec94ba34a53dc", + "subscription_test/[2020] Download First/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/[2020] Mock Entry 20-4/01 - Mock Entry 20-4.mp3": "5ceaa156a59d7f80dd74d9ce80cf8e5c", + "subscription_test/[2020] Mock Entry 20-4/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/[2020] Mock Entry 20-5/01 - Mock Entry 20-5.mp3": "e651c65df918ab082d7051cd9b743972", + "subscription_test/[2020] Mock Entry 20-5/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/[2020] Mock Entry 20-6/01 - Mock Entry 20-6.mp3": "c045e7ca79847848b4ccd905ae65c2f9", + "subscription_test/[2020] Mock Entry 20-6/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/[2020] Mock Entry 20-7/01 - Mock Entry 20-7.mp3": "974fe1dc4a18a67f4b0e8c7c123397e3", + "subscription_test/[2020] Mock Entry 20-7/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/[2021] Download First/01 - Mock Entry 21-1.mp3": "3459b2735afa7e41a32c34198e780a5e", + "subscription_test/[2021] Download First/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7" +} \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/unit/music/YouTube Full Albums.json b/tests/resources/expected_downloads_summaries/unit/music/YouTube Full Albums.json new file mode 100644 index 00000000..d01861de --- /dev/null +++ b/tests/resources/expected_downloads_summaries/unit/music/YouTube Full Albums.json @@ -0,0 +1,11 @@ +{ + ".ytdl-sub-subscription_test-download-archive.json": "9f6f4458d42da4561db236473896fe71", + "subscription_test/[2020] Mock Entry 20-1/01 - Mock Entry 20-1.mp3": "97320d70b1ccf04d4900b95b3c3645bc", + "subscription_test/[2020] Mock Entry 20-1/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/[2020] Mock Entry 20-2/01 - Mock Entry 20-2.mp3": "b3ceb9fc194b524c77287e248d5860aa", + "subscription_test/[2020] Mock Entry 20-2/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/[2020] Mock Entry 20-3/01 - Mock Entry 20-3.mp3": "55202bc60302d8475a3eaebc0902a253", + "subscription_test/[2020] Mock Entry 20-3/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/[2021] Mock Entry 21-1/01 - Mock Entry 21-1.mp3": "2ad0d8ee1e28a2ecc726197cda67248d", + "subscription_test/[2021] Mock Entry 21-1/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7" +} \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/unit/music/YouTube Releases.json b/tests/resources/expected_downloads_summaries/unit/music/YouTube Releases.json new file mode 100644 index 00000000..d051d7d5 --- /dev/null +++ b/tests/resources/expected_downloads_summaries/unit/music/YouTube Releases.json @@ -0,0 +1,9 @@ +{ + ".ytdl-sub-subscription_test-download-archive.json": "36b3c7143ac4257489791309d802af82", + "subscription_test/[2020] Download First/02 - Mock Entry 20-1.mp3": "7b0ff394bc1fbb8419735914692cb2e4", + "subscription_test/[2020] Download First/03 - Mock Entry 20-2.mp3": "e3b5de70c625eb55d0eb7cacf0429fa5", + "subscription_test/[2020] Download First/04 - Mock Entry 20-3.mp3": "31fd8d0d38139aafb74ec94ba34a53dc", + "subscription_test/[2020] Download First/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/[2021] Download First/01 - Mock Entry 21-1.mp3": "3459b2735afa7e41a32c34198e780a5e", + "subscription_test/[2021] Download First/folder.jpg": "e80c508c4818454300133fe1dc1a9cd7" +} \ No newline at end of file diff --git a/tests/resources/file_fixtures/sample_audio.mp3 b/tests/resources/file_fixtures/sample_audio.mp3 new file mode 100644 index 00000000..ab940459 Binary files /dev/null and b/tests/resources/file_fixtures/sample_audio.mp3 differ diff --git a/tests/resources/transaction_log_summaries/bandcamp/test_artist_url.txt b/tests/resources/transaction_log_summaries/bandcamp/test_artist_url.txt index e85cfcae..54b6fae0 100644 --- a/tests/resources/transaction_log_summaries/bandcamp/test_artist_url.txt +++ b/tests/resources/transaction_log_summaries/bandcamp/test_artist_url.txt @@ -1,186 +1,188 @@ Files created: ---------------------------------------- {output_directory} - .ytdl-sub-jb-download-archive.json -{output_directory}/El Jazzy Chavo/[2022] S950 Funk - 01 - Spark it.mp3 + .ytdl-sub-Sithu Aye-download-archive.json +{output_directory}/Sithu Aye/[2021] 10 Years: Remixes and Reimaginings + 01 - Double Helix Reimagined.mp3 Music Tags: - album: S950 Funk - albumartist: El Jazzy Chavo - albumartists: El Jazzy Chavo - artist: El Jazzy Chavo - artists: El Jazzy Chavo - genre: Unset - title: Spark it + album: 10 Years: Remixes and Reimaginings + albumartist: Sithu Aye + albumartists: Sithu Aye + artist: Sithu Aye + artists: Sithu Aye + genre: Progressive Metal + title: Double Helix Reimagined track: 1 - tracktotal: 15 - year: 2022 - 02 - Astronomikal Funk.mp3 + tracktotal: 10 + year: 2021 + 02 - Skye Reimagined.mp3 Music Tags: - album: S950 Funk - albumartist: El Jazzy Chavo - albumartists: El Jazzy Chavo - artist: El Jazzy Chavo - artists: El Jazzy Chavo - genre: Unset - title: Astronomikal Funk + album: 10 Years: Remixes and Reimaginings + albumartist: Sithu Aye + albumartists: Sithu Aye + artist: Sithu Aye + artists: Sithu Aye + genre: Progressive Metal + title: Skye Reimagined track: 2 - tracktotal: 15 - year: 2022 - 03 - Impulse.mp3 + tracktotal: 10 + year: 2021 + 03 - Baryofusion.mp3 Music Tags: - album: S950 Funk - albumartist: El Jazzy Chavo - albumartists: El Jazzy Chavo - artist: El Jazzy Chavo - artists: El Jazzy Chavo - genre: Unset - title: Impulse + album: 10 Years: Remixes and Reimaginings + albumartist: Sithu Aye + albumartists: Sithu Aye + artist: Sithu Aye + artists: Sithu Aye + genre: Progressive Metal + title: Baryofusion track: 3 - tracktotal: 15 - year: 2022 - 04 - September.mp3 + tracktotal: 10 + year: 2021 + 04 - Mandalay Reimagined.mp3 Music Tags: - album: S950 Funk - albumartist: El Jazzy Chavo - albumartists: El Jazzy Chavo - artist: El Jazzy Chavo - artists: El Jazzy Chavo - genre: Unset - title: September + album: 10 Years: Remixes and Reimaginings + albumartist: Sithu Aye + albumartists: Sithu Aye + artist: Sithu Aye + artists: Sithu Aye + genre: Progressive Metal + title: Mandalay Reimagined track: 4 - tracktotal: 15 - year: 2022 - 05 - Interlune.mp3 + tracktotal: 10 + year: 2021 + 05 - Messenger EDM Remix.mp3 Music Tags: - album: S950 Funk - albumartist: El Jazzy Chavo - albumartists: El Jazzy Chavo - artist: El Jazzy Chavo - artists: El Jazzy Chavo - genre: Unset - title: Interlune + album: 10 Years: Remixes and Reimaginings + albumartist: Sithu Aye + albumartists: Sithu Aye + artist: Sithu Aye + artists: Sithu Aye + genre: Progressive Metal + title: Messenger EDM Remix track: 5 - tracktotal: 15 - year: 2022 - 06 - Ninjutsu Techniques.mp3 + tracktotal: 10 + year: 2021 + folder.jpg +{output_directory}/Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster) + 01 - Invent the Universe.mp3 Music Tags: - album: S950 Funk - albumartist: El Jazzy Chavo - albumartists: El Jazzy Chavo - artist: El Jazzy Chavo - artists: El Jazzy Chavo - genre: Unset - title: Ninjutsu Techniques + album: Re:Invent the Universe (10th Anniversary Remaster) + albumartist: Sithu Aye + albumartists: Sithu Aye + artist: Sithu Aye + artists: Sithu Aye + genre: Progressive Metal + title: Invent the Universe + track: 1 + tracktotal: 10 + year: 2022 + 02 - Grand Unification (feat. David Maxim Micic).mp3 + Music Tags: + album: Re:Invent the Universe (10th Anniversary Remaster) + albumartist: Sithu Aye + albumartists: Sithu Aye + artist: Sithu Aye + artists: Sithu Aye + genre: Progressive Metal + title: Grand Unification (feat. David Maxim Micic) + track: 2 + tracktotal: 10 + year: 2022 + 03 - Expansion.mp3 + Music Tags: + album: Re:Invent the Universe (10th Anniversary Remaster) + albumartist: Sithu Aye + albumartists: Sithu Aye + artist: Sithu Aye + artists: Sithu Aye + genre: Progressive Metal + title: Expansion + track: 3 + tracktotal: 10 + year: 2022 + 04 - Baryogenesis.mp3 + Music Tags: + album: Re:Invent the Universe (10th Anniversary Remaster) + albumartist: Sithu Aye + albumartists: Sithu Aye + artist: Sithu Aye + artists: Sithu Aye + genre: Progressive Metal + title: Baryogenesis + track: 4 + tracktotal: 10 + year: 2022 + 05 - Particles Collide (feat. Plini).mp3 + Music Tags: + album: Re:Invent the Universe (10th Anniversary Remaster) + albumartist: Sithu Aye + albumartists: Sithu Aye + artist: Sithu Aye + artists: Sithu Aye + genre: Progressive Metal + title: Particles Collide (feat. Plini) + track: 5 + tracktotal: 10 + year: 2022 + 06 - Nucleosynthesis.mp3 + Music Tags: + album: Re:Invent the Universe (10th Anniversary Remaster) + albumartist: Sithu Aye + albumartists: Sithu Aye + artist: Sithu Aye + artists: Sithu Aye + genre: Progressive Metal + title: Nucleosynthesis track: 6 - tracktotal: 15 + tracktotal: 10 year: 2022 - 07 - Space Funk Flow.mp3 + 07 - Recombination.mp3 Music Tags: - album: S950 Funk - albumartist: El Jazzy Chavo - albumartists: El Jazzy Chavo - artist: El Jazzy Chavo - artists: El Jazzy Chavo - genre: Unset - title: Space Funk Flow + album: Re:Invent the Universe (10th Anniversary Remaster) + albumartist: Sithu Aye + albumartists: Sithu Aye + artist: Sithu Aye + artists: Sithu Aye + genre: Progressive Metal + title: Recombination track: 7 - tracktotal: 15 + tracktotal: 10 year: 2022 - 08 - Cellar Groove.mp3 + 08 - Dark Ages.mp3 Music Tags: - album: S950 Funk - albumartist: El Jazzy Chavo - albumartists: El Jazzy Chavo - artist: El Jazzy Chavo - artists: El Jazzy Chavo - genre: Unset - title: Cellar Groove + album: Re:Invent the Universe (10th Anniversary Remaster) + albumartist: Sithu Aye + albumartists: Sithu Aye + artist: Sithu Aye + artists: Sithu Aye + genre: Progressive Metal + title: Dark Ages track: 8 - tracktotal: 15 + tracktotal: 10 year: 2022 - 09 - Solar Wind.mp3 + 09 - Formation.mp3 Music Tags: - album: S950 Funk - albumartist: El Jazzy Chavo - albumartists: El Jazzy Chavo - artist: El Jazzy Chavo - artists: El Jazzy Chavo - genre: Unset - title: Solar Wind + album: Re:Invent the Universe (10th Anniversary Remaster) + albumartist: Sithu Aye + albumartists: Sithu Aye + artist: Sithu Aye + artists: Sithu Aye + genre: Progressive Metal + title: Formation track: 9 - tracktotal: 15 + tracktotal: 10 year: 2022 - 10 - Interlune II.mp3 + 10 - Pale Blue Dot.mp3 Music Tags: - album: S950 Funk - albumartist: El Jazzy Chavo - albumartists: El Jazzy Chavo - artist: El Jazzy Chavo - artists: El Jazzy Chavo - genre: Unset - title: Interlune II + album: Re:Invent the Universe (10th Anniversary Remaster) + albumartist: Sithu Aye + albumartists: Sithu Aye + artist: Sithu Aye + artists: Sithu Aye + genre: Progressive Metal + title: Pale Blue Dot track: 10 - tracktotal: 15 - year: 2022 - 11 - Ghetto Anthem.mp3 - Music Tags: - album: S950 Funk - albumartist: El Jazzy Chavo - albumartists: El Jazzy Chavo - artist: El Jazzy Chavo - artists: El Jazzy Chavo - genre: Unset - title: Ghetto Anthem - track: 11 - tracktotal: 15 - year: 2022 - 12 - Street Degree.mp3 - Music Tags: - album: S950 Funk - albumartist: El Jazzy Chavo - albumartists: El Jazzy Chavo - artist: El Jazzy Chavo - artists: El Jazzy Chavo - genre: Unset - title: Street Degree - track: 12 - tracktotal: 15 - year: 2022 - 13 - Trouble World.mp3 - Music Tags: - album: S950 Funk - albumartist: El Jazzy Chavo - albumartists: El Jazzy Chavo - artist: El Jazzy Chavo - artists: El Jazzy Chavo - genre: Unset - title: Trouble World - track: 13 - tracktotal: 15 - year: 2022 - 14 - Relaxation.mp3 - Music Tags: - album: S950 Funk - albumartist: El Jazzy Chavo - albumartists: El Jazzy Chavo - artist: El Jazzy Chavo - artists: El Jazzy Chavo - genre: Unset - title: Relaxation - track: 14 - tracktotal: 15 - year: 2022 - 15 - Journey From Within.mp3 - Music Tags: - album: S950 Funk - albumartist: El Jazzy Chavo - albumartists: El Jazzy Chavo - artist: El Jazzy Chavo - artists: El Jazzy Chavo - genre: Unset - title: Journey From Within - track: 15 - tracktotal: 15 + tracktotal: 10 year: 2022 folder.jpg \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/plugins/split_by_chapters_video-dry-run.txt b/tests/resources/transaction_log_summaries/plugins/split_by_chapters_video-dry-run.txt index 4ab6d393..dfa9b46e 100644 --- a/tests/resources/transaction_log_summaries/plugins/split_by_chapters_video-dry-run.txt +++ b/tests/resources/transaction_log_summaries/plugins/split_by_chapters_video-dry-run.txt @@ -1,7 +1,7 @@ Files created: ---------------------------------------- {output_directory} - .ytdl-sub-split_by_chapters_video-download-archive.json + .ytdl-sub-Proved Records-download-archive.json {output_directory}/Proved Records/[2017] Alfa Mist - Nocturne [Full Album] 01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3 From Chapter Split: diff --git a/tests/resources/transaction_log_summaries/plugins/split_by_chapters_video.txt b/tests/resources/transaction_log_summaries/plugins/split_by_chapters_video.txt index 8ee4b650..bdb80de9 100644 --- a/tests/resources/transaction_log_summaries/plugins/split_by_chapters_video.txt +++ b/tests/resources/transaction_log_summaries/plugins/split_by_chapters_video.txt @@ -1,7 +1,7 @@ Files created: ---------------------------------------- {output_directory} - .ytdl-sub-split_by_chapters_video-download-archive.json + .ytdl-sub-Proved Records-download-archive.json {output_directory}/Proved Records/[2017] Alfa Mist - Nocturne [Full Album] 01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3 From Chapter Split: diff --git a/tests/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt b/tests/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt index bcab86ee..8d620263 100644 --- a/tests/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt +++ b/tests/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt @@ -1,7 +1,7 @@ Files created: ---------------------------------------- {output_directory} - .ytdl-sub-split_by_chapters_with_regex_video-download-archive.json + .ytdl-sub-split_by_chapters_with_regex_video_no_chapters-download-archive.json {output_directory}/Project Zombie/[2010] Oblivion Mod "Falcor" p.1 01 - Oblivion Mod "Falcor" p.1.mp3 Music Tags: diff --git a/tests/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video-dry-run.txt b/tests/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video-dry-run.txt index 530c205e..98cf227c 100644 --- a/tests/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video-dry-run.txt +++ b/tests/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video-dry-run.txt @@ -1,7 +1,7 @@ Files created: ---------------------------------------- {output_directory} - .ytdl-sub-split_by_chapters_with_regex_video-download-archive.json + .ytdl-sub-split_by_chapters_with_regex_video_preset-download-archive.json {output_directory}/Alfa Mist/[2017] Nocturne 01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3 From Chapter Split: diff --git a/tests/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video.txt b/tests/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video.txt index 1df12e08..59cd59ac 100644 --- a/tests/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video.txt +++ b/tests/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video.txt @@ -1,7 +1,7 @@ Files created: ---------------------------------------- {output_directory} - .ytdl-sub-split_by_chapters_with_regex_video-download-archive.json + .ytdl-sub-split_by_chapters_with_regex_video_preset-download-archive.json {output_directory}/Alfa Mist/[2017] Nocturne 01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3 From Chapter Split: diff --git a/tests/resources/transaction_log_summaries/soundcloud/test_soundcloud_discography.txt b/tests/resources/transaction_log_summaries/soundcloud/test_soundcloud_discography.txt index 86015ee3..246601a9 100644 --- a/tests/resources/transaction_log_summaries/soundcloud/test_soundcloud_discography.txt +++ b/tests/resources/transaction_log_summaries/soundcloud/test_soundcloud_discography.txt @@ -1,7 +1,7 @@ Files created: ---------------------------------------- {output_directory} - .ytdl-sub-jb-download-archive.json + .ytdl-sub-j_b-download-archive.json {output_directory}/j_b/[2021] Baby Santana's Dorian Groove 01 - Baby Santana's Dorian Groove.mp3 Music Tags: @@ -10,7 +10,7 @@ Files created: albumartists: j_b artist: j_b artists: j_b - genre: Unset + genre: Acoustic title: Baby Santana's Dorian Groove track: 1 tracktotal: 1 @@ -24,7 +24,7 @@ Files created: albumartists: j_b artist: j_b artists: j_b - genre: Unset + genre: Acoustic title: Purple Clouds track: 1 tracktotal: 1 @@ -38,7 +38,7 @@ Files created: albumartists: j_b artist: j_b artists: j_b - genre: Unset + genre: Acoustic title: 20160426 184214 track: 1 tracktotal: 11 @@ -50,7 +50,7 @@ Files created: albumartists: j_b artist: j_b artists: j_b - genre: Unset + genre: Acoustic title: 20160502 123150 track: 2 tracktotal: 11 @@ -62,7 +62,7 @@ Files created: albumartists: j_b artist: j_b artists: j_b - genre: Unset + genre: Acoustic title: 20160504 143832 track: 3 tracktotal: 11 @@ -74,7 +74,7 @@ Files created: albumartists: j_b artist: j_b artists: j_b - genre: Unset + genre: Acoustic title: 20160601 221234 track: 4 tracktotal: 11 @@ -86,7 +86,7 @@ Files created: albumartists: j_b artist: j_b artists: j_b - genre: Unset + genre: Acoustic title: 20160601 222440 track: 5 tracktotal: 11 @@ -98,7 +98,7 @@ Files created: albumartists: j_b artist: j_b artists: j_b - genre: Unset + genre: Acoustic title: 20170604 190236 track: 6 tracktotal: 11 @@ -110,7 +110,7 @@ Files created: albumartists: j_b artist: j_b artists: j_b - genre: Unset + genre: Acoustic title: 20170612 193646 track: 7 tracktotal: 11 @@ -122,7 +122,7 @@ Files created: albumartists: j_b artist: j_b artists: j_b - genre: Unset + genre: Acoustic title: 20170628 215206 track: 8 tracktotal: 11 @@ -134,7 +134,7 @@ Files created: albumartists: j_b artist: j_b artists: j_b - genre: Unset + genre: Acoustic title: Finding Home track: 9 tracktotal: 11 @@ -146,7 +146,7 @@ Files created: albumartists: j_b artist: j_b artists: j_b - genre: Unset + genre: Acoustic title: Shallow Water WIP track: 10 tracktotal: 11 @@ -158,7 +158,7 @@ Files created: albumartists: j_b artist: j_b artists: j_b - genre: Unset + genre: Acoustic title: Untold History track: 11 tracktotal: 11 diff --git a/tests/resources/transaction_log_summaries/unit/music/Bandcamp.txt b/tests/resources/transaction_log_summaries/unit/music/Bandcamp.txt new file mode 100644 index 00000000..5ae093e3 --- /dev/null +++ b/tests/resources/transaction_log_summaries/unit/music/Bandcamp.txt @@ -0,0 +1,56 @@ +Files created: +---------------------------------------- +{output_directory} + .ytdl-sub-subscription_test-download-archive.json +{output_directory}/subscription_test/[2020] Download First + 02 - Mock Entry 20-1.mp3 + Music Tags: + album: Download First + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-1 + track: 2 + tracktotal: 4 + year: 2020 + 03 - Mock Entry 20-2.mp3 + Music Tags: + album: Download First + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-2 + track: 3 + tracktotal: 4 + year: 2020 + 04 - Mock Entry 20-3.mp3 + Music Tags: + album: Download First + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-3 + track: 4 + tracktotal: 4 + year: 2020 + folder.jpg +{output_directory}/subscription_test/[2021] Download First + 01 - Mock Entry 21-1.mp3 + Music Tags: + album: Download First + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 21-1 + track: 1 + tracktotal: 4 + year: 2021 + folder.jpg \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/unit/music/Single.txt b/tests/resources/transaction_log_summaries/unit/music/Single.txt new file mode 100644 index 00000000..2bf50619 --- /dev/null +++ b/tests/resources/transaction_log_summaries/unit/music/Single.txt @@ -0,0 +1,60 @@ +Files created: +---------------------------------------- +{output_directory} + .ytdl-sub-subscription_test-download-archive.json +{output_directory}/subscription_test/[2020] Mock Entry 20-1 + 01 - Mock Entry 20-1.mp3 + Music Tags: + album: Mock Entry 20-1 + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-1 + track: 1 + tracktotal: 1 + year: 2020 + folder.jpg +{output_directory}/subscription_test/[2020] Mock Entry 20-2 + 01 - Mock Entry 20-2.mp3 + Music Tags: + album: Mock Entry 20-2 + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-2 + track: 1 + tracktotal: 1 + year: 2020 + folder.jpg +{output_directory}/subscription_test/[2020] Mock Entry 20-3 + 01 - Mock Entry 20-3.mp3 + Music Tags: + album: Mock Entry 20-3 + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-3 + track: 1 + tracktotal: 1 + year: 2020 + folder.jpg +{output_directory}/subscription_test/[2021] Mock Entry 21-1 + 01 - Mock Entry 21-1.mp3 + Music Tags: + album: Mock Entry 21-1 + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 21-1 + track: 1 + tracktotal: 1 + year: 2021 + folder.jpg \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/unit/music/SoundCloud Discography.txt b/tests/resources/transaction_log_summaries/unit/music/SoundCloud Discography.txt new file mode 100644 index 00000000..fdee3723 --- /dev/null +++ b/tests/resources/transaction_log_summaries/unit/music/SoundCloud Discography.txt @@ -0,0 +1,112 @@ +Files created: +---------------------------------------- +{output_directory} + .ytdl-sub-subscription_test-download-archive.json +{output_directory}/subscription_test/[2020] Download First + 02 - Mock Entry 20-1.mp3 + Music Tags: + album: Download First + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-1 + track: 2 + tracktotal: 4 + year: 2020 + 03 - Mock Entry 20-2.mp3 + Music Tags: + album: Download First + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-2 + track: 3 + tracktotal: 4 + year: 2020 + 04 - Mock Entry 20-3.mp3 + Music Tags: + album: Download First + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-3 + track: 4 + tracktotal: 4 + year: 2020 + folder.jpg +{output_directory}/subscription_test/[2020] Mock Entry 20-4 + 01 - Mock Entry 20-4.mp3 + Music Tags: + album: Mock Entry 20-4 + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-4 + track: 1 + tracktotal: 1 + year: 2020 + folder.jpg +{output_directory}/subscription_test/[2020] Mock Entry 20-5 + 01 - Mock Entry 20-5.mp3 + Music Tags: + album: Mock Entry 20-5 + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-5 + track: 1 + tracktotal: 1 + year: 2020 + folder.jpg +{output_directory}/subscription_test/[2020] Mock Entry 20-6 + 01 - Mock Entry 20-6.mp3 + Music Tags: + album: Mock Entry 20-6 + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-6 + track: 1 + tracktotal: 1 + year: 2020 + folder.jpg +{output_directory}/subscription_test/[2020] Mock Entry 20-7 + 01 - Mock Entry 20-7.mp3 + Music Tags: + album: Mock Entry 20-7 + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-7 + track: 1 + tracktotal: 1 + year: 2020 + folder.jpg +{output_directory}/subscription_test/[2021] Download First + 01 - Mock Entry 21-1.mp3 + Music Tags: + album: Download First + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 21-1 + track: 1 + tracktotal: 4 + year: 2021 + folder.jpg \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/unit/music/YouTube Full Albums.txt b/tests/resources/transaction_log_summaries/unit/music/YouTube Full Albums.txt new file mode 100644 index 00000000..2bf50619 --- /dev/null +++ b/tests/resources/transaction_log_summaries/unit/music/YouTube Full Albums.txt @@ -0,0 +1,60 @@ +Files created: +---------------------------------------- +{output_directory} + .ytdl-sub-subscription_test-download-archive.json +{output_directory}/subscription_test/[2020] Mock Entry 20-1 + 01 - Mock Entry 20-1.mp3 + Music Tags: + album: Mock Entry 20-1 + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-1 + track: 1 + tracktotal: 1 + year: 2020 + folder.jpg +{output_directory}/subscription_test/[2020] Mock Entry 20-2 + 01 - Mock Entry 20-2.mp3 + Music Tags: + album: Mock Entry 20-2 + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-2 + track: 1 + tracktotal: 1 + year: 2020 + folder.jpg +{output_directory}/subscription_test/[2020] Mock Entry 20-3 + 01 - Mock Entry 20-3.mp3 + Music Tags: + album: Mock Entry 20-3 + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-3 + track: 1 + tracktotal: 1 + year: 2020 + folder.jpg +{output_directory}/subscription_test/[2021] Mock Entry 21-1 + 01 - Mock Entry 21-1.mp3 + Music Tags: + album: Mock Entry 21-1 + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 21-1 + track: 1 + tracktotal: 1 + year: 2021 + folder.jpg \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/unit/music/YouTube Releases.txt b/tests/resources/transaction_log_summaries/unit/music/YouTube Releases.txt new file mode 100644 index 00000000..5ae093e3 --- /dev/null +++ b/tests/resources/transaction_log_summaries/unit/music/YouTube Releases.txt @@ -0,0 +1,56 @@ +Files created: +---------------------------------------- +{output_directory} + .ytdl-sub-subscription_test-download-archive.json +{output_directory}/subscription_test/[2020] Download First + 02 - Mock Entry 20-1.mp3 + Music Tags: + album: Download First + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-1 + track: 2 + tracktotal: 4 + year: 2020 + 03 - Mock Entry 20-2.mp3 + Music Tags: + album: Download First + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-2 + track: 3 + tracktotal: 4 + year: 2020 + 04 - Mock Entry 20-3.mp3 + Music Tags: + album: Download First + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 20-3 + track: 4 + tracktotal: 4 + year: 2020 + folder.jpg +{output_directory}/subscription_test/[2021] Download First + 01 - Mock Entry 21-1.mp3 + Music Tags: + album: Download First + albumartist: subscription_test + albumartists: subscription_test + artist: subscription_test + artists: subscription_test + genre: Unset + title: Mock Entry 21-1 + track: 1 + tracktotal: 4 + year: 2021 + folder.jpg \ No newline at end of file diff --git a/tests/unit/config/test_subscription.py b/tests/unit/config/test_subscription.py index 3b99b7bf..849c7823 100644 --- a/tests/unit/config/test_subscription.py +++ b/tests/unit/config/test_subscription.py @@ -341,7 +341,7 @@ def test_tv_show_subscriptions( config=channel_as_tv_show_config, subscription_path=tv_show_subscriptions_path ) - assert len(subs) == 6 + assert len(subs) == 5 assert subs[2].name == "Jake Trains" jake_train_overrides = subs[2].overrides.dict_with_format_strings @@ -349,3 +349,17 @@ def test_tv_show_subscriptions( assert jake_train_overrides["subscription_value"] == "https://www.youtube.com/@JakeTrains" assert jake_train_overrides["subscription_indent_1"] == "Kids" assert jake_train_overrides["subscription_indent_2"] == "TV-Y" + + +def test_music_subscriptions(music_audio_config: ConfigFile, music_subscriptions_path: Path): + subs = Subscription.from_file_path( + config=music_audio_config, subscription_path=music_subscriptions_path + ) + + assert len(subs) == 14 + assert subs[2].name == "Stan Getz" + monk = subs[2].overrides.dict_with_format_strings + + assert monk["subscription_name"] == "Stan Getz" + assert monk["subscription_value"] == "https://www.youtube.com/@stangetzofficial/releases" + assert monk["subscription_indent_1"] == "Jazz" diff --git a/tests/unit/prebuilt_presets/conftest.py b/tests/unit/prebuilt_presets/conftest.py index eb17d21a..f25845a7 100644 --- a/tests/unit/prebuilt_presets/conftest.py +++ b/tests/unit/prebuilt_presets/conftest.py @@ -19,6 +19,7 @@ from ytdl_sub.entries.variables.kwargs import EXTRACTOR from ytdl_sub.entries.variables.kwargs import PLAYLIST_COUNT from ytdl_sub.entries.variables.kwargs import PLAYLIST_ENTRY from ytdl_sub.entries.variables.kwargs import PLAYLIST_INDEX +from ytdl_sub.entries.variables.kwargs import PLAYLIST_TITLE from ytdl_sub.entries.variables.kwargs import TITLE from ytdl_sub.entries.variables.kwargs import UID from ytdl_sub.entries.variables.kwargs import UPLOAD_DATE @@ -53,14 +54,17 @@ def mock_entry_dict_factory(mock_downloaded_file_path) -> Callable: def _mock_entry_dict_factory( uid: int, upload_date: str, + playlist_title: str = "playlist title", playlist_index: int = 1, playlist_count: int = 1, is_youtube_channel: bool = False, mock_download_to_working_dir: bool = True, + is_extracted_audio: bool = False, ) -> Dict: entry_dict = { UID: uid, EPOCH: 1596878400, + PLAYLIST_TITLE: playlist_title, PLAYLIST_INDEX: playlist_index, PLAYLIST_COUNT: playlist_count, EXTRACTOR: "mock-entry-dict", @@ -86,10 +90,16 @@ def mock_entry_dict_factory(mock_downloaded_file_path) -> Callable: # Create mock video file if mock_download_to_working_dir: - copy_file_fixture( - fixture_name="sample_vid.mp4", - output_file_path=mock_downloaded_file_path(f"{uid}.mp4"), - ) + if is_extracted_audio: + copy_file_fixture( + fixture_name="sample_audio.mp3", + output_file_path=mock_downloaded_file_path(f"{uid}.mp3"), + ) + else: + copy_file_fixture( + fixture_name="sample_vid.mp4", + output_file_path=mock_downloaded_file_path(f"{uid}.mp4"), + ) copy_file_fixture( fixture_name="thumb.jpg", output_file_path=mock_downloaded_file_path(f"{uid}.jpg") ) @@ -106,10 +116,14 @@ def mock_download_collection_thumbnail(mock_downloaded_file_path): _ = thumbnail_url output_name = os.path.basename(output_thumbnail_path) if "poster" in output_name or "show" in output_name: - copy_file_fixture(fixture_name="poster.jpg", output_file_path=output_thumbnail_path) + copy_file_fixture( + fixture_name="poster.jpg", output_file_path=Path(output_thumbnail_path) + ) return True elif "fanart" in output_name: - copy_file_fixture(fixture_name="fanart.jpeg", output_file_path=output_thumbnail_path) + copy_file_fixture( + fixture_name="fanart.jpeg", output_file_path=Path(output_thumbnail_path) + ) return True return False @@ -125,37 +139,50 @@ def mock_download_collection_entries( mock_download_collection_thumbnail, mock_entry_dict_factory: Callable, working_directory: str ): @contextlib.contextmanager - def _mock_download_collection_entries_factory(is_youtube_channel: bool, num_urls: int = 1): + def _mock_download_collection_entries_factory( + is_youtube_channel: bool, num_urls: int = 1, is_extracted_audio: bool = False + ): def _write_entries_to_working_dir(*args, **kwargs) -> List[Dict]: - if num_urls == 1 or ("2" in kwargs["url"] and num_urls > 1): + # Second TV URL or second soundcloud URL, which downloads first + is_second_url = "2" in kwargs["url"] or kwargs["url"].endswith("/albums") + + if num_urls == 1 or (is_second_url and num_urls > 1): return [ mock_entry_dict_factory( uid="21-1", upload_date="20210808", + playlist_title="Download First", playlist_index=1, playlist_count=4, is_youtube_channel=is_youtube_channel, + is_extracted_audio=is_extracted_audio, ), # 1 mock_entry_dict_factory( uid="20-1", upload_date="20200808", + playlist_title="Download First", playlist_index=2, playlist_count=4, is_youtube_channel=is_youtube_channel, + is_extracted_audio=is_extracted_audio, ), # 2 98 mock_entry_dict_factory( uid="20-2", upload_date="20200808", + playlist_title="Download First", playlist_index=3, playlist_count=4, is_youtube_channel=is_youtube_channel, + is_extracted_audio=is_extracted_audio, ), # 1 99 mock_entry_dict_factory( uid="20-3", upload_date="20200807", + playlist_title="Download First", playlist_index=4, playlist_count=4, is_youtube_channel=is_youtube_channel, + is_extracted_audio=is_extracted_audio, ), ] return [ @@ -163,38 +190,48 @@ def mock_download_collection_entries( mock_entry_dict_factory( uid="20-3", upload_date="20200807", + playlist_title="Download Second", playlist_index=1, playlist_count=5, is_youtube_channel=is_youtube_channel, mock_download_to_working_dir=False, + is_extracted_audio=is_extracted_audio, ), mock_entry_dict_factory( uid="20-4", upload_date="20200806", + playlist_title="Download Second", playlist_index=2, playlist_count=5, is_youtube_channel=is_youtube_channel, + is_extracted_audio=is_extracted_audio, ), mock_entry_dict_factory( uid="20-5", upload_date="20200706", + playlist_title="Download Second", playlist_index=3, playlist_count=5, is_youtube_channel=is_youtube_channel, + is_extracted_audio=is_extracted_audio, ), mock_entry_dict_factory( uid="20-6", upload_date="20200706", + playlist_title="Download Second", playlist_index=4, playlist_count=5, is_youtube_channel=is_youtube_channel, + is_extracted_audio=is_extracted_audio, ), mock_entry_dict_factory( uid="20-7", upload_date="20200606", + playlist_title="Download Second", playlist_index=5, playlist_count=5, is_youtube_channel=is_youtube_channel, + is_extracted_audio=is_extracted_audio, ), ] diff --git a/tests/unit/prebuilt_presets/test_prebuilt_presets.py b/tests/unit/prebuilt_presets/test_prebuilt_presets.py index d663f05a..c75692dd 100644 --- a/tests/unit/prebuilt_presets/test_prebuilt_presets.py +++ b/tests/unit/prebuilt_presets/test_prebuilt_presets.py @@ -6,18 +6,19 @@ import pytest from expected_download import assert_expected_downloads from expected_transaction_log import assert_transaction_log_matches -from ytdl_sub.prebuilt_presets import TvShowByDatePresets -from ytdl_sub.prebuilt_presets import TvShowCollectionPresets +from ytdl_sub.prebuilt_presets.music import MusicPresets from ytdl_sub.prebuilt_presets.tv_show import TvShowByDateEpisodeFormattingPresets +from ytdl_sub.prebuilt_presets.tv_show import TvShowByDatePresets from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionEpisodeFormattingPresets +from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionPresets from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionSeasonPresets from ytdl_sub.subscriptions.subscription import Subscription from ytdl_sub.utils.exceptions import ValidationException -@pytest.mark.parametrize("media_player_preset", TvShowByDatePresets.get_preset_names()) +@pytest.mark.parametrize("media_player_preset", TvShowByDatePresets.preset_names) @pytest.mark.parametrize( - "tv_show_structure_preset", TvShowByDateEpisodeFormattingPresets.get_preset_names() + "tv_show_structure_preset", TvShowByDateEpisodeFormattingPresets.preset_names ) class TestPrebuiltTVShowPresets: def test_compilation( @@ -179,12 +180,12 @@ class TestPrebuiltTVShowPresets: ) -@pytest.mark.parametrize("media_player_preset", TvShowCollectionPresets.get_preset_names()) +@pytest.mark.parametrize("media_player_preset", TvShowCollectionPresets.preset_names) @pytest.mark.parametrize( - "tv_show_structure_preset", TvShowCollectionEpisodeFormattingPresets.get_preset_names() + "tv_show_structure_preset", TvShowCollectionEpisodeFormattingPresets.preset_names ) class TestPrebuiltTvShowCollectionPresets: - @pytest.mark.parametrize("season_preset", TvShowCollectionSeasonPresets.get_preset_names()) + @pytest.mark.parametrize("season_preset", TvShowCollectionSeasonPresets.preset_names) def test_compilation( self, config, @@ -208,7 +209,7 @@ class TestPrebuiltTvShowCollectionPresets: }, ) - @pytest.mark.parametrize("season_preset", TvShowCollectionSeasonPresets.get_preset_names()) + @pytest.mark.parametrize("season_preset", TvShowCollectionSeasonPresets.preset_names) def test_compilation_errors_missing_one( self, config, @@ -342,3 +343,70 @@ class TestPrebuiltTvShowCollectionPresets: dry_run=False, expected_download_summary_file_name=f"{reformatted_expected_summary_name}_migrated.json", ) + + +@pytest.mark.parametrize("music_preset", MusicPresets.preset_names) +class TestPrebuiltMusicPresets: + def test_compilation( + self, + config, + music_preset: str, + ): + _ = Subscription.from_dict( + config=config, + preset_name="preset_test", + preset_dict={ + "preset": [ + music_preset, + ], + "overrides": { + "subscription_value": "https://your.name.here", + }, + }, + ) + + def test_presets_run( + self, + config, + subscription_name, + output_directory, + mock_download_collection_entries, + music_preset: str, + ): + expected_summary_name = f"unit/music/{music_preset}" + + preset_dict = { + "preset": [ + music_preset, + ], + "overrides": { + "url": "https://your.name.here", + "music_directory": output_directory, + }, + } + + subscription = Subscription.from_dict( + config=config, + preset_name=subscription_name, + preset_dict=preset_dict, + ) + + num_urls = 1 + if music_preset == "SoundCloud Discography": + num_urls = 2 # simulate /albums and /tracks + + with mock_download_collection_entries( + is_youtube_channel=False, num_urls=num_urls, is_extracted_audio=True + ): + transaction_log = subscription.download(dry_run=False) + + assert_transaction_log_matches( + output_directory=output_directory, + transaction_log=transaction_log, + transaction_log_summary_file_name=f"{expected_summary_name}.txt", + ) + assert_expected_downloads( + output_directory=output_directory, + dry_run=False, + expected_download_summary_file_name=f"{expected_summary_name}.json", + )