A commandline tool to synchronize your Spotify playlists to Music Player Daemon
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.

98 lines
3.3 KiB

#! /usr/bin/env python
import gevent.monkey
gevent.monkey.patch_all()
import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
from spotipy.util import prompt_for_user_token
from mpd import MPDClient
from mpd.base import CommandError
from collections import defaultdict
from re import sub
from os import environ
import spotipy.util as util
from spotify_mpd_sync.msplaylist.authenticate import prompt_for_user_token
class Spotify():
def __init__(self):
self.username = environ.get("SPOTIFY_USERNAME")
scope = "playlist-read-private"
token = prompt_for_user_token(self.username,
scope,
client_id=environ.get("SPOTIPY_CLIENT_ID"),
client_secret=environ.get("SPOTIPY_CLIENT_SECRET"),
redirect_uri=environ.get("SPOTIPY_REDIRECT_URI"))
if token:
self.sp = spotipy.Spotify(auth=token)
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:
print(track_id)
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()