[BACKEND] Bandcamp e2e test, update music example (#393)

* [BUGFIX] Fix missing contains function when checking entries

* remove children func

* [BACKEND] Bandcamp e2e test, update music example

* WIP

* combine soundcloud and all music into music_audio config

* sc fixtures

* updated tests and examples

* bandcamp e2e test

* regen off

* remove url validators

* use bandcamp artist url for more parent coverage

* lint
This commit is contained in:
Jesse Bannon 2023-01-14 16:48:27 -08:00 committed by GitHub
parent c828ca5978
commit e5b5c5e638
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 852 additions and 636 deletions

View file

@ -102,11 +102,33 @@ jobs:
source /opt/env/bin/activate
coverage run -m pytest tests/e2e/soundcloud && coverage xml -o /opt/coverage/soundcloud/coverage.xml
test-bandcamp:
runs-on: ubuntu-22.04
needs: test-build
permissions:
contents: read
steps:
- uses: actions/checkout@v3
- name: Restore Python build cache
uses: actions/cache@v3
with:
path: /opt/env
key: ${{github.sha}}-env
- name: Run e2e soundcloud tests with coverage
run: |
sudo apt-get update
sudo apt-get install -y ffmpeg
source /opt/env/bin/activate
coverage run -m pytest tests/e2e/bandcamp && coverage xml -o /opt/coverage/bandcamp/coverage.xml
- name: Save coverage
uses: actions/cache@v3
with:
path: /opt/coverage/soundcloud
key: ${{github.sha}}-coverage-soundcloud
path: /opt/coverage/bandcamp
key: ${{github.sha}}-coverage-bandcamp
test-youtube:
runs-on: ubuntu-22.04
@ -169,6 +191,7 @@ jobs:
needs: [
test-unit,
test-soundcloud,
test-bandcamp,
test-youtube,
test-plugins
]
@ -188,6 +211,12 @@ jobs:
path: /opt/coverage/soundcloud
key: ${{github.sha}}-coverage-soundcloud
- name: Restore bandcamp test coverage
uses: actions/cache@v3
with:
path: /opt/coverage/bandcamp
key: ${{github.sha}}-coverage-bandcamp
- name: Restore youtube test coverage
uses: actions/cache@v3
with:
@ -204,4 +233,4 @@ jobs:
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: /opt/coverage/unit/coverage.xml,/opt/coverage/soundcloud/coverage.xml,/opt/coverage/youtube/coverage.xml,/opt/coverage/plugins/coverage.xml
files: /opt/coverage/unit/coverage.xml,/opt/coverage/soundcloud/coverage.xml,/opt/coverage/bandcamp/coverage.xml,/opt/coverage/youtube/coverage.xml,/opt/coverage/plugins/coverage.xml

View file

@ -0,0 +1,195 @@
# 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:
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}"
# 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:
download_strategy: "url"
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:
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: "{sc_artist_url}/tracks"
variables:
sc_track_album: "{title}"
sc_track_number: "1"
sc_track_number_padded: "01"
sc_track_total: "1"
sc_track_year: "{upload_year}"
# Set the second URL to the artist's albums. If a track belongs to both
# to an album and tracks (in the URL above), it will resolve to this
# URL and include the album metadata we set below.
- url: "{sc_artist_url}/albums"
variables:
sc_track_album: "{playlist_title}"
sc_track_number: "{playlist_index}"
sc_track_number_padded: "{playlist_index_padded}"
sc_track_total: "{playlist_count}"
sc_track_year: "{playlist_max_upload_year}"
# Override various track properties using playlist variables.
overrides:
track_album: "{sc_track_album}"
track_number: "{sc_track_number}"
track_number_padded: "{sc_track_number_padded}"
track_total: "{sc_track_total}"
track_year: "{sc_track_year}"

View file

@ -1,60 +0,0 @@
# Extracts audio from YouTube videos, converts it to mp3, and adds audio tags to it.
configuration:
working_directory: '.ytdl-sub-downloads'
presets:
song:
download:
download_strategy: "url"
url: "{url}"
output_options:
output_directory: "{music_directory}"
file_name: "{custom_track_name_sanitized}.{ext}"
audio_extract:
codec: "mp3"
quality: 128
music_tags:
embed_thumbnail: False # Set to True to embed album art
tags:
artist: "{custom_artist_name}"
artists: "{custom_artist_name}"
albumartist: "{custom_artist_name}"
albumartists: "{custom_artist_name}"
title: "{custom_track_name}"
album: "{custom_album_name}"
track: "{custom_track_number}"
year: "{upload_year}"
genre: "Unset"
overrides:
music_directory: "/path/to/music"
custom_track_name: "{title}"
custom_album_name: "Singles"
custom_artist_name: "{channel}"
custom_track_number: "1"
# TODO: make a playlist of individual songs into an album. Need playlist_title
song_playlist:
preset: "song"
overrides:
custom_track_number: "{playlist_index}"
album_from_chapters:
preset: "song"
output_options:
file_name: "{custom_album_name_sanitized}/{chapter_index_padded} - {custom_track_name_sanitized}.{ext}"
thumbnail_name: "{custom_album_name_sanitized}/folder.{thumbnail_ext}"
chapters:
embed_chapters: True
split_by_chapters:
when_no_chapters: "pass"
overrides:
custom_track_name: "{chapter_title}"
custom_album_name: "{title}" # Have the video name be the album
custom_track_number: "{chapter_index}"

View file

@ -0,0 +1,138 @@
# 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 the GameChops Albums' playlist. Each video in the playlist is an album with
# chapters representing songs.
emily_hopkins:
preset: "albums_from_playlists"
regex:
from:
title:
match:
- "^Emily Hopkins - (.*)" # Captures 'title' from 'Emily Hopkins - title'
capture_group_names:
- "captured_track_title"
capture_group_defaults:
- "{title}"
# Explicitly set the URL, track artist, and genre.
# Override various track properties using the regex variables we extracted.
overrides:
url: "https://emilyharpist.bandcamp.com/"
track_artist: "Emily Hopkins"
track_genre: "Lofi"
track_title: "{captured_track_title}"
####################################################################################################
# SOUNDCLOUD - DISCOGRAPHY
# See https://soundcloud.com/jessebannon
#
# Downloads my acoustic 'album' and various tracks from SoundCloud using the soundcloud
# discography preset. I'm not very good so keep your expectations low :-)
jmbannon:
# Inherit soundcloud_discography preset
preset: "soundcloud_discography"
# Explicitly set the SoundCloud artist url, track artist, and genre.
overrides:
sc_artist_url: "sc_artist_url"
track_artist: "jmbannon"
track_genre: "Acoustic"

View file

@ -1,88 +0,0 @@
# This example shows how to download and format a Soundcloud artist's
# discography with tags and album art. We will configure this to make
# the output directory formatted as:
#
# /path/to/music
# /The Be Sharps
# /[2020] My first upload
# 01 - My first upload.mp3
# folder.jpg
# /[2021] My first album
# 01 - Track one.mp3
# 02 - Track two.mp3
# folder.jpg
# /Another artist
# ...
#
configuration:
working_directory: '.ytdl-sub-downloads'
presets:
soundcloud_discography:
# 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: "{artist_url}/tracks"
variables:
track_number: "1"
track_number_padded: "01"
track_count: "1"
album: "{title}"
album_sanitized: "{title_sanitized}"
album_year: "{upload_year}"
# Set the second URL to the artist's albums. If a track belongs 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: "{artist_url}/albums"
variables:
track_number: "{playlist_index}"
track_number_padded: "{playlist_index_padded}"
track_count: "{playlist_count}"
album: "{playlist_title}"
album_sanitized: "{playlist_title_sanitized}"
album_year: "{playlist_max_upload_year}"
# For advanced YTDL users only; set any YTDL parameter here.
# Let us set the format to download the best mp3.
ytdl_options:
format: 'bestaudio[ext=mp3]'
# For each song downloaded, set the file and thumbnail name here.
# The output directory stores all artists in a shared {music_directory}.
# We store the audio file in its respective {album_directory_name} folder
# with the track number and title. The (thumbnail) album art is stored
# in the album folder.
#
# Set maintain_download_archive=True. This will tell YTDL not to
# re-download them on a successive invocation.
output_options:
output_directory: "{music_directory}"
file_name: "{album_path}/{track_file_name}.{ext}"
thumbnail_name: "{album_path}/folder.{thumbnail_ext}"
maintain_download_archive: True
# For each song downloaded, populate the audio file with music tags.
# Tagging should work with most audio file formats. See
# https://ytdl-sub.readthedocs.io/en/latest/config.html#music-tags
# for more details.
music_tags:
tags:
artist: "{artist}"
albumartist: "{artist}"
title: "{title}"
album: "{album}"
track: "{track_number}"
year: "{album_year}"
genre: "Unset"
# Overrides is a section where we can define our own variables, and use them in
# any other section. We define our music directory and album directory names here,
# which gets reused above for the audio file name and album art path.
overrides:
album_directory_name: "[{album_year}] {album_sanitized}"
track_file_name: "{track_number_padded} - {title_sanitized}"
album_path: "{artist_sanitized}/{album_directory_name}"
music_directory: "/path/to/music"

