From 60bace9f2885270c566b406460731a49a2103fc4 Mon Sep 17 00:00:00 2001 From: Parker Date: Fri, 29 Nov 2024 22:57:11 -0600 Subject: [PATCH] Add support for Spotify `artist` links --- code/utils/custom_sources.py | 28 ++++++++ code/utils/source_helpers/parse.py | 13 +++- code/utils/source_helpers/spotify/artist.py | 77 +++++++++++++++++++++ test.py | 3 - 4 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 code/utils/source_helpers/spotify/artist.py delete mode 100644 test.py diff --git a/code/utils/custom_sources.py b/code/utils/custom_sources.py index ed00c66..ee441d6 100644 --- a/code/utils/custom_sources.py +++ b/code/utils/custom_sources.py @@ -153,6 +153,34 @@ class SpotifySource(Source): LoadType.PLAYLIST, tracks, playlist_info=PlaylistInfo.none() ) + async def load_artist(self, user, metadata): + tracks = [] + for track in metadata["tracks"]: + try: + artwork_url = track["album"]["images"][0]["url"] + except IndexError: + artwork_url = None + tracks.append( + CustomAudioTrack( + { + "identifier": track["id"], + "isSeekable": True, + "author": track["artists"][0]["name"], + "length": track["duration_ms"], + "isStream": False, + "title": track["name"], + "uri": track["external_urls"]["spotify"], + "duration": track["duration_ms"], + "artworkUrl": artwork_url, + }, + requester=user, + ) + ) + + return LoadResult( + LoadType.PLAYLIST, tracks, playlist_info=PlaylistInfo.none() + ) + """ Custom Source for Apple Music links diff --git a/code/utils/source_helpers/parse.py b/code/utils/source_helpers/parse.py index 8489515..b23a895 100644 --- a/code/utils/source_helpers/parse.py +++ b/code/utils/source_helpers/parse.py @@ -7,6 +7,7 @@ from utils.source_helpers.apple import ( ) from utils.source_helpers.spotify import ( album as spotify_album, + artist as spotify_artist, playlist as spotify_playlist, song as spotify_song, ) @@ -29,6 +30,7 @@ async def parse_custom_source( }, "spotify": { "album": spotify_album.load, + "artist": spotify_artist.load, "playlist": spotify_playlist.load, "song": spotify_song.load, }, @@ -43,7 +45,6 @@ async def parse_custom_source( "apple": AppleSource, "spotify": SpotifySource, } - # Catch all songs if "?i=" in query or "/track/" in query: song, embed = await load_funcs[provider]["song"]( @@ -76,5 +77,15 @@ async def parse_custom_source( results = await sources[provider].load_album(self, user, album) else: return None, embed + # Catch Spotify artists + elif "/artist/" in query: + artist, embed = await load_funcs[provider]["artist"]( + headers[provider], query, user + ) + + if artist: + results = await sources[provider].load_artist(self, user, artist) + else: + return None, embed return results, embed diff --git a/code/utils/source_helpers/spotify/artist.py b/code/utils/source_helpers/spotify/artist.py new file mode 100644 index 0000000..995e208 --- /dev/null +++ b/code/utils/source_helpers/spotify/artist.py @@ -0,0 +1,77 @@ +import datetime +import discord +import requests +from typing import Tuple, Optional +from requests.exceptions import JSONDecodeError + +from utils.config import create_embed, LOG + + +async def load( + headers: dict, + query: str, + user: discord.User, +) -> Tuple[Optional[dict], Optional[discord.Embed]]: + """ + Get the artists top tracks from the Spotify API + """ + artist_id = query.split("/artist/")[1] + + try: + # Get the artists songs + response = requests.get( + f"https://api.spotify.com/v1/artists/{artist_id}/top-tracks", + headers=headers, + ) + + if response.status_code == 404: + embed = create_embed( + title="Artist Not Found", + description=( + "Either the provided link is malformed, the artist does" + " not exist, or the artist does not have any songs." + ), + ) + return None, embed + + if response.status_code == 401: + LOG.error( + "Could not authorize with Spotify API. Likely need to" + " restart the bot." + ) + return None, None + + response.raise_for_status() + # Unpack the artists songs + artist = response.json() + name = artist["tracks"][0]["artists"][0]["name"] + num_tracks = len(artist["tracks"]) + + # Get the artist info (for the thumbnail) + response = requests.get( + f"https://api.spotify.com/v1/artists/{artist_id}", + headers=headers, + ) + + response.raise_for_status() + try: + artwork_url = response.json()["images"][0]["url"] + except IndexError: + artwork_url = None + + except IndexError: + LOG.error("Failed unpacking Spotify artist info") + return None, None + except (JSONDecodeError, requests.HTTPError): + LOG.error("Failed making request to Spotify API") + return None, None + + embed = create_embed( + title="Artist Queued", + description=( + f"Top `{num_tracks}` track by **{name}**\n\n" + f"Queued by {user.mention}" + ), + thumbnail=artwork_url, + ) + return artist, embed diff --git a/test.py b/test.py deleted file mode 100644 index bbfe23b..0000000 --- a/test.py +++ /dev/null @@ -1,3 +0,0 @@ -while not Exception: - print("Test") - Exception