Fixed bugs and optimized code
This commit is contained in:
@@ -825,9 +825,6 @@ class Player(VoiceProtocol):
|
||||
if self.is_paused:
|
||||
await self.set_pause(True)
|
||||
|
||||
if self.volume != 100:
|
||||
await self.set_volume(self.volume)
|
||||
|
||||
async def get_recommendations(self, *, track: Optional[Track] = None) -> bool:
|
||||
"""Get recommendations from Youtube or Spotify."""
|
||||
if not track:
|
||||
|
||||
@@ -566,12 +566,12 @@ class NodePool:
|
||||
This option is preferred if you want to choose the best node
|
||||
from a multi-node setup using either the node's latency
|
||||
or the node's voice region.
|
||||
Use NodeAlgorithm.by_ping if you want to get the best node
|
||||
Use NodeAlgorithm.BY_PING if you want to get the best node
|
||||
based on the node's latency.
|
||||
Use NodeAlgorithm.by_region if you want to get the best node
|
||||
based on the node's voice region. This method will only work
|
||||
if you set a voice region when you create a node.
|
||||
Use NodeAlgorithm.by_players if you want to get the best node
|
||||
Use NodeAlgorithm.BY_PLAYERS if you want to get the best node
|
||||
based on how players it has. This method will return a node with
|
||||
the least amount of players
|
||||
"""
|
||||
@@ -580,11 +580,11 @@ class NodePool:
|
||||
if not available_nodes:
|
||||
raise NoNodesAvailable("There are no nodes available.")
|
||||
|
||||
if algorithm == NodeAlgorithm.by_ping:
|
||||
if algorithm == NodeAlgorithm.BY_PING:
|
||||
tested_nodes = {node: node.latency for node in available_nodes}
|
||||
return min(tested_nodes, key=tested_nodes.get)
|
||||
|
||||
elif algorithm == NodeAlgorithm.by_players:
|
||||
elif algorithm == NodeAlgorithm.BY_PLAYERS:
|
||||
tested_nodes = {node: len(node.players.keys()) for node in available_nodes}
|
||||
return min(tested_nodes, key=tested_nodes.get)
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ class Client:
|
||||
self._categories: List[Category] = []
|
||||
|
||||
async def _fetch_bearer_token(self) -> None:
|
||||
"""Fetches and stores a bearer token for API authentication."""
|
||||
if self._client_id and self._client_secret:
|
||||
url, data = GRANT_URL, {"grant_type": "client_credentials"}
|
||||
else:
|
||||
@@ -90,6 +91,7 @@ class Client:
|
||||
self._bearer_headers = {"Authorization": f"Bearer {self._bearer_token}"}
|
||||
|
||||
async def get_request(self, url: str) -> Dict:
|
||||
"""Performs a GET request to the specified URL with authorization headers."""
|
||||
if not self._bearer_token or time.time() >= self._expiry:
|
||||
await self._fetch_bearer_token()
|
||||
|
||||
@@ -102,68 +104,72 @@ class Client:
|
||||
return await resp.json()
|
||||
|
||||
async def track_search(self, query: str, track: str = "track", limit: int = 10) -> List[Track]:
|
||||
"""Searches for tracks based on the provided query and returns a list of Track objects."""
|
||||
request_url = SEARCH_URL.format(query=query, type=track, limit=limit)
|
||||
data = await self.get_request(request_url)
|
||||
return [ Track(track) for track in data['tracks']['items'] ]
|
||||
|
||||
async def similar_track(self, seed_tracks: str, *, limit: int = 10) -> List[Track]:
|
||||
"""Retrieves tracks similar to the provided seed tracks and returns them as Track objects."""
|
||||
request_url = SUGGESTION_URL.format(limit=limit, seed_tracks=seed_tracks)
|
||||
data = await self.get_request(request_url)
|
||||
return [ Track(track) for track in data['tracks'] ]
|
||||
|
||||
async def search(self, *, query: str) -> Union[Track, Album, Playlist]:
|
||||
"""Searches for an item (track, album, artist, or playlist) by query and returns the corresponding object."""
|
||||
result = SPOTIFY_URL_REGEX.match(query)
|
||||
spotify_type = result.group("type")
|
||||
spotify_id = result.group("id")
|
||||
|
||||
if not result:
|
||||
raise InvalidSpotifyURL("The Spotify link provided is not valid.")
|
||||
|
||||
spotify_type = result.group("type")
|
||||
spotify_id = result.group("id")
|
||||
request_url = REQUEST_URL.format(type=spotify_type, id=spotify_id)
|
||||
|
||||
if isArtist := (spotify_type == "artist"):
|
||||
request_url += "/top-tracks?market=US"
|
||||
|
||||
data = await self.get_request(request_url)
|
||||
|
||||
if spotify_type == "track":
|
||||
return Track(data)
|
||||
elif spotify_type == "album":
|
||||
return Album(data)
|
||||
elif isArtist:
|
||||
return Artist(data)
|
||||
else:
|
||||
tracks = [
|
||||
|
||||
tracks = [
|
||||
Track(track["track"])
|
||||
for track in data["tracks"]["items"] if track.get("track") is not None
|
||||
]
|
||||
|
||||
if not tracks:
|
||||
raise SpotifyRequestException("This playlist is empty and therefore cannot be queued.")
|
||||
|
||||
next_page_url = data["tracks"].get("next")
|
||||
|
||||
while next_page_url:
|
||||
next_data = await self.get_request(next_page_url)
|
||||
tracks.extend([
|
||||
Track(track["track"])
|
||||
for track in data["tracks"]["items"] if track["track"] is not None
|
||||
]
|
||||
if not tracks:
|
||||
raise SpotifyRequestException("This playlist is empty and therefore cannot be queued.")
|
||||
for track in next_data.get("items", []) if track.get("track") is not None
|
||||
])
|
||||
next_page_url = next_data.get("next")
|
||||
|
||||
next_page_url = data["tracks"]["next"]
|
||||
|
||||
while next_page_url is not None:
|
||||
async with self.session.get(next_page_url, headers=self._bearer_headers) as resp:
|
||||
if resp.status != 200:
|
||||
raise SpotifyRequestException(
|
||||
f"Error while fetching results: {resp.status} {resp.reason}"
|
||||
)
|
||||
|
||||
next_data: Dict = await resp.json()
|
||||
|
||||
tracks += [
|
||||
Track(track["track"])
|
||||
for track in next_data["items"] if track["track"] is not None
|
||||
]
|
||||
next_page_url = next_data["next"]
|
||||
|
||||
return Playlist(data, tracks)
|
||||
return Playlist(data, tracks)
|
||||
|
||||
async def get_categories(self) -> List[Category]:
|
||||
"""Fetches and returns available music categories from the Spotify API."""
|
||||
if not self._categories:
|
||||
request_url = f"{BASE_URL}browse/categories"
|
||||
data = await self.get_request(request_url)
|
||||
self._categories = [Category(item) for item in data.get("items", [])]
|
||||
|
||||
while request_url:
|
||||
data = await self.get_request(request_url)
|
||||
items = data.get("categories", {}).get("items", [])
|
||||
self._categories.extend(Category(item) for item in items)
|
||||
request_url = data.get("categories", {}).get("next")
|
||||
|
||||
return self._categories
|
||||
|
||||
async def close(self) -> None:
|
||||
"""Closes the HTTP session used for making API requests."""
|
||||
await self.session.close()
|
||||
@@ -129,7 +129,7 @@ class Category:
|
||||
self.href: str = data.get("href")
|
||||
self.id: str = data.get("id")
|
||||
self.name: str = data.get("name")
|
||||
self.icon: str = data.get("icon", [])[0].get("url")
|
||||
self.icon: str = data.get("icons", [{}])[0].get("url")
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return (f"<Voicelink.spotify.Category name={self.name} id={self.id}")
|
||||
Reference in New Issue
Block a user