You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
85 lines
2.8 KiB
85 lines
2.8 KiB
#! /usr/bin/env python
|
|
|
|
import spotipy
|
|
from spotipy.oauth2 import SpotifyClientCredentials
|
|
from mpd import MPDClient
|
|
from mpd.base import CommandError
|
|
from collections import defaultdict
|
|
from re import sub
|
|
from os import environ
|
|
|
|
class Spotify():
|
|
def __init__(self):
|
|
self.username = environ.get("SPOTIFY_USERNAME")
|
|
self.client_credentials_manager = SpotifyClientCredentials()
|
|
self.sp = spotipy.Spotify(
|
|
client_credentials_manager=self.client_credentials_manager
|
|
)
|
|
|
|
self.mpd_client = MPDClient()
|
|
self.mpd_client.connect("127.0.0.1", 6600)
|
|
|
|
self._playlists = defaultdict(lambda: [])
|
|
|
|
def fmt_track(self, track_id):
|
|
return "spotify:track:{0}".format(track_id)
|
|
|
|
def sanitize_playlist(self, playlist):
|
|
return sub(r'[\/\n\r]', "", playlist)
|
|
|
|
@property
|
|
def playlists(self):
|
|
if self._playlists:
|
|
return self._playlists
|
|
|
|
playlists = self.sp.user_playlists(self.username)
|
|
|
|
while playlists:
|
|
for playlist in playlists['items']:
|
|
for track in self.sp.user_playlist(self.username,
|
|
playlist["id"],
|
|
fields="tracks,next")["tracks"]["items"]:
|
|
|
|
self._playlists[self.sanitize_playlist(playlist["name"])].append(
|
|
self.fmt_track(track["track"]["id"])
|
|
)
|
|
|
|
if playlists["next"]:
|
|
playlists = self.sp.next(playlists)
|
|
else:
|
|
playlists = None
|
|
|
|
return self._playlists
|
|
|
|
def persist_playlists(self):
|
|
for playlist in self.playlists:
|
|
try:
|
|
# The actual MPD playlist as it currently is
|
|
current_playlist_stored = set(self.mpd_client.listplaylist(playlist))
|
|
except CommandError as e:
|
|
print(e)
|
|
current_playlist_stored = set()
|
|
|
|
# The spotify playlist as it currently is
|
|
new_playlist = self.playlists[playlist]
|
|
|
|
if set(new_playlist) != current_playlist_stored:
|
|
print("{0} has missing tracks, trying to add them".format(playlist))
|
|
try:
|
|
self.mpd_client.playlistclear(playlist)
|
|
except CommandError as e:
|
|
print(e)
|
|
|
|
# Now it should be safe to add any new playlist items
|
|
for track_id in new_playlist:
|
|
try:
|
|
self.mpd_client.playlistadd(playlist, track_id)
|
|
except CommandError as e:
|
|
print(e)
|
|
print("Could not add {0}".format(track_id))
|
|
continue
|
|
|
|
|
|
def run_sync():
|
|
spotify = Spotify()
|
|
spotify.persist_playlists()
|
|
|