mirror of
				https://github.com/KevinMidboe/spotify-downloader.git
				synced 2025-10-29 18:00:15 +00:00 
			
		
		
		
	Save file names using a custom format specifiers (#205)
* Use custom formats to generate file name * Do not mess up search term * Fix tests * Fix conflicting names * Fix subprocess call on file paths with spaces * Create directories and keep spaces as defaults * Fix config merge * Remove underscores from default file format * Remove debug info * Show possible formats in usage help
This commit is contained in:
		
							
								
								
									
										18
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								README.md
									
									
									
									
									
								
							| @@ -89,8 +89,8 @@ but make sure `$ python -V` gives you a `Python 3.x.x`! | |||||||
| ``` | ``` | ||||||
| usage: spotdl.py [-h] | usage: spotdl.py [-h] | ||||||
|                  (-s SONG | -l LIST | -p PLAYLIST | -b ALBUM | -u USERNAME) |                  (-s SONG | -l LIST | -p PLAYLIST | -b ALBUM | -u USERNAME) | ||||||
|                  [-m] [-nm] [-a] [-f FOLDER] [--overwrite {skip,force,prompt}] |                  [-m] [-nm] [-a] [-f FOLDER] [--overwrite {force,prompt,skip}] | ||||||
|                  [-i INPUT_EXT] [-o OUTPUT_EXT] [-dm] [-d] [-mo] |                  [-i INPUT_EXT] [-o OUTPUT_EXT] [-ff] [-dm] [-d] [-mo] [-ns] | ||||||
|                  [-ll {INFO,WARNING,ERROR,DEBUG}] |                  [-ll {INFO,WARNING,ERROR,DEBUG}] | ||||||
|  |  | ||||||
| Download and convert songs from Spotify, Youtube etc. | Download and convert songs from Spotify, Youtube etc. | ||||||
| @@ -114,8 +114,8 @@ optional arguments: | |||||||
|                         ffmpeg (default: False) |                         ffmpeg (default: False) | ||||||
|   -f FOLDER, --folder FOLDER |   -f FOLDER, --folder FOLDER | ||||||
|                         path to folder where files will be stored in (default: |                         path to folder where files will be stored in (default: | ||||||
|                         Music/) |                         Music) | ||||||
|   --overwrite {skip,force,prompt} |   --overwrite {force,prompt,skip} | ||||||
|                         change the overwrite policy (default: prompt) |                         change the overwrite policy (default: prompt) | ||||||
|   -i INPUT_EXT, --input-ext INPUT_EXT |   -i INPUT_EXT, --input-ext INPUT_EXT | ||||||
|                         prefered input format .m4a or .webm (Opus) (default: |                         prefered input format .m4a or .webm (Opus) (default: | ||||||
| @@ -123,14 +123,20 @@ optional arguments: | |||||||
|   -o OUTPUT_EXT, --output-ext OUTPUT_EXT |   -o OUTPUT_EXT, --output-ext OUTPUT_EXT | ||||||
|                         prefered output extension .mp3 or .m4a (AAC) (default: |                         prefered output extension .mp3 or .m4a (AAC) (default: | ||||||
|                         .mp3) |                         .mp3) | ||||||
|  |   -ff, --file-format    File format to save the downloaded song with, each tag | ||||||
|  |                         is surrounded by curly braces. Possible formats: | ||||||
|  |                         ['track_name', 'artist', 'album', 'album_artist', | ||||||
|  |                         'genre', 'disc_number', 'duration', 'year', | ||||||
|  |                         'original_date', 'track_number', 'total_tracks', | ||||||
|  |                         'isrc'] (default: {artist} - {track_name}) | ||||||
|   -dm, --download-only-metadata |   -dm, --download-only-metadata | ||||||
|                         download songs for which metadata is found (default: |                         download songs for which metadata is found (default: | ||||||
|                         False) |                         False) | ||||||
|   -d, --dry-run         Show only track title and YouTube URL (default: False) |   -d, --dry-run         Show only track title and YouTube URL (default: False) | ||||||
|   -mo, --music-videos-only |   -mo, --music-videos-only | ||||||
|                         Search only for music on Youtube (default: False) |                         Search only for music on Youtube (default: False) | ||||||
|   -ps, --preserve-spaces |   -ns, --no-spaces      Replace spaces with underscores in file names | ||||||
|                         Preserve spaces on file names (default: False) |                         (default: False) | ||||||
|   -ll {INFO,WARNING,ERROR,DEBUG}, --log-level {INFO,WARNING,ERROR,DEBUG} |   -ll {INFO,WARNING,ERROR,DEBUG}, --log-level {INFO,WARNING,ERROR,DEBUG} | ||||||
|                         set log verbosity (default: INFO) |                         set log verbosity (default: INFO) | ||||||
| ``` | ``` | ||||||
|   | |||||||
| @@ -31,9 +31,8 @@ def song(input_song, output_song, folder, avconv=False): | |||||||
|  |  | ||||||
| class Converter: | class Converter: | ||||||
|     def __init__(self, input_song, output_song, folder): |     def __init__(self, input_song, output_song, folder): | ||||||
|         self.input_song = input_song |         self.input_file = os.path.join(folder, input_song) | ||||||
|         self.output_song = output_song |         self.output_file = os.path.join(folder, output_song) | ||||||
|         self.folder = folder |  | ||||||
|  |  | ||||||
|     def with_avconv(self): |     def with_avconv(self): | ||||||
|         if log.level == 10: |         if log.level == 10: | ||||||
| @@ -42,8 +41,8 @@ class Converter: | |||||||
|             level = '0' |             level = '0' | ||||||
|  |  | ||||||
|         command = ['avconv', '-loglevel', level, '-i', |         command = ['avconv', '-loglevel', level, '-i', | ||||||
|                    os.path.join(self.folder, self.input_song), '-ab', '192k', |                    self.input_file, '-ab', '192k', | ||||||
|                    os.path.join(self.folder, self.output_song)] |                    self.output_file] | ||||||
|  |  | ||||||
|         log.debug(command) |         log.debug(command) | ||||||
|         return subprocess.call(command) |         return subprocess.call(command) | ||||||
| @@ -54,8 +53,8 @@ class Converter: | |||||||
|         if not log.level == 10: |         if not log.level == 10: | ||||||
|             ffmpeg_pre += '-hide_banner -nostats -v panic ' |             ffmpeg_pre += '-hide_banner -nostats -v panic ' | ||||||
|  |  | ||||||
|         input_ext = self.input_song.split('.')[-1] |         input_ext = self.input_file.split('.')[-1] | ||||||
|         output_ext = self.output_song.split('.')[-1] |         output_ext = self.output_file.split('.')[-1] | ||||||
|  |  | ||||||
|         if input_ext == 'm4a': |         if input_ext == 'm4a': | ||||||
|             if output_ext == 'mp3': |             if output_ext == 'mp3': | ||||||
| @@ -69,9 +68,8 @@ class Converter: | |||||||
|             elif output_ext == 'm4a': |             elif output_ext == 'm4a': | ||||||
|                 ffmpeg_params = '-cutoff 20000 -c:a libfdk_aac -b:a 192k -vn ' |                 ffmpeg_params = '-cutoff 20000 -c:a libfdk_aac -b:a 192k -vn ' | ||||||
|  |  | ||||||
|         command = '{0}-i {1} {2}{3}'.format( |         ffmpeg_pre += ' -i' | ||||||
|             ffmpeg_pre, os.path.join(self.folder, self.input_song), |         command = ffmpeg_pre.split() + [self.input_file] + ffmpeg_params.split() + [self.output_file] | ||||||
|             ffmpeg_params, os.path.join(self.folder, self.output_song)).split(' ') |  | ||||||
|  |  | ||||||
|         log.debug(command) |         log.debug(command) | ||||||
|         return subprocess.call(command) |         return subprocess.call(command) | ||||||
|   | |||||||
| @@ -1,3 +1,5 @@ | |||||||
|  | from core import internals | ||||||
|  |  | ||||||
| import logging | import logging | ||||||
| import yaml | import yaml | ||||||
| import argparse | import argparse | ||||||
| @@ -19,7 +21,8 @@ default_conf = { 'spotify-downloader': | |||||||
|                    'download-only-metadata' : False, |                    'download-only-metadata' : False, | ||||||
|                    'dry-run'                : False, |                    'dry-run'                : False, | ||||||
|                    'music-videos-only'      : False, |                    'music-videos-only'      : False, | ||||||
|                    'preserve-spaces'        : False, |                    'no-spaces'              : False, | ||||||
|  |                    'file-format'            : '{artist} - {track_name}', | ||||||
|                    'log-level'              : 'INFO' } |                    'log-level'              : 'INFO' } | ||||||
|                } |                } | ||||||
|  |  | ||||||
| @@ -50,13 +53,16 @@ def get_config(config_file): | |||||||
|     return cfg['spotify-downloader'] |     return cfg['spotify-downloader'] | ||||||
|  |  | ||||||
|  |  | ||||||
| def get_arguments(to_group=True, raw_args=None): | def get_arguments(raw_args=None, to_group=True, to_merge=True): | ||||||
|     parser = argparse.ArgumentParser( |     parser = argparse.ArgumentParser( | ||||||
|         description='Download and convert songs from Spotify, Youtube etc.', |         description='Download and convert songs from Spotify, Youtube etc.', | ||||||
|         formatter_class=argparse.ArgumentDefaultsHelpFormatter) |         formatter_class=argparse.ArgumentDefaultsHelpFormatter) | ||||||
|  |  | ||||||
|     config_file = os.path.join(sys.path[0], 'config.yml') |     if to_merge: | ||||||
|     config = merge(default_conf, get_config(config_file)) |         config_file = os.path.join(sys.path[0], 'config.yml') | ||||||
|  |         config = merge(default_conf['spotify-downloader'], get_config(config_file)) | ||||||
|  |     else: | ||||||
|  |         config = default_conf['spotify-downloader'] | ||||||
|  |  | ||||||
|     if to_group: |     if to_group: | ||||||
|         group = parser.add_mutually_exclusive_group(required=True) |         group = parser.add_mutually_exclusive_group(required=True) | ||||||
| @@ -84,7 +90,7 @@ def get_arguments(to_group=True, raw_args=None): | |||||||
|         help='Use avconv for conversion otherwise set defaults to ffmpeg', |         help='Use avconv for conversion otherwise set defaults to ffmpeg', | ||||||
|         action='store_true') |         action='store_true') | ||||||
|     parser.add_argument( |     parser.add_argument( | ||||||
|         '-f', '--folder', default=config['folder'], |         '-f', '--folder', default=os.path.relpath(config['folder'], os.getcwd()), | ||||||
|         help='path to folder where files will be stored in') |         help='path to folder where files will be stored in') | ||||||
|     parser.add_argument( |     parser.add_argument( | ||||||
|         '--overwrite', default=config['overwrite'], |         '--overwrite', default=config['overwrite'], | ||||||
| @@ -96,6 +102,12 @@ def get_arguments(to_group=True, raw_args=None): | |||||||
|     parser.add_argument( |     parser.add_argument( | ||||||
|         '-o', '--output-ext', default=config['output-ext'], |         '-o', '--output-ext', default=config['output-ext'], | ||||||
|         help='prefered output extension .mp3 or .m4a (AAC)') |         help='prefered output extension .mp3 or .m4a (AAC)') | ||||||
|  |     parser.add_argument( | ||||||
|  |         '-ff', '--file-format', default=config['file-format'], | ||||||
|  |         help='File format to save the downloaded song with, each tag ' | ||||||
|  |              'is surrounded by curly braces. Possible formats: ' | ||||||
|  |              '{}'.format([internals.formats[x] for x in internals.formats]), | ||||||
|  |         action='store_true') | ||||||
|     parser.add_argument( |     parser.add_argument( | ||||||
|         '-dm', '--download-only-metadata', default=config['download-only-metadata'], |         '-dm', '--download-only-metadata', default=config['download-only-metadata'], | ||||||
|         help='download songs for which metadata is found', |         help='download songs for which metadata is found', | ||||||
| @@ -109,8 +121,8 @@ def get_arguments(to_group=True, raw_args=None): | |||||||
|         help='Search only for music on Youtube', |         help='Search only for music on Youtube', | ||||||
|         action='store_true') |         action='store_true') | ||||||
|     parser.add_argument( |     parser.add_argument( | ||||||
|         '-ps', '--preserve-spaces', default=config['preserve-spaces'], |         '-ns', '--no-spaces', default=config['no-spaces'], | ||||||
|         help='Preserve spaces on file names', |         help='Replace spaces with underscores in file names', | ||||||
|         action='store_true') |         action='store_true') | ||||||
|     parser.add_argument( |     parser.add_argument( | ||||||
|         '-ll', '--log-level', default=config['log-level'], |         '-ll', '--log-level', default=config['log-level'], | ||||||
|   | |||||||
| @@ -1,8 +1,23 @@ | |||||||
| from slugify import SLUG_OK, slugify | from slugify import SLUG_OK, slugify | ||||||
| from core.const import log | from core import const | ||||||
|  |  | ||||||
| import os | import os | ||||||
|  |  | ||||||
|  | log = const.log | ||||||
|  |  | ||||||
|  | formats = { 0  : 'track_name', | ||||||
|  |             1  : 'artist', | ||||||
|  |             2  : 'album', | ||||||
|  |             3  : 'album_artist', | ||||||
|  |             4  : 'genre', | ||||||
|  |             5  : 'disc_number', | ||||||
|  |             6  : 'duration', | ||||||
|  |             7  : 'year', | ||||||
|  |             8  : 'original_date', | ||||||
|  |             9  : 'track_number', | ||||||
|  |             10 : 'total_tracks', | ||||||
|  |             11 : 'isrc' } | ||||||
|  |  | ||||||
|  |  | ||||||
| def input_link(links): | def input_link(links): | ||||||
|     """ Let the user input a choice. """ |     """ Let the user input a choice. """ | ||||||
| @@ -43,19 +58,37 @@ def is_youtube(raw_song): | |||||||
|     return status |     return status | ||||||
|  |  | ||||||
|  |  | ||||||
| def generate_songname(tags): | def generate_songname(file_format, tags): | ||||||
|     """ Generate a string of the format '[artist] - [song]' for the given spotify song. """ |     """ Generate a string of the format '[artist] - [song]' for the given spotify song. """ | ||||||
|     raw_song = u'{0} - {1}'.format(tags['artists'][0]['name'], tags['name']) |     format_tags = dict(formats) | ||||||
|     return raw_song |     format_tags[0]  = tags['name'] | ||||||
|  |     format_tags[1]  = tags['artists'][0]['name'] | ||||||
|  |     format_tags[2]  = tags['album']['name'] | ||||||
|  |     format_tags[3]  = tags['artists'][0]['name'] | ||||||
|  |     format_tags[4]  = tags['genre'] | ||||||
|  |     format_tags[5]  = tags['disc_number'] | ||||||
|  |     format_tags[6]  = tags['duration'] | ||||||
|  |     format_tags[7]  = tags['year'] | ||||||
|  |     format_tags[8]  = tags['release_date'] | ||||||
|  |     format_tags[9]  = tags['track_number'] | ||||||
|  |     format_tags[10] = tags['total_tracks'] | ||||||
|  |     format_tags[11] = tags['external_ids']['isrc'] | ||||||
|  |  | ||||||
|  |     for x in formats: | ||||||
|  |         file_format = file_format.replace('{' + formats[x] + '}', | ||||||
|  |                                           str(format_tags[x])) | ||||||
|  |  | ||||||
|  |     if const.args.no_spaces: | ||||||
|  |         file_format = file_format.replace(' ', '_') | ||||||
|  |  | ||||||
|  |     return file_format | ||||||
|  |  | ||||||
|  |  | ||||||
| def sanitize_title(title): | def sanitize_title(title): | ||||||
|     """ Generate filename of the song to be downloaded. """ |     """ Generate filename of the song to be downloaded. """ | ||||||
|     title = title.replace(' ', '_') |  | ||||||
|     title = title.replace('/', '_') |  | ||||||
|  |  | ||||||
|     # slugify removes any special characters |     # slugify removes any special characters | ||||||
|     title = slugify(title, ok='-_()[]{}', lower=False) |     title = slugify(title, ok='-_()[]{}\/', lower=False, | ||||||
|  |                     spaces=(not const.args.no_spaces)) | ||||||
|     return title |     return title | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -64,7 +64,7 @@ class EmbedMetadata: | |||||||
|         audiofile['arranger'] = meta_tags['artists'][0]['name'] |         audiofile['arranger'] = meta_tags['artists'][0]['name'] | ||||||
|         audiofile['performer'] = meta_tags['artists'][0]['name'] |         audiofile['performer'] = meta_tags['artists'][0]['name'] | ||||||
|         audiofile['website'] = meta_tags['external_urls']['spotify'] |         audiofile['website'] = meta_tags['external_urls']['spotify'] | ||||||
|         audiofile['length'] = str(meta_tags['duration_ms'] / 1000.0) |         audiofile['length'] = str(meta_tags['duration']) | ||||||
|         if meta_tags['publisher']: |         if meta_tags['publisher']: | ||||||
|             audiofile['encodedby'] = meta_tags['publisher'] |             audiofile['encodedby'] = meta_tags['publisher'] | ||||||
|         if meta_tags['genre']: |         if meta_tags['genre']: | ||||||
| @@ -79,9 +79,8 @@ class EmbedMetadata: | |||||||
|         # https://github.com/quodlibet/mutagen/blob/master/mutagen/id3/_frames.py |         # https://github.com/quodlibet/mutagen/blob/master/mutagen/id3/_frames.py | ||||||
|         # Each class represents an id3 tag |         # Each class represents an id3 tag | ||||||
|         audiofile = ID3(music_file) |         audiofile = ID3(music_file) | ||||||
|         year, *_ = meta_tags['release_date'].split('-') |         audiofile['TORY'] = TORY(encoding=3, text=meta_tags['year']) | ||||||
|         audiofile['TORY'] = TORY(encoding=3, text=year) |         audiofile['TYER'] = TYER(encoding=3, text=meta_tags['year']) | ||||||
|         audiofile['TYER'] = TYER(encoding=3, text=year) |  | ||||||
|         audiofile['TPUB'] = TPUB(encoding=3, text=meta_tags['publisher']) |         audiofile['TPUB'] = TPUB(encoding=3, text=meta_tags['publisher']) | ||||||
|         audiofile['COMM'] = COMM(encoding=3, text=meta_tags['external_urls']['spotify']) |         audiofile['COMM'] = COMM(encoding=3, text=meta_tags['external_urls']['spotify']) | ||||||
|         if meta_tags['lyrics']: |         if meta_tags['lyrics']: | ||||||
| @@ -131,8 +130,7 @@ class EmbedMetadata: | |||||||
|                                            meta_tags['total_tracks'])] |                                            meta_tags['total_tracks'])] | ||||||
|         audiofile[tags['disknumber']] = [(meta_tags['disc_number'], 0)] |         audiofile[tags['disknumber']] = [(meta_tags['disc_number'], 0)] | ||||||
|         audiofile[tags['date']] = meta_tags['release_date'] |         audiofile[tags['date']] = meta_tags['release_date'] | ||||||
|         year, *_ = meta_tags['release_date'].split('-') |         audiofile[tags['year']] = meta_tags['year'] | ||||||
|         audiofile[tags['year']] = year |  | ||||||
|         audiofile[tags['originaldate']] = meta_tags['release_date'] |         audiofile[tags['originaldate']] = meta_tags['release_date'] | ||||||
|         audiofile[tags['comment']] = meta_tags['external_urls']['spotify'] |         audiofile[tags['comment']] = meta_tags['external_urls']['spotify'] | ||||||
|         if meta_tags['genre']: |         if meta_tags['genre']: | ||||||
|   | |||||||
| @@ -66,7 +66,10 @@ def generate_metadata(raw_song): | |||||||
|     except lyricwikia.LyricsNotFound: |     except lyricwikia.LyricsNotFound: | ||||||
|         meta_tags['lyrics'] = None |         meta_tags['lyrics'] = None | ||||||
|  |  | ||||||
|     # remove unused clutter when debug meta_tags |     # fix clutter | ||||||
|  |     meta_tags['year'], *_ = meta_tags['release_date'].split('-') | ||||||
|  |     meta_tags['duration'] = meta_tags['duration_ms'] / 1000.0 | ||||||
|  |     del meta_tags['duration_ms'] | ||||||
|     del meta_tags['available_markets'] |     del meta_tags['available_markets'] | ||||||
|     del meta_tags['album']['available_markets'] |     del meta_tags['album']['available_markets'] | ||||||
|  |  | ||||||
|   | |||||||
| @@ -69,7 +69,8 @@ def generate_youtube_url(raw_song, meta_tags, tries_remaining=5): | |||||||
|         song = raw_song |         song = raw_song | ||||||
|         query['q'] = song |         query['q'] = song | ||||||
|     else: |     else: | ||||||
|         song = internals.generate_songname(meta_tags) |         song = '{0} - {1}'.format(meta_tags['artists'][0]['name'], | ||||||
|  |                                   meta_tags['name']) | ||||||
|         query['q'] = song |         query['q'] = song | ||||||
|     log.debug('query: {0}'.format(query)) |     log.debug('query: {0}'.format(query)) | ||||||
|  |  | ||||||
| @@ -123,7 +124,7 @@ def generate_youtube_url(raw_song, meta_tags, tries_remaining=5): | |||||||
|             the duration_tolerance has reached the max_duration_tolerance |             the duration_tolerance has reached the max_duration_tolerance | ||||||
|             ''' |             ''' | ||||||
|             while len(possible_videos_by_duration) == 0: |             while len(possible_videos_by_duration) == 0: | ||||||
|                 possible_videos_by_duration = list(filter(lambda x: abs(x['seconds'] - (int(meta_tags['duration_ms'])/1000)) <= duration_tolerance, videos)) |                 possible_videos_by_duration = list(filter(lambda x: abs(x['seconds'] - meta_tags['duration']) <= duration_tolerance, videos)) | ||||||
|                 duration_tolerance += 1 |                 duration_tolerance += 1 | ||||||
|                 if duration_tolerance > max_duration_tolerance: |                 if duration_tolerance > max_duration_tolerance: | ||||||
|                     log.error("{0} by {1} was not found.\n".format(meta_tags['name'], meta_tags['artists'][0]['name'])) |                     log.error("{0} by {1} was not found.\n".format(meta_tags['name'], meta_tags['artists'][0]['name'])) | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								spotdl.py
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								spotdl.py
									
									
									
									
									
								
							| @@ -28,8 +28,7 @@ def check_exists(music_file, raw_song, meta_tags): | |||||||
