from __future__ import annotations from enum import StrEnum class QQBotErrorCode(StrEnum): AUTH_FAILED = "auth_failed" INVALID_SESSION = "invalid_session" RATE_LIMITED = "rate_limited" SESSION_TIMEOUT = "session_timeout" INSUFFICIENT_INTENTS = "insufficient_intents" DISALLOWED_INTENTS = "disallowed_intents" NETWORK_ERROR = "network_error" CONNECTION_CLOSED = "connection_closed" CONFIG_ERROR = "config_error" TOKEN_EXPIRED = "token_expired" MEDIA_UPLOAD_FAILED = "media_upload_failed" STREAMING_FAILED = "streaming_failed" SEND_FAILED = "send_failed" UNKNOWN = "unknown" class QQBotError(Exception): def __init__(self, code: QQBotErrorCode, message: str, retryable: bool = False): self.code = code self.retryable = retryable super().__init__(f"[{code.value}] {message}") CLOSE_CODE_RETRY_MAP: dict[int, tuple[bool, float | None]] = { 1000: (False, None), 4004: (True, 0), 4006: (True, 0), 4007: (True, 0), 4008: (True, 60_000), 4009: (True, 0), 4914: (False, None), 4915: (False, None), } SERVER_ERROR_RANGE = range(4900, 4914) def classify_close_code(code: int) -> tuple[bool, float | None]: if code in CLOSE_CODE_RETRY_MAP: return CLOSE_CODE_RETRY_MAP[code] if code in SERVER_ERROR_RANGE: return (True, 0) return (True, 0)