diff --git a/setup.py b/setup.py index 2deefb4..99650d5 100755 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ exec(open("ytmdl/__version__.py").read()) req_pkgs = [ - 'yt-dlp>=2022.03.08.1', + 'yt-dlp>=2022.7.6', 'mutagen', 'itunespy', 'requests', diff --git a/ytmdl/dir.py b/ytmdl/dir.py index 97f6178..ae1f4a7 100644 --- a/ytmdl/dir.py +++ b/ytmdl/dir.py @@ -22,7 +22,7 @@ def __replace_special_characters(passed_name: str) -> str: return sub(r'/', '-', passed_name) -def cleanup(TRACK_INFO, index, datatype, remove_cached=True): +def cleanup(TRACK_INFO, index, datatype, remove_cached=True, filename_passed=None): """Move the song from temp to the song dir.""" try: SONG = glob.glob(os.path.join( @@ -33,6 +33,14 @@ def cleanup(TRACK_INFO, index, datatype, remove_cached=True): SONG_NAME = os.path.basename(SONG) + # If the filename is passed, use that instead of the song + # + # NOTE that is the path is set to be a dynamic value by using + # special characters like `$` though the config then that will + # overwrite the filename_passed. + if filename_passed is not None: + SONG_NAME = filename_passed + ".{}".format(datatype) + DIR = defaults.DEFAULT.SONG_DIR logger.debug(DIR) @@ -49,6 +57,8 @@ def cleanup(TRACK_INFO, index, datatype, remove_cached=True): dest_filename = os.path.join( DIR, __replace_special_characters(SONG_NAME)) + + logger.debug("Final name: ", dest_filename) shutil.move(SONG, dest_filename) if remove_cached: @@ -181,7 +191,7 @@ def make_custom_dir(DIR, TRACK_INFO): return (base_DIR, last_element) -def dry_cleanup(current_path, passed_name): +def dry_cleanup(current_path, passed_name, filename_passed=None): """ Move the song from the current path to the song dir and change the name to the passed_name. @@ -194,6 +204,11 @@ def dry_cleanup(current_path, passed_name): extension = os.path.basename(current_path).split(".")[-1] logger.debug("ext: {}".format(extension)) + # If the filename is passed from the CLI, we will use that + # instead of the passed name. + if filename_passed is not None: + passed_name = filename_passed + new_basename = "{}.{}".format(passed_name, extension) DEST = defaults.DEFAULT.SONG_DIR diff --git a/ytmdl/main.py b/ytmdl/main.py index 6889ea8..542f929 100644 --- a/ytmdl/main.py +++ b/ytmdl/main.py @@ -160,6 +160,9 @@ def arguments(): parser.add_argument("--dont-transcode", help="Don't transcode the audio after \ downloading. Applicable for OPUS format only. (Default: false)", action="store_true") + parser.add_argument("--filename", help="Final filename after the song is ready to be used. \ + This will be given priority over automatic detection unless dynamic filename \ + path is set through config", default=None, metavar="NAME", type=str) playlist_group = parser.add_argument_group("Playlist") playlist_group.add_argument( @@ -402,7 +405,7 @@ def post_processing( stream=stream, youtube_link=link) if is_download_archive else None # Do a dry cleanup - if dir.dry_cleanup(conv_name, song_name): + if dir.dry_cleanup(conv_name, song_name, args.filename): logger.info("Done") return @@ -415,7 +418,7 @@ def post_processing( add_song_to_archive( stream=stream, youtube_link=link) if is_download_archive else None - if dir.dry_cleanup(conv_name, song_name): + if dir.dry_cleanup(conv_name, song_name, args.filename): logger.info("Done") elif not args.ignore_errors or args.on_meta_error == 'exit': logger.critical( @@ -434,14 +437,15 @@ def post_processing( # If no metadata was selected, just do a dry cleanup and skip the # song if track_selected is None: - if dir.dry_cleanup(conv_name, song_name): + if dir.dry_cleanup(conv_name, song_name, args.filename): logger.info("Done") elif not args.ignore_errors or args.on_meta_error == 'exit': logger.critical( ". Pass `--ignore-errors` or `on-meta-error` to ignore this.") return - if dir.cleanup([track_selected], 0, passed_format, remove_cached=False): + if dir.cleanup([track_selected], 0, passed_format, remove_cached=False, + filename_passed=args.filename): logger.info("Done") diff --git a/ytmdl/metadata.py b/ytmdl/metadata.py index 2d2cae8..8010612 100644 --- a/ytmdl/metadata.py +++ b/ytmdl/metadata.py @@ -149,6 +149,7 @@ def _search_tokens(song_name, song_list): # If there is a part like (featuring ..) or any extra data # we should remove it as it doesn't aid the search name = re.sub(r'\([^)]*\)', '', name) + name = re.sub(r'&', 'and', name) name = remove_stopwords(name) name = remove_punct(name) name = remove_multiple_spaces(name) diff --git a/ytmdl/song.py b/ytmdl/song.py index abd0cbf..aa5503c 100644 --- a/ytmdl/song.py +++ b/ytmdl/song.py @@ -27,6 +27,7 @@ from ytmdl import prepend, defaults from simber import Logger from ytmdl.meta import preconfig +from ytmdl.dir import __replace_special_characters # import traceback logger = Logger("song") @@ -227,13 +228,17 @@ def set_MP3_data(song, song_path): data.save() - defaults.DEFAULT.SONG_NAME_TO_SAVE = song.track_name + '.mp3' + defaults.DEFAULT.SONG_NAME_TO_SAVE = __replace_special_characters( + song.track_name) + '.mp3' # Rename the downloaded file - os.rename(SONG_PATH, os.path.join( + to_save_as = os.path.join( defaults.DEFAULT.SONG_TEMP_DIR, defaults.DEFAULT.SONG_NAME_TO_SAVE - )) + ) + logger.debug("Renaming file from: `{}` to `{}`".format( + SONG_PATH, to_save_as)) + os.rename(SONG_PATH, to_save_as) return IS_IMG_ADDED diff --git a/ytmdl/yt.py b/ytmdl/yt.py index 9c85182..3a73772 100644 --- a/ytmdl/yt.py +++ b/ytmdl/yt.py @@ -6,7 +6,7 @@ from urllib.parse import urlparse, parse_qs import yt_dlp from yt_dlp.utils import DownloadError -from re import match +from re import match, sub from ytmdl import defaults, utility, stringutils from downloader_cli.download import Download import traceback @@ -221,6 +221,11 @@ def search(query, bettersearch, proxy, kw=[], lim=20): Search the passed query using the `youtube_search` module and extract the results accordingly and return. """ + # Remove any `plus` in the query + if '+' in query: + query = sub(r'\+\s?', '', query) + logger.debug('Query used: ', query) + # Add keywords if better search is enabled kw = [kw_ for kw_ in kw if kw_ is not None]