[FEATURE] Prebuilt music presets (#780)

Adds the following prebuilt presets:
```
"Single"
"SoundCloud Discography"
"YouTube Releases"
"YouTube Full Albums"
"Bandcamp"
```

which require no config.yaml to use. Usage examples can be found in the `/examples` directory
This commit is contained in:
Jesse Bannon 2023-10-24 09:23:05 -07:00 committed by GitHub
parent c149957b04
commit ff857c84af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 1058 additions and 671 deletions

4
.gitignore vendored
View file

@ -145,5 +145,7 @@ docker/testing/volumes
.local/
.ytdl-sub-working-directory
ffmpeg.exe
ffprobe.exe
ffprobe.exe

View file

@ -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}"

View file

@ -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"

View file

@ -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/"

View file

@ -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"

View file

@ -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] = []

View file

@ -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

View file

@ -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]

View file

@ -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",
}

View file

@ -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}"

View file

@ -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",
}

View file

@ -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")

View file

@ -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)

View file

@ -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)

View file

@ -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,
)

View file

@ -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)

View file

@ -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] ReInvent the Universe (10th Anniversary Remaster)/01 - Invent the Universe.mp3": "d723a2e1f2ec75b3d20f1a0de616a191",
"Sithu Aye/[2022] ReInvent the Universe (10th Anniversary Remaster)/02 - Grand Unification (feat. David Maxim Micic).mp3": "0e550ebe93f8b5349eb07c7554ad22d9",
"Sithu Aye/[2022] ReInvent the Universe (10th Anniversary Remaster)/03 - Expansion.mp3": "6324f012f09a2e7028ca923fdff3a89a",
"Sithu Aye/[2022] ReInvent the Universe (10th Anniversary Remaster)/04 - Baryogenesis.mp3": "d30de9d811f56c2179fd86c6bede2fc5",
"Sithu Aye/[2022] ReInvent the Universe (10th Anniversary Remaster)/05 - Particles Collide (feat. Plini).mp3": "f869f1948b376f2ad98381b0c77d447f",
"Sithu Aye/[2022] ReInvent the Universe (10th Anniversary Remaster)/06 - Nucleosynthesis.mp3": "23d6ceb9865d6d6030d8659a2eed5698",
"Sithu Aye/[2022] ReInvent the Universe (10th Anniversary Remaster)/07 - Recombination.mp3": "4ae97dc8457e48fa7aad9a64b927bf1d",
"Sithu Aye/[2022] ReInvent the Universe (10th Anniversary Remaster)/08 - Dark Ages.mp3": "922e8a54e3e543bbf9b866e2f4a53607",
"Sithu Aye/[2022] ReInvent the Universe (10th Anniversary Remaster)/09 - Formation.mp3": "fd7ce4553df5323355bc95e6528e1515",
"Sithu Aye/[2022] ReInvent the Universe (10th Anniversary Remaster)/10 - Pale Blue Dot.mp3": "6328960f01a118d84fa1f1ab3565bf90",
"Sithu Aye/[2022] ReInvent the Universe (10th Anniversary Remaster)/folder.jpg": "d8cffeca026afaa619f641a95143f803"
}

View file

@ -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",

View file

@ -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"
}

View file

@ -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",

View file

@ -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"
}

View file

@ -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"
}

View file

@ -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"
}

View file

@ -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"
}

View file

@ -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"
}

View file

@ -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"
}

Binary file not shown.

View file

@ -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] ReInvent 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

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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"

View file

@ -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,
),
]

View file

@ -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",
)