Skip to content

Commit

Permalink
feat: better handle remote arl & local arl
Browse files Browse the repository at this point in the history
  • Loading branch information
tristiisch committed Nov 18, 2024
1 parent 03d69c2 commit f0fcbda
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 52 deletions.
58 changes: 27 additions & 31 deletions src/pyramid/connector/deezer/downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@
from pyramid.connector.deezer.downloader_progress_bar import DownloaderProgressBar
from pyramid.connector.deezer.py_deezer import PyDeezer
from pyramid.data.track import Track
from pyramid.tools.generate_token import DeezerTokenProvider, DeezerTokenEmptyException, DeezerTokenOverflowException
from pyramid.tools.generate_token import DeezerTokenProvider
from pydeezer.constants import track_formats
from pydeezer.exceptions import LoginError
from urllib3.exceptions import MaxRetryError

from pyramid.data.exceptions import CustomException
from pyramid.data.exceptions import CustomException, DeezerTokensUnavailableException, DeezerTokenInvalidException, DeezerTokenOverflowException


class DeezerDownloader:
Expand All @@ -28,15 +27,6 @@ def __init__(self, folder: str, arl: Optional[str] = None):
os.makedirs(self.folder_path, exist_ok=True)
self.__deezer_dl_api = None

async def check_credentials(self):
if not self.__deezer_dl_api:
raise Exception("deezer_dl_api not init")
try:
await self.__deezer_dl_api.get_user_data()
return self.__deezer_dl_api.user
except LoginError as err:
raise err # Arl is invalid

async def dl_track_by_id(self, track_id) -> Track | None:
client = await self._get_client()
# try:
Expand Down Expand Up @@ -96,25 +86,21 @@ async def __dl_track(self, track_info, file_name: str) -> bool:
return False

async def _get_client(self) -> PyDeezer:
if not self.__deezer_dl_api:
self.__deezer_dl_api = await self._define_client()
return self.__deezer_dl_api
return await self._define_client()

async def _define_client(self) -> PyDeezer:
last_err = None
last_err_local = None
if self.__arls:
for arl in self.__arls:
deezer_dl_api = PyDeezer(arl)
try:
await deezer_dl_api.get_user_data()
return deezer_dl_api
except LoginError as err:
last_err = err
except DeezerTokenInvalidException as err:
last_err_local = err
continue
if last_err is not None:
raise last_err

last_err = None
last_err_remote = None
already_overflow = False
while self.__token_provider.count_valids_tokens() != 0:
try:
Expand All @@ -123,22 +109,32 @@ async def _define_client(self) -> PyDeezer:
await deezer_dl_api.get_user_data()
return deezer_dl_api

except DeezerTokenEmptyException as err:
last_err = err
break
except DeezerTokenInvalidException as err:
last_err_remote = err
continue

except DeezerTokenOverflowException as err:
last_err = err
last_err_remote = err
if already_overflow is True:
break
already_overflow = True
self.__token_provider = DeezerTokenProvider()
continue

except LoginError as err:
last_err = err
continue
except DeezerTokensUnavailableException as err:
last_err_remote = err
break

if last_err_local is not None:
tb = traceback.TracebackException.from_exception(last_err_local)
formatted_tb = ''.join(tb.format())
logging.warning("Failed to fetch valid Deezer client from local\n%s", formatted_tb)

if last_err_remote is not None:
tb = traceback.TracebackException.from_exception(last_err_remote)
formatted_tb = ''.join(tb.format())
logging.warning("Failed to fetch valid Deezer client from remote\n%s", formatted_tb)

if last_err is not None:
raise last_err
raise Exception("Unknown exit")
if last_err_remote is not None and last_err_local is not None:
raise last_err_remote
raise Exception("Unknown func exit")
6 changes: 3 additions & 3 deletions src/pyramid/connector/deezer/py_deezer.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

from pyramid.data.exceptions import CustomException
from pyramid.data.exceptions import CustomException, DeezerTokenInvalidException

with warnings.catch_warnings():
warnings.simplefilter("ignore")
from cryptography.hazmat.primitives.ciphers.algorithms import Blowfish

from pydeezer import Deezer, util
from pydeezer.constants import api_methods, api_urls, networking_settings, track_formats
from pydeezer.exceptions import APIRequestError, DownloadLinkDecryptionError, LoginError
from pydeezer.exceptions import APIRequestError, DownloadLinkDecryptionError
from pydeezer.ProgressHandler import BaseProgressHandler, DefaultProgressHandler


