def test_artist_ref(): assert translator.ref({ 'DisplayName': 'Foo', 'URI': BASEURI + '/foo', 'Type': 'container', 'TypeEx': ARTIST_TYPE }) == Ref.artist(uri=BASEURI+'/foo', name='Foo')
def raw_artist_to_ref(self, artist): if artist is None: return None return Ref.artist( name=artist.get("name") or UNKNOWN_ARTIST, uri=uri.get_artist_uri(artist.get("id")), )
def test_listallinfo_without_uri(self): tracks = [ Track(uri='dummy:/a', name='a'), Track(uri='dummy:/foo/b', name='b') ] self.backend.library.dummy_library = tracks self.backend.library.dummy_browse_result = { 'dummy:/': [ Ref.track(uri='dummy:/a', name='a'), Ref.directory(uri='dummy:/foo', name='foo'), Ref.album(uri='dummy:/album', name='album'), Ref.artist(uri='dummy:/artist', name='artist'), Ref.playlist(uri='dummy:/pl', name='pl') ], 'dummy:/foo': [Ref.track(uri='dummy:/foo/b', name='b')] } self.send_request('listallinfo') self.assertInResponse('file: dummy:/a') self.assertInResponse('Title: a') self.assertInResponse('directory: /dummy/foo') self.assertInResponse('directory: /dummy/album') self.assertInResponse('directory: /dummy/artist') self.assertInResponse('directory: /dummy/pl') self.assertInResponse('file: dummy:/foo/b') self.assertInResponse('Title: b') self.assertInResponse('OK')
def test_listallinfo_without_uri(self): tracks = [ Track(uri="dummy:/a", name="a"), Track(uri="dummy:/foo/b", name="b"), ] self.backend.library.dummy_library = tracks self.backend.library.dummy_browse_result = { "dummy:/": [ Ref.track(uri="dummy:/a", name="a"), Ref.directory(uri="dummy:/foo", name="foo"), Ref.album(uri="dummy:/album", name="album"), Ref.artist(uri="dummy:/artist", name="artist"), Ref.playlist(uri="dummy:/pl", name="pl"), ], "dummy:/foo": [Ref.track(uri="dummy:/foo/b", name="b")], } self.send_request("listallinfo") self.assertInResponse("file: dummy:/a") self.assertInResponse("Title: a") self.assertInResponse("directory: dummy/foo") self.assertInResponse("directory: dummy/album") self.assertInResponse("directory: dummy/artist") self.assertInResponse("directory: dummy/pl") self.assertInResponse("file: dummy:/foo/b") self.assertInResponse("Title: b") self.assertInResponse("OK")
def test_artist_ref(): assert translator.ref( { "DisplayName": "Foo", "URI": BASEURI + "/foo", "Type": "container", "TypeEx": ARTIST_TYPE, } ) == Ref.artist(uri=BASEURI + "/foo", name="Foo")
def createRef(refType, name, uri): if refType == Ref.TRACK: return Ref.track(name=name, uri=uri) elif refType == Ref.ALBUM: return Ref.album(name=name, uri=uri) elif refType == Ref.ARTIST: return Ref.artist(name=name, uri=uri) elif refType == Ref.DIRECTORY: return Ref.directory(name=name, uri=uri) elif refType == Ref.PLAYLIST: return Ref.album(name=name, uri=uri) else: return None
def make_ref(data): if isinstance(data, Track): ref = Ref.track(uri=data.uri, name=data.name) elif isinstance(data, Album): ref = Ref.album(uri=data.uri, name=data.name) elif isinstance(data, Artist): ref = Ref.artist(uri=data.uri, name=data.name) elif isinstance(data, Playlist): ref = Ref.playlist(uri=data.uri, name=data.name) elif isinstance(data, Directory): ref = Ref.directory(uri=data.uri, name=data.name) return RefWithData(ref, data)
def test_listall_without_uri(self): tracks = [Track(uri='dummy:/a', name='a'), Track(uri='dummy:/foo/b', name='b')] self.backend.library.dummy_library = tracks self.backend.library.dummy_browse_result = { 'dummy:/': [Ref.track(uri='dummy:/a', name='a'), Ref.directory(uri='dummy:/foo', name='foo'), Ref.album(uri='dummy:/album', name='album'), Ref.artist(uri='dummy:/artist', name='artist'), Ref.playlist(uri='dummy:/pl', name='pl')], 'dummy:/foo': [Ref.track(uri='dummy:/foo/b', name='b')]} self.send_request('listall') self.assertInResponse('file: dummy:/a') self.assertInResponse('directory: /dummy/foo') self.assertInResponse('directory: /dummy/album') self.assertInResponse('directory: /dummy/artist') self.assertInResponse('directory: /dummy/pl') self.assertInResponse('file: dummy:/foo/b') self.assertInResponse('OK')
def raw_artist_to_ref(self, artist): if artist is None: return None return Ref.artist(name=artist.get('name') or UNKNOWN_ARTIST, uri=uri.get_artist_uri(artist.get('id')))
def ref(artist): return Ref.artist(name=artist.name, uri=artist.uri)
def artist_ref(json): return Ref.artist(uri=translator.get_artist_uri(json['id']), name=json['name'])
def create_artist(tidal_artist): return Ref.artist(uri="tidal:artist:" + str(tidal_artist.id), name=tidal_artist.name)
def test_artist_constructor(self): ref = Ref.artist(uri='foo', name='bar') self.assertEqual(ref.uri, 'foo') self.assertEqual(ref.name, 'bar') self.assertEqual(ref.type, Ref.ARTIST)
def browse(self, uri): logger.info("YTMusic browsing uri \"%s\"", uri) if uri == "ytm:root": return [ Ref.directory(uri="ytm:artist", name="Artists"), Ref.directory(uri="ytm:album", name="Albums"), Ref.directory(uri="ytm:liked", name="Liked Songs"), ] elif uri == "ytm:artist": try: library_artists = [ Ref.artist( uri=f"ytm:artist?id={a['browseId']}&upload=false", name=a["artist"]) for a in API.get_library_artists(limit=100) ] logger.info("YTMusic found %d artists in library", len(library_artists)) except Exception: logger.exception("YTMusic failed getting artists from library") library_artists = [] # try: # upload_artists = [ # Ref.artist(uri=f"ytm:artist?id={a['browseId']}&upload=true", name=a["artist"]) # for a in API.get_library_upload_artists(limit=100) # ] # logger.info("YTMusic found %d uploaded artists", len(upload_artists)) # except Exception: # logger.exception("YTMusic failed getting uploaded artists") # upload_artists = [] return library_artists # + upload_artists elif uri == "ytm:album": try: library_albums = [ Ref.album(uri=f"ytm:album?id={a['browseId']}&upload=false", name=a["title"]) for a in API.get_library_albums(limit=100) ] logger.info("YTMusic found %d albums in library", len(library_albums)) except Exception: logger.exception("YTMusic failed getting albums from library") library_albums = [] # try: # upload_albums = [ # Ref.album(uri=f"ytm:album?id={a['browseId']}&upload=true", name=a["title"]) # for a in API.get_library_upload_albums(limit=100) # ] # logger.info("YTMusic found %d uploaded albums", len(upload_albums)) # except Exception: # logger.exception("YTMusic failed getting uploaded albums") # upload_albums = [] return library_albums # + upload_albums elif uri == "ytm:liked": try: res = API.get_liked_songs(limit=100) logger.info("YTMusic found %d liked songs", len(res["tracks"])) playlistToTracks(res) return [ Ref.track(uri=f"ytm:video?id={t['videoId']}", name=t["title"]) for t in ("tracks" in res and res["tracks"]) or [] ] except Exception: logger.exception("YTMusic failed getting liked songs") elif uri.startswith("ytm:artist?"): id_, upload = parse_uri(uri) # if upload: # try: # res = API.get_library_upload_artist(id_) # uploadArtistToTracks(res) # return [ # Ref.track(uri=f"ytm:album?id={t['videoId']}", name=t["title"]) # for t in res # ] # logger.info("YTMusic found %d songs for uploaded artist \"%s\"", len(res), res[0]["artist"]["name"]) # except Exception: # logger.exception("YTMusic failed getting tracks for uploaded artist \"%s\"", id_) # else: try: res = API.get_artist(id_) logger.info( "YTMusic found %d songs for artist \"%s\" in library", len(res["songs"]), res["name"]) artistToTracks(res) return [ Ref.track(uri=f"ytm:video?id={t['videoId']}", name=t["title"]) for t in ("songs" in res and "results" in res["songs"] and res["songs"]["results"]) or [] ] except Exception: logger.exception( "YTMusic failed getting tracks for artist \"%s\"", id_) elif uri.startswith("ytm:album?"): id_, upload = parse_uri(uri) # if upload: # try: # res = API.get_library_upload_album(id_) # uploadAlbumToTracks(res, id_) # return [ # Ref.track(uri=f"ytm:video?id={t['videoId']}", name=t["title"]) # for t in ("tracks" in res and res["tracks"]) or [] # ] # logger.info("YTMusic found %d songs for uploaded album \"%s\"", len(res["tracks"]), res["title"]) # except Exception: # logger.exception("YTMusic failed getting tracks for uploaded album \"%s\"", id_) # else: try: res = API.get_album(id_) logger.info( "YTMusic found %d songs for album \"%s\" in library", len(res["tracks"]), res["title"]) albumToTracks(res, id_) return [ Ref.track(uri=f"ytm:video?id={t['videoId']}", name=t["title"]) for t in ("tracks" in res and res["tracks"]) or [] ] except Exception: logger.exception( "YTMusic failed getting tracks for album \"%s\"", id_) return []
def browse(self, uri): if not uri: return [] logger.debug("YoutubeMusic browsing uri \"%s\"", uri) if uri == "youtubemusic:root": dirs = [] if self.backend.auth: dirs += [ Ref.directory(uri="youtubemusic:artist", name="Artists"), Ref.directory(uri="youtubemusic:album", name="Albums"), ] if self.backend.liked_songs: dirs.append( Ref.directory(uri="youtubemusic:liked", name="Liked Songs")) if self.backend.history: dirs.append( Ref.directory(uri="youtubemusic:history", name="Recently Played")) if self.backend.subscribed_artist_limit: dirs.append( Ref.directory(uri="youtubemusic:subscriptions", name="Subscriptions")) dirs.append( Ref.directory(uri="youtubemusic:watch", name="Similar to last played")) if self.backend.mood_genre: dirs.append( Ref.directory(uri="youtubemusic:mood", name="Mood and Genre Playlists")) if self.backend._auto_playlist_refresh_rate: dirs.append( Ref.directory(uri="youtubemusic:auto", name="Auto Playlists")) return (dirs) elif uri == "youtubemusic:subscriptions" and self.backend.subscribed_artist_limit: try: subs = self.backend.api.get_library_subscriptions( limit=self.backend.subscribed_artist_limit) logger.debug("YoutubeMusic found %d artists in subscriptions", len(subs)) return [ Ref.artist(uri=f"youtubemusic:artist:{a['browseId']}", name=a["artist"]) for a in subs ] except Exception: logger.exception( "YoutubeMusic failed getting artists from subscriptions") elif uri == "youtubemusic:artist": try: library_artists = [ Ref.artist(uri=f"youtubemusic:artist:{a['browseId']}", name=a["artist"]) for a in self.backend.api.get_library_artists(limit=100) ] logger.debug("YoutubeMusic found %d artists in library", len(library_artists)) except Exception: logger.exception( "YoutubeMusic failed getting artists from library") library_artists = [] if self.backend.auth: try: upload_artists = [ Ref.artist( uri=f"youtubemusic:artist:{a['browseId']}:upload", name=a["artist"]) for a in self.backend.api.get_library_upload_artists( limit=100) ] logger.debug("YoutubeMusic found %d uploaded artists", len(upload_artists)) except Exception: logger.exception( "YoutubeMusic failed getting uploaded artists") upload_artists = [] else: upload_artists = [] return library_artists + upload_artists elif uri == "youtubemusic:album": try: library_albums = [ Ref.album(uri=f"youtubemusic:album:{a['browseId']}", name=a["title"]) for a in self.backend.api.get_library_albums(limit=100) ] logger.debug("YoutubeMusic found %d albums in library", len(library_albums)) except Exception: logger.exception( "YoutubeMusic failed getting albums from library") library_albums = [] if self.backend.auth: try: upload_albums = [ Ref.album( uri=f"youtubemusic:album:{a['browseId']}:upload", name=a["title"]) for a in self.backend.api.get_library_upload_albums( limit=100) ] logger.debug("YoutubeMusic found %d uploaded albums", len(upload_albums)) except Exception: logger.exception( "YoutubeMusic failed getting uploaded albums") upload_albums = [] else: upload_albums = [] return library_albums + upload_albums elif uri == "youtubemusic:liked": try: res = self.backend.api.get_liked_songs( limit=self.backend.playlist_item_limit) tracks = self.playlistToTracks(res) logger.debug("YoutubeMusic found %d liked songs", len(res["tracks"])) return [Ref.track(uri=t.uri, name=t.name) for t in tracks] except Exception: logger.exception("YoutubeMusic failed getting liked songs") elif uri == "youtubemusic:history": try: res = self.backend.api.get_history() tracks = self.playlistToTracks({'tracks': res}) logger.debug("YoutubeMusic found %d songs from recent history", len(res)) return [Ref.track(uri=t.uri, name=t.name) for t in tracks] except Exception: logger.exception( "YoutubeMusic failed getting listening history") elif uri == "youtubemusic:watch": try: playback = self.backend.playback if playback.last_id is not None: track_id = playback.last_id elif self.backend.auth: hist = self.backend.api.get_history() track_id = hist[0]['videoId'] if track_id: res = self.backend.api.get_watch_playlist( track_id, limit=self.backend.playlist_item_limit) if 'tracks' in res: logger.debug( "YoutubeMusic found %d watch songs for \"%s\"", len(res["tracks"]), track_id) res['tracks'].pop(0) tracks = self.playlistToTracks(res) return [ Ref.track(uri=t.uri, name=t.name) for t in tracks ] except Exception: logger.exception("YoutubeMusic failed getting watch songs") elif uri == "youtubemusic:mood": try: logger.debug('YoutubeMusic loading mood/genre playlists') moods = {} response = self.backend.api._send_request( 'browse', {"browseId": "FEmusic_moods_and_genres"}) for sect in nav(response, SINGLE_COLUMN_TAB + SECTION_LIST): for cat in nav(sect, ['gridRenderer', 'items']): title = nav(cat, [ 'musicNavigationButtonRenderer', 'buttonText', 'runs', 0, 'text' ]).strip() endpnt = nav(cat, [ 'musicNavigationButtonRenderer', 'clickCommand', 'browseEndpoint', 'browseId' ]) params = nav(cat, [ 'musicNavigationButtonRenderer', 'clickCommand', 'browseEndpoint', 'params' ]) moods[title] = { 'name': title, 'uri': 'youtubemusic:mood:' + params + ':' + endpnt } return [ Ref.directory(uri=moods[a]['uri'], name=moods[a]['name']) for a in sorted(moods.keys()) ] except Exception: logger.exception( 'YoutubeMusic failed to load mood/genre playlists') elif uri.startswith("youtubemusic:mood:"): try: ret = [] _, _, params, endpnt = uri.split(':') response = self.backend.api._send_request( 'browse', { "browseId": endpnt, "params": params }) for sect in nav(response, SINGLE_COLUMN_TAB + SECTION_LIST): key = [] if 'gridRenderer' in sect: key = ['gridRenderer', 'items'] elif 'musicCarouselShelfRenderer' in sect: key = ['musicCarouselShelfRenderer', 'contents'] elif 'musicImmersiveCarouselShelfRenderer' in sect: key = [ 'musicImmersiveCarouselShelfRenderer', 'contents' ] if len(key): for item in nav(sect, key): title = nav(item, ['musicTwoRowItemRenderer'] + TITLE_TEXT).strip() # if 'subtitle' in item['musicTwoRowItemRenderer']: # title += ' (' # for st in item['musicTwoRowItemRenderer']['subtitle']['runs']: # title += st['text'] # title += ')' brId = nav(item, ['musicTwoRowItemRenderer'] + NAVIGATION_BROWSE_ID) ret.append( Ref.playlist( uri=f"youtubemusic:playlist:{brId}", name=title)) return (ret) except Exception: logger.exception( 'YoutubeMusic failed getting mood/genre playlist "%s"', uri) elif uri == "youtubemusic:auto" and self.backend._auto_playlist_refresh_rate: try: return [ Ref.directory(uri=a['uri'], name=a['name']) for a in self.ytbrowse ] except Exception: logger.exception('YoutubeMusic failed getting auto playlists') elif uri.startswith("youtubemusic:auto:" ) and self.backend._auto_playlist_refresh_rate: try: for a in self.ytbrowse: if a['uri'] == uri: ret = [] for i in a['items']: if i['type'] == 'playlist': ret.append( Ref.playlist(uri=i['uri'], name=i['name'])) logger.debug("playlist: %s - %s", i['name'], i['uri']) elif i['type'] == 'artist': ret.append( Ref.artist(uri=i['uri'], name=i['name'])) logger.debug("artist: %s - %s", i['name'], i['uri']) elif i['type'] == 'album': ret.append( Ref.album(uri=i['uri'], name=i['name'])) logger.debug("album: %s - %s", i['name'], i['uri']) return (ret) except Exception: logger.exception( 'YoutubeMusic failed getting auto playlist "%s"', uri) elif uri.startswith("youtubemusic:artist:"): bId, upload = parse_uri(uri) if upload: try: res = self.backend.api.get_library_upload_artist(bId) tracks = self.uploadArtistToTracks(res) logger.debug( "YoutubeMusic found %d songs for uploaded artist \"%s\"", len(res), res[0]["artist"]["name"]) return [Ref.track(uri=t.uri, name=t.name) for t in tracks] except Exception: logger.exception( "YoutubeMusic failed getting tracks for uploaded artist \"%s\"", bId) else: try: res = self.backend.api.get_artist(bId) tracks = self.artistToTracks(res) logger.debug( "YoutubeMusic found %d songs for artist \"%s\" in library", len(res["songs"]), res["name"]) return [Ref.track(uri=t.uri, name=t.name) for t in tracks] except Exception: logger.exception( "YoutubeMusic failed getting tracks for artist \"%s\"", bId) elif uri.startswith("youtubemusic:album:"): bId, upload = parse_uri(uri) if upload: try: res = self.backend.api.get_library_upload_album(bId) tracks = self.uploadAlbumToTracks(res, bId) logger.debug( "YoutubeMusic found %d songs for uploaded album \"%s\"", len(res["tracks"]), res["title"]) return [Ref.track(uri=t.uri, name=t.name) for t in tracks] except Exception: logger.exception( "YoutubeMusic failed getting tracks for uploaded album \"%s\"", bId) else: try: res = self.backend.api.get_album(bId) tracks = self.albumToTracks(res, bId) logger.debug( "YoutubeMusic found %d songs for album \"%s\" in library", len(res["tracks"]), res["title"]) return [Ref.track(uri=t.uri, name=t.name) for t in tracks] except Exception: logger.exception( "YoutubeMusic failed getting tracks for album \"%s\"", bId) elif uri.startswith("youtubemusic:playlist:"): bId, upload = parse_uri(uri) try: res = self.backend.api.get_playlist( bId, limit=self.backend.playlist_item_limit) tracks = self.playlistToTracks(res) return [Ref.track(uri=t.uri, name=t.name) for t in tracks] except Exception: logger.exception( "YoutubeMusic failed to get tracks from playlist '%s'", bId) return []
def test_artist_constructor(self): ref = Ref.artist(uri="foo", name="bar") assert ref.uri == "foo" assert ref.name == "bar" assert ref.type == Ref.ARTIST
def create_artist(tidal_artist): create_mopidy_artist(tidal_artist) return Ref.artist(uri="tidal:artist:{0}".format(tidal_artist.id), name=tidal_artist.name)