import csv import json import time from typing import List import spotipy from TheCodeLabs_BaseUtils.DefaultLogger import DefaultLogger from spotipy.oauth2 import SpotifyPKCE LOG_FORMAT = '[%(levelname)-7s] - %(asctime)s - %(message)s' LOGGER = DefaultLogger().create_logger_if_not_exists('SpotifyBackup', logFormat=LOG_FORMAT) class SpotifyImport: def __init__(self, clientID: str): client_credentials_manager = SpotifyPKCE(client_id=clientID, redirect_uri='http://localhost', scope='playlist-modify-private') self._spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager) def import_playlist(self, backupFilePath: str, username: str, playlistID: str): tracks = self.__load_backup_file(backupFilePath) identifier = f'spotify:user:{username}:playlist:{playlistID}' LOGGER.info(f'>>> Importing tracks to playlist "{playlistID}"...') numberOfImportedTracks = 0 for index, track in enumerate(tracks): LOGGER.info(f'Importing {index + 1}/{len(tracks)} - "{track}"...') try: self._spotify.playlist_add_items(identifier, [track]) numberOfImportedTracks += 1 time.sleep(1) except: LOGGER.error(f'Error importing track {index + 1}/{len(tracks)} - "{track}"!') LOGGER.info(f'Importing DONE ({numberOfImportedTracks}/{len(tracks)}) successful') def __load_backup_file(self, backupFilePath: str) -> List[str]: LOGGER.info(f'>>> Parsing backup file "{backupFilePath}"...') tracks = [] with open(backupFilePath, 'r', newline='', encoding='utf-8') as f: reader = csv.reader(f, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL) next(reader) # skip header for row in reader: trackUrl = row[-1] if trackUrl: tracks.append(trackUrl) LOGGER.info(f'>>> Found {len(tracks)} tracks in backup file') return tracks if __name__ == '__main__': with open('config/settings-import.json', 'r', encoding='utf-8') as f: SETTINGS = json.load(f) spotifyImport = SpotifyImport(SETTINGS['spotifyAPI']['clientID']) for playlist in SETTINGS['playlists']: spotifyImport.import_playlist(playlist['backupFilePath'], playlist['user'], playlist['id']) LOGGER.info('### DONE ###')