View file

@ -1,204 +0,0 @@
from typing import Any
from typing import Optional
from urllib.parse import parse_qs
from urllib.parse import urlparse
from ytdl_sub.validators.validators import StringValidator
class YoutubeVideoUrlValidator(StringValidator):
_expected_value_type_name = "Youtube video url"
@classmethod
def _get_video_id(cls, url: str) -> Optional[str]:
"""
Examples:
https://youtu.be/SA2iWivDJiE
https://www.youtube.com/watch?v=_oPAwA_Udwc&feature=feedu
https://www.youtube.com/embed/SA2iWivDJiE
https://www.youtube.com/v/SA2iWivDJiE?version=3&hl=en_US
https://www.youtube.com/shorts/ucYmEqmlhFw
Returns
-------
The video id if it is parsed correctly. None if parsing fails
"""
# If the url doesn't contain youtube or youtu.be, assume it is invalid
if "youtube.com" not in url and "youtu.be" not in url:
return None
# If https:// is not present, urlparse will not work
if not url.startswith("https://"):
url = f"https://{url}"
query = urlparse(url)
if query.hostname in ("youtu.be", "www.youtu.be"):
return query.path[1:]
if query.hostname in ("youtube.com", "www.youtube.com"):
if query.path == "/watch":
parsed_q = parse_qs(query.query)
if "v" in parsed_q:
return parsed_q["v"][0]
if query.path.startswith(("/embed/", "/v/", "/shorts/")):
return query.path.split("/")[2]
return None
def __init__(self, name: str, value: Any):
super().__init__(name, value)
self._video_id = self._get_video_id(value)
if not self._video_id:
raise self._validation_exception(f"'{value}' is not a valid Youtube video url.")
@property
def video_url(self) -> str:
"""
Returns
-------
Full video URL
"""
return f"https://youtube.com/watch?v={self._video_id}"
class YoutubePlaylistUrlValidator(StringValidator):
_expected_value_type_name = "Youtube playlist url"
@classmethod
def _get_playlist_id(cls, url: str) -> Optional[str]:
"""
Examples:
- https://www.youtube.com/playlist?list=PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc
"""
# If the url doesn't contain youtube, assume it is invalid
if "youtube.com" not in url:
return None
# If https:// is not present, urlparse will not work
if not url.startswith("https://"):
url = f"https://{url}"
query = urlparse(url)
if query.hostname in ("youtube.com", "www.youtube.com"):
if query.path == "/playlist":
parsed_q = parse_qs(query.query)
if "list" in parsed_q:
return parsed_q["list"][0]
return None
def __init__(self, name: str, value: Any):
super().__init__(name, value)
self._playlist_id = self._get_playlist_id(value)
if not self._playlist_id:
raise self._validation_exception(f"'{value}' is not a valid Youtube playlist url.")
@property
def playlist_url(self) -> str:
"""
Returns
-------
Full playlist URL
"""
return f"https://youtube.com/playlist?list={self._playlist_id}"
class YoutubeChannelUrlValidator(StringValidator):
_expected_value_type_name = "Youtube channel url"
@classmethod
def _get_channel_url(cls, url: str) -> Optional[str]:
"""
Examples:
- https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw
- https://www.youtube.com/user/username
- https://www.youtube.com/c/channel_name
- https://youtube.com/channel_name
"""
# If the url doesn't contain youtube, assume it is invalid
if "youtube.com" not in url:
return None
# If https:// is not present, urlparse will not work
if not url.startswith("https://"):
url = f"https://{url}"
query = urlparse(url)
if query.hostname in ("youtube.com", "www.youtube.com"):
query_path_split = query.path.split("/")
if any(query.path.startswith(qpath) for qpath in ("/channel/", "/user/", "/c/")):
# Ensure there is "/path/id".split('/') = ['', 'path', 'id'] at least three
if len(query_path_split) < 3 or len(query_path_split[2]) == 0:
return None
return f"https://youtube.com{query.path}"
if len(query_path_split) == 2 and len(query_path_split[1]) > 0:
# For channels that do not feature a 'c' or 'channel'
# Ensure length of channel string is at least one
return f"https://youtube.com{query.path}"
return None
def __init__(self, name: str, value: Any):
super().__init__(name, value)
self._channel_url = self._get_channel_url(value)
if not self._channel_url:
raise self._validation_exception(f"'{value}' is not a valid Youtube channel url.")
@property
def channel_url(self) -> str:
"""
Returns
-------
Full channel URL
"""
return self._channel_url
class SoundcloudUsernameUrlValidator(StringValidator):
_expected_value_type_name = "Soundcloud username url"
@classmethod
def _get_channel_url(cls, url: str) -> Optional[str]:
"""
Examples:
- https://www.soundcloud.com/artist_name
"""
# If the url doesn't contain soundcloud, assume it is invalid
if "soundcloud.com" not in url:
return None
# If https:// is not present, urlparse will not work
if not url.startswith("https://"):
url = f"https://{url}"
query = urlparse(url)
if query.hostname in ("soundcloud.com", "www.soundcloud.com"):
if len(query.path) > 2: # /artist_name
username = query.path[1:].split("/")[0] # strip extra paths or slashes
username = username.split("?")[0] # strip extra arguments
return f"https://soundcloud.com/{username}"
return None
def __init__(self, name: str, value: Any):
super().__init__(name, value)
self._username_url = self._get_channel_url(value)
if not self._username_url:
raise self._validation_exception(f"'{value}' is not a valid Soundcloud username url.")
@property
def username_url(self) -> str:
"""
Returns
-------
Full artist URL
"""
return self._username_url

View file

View file

@ -0,0 +1,61 @@
import pytest
from expected_download import assert_expected_downloads
from expected_transaction_log import assert_transaction_log_matches
from ytdl_sub.subscriptions.subscription import Subscription
@pytest.fixture
def subscription_dict(output_directory):
return {
"preset": "albums_from_playlists",
"regex": {
"skip_if_match_fails": False, # Error if regex match fails
"from": {
"title": {
"match": ["^(.*) - (.*)"], # Captures 'title' from 'Emily Hopkins - title'
"capture_group_names": [
"captured_track_artist",
"captured_track_title",
],
}
},
},
"ytdl_options": {
"max_downloads": 15,
},
"date_range": {"before": "20230101"},
"overrides": {
"url": "https://funkypselicave.bandcamp.com/",
"track_title": "{captured_track_title}",
"track_artist": "{captured_track_artist}",
"music_directory": output_directory,
},
}
class TestBandcamp:
@pytest.mark.parametrize("dry_run", [True, False])
def test_download_artist_url(
self,
subscription_dict,
music_audio_config,
output_directory,
dry_run,
):
discography_subscription = Subscription.from_dict(
preset_dict=subscription_dict,
preset_name="jb",
config=music_audio_config,
)
transaction_log = discography_subscription.download(dry_run=dry_run)
assert_transaction_log_matches(
output_directory=output_directory,
transaction_log=transaction_log,
transaction_log_summary_file_name="bandcamp/test_artist_url.txt",
)
assert_expected_downloads(
output_directory=output_directory,
dry_run=dry_run,
expected_download_summary_file_name="bandcamp/test_artist_url.json",
)

View file

@ -79,18 +79,10 @@ def channel_as_tv_show_config(working_directory) -> ConfigFile:
)
@pytest.fixture
def soundcloud_discography_config(working_directory) -> ConfigFile:
return _load_config(
config_path="examples/soundcloud_discography_config.yaml",
working_directory=working_directory,
)
@pytest.fixture()
def youtube_audio_config(working_directory) -> ConfigFile:
def music_audio_config(working_directory) -> ConfigFile:
return _load_config(
config_path="examples/music_audio_from_videos.yaml", working_directory=working_directory
config_path="examples/music_audio_config.yaml", working_directory=working_directory
)

View file

