Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
  • v1.0.0
  • v1.1.0
  • v1.10.0
  • v1.11.0
  • v1.12.0
  • v1.12.1
  • v1.12.2
8 results

Target

Select target project
  • deadlocker8/SpotifyBackup
1 result
Select Git revision
Loading items
Show changes
Commits on Source (2)
exports/
config/settings.json
config/settings-import.json
config/settings-creator.json
config/settings-creator-latest.json
config/settings-creator-random.json
config/settings-recorder.json
.cache
.cache_creator
.cache_recorder
.cache_spotify_creator
recorder/
import json
import random
from typing import Dict, List
import click
import spotipy
from TheCodeLabs_BaseUtils.DefaultLogger import DefaultLogger
from spotipy import CacheFileHandler
......@@ -10,12 +12,17 @@ LOG_FORMAT = '[%(levelname)-7s] - %(asctime)s - %(message)s'
LOGGER = DefaultLogger().create_logger_if_not_exists('SpotifyAutoPlaylistCreator', logFormat=LOG_FORMAT)
MODE_LATEST = 'LATEST'
MODE_RANDOM = 'RANDOM'
class SpotifyAutoPlaylistCreator:
def __init__(self, clientID: str,
clientSecret: str,
playlistInfo: List[Dict[str, str]],
destinationPlaylistInfo: Dict[str, str],
numberOfTracks: int,
mode: str,
redirectUrl: str,
openBrowser: bool,
cacheFilePath: str):
......@@ -24,6 +31,7 @@ class SpotifyAutoPlaylistCreator:
self._playlistInfo = playlistInfo
self._destinationPlaylistInfo = destinationPlaylistInfo
self._numberOfTracks = numberOfTracks
self._mode = mode
self._redirectUrl = redirectUrl
self._openBrowser = openBrowser
self._cacheFilePath = cacheFilePath
......@@ -47,10 +55,19 @@ class SpotifyAutoPlaylistCreator:
LOGGER.info(f'>>> Fetching tracks for all source playlists...')
allTracks = []
for playlistInfo in SETTINGS['playlists']:
for playlistInfo in self._playlistInfo:
playlist = self.__get_playlist(playlistInfo['user'], playlistInfo['id'])
allTracks.extend(self.__get_tracks(playlist))
LOGGER.info(f'>>> Run mode {self._mode}...')
if self._mode == MODE_LATEST:
self.__RunModeLatestTracks(allTracks, destinationPlaylist)
elif self._mode == MODE_RANDOM:
self.__RunModeRandom(allTracks, destinationPlaylist)
else:
raise RuntimeError(f'Unknown mode {self._mode}')
def __RunModeLatestTracks(self, allTracks: List, destinationPlaylist) -> None:
sortedTracks = sorted(allTracks, key=lambda d: d['added_at'], reverse=True)
LOGGER.info(f'>>> Collecting latest tracks (limit: {self._numberOfTracks})...')
......@@ -61,6 +78,20 @@ class SpotifyAutoPlaylistCreator:
LOGGER.info(f'>>> Adding tracks to destination playlist "{destinationPlaylist["name"]}"...')
self._spotify.playlist_add_items(self._destinationPlaylistInfo['id'], latestTrackUris)
def __RunModeRandom(self, allTracks: List, destinationPlaylist) -> None:
randomTracks = []
filteredTracks = [t for t in allTracks if not t['is_local']]
while len(randomTracks) < self._numberOfTracks:
numberOfExercisesToGenerate = self._numberOfTracks - len(randomTracks)
randomTracks.extend(random.sample(filteredTracks, min(len(filteredTracks), numberOfExercisesToGenerate)))
LOGGER.info(f'>>> Found {len(randomTracks)} random tracks (limit: {self._numberOfTracks})')
LOGGER.info(f'>>> Adding tracks to destination playlist "{destinationPlaylist["name"]}"...')
randomTrackUris = self.__extract_track_uris(randomTracks)
self._spotify.playlist_add_items(self._destinationPlaylistInfo['id'], randomTrackUris)
def __CollectLatestTracks(self, sortedTracks):
tracksToAdd = []
for track in sortedTracks:
......@@ -83,6 +114,7 @@ class SpotifyAutoPlaylistCreator:
LOGGER.info(f'>>> Removing {len(existingTracks)} tracks from destination '
f'playlist "{destinationPlaylist["name"]}"...')
existingTracksUris = self.__extract_track_uris(existingTracks)
if existingTracksUris:
self._spotify.playlist_remove_all_occurrences_of_items(self._destinationPlaylistInfo['id'], existingTracksUris)
def __get_playlist(self, username: str, playlistID: str) -> Dict:
......@@ -107,8 +139,10 @@ class SpotifyAutoPlaylistCreator:
return [track['track']['uri'] for track in tracks]
if __name__ == '__main__':
with open('config/settings-creator.json', 'r', encoding='utf-8') as f:
@click.command()
@click.option('--settings-path', '-s', 'settingsPath', help='Path to the settings file.', required=True)
def start(settingsPath) -> None:
with open(settingsPath, 'r', encoding='utf-8') as f:
SETTINGS = json.load(f)
spotifyBackup = SpotifyAutoPlaylistCreator(SETTINGS['spotifyAPI']['clientID'],
......@@ -116,6 +150,7 @@ if __name__ == '__main__':
SETTINGS['playlists'],
SETTINGS['destinationPlaylist'],
SETTINGS['numberOfTracks'],
SETTINGS['mode'],
SETTINGS['redirectUrl'],
SETTINGS['openBrowser'],
SETTINGS['cacheFilePath'])
......@@ -123,3 +158,7 @@ if __name__ == '__main__':
spotifyBackup.run()
LOGGER.info('### DONE ###')
if __name__ == '__main__':
start()
......@@ -18,5 +18,6 @@
"numberOfTracks": 10,
"redirectUrl": "http://localhost:8080",
"openBrowser": false,
"cacheFilePath": ".cache"
"cacheFilePath": ".cache",
"mode": "LATEST or RANDOM"
}
\ No newline at end of file
[tool.poetry]
name = "SpotifyBackup"
version = "1.11.0"
version = "1.12.0"
description = "Simple script for backing up public playlists from Spotify."
authors = ["deadlocker8"]
......
{
"version": {
"name": "v1.11.0",
"code": 14,
"date": "09.10.23"
"name": "v1.12.0",
"code": 15,
"date": "30.08.24"
}
}
\ No newline at end of file