"""카페24 연동 공통 예외. 라우터/서비스는 httpx 예외를 직접 다루지 않고 여기 정의된 타입만 잡는다. 모든 메시지는 사용자에게 그대로 노출될 수 있으므로 토큰/시크릿을 담지 않는다. """ from __future__ import annotations class Cafe24Error(Exception): """카페24 연동 최상위 예외.""" class Cafe24ConfigError(Cafe24Error): """CAFE24_* 환경변수 미설정 등 설정 문제.""" class Cafe24AuthError(Cafe24Error): """인증 실패 — 토큰 없음/만료/refresh 불가. 재인증이 필요하다.""" def __init__(self, message: str, *, needs_reauth: bool = False): super().__init__(message) self.needs_reauth = needs_reauth class Cafe24RateLimitError(Cafe24Error): """429 Too Many Requests. retry_after 초 뒤 재시도 가능.""" def __init__(self, message: str, *, retry_after: float = 1.0): super().__init__(message) self.retry_after = retry_after class Cafe24FtpError(Cafe24Error): """디자인 보관함 FTP 연결/전송 실패 (product-swiper.js 편집 등).""" class Cafe24ApiError(Cafe24Error): """그 외 API 오류(4xx/5xx). status 로 재시도 가능 여부를 판단한다.""" def __init__(self, message: str, *, status: int = 0, endpoint: str = ""): super().__init__(message) self.status = status self.endpoint = endpoint @property def retryable(self) -> bool: """5xx 와 타임아웃(status=0)만 재시도 대상. 4xx 는 고쳐야 할 요청.""" return self.status == 0 or self.status >= 500