@ -8,9 +8,7 @@ from ytdl_sub.subscriptions.subscription import Subscription
@pytest.fixture
def single_song_preset_dict(output_directory):
return {
"preset": "song",
"download": {"url": "https://www.youtube.com/watch?v=2lAe1cqCOXo"},
"output_options": {"output_directory": output_directory},
"preset": "single",
# test multi-tags
"music_tags": {"embed_thumbnail": True, "tags": {"genres": ["multi_tag_1", "multi_tag_2"]}},
# download the worst format so it is fast
@ -18,21 +16,27 @@ def single_song_preset_dict(output_directory):
"format": "worst[ext=mp4]",
"postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility
},
"overrides": {
"url": "https://www.youtube.com/watch?v=2lAe1cqCOXo",
"music_directory": output_directory,
},
}
@pytest.fixture
def multiple_songs_preset_dict(output_directory):
return {
"preset": "song_playlist",
"download": {"url": "https://youtube.com/playlist?list=PL5BC0FC26BECA5A35"},
"output_options": {"output_directory": output_directory},
"preset": "albums_from_playlists",
"audio_extract": {"codec": "vorbis", "quality": 140},
# download the worst format so it is fast
"ytdl_options": {
"format": "worst[ext=mp4]",
"postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility
},
"overrides": {
"url": "https://youtube.com/playlist?list=PL5BC0FC26BECA5A35",
"music_directory": output_directory,
},
}
@ -40,13 +44,13 @@ class TestAudioExtract:
@pytest.mark.parametrize("dry_run", [True, False])
def test_audio_extract_single_song(
self,
youtube_audio_config,
music_audio_config,
single_song_preset_dict,
output_directory,
dry_run,
):
subscription = Subscription.from_dict(
config=youtube_audio_config,
config=music_audio_config,
preset_name="single_song_test",
preset_dict=single_song_preset_dict,
)
@ -66,13 +70,13 @@ class TestAudioExtract:
@pytest.mark.parametrize("dry_run", [True, False])
def test_audio_extract_multiple_songs(
self,
youtube_audio_config,
music_audio_config,
multiple_songs_preset_dict,
output_directory,
dry_run,
):
subscription = Subscription.from_dict(
config=youtube_audio_config,
config=music_audio_config,
preset_name="multiple_songs_test",
preset_dict=multiple_songs_preset_dict,
)

View file

@ -29,12 +29,12 @@ def single_song_video_dict(output_directory):
class TestMusicTags:
def test_music_tags_errors_on_video(
self,
youtube_audio_config,
music_audio_config,
single_song_video_dict,
output_directory,
):
subscription = Subscription.from_dict(
config=youtube_audio_config,
config=music_audio_config,
preset_name="single_song_test",
preset_dict=single_song_video_dict,
)

View file

