[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:
parent
c149957b04
commit
ff857c84af
42 changed files with 1058 additions and 671 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -145,5 +145,7 @@ docker/testing/volumes
|
||||||
|
|
||||||
.local/
|
.local/
|
||||||
|
|
||||||
|
.ytdl-sub-working-directory
|
||||||
|
|
||||||
ffmpeg.exe
|
ffmpeg.exe
|
||||||
ffprobe.exe
|
ffprobe.exe
|
||||||
|
|
|
||||||
|
|
@ -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}"
|
|
||||||
|
|
@ -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"
|
|
||||||
|
|
||||||
52
examples/music_subscriptions.yaml
Normal file
52
examples/music_subscriptions.yaml
Normal 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/"
|
||||||
|
|
||||||
|
|
@ -22,15 +22,3 @@ TV Show Full Archive:
|
||||||
TV Show Only Recent:
|
TV Show Only Recent:
|
||||||
= News | TV-14:
|
= News | TV-14:
|
||||||
"BBC": "https://www.youtube.com/@BBCNews"
|
"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"
|
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,7 @@ def main() -> List[Subscription]:
|
||||||
config = ConfigFile.from_file_path(DEFAULT_CONFIG_FILE_NAME)
|
config = ConfigFile.from_file_path(DEFAULT_CONFIG_FILE_NAME)
|
||||||
else:
|
else:
|
||||||
logger.info("No config specified, using defaults.")
|
logger.info("No config specified, using defaults.")
|
||||||
config = ConfigFile(name="default_config", value={})
|
config = ConfigFile.default()
|
||||||
|
|
||||||
subscriptions: List[Subscription] = []
|
subscriptions: List[Subscription] = []
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,15 @@ class ConfigFile(ConfigValidator):
|
||||||
|
|
||||||
return ConfigFile.from_dict(name=config_path, config_dict=config_dict)
|
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]:
|
def as_dict(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Returns
|
Returns
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,6 @@ from typing import Set
|
||||||
|
|
||||||
import mergedeep
|
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
|
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] = {
|
PUBLISHED_PRESET_NAMES: Set[str] = {
|
||||||
name for name in PREBUILT_PRESET_NAMES if not name.startswith("_")
|
name for name in PREBUILT_PRESET_NAMES if not name.startswith("_")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PrebuiltPresets:
|
||||||
|
preset_names: Set[str]
|
||||||
|
|
|
||||||
11
src/ytdl_sub/prebuilt_presets/music/__init__.py
Normal file
11
src/ytdl_sub/prebuilt_presets/music/__init__.py
Normal 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",
|
||||||
|
}
|
||||||
150
src/ytdl_sub/prebuilt_presets/music/music.yaml
Normal file
150
src/ytdl_sub/prebuilt_presets/music/music.yaml
Normal 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}"
|
||||||
|
|
@ -1,26 +1,4 @@
|
||||||
from typing import Set
|
from ytdl_sub.prebuilt_presets import PrebuiltPresets
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class TvShowByDatePresets(PrebuiltPresets):
|
class TvShowByDatePresets(PrebuiltPresets):
|
||||||
|
|
@ -29,38 +7,44 @@ class TvShowByDatePresets(PrebuiltPresets):
|
||||||
numbers.
|
numbers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
kodi_tv_show_by_date = _
|
preset_names = {
|
||||||
jellyfin_tv_show_by_date = _
|
"kodi_tv_show_by_date",
|
||||||
plex_tv_show_by_date = _
|
"jellyfin_tv_show_by_date",
|
||||||
|
"plex_tv_show_by_date",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class TvShowByDateEpisodeFormattingPresets(PrebuiltPresets):
|
class TvShowByDateEpisodeFormattingPresets(PrebuiltPresets):
|
||||||
season_by_year__episode_by_month_day = _
|
preset_names = {
|
||||||
season_by_year__episode_by_month_day_reversed = _
|
"season_by_year__episode_by_month_day",
|
||||||
season_by_year_month__episode_by_day = _
|
"season_by_year__episode_by_month_day_reversed",
|
||||||
season_by_year__episode_by_download_index = _
|
"season_by_year_month__episode_by_day",
|
||||||
|
"season_by_year__episode_by_download_index",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class TvShowCollectionPresets(PrebuiltPresets):
|
class TvShowCollectionPresets(PrebuiltPresets):
|
||||||
"""
|
preset_names = {
|
||||||
Docstring for all TV SHOW URL presets
|
"kodi_tv_show_collection",
|
||||||
"""
|
"jellyfin_tv_show_collection",
|
||||||
|
"plex_tv_show_collection",
|
||||||
kodi_tv_show_collection = _
|
}
|
||||||
jellyfin_tv_show_collection = _
|
|
||||||
plex_tv_show_collection = _
|
|
||||||
|
|
||||||
|
|
||||||
class TvShowCollectionEpisodeFormattingPresets(PrebuiltPresets):
|
class TvShowCollectionEpisodeFormattingPresets(PrebuiltPresets):
|
||||||
season_by_collection__episode_by_year_month_day = _
|
preset_names = {
|
||||||
season_by_collection__episode_by_year_month_day_reversed = _
|
"season_by_collection__episode_by_year_month_day",
|
||||||
season_by_collection__episode_by_playlist_index = _
|
"season_by_collection__episode_by_year_month_day_reversed",
|
||||||
season_by_collection__episode_by_playlist_index_reversed = _
|
"season_by_collection__episode_by_playlist_index",
|
||||||
|
"season_by_collection__episode_by_playlist_index_reversed",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class TvShowCollectionSeasonPresets(PrebuiltPresets):
|
class TvShowCollectionSeasonPresets(PrebuiltPresets):
|
||||||
collection_season_1 = _
|
preset_names = {
|
||||||
collection_season_2 = _
|
"collection_season_1",
|
||||||
collection_season_3 = _
|
"collection_season_2",
|
||||||
collection_season_4 = _
|
"collection_season_3",
|
||||||
collection_season_5 = _
|
"collection_season_4",
|
||||||
|
"collection_season_5",
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -186,6 +186,9 @@ def tv_show_subscriptions_path() -> Path:
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def music_audio_config(working_directory) -> ConfigFile:
|
def music_audio_config(working_directory) -> ConfigFile:
|
||||||
return _load_config(
|
return ConfigFile.from_dict({"configuration": {"working_directory": working_directory}})
|
||||||
config_path=Path("examples/music_audio_config.yaml"), working_directory=working_directory
|
|
||||||
)
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def music_subscriptions_path() -> Path:
|
||||||
|
return Path("examples/music_subscriptions.yaml")
|
||||||
|
|
|
||||||
|
|
@ -10,27 +10,15 @@ from ytdl_sub.subscriptions.subscription import Subscription
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def subscription_dict(output_directory):
|
def subscription_dict(output_directory):
|
||||||
return {
|
return {
|
||||||
"preset": "albums_from_playlists",
|
"preset": "Bandcamp",
|
||||||
"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",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"ytdl_options": {
|
"ytdl_options": {
|
||||||
"max_downloads": 15,
|
"max_downloads": 15,
|
||||||
},
|
},
|
||||||
"date_range": {"before": "20230101"},
|
"audio_extract": {"codec": "mp3", "quality": 320},
|
||||||
|
"date_range": {"after": "20210110"},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"url": "https://funkypselicave.bandcamp.com/",
|
"subscription_value": "https://sithuayemusic.bandcamp.com/",
|
||||||
"track_title": "{captured_track_title}",
|
"subscription_indent_1": "Progressive Metal",
|
||||||
"track_artist": "{captured_track_artist}",
|
|
||||||
"music_directory": output_directory,
|
"music_directory": output_directory,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -38,7 +26,7 @@ def subscription_dict(output_directory):
|
||||||
|
|
||||||
class TestBandcamp:
|
class TestBandcamp:
|
||||||
@pytest.mark.parametrize("dry_run", [True, False])
|
@pytest.mark.parametrize("dry_run", [True, False])
|
||||||
def test_download_artist_url(
|
def test_prebuilt_preset_download(
|
||||||
self,
|
self,
|
||||||
subscription_dict,
|
subscription_dict,
|
||||||
music_audio_config,
|
music_audio_config,
|
||||||
|
|
@ -47,7 +35,7 @@ class TestBandcamp:
|
||||||
):
|
):
|
||||||
discography_subscription = Subscription.from_dict(
|
discography_subscription = Subscription.from_dict(
|
||||||
preset_dict=subscription_dict,
|
preset_dict=subscription_dict,
|
||||||
preset_name="jb",
|
preset_name="Sithu Aye",
|
||||||
config=music_audio_config,
|
config=music_audio_config,
|
||||||
)
|
)
|
||||||
transaction_log = discography_subscription.download(dry_run=dry_run)
|
transaction_log = discography_subscription.download(dry_run=dry_run)
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,18 @@ from ytdl_sub.subscriptions.subscription import Subscription
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def single_song_preset_dict_old_format(output_directory):
|
def single_preset_dict_old_format(output_directory):
|
||||||
return {
|
return {
|
||||||
"preset": "single",
|
"preset": "Single",
|
||||||
# test multi-tags
|
# test multi-tags
|
||||||
"music_tags": {"embed_thumbnail": True, "tags": {"genres": ["multi_tag_1", "multi_tag_2"]}},
|
"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": {
|
"ytdl_options": {
|
||||||
"postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility
|
"postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
"track_artist": "YouTube",
|
||||||
"url": "https://www.youtube.com/watch?v=2lAe1cqCOXo",
|
"url": "https://www.youtube.com/watch?v=2lAe1cqCOXo",
|
||||||
"music_directory": output_directory,
|
"music_directory": output_directory,
|
||||||
},
|
},
|
||||||
|
|
@ -23,18 +25,20 @@ def single_song_preset_dict_old_format(output_directory):
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def single_song_preset_dict(output_directory):
|
def single_preset_dict(output_directory):
|
||||||
return {
|
return {
|
||||||
"preset": "single",
|
"preset": "Single",
|
||||||
# test multi-tags
|
# test multi-tags
|
||||||
"music_tags": {"genres": ["multi_tag_1", "multi_tag_2"]},
|
"music_tags": {"genres": ["multi_tag_1", "multi_tag_2"]},
|
||||||
# test the new embed_thumbnail plugin
|
# test the new embed_thumbnail plugin
|
||||||
"embed_thumbnail": True,
|
"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": {
|
"ytdl_options": {
|
||||||
"postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility
|
"postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
"track_artist": "YouTube",
|
||||||
"url": "https://www.youtube.com/watch?v=2lAe1cqCOXo",
|
"url": "https://www.youtube.com/watch?v=2lAe1cqCOXo",
|
||||||
"music_directory": output_directory,
|
"music_directory": output_directory,
|
||||||
},
|
},
|
||||||
|
|
@ -42,20 +46,21 @@ def single_song_preset_dict(output_directory):
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def single_song_best_format_preset_dict(single_song_preset_dict):
|
def single_best_format_preset_dict(single_preset_dict):
|
||||||
return dict(single_song_preset_dict, **{"audio_extract": {"codec": "best"}})
|
return dict(single_preset_dict, **{"audio_extract": {"codec": "best"}})
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def multiple_songs_preset_dict(output_directory):
|
def youtube_release_preset_dict(output_directory):
|
||||||
return {
|
return {
|
||||||
"preset": "albums_from_playlists",
|
"preset": "YouTube Releases",
|
||||||
"audio_extract": {"codec": "vorbis", "quality": 140},
|
"audio_extract": {"codec": "vorbis", "quality": 140},
|
||||||
"format": "worst[ext=mp4]", # download the worst format so it is fast
|
"format": "worst[ext=mp4]", # download the worst format so it is fast
|
||||||
"ytdl_options": {
|
"ytdl_options": {
|
||||||
"postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility
|
"postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
"track_artist": "Project Zombie",
|
||||||
"url": "https://youtube.com/playlist?list=PL5BC0FC26BECA5A35",
|
"url": "https://youtube.com/playlist?list=PL5BC0FC26BECA5A35",
|
||||||
"music_directory": output_directory,
|
"music_directory": output_directory,
|
||||||
},
|
},
|
||||||
|
|
@ -67,14 +72,14 @@ class TestAudioExtract:
|
||||||
def test_audio_extract_single_song_old_format(
|
def test_audio_extract_single_song_old_format(
|
||||||
self,
|
self,
|
||||||
music_audio_config,
|
music_audio_config,
|
||||||
single_song_preset_dict_old_format,
|
single_preset_dict_old_format,
|
||||||
output_directory,
|
output_directory,
|
||||||
dry_run,
|
dry_run,
|
||||||
):
|
):
|
||||||
subscription = Subscription.from_dict(
|
subscription = Subscription.from_dict(
|
||||||
config=music_audio_config,
|
config=music_audio_config,
|
||||||
preset_name="single_song_test",
|
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)
|
transaction_log = subscription.download(dry_run=dry_run)
|
||||||
|
|
@ -93,14 +98,14 @@ class TestAudioExtract:
|
||||||
def test_audio_extract_single_song(
|
def test_audio_extract_single_song(
|
||||||
self,
|
self,
|
||||||
music_audio_config,
|
music_audio_config,
|
||||||
single_song_preset_dict,
|
single_preset_dict,
|
||||||
output_directory,
|
output_directory,
|
||||||
dry_run,
|
dry_run,
|
||||||
):
|
):
|
||||||
subscription = Subscription.from_dict(
|
subscription = Subscription.from_dict(
|
||||||
config=music_audio_config,
|
config=music_audio_config,
|
||||||
preset_name="single_song_test",
|
preset_name="single_song_test",
|
||||||
preset_dict=single_song_preset_dict,
|
preset_dict=single_preset_dict,
|
||||||
)
|
)
|
||||||
|
|
||||||
transaction_log = subscription.download(dry_run=dry_run)
|
transaction_log = subscription.download(dry_run=dry_run)
|
||||||
|
|
@ -119,14 +124,14 @@ class TestAudioExtract:
|
||||||
def test_audio_extract_single_song_best_format(
|
def test_audio_extract_single_song_best_format(
|
||||||
self,
|
self,
|
||||||
music_audio_config,
|
music_audio_config,
|
||||||
single_song_best_format_preset_dict,
|
single_best_format_preset_dict,
|
||||||
output_directory,
|
output_directory,
|
||||||
dry_run,
|
dry_run,
|
||||||
):
|
):
|
||||||
subscription = Subscription.from_dict(
|
subscription = Subscription.from_dict(
|
||||||
config=music_audio_config,
|
config=music_audio_config,
|
||||||
preset_name="single_song_best_test",
|
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)
|
transaction_log = subscription.download(dry_run=dry_run)
|
||||||
|
|
@ -145,14 +150,14 @@ class TestAudioExtract:
|
||||||
def test_audio_extract_multiple_songs(
|
def test_audio_extract_multiple_songs(
|
||||||
self,
|
self,
|
||||||
music_audio_config,
|
music_audio_config,
|
||||||
multiple_songs_preset_dict,
|
youtube_release_preset_dict,
|
||||||
output_directory,
|
output_directory,
|
||||||
dry_run,
|
dry_run,
|
||||||
):
|
):
|
||||||
subscription = Subscription.from_dict(
|
subscription = Subscription.from_dict(
|
||||||
config=music_audio_config,
|
config=music_audio_config,
|
||||||
preset_name="multiple_songs_test",
|
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)
|
transaction_log = subscription.download(dry_run=dry_run)
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,14 @@ from ytdl_sub.utils.exceptions import ValidationException
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def yt_album_as_chapters_preset_dict(output_directory):
|
def yt_album_as_chapters_preset_dict(output_directory):
|
||||||
return {
|
return {
|
||||||
"preset": "albums_from_chapters",
|
"preset": "YouTube Full Albums",
|
||||||
"format": "worst[ext=mp4]", # download the worst format so it is fast
|
"format": "worst[ext=mp4]",
|
||||||
|
"audio_extract": {"codec": "mp3", "quality": 320},
|
||||||
"ytdl_options": {
|
"ytdl_options": {
|
||||||
"postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility
|
"postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"url": "https://www.youtube.com/watch?v=zeR2_YjlXWA",
|
"subscription_value": "https://www.youtube.com/watch?v=zeR2_YjlXWA",
|
||||||
"music_directory": output_directory,
|
"music_directory": output_directory,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -76,7 +77,7 @@ class TestSplitByChapters:
|
||||||
):
|
):
|
||||||
subscription = Subscription.from_dict(
|
subscription = Subscription.from_dict(
|
||||||
config=music_audio_config,
|
config=music_audio_config,
|
||||||
preset_name="split_by_chapters_video",
|
preset_name="Proved Records",
|
||||||
preset_dict=yt_album_as_chapters_preset_dict,
|
preset_dict=yt_album_as_chapters_preset_dict,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -106,7 +107,7 @@ class TestSplitByChapters:
|
||||||
):
|
):
|
||||||
subscription = Subscription.from_dict(
|
subscription = Subscription.from_dict(
|
||||||
config=music_audio_config,
|
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,
|
preset_dict=yt_album_as_chapters_with_regex_preset_dict,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -142,7 +143,7 @@ class TestSplitByChapters:
|
||||||
|
|
||||||
subscription = Subscription.from_dict(
|
subscription = Subscription.from_dict(
|
||||||
config=music_audio_config,
|
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,
|
preset_dict=yt_album_as_chapters_with_regex_preset_dict,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,11 @@ from ytdl_sub.subscriptions.subscription import Subscription
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def subscription_dict(output_directory):
|
def subscription_dict(output_directory):
|
||||||
return {
|
return {
|
||||||
"preset": "soundcloud_discography",
|
"preset": "SoundCloud Discography",
|
||||||
"format": "worst[ext=mp3]", # download the worst format so it is fast
|
"audio_extract": {"codec": "mp3", "quality": 320},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"track_artist": "j_b",
|
"subscription_value": "https://soundcloud.com/jessebannon",
|
||||||
"sc_artist_url": "https://soundcloud.com/jessebannon",
|
"subscription_indent_1": "Acoustic",
|
||||||
"music_directory": output_directory,
|
"music_directory": output_directory,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -34,7 +34,7 @@ class TestSoundcloudDiscography:
|
||||||
):
|
):
|
||||||
discography_subscription = Subscription.from_dict(
|
discography_subscription = Subscription.from_dict(
|
||||||
preset_dict=subscription_dict,
|
preset_dict=subscription_dict,
|
||||||
preset_name="jb",
|
preset_name="j_b",
|
||||||
config=music_audio_config,
|
config=music_audio_config,
|
||||||
)
|
)
|
||||||
transaction_log = discography_subscription.download(dry_run=dry_run)
|
transaction_log = discography_subscription.download(dry_run=dry_run)
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,20 @@
|
||||||
{
|
{
|
||||||
".ytdl-sub-jb-download-archive.json": "9f5ca17dc0d842ac4c296054c0011ace",
|
".ytdl-sub-Sithu Aye-download-archive.json": "0c58919b660f699f6aea2ec523c812c5",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/01 - Spark it.mp3": "f1fcc87884ced84be016391e3989b5c1",
|
"Sithu Aye/[2021] 10 Years: Remixes and Reimaginings/01 - Double Helix Reimagined.mp3": "a627cfc0964be6a7e668fd8289326140",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/02 - Astronomikal Funk.mp3": "d07701404b8ddaa2e38eb51f7e2ac2d8",
|
"Sithu Aye/[2021] 10 Years: Remixes and Reimaginings/02 - Skye Reimagined.mp3": "94127e3d82f5d33d920b82f90d4f9657",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/03 - Impulse.mp3": "43118db203e1d9427036102cfb39a1e3",
|
"Sithu Aye/[2021] 10 Years: Remixes and Reimaginings/03 - Baryofusion.mp3": "dcf4b30e3fdeb29154b3888838986c1e",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/04 - September.mp3": "3d75c5068e3dbb93dd86fc650c7ca84d",
|
"Sithu Aye/[2021] 10 Years: Remixes and Reimaginings/04 - Mandalay Reimagined.mp3": "8304b012a8a8306c80e3f7f7cb0f35e7",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/05 - Interlune.mp3": "63897d8af920f31af2183a17bc697c11",
|
"Sithu Aye/[2021] 10 Years: Remixes and Reimaginings/05 - Messenger EDM Remix.mp3": "0a7e4c613a055e571142182717fc684e",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/06 - Ninjutsu Techniques.mp3": "a500409583ee30e4cb68d64af2b32596",
|
"Sithu Aye/[2021] 10 Years: Remixes and Reimaginings/folder.jpg": "bf6f70d51557a71b69fed85b2cb476f0",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/07 - Space Funk Flow.mp3": "1e1a12a5a42a607abf342ec4f301f471",
|
"Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/01 - Invent the Universe.mp3": "d723a2e1f2ec75b3d20f1a0de616a191",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/08 - Cellar Groove.mp3": "a18ceff8785e8849d166eb2710caafa4",
|
"Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/02 - Grand Unification (feat. David Maxim Micic).mp3": "0e550ebe93f8b5349eb07c7554ad22d9",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/09 - Solar Wind.mp3": "a41665337e3fe05d7c7d9d8e6ddde737",
|
"Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/03 - Expansion.mp3": "6324f012f09a2e7028ca923fdff3a89a",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/10 - Interlune II.mp3": "8d2f3158ac9bac51aafbdbe6eb43154b",
|
"Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/04 - Baryogenesis.mp3": "d30de9d811f56c2179fd86c6bede2fc5",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/11 - Ghetto Anthem.mp3": "39085bae1b0f8544acd08f74f88cacfd",
|
"Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/05 - Particles Collide (feat. Plini).mp3": "f869f1948b376f2ad98381b0c77d447f",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/12 - Street Degree.mp3": "561f0d8fbc62f87f2149c17ee0a53ce2",
|
"Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/06 - Nucleosynthesis.mp3": "23d6ceb9865d6d6030d8659a2eed5698",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/13 - Trouble World.mp3": "1ad07dc6a2d6ced78449bc46a2909335",
|
"Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/07 - Recombination.mp3": "4ae97dc8457e48fa7aad9a64b927bf1d",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/14 - Relaxation.mp3": "ba8addb0d59f26a84bbb79a6cdd1af11",
|
"Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/08 - Dark Ages.mp3": "922e8a54e3e543bbf9b866e2f4a53607",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/15 - Journey From Within.mp3": "bd97135290482c6bbe6eac7d3a700f11",
|
"Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)/09 - Formation.mp3": "fd7ce4553df5323355bc95e6528e1515",
|
||||||
"El Jazzy Chavo/[2022] S950 Funk/folder.jpg": "62e51365dd309e76a6323f927f6fcc94"
|
"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"
|
||||||
}
|
}
|
||||||
|
|
@ -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]/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]/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",
|
"Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/03 - 03. Blaze (Feat. Kaya Thomas - Dyke).mp3": "63c0bc97cbdaf35203011378b1860418",
|
||||||
|
|
|
||||||
|
|
@ -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/01 - Oblivion Mod "Falcor" p.1.mp3": "8fc765ce55304814942c1f38fe9e38e2",
|
||||||
"Project Zombie/[2010] Oblivion Mod "Falcor" p.1/folder.jpg": "fb95b510681676e81c321171fc23143e"
|
"Project Zombie/[2010] Oblivion Mod "Falcor" p.1/folder.jpg": "fb95b510681676e81c321171fc23143e"
|
||||||
}
|
}
|
||||||
|
|
@ -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/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/02 - Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3": "881ecdbee4a0d565c0ec6eacf03115df",
|
||||||
"Alfa Mist/[2017] Nocturne/03 - Blaze (Feat. Kaya Thomas - Dyke).mp3": "aa5c6fbab58dd2be2660bfb65be6a172",
|
"Alfa Mist/[2017] Nocturne/03 - Blaze (Feat. Kaya Thomas - Dyke).mp3": "aa5c6fbab58dd2be2660bfb65be6a172",
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
{
|
{
|
||||||
".ytdl-sub-jb-download-archive.json": "1a99156e9ece62539fb2608416a07200",
|
".ytdl-sub-j_b-download-archive.json": "1a99156e9ece62539fb2608416a07200",
|
||||||
"j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.mp3": "317a9ee75431d6020e3cad0883c7392f",
|
"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] 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/[2021] Purple Clouds/folder.jpg": "967892be44b8c47e1be73f055a7c6f08",
|
||||||
"j_b/[2022] Acoustic Treats/01 - 20160426 184214.mp3": "bcc88eb579311b59ede4c13cdf24bcb9",
|
"j_b/[2022] Acoustic Treats/01 - 20160426 184214.mp3": "2a0232454e2ef2a12e74496d3389f1ca",
|
||||||
"j_b/[2022] Acoustic Treats/02 - 20160502 123150.mp3": "239d10c17047662c760cce834548d91d",
|
"j_b/[2022] Acoustic Treats/02 - 20160502 123150.mp3": "cd4276f72de542b03d6e193352565603",
|
||||||
"j_b/[2022] Acoustic Treats/03 - 20160504 143832.mp3": "2d6e977e3e665012fdeaa0e8c2ee7375",
|
"j_b/[2022] Acoustic Treats/03 - 20160504 143832.mp3": "80d9152600faca9d0dc8dee41a028cf8",
|
||||||
"j_b/[2022] Acoustic Treats/04 - 20160601 221234.mp3": "9da5b26fc231dfd0c8f09a2a3d2fe116",
|
"j_b/[2022] Acoustic Treats/04 - 20160601 221234.mp3": "2ee3c7f489ffc961e6ebc8d2ab4af000",
|
||||||
"j_b/[2022] Acoustic Treats/05 - 20160601 222440.mp3": "8fb1cb262175921dbdddd6783664fa65",
|
"j_b/[2022] Acoustic Treats/05 - 20160601 222440.mp3": "0aeb9c6165ecdaa993de4d7958ae9b5f",
|
||||||
"j_b/[2022] Acoustic Treats/06 - 20170604 190236.mp3": "529846e26a18be616deb3f12d858b8ea",
|
"j_b/[2022] Acoustic Treats/06 - 20170604 190236.mp3": "eeb122552f13533a647828435dcac99e",
|
||||||
"j_b/[2022] Acoustic Treats/07 - 20170612 193646.mp3": "ba2be1ace7b0c31964bf0b8b15781b27",
|
"j_b/[2022] Acoustic Treats/07 - 20170612 193646.mp3": "1c387d318152e3783c06fbe040c4abf0",
|
||||||
"j_b/[2022] Acoustic Treats/08 - 20170628 215206.mp3": "ad248c0392ced4f6d548a4852fd99f1f",
|
"j_b/[2022] Acoustic Treats/08 - 20170628 215206.mp3": "97a5689681217fb6da82f21953f63ffb",
|
||||||
"j_b/[2022] Acoustic Treats/09 - Finding Home.mp3": "52326cbd96e6f243cae77b0f68f00ef6",
|
"j_b/[2022] Acoustic Treats/09 - Finding Home.mp3": "5440e42341549d2ade910ef44baf44d4",
|
||||||
"j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.mp3": "a265ed7e4d3a014d09e79ac5f4fe3fc7",
|
"j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.mp3": "4029bdf1d78995aa6a961fd2ea671f41",
|
||||||
"j_b/[2022] Acoustic Treats/11 - Untold History.mp3": "94d548773dded0089e73b26e6f923d9a",
|
"j_b/[2022] Acoustic Treats/11 - Untold History.mp3": "3687b16d0cefde103f80b76ba8490632",
|
||||||
"j_b/[2022] Acoustic Treats/folder.jpg": "967892be44b8c47e1be73f055a7c6f08"
|
"j_b/[2022] Acoustic Treats/folder.jpg": "967892be44b8c47e1be73f055a7c6f08"
|
||||||
}
|
}
|
||||||
|
|
@ -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"
|
||||||
|
}
|
||||||
|
|
@ -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"
|
||||||
|
}
|
||||||
|
|
@ -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"
|
||||||
|
}
|
||||||
|
|
@ -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"
|
||||||
|
}
|
||||||
|
|
@ -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"
|
||||||
|
}
|
||||||
BIN
tests/resources/file_fixtures/sample_audio.mp3
Normal file
BIN
tests/resources/file_fixtures/sample_audio.mp3
Normal file
Binary file not shown.
|
|
@ -1,186 +1,188 @@
|
||||||
Files created:
|
Files created:
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
{output_directory}
|
{output_directory}
|
||||||
.ytdl-sub-jb-download-archive.json
|
.ytdl-sub-Sithu Aye-download-archive.json
|
||||||
{output_directory}/El Jazzy Chavo/[2022] S950 Funk
|
{output_directory}/Sithu Aye/[2021] 10 Years: Remixes and Reimaginings
|
||||||
01 - Spark it.mp3
|
01 - Double Helix Reimagined.mp3
|
||||||
Music Tags:
|
Music Tags:
|
||||||
album: S950 Funk
|
album: 10 Years: Remixes and Reimaginings
|
||||||
albumartist: El Jazzy Chavo
|
albumartist: Sithu Aye
|
||||||
albumartists: El Jazzy Chavo
|
albumartists: Sithu Aye
|
||||||
artist: El Jazzy Chavo
|
artist: Sithu Aye
|
||||||
artists: El Jazzy Chavo
|
artists: Sithu Aye
|
||||||
genre: Unset
|
genre: Progressive Metal
|
||||||
title: Spark it
|
title: Double Helix Reimagined
|
||||||
track: 1
|
track: 1
|
||||||
tracktotal: 15
|
tracktotal: 10
|
||||||
year: 2022
|
year: 2021
|
||||||
02 - Astronomikal Funk.mp3
|
02 - Skye Reimagined.mp3
|
||||||
Music Tags:
|
Music Tags:
|
||||||
album: S950 Funk
|
album: 10 Years: Remixes and Reimaginings
|
||||||
albumartist: El Jazzy Chavo
|
albumartist: Sithu Aye
|
||||||
albumartists: El Jazzy Chavo
|
albumartists: Sithu Aye
|
||||||
artist: El Jazzy Chavo
|
artist: Sithu Aye
|
||||||
artists: El Jazzy Chavo
|
artists: Sithu Aye
|
||||||
genre: Unset
|
genre: Progressive Metal
|
||||||
title: Astronomikal Funk
|
title: Skye Reimagined
|
||||||
track: 2
|
track: 2
|
||||||
tracktotal: 15
|
tracktotal: 10
|
||||||
year: 2022
|
year: 2021
|
||||||
03 - Impulse.mp3
|
03 - Baryofusion.mp3
|
||||||
Music Tags:
|
Music Tags:
|
||||||
album: S950 Funk
|
album: 10 Years: Remixes and Reimaginings
|
||||||
albumartist: El Jazzy Chavo
|
albumartist: Sithu Aye
|
||||||
albumartists: El Jazzy Chavo
|
albumartists: Sithu Aye
|
||||||
artist: El Jazzy Chavo
|
artist: Sithu Aye
|
||||||
artists: El Jazzy Chavo
|
artists: Sithu Aye
|
||||||
genre: Unset
|
genre: Progressive Metal
|
||||||
title: Impulse
|
title: Baryofusion
|
||||||
track: 3
|
track: 3
|
||||||
tracktotal: 15
|
tracktotal: 10
|
||||||
year: 2022
|
year: 2021
|
||||||
04 - September.mp3
|
04 - Mandalay Reimagined.mp3
|
||||||
Music Tags:
|
Music Tags:
|
||||||
album: S950 Funk
|
album: 10 Years: Remixes and Reimaginings
|
||||||
albumartist: El Jazzy Chavo
|
albumartist: Sithu Aye
|
||||||
albumartists: El Jazzy Chavo
|
albumartists: Sithu Aye
|
||||||
artist: El Jazzy Chavo
|
artist: Sithu Aye
|
||||||
artists: El Jazzy Chavo
|
artists: Sithu Aye
|
||||||
genre: Unset
|
genre: Progressive Metal
|
||||||
title: September
|
title: Mandalay Reimagined
|
||||||
track: 4
|
track: 4
|
||||||
tracktotal: 15
|
tracktotal: 10
|
||||||
year: 2022
|
year: 2021
|
||||||
05 - Interlune.mp3
|
05 - Messenger EDM Remix.mp3
|
||||||
Music Tags:
|
Music Tags:
|
||||||
album: S950 Funk
|
album: 10 Years: Remixes and Reimaginings
|
||||||
albumartist: El Jazzy Chavo
|
albumartist: Sithu Aye
|
||||||
albumartists: El Jazzy Chavo
|
albumartists: Sithu Aye
|
||||||
artist: El Jazzy Chavo
|
artist: Sithu Aye
|
||||||
artists: El Jazzy Chavo
|
artists: Sithu Aye
|
||||||
genre: Unset
|
genre: Progressive Metal
|
||||||
title: Interlune
|
title: Messenger EDM Remix
|
||||||
track: 5
|
track: 5
|
||||||
tracktotal: 15
|
tracktotal: 10
|
||||||
year: 2022
|
year: 2021
|
||||||
06 - Ninjutsu Techniques.mp3
|
folder.jpg
|
||||||
|
{output_directory}/Sithu Aye/[2022] Re:Invent the Universe (10th Anniversary Remaster)
|
||||||
|
01 - Invent the Universe.mp3
|
||||||
Music Tags:
|
Music Tags:
|
||||||
album: S950 Funk
|
album: Re:Invent the Universe (10th Anniversary Remaster)
|
||||||
albumartist: El Jazzy Chavo
|
albumartist: Sithu Aye
|
||||||
albumartists: El Jazzy Chavo
|
albumartists: Sithu Aye
|
||||||
artist: El Jazzy Chavo
|
artist: Sithu Aye
|
||||||
artists: El Jazzy Chavo
|
artists: Sithu Aye
|
||||||
genre: Unset
|
genre: Progressive Metal
|
||||||
title: Ninjutsu Techniques
|
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
|
track: 6
|
||||||
tracktotal: 15
|
tracktotal: 10
|
||||||
year: 2022
|
year: 2022
|
||||||
07 - Space Funk Flow.mp3
|
07 - Recombination.mp3
|
||||||
Music Tags:
|
Music Tags:
|
||||||
album: S950 Funk
|
album: Re:Invent the Universe (10th Anniversary Remaster)
|
||||||
albumartist: El Jazzy Chavo
|
albumartist: Sithu Aye
|
||||||
albumartists: El Jazzy Chavo
|
albumartists: Sithu Aye
|
||||||
artist: El Jazzy Chavo
|
artist: Sithu Aye
|
||||||
artists: El Jazzy Chavo
|
artists: Sithu Aye
|
||||||
genre: Unset
|
genre: Progressive Metal
|
||||||
title: Space Funk Flow
|
title: Recombination
|
||||||
track: 7
|
track: 7
|
||||||
tracktotal: 15
|
tracktotal: 10
|
||||||
year: 2022
|
year: 2022
|
||||||
08 - Cellar Groove.mp3
|
08 - Dark Ages.mp3
|
||||||
Music Tags:
|
Music Tags:
|
||||||
album: S950 Funk
|
album: Re:Invent the Universe (10th Anniversary Remaster)
|
||||||
albumartist: El Jazzy Chavo
|
albumartist: Sithu Aye
|
||||||
albumartists: El Jazzy Chavo
|
albumartists: Sithu Aye
|
||||||
artist: El Jazzy Chavo
|
artist: Sithu Aye
|
||||||
artists: El Jazzy Chavo
|
artists: Sithu Aye
|
||||||
genre: Unset
|
genre: Progressive Metal
|
||||||
title: Cellar Groove
|
title: Dark Ages
|
||||||
track: 8
|
track: 8
|
||||||
tracktotal: 15
|
tracktotal: 10
|
||||||
year: 2022
|
year: 2022
|
||||||
09 - Solar Wind.mp3
|
09 - Formation.mp3
|
||||||
Music Tags:
|
Music Tags:
|
||||||
album: S950 Funk
|
album: Re:Invent the Universe (10th Anniversary Remaster)
|
||||||
albumartist: El Jazzy Chavo
|
albumartist: Sithu Aye
|
||||||
albumartists: El Jazzy Chavo
|
albumartists: Sithu Aye
|
||||||
artist: El Jazzy Chavo
|
artist: Sithu Aye
|
||||||
artists: El Jazzy Chavo
|
artists: Sithu Aye
|
||||||
genre: Unset
|
genre: Progressive Metal
|
||||||
title: Solar Wind
|
title: Formation
|
||||||
track: 9
|
track: 9
|
||||||
tracktotal: 15
|
tracktotal: 10
|
||||||
year: 2022
|
year: 2022
|
||||||
10 - Interlune II.mp3
|
10 - Pale Blue Dot.mp3
|
||||||
Music Tags:
|
Music Tags:
|
||||||
album: S950 Funk
|
album: Re:Invent the Universe (10th Anniversary Remaster)
|
||||||
albumartist: El Jazzy Chavo
|
albumartist: Sithu Aye
|
||||||
albumartists: El Jazzy Chavo
|
albumartists: Sithu Aye
|
||||||
artist: El Jazzy Chavo
|
artist: Sithu Aye
|
||||||
artists: El Jazzy Chavo
|
artists: Sithu Aye
|
||||||
genre: Unset
|
genre: Progressive Metal
|
||||||
title: Interlune II
|
title: Pale Blue Dot
|
||||||
track: 10
|
track: 10
|
||||||
tracktotal: 15
|
tracktotal: 10
|
||||||
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
|
|
||||||
year: 2022
|
year: 2022
|
||||||
folder.jpg
|
folder.jpg
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
Files created:
|
Files created:
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
{output_directory}
|
{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]
|
{output_directory}/Proved Records/[2017] Alfa Mist - Nocturne [Full Album]
|
||||||
01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3
|
01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3
|
||||||
From Chapter Split:
|
From Chapter Split:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
Files created:
|
Files created:
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
{output_directory}
|
{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]
|
{output_directory}/Proved Records/[2017] Alfa Mist - Nocturne [Full Album]
|
||||||
01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3
|
01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3
|
||||||
From Chapter Split:
|
From Chapter Split:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
Files created:
|
Files created:
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
{output_directory}
|
{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
|
{output_directory}/Project Zombie/[2010] Oblivion Mod "Falcor" p.1
|
||||||
01 - Oblivion Mod "Falcor" p.1.mp3
|
01 - Oblivion Mod "Falcor" p.1.mp3
|
||||||
Music Tags:
|
Music Tags:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
Files created:
|
Files created:
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
{output_directory}
|
{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
|
{output_directory}/Alfa Mist/[2017] Nocturne
|
||||||
01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3
|
01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3
|
||||||
From Chapter Split:
|
From Chapter Split:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
Files created:
|
Files created:
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
{output_directory}
|
{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
|
{output_directory}/Alfa Mist/[2017] Nocturne
|
||||||
01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3
|
01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3
|
||||||
From Chapter Split:
|
From Chapter Split:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
Files created:
|
Files created:
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
{output_directory}
|
{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
|
{output_directory}/j_b/[2021] Baby Santana's Dorian Groove
|
||||||
01 - Baby Santana's Dorian Groove.mp3
|
01 - Baby Santana's Dorian Groove.mp3
|
||||||
Music Tags:
|
Music Tags:
|
||||||
|
|
@ -10,7 +10,7 @@ Files created:
|
||||||
albumartists: j_b
|
albumartists: j_b
|
||||||
artist: j_b
|
artist: j_b
|
||||||
artists: j_b
|
artists: j_b
|
||||||
genre: Unset
|
genre: Acoustic
|
||||||
title: Baby Santana's Dorian Groove
|
title: Baby Santana's Dorian Groove
|
||||||
track: 1
|
track: 1
|
||||||
tracktotal: 1
|
tracktotal: 1
|
||||||
|
|
@ -24,7 +24,7 @@ Files created:
|
||||||
albumartists: j_b
|
albumartists: j_b
|
||||||
artist: j_b
|
artist: j_b
|
||||||
artists: j_b
|
artists: j_b
|
||||||
genre: Unset
|
genre: Acoustic
|
||||||
title: Purple Clouds
|
title: Purple Clouds
|
||||||
track: 1
|
track: 1
|
||||||
tracktotal: 1
|
tracktotal: 1
|
||||||
|
|
@ -38,7 +38,7 @@ Files created:
|
||||||
albumartists: j_b
|
albumartists: j_b
|
||||||
artist: j_b
|
artist: j_b
|
||||||
artists: j_b
|
artists: j_b
|
||||||
genre: Unset
|
genre: Acoustic
|
||||||
title: 20160426 184214
|
title: 20160426 184214
|
||||||
track: 1
|
track: 1
|
||||||
tracktotal: 11
|
tracktotal: 11
|
||||||
|
|
@ -50,7 +50,7 @@ Files created:
|
||||||
albumartists: j_b
|
albumartists: j_b
|
||||||
artist: j_b
|
artist: j_b
|
||||||
artists: j_b
|
artists: j_b
|
||||||
genre: Unset
|
genre: Acoustic
|
||||||
title: 20160502 123150
|
title: 20160502 123150
|
||||||
track: 2
|
track: 2
|
||||||
tracktotal: 11
|
tracktotal: 11
|
||||||
|
|
@ -62,7 +62,7 @@ Files created:
|
||||||
albumartists: j_b
|
albumartists: j_b
|
||||||
artist: j_b
|
artist: j_b
|
||||||
artists: j_b
|
artists: j_b
|
||||||
genre: Unset
|
genre: Acoustic
|
||||||
title: 20160504 143832
|
title: 20160504 143832
|
||||||
track: 3
|
track: 3
|
||||||
tracktotal: 11
|
tracktotal: 11
|
||||||
|
|
@ -74,7 +74,7 @@ Files created:
|
||||||
albumartists: j_b
|
albumartists: j_b
|
||||||
artist: j_b
|
artist: j_b
|
||||||
artists: j_b
|
artists: j_b
|
||||||
genre: Unset
|
genre: Acoustic
|
||||||
title: 20160601 221234
|
title: 20160601 221234
|
||||||
track: 4
|
track: 4
|
||||||
tracktotal: 11
|
tracktotal: 11
|
||||||
|
|
@ -86,7 +86,7 @@ Files created:
|
||||||
albumartists: j_b
|
albumartists: j_b
|
||||||
artist: j_b
|
artist: j_b
|
||||||
artists: j_b
|
artists: j_b
|
||||||
genre: Unset
|
genre: Acoustic
|
||||||
title: 20160601 222440
|
title: 20160601 222440
|
||||||
track: 5
|
track: 5
|
||||||
tracktotal: 11
|
tracktotal: 11
|
||||||
|
|
@ -98,7 +98,7 @@ Files created:
|
||||||
albumartists: j_b
|
albumartists: j_b
|
||||||
artist: j_b
|
artist: j_b
|
||||||
artists: j_b
|
artists: j_b
|
||||||
genre: Unset
|
genre: Acoustic
|
||||||
title: 20170604 190236
|
title: 20170604 190236
|
||||||
track: 6
|
track: 6
|
||||||
tracktotal: 11
|
tracktotal: 11
|
||||||
|
|
@ -110,7 +110,7 @@ Files created:
|
||||||
albumartists: j_b
|
albumartists: j_b
|
||||||
artist: j_b
|
artist: j_b
|
||||||
artists: j_b
|
artists: j_b
|
||||||
genre: Unset
|
genre: Acoustic
|
||||||
title: 20170612 193646
|
title: 20170612 193646
|
||||||
track: 7
|
track: 7
|
||||||
tracktotal: 11
|
tracktotal: 11
|
||||||
|
|
@ -122,7 +122,7 @@ Files created:
|
||||||
albumartists: j_b
|
albumartists: j_b
|
||||||
artist: j_b
|
artist: j_b
|
||||||
artists: j_b
|
artists: j_b
|
||||||
genre: Unset
|
genre: Acoustic
|
||||||
title: 20170628 215206
|
title: 20170628 215206
|
||||||
track: 8
|
track: 8
|
||||||
tracktotal: 11
|
tracktotal: 11
|
||||||
|
|
@ -134,7 +134,7 @@ Files created:
|
||||||
albumartists: j_b
|
albumartists: j_b
|
||||||
artist: j_b
|
artist: j_b
|
||||||
artists: j_b
|
artists: j_b
|
||||||
genre: Unset
|
genre: Acoustic
|
||||||
title: Finding Home
|
title: Finding Home
|
||||||
track: 9
|
track: 9
|
||||||
tracktotal: 11
|
tracktotal: 11
|
||||||
|
|
@ -146,7 +146,7 @@ Files created:
|
||||||
albumartists: j_b
|
albumartists: j_b
|
||||||
artist: j_b
|
artist: j_b
|
||||||
artists: j_b
|
artists: j_b
|
||||||
genre: Unset
|
genre: Acoustic
|
||||||
title: Shallow Water WIP
|
title: Shallow Water WIP
|
||||||
track: 10
|
track: 10
|
||||||
tracktotal: 11
|
tracktotal: 11
|
||||||
|
|
@ -158,7 +158,7 @@ Files created:
|
||||||
albumartists: j_b
|
albumartists: j_b
|
||||||
artist: j_b
|
artist: j_b
|
||||||
artists: j_b
|
artists: j_b
|
||||||
genre: Unset
|
genre: Acoustic
|
||||||
title: Untold History
|
title: Untold History
|
||||||
track: 11
|
track: 11
|
||||||
tracktotal: 11
|
tracktotal: 11
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -341,7 +341,7 @@ def test_tv_show_subscriptions(
|
||||||
config=channel_as_tv_show_config, subscription_path=tv_show_subscriptions_path
|
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"
|
assert subs[2].name == "Jake Trains"
|
||||||
jake_train_overrides = subs[2].overrides.dict_with_format_strings
|
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_value"] == "https://www.youtube.com/@JakeTrains"
|
||||||
assert jake_train_overrides["subscription_indent_1"] == "Kids"
|
assert jake_train_overrides["subscription_indent_1"] == "Kids"
|
||||||
assert jake_train_overrides["subscription_indent_2"] == "TV-Y"
|
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"
|
||||||
|
|
|
||||||
|
|
@ -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_COUNT
|
||||||
from ytdl_sub.entries.variables.kwargs import PLAYLIST_ENTRY
|
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_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 TITLE
|
||||||
from ytdl_sub.entries.variables.kwargs import UID
|
from ytdl_sub.entries.variables.kwargs import UID
|
||||||
from ytdl_sub.entries.variables.kwargs import UPLOAD_DATE
|
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(
|
def _mock_entry_dict_factory(
|
||||||
uid: int,
|
uid: int,
|
||||||
upload_date: str,
|
upload_date: str,
|
||||||
|
playlist_title: str = "playlist title",
|
||||||
playlist_index: int = 1,
|
playlist_index: int = 1,
|
||||||
playlist_count: int = 1,
|
playlist_count: int = 1,
|
||||||
is_youtube_channel: bool = False,
|
is_youtube_channel: bool = False,
|
||||||
mock_download_to_working_dir: bool = True,
|
mock_download_to_working_dir: bool = True,
|
||||||
|
is_extracted_audio: bool = False,
|
||||||
) -> Dict:
|
) -> Dict:
|
||||||
entry_dict = {
|
entry_dict = {
|
||||||
UID: uid,
|
UID: uid,
|
||||||
EPOCH: 1596878400,
|
EPOCH: 1596878400,
|
||||||
|
PLAYLIST_TITLE: playlist_title,
|
||||||
PLAYLIST_INDEX: playlist_index,
|
PLAYLIST_INDEX: playlist_index,
|
||||||
PLAYLIST_COUNT: playlist_count,
|
PLAYLIST_COUNT: playlist_count,
|
||||||
EXTRACTOR: "mock-entry-dict",
|
EXTRACTOR: "mock-entry-dict",
|
||||||
|
|
@ -86,10 +90,16 @@ def mock_entry_dict_factory(mock_downloaded_file_path) -> Callable:
|
||||||
|
|
||||||
# Create mock video file
|
# Create mock video file
|
||||||
if mock_download_to_working_dir:
|
if mock_download_to_working_dir:
|
||||||
copy_file_fixture(
|
if is_extracted_audio:
|
||||||
fixture_name="sample_vid.mp4",
|
copy_file_fixture(
|
||||||
output_file_path=mock_downloaded_file_path(f"{uid}.mp4"),
|
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(
|
copy_file_fixture(
|
||||||
fixture_name="thumb.jpg", output_file_path=mock_downloaded_file_path(f"{uid}.jpg")
|
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
|
_ = thumbnail_url
|
||||||
output_name = os.path.basename(output_thumbnail_path)
|
output_name = os.path.basename(output_thumbnail_path)
|
||||||
if "poster" in output_name or "show" in output_name:
|
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
|
return True
|
||||||
elif "fanart" in output_name:
|
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 True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
@ -125,37 +139,50 @@ def mock_download_collection_entries(
|
||||||
mock_download_collection_thumbnail, mock_entry_dict_factory: Callable, working_directory: str
|
mock_download_collection_thumbnail, mock_entry_dict_factory: Callable, working_directory: str
|
||||||
):
|
):
|
||||||
@contextlib.contextmanager
|
@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]:
|
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 [
|
return [
|
||||||
mock_entry_dict_factory(
|
mock_entry_dict_factory(
|
||||||
uid="21-1",
|
uid="21-1",
|
||||||
upload_date="20210808",
|
upload_date="20210808",
|
||||||
|
playlist_title="Download First",
|
||||||
playlist_index=1,
|
playlist_index=1,
|
||||||
playlist_count=4,
|
playlist_count=4,
|
||||||
is_youtube_channel=is_youtube_channel,
|
is_youtube_channel=is_youtube_channel,
|
||||||
|
is_extracted_audio=is_extracted_audio,
|
||||||
), # 1
|
), # 1
|
||||||
mock_entry_dict_factory(
|
mock_entry_dict_factory(
|
||||||
uid="20-1",
|
uid="20-1",
|
||||||
upload_date="20200808",
|
upload_date="20200808",
|
||||||
|
playlist_title="Download First",
|
||||||
playlist_index=2,
|
playlist_index=2,
|
||||||
playlist_count=4,
|
playlist_count=4,
|
||||||
is_youtube_channel=is_youtube_channel,
|
is_youtube_channel=is_youtube_channel,
|
||||||
|
is_extracted_audio=is_extracted_audio,
|
||||||
), # 2 98
|
), # 2 98
|
||||||
mock_entry_dict_factory(
|
mock_entry_dict_factory(
|
||||||
uid="20-2",
|
uid="20-2",
|
||||||
upload_date="20200808",
|
upload_date="20200808",
|
||||||
|
playlist_title="Download First",
|
||||||
playlist_index=3,
|
playlist_index=3,
|
||||||
playlist_count=4,
|
playlist_count=4,
|
||||||
is_youtube_channel=is_youtube_channel,
|
is_youtube_channel=is_youtube_channel,
|
||||||
|
is_extracted_audio=is_extracted_audio,
|
||||||
), # 1 99
|
), # 1 99
|
||||||
mock_entry_dict_factory(
|
mock_entry_dict_factory(
|
||||||
uid="20-3",
|
uid="20-3",
|
||||||
upload_date="20200807",
|
upload_date="20200807",
|
||||||
|
playlist_title="Download First",
|
||||||
playlist_index=4,
|
playlist_index=4,
|
||||||
playlist_count=4,
|
playlist_count=4,
|
||||||
is_youtube_channel=is_youtube_channel,
|
is_youtube_channel=is_youtube_channel,
|
||||||
|
is_extracted_audio=is_extracted_audio,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
return [
|
return [
|
||||||
|
|
@ -163,38 +190,48 @@ def mock_download_collection_entries(
|
||||||
mock_entry_dict_factory(
|
mock_entry_dict_factory(
|
||||||
uid="20-3",
|
uid="20-3",
|
||||||
upload_date="20200807",
|
upload_date="20200807",
|
||||||
|
playlist_title="Download Second",
|
||||||
playlist_index=1,
|
playlist_index=1,
|
||||||
playlist_count=5,
|
playlist_count=5,
|
||||||
is_youtube_channel=is_youtube_channel,
|
is_youtube_channel=is_youtube_channel,
|
||||||
mock_download_to_working_dir=False,
|
mock_download_to_working_dir=False,
|
||||||
|
is_extracted_audio=is_extracted_audio,
|
||||||
),
|
),
|
||||||
mock_entry_dict_factory(
|
mock_entry_dict_factory(
|
||||||
uid="20-4",
|
uid="20-4",
|
||||||
upload_date="20200806",
|
upload_date="20200806",
|
||||||
|
playlist_title="Download Second",
|
||||||
playlist_index=2,
|
playlist_index=2,
|
||||||
playlist_count=5,
|
playlist_count=5,
|
||||||
is_youtube_channel=is_youtube_channel,
|
is_youtube_channel=is_youtube_channel,
|
||||||
|
is_extracted_audio=is_extracted_audio,
|
||||||
),
|
),
|
||||||
mock_entry_dict_factory(
|
mock_entry_dict_factory(
|
||||||
uid="20-5",
|
uid="20-5",
|
||||||
upload_date="20200706",
|
upload_date="20200706",
|
||||||
|
playlist_title="Download Second",
|
||||||
playlist_index=3,
|
playlist_index=3,
|
||||||
playlist_count=5,
|
playlist_count=5,
|
||||||
is_youtube_channel=is_youtube_channel,
|
is_youtube_channel=is_youtube_channel,
|
||||||
|
is_extracted_audio=is_extracted_audio,
|
||||||
),
|
),
|
||||||
mock_entry_dict_factory(
|
mock_entry_dict_factory(
|
||||||
uid="20-6",
|
uid="20-6",
|
||||||
upload_date="20200706",
|
upload_date="20200706",
|
||||||
|
playlist_title="Download Second",
|
||||||
playlist_index=4,
|
playlist_index=4,
|
||||||
playlist_count=5,
|
playlist_count=5,
|
||||||
is_youtube_channel=is_youtube_channel,
|
is_youtube_channel=is_youtube_channel,
|
||||||
|
is_extracted_audio=is_extracted_audio,
|
||||||
),
|
),
|
||||||
mock_entry_dict_factory(
|
mock_entry_dict_factory(
|
||||||
uid="20-7",
|
uid="20-7",
|
||||||
upload_date="20200606",
|
upload_date="20200606",
|
||||||
|
playlist_title="Download Second",
|
||||||
playlist_index=5,
|
playlist_index=5,
|
||||||
playlist_count=5,
|
playlist_count=5,
|
||||||
is_youtube_channel=is_youtube_channel,
|
is_youtube_channel=is_youtube_channel,
|
||||||
|
is_extracted_audio=is_extracted_audio,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,18 +6,19 @@ import pytest
|
||||||
from expected_download import assert_expected_downloads
|
from expected_download import assert_expected_downloads
|
||||||
from expected_transaction_log import assert_transaction_log_matches
|
from expected_transaction_log import assert_transaction_log_matches
|
||||||
|
|
||||||
from ytdl_sub.prebuilt_presets import TvShowByDatePresets
|
from ytdl_sub.prebuilt_presets.music import MusicPresets
|
||||||
from ytdl_sub.prebuilt_presets import TvShowCollectionPresets
|
|
||||||
from ytdl_sub.prebuilt_presets.tv_show import TvShowByDateEpisodeFormattingPresets
|
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 TvShowCollectionEpisodeFormattingPresets
|
||||||
|
from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionPresets
|
||||||
from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionSeasonPresets
|
from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionSeasonPresets
|
||||||
from ytdl_sub.subscriptions.subscription import Subscription
|
from ytdl_sub.subscriptions.subscription import Subscription
|
||||||
from ytdl_sub.utils.exceptions import ValidationException
|
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(
|
@pytest.mark.parametrize(
|
||||||
"tv_show_structure_preset", TvShowByDateEpisodeFormattingPresets.get_preset_names()
|
"tv_show_structure_preset", TvShowByDateEpisodeFormattingPresets.preset_names
|
||||||
)
|
)
|
||||||
class TestPrebuiltTVShowPresets:
|
class TestPrebuiltTVShowPresets:
|
||||||
def test_compilation(
|
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(
|
@pytest.mark.parametrize(
|
||||||
"tv_show_structure_preset", TvShowCollectionEpisodeFormattingPresets.get_preset_names()
|
"tv_show_structure_preset", TvShowCollectionEpisodeFormattingPresets.preset_names
|
||||||
)
|
)
|
||||||
class TestPrebuiltTvShowCollectionPresets:
|
class TestPrebuiltTvShowCollectionPresets:
|
||||||
@pytest.mark.parametrize("season_preset", TvShowCollectionSeasonPresets.get_preset_names())
|
@pytest.mark.parametrize("season_preset", TvShowCollectionSeasonPresets.preset_names)
|
||||||
def test_compilation(
|
def test_compilation(
|
||||||
self,
|
self,
|
||||||
config,
|
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(
|
def test_compilation_errors_missing_one(
|
||||||
self,
|
self,
|
||||||
config,
|
config,
|
||||||
|
|
@ -342,3 +343,70 @@ class TestPrebuiltTvShowCollectionPresets:
|
||||||
dry_run=False,
|
dry_run=False,
|
||||||
expected_download_summary_file_name=f"{reformatted_expected_summary_name}_migrated.json",
|
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",
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue