diff --git a/pomice/__init__.py b/pomice/__init__.py index b9de886..26c9f49 100644 --- a/pomice/__init__.py +++ b/pomice/__init__.py @@ -18,7 +18,7 @@ if not discord.version_info.major >= 2: "using 'pip install discord.py'" ) -__version__ = "2.0.1a" +__version__ = "2.1" __title__ = "pomice" __author__ = "cloudwithax" @@ -30,4 +30,5 @@ from .objects import * from .queue import * from .player import * from .pool import * +from .routeplanner import * diff --git a/pomice/applemusic/client.py b/pomice/applemusic/client.py index 7fbcf6d..e0b00b3 100644 --- a/pomice/applemusic/client.py +++ b/pomice/applemusic/client.py @@ -93,13 +93,16 @@ class Client: return Artist(data, tracks=tracks) else: - tracks = [Song(track) for track in data["relationships"]["tracks"]["data"]] + + track_data: dict = data["relationships"]["tracks"] + + tracks = [Song(track) for track in track_data.get("data")] if not len(tracks): raise AppleMusicRequestException("This playlist is empty and therefore cannot be queued.") - if data["relationships"]["tracks"]["next"]: - next_page_url = AM_BASE_URL + data["relationships"]["tracks"]["next"] + if track_data.get("next"): + next_page_url = AM_BASE_URL + track_data.get("next") while next_page_url is not None: async with self.session.get(next_page_url, headers=self.headers) as resp: @@ -112,12 +115,10 @@ class Client: tracks += [Song(track) for track in next_data["data"]] if next_data.get("next"): - next_page_url = AM_BASE_URL + next_data["next"] + next_page_url = AM_BASE_URL + next_data.get("next") else: next_page_url = None - return Playlist(data, tracks) - - + - \ No newline at end of file + return Playlist(data, tracks) \ No newline at end of file diff --git a/pomice/applemusic/objects.py b/pomice/applemusic/objects.py index 070dd48..4b36c31 100644 --- a/pomice/applemusic/objects.py +++ b/pomice/applemusic/objects.py @@ -6,6 +6,7 @@ from typing import List class Song: """The base class for an Apple Music song""" def __init__(self, data: dict) -> None: + self.name: str = data["attributes"]["name"] self.url: str = data["attributes"]["url"] self.isrc: str = data["attributes"]["isrc"] @@ -36,6 +37,7 @@ class Playlist: # we'll use the first song's image as the image for the playlist # because apple dynamically generates playlist covers client-side self.image = self.tracks[0].image + print("worked") def __repr__(self) -> str: return ( diff --git a/pomice/enums.py b/pomice/enums.py index 328d0d5..54217b3 100644 --- a/pomice/enums.py +++ b/pomice/enums.py @@ -1,19 +1,22 @@ +import re + from enum import Enum class SearchType(Enum): - """The enum for the different search types for Pomice. - This feature is exclusively for the Spotify search feature of Pomice. - If you are not using this feature, this class is not necessary. + """ + The enum for the different search types for Pomice. + This feature is exclusively for the Spotify search feature of Pomice. + If you are not using this feature, this class is not necessary. - SearchType.ytsearch searches using regular Youtube, - which is best for all scenarios. + SearchType.ytsearch searches using regular Youtube, + which is best for all scenarios. - SearchType.ytmsearch searches using YouTube Music, - which is best for getting audio-only results. + SearchType.ytmsearch searches using YouTube Music, + which is best for getting audio-only results. - SearchType.scsearch searches using SoundCloud, - which is an alternative to YouTube or YouTube Music. + SearchType.scsearch searches using SoundCloud, + which is an alternative to YouTube or YouTube Music. """ ytsearch = "ytsearch" ytmsearch = "ytmsearch" @@ -22,19 +25,70 @@ class SearchType(Enum): def __str__(self) -> str: return self.value + +class TrackType(Enum): + """ + The enum for the different track types for Pomice. + + TrackType.YOUTUBE defines that the track is from YouTube + + TrackType.SOUNDCLOUD defines that the track is from SoundCloud. + + TrackType.SPOTIFY defines that the track is from Spotify + + TrackType.APPLE_MUSIC defines that the track is from Apple Music. + + TrackType.HTTP defines that the track is from an HTTP source. + """ + + # We don't have to define anything special for these, since these just serve as flags + YOUTUBE = "youtube_track" + SOUNDCLOUD = "soundcloud_track" + SPOTIFY = "spotify_track" + APPLE_MUSIC = "apple_music_track" + HTTP = "http_source" + + def __str__(self) -> str: + return self.value + +class PlaylistType(Enum): + """ + The enum for the different playlist types for Pomice. + + PlaylistType.YOUTUBE defines that the playlist is from YouTube + + PlaylistType.SOUNDCLOUD defines that the playlist is from SoundCloud. + + PlaylistType.SPOTIFY defines that the playlist is from Spotify + + PlaylistType.APPLE_MUSIC defines that the playlist is from Apple Music. + """ + + # We don't have to define anything special for these, since these just serve as flags + YOUTUBE = "youtube_playlist" + SOUNDCLOUD = "soundcloud_playlist" + SPOTIFY = "spotify_playlist" + APPLE_MUSIC = "apple_music_list" + + def __str__(self) -> str: + return self.value + + + class NodeAlgorithm(Enum): - """The enum for the different node algorithms in Pomice. + """ + The enum for the different node algorithms in Pomice. - The enums in this class are to only differentiate different - methods, since the actual method is handled in the - get_best_node() method. + The enums in this class are to only differentiate different + methods, since the actual method is handled in the + get_best_node() method. - NodeAlgorithm.by_ping returns a node based on it's latency, - preferring a node with the lowest response time + NodeAlgorithm.by_ping returns a node based on it's latency, + preferring a node with the lowest response time - NodeAlgorithm.by_players return a nodes based on how many players it has. - This algorithm prefers nodes with the least amount of players. + NodeAlgorithm.by_players return a nodes based on how many players it has. + This algorithm prefers nodes with the least amount of players. """ # We don't have to define anything special for these, since these just serve as flags @@ -45,19 +99,162 @@ class NodeAlgorithm(Enum): return self.value class LoopMode(Enum): - """The enum for the different loop modes. - This feature is exclusively for the queue utility of pomice. - If you are not using this feature, this class is not necessary. + """ + The enum for the different loop modes. + This feature is exclusively for the queue utility of pomice. + If you are not using this feature, this class is not necessary. - LoopMode.TRACK sets the queue loop to the current track. + LoopMode.TRACK sets the queue loop to the current track. - LoopMode.QUEUE sets the queue loop to the whole queue. + LoopMode.QUEUE sets the queue loop to the whole queue. """ # We don't have to define anything special for these, since these just serve as flags - TRACK = "TRACK" + TRACK = "track" QUEUE = "queue" def __str__(self) -> str: - return self.value \ No newline at end of file + return self.value + +class PlatformRecommendation(Enum): + + """ + The enum for choosing what platform you want for recommendations. + This feature is exclusively for the recommendations function. + If you are not using this feature, this class is not necessary. + + PlatformRecommendation.SPOTIFY sets the recommendations to come from Spotify + + PlatformRecommendation.YOUTUBE sets the recommendations to come from YouTube + + """ + + # We don't have to define anything special for these, since these just serve as flags + SPOTIFY = "spotify" + YOUTUBE = "youtube" + + + def __str__(self) -> str: + return self.value + + +class RouteStrategy(Enum): + """ + The enum for specifying the route planner strategy for Lavalink. + This feature is exclusively for the RoutePlanner class. + If you are not using this feature, this class is not necessary. + + RouteStrategy.ROTATE_ON_BAN specifies that the node is rotating IPs + whenever they get banned by Youtube. + + RouteStrategy.LOAD_BALANCE specifies that the node is selecting + random IPs to balance out requests between them. + + RouteStrategy.NANO_SWITCH specifies that the node is switching + between IPs every CPU clock cycle. + + RouteStrategy.ROTATING_NANO_SWITCH specifies that the node is switching + between IPs every CPU clock cycle and is rotating between IP blocks on + ban. + + """ + + ROTATE_ON_BAN = "RotatingIpRoutePlanner" + LOAD_BALANCE = "BalancingIpRoutePlanner" + NANO_SWITCH = "NanoIpRoutePlanner" + ROTATING_NANO_SWITCH = "RotatingNanoIpRoutePlanner" + + +class RouteIPType(Enum): + """ + The enum for specifying the route planner IP block type for Lavalink. + This feature is exclusively for the RoutePlanner class. + If you are not using this feature, this class is not necessary. + + RouteIPType.IPV4 specifies that the IP block type is IPV4 + + RouteIPType.IPV6 specifies that the IP block type is IPV6 + """ + + IPV4 = "Inet4Address" + IPV6 = "Inet6Address" + + +class URLRegex(): + """ + The enums for all the URL Regexes in use by Pomice. + + URLRegex.SPOTIFY_URL returns the Spotify URL Regex. + + URLRegex.DISCORD_MP3_URL returns the Discord MP3 URL Regex. + + URLRegex.YOUTUBE_URL returns the Youtube URL Regex. + + URLRegex.YOUTUBE_PLAYLIST returns the Youtube Playlist Regex. + + URLRegex.YOUTUBE_TIMESTAMP returns the Youtube Timestamp Regex. + + URLRegex.AM_URL returns the Apple Music URL Regex. + + URLRegex.SOUNDCLOUD_URL returns the SoundCloud URL Regex. + + URLRegex.BASE_URL returns the standard URL Regex. + + """ + SPOTIFY_URL = re.compile( + r"https?://open.spotify.com/(?Palbum|playlist|track|artist)/(?P[a-zA-Z0-9]+)" + ) + + DISCORD_MP3_URL = re.compile( + r"https?://cdn.discordapp.com/attachments/(?P[0-9]+)/" + r"(?P[0-9]+)/(?P[a-zA-Z0-9_.]+)+" + ) + + YOUTUBE_URL = re.compile( + r"^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube\.com|youtu.be))" + r"(\/(?:[\w\-]+\?v=|embed\/|v\/)?)([\w\-]+)(\S+)?$" + ) + + YOUTUBE_PLAYLIST_URL = re.compile( + r"^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube\.com|youtu.be))/playlist\?list=.*" + ) + + YOUTUBE_VID_IN_PLAYLIST = re.compile( + r"(?P