Expand Down Expand Up @@ -289,7 +289,7 @@ async def get_user_data(self):
self.token = data["checkForm"]

if not data["USER"]["USER_ID"]:
raise LoginError(f"Arl ${self.arl} is invalid.")
raise DeezerTokenInvalidException("ARL invalid : %s", self.arl)

raw_user = data["USER"]

Expand Down
20 changes: 11 additions & 9 deletions src/pyramid/connector/discord/guild_cmd_tools.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import logging
import traceback
from typing import Union
from discord.abc import Messageable
from discord import Member, StageChannel, TextChannel, User, VoiceChannel, VoiceClient, VoiceState

from pyramid.data.exceptions import DeezerTokenException
from pyramid.data.track import Track, TrackMinimal, TrackMinimalDeezer
from pyramid.data.guild_data import GuildData
from pyramid.data.tracklist import TrackList
from pyramid.connector.discord.guild_queue import GuildQueue
from pyramid.data.functional.messages.message_sender_queued import MessageSenderQueued
from pyramid.data.functional.engine_source import EngineSource
from pyramid.tools.generate_token import DeezerTokenEmptyException


class GuildCmdTools:
Expand Down Expand Up @@ -127,11 +129,11 @@ async def _execute_play_multiple(
for i, track in enumerate(tracks):
try:
track_downloaded: Track | None = await self.engine_source.download_track(track)
except DeezerTokenEmptyException:
ms.add_message("😥 There are currently no music accounts available. Try again later.")
except DeezerTokenException as err:
ms.add_message("😥 **There are currently no music accounts available**. Try again later.")
return False
except Exception:
ms.add_message("😓 Unable to connect to music API. Try again later.")
except Exception as err:
ms.add_message("😓 **Unable to connect to music API**. Try again later.")
return False
if not track_downloaded:
ms.add_message(content=f"ERROR > **{track.get_full_name()}** can't be downloaded.")
Expand Down Expand Up @@ -168,11 +170,11 @@ async def _execute_play(

try:
track_downloaded: Track | None = await self.engine_source.download_track(track)
except DeezerTokenEmptyException:
ms.add_message("😥 There are currently no music accounts available. Try again later.")
except DeezerTokenException as err:
ms.add_message("😥 **There are currently no music accounts available**. Try again later.")
return False
except Exception:
ms.add_message("😓 Unable to connect to music API. Try again later.")
except Exception as err:
ms.add_message("😓 **Unable to connect to music API**. Try again later.")
return False

if not track_downloaded:
Expand Down
16 changes: 14 additions & 2 deletions src/pyramid/data/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class CustomException(Exception):
def __init__(self, *args: object):
self.msg = str(args[0]) % args[1:]
super().__init__(*args)
msg = str(args[0]) % args[1:]
super().__init__(msg)


class DiscordMessageException(CustomException):
Expand All @@ -14,3 +14,15 @@ class EngineSourceNotFoundException(DiscordMessageException):

class TrackNotFoundException(DiscordMessageException):
pass

class DeezerTokenException(CustomException):
pass

class DeezerTokenInvalidException(DeezerTokenException):
pass

class DeezerTokensUnavailableException(DeezerTokenException):
pass

class DeezerTokenOverflowException(DeezerTokenException):
pass
10 changes: 3 additions & 7 deletions src/pyramid/tools/generate_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@
from typing import Optional, List
import requests

class DeezerTokenEmptyException(Exception):
pass

class DeezerTokenOverflowException(Exception):
pass
from pyramid.data.exceptions import DeezerTokensUnavailableException, DeezerTokenOverflowException

class DeezerToken:
def __init__(self,
Expand Down Expand Up @@ -88,9 +84,9 @@ def next(self) -> DeezerToken:
self.generate(True)
token = self.pop_token()
if not token and not refreshed:
raise DeezerTokenOverflowException("No tokens are available, you can regenerate them.")
raise DeezerTokenOverflowException("No valids tokens are available in cache, you can regenerate them.")
if not token:
raise DeezerTokenEmptyException("No tokens are available")
raise DeezerTokensUnavailableException("No valids tokens are available")
return token

def _fetch(self) -> None:
Expand Down

0 comments on commit f0fcbda

Please sign in to comment.