async def spotify_album(self, album_url) -> List[Song]: """ Retrieves an album from Spotify. @param album_url: @return: """ token = await self._request_token() album = SpotifyType(album_url) if not album.valid: raise PlaylistExtractionException() url = "https://api.spotify.com/v1/albums/" + album.id + "?limit=50" header = {"Authorization": "Bearer " + token} result = await self._request_get(url, header) json_result = json.loads(result) if "error" in json_result: raise PlaylistExtractionException() track_list = [] for item in json_result["tracks"]["items"]: track_list.append( Song( title=f"{item['artists'][0]['name']} - {item['name']}", artist=item["artists"][0]["name"], image_url=json_result["images"][0]["url"], song_name=item["name"], )) if not track_list: raise PlaylistExtractionException() return track_list
async def spotify_artist(self, artist_url: str) -> List[Song]: """ Retrieves a Spotify Artist @param artist_url: @return: """ token = await self._request_token() artist = SpotifyType(artist_url) if not artist.valid: raise PlaylistExtractionException() url = ("https://api.spotify.com/v1/artists/" + artist.id + "/top-tracks?country=DE") header = {"Authorization": "Bearer " + token} result = await self._request_get(url, header) json_result = json.loads(result) if "error" in json_result: raise PlaylistExtractionException() track_list = [] for item in json_result["tracks"]: track_list.append( Song( title=f"{item['artists'][0]['name']} - {item['name']}", artist=item["artists"][0]["name"], image_url=item["album"]["images"][0]["url"], song_name=item["name"], )) if not track_list: raise PlaylistExtractionException return track_list
def test_spotify_id_extraction(self): """ Test Spotify ID Extraction @return: """ self.assertEqual( SpotifyType( "https://open.spotify.com/track/6GyFP1nfCDB8lbD2bG0Hq9" "?si=o-6i8HRoSe6yftQmciVOvg" ).id, "6GyFP1nfCDB8lbD2bG0Hq9", ) self.assertEqual( SpotifyType("spotify:track:6GyFP1nfCDB8lbD2bG0Hq9").id, "6GyFP1nfCDB8lbD2bG0Hq9", ) self.assertEqual( SpotifyType(url="https://www.youtube.com/watch?v=spzZHIPMd6Q").id, None, )
def test_spotify_detect_type(self): """ Tests the Spotify test type @return: """ self.assertEqual( SpotifyType( url="https://open.spotify.com/track/0qi4b1l0eT3jpzeNHeFXDT" "?si=qVMwkN1ySXSw2KJ-Bo_MAQ", ).type, SpotifyType.SPOTIFY_URL, ) self.assertEqual( SpotifyType(url="spotify:track:0qi4b1l0eT3jpzeNHeFXDT").type, SpotifyType.SPOTIFY_URI, ) self.assertEqual( SpotifyType(url="https://www.youtube.com/watch?v=spzZHIPMd6Q").type, None, )
def test_spotify_pattern(self): """ Tests the Spotify Patterns with different Spotify URLS """ for url, expected in Test.spotify_urls: if ( re.match(VariableStore.spotify_url_pattern, url) is not None or re.match(VariableStore.spotify_uri_pattern, url) is not None ): self.assertEqual(expected, True) else: self.assertEqual(expected, False) self.assertEqual(SpotifyType(url).valid, expected)
async def spotify_track(self, track_url): token = await self.request_token() track = SpotifyType(track_url) if not track.valid: return None url = "https://api.spotify.com/v1/tracks/" + track.id header = {"Authorization": "Bearer " + token} result = await self.request_get(url, header) result = json.loads(result) return SpotifySong( title=result["artists"][0]["name"] + " - " + result["name"], image_url=result["album"]["images"][0]["url"], song_name=result["name"], artist=result["artists"][0]["name"], )
async def spotify_album(self, album_url): token = await self.request_token() album = SpotifyType(album_url) if not album.valid: return [] url = ( "https://api.spotify.com/v1/albums/" + album.id + "/tracks?limit=50" ) header = {"Authorization": "Bearer " + token} result = await self.request_get(url, header) js = json.loads(result) track_list = [] for item in js["items"]: artist = item["artists"][0]["name"] song = item["name"] track_list.append(artist + " - " + song) return track_list
async def play_check(self, ctx, url): if not await self.join_check(ctx, url): return False if not await self.join_channel(ctx=ctx): return False yt = YouTubeType(url) sp = SpotifyType(url) sc = SoundCloudType(url) if yt.valid or sp.valid or sc.valid or url.lower() == "charts": return True if re.match(VariableStore.url_pattern, url) is not None: await self.parent.send_embed_message( ctx, "This is not a valid/supported url.") return False return True
async def spotify_artist(self, artist_url): token = await self.request_token() artist = SpotifyType(artist_url) if not artist.valid: return [] url = ( "https://api.spotify.com/v1/artists/" + artist.id + "/top-tracks?country=DE" ) header = {"Authorization": "Bearer " + token} result = await self.request_get(url, header) js = json.loads(result) track_list = [] for item in js["tracks"]: artist = item["artists"][0]["name"] song = item["name"] track_list.append(artist + " - " + song) return track_list
async def spotify_track(self, track_url) -> Song: """ Extract Information from a Spotify Track url. @param track_url: Spotify Track Url @return: Spotify Song @rtype: Song """ token = await self._request_token() track = SpotifyType(track_url) if not track.valid: raise SongExtractionException() url = "https://api.spotify.com/v1/tracks/" + track.id header = {"Authorization": "Bearer " + token} result = await self._request_get(url, header) result = json.loads(result) if "error" in result: raise SongExtractionException() return Song( title=result["artists"][0]["name"] + " - " + result["name"], image_url=result["album"]["images"][0]["url"], song_name=result["name"], artist=result["artists"][0]["name"], )
async def play_check(self, ctx: commands.Context, url: str) -> bool: """ Checks if a url or term is supported by the bots architecture. @param ctx: @param url: @return: """ if not await self.join_check(ctx): return False if not await self.join_channel(ctx=ctx): return False youtube_type = YouTubeType(url) spotify_type = SpotifyType(url) soundcloud_type = SoundCloudType(url) if (youtube_type.valid or spotify_type.valid or soundcloud_type.valid or url.lower() == "charts"): return True if re.match(VariableStore.url_pattern, url) is not None: await self.parent.send_embed_message( ctx, "This is not a valid/supported url.") return False return True
async def spotify_playlist(self, playlist_url): token = await self.request_token() playlist = SpotifyType(playlist_url) if not playlist.valid: return [] url = ( "https://api.spotify.com/v1/playlists/" + playlist.id + "/tracks?limit=100&offset=0" ) header = {"Authorization": "Bearer " + token} result = await self.request_get(url, header) js = json.loads(result) t_list = [] more = True while more is True: try: for track in js["items"]: if track["is_local"]: try: t_list.append( SpotifySong( title=track["track"]["artists"][0]["name"] + " - " + track["track"]["name"], image_url=None, song_name=track["track"]["name"], artist=track["track"]["artists"][0]["name"], ) ) except (IndexError, KeyError): # Probably invalid local file continue else: t_list.append( SpotifySong( title=track["track"]["album"]["artists"][0][ "name" ] + " - " + track["track"]["name"], image_url=track["track"]["album"]["images"][0][ "url" ], song_name=track["track"]["name"], artist=track["track"]["artists"][0]["name"], ) ) if js["next"] is None: more = False else: url = js["next"] result = await self.request_get(url, header) js = json.loads(result) except KeyError as key_error: self.log.warning( logging_manager.debug_info(str(key_error) + " " + str(js)) ) if "error" in js: self.token = "" more = False return t_list
async def spotify_playlist(self, playlist_url) -> List[Song]: """ Extracts all songs from a spotify playlist. @param playlist_url: Spotify Playlist Url @return: List of Songs @rtype: List[Song] """ token = await self._request_token() playlist = SpotifyType(playlist_url) if not playlist.valid: raise PlaylistExtractionException() url = ("https://api.spotify.com/v1/playlists/" + playlist.id + "/tracks?limit=100&offset=0") header = {"Authorization": "Bearer " + token} result = await self._request_get(url, header) json_result = json.loads(result) if "error" in json_result: raise PlaylistExtractionException() t_list = [] more = True while more is True: try: for track in json_result["items"]: if track["is_local"]: try: t_list.append( Song( title=track["track"]["artists"][0]["name"] + " - " + track["track"]["name"], image_url=None, song_name=track["track"]["name"], artist=track["track"]["artists"][0] ["name"], )) except ( IndexError, KeyError, TypeError, ): # pragma: no cover # Probably invalid local file continue else: try: t_list.append( Song( title=track["track"]["album"]["artists"][0] ["name"] + " - " + track["track"]["name"], image_url=track["track"]["album"]["images"] [0]["url"], song_name=track["track"]["name"], artist=track["track"]["artists"][0] ["name"], )) except ( IndexError, KeyError, TypeError, ): # catch preemtively to prevent # no-response pass if json_result["next"] is None: more = False else: url = json_result["next"] result = await self._request_get(url, header) json_result = json.loads(result) except KeyError as key_error: self.log.warning( logging_manager.debug_info( str(key_error) + " " + str(json_result))) if "error" in json_result: self.token = "" more = False if not t_list: raise PlaylistExtractionException() return t_list