From bb7cd1f7027982469fa445ccfa64e74a66755d0e Mon Sep 17 00:00:00 2001 From: David Ziegler <25408738+InfinityMod@users.noreply.github.com> Date: Sat, 27 Feb 2021 23:44:01 +0100 Subject: [PATCH] Adds support to match Spotify tracks to Tidal tracks and to playback them via Tidal in the chosen quality. Is only enabled by setting: tidal -> spotify_proxy = true. Also tidal -> spotify_client_id and tidal -> spotify_client_secret have to be added additionally inside the config. Works with free spotify accounts. --- mopidy_tidal/__init__.py | 3 +++ mopidy_tidal/backend.py | 5 ++++- mopidy_tidal/ext.conf | 3 +++ mopidy_tidal/library.py | 14 +++++++++++++- mopidy_tidal/spotify_proxy.py | 23 +++++++++++++++++++++++ setup.py | 1 + 6 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 mopidy_tidal/spotify_proxy.py diff --git a/mopidy_tidal/__init__.py b/mopidy_tidal/__init__.py index 3d686de8..6d19286c 100755 --- a/mopidy_tidal/__init__.py +++ b/mopidy_tidal/__init__.py @@ -30,6 +30,9 @@ def get_config_schema(self): schema['username'] = config.String() schema['password'] = config.Secret() schema['quality'] = config.String(choices=["LOSSLESS", "HIGH", "LOW"]) + schema['spotify_proxy'] = config.Boolean(optional=True) + schema['spotify_client_id'] = config.String(optional=True) + schema['spotify_client_secret'] = config.String(optional=True) return schema def setup(self, registry): diff --git a/mopidy_tidal/backend.py b/mopidy_tidal/backend.py index f90ce2da..65a63fe1 100755 --- a/mopidy_tidal/backend.py +++ b/mopidy_tidal/backend.py @@ -25,7 +25,10 @@ def __init__(self, config, audio): backend=self) self.library = library.TidalLibraryProvider(backend=self) self.playlists = playlists.TidalPlaylistsProvider(backend=self) - self.uri_schemes = ['tidal'] + if config['tidal']['spotify_proxy']: + self.uri_schemes = ['tidal', 'spotify'] + else: + self.uri_schemes = ['tidal'] def on_start(self): quality = self._config['tidal']['quality'] diff --git a/mopidy_tidal/ext.conf b/mopidy_tidal/ext.conf index 3ad9db90..6ab40b23 100644 --- a/mopidy_tidal/ext.conf +++ b/mopidy_tidal/ext.conf @@ -3,3 +3,6 @@ enabled = true username= password= quality=LOSSLESS +spotify_proxy = false +spotify_client_id = "" +spotify_client_secret = "" \ No newline at end of file diff --git a/mopidy_tidal/library.py b/mopidy_tidal/library.py index a74fb522..8f9d5e88 100755 --- a/mopidy_tidal/library.py +++ b/mopidy_tidal/library.py @@ -18,6 +18,7 @@ from mopidy_tidal.utils import apply_watermark +from mopidy_tidal.spotify_proxy import SpotifyProxy logger = logging.getLogger(__name__) @@ -45,6 +46,11 @@ def __init__(self, *args, **kwargs): self.lru_artist_img = LruCache() self.lru_album_img = LruCache() self.track_cache = Cache() + self.config = kwargs["backend"]._config + if self.config["tidal"]["spotify_proxy"]: + self.spotify_proxy = SpotifyProxy(str(self.config["tidal"]["spotify_client_id"]), + str(self.config["tidal"]["spotify_client_secret"])) + def get_distinct(self, field, query=None): logger.debug("Browsing distinct %s with query %r", field, query) @@ -88,7 +94,6 @@ def browse(self, uri): session = self.backend._session # summaries - if uri == self.root_directory.uri: return ref_models_mappers.create_root() @@ -205,6 +210,13 @@ def lookup(self, uris=None): tracks = [] for uri in uris: parts = uri.split(':') + logger.info('URI: %s', uri) + if uri.startswith('spotify:track:'): + info = self.spotify_proxy.get_song_info(uri) + if info is not None: + result = self.search(query={"track_name": [info["title"] + " " + " ".join(info["artists"])]}) + if len(result.tracks) > 0: + tracks.append(result.tracks[0]) if uri.startswith('tidal:track:'): if uri in self.track_cache: tracks.append(self.track_cache[uri]) diff --git a/mopidy_tidal/spotify_proxy.py b/mopidy_tidal/spotify_proxy.py new file mode 100644 index 00000000..003b2ea2 --- /dev/null +++ b/mopidy_tidal/spotify_proxy.py @@ -0,0 +1,23 @@ +import spotipy +from spotipy.oauth2 import SpotifyClientCredentials + +class SpotifyProxy: + def __init__(self, client_id, client_secret): + self.set_credentials(client_id, client_secret) + + def set_credentials(self, client_id, client_secret): + self.credentials = SpotifyClientCredentials( + client_id=client_id, + client_secret=client_secret + ) + + def get_song_info(self, lz_uri): + spotify = spotipy.Spotify(client_credentials_manager = self.credentials) + results = spotify.tracks([lz_uri]) + if len(results['tracks']) > 0: + track = results['tracks'][-1] + title = track["name"] + artists = [a["name"] for a in track["artists"]] + return {"title": title, "artists": artists} + else: + return None diff --git a/setup.py b/setup.py index 9ec6fe01..f30507f2 100644 --- a/setup.py +++ b/setup.py @@ -29,6 +29,7 @@ def get_version(filename): 'Pykka >= 1.1', 'tidalapi >= 0.6.7,<0.7.0', 'requests >= 2.0.0', + 'spotipy >= 2.16.0' ], entry_points={ 'mopidy.ext': [