Newer
Older
from datetime import datetime, timedelta
from TheCodeLabs_BaseUtils.DefaultLogger import DefaultLogger
LOG_FORMAT = '[%(levelname)-7s] - %(asctime)s - %(message)s'
LOGGER = DefaultLogger().create_logger_if_not_exists('SpotifyBackup', logFormat=LOG_FORMAT)
class SpotifyBackup:
DATE_FORMAT = '%Y-%m-%d_%H-%M-%S'
DATE_FORMAT_SHORT = '%Y-%m-%d'
INVALID_CHARS = [' ', '\t', '\n']
REPLACE_CHAR = '_'
def __init__(self, clientID: str, clientSecret: str, exportFolder: str):
self._exportFolder = exportFolder
if self._exportFolder:
os.makedirs(self._exportFolder, exist_ok=True)
client_credentials_manager = SpotifyClientCredentials(client_id=clientID, client_secret=clientSecret)
self._spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
def backup_playlist(self, username: str, playlistID: str):
playlist = self.__get_playlist(username, playlistID)
tracks = self.__get_tracks(playlist)
exportPath = self.__determine_export_path(playlist['name'])
LOGGER.info(f'>>> Exporting tracks to "{exportPath}"...')
self.__export_csv(exportPath, tracks)
LOGGER.info('Exporting DONE')
def __get_playlist(self, username: str, playlistID: str):
LOGGER.info(f'>>> Fetching playlist with ID: {playlistID} by {username}...')
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
identifier = f'spotify:user:{username}:playlist:{playlistID}'
playlist = self._spotify.playlist(identifier)
LOGGER.info(f'Found playlist "{playlist["name"]}"')
return playlist
def __get_tracks(self, playlist):
tracks = playlist['tracks']
results = tracks['items']
while tracks['next']:
tracks = self._spotify.next(tracks)
results.extend(tracks['items'])
LOGGER.info(f'Fetched {len(results)} tracks')
return results
def __determine_export_path(self, playlistName):
for item in self.INVALID_CHARS:
playlistName = playlistName.replace(item, self.REPLACE_CHAR)
fileName = f'{datetime.strftime(datetime.now(), self.DATE_FORMAT)}_{playlistName}.csv'
exportPath = os.path.join(self._exportFolder, fileName)
return exportPath
def __export_csv(self, exportPath, tracks):
with open(exportPath, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
writer.writerow(('title', 'artists', 'album', 'addedBy', 'addedAt', 'url'))
for track in tracks:
try:
trackInfo = track['track']
title = trackInfo['name']
artists = trackInfo['artists']
artists = ' & '.join(artist['name'] for artist in artists)
album = trackInfo['album']['name']
author = track['added_by']['id']
addedAt = track['added_at']
url = trackInfo['external_urls'].get('spotify', '')
writer.writerow((title, artists, album, author, addedAt, url))
except Exception:
LOGGER.exception(f'Error while exporting track "{track}"')
def clean_old_exports(self, daysToKeep):
if not daysToKeep:
LOGGER.info('Skipping deletion of old files')
return
minimumDate = datetime.today() - timedelta(days=int(daysToKeep))
LOGGER.info(f'>>> Deleting files older than {minimumDate} ({daysToKeep} days)')
files = [file for file in sorted(os.listdir(self._exportFolder)) if
os.path.isfile(os.path.join(self._exportFolder, file))]
for file in files:
parts = file.split('_')
creationDate = datetime.strptime(parts[0], self.DATE_FORMAT_SHORT)
if creationDate < minimumDate:
LOGGER.info(f'Removing old file "{file}"')
os.remove(os.path.join(self._exportFolder, file))
with open('config/settings-backup.json', 'r', encoding='utf-8') as f:
SETTINGS = json.load(f)
spotifyBackup = SpotifyBackup(SETTINGS['spotifyAPI']['clientID'],
SETTINGS['spotifyAPI']['clientSecret'],
SETTINGS['exportFolder'])
spotifyBackup.clean_old_exports(SETTINGS['daysToKeep'])
for playlist in SETTINGS['playlists']:
spotifyBackup.backup_playlist(playlist['user'], playlist['id'])
LOGGER.info('### DONE ###')