|             os.remove(os.path.join(const.args.folder, song)) |             os.remove(os.path.join(const.args.folder, song)) | ||||||
|             continue |             continue | ||||||
|         # check if any song with similar name is already present in the given folder |         # check if any song with similar name is already present in the given folder | ||||||
|         file_name = internals.sanitize_title(music_file) |         if song.startswith(music_file): | ||||||
|         if song.startswith(file_name): |  | ||||||
|             log.debug('Found an already existing song: "{}"'.format(song)) |             log.debug('Found an already existing song: "{}"'.format(song)) | ||||||
|             if internals.is_spotify(raw_song): |             if internals.is_spotify(raw_song): | ||||||
|                 # check if the already downloaded song has correct metadata |                 # check if the already downloaded song has correct metadata | ||||||
| @@ -152,23 +151,24 @@ def grab_single(raw_song, number=None): | |||||||
|     songname = content.title |     songname = content.title | ||||||
|  |  | ||||||
|     if meta_tags is not None: |     if meta_tags is not None: | ||||||
|         refined_songname = internals.generate_songname(meta_tags) |         refined_songname = internals.generate_songname(const.args.file_format, meta_tags) | ||||||
|         log.debug('Refining songname from "{0}" to "{1}"'.format(songname, refined_songname)) |         log.debug('Refining songname from "{0}" to "{1}"'.format(songname, refined_songname)) | ||||||
|         if not refined_songname == ' - ': |         if not refined_songname == ' - ': | ||||||
|             songname = refined_songname |             songname = refined_songname | ||||||
|     else: |     else: | ||||||
|         log.warning('Could not find metadata') |         log.warning('Could not find metadata') | ||||||
|  |         songname = internals.sanitize_title(songname) | ||||||
|  |  | ||||||
|     if const.args.dry_run: |     if const.args.dry_run: | ||||||
|         return |         return | ||||||
|  |  | ||||||
|     file_name = internals.sanitize_title(songname) |     if not check_exists(songname, raw_song, meta_tags): | ||||||
|  |         # deal with file formats containing slashes to non-existent directories | ||||||
|     if not check_exists(file_name, raw_song, meta_tags): |         songpath = os.path.join(const.args.folder, os.path.dirname(songname)) | ||||||
|         if youtube_tools.download_song(file_name, content): |         os.makedirs(songpath, exist_ok=True) | ||||||
|             input_song = file_name + const.args.input_ext |         if youtube_tools.download_song(songname, content): | ||||||
|             output_song = file_name + const.args.output_ext |             input_song = songname + const.args.input_ext | ||||||
|  |             output_song = songname + const.args.output_ext | ||||||
|             print('') |             print('') | ||||||
|  |  | ||||||
|             try: |             try: | ||||||
| @@ -178,7 +178,7 @@ def grab_single(raw_song, number=None): | |||||||
|                 encoder = 'avconv' if const.args.avconv else 'ffmpeg' |                 encoder = 'avconv' if const.args.avconv else 'ffmpeg' | ||||||
|                 log.warning('Could not find {0}, skipping conversion'.format(encoder)) |                 log.warning('Could not find {0}, skipping conversion'.format(encoder)) | ||||||
|                 const.args.output_ext = const.args.input_ext |                 const.args.output_ext = const.args.input_ext | ||||||
|                 output_song = file_name + const.args.output_ext |                 output_song = songname + const.args.output_ext | ||||||
|  |  | ||||||
|             if not const.args.input_ext == const.args.output_ext: |             if not const.args.input_ext == const.args.output_ext: | ||||||
|                 os.remove(os.path.join(const.args.folder, input_song)) |                 os.remove(os.path.join(const.args.folder, input_song)) | ||||||
| @@ -186,10 +186,6 @@ def grab_single(raw_song, number=None): | |||||||
|             if not const.args.no_metadata and meta_tags is not None: |             if not const.args.no_metadata and meta_tags is not None: | ||||||
|                 metadata.embed(os.path.join(const.args.folder, output_song), meta_tags) |                 metadata.embed(os.path.join(const.args.folder, output_song), meta_tags) | ||||||
|  |  | ||||||
|             if const.args.preserve_spaces and "_" in output_song: |  | ||||||
|                 song_path = os.path.join(const.args.folder, output_song.replace('_', ' ')) |  | ||||||
|                 os.rename(os.path.join(const.args.folder, output_song), song_path) |  | ||||||
|  |  | ||||||
|         else: |         else: | ||||||
|             log.error('No audio streams available') |             log.error('No audio streams available') | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,10 +4,8 @@ import spotdl | |||||||
|  |  | ||||||
|  |  | ||||||
| def load_defaults(): | def load_defaults(): | ||||||
|     const.args = handle.get_arguments(to_group=False, raw_args='') |     const.args = handle.get_arguments(raw_args='', to_group=False, to_merge=False) | ||||||
|     const.args.folder = 'test' |  | ||||||
|     const.args.overwrite = 'skip' |     const.args.overwrite = 'skip' | ||||||
|     const.args.log_level = handle.logging.DEBUG |  | ||||||
|  |  | ||||||
|     spotdl.args = const.args |     spotdl.args = const.args | ||||||
|     spotdl.log = const.logzero.setup_logger(formatter=const.formatter, |     spotdl.log = const.logzero.setup_logger(formatter=const.formatter, | ||||||
|   | |||||||
| @@ -1,5 +1,10 @@ | |||||||
| from core import const | from core import const | ||||||
| from core import handle | from core import handle | ||||||
|  | from core import internals | ||||||
|  | from core import spotify_tools | ||||||
|  | from core import youtube_tools | ||||||
|  | from core import convert | ||||||
|  | from core import metadata | ||||||
|  |  | ||||||
| import spotdl | import spotdl | ||||||
| import loader | import loader | ||||||
| @@ -7,12 +12,13 @@ import loader | |||||||
| import os | import os | ||||||
|  |  | ||||||
| loader.load_defaults() | loader.load_defaults() | ||||||
|  | internals.filter_path(const.args.folder) | ||||||
| raw_song = "Tony's Videos VERY SHORT VIDEO 28.10.2016" | raw_song = "Tony's Videos VERY SHORT VIDEO 28.10.2016" | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_youtube_url(): | def test_youtube_url(): | ||||||
|     expect_url = 'http://youtube.com/watch?v=qOOcy2-tmbk' |     expect_url = 'http://youtube.com/watch?v=qOOcy2-tmbk' | ||||||
|     url = spotdl.youtube_tools.generate_youtube_url(raw_song, meta_tags=None) |     url = youtube_tools.generate_youtube_url(raw_song, meta_tags=None) | ||||||
|     assert url == expect_url |     assert url == expect_url | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -20,48 +26,43 @@ def test_youtube_title(): | |||||||
|     global content |     global content | ||||||
|     global title |     global title | ||||||
|     expect_title = "Tony's Videos VERY SHORT VIDEO 28.10.2016" |     expect_title = "Tony's Videos VERY SHORT VIDEO 28.10.2016" | ||||||
|     content = spotdl.youtube_tools.go_pafy(raw_song, meta_tags=None) |     content = youtube_tools.go_pafy(raw_song, meta_tags=None) | ||||||
|     title = spotdl.youtube_tools.get_youtube_title(content) |     title = youtube_tools.get_youtube_title(content) | ||||||
|     assert title == expect_title |     assert title == expect_title | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_check_exists(): | def test_check_exists(): | ||||||
|     expect_check = False |     expect_check = False | ||||||
|     # prerequisites for determining filename |     # prerequisites for determining filename | ||||||
|     file_name = spotdl.internals.sanitize_title(title) |     global file_name | ||||||
|  |     file_name = internals.sanitize_title(title) | ||||||
|     check = spotdl.check_exists(file_name, raw_song, meta_tags=None) |     check = spotdl.check_exists(file_name, raw_song, meta_tags=None) | ||||||
|     assert check == expect_check |     assert check == expect_check | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_download(): | def test_download(): | ||||||
|     expect_download = True |     expect_download = True | ||||||
|     # prerequisites for determining filename |     download = youtube_tools.download_song(file_name, content) | ||||||
|     file_name = spotdl.internals.sanitize_title(title) |  | ||||||
|     download = spotdl.youtube_tools.download_song(file_name, content) |  | ||||||
|     assert download == expect_download |     assert download == expect_download | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_convert(): | def test_convert(): | ||||||
|     # exit code 0 = success |     # exit code 0 = success | ||||||
|     expect_convert = 0 |     expect_converted = 0 | ||||||
|     # prerequisites for determining filename |  | ||||||
|     file_name = spotdl.internals.sanitize_title(title) |  | ||||||
|     global input_song |     global input_song | ||||||
|     global output_song |     global output_song | ||||||
|     input_song = file_name + const.args.input_ext |     input_song = file_name + const.args.input_ext | ||||||
|     output_song = file_name + const.args.output_ext |     output_song = file_name + const.args.output_ext | ||||||
|     convert = spotdl.convert.song(input_song, output_song, const.args.folder) |     converted = convert.song(input_song, output_song, const.args.folder) | ||||||
|     assert convert == expect_convert |     assert converted == expect_converted | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_metadata(): | def test_metadata(): | ||||||
|     expect_metadata = None |     expect_metadata = None | ||||||
|     # prerequisites for determining filename |     meta_tags = spotify_tools.generate_metadata(raw_song) | ||||||
|     meta_tags = spotdl.spotify_tools.generate_metadata(raw_song) |  | ||||||
|     file_name = spotdl.internals.sanitize_title(title) |  | ||||||
|     if meta_tags: |     if meta_tags: | ||||||
|         metadata_output = spotdl.metadata.embed(os.path.join(const.args.folder, output_song), meta_tags) |         metadata_output = metadata.embed(os.path.join(const.args.folder, output_song), meta_tags) | ||||||
|         metadata_input = spotdl.metadata.embed(os.path.join(const.args.folder, input_song), meta_tags) |         metadata_input = metadata.embed(os.path.join(const.args.folder, input_song), meta_tags) | ||||||
|     else: |     else: | ||||||
|         metadata_input = None |         metadata_input = None | ||||||
|         metadata_output = None |         metadata_output = None | ||||||
| @@ -70,8 +71,6 @@ def test_metadata(): | |||||||
|  |  | ||||||
| def test_check_exists2(): | def test_check_exists2(): | ||||||
|     expect_check = True |     expect_check = True | ||||||
|     # prerequisites for determining filename |  | ||||||
|     file_name = spotdl.internals.sanitize_title(title) |  | ||||||
|     os.remove(os.path.join(const.args.folder, input_song)) |     os.remove(os.path.join(const.args.folder, input_song)) | ||||||
|     check = spotdl.check_exists(file_name, raw_song, meta_tags=None) |     check = spotdl.check_exists(file_name, raw_song, meta_tags=None) | ||||||
|     os.remove(os.path.join(const.args.folder, output_song)) |     os.remove(os.path.join(const.args.folder, output_song)) | ||||||
|   | |||||||
| @@ -1,6 +1,11 @@ | |||||||
|  |  | ||||||
| from core import const | from core import const | ||||||
| from core import handle | from core import handle | ||||||
|  | from core import internals | ||||||
|  | from core import spotify_tools | ||||||
|  | from core import youtube_tools | ||||||
|  | from core import convert | ||||||
|  | from core import metadata | ||||||
|  |  | ||||||
| import spotdl | import spotdl | ||||||
|  |  | ||||||
| @@ -8,35 +13,36 @@ import loader | |||||||
| import os | import os | ||||||
|  |  | ||||||
| loader.load_defaults() | loader.load_defaults() | ||||||
|  | internals.filter_path(const.args.folder) | ||||||
| raw_song = 'http://open.spotify.com/track/0JlS7BXXD07hRmevDnbPDU' | raw_song = 'http://open.spotify.com/track/0JlS7BXXD07hRmevDnbPDU' | ||||||
|  |  | ||||||
| def test_spotify_title(): | def test_spotify_title(): | ||||||
|     expect_title = 'David André Østby - Intro' |     expect_title = 'David André Østby - Intro' | ||||||
|     global meta_tags |     global meta_tags | ||||||
|     meta_tags = spotdl.spotify_tools.generate_metadata(raw_song) |     meta_tags = spotify_tools.generate_metadata(raw_song) | ||||||
|     title = spotdl.internals.generate_songname(meta_tags) |     title = internals.generate_songname(const.args.file_format, meta_tags) | ||||||
|     assert title == expect_title |     assert title == expect_title | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_youtube_url(): | def test_youtube_url(): | ||||||
|     expect_url = 'http://youtube.com/watch?v=rg1wfcty0BA' |     expect_url = 'http://youtube.com/watch?v=rg1wfcty0BA' | ||||||
|     url = spotdl.youtube_tools.generate_youtube_url(raw_song, meta_tags) |     url = youtube_tools.generate_youtube_url(raw_song, meta_tags) | ||||||
|     assert url == expect_url |     assert url == expect_url | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_youtube_title(): | def test_youtube_title(): | ||||||
|     expect_title = 'Intro - David André Østby' |     expect_title = 'Intro - David André Østby' | ||||||
|     content = spotdl.youtube_tools.go_pafy(raw_song, meta_tags) |     content = youtube_tools.go_pafy(raw_song, meta_tags) | ||||||
|     title = spotdl.youtube_tools.get_youtube_title(content) |     title = youtube_tools.get_youtube_title(content) | ||||||
|     assert title == expect_title |     assert title == expect_title | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_check_exists(): | def test_check_exists(): | ||||||
|     expect_check = False |     expect_check = False | ||||||
|     # prerequisites for determining filename |     # prerequisites for determining filename | ||||||
|     songname = spotdl.internals.generate_songname(meta_tags) |     songname = internals.generate_songname(const.args.file_format, meta_tags) | ||||||
|     global file_name |     global file_name | ||||||
|     file_name = spotdl.internals.sanitize_title(songname) |     file_name = internals.sanitize_title(songname) | ||||||
|     check = spotdl.check_exists(file_name, raw_song, meta_tags) |     check = spotdl.check_exists(file_name, raw_song, meta_tags) | ||||||
|     assert check == expect_check |     assert check == expect_check | ||||||
|  |  | ||||||
| @@ -44,35 +50,35 @@ def test_check_exists(): | |||||||
| def test_download(): | def test_download(): | ||||||
|     expect_download = True |     expect_download = True | ||||||
|     # prerequisites for determining filename |     # prerequisites for determining filename | ||||||
|     content = spotdl.youtube_tools.go_pafy(raw_song, meta_tags) |     content = youtube_tools.go_pafy(raw_song, meta_tags) | ||||||
|     download = spotdl.youtube_tools.download_song(file_name, content) |     download = youtube_tools.download_song(file_name, content) | ||||||
|     assert download == expect_download |     assert download == expect_download | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_convert(): | def test_convert(): | ||||||
|     # exit code 0 = success |     # exit code 0 = success | ||||||
|     expect_convert = 0 |     expect_converted = 0 | ||||||
|     # prerequisites for determining filename |     # prerequisites for determining filename | ||||||
|     global input_song |     global input_song | ||||||
|     global output_song |     global output_song | ||||||
|     input_song = file_name + spotdl.args.input_ext |     input_song = file_name + const.args.input_ext | ||||||
|     output_song = file_name + spotdl.args.output_ext |     output_song = file_name + const.args.output_ext | ||||||
|     convert = spotdl.convert.song(input_song, output_song, spotdl.args.folder) |     converted = convert.song(input_song, output_song, const.args.folder) | ||||||
|     assert convert == expect_convert |     assert converted == expect_converted | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_metadata(): | def test_metadata(): | ||||||
|     expect_metadata = True |     expect_metadata = True | ||||||
|     # prerequisites for determining filename |     # prerequisites for determining filename | ||||||
|     metadata_output = spotdl.metadata.embed(os.path.join(spotdl.args.folder, output_song), meta_tags) |     metadata_output = metadata.embed(os.path.join(const.args.folder, output_song), meta_tags) | ||||||
|     metadata_input = spotdl.metadata.embed(os.path.join(spotdl.args.folder, input_song), meta_tags) |     metadata_input = metadata.embed(os.path.join(const.args.folder, input_song), meta_tags) | ||||||
|     assert metadata_output == (metadata_input == expect_metadata) |     assert metadata_output == (metadata_input == expect_metadata) | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_check_exists2(): | def test_check_exists2(): | ||||||
|     expect_check = True |     expect_check = True | ||||||
|     # prerequisites for determining filename |     # prerequisites for determining filename | ||||||
|     os.remove(os.path.join(spotdl.args.folder, input_song)) |     os.remove(os.path.join(const.args.folder, input_song)) | ||||||
|     check = spotdl.check_exists(file_name, raw_song, meta_tags) |     check = spotdl.check_exists(file_name, raw_song, meta_tags) | ||||||
|     os.remove(os.path.join(spotdl.args.folder, output_song)) |     os.remove(os.path.join(const.args.folder, output_song)) | ||||||
|     assert check == expect_check |     assert check == expect_check | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user