47 lines
1.8 KiB
Python
47 lines
1.8 KiB
Python
"""Typed failures raised by the Spotify adapter."""
|
|
|
|
from app.ports.protocols import CatalogQuotaExhaustedError
|
|
|
|
|
|
class SpotifyError(Exception):
|
|
"""Base class for Spotify adapter failures."""
|
|
|
|
|
|
class SpotifyAuthenticationError(SpotifyError):
|
|
"""Spotify rejected authentication or token refresh."""
|
|
|
|
|
|
class SpotifyRateLimitedError(SpotifyError):
|
|
"""Spotify rate limited a request that could not be retried."""
|
|
|
|
def __init__(self, retry_after_seconds: float | None, reason: str | None = None) -> None:
|
|
"""Record Spotify's requested delay without exposing request data."""
|
|
super().__init__("Spotify rate limit exceeded")
|
|
self.retry_after_seconds = retry_after_seconds
|
|
self.reason = reason
|
|
|
|
|
|
class SpotifyQuotaExhaustedError(SpotifyRateLimitedError, CatalogQuotaExhaustedError):
|
|
"""Spotify rejected a request because the application quota is exhausted."""
|
|
|
|
|
|
class SpotifyUnavailableError(SpotifyError):
|
|
"""Spotify returned a server-side failure."""
|
|
|
|
def __init__(self, status_code: int, message: str | None = None) -> None:
|
|
"""Record safe details from a Spotify server failure."""
|
|
generic_message = f"Spotify is unavailable with status {status_code}"
|
|
super().__init__(message if message is not None else generic_message)
|
|
self.status_code = status_code
|
|
self.message = message
|
|
|
|
|
|
class SpotifyRequestError(SpotifyError):
|
|
"""Spotify rejected a non-authenticated API request."""
|
|
|
|
def __init__(self, status_code: int, message: str | None = None) -> None:
|
|
"""Record safe details from a rejected Spotify request."""
|
|
generic_message = f"Spotify request failed with status {status_code}"
|
|
super().__init__(message if message is not None else generic_message)
|
|
self.status_code = status_code
|
|
self.message = message
|