@ -12,15 +12,16 @@ from ytdl_sub.utils.exceptions import ValidationException
@pytest.fixture
def yt_album_as_chapters_preset_dict(output_directory):
return {
"preset": "album_from_chapters",
"download": {"url": "https://www.youtube.com/watch?v=zeR2_YjlXWA"},
# override the output directory with our fixture-generated dir
"output_options": {"output_directory": output_directory, "maintain_download_archive": True},
"preset": "albums_from_chapters",
# download the worst format so it is fast
"ytdl_options": {
"format": "worst[ext=mp4]",
"postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility
},
"overrides": {
"url": "https://www.youtube.com/watch?v=zeR2_YjlXWA",
"music_directory": output_directory,
},
}
@ -33,7 +34,7 @@ def yt_album_as_chapters_with_regex_preset_dict(yt_album_as_chapters_preset_dict
"from": {
"chapter_title": {
"match": r"\d+\. (.+)",
"capture_group_names": "captured_chapter_title",
"capture_group_names": "captured_track_title",
"capture_group_defaults": "{chapter_title}",
},
"title": {
@ -42,8 +43,8 @@ def yt_album_as_chapters_with_regex_preset_dict(yt_album_as_chapters_preset_dict
"(.+) - (.+)",
],
"capture_group_names": [
"captured_artist",
"captured_album",
"captured_track_artist",
"captured_track_album",
],
"capture_group_defaults": [
"{channel}",
@ -53,9 +54,9 @@ def yt_album_as_chapters_with_regex_preset_dict(yt_album_as_chapters_preset_dict
}
},
"overrides": {
"custom_track_name": "{captured_chapter_title}",
"custom_album_name": "{captured_album}",
"custom_artist_name": "{captured_artist}",
"track_title": "{captured_track_title}",
"track_album": "{captured_track_album}",
"track_artist": "{captured_track_artist}",
},
},
)
@ -66,13 +67,13 @@ class TestSplitByChapters:
@pytest.mark.parametrize("dry_run", [True, False])
def test_video_with_chapters(
self,
youtube_audio_config,
music_audio_config,
yt_album_as_chapters_preset_dict,
output_directory,
dry_run,
):
subscription = Subscription.from_dict(
config=youtube_audio_config,
config=music_audio_config,
preset_name="split_by_chapters_video",
preset_dict=yt_album_as_chapters_preset_dict,
)
@ -96,13 +97,13 @@ class TestSplitByChapters:
@pytest.mark.parametrize("dry_run", [True, False])
def test_video_with_chapters_and_regex(
self,
youtube_audio_config,
music_audio_config,
yt_album_as_chapters_with_regex_preset_dict,
output_directory,
dry_run,
):
subscription = Subscription.from_dict(
config=youtube_audio_config,
config=music_audio_config,
preset_name="split_by_chapters_with_regex_video",
preset_dict=yt_album_as_chapters_with_regex_preset_dict,
)
@ -123,7 +124,7 @@ class TestSplitByChapters:
@pytest.mark.parametrize("when_no_chapters", ["pass", "drop", "error"])
def test_video_with_no_chapters_and_regex(
self,
youtube_audio_config,
music_audio_config,
yt_album_as_chapters_with_regex_preset_dict,
output_directory,
dry_run,
@ -138,7 +139,7 @@ class TestSplitByChapters:
)
subscription = Subscription.from_dict(
config=youtube_audio_config,
config=music_audio_config,
preset_name="split_by_chapters_with_regex_video",
preset_dict=yt_album_as_chapters_with_regex_preset_dict,
)

View file

@ -14,8 +14,8 @@ def subscription_dict(output_directory):
"format": "worst[ext=mp3]",
},
"overrides": {
"artist": "j_b",
"artist_url": "https://soundcloud.com/jessebannon",
"track_artist": "j_b",
"sc_artist_url": "https://soundcloud.com/jessebannon",
"music_directory": output_directory,
},
}
@ -31,14 +31,14 @@ class TestSoundcloudDiscography:
def test_discography_download(
self,
subscription_dict,
soundcloud_discography_config,
music_audio_config,
output_directory,
dry_run,
):
discography_subscription = Subscription.from_dict(
preset_dict=subscription_dict,
preset_name="jb",
config=soundcloud_discography_config,
config=music_audio_config,
)
transaction_log = discography_subscription.download(dry_run=dry_run)
assert_transaction_log_matches(

View file

@ -0,0 +1,19 @@
{
".ytdl-sub-jb-download-archive.json": "9f5ca17dc0d842ac4c296054c0011ace",
"El Jazzy Chavo/[2022] S950 Funk/01 - Spark it.mp3": "6f21b6f977609382fa9b9fa9817b28cc",
"El Jazzy Chavo/[2022] S950 Funk/02 - Astronomikal Funk.mp3": "870199f5e75ea170051122f7220e2f42",
"El Jazzy Chavo/[2022] S950 Funk/03 - Impulse.mp3": "3a14e5e034016ad131186caf94be00da",
"El Jazzy Chavo/[2022] S950 Funk/04 - September.mp3": "c58520ef3f7f8944151ee0fb95fb0ac5",
"El Jazzy Chavo/[2022] S950 Funk/05 - Interlune.mp3": "5a7365a253ac4a5af54e550508a40b66",
"El Jazzy Chavo/[2022] S950 Funk/06 - Ninjutsu Techniques.mp3": "07b3f74ef78cb0c869c86dded054b1e9",
"El Jazzy Chavo/[2022] S950 Funk/07 - Space Funk Flow.mp3": "fef74e222258c4845e8b51e05acd240f",
"El Jazzy Chavo/[2022] S950 Funk/08 - Cellar Groove.mp3": "743927c47df60e811d367f5ef969faaf",
"El Jazzy Chavo/[2022] S950 Funk/09 - Solar Wind.mp3": "dd97643e3dc5decefb543da3a6e31356",
"El Jazzy Chavo/[2022] S950 Funk/10 - Interlune II.mp3": "37717cbd8f837657047616743937595b",
"El Jazzy Chavo/[2022] S950 Funk/11 - Ghetto Anthem.mp3": "54089f39836d469f391f6850926a392d",
"El Jazzy Chavo/[2022] S950 Funk/12 - Street Degree.mp3": "ddd3dc74d9bc07b988e4e4da363624dd",
"El Jazzy Chavo/[2022] S950 Funk/13 - Trouble World.mp3": "90dacf561b52852312f9e3f06084bfca",
"El Jazzy Chavo/[2022] S950 Funk/14 - Relaxation.mp3": "12dc503e0f758ae0b962e941727f272b",
"El Jazzy Chavo/[2022] S950 Funk/15 - Journey From Within.mp3": "c593e610ac6853b3795781b6650fc59e",
"El Jazzy Chavo/[2022] S950 Funk/folder.jpg": "62e51365dd309e76a6323f927f6fcc94"
}

View file

@ -1,15 +1,15 @@
{
".ytdl-sub-split_by_chapters_video-download-archive.json": "7001417f7a398959f3296ece81575a77",
"Alfa Mist - Nocturne [Full Album]/01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3": "87d036987c4903e62e4f5001ea38a49a",
"Alfa Mist - Nocturne [Full Album]/02 - 02. Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3": "96975f139dcc87a05dec03ab4f839d94",
"Alfa Mist - Nocturne [Full Album]/03 - 03. Blaze (Feat. Kaya Thomas - Dyke).mp3": "58df7bb835d05e3cb0e28abb4c784a5e",
"Alfa Mist - Nocturne [Full Album]/04 - 04. What If (Interlude).mp3": "d8313eb888dc3c8109623c84139280e7",
"Alfa Mist - Nocturne [Full Album]/05 - 05. No Peace (Feat. Tom Misch).mp3": "4c6ee32b371e6e5374c722f4c854a965",
"Alfa Mist - Nocturne [Full Album]/06 - 06. Closer (Feat. Lester Duval).mp3": "d54280bca884ddc1a0614b00c2d70ea3",
"Alfa Mist - Nocturne [Full Album]/07 - 07. Delusions Rumination (Interlude) (Feat. Racheal Ofori).mp3": "61943dfb29ca40069969790773bf3cd9",
"Alfa Mist - Nocturne [Full Album]/08 - 08. Dreams (Feat. Carmody).mp3": "c37001fb9f3c0cca1bffdf3b2ae4a0fc",
"Alfa Mist - Nocturne [Full Album]/09 - 09. Dreaming (Interlude) (Feat. Racheal Ofori).mp3": "5334aa0af6ce2ec1283806cf7d9a15c1",
"Alfa Mist - Nocturne [Full Album]/10 - 10. Hopeful (Feat. Jordan Rakei).mp3": "526d70f88ab03b972c06243f164d4b0e",
"Alfa Mist - Nocturne [Full Album]/11 - 11. Sunrise (Pillows) (Feat. Emmavie).mp3": "8376927e5cecf6bed63f016649b77354",
"Alfa Mist - Nocturne [Full Album]/folder.jpg": "bd3685acc53072e591bae2505ecb0648"
".ytdl-sub-split_by_chapters_video-download-archive.json": "5e7a31ec4a73e71696f8f3ba9eab9303",
"Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3": "29d09da874133ce5c5f7459c2fa6cd85",
"Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/02 - 02. Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3": "d5432e6a4f7af9810b0e7c8eebe4898a",
"Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/03 - 03. Blaze (Feat. Kaya Thomas - Dyke).mp3": "cf03da6688a73373f9295dc595156e11",
"Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/04 - 04. What If (Interlude).mp3": "b7b943b6f3395c05433b8532364d63d6",
"Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/05 - 05. No Peace (Feat. Tom Misch).mp3": "0d9719268900d4abcd8c0f51ad3af92c",
"Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/06 - 06. Closer (Feat. Lester Duval).mp3": "bbd9ec616a0f7d3c5d13c04bb118681e",
"Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/07 - 07. Delusions: Rumination (Interlude) (Feat. Racheal Ofori).mp3": "2e59ecdc0f8050bcf190a7898d7ae968",
"Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/08 - 08. Dreams (Feat. Carmody).mp3": "e58966f3326b876f0ab97459b681f76f",
"Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/09 - 09. Dreaming (Interlude) (Feat. Racheal Ofori).mp3": "d6939215b73457fce4e026f8c9b57ecc",
"Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/10 - 10. Hopeful (Feat. Jordan Rakei).mp3": "82d0e7d8070fd15d71c2e11c0285d426",
"Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/11 - 11. Sunrise (Pillows) (Feat. Emmavie).mp3": "3edb11e8cd5f270dd42ee62d9a9aa4ff",
"Proved Records/[2017] Alfa Mist - Nocturne [Full Album]/folder.jpg": "bd3685acc53072e591bae2505ecb0648"
}

View file

@ -1,5 +1,5 @@
{
".ytdl-sub-split_by_chapters_with_regex_video-download-archive.json": "11367ac13068646e35a53d25deeba834",
"Oblivion Mod Falcor p.1/01 - Oblivion Mod Falcor p.1.mp3": "dfcf5aed1742bd55e562a0d93e555f01",
"Oblivion Mod Falcor p.1/folder.jpg": "fb95b510681676e81c321171fc23143e"
".ytdl-sub-split_by_chapters_with_regex_video-download-archive.json": "ed212171889707bf65462878248fc0b8",
"Project Zombie/[2010] Oblivion Mod \"Falcor\" p.1/01 - Oblivion Mod \"Falcor\" p.1.mp3": "a3c01f164eeca4541aeed49264d2fc8c",
"Project Zombie/[2010] Oblivion Mod \"Falcor\" p.1/folder.jpg": "fb95b510681676e81c321171fc23143e"
}

View file

@ -1,15 +1,15 @@
{
".ytdl-sub-split_by_chapters_with_regex_video-download-archive.json": "5f281991d441f406b0d721b250e74b79",
"Nocturne/01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3": "1f51d6809509904b51ad8930d9bb49b0",
"Nocturne/02 - Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3": "16ba92db30c7199373855d0ed6d2cdde",
"Nocturne/03 - Blaze (Feat. Kaya Thomas - Dyke).mp3": "21af1894554dc61f437b191a6702c274",
"Nocturne/04 - What If (Interlude).mp3": "b6cab2cfcbcb3807eb8176281960e9be",
"Nocturne/05 - No Peace (Feat. Tom Misch).mp3": "56ae7656dc6edca4e55e0afc9422002a",
"Nocturne/06 - Closer (Feat. Lester Duval).mp3": "93e7025813924670595032c3a2038d94",
"Nocturne/07 - Delusions Rumination (Interlude) (Feat. Racheal Ofori).mp3": "b757d50d7ad154fe36d13ae72a05a744",
"Nocturne/08 - Dreams (Feat. Carmody).mp3": "de1e9313623368a9c7e63a08d77ca54b",
"Nocturne/09 - Dreaming (Interlude) (Feat. Racheal Ofori).mp3": "264e0a6c3e572e05daffc38bf8178226",
"Nocturne/10 - Hopeful (Feat. Jordan Rakei).mp3": "e72408d03604ff928acf6ce4b383895c",
"Nocturne/11 - Sunrise (Pillows) (Feat. Emmavie).mp3": "146d981480be3bf28726a27443c1695a",
"Nocturne/folder.jpg": "bd3685acc53072e591bae2505ecb0648"
".ytdl-sub-split_by_chapters_with_regex_video-download-archive.json": "cb82ae5ed9d7a41aea15446254c93738",
"Alfa Mist/[2017] Nocturne/01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3": "7be57c4dde9ba2c3fa72e9cc65b0f586",
"Alfa Mist/[2017] Nocturne/02 - Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3": "5ee032da9965c51913fcfa0319d061bd",
"Alfa Mist/[2017] Nocturne/03 - Blaze (Feat. Kaya Thomas - Dyke).mp3": "82c1f35bdccfb4ec146f33661ac94d6b",
"Alfa Mist/[2017] Nocturne/04 - What If (Interlude).mp3": "040b38c249e478d8832dcea8bfeca17f",
"Alfa Mist/[2017] Nocturne/05 - No Peace (Feat. Tom Misch).mp3": "06f7e57fecdc7b4d2e37c7652791ce19",
"Alfa Mist/[2017] Nocturne/06 - Closer (Feat. Lester Duval).mp3": "91a03449c33bf9dcff5a9654a8525626",
"Alfa Mist/[2017] Nocturne/07 - Delusions: Rumination (Interlude) (Feat. Racheal Ofori).mp3": "54c26621b8d4e74f37217c836479a077",
"Alfa Mist/[2017] Nocturne/08 - Dreams (Feat. Carmody).mp3": "2704327ac5998086e77a77da164e2afd",
"Alfa Mist/[2017] Nocturne/09 - Dreaming (Interlude) (Feat. Racheal Ofori).mp3": "75b8a26d3099aa2d9ba488b33c4eb1e7",
"Alfa Mist/[2017] Nocturne/10 - Hopeful (Feat. Jordan Rakei).mp3": "0bf0979c99c55ef986efaba55c0dc858",
"Alfa Mist/[2017] Nocturne/11 - Sunrise (Pillows) (Feat. Emmavie).mp3": "78950fbfe459de8e9aa951ab6fa153bf",
"Alfa Mist/[2017] Nocturne/folder.jpg": "bd3685acc53072e591bae2505ecb0648"
}

View file

@ -1,5 +1,7 @@
{
"Jesse's Minecraft Server [Trailer - Feb.1].ogg": "e0ab90ea97f26738195111de2fbf0f5f",
"Jesse's Minecraft Server [Trailer - Feb.27].ogg": "814bdd627fbd4b55017341ffdec9da9d",
"Jesse's Minecraft Server [Trailer - Mar.21].ogg": "90303a47a312c27cf8eed56bf09aa526"
".ytdl-sub-multiple_songs_test-download-archive.json": "54237df5e00d1598dfd39f341ee03d75",
"Project Zombie/[2011] Jesse's Minecraft Server/01 - Jesse's Minecraft Server [Trailer - Mar.21].ogg": "5657c5b92f8980b20d8bbee0fdc7e5d8",
"Project Zombie/[2011] Jesse's Minecraft Server/02 - Jesse's Minecraft Server [Trailer - Feb.27].ogg": "a2a3a34e02e26a6c0265530d4499473b",
"Project Zombie/[2011] Jesse's Minecraft Server/03 - Jesse's Minecraft Server [Trailer - Feb.1].ogg": "b2d6388b4ddf8e3fbca042cb123672c3",
"Project Zombie/[2011] Jesse's Minecraft Server/folder.jpg": "e7830aa8a64b0cde65ba3f7e5fc56530"
}

View file

@ -1,3 +1,5 @@
{
"YouTube Rewind 2019 For the Record #YouTubeRewind.mp3": "05bd1d218f5a0c942ddb1448d939a1dc"
".ytdl-sub-single_song_test-download-archive.json": "22c1431e35033d777a674c4802bcc786",
"YouTube/[2019] YouTube Rewind 2019: For the Record | #YouTubeRewind/01 - YouTube Rewind 2019: For the Record | #YouTubeRewind.mp3": "7affc0ecf01f36de9cee1a7aafd776eb",
"YouTube/[2019] YouTube Rewind 2019: For the Record | #YouTubeRewind/folder.jpg": "50ee47c80f679029f5d3503bb91b045a"
}

View file

@ -1,19 +1,19 @@
{
".ytdl-sub-jb-download-archive.json": "1a99156e9ece62539fb2608416a07200",
"j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.mp3": "bffbd558e12c6a9e029dc136a88342c4",
"j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.mp3": "a8955bccae34c39e64d70a021c95e6d4",
"j_b/[2021] Baby Santana's Dorian Groove/folder.jpg": "967892be44b8c47e1be73f055a7c6f08",
"j_b/[2021] Purple Clouds/01 - Purple Clouds.mp3": "038db58aebe2ba875b733932b42a94d6",
"j_b/[2021] Purple Clouds/01 - Purple Clouds.mp3": "ec1d40fee597da35f5dc0126438efe54",
"j_b/[2021] Purple Clouds/folder.jpg": "967892be44b8c47e1be73f055a7c6f08",
"j_b/[2022] Acoustic Treats/01 - 20160426 184214.mp3": "e145f0a2f6012768280c38655ca58065",
"j_b/[2022] Acoustic Treats/02 - 20160502 123150.mp3": "60c8b8817a197a13e4bb90903af612c5",
"j_b/[2022] Acoustic Treats/03 - 20160504 143832.mp3": "8265b7e4f79878af877bc6ecd9757efe",
"j_b/[2022] Acoustic Treats/04 - 20160601 221234.mp3": "accf46b76891d2954b893d0f91d82816",
"j_b/[2022] Acoustic Treats/05 - 20160601 222440.mp3": "e1f584f523336160d5c1104a61de77f3",
"j_b/[2022] Acoustic Treats/06 - 20170604 190236.mp3": "f6885b25901177f0357649afe97328cc",
"j_b/[2022] Acoustic Treats/07 - 20170612 193646.mp3": "fa057f221cbe4cf2442cd2fdb960743e",
"j_b/[2022] Acoustic Treats/08 - 20170628 215206.mp3": "7794ae812c64580e2ac8fc457d5cc85f",
"j_b/[2022] Acoustic Treats/09 - Finding Home.mp3": "adbf02eddb2090c008eb497d13ff84b9",
"j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.mp3": "65bb10c84366c71498161734f953e93d",
"j_b/[2022] Acoustic Treats/11 - Untold History.mp3": "6904b2918e5dc38d9a9f72d967eb74bf",
"j_b/[2022] Acoustic Treats/01 - 20160426 184214.mp3": "768e148a2b24ed2de299ca4899d8e533",
"j_b/[2022] Acoustic Treats/02 - 20160502 123150.mp3": "a9cd2d2176f94fdad8965c1fbbc3396a",
"j_b/[2022] Acoustic Treats/03 - 20160504 143832.mp3": "f3c74e7e8595505d15a384226d0c906e",
"j_b/[2022] Acoustic Treats/04 - 20160601 221234.mp3": "d13a3008d9a39da3e5fdcd0c279718e8",
"j_b/[2022] Acoustic Treats/05 - 20160601 222440.mp3": "3a40d1108c4f6a0d004eea2151001d66",
"j_b/[2022] Acoustic Treats/06 - 20170604 190236.mp3": "8224406bb95e100f4ebcdf7fec3db1c0",
"j_b/[2022] Acoustic Treats/07 - 20170612 193646.mp3": "1ea96a8581eb81e45564617f75bd467e",
"j_b/[2022] Acoustic Treats/08 - 20170628 215206.mp3": "df14e3b41386cf408b4d1549428a17a5",
"j_b/[2022] Acoustic Treats/09 - Finding Home.mp3": "f52df647e1f5cf15df720d62b5ad64b1",
"j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.mp3": "429ac1c752822230803c1a452987e492",
"j_b/[2022] Acoustic Treats/11 - Untold History.mp3": "9322445a6a7cdd506038b8714cb1731f",
"j_b/[2022] Acoustic Treats/folder.jpg": "967892be44b8c47e1be73f055a7c6f08"
}

View file

@ -0,0 +1,186 @@
Files created:
----------------------------------------
{output_directory}
.ytdl-sub-jb-download-archive.json
{output_directory}/El Jazzy Chavo/[2022] S950 Funk
01 - Spark it.mp3
Music Tags:
album: S950 Funk
albumartist: El Jazzy Chavo
albumartists: El Jazzy Chavo
artist: El Jazzy Chavo
artists: El Jazzy Chavo
genre: Unset
title: Spark it
track: 1
tracktotal: 15
year: 2022
02 - Astronomikal Funk.mp3
Music Tags:
album: S950 Funk
albumartist: El Jazzy Chavo
albumartists: El Jazzy Chavo
artist: El Jazzy Chavo
artists: El Jazzy Chavo
genre: Unset
title: Astronomikal Funk
track: 2
tracktotal: 15
year: 2022
03 - Impulse.mp3
Music Tags:
album: S950 Funk
albumartist: El Jazzy Chavo
albumartists: El Jazzy Chavo
artist: El Jazzy Chavo
artists: El Jazzy Chavo
genre: Unset
title: Impulse
track: 3
tracktotal: 15
year: 2022
04 - September.mp3
Music Tags:
album: S950 Funk
albumartist: El Jazzy Chavo
albumartists: El Jazzy Chavo
artist: El Jazzy Chavo
artists: El Jazzy Chavo
genre: Unset
title: September
track: 4
tracktotal: 15
year: 2022
05 - Interlune.mp3
Music Tags:
album: S950 Funk
albumartist: El Jazzy Chavo
albumartists: El Jazzy Chavo
artist: El Jazzy Chavo
artists: El Jazzy Chavo
genre: Unset
title: Interlune
track: 5
tracktotal: 15
year: 2022
06 - Ninjutsu Techniques.mp3
Music Tags:
album: S950 Funk
albumartist: El Jazzy Chavo
albumartists: El Jazzy Chavo
artist: El Jazzy Chavo
artists: El Jazzy Chavo
genre: Unset
title: Ninjutsu Techniques
track: 6
tracktotal: 15
year: 2022
07 - Space Funk Flow.mp3
Music Tags:
album: S950 Funk
albumartist: El Jazzy Chavo
albumartists: El Jazzy Chavo
artist: El Jazzy Chavo
artists: El Jazzy Chavo
genre: Unset
title: Space Funk Flow
track: 7
tracktotal: 15
year: 2022
08 - Cellar Groove.mp3
Music Tags:
album: S950 Funk
albumartist: El Jazzy Chavo
albumartists: El Jazzy Chavo
artist: El Jazzy Chavo
artists: El Jazzy Chavo
genre: Unset
title: Cellar Groove
track: 8
tracktotal: 15
year: 2022
09 - Solar Wind.mp3
Music Tags:
album: S950 Funk
albumartist: El Jazzy Chavo
albumartists: El Jazzy Chavo
artist: El Jazzy Chavo
artists: El Jazzy Chavo
genre: Unset
title: Solar Wind
track: 9
tracktotal: 15
year: 2022
10 - Interlune II.mp3
Music Tags:
album: S950 Funk
albumartist: El Jazzy Chavo
albumartists: El Jazzy Chavo
artist: El Jazzy Chavo
artists: El Jazzy Chavo
genre: Unset
title: Interlune II
track: 10
tracktotal: 15
year: 2022
11 - Ghetto Anthem.mp3
Music Tags:
album: S950 Funk
albumartist: El Jazzy Chavo
albumartists: El Jazzy Chavo
artist: El Jazzy Chavo
artists: El Jazzy Chavo
genre: Unset
title: Ghetto Anthem
track: 11
tracktotal: 15
year: 2022
12 - Street Degree.mp3
Music Tags:
album: S950 Funk
albumartist: El Jazzy Chavo
albumartists: El Jazzy Chavo
artist: El Jazzy Chavo
artists: El Jazzy Chavo
genre: Unset
title: Street Degree
track: 12
tracktotal: 15
year: 2022
13 - Trouble World.mp3
Music Tags:
album: S950 Funk
albumartist: El Jazzy Chavo
albumartists: El Jazzy Chavo
artist: El Jazzy Chavo
artists: El Jazzy Chavo
genre: Unset
title: Trouble World
track: 13
tracktotal: 15
year: 2022
14 - Relaxation.mp3
Music Tags:
album: S950 Funk
albumartist: El Jazzy Chavo
albumartists: El Jazzy Chavo
artist: El Jazzy Chavo
artists: El Jazzy Chavo
genre: Unset
title: Relaxation
track: 14
tracktotal: 15
year: 2022
15 - Journey From Within.mp3
Music Tags:
album: S950 Funk
albumartist: El Jazzy Chavo
albumartists: El Jazzy Chavo
artist: El Jazzy Chavo
artists: El Jazzy Chavo
genre: Unset
title: Journey From Within
track: 15
tracktotal: 15
year: 2022
folder.jpg

View file

@ -2,7 +2,7 @@ Files created:
----------------------------------------
{output_directory}
.ytdl-sub-split_by_chapters_video-download-archive.json
{output_directory}/Alfa Mist - Nocturne [Full Album]
{output_directory}/Proved Records/[2017] Alfa Mist - Nocturne [Full Album]
01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3
From Chapter Split:
Warning: Dry-run assumes embedded chapters with no modifications
@ -17,6 +17,7 @@ Files created:
genre: Unset
title: 01. Intro (Feat. Racheal Ofori & Barney Artist)
track: 1
tracktotal: 11
year: 2017
02 - 02. Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3
From Chapter Split:
@ -32,6 +33,7 @@ Files created:
genre: Unset
title: 02. Answers (Feat. Rick David & Kaya Thomas - Dyke)
track: 2
tracktotal: 11
year: 2017
03 - 03. Blaze (Feat. Kaya Thomas - Dyke).mp3
From Chapter Split:
@ -47,6 +49,7 @@ Files created:
genre: Unset
title: 03. Blaze (Feat. Kaya Thomas - Dyke)
track: 3
tracktotal: 11
year: 2017
04 - 04. What If (Interlude).mp3
From Chapter Split:
@ -62,6 +65,7 @@ Files created:
genre: Unset
title: 04. What If (Interlude)
track: 4
tracktotal: 11
year: 2017
05 - 05. No Peace (Feat. Tom Misch).mp3
From Chapter Split:
@ -77,6 +81,7 @@ Files created:
genre: Unset
title: 05. No Peace (Feat. Tom Misch)
track: 5
tracktotal: 11
year: 2017
06 - 06. Closer (Feat. Lester Duval).mp3
From Chapter Split:
@ -92,8 +97,9 @@ Files created:
genre: Unset
title: 06. Closer (Feat. Lester Duval)
track: 6
tracktotal: 11
year: 2017
07 - 07. Delusions Rumination (Interlude) (Feat. Racheal Ofori).mp3
07 - 07. Delusions: Rumination (Interlude) (Feat. Racheal Ofori).mp3
From Chapter Split:
Warning: Dry-run assumes embedded chapters with no modifications
Source Title: Alfa Mist - Nocturne [Full Album]
@ -107,6 +113,7 @@ Files created:
genre: Unset
title: 07. Delusions: Rumination (Interlude) (Feat. Racheal Ofori)
track: 7
tracktotal: 11
year: 2017
08 - 08. Dreams (Feat. Carmody).mp3
From Chapter Split:
@ -122,6 +129,7 @@ Files created:
genre: Unset
title: 08. Dreams (Feat. Carmody)
track: 8
tracktotal: 11
year: 2017
09 - 09. Dreaming (Interlude) (Feat. Racheal Ofori).mp3
From Chapter Split:
@ -137,6 +145,7 @@ Files created:
genre: Unset
title: 09. Dreaming (Interlude) (Feat. Racheal Ofori)
track: 9
tracktotal: 11
year: 2017
10 - 10. Hopeful (Feat. Jordan Rakei).mp3
From Chapter Split:
@ -152,6 +161,7 @@ Files created:
genre: Unset
title: 10. Hopeful (Feat. Jordan Rakei)
track: 10
tracktotal: 11
year: 2017
11 - 11. Sunrise (Pillows) (Feat. Emmavie).mp3
From Chapter Split:
@ -167,5 +177,6 @@ Files created:
genre: Unset
title: 11. Sunrise (Pillows) (Feat. Emmavie)
track: 11
tracktotal: 11
year: 2017
folder.jpg

View file

@ -2,7 +2,7 @@ Files created:
----------------------------------------
{output_directory}
.ytdl-sub-split_by_chapters_video-download-archive.json
{output_directory}/Alfa Mist - Nocturne [Full Album]
{output_directory}/Proved Records/[2017] Alfa Mist - Nocturne [Full Album]
01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3
From Chapter Split:
Source Title: Alfa Mist - Nocturne [Full Album]
@ -16,6 +16,7 @@ Files created:
genre: Unset
title: 01. Intro (Feat. Racheal Ofori & Barney Artist)
track: 1
tracktotal: 11
year: 2017
02 - 02. Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3
From Chapter Split:
@ -30,6 +31,7 @@ Files created:
genre: Unset
title: 02. Answers (Feat. Rick David & Kaya Thomas - Dyke)
track: 2
tracktotal: 11
year: 2017
03 - 03. Blaze (Feat. Kaya Thomas - Dyke).mp3
From Chapter Split:
@ -44,6 +46,7 @@ Files created:
genre: Unset
title: 03. Blaze (Feat. Kaya Thomas - Dyke)
track: 3
tracktotal: 11
year: 2017
04 - 04. What If (Interlude).mp3
From Chapter Split:
@ -58,6 +61,7 @@ Files created:
genre: Unset
title: 04. What If (Interlude)
track: 4
tracktotal: 11
year: 2017
05 - 05. No Peace (Feat. Tom Misch).mp3
From Chapter Split:
@ -72,6 +76,7 @@ Files created:
genre: Unset
title: 05. No Peace (Feat. Tom Misch)
track: 5
tracktotal: 11
year: 2017
06 - 06. Closer (Feat. Lester Duval).mp3
From Chapter Split:
@ -86,8 +91,9 @@ Files created:
genre: Unset
title: 06. Closer (Feat. Lester Duval)
track: 6
tracktotal: 11
year: 2017
07 - 07. Delusions Rumination (Interlude) (Feat. Racheal Ofori).mp3
07 - 07. Delusions: Rumination (Interlude) (Feat. Racheal Ofori).mp3
From Chapter Split:
Source Title: Alfa Mist - Nocturne [Full Album]
Segment: 17:57 - 20:05
@ -100,6 +106,7 @@ Files created:
genre: Unset
title: 07. Delusions: Rumination (Interlude) (Feat. Racheal Ofori)
track: 7
tracktotal: 11
year: 2017
08 - 08. Dreams (Feat. Carmody).mp3
From Chapter Split:
@ -114,6 +121,7 @@ Files created:
genre: Unset
title: 08. Dreams (Feat. Carmody)
track: 8
tracktotal: 11
year: 2017
09 - 09. Dreaming (Interlude) (Feat. Racheal Ofori).mp3
From Chapter Split:
@ -128,6 +136,7 @@ Files created:
genre: Unset
title: 09. Dreaming (Interlude) (Feat. Racheal Ofori)
track: 9
tracktotal: 11
year: 2017
10 - 10. Hopeful (Feat. Jordan Rakei).mp3
From Chapter Split:
@ -142,6 +151,7 @@ Files created:
genre: Unset
title: 10. Hopeful (Feat. Jordan Rakei)
track: 10
tracktotal: 11
year: 2017
11 - 11. Sunrise (Pillows) (Feat. Emmavie).mp3
From Chapter Split:
@ -156,5 +166,6 @@ Files created:
genre: Unset
title: 11. Sunrise (Pillows) (Feat. Emmavie)
track: 11
tracktotal: 11
year: 2017
folder.jpg

View file

@ -2,8 +2,8 @@ Files created:
----------------------------------------
{output_directory}
.ytdl-sub-split_by_chapters_with_regex_video-download-archive.json
{output_directory}/Oblivion Mod Falcor p.1
01 - Oblivion Mod Falcor p.1.mp3
{output_directory}/Project Zombie/[2010] Oblivion Mod "Falcor" p.1
01 - Oblivion Mod "Falcor" p.1.mp3
Music Tags:
album: Oblivion Mod "Falcor" p.1
albumartist: Project Zombie
@ -13,5 +13,6 @@ Files created:
genre: Unset
title: Oblivion Mod "Falcor" p.1
track: 1
tracktotal: 1
year: 2010
folder.jpg

View file

@ -2,7 +2,7 @@ Files created:
----------------------------------------
{output_directory}
.ytdl-sub-split_by_chapters_with_regex_video-download-archive.json
{output_directory}/Nocturne
{output_directory}/Alfa Mist/[2017] Nocturne
01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3
From Chapter Split:
Warning: Dry-run assumes embedded chapters with no modifications
@ -17,6 +17,7 @@ Files created:
genre: Unset
title: Intro (Feat. Racheal Ofori & Barney Artist)
track: 1
tracktotal: 11
year: 2017
02 - Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3
From Chapter Split:
@ -32,6 +33,7 @@ Files created:
genre: Unset
title: Answers (Feat. Rick David & Kaya Thomas - Dyke)
track: 2
tracktotal: 11
year: 2017
03 - Blaze (Feat. Kaya Thomas - Dyke).mp3
From Chapter Split:
@ -47,6 +49,7 @@ Files created:
genre: Unset
title: Blaze (Feat. Kaya Thomas - Dyke)
track: 3
tracktotal: 11
year: 2017
04 - What If (Interlude).mp3
From Chapter Split:
@ -62,6 +65,7 @@ Files created:
genre: Unset
title: What If (Interlude)
track: 4
tracktotal: 11
year: 2017
05 - No Peace (Feat. Tom Misch).mp3
From Chapter Split:
@ -77,6 +81,7 @@ Files created:
genre: Unset
title: No Peace (Feat. Tom Misch)
track: 5
tracktotal: 11
year: 2017
06 - Closer (Feat. Lester Duval).mp3
From Chapter Split:
@ -92,8 +97,9 @@ Files created:
genre: Unset
title: Closer (Feat. Lester Duval)
track: 6
tracktotal: 11
year: 2017
07 - Delusions Rumination (Interlude) (Feat. Racheal Ofori).mp3
07 - Delusions: Rumination (Interlude) (Feat. Racheal Ofori).mp3
From Chapter Split:
Warning: Dry-run assumes embedded chapters with no modifications
Source Title: Alfa Mist - Nocturne [Full Album]
@ -107,6 +113,7 @@ Files created:
genre: Unset
title: Delusions: Rumination (Interlude) (Feat. Racheal Ofori)
track: 7
tracktotal: 11
year: 2017
08 - Dreams (Feat. Carmody).mp3
From Chapter Split:
@ -122,6 +129,7 @@ Files created:
genre: Unset
title: Dreams (Feat. Carmody)
track: 8
tracktotal: 11
year: 2017
09 - Dreaming (Interlude) (Feat. Racheal Ofori).mp3
From Chapter Split:
@ -137,6 +145,7 @@ Files created:
genre: Unset
title: Dreaming (Interlude) (Feat. Racheal Ofori)
track: 9
tracktotal: 11
year: 2017
10 - Hopeful (Feat. Jordan Rakei).mp3
From Chapter Split:
@ -152,6 +161,7 @@ Files created:
genre: Unset
title: Hopeful (Feat. Jordan Rakei)
track: 10
tracktotal: 11
year: 2017
11 - Sunrise (Pillows) (Feat. Emmavie).mp3
From Chapter Split:
@ -167,5 +177,6 @@ Files created:
genre: Unset
title: Sunrise (Pillows) (Feat. Emmavie)
track: 11
tracktotal: 11
year: 2017
folder.jpg

View file

@ -2,7 +2,7 @@ Files created:
----------------------------------------
{output_directory}
.ytdl-sub-split_by_chapters_with_regex_video-download-archive.json
{output_directory}/Nocturne
{output_directory}/Alfa Mist/[2017] Nocturne
01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3
From Chapter Split:
Source Title: Alfa Mist - Nocturne [Full Album]
@ -16,6 +16,7 @@ Files created:
genre: Unset
title: Intro (Feat. Racheal Ofori & Barney Artist)
track: 1
tracktotal: 11
year: 2017
02 - Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3
From Chapter Split:
@ -30,6 +31,7 @@ Files created:
genre: Unset
title: Answers (Feat. Rick David & Kaya Thomas - Dyke)
track: 2
tracktotal: 11
year: 2017
03 - Blaze (Feat. Kaya Thomas - Dyke).mp3
From Chapter Split:
@ -44,6 +46,7 @@ Files created:
genre: Unset
title: Blaze (Feat. Kaya Thomas - Dyke)
track: 3
tracktotal: 11
year: 2017
04 - What If (Interlude).mp3
From Chapter Split:
@ -58,6 +61,7 @@ Files created:
genre: Unset
title: What If (Interlude)
track: 4
tracktotal: 11
year: 2017
05 - No Peace (Feat. Tom Misch).mp3
From Chapter Split:
@ -72,6 +76,7 @@ Files created:
genre: Unset
title: No Peace (Feat. Tom Misch)
track: 5
tracktotal: 11
year: 2017
06 - Closer (Feat. Lester Duval).mp3
From Chapter Split:
@ -86,8 +91,9 @@ Files created:
genre: Unset
title: Closer (Feat. Lester Duval)
track: 6
tracktotal: 11
year: 2017
07 - Delusions Rumination (Interlude) (Feat. Racheal Ofori).mp3
07 - Delusions: Rumination (Interlude) (Feat. Racheal Ofori).mp3
From Chapter Split:
Source Title: Alfa Mist - Nocturne [Full Album]
Segment: 17:57 - 20:05
@ -100,6 +106,7 @@ Files created:
genre: Unset
title: Delusions: Rumination (Interlude) (Feat. Racheal Ofori)
track: 7
tracktotal: 11
year: 2017
08 - Dreams (Feat. Carmody).mp3
From Chapter Split:
@ -114,6 +121,7 @@ Files created:
genre: Unset
title: Dreams (Feat. Carmody)
track: 8
tracktotal: 11
year: 2017
09 - Dreaming (Interlude) (Feat. Racheal Ofori).mp3
From Chapter Split:
@ -128,6 +136,7 @@ Files created:
genre: Unset
title: Dreaming (Interlude) (Feat. Racheal Ofori)
track: 9
tracktotal: 11
year: 2017
10 - Hopeful (Feat. Jordan Rakei).mp3
From Chapter Split:
@ -142,6 +151,7 @@ Files created:
genre: Unset
title: Hopeful (Feat. Jordan Rakei)
track: 10
tracktotal: 11
year: 2017
11 - Sunrise (Pillows) (Feat. Emmavie).mp3
From Chapter Split:
@ -156,5 +166,6 @@ Files created:
genre: Unset
title: Sunrise (Pillows) (Feat. Emmavie)
track: 11
tracktotal: 11
year: 2017
folder.jpg

View file

@ -1,31 +1,11 @@
Files created:
----------------------------------------
{output_directory}
Jesse's Minecraft Server [Trailer - Feb.1].ogg
.ytdl-sub-multiple_songs_test-download-archive.json
{output_directory}/Project Zombie/[2011] Jesse's Minecraft Server
01 - Jesse's Minecraft Server [Trailer - Mar.21].ogg
Music Tags:
album: Singles
albumartist: Project Zombie
albumartists: Project Zombie
artist: Project Zombie
artists: Project Zombie
genre: Unset
title: Jesse's Minecraft Server [Trailer - Feb.1]
track: 3
year: 2011
Jesse's Minecraft Server [Trailer - Feb.27].ogg
Music Tags:
album: Singles
albumartist: Project Zombie
albumartists: Project Zombie
artist: Project Zombie
artists: Project Zombie
genre: Unset
title: Jesse's Minecraft Server [Trailer - Feb.27]
track: 2
year: 2011
Jesse's Minecraft Server [Trailer - Mar.21].ogg
Music Tags:
album: Singles
album: Jesse's Minecraft Server
albumartist: Project Zombie
albumartists: Project Zombie
artist: Project Zombie
@ -33,4 +13,30 @@ Files created:
genre: Unset
title: Jesse's Minecraft Server [Trailer - Mar.21]
track: 1
year: 2011
tracktotal: 3
year: 2011
02 - Jesse's Minecraft Server [Trailer - Feb.27].ogg
Music Tags:
album: Jesse's Minecraft Server
albumartist: Project Zombie
albumartists: Project Zombie
artist: Project Zombie
artists: Project Zombie
genre: Unset
title: Jesse's Minecraft Server [Trailer - Feb.27]
track: 2
tracktotal: 3
year: 2011
03 - Jesse's Minecraft Server [Trailer - Feb.1].ogg
Music Tags:
album: Jesse's Minecraft Server
albumartist: Project Zombie
albumartists: Project Zombie
artist: Project Zombie
artists: Project Zombie
genre: Unset
title: Jesse's Minecraft Server [Trailer - Feb.1]
track: 3
tracktotal: 3
year: 2011
folder.jpg

View file

@ -1,9 +1,11 @@
Files created:
----------------------------------------
{output_directory}
YouTube Rewind 2019 For the Record #YouTubeRewind.mp3
.ytdl-sub-single_song_test-download-archive.json
{output_directory}/YouTube/[2019] YouTube Rewind 2019: For the Record | #YouTubeRewind
01 - YouTube Rewind 2019: For the Record | #YouTubeRewind.mp3
Embedded Thumbnail, Music Tags:
album: Singles
album: YouTube Rewind 2019: For the Record | #YouTubeRewind
albumartist: YouTube
albumartists: YouTube
artist: YouTube
@ -14,4 +16,6 @@ Files created:
- multi_tag_2
title: YouTube Rewind 2019: For the Record | #YouTubeRewind
track: 1
year: 2019
tracktotal: 1
year: 2019
folder.jpg

View file

@ -7,10 +7,13 @@ Files created:
Music Tags:
album: Baby Santana's Dorian Groove
albumartist: j_b
albumartists: j_b
artist: j_b
artists: j_b
genre: Unset
title: Baby Santana's Dorian Groove
track: 1
tracktotal: 1
year: 2021
folder.jpg
{output_directory}/j_b/[2021] Purple Clouds
@ -18,10 +21,13 @@ Files created:
Music Tags:
album: Purple Clouds
albumartist: j_b
albumartists: j_b
artist: j_b
artists: j_b
genre: Unset
title: Purple Clouds
track: 1
tracktotal: 1
year: 2021
folder.jpg
{output_directory}/j_b/[2022] Acoustic Treats
@ -29,99 +35,132 @@ Files created:
Music Tags:
album: Acoustic Treats
albumartist: j_b
albumartists: j_b
artist: j_b
artists: j_b
genre: Unset
title: 20160426 184214
track: 1
tracktotal: 11
year: 2022
02 - 20160502 123150.mp3
Music Tags:
album: Acoustic Treats
albumartist: j_b
albumartists: j_b
artist: j_b
artists: j_b
genre: Unset
title: 20160502 123150
track: 2
tracktotal: 11
year: 2022
03 - 20160504 143832.mp3
Music Tags:
album: Acoustic Treats
albumartist: j_b
albumartists: j_b
artist: j_b
artists: j_b
genre: Unset
title: 20160504 143832
track: 3
tracktotal: 11
year: 2022
04 - 20160601 221234.mp3
Music Tags:
album: Acoustic Treats
albumartist: j_b
albumartists: j_b
artist: j_b
artists: j_b
genre: Unset
title: 20160601 221234
track: 4
tracktotal: 11
year: 2022
05 - 20160601 222440.mp3
Music Tags:
album: Acoustic Treats
albumartist: j_b
albumartists: j_b
artist: j_b
artists: j_b
genre: Unset
title: 20160601 222440
track: 5
tracktotal: 11
year: 2022
06 - 20170604 190236.mp3
Music Tags:
album: Acoustic Treats
albumartist: j_b
albumartists: j_b
artist: j_b
artists: j_b
genre: Unset
title: 20170604 190236
track: 6
tracktotal: 11
year: 2022
07 - 20170612 193646.mp3
Music Tags:
album: Acoustic Treats
albumartist: j_b
albumartists: j_b
artist: j_b
artists: j_b
genre: Unset
title: 20170612 193646
track: 7
tracktotal: 11
year: 2022
08 - 20170628 215206.mp3
Music Tags:
album: Acoustic Treats
albumartist: j_b
albumartists: j_b
artist: j_b
artists: j_b
genre: Unset
title: 20170628 215206
track: 8
tracktotal: 11
year: 2022
09 - Finding Home.mp3
Music Tags:
album: Acoustic Treats
albumartist: j_b
albumartists: j_b
artist: j_b
artists: j_b
genre: Unset
title: Finding Home
track: 9
tracktotal: 11
year: 2022
10 - Shallow Water WIP.mp3
Music Tags:
album: Acoustic Treats
albumartist: j_b
albumartists: j_b
artist: j_b
artists: j_b
genre: Unset
title: Shallow Water WIP
track: 10
tracktotal: 11
year: 2022
11 - Untold History.mp3
Music Tags:
album: Acoustic Treats
albumartist: j_b
albumartists: j_b
artist: j_b
artists: j_b
genre: Unset
title: Untold History
track: 11
tracktotal: 11
year: 2022
folder.jpg

View file

@ -1,155 +0,0 @@
import re
import pytest
from ytdl_sub.utils.exceptions import ValidationException
from ytdl_sub.validators.url_validator import SoundcloudUsernameUrlValidator
from ytdl_sub.validators.url_validator import YoutubeChannelUrlValidator
from ytdl_sub.validators.url_validator import YoutubePlaylistUrlValidator
from ytdl_sub.validators.url_validator import YoutubeVideoUrlValidator
class TestYoutubeVideoUrlValidator:
@pytest.mark.parametrize(
"url",
[
"youtu.be/dQw4w9WgXcQ",
"www.youtu.be/dQw4w9WgXcQ",
"https://youtu.be/dQw4w9WgXcQ",
"https://www.youtu.be/dQw4w9WgXcQ",
"https://www.youtube.com/watch?v=dQw4w9WgXcQ&feature=feedu",
"https://www.youtube.com/embed/dQw4w9WgXcQ",
"https://www.youtube.com/v/dQw4w9WgXcQ?version=3&amp;hl=en_US",
"https://www.youtube.com/shorts/dQw4w9WgXcQ",
],
)
def test_youtube_video_url_validator_success(self, url):
video_url = YoutubeVideoUrlValidator(name="unit test", value=url).video_url
assert video_url == "https://youtube.com/watch?v=dQw4w9WgXcQ"
@pytest.mark.parametrize(
"bad_url",
[
"utube.com/watch?v=sdfsadf",
"youtube.com/nope?v=sdfsadf",
"youtube.com",
"youtube.com/watch",
"youtube.com/watch?v=",
"youtu.be/",
"youtu.be",
"youtube.com/shorts",
],
)
def test_youtube_video_url_validator_fail(self, bad_url):
expected_error_msg = f"'{bad_url}' is not a valid Youtube video url."
with pytest.raises(ValidationException, match=re.escape(expected_error_msg)):
YoutubeVideoUrlValidator(name="unit test", value=bad_url)
class TestYoutubePlaylistUrlValidator:
@pytest.mark.parametrize(
"url",
[
"youtube.com/playlist?list=PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc",
"www.youtube.com/playlist?list=PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc",
"https://youtube.com/playlist?list=PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc",
"https://www.youtube.com/playlist?list=PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc",
],
)
def test_youtube_playlist_url_validator_success(self, url):
playlist_url = YoutubePlaylistUrlValidator(name="unit test", value=url).playlist_url
assert (
playlist_url == "https://youtube.com/playlist?list=PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc"
)
@pytest.mark.parametrize(
"bad_url",
[
"youpoop.com/playlist?list=PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc",
"youtube.com/playlistlist=PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc",
"youtube.com",
"youtube.com/playlist/asdfsdfsdf",
"youtube.com/playlist?list=",
"youtube.com/playlist",
],
)
def test_youtube_playlist_url_validator_fail(self, bad_url):
expected_error_msg = f"'{bad_url}' is not a valid Youtube playlist url."
with pytest.raises(ValidationException, match=re.escape(expected_error_msg)):
YoutubePlaylistUrlValidator(name="unit test", value=bad_url)
class TestYoutubeChannelUrlValidator:
@pytest.mark.parametrize(
"url, expected_url",
[
(
"https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw",
"https://youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw",
),
(
"https://youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw",
"https://youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw",
),
(
"youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw",
"https://youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw",
),
(
"www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw",
"https://youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw",
),
(
"https://www.youtube.com/c/RickastleyCoUkOfficial",
"https://youtube.com/c/RickastleyCoUkOfficial",
),
(
"https://www.youtube.com/user/videogamedunkey",
"https://youtube.com/user/videogamedunkey",
),
(
"https://youtube.com/extracredits",
"https://youtube.com/extracredits",
),
],
)
def test_youtube_channel_url_validator_success(self, url, expected_url):
channel_url = YoutubeChannelUrlValidator(name="unit test", value=url).channel_url
assert channel_url == expected_url
@pytest.mark.parametrize(
"bad_url",
[
"www.youtube.com/cha/UCuAXFkgsw1L7xaCfnd5JJOw",
"www.nopetube.com/channel/asdfdsf",
"www.youtube.com/channel/",
"www.youtube.com/channell/asdfasdf",
],
)
def test_youtube_channel_url_validator_fail(self, bad_url):
expected_error_msg = f"'{bad_url}' is not a valid Youtube channel url."
with pytest.raises(ValidationException, match=re.escape(expected_error_msg)):
YoutubeChannelUrlValidator(name="unit test", value=bad_url)
class TestSoundcloudUsernameUrlValidator:
@pytest.mark.parametrize(
"url",
[
"soundcloud.com/poop",
"www.soundcloud.com/poop",
"https://soundcloud.com/poop",
"https://www.soundcloud.com/poop",
"https://www.soundcloud.com/poop/albums",
"https://www.soundcloud.com/poop?link=clipboard_share",
],
)
def test_soundcloud_artist_url_validator_success(self, url):
username_url = SoundcloudUsernameUrlValidator(name="unit test", value=url).username_url
assert username_url == "https://soundcloud.com/poop"
@pytest.mark.parametrize("bad_url", ["soundcloud.com", "soundnope.lol", "soundcloud.comm/"])
def test_youtube_playlist_url_validator_fail(self, bad_url):
expected_error_msg = f"'{bad_url}' is not a valid Soundcloud username url."
with pytest.raises(ValidationException, match=re.escape(expected_error_msg)):
SoundcloudUsernameUrlValidator(name="unit test", value=bad_url)