diff --git a/addMetadata.py b/addMetadata.py index 6316b04..7b681c0 100644 --- a/addMetadata.py +++ b/addMetadata.py @@ -1,15 +1,87 @@ +#!/usr/bin/env python + +DESC = """ + +______________________________________________________________ +| | +| Edit Metadata of MP3 files based on file name | +|____________________________________________________________| +""" + + import sys -import os -from os.path import basename +from os import chdir, listdir, rename, walk, path, environ +from os.path import basename, dirname, realpath import spotipy +import argparse +import configparser import spotipy.oauth2 as oauth2 import re from titlecase import titlecase import requests from bs4 import BeautifulSoup +import eyed3 +import argparse + + +def setup_config(): + ''' + read api keys from config.ini file + ''' + + global CONFIG, GENIUS_KEY, SP_SECRET, SP_ID, config_path + + CONFIG = configparser.ConfigParser() + config_path = realpath(__file__).replace(basename(__file__), '') + config_path = config_path + 'config.ini' + CONFIG.read(config_path) + + GENIUS_KEY = CONFIG['keys']['genius_key'] + SP_SECRET = CONFIG['keys']['spotify_client_secret'] + SP_ID = CONFIG['keys']['spotify_client_id'] + + if GENIUS_KEY == '': + print('Warning, you are missing Genius key. Add it using --config\n\n') + + if SP_SECRET == '': + print('Warning, you are missing Spotify Client Secret. Add it using --config\n\n') + + if SP_ID == '': + print('Warning, you are missing Spotify Client ID. Add it using --config\n\n') + + +def add_config_keys(): + ''' + Adds configuration keys in the config.ini file + ''' + + GENIUS_KEY = CONFIG['keys']['genius_key'] + SP_SECRET = CONFIG['keys']['spotify_client_secret'] + SP_ID = CONFIG['keys']['spotify_client_id'] + + if GENIUS_KEY == '': + genius_key = input('Enter Genius Client Access token : ') + CONFIG['keys']['genius_key'] = genius_key + + if SP_SECRET == '': + sp_secret = input('Enter Spotify Secret token : ') + CONFIG['keys']['spotify_client_secret'] = sp_secret + + if SP_ID == '': + sp_id = input('Enter Spotify Client ID : ') + CONFIG['keys']['spotify_client_id'] = sp_id + + with open(config_path, 'w') as configfile: + CONFIG.write(configfile) def improve_song_names(songs): + ''' + removes all unwanted words and numbers from file name so that the spotify search results can be improved + + removes all numbers from beginning, then strip all punctuation marks from the string, then remove words in word_filters, then remove unwanted space + ''' + char_filters = "()[]{}-:_/=+\"\'" word_filters = ('lyrics', 'lyric', 'by', 'video', 'official', 'hd', 'dirty', 'with', 'lyrics', 'feat', 'original', 'mix', 'www', 'com', 'mp3', 'audio', 'remixed', 'remix', 'full', 'version', 'music', 'hq', 'uploaded', 'explicit') @@ -34,11 +106,18 @@ def improve_song_names(songs): def get_song_name(title, artist): + ''' + return search query for spotify api call + ''' + return title + ' - ' + artist def get_lyrics_genius(song_name): - GENIUS_KEY = "TxvC3bwsONZ1lh3j8Idq-VFBXKk5SlwYoAyGwkWFvbqkJB8vwdMGV7b5Q4sJSTd2" + ''' + calls genius.com api for getting the url of the song lyrics page then scrapes that page to fetch the lyrics + ''' + base_url = "https://api.genius.com" headers = {'Authorization': 'Bearer %s' % (GENIUS_KEY)} search_url = base_url + "/search" @@ -52,6 +131,9 @@ def get_lyrics_genius(song_name): except KeyError: print("Could not find lyrics") return None + except IndexError: + print("Could not find lyrics") + return None song_url = base_url + song_info response = requests.get(song_url, headers=headers) @@ -70,8 +152,16 @@ def get_lyrics_genius(song_name): def get_metadata_spotify(spotify, song_name): + ''' + call spotify.com api to get the metadata required, as much as possible + ''' + metadata = {} - meta_tags = spotify.search(song_name, limit=1)['tracks']['items'][0] + try: + meta_tags = spotify.search(song_name, limit=1)['tracks']['items'][0] + except IndexError: + print("Could not find the song on Spotify") + return [] metadata['title'] = meta_tags['name'] metadata['artist'] = meta_tags['artists'][0]['name'] @@ -81,8 +171,9 @@ def get_metadata_spotify(spotify, song_name): album_id = meta_tags['album']['id'] album_meta_tags = spotify.album(album_id) - metadata['release-date'] = album_meta_tags['release_date'] + metadata['release_date'] = album_meta_tags['release_date'] try: + metadata['total'] = album_meta_tags['tracks']['total'] metadata['genre'] = titlecase(album_meta_tags['genres'][0]) except IndexError: try: @@ -100,28 +191,102 @@ def get_metadata_spotify(spotify, song_name): metadata['lyrics'] = get_lyrics_genius( get_song_name(metadata['title'], metadata['artist'])) + print(metadata) return metadata def list_files(): + ''' + list all files in current directory with extension .mp3 + ''' + files = [] - return [f for f in os.listdir('.') if f.endswith('.mp3')] + return [f for f in listdir('.') if f.endswith('.mp3')] + + +def set_metadata(file_name, metadata): + ''' + call eyed3 module to set mp3 song metadata as received from spotify + ''' + + audiofile = eyed3.load(file_name) + tag = audiofile.tag + + try: + tag.artist = metadata['artist'] + tag.album_artist = metadata['album_artist'] + tag.album = metadata['album'] + tag.title = metadata['title'] + tag.genre = metadata['genre'] + tag.track_num = metadata['track_num'] + tag.release_date = metadata['release_date'] + tag.disc_num = metadata['disc_num'] + # tag.lyrics.set(metadata['lyrics']) + + img = requests.get( + metadata['albumart'], stream=True) + img = img.raw + + albumart = img.read() + tag.images.set(3, albumart, 'image/jpeg') + + tag.save(version=(2, 3, 0)) + + except: + return + + return def main(): + ''' + Deals with arguements and calls other functions + ''' + + setup_config() + + parser = argparse.ArgumentParser( + description="{}".format(DESC), formatter_class=argparse.RawDescriptionHelpFormatter + ) + + group = parser.add_mutually_exclusive_group(required=True) + + group.add_argument('-d', '--dir', action="store", dest='repair_directory', + help='give path of music files\' directory', default='.') + + group.add_argument('-s', '--song', action='store', dest='song_name', + help='Only fix metadata of the file specified') + + parser.add_argument('-c', '--config', action='store_true', dest='config', + help="Add API Keys to config\n\n") + + parser.add_argument('-n', '--norename', action='store_true', + help='Does not rename files to song title\n\n') + + parser.add_argument('-f', '--format', action='store', dest='rename_format', help='''Specify the Name format used in renaming, + Valid Keywords are: + {title}{artist}{album}\n\n)''') + + args = parser.parse_args() + + repair_directory = args.repair_directory or '.' + norename = args.norename or False + format = args.rename_format or '{title}' + config = args.config + + if config: + add_config_keys() + auth = oauth2.SpotifyClientCredentials( - client_id='622a0e16a4914e3eadc2a37b4a134f1e', - client_secret='6fe008a8b7754954a58a9849fa3172df') + client_id=SP_ID, client_secret=SP_SECRET) token = auth.get_access_token() spotify = spotipy.Spotify(auth=token) files = list_files() improved_name = improve_song_names(files) - # print(improved_name[19]) - # print(files[16]) metadata = get_metadata_spotify( - spotify, improved_name[19]) + spotify, "Martin Garrix and Bebe Rexha In The Name of Love") if __name__ == "__main__":