diff --git a/tidal_dl_ng/config.py b/tidal_dl_ng/config.py index 72b9f93..f390e4c 100644 --- a/tidal_dl_ng/config.py +++ b/tidal_dl_ng/config.py @@ -190,6 +190,26 @@ class Tidal(BaseConfig, metaclass=SingletonMeta): return True + def validate_session(self) -> bool: + """Validate that the TIDAL session is still authenticated. + + Returns: + bool: True if session is valid, False otherwise. + """ + return self.session.check_login() + + def is_authentication_error(self, error: Exception) -> bool: + """Check if an error is related to authentication/OAuth issues. + + Args: + error (Exception): The exception to check. + + Returns: + bool: True if the error is authentication-related, False otherwise. + """ + error_msg = str(error) + return "401" in error_msg or "OAuth" in error_msg or "token" in error_msg.lower() + class HandlingApp(metaclass=SingletonMeta): event_abort: Event = Event() diff --git a/tidal_dl_ng/gui.py b/tidal_dl_ng/gui.py index 4bf0f06..74192f0 100644 --- a/tidal_dl_ng/gui.py +++ b/tidal_dl_ng/gui.py @@ -728,16 +728,19 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): dict[int, Album]: Dictionary of successfully loaded full album objects. """ albums_dict = {} + batch_size = self.settings.data.api_rate_limit_batch_size + delay_sec = self.settings.data.api_rate_limit_delay_sec for idx, album_id in enumerate(album_ids.keys(), start=1): try: - # Add delay every 20 albums to avoid rate limiting - if idx > 1 and (idx - 1) % 20 == 0: - logger_gui.info(f"🛑 RATE LIMITING: Processed {idx - 1} albums, pausing for 3 seconds...") - time.sleep(3) + # Add delay every N albums to avoid rate limiting + if idx > 1 and (idx - 1) % batch_size == 0: + logger_gui.info(f"🛑 RATE LIMITING: Processed {idx - 1} albums, pausing for {delay_sec} seconds...") + time.sleep(delay_sec) # Check session validity before making API calls - if not self._validate_session(): + if not self.tidal.validate_session(): + logger_gui.error("Session expired. Please restart the application and login again.") return albums_dict # Reload full album object @@ -753,17 +756,6 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): logger_gui.info(f"Successfully loaded {len(albums_dict)} albums.") return albums_dict - def _validate_session(self) -> bool: - """Validate that the TIDAL session is still authenticated. - - Returns: - bool: True if session is valid, False otherwise. - """ - if not self.tidal.session.check_login(): - logger_gui.error("Session expired. Please restart the application and login again.") - return False - return True - def _handle_album_load_error(self, error: Exception, album_id: int) -> bool: """Handle errors that occur when loading an album. @@ -774,10 +766,9 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): Returns: bool: True if processing should continue, False if it should stop. """ - error_msg = str(error) - - # Check for OAuth/authentication errors - if "401" in error_msg or "OAuth" in error_msg or "token" in error_msg.lower(): + # Check for OAuth/authentication errors using Tidal class method + if self.tidal.is_authentication_error(error): + error_msg = str(error) logger_gui.error(f"Authentication error: {error_msg}") logger_gui.error("Your session has expired. Please restart the application and login again.") self.s_statusbar_message.emit( @@ -785,7 +776,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): ) return False - logger_gui.warning(f"Failed to load album {album_id}: {error_msg}") + logger_gui.warning(f"Failed to load album {album_id}: {error!s}") logger_gui.info( "Note: Some albums may be unavailable due to region restrictions or removal from TIDAL. This is normal." ) diff --git a/tidal_dl_ng/model/cfg.py b/tidal_dl_ng/model/cfg.py index 1c87992..4101b9d 100644 --- a/tidal_dl_ng/model/cfg.py +++ b/tidal_dl_ng/model/cfg.py @@ -59,6 +59,9 @@ class Settings: filename_delimiter_artist: str = ", " filename_delimiter_album_artist: str = ", " metadata_target_upc: MetadataTargetUPC = MetadataTargetUPC.UPC + # Rate limiting for API calls (tweaking variables) + api_rate_limit_batch_size: int = 20 # Number of albums to process before applying rate limit delay + api_rate_limit_delay_sec: float = 3.0 # Delay in seconds between batches to avoid rate limiting @dataclass_json @@ -127,6 +130,8 @@ class HelpSettings: metadata_target_upc: str = ( "Select the target metadata tag ('UPC', 'BARCODE', 'EAN') where to write the UPC information to. Default: 'UPC'." ) + api_rate_limit_batch_size: str = "Number of albums to process before applying rate limit delay (tweaking variable)." + api_rate_limit_delay_sec: str = "Delay in seconds between batches to avoid API rate limiting (tweaking variable)." @dataclass_json