""" Instagram Graph API 커스텀 예외 모듈 Instagram API 에러 코드에 맞는 예외 클래스를 정의합니다. """ from typing import Optional class InstagramAPIError(Exception): """ Instagram API 기본 예외 모든 Instagram API 관련 예외의 기본 클래스입니다. Attributes: message: 에러 메시지 code: Instagram API 에러 코드 subcode: Instagram API 에러 서브코드 fbtrace_id: Facebook 트레이스 ID (디버깅용) """ def __init__( self, message: str, code: Optional[int] = None, subcode: Optional[int] = None, fbtrace_id: Optional[str] = None, ): self.message = message self.code = code self.subcode = subcode self.fbtrace_id = fbtrace_id super().__init__(self.message) def __str__(self) -> str: parts = [self.message] if self.code is not None: parts.append(f"code={self.code}") if self.subcode is not None: parts.append(f"subcode={self.subcode}") if self.fbtrace_id: parts.append(f"fbtrace_id={self.fbtrace_id}") return " | ".join(parts) class AuthenticationError(InstagramAPIError): """ 인증 관련 에러 토큰이 만료되었거나, 유효하지 않거나, 앱 권한이 없는 경우 발생합니다. """ pass class RateLimitError(InstagramAPIError): """ Rate Limit 초과 에러 시간당 API 호출 제한을 초과한 경우 발생합니다. Attributes: retry_after: 재시도까지 대기해야 하는 시간 (초) """ def __init__( self, message: str, retry_after: Optional[int] = None, code: Optional[int] = 4, subcode: Optional[int] = None, fbtrace_id: Optional[str] = None, ): super().__init__(message, code, subcode, fbtrace_id) self.retry_after = retry_after def __str__(self) -> str: base = super().__str__() if self.retry_after is not None: return f"{base} | retry_after={self.retry_after}s" return base class ContainerStatusError(InstagramAPIError): """ 컨테이너 상태 에러 미디어 컨테이너가 ERROR 상태가 되었을 때 발생합니다. """ pass class ContainerTimeoutError(InstagramAPIError): """ 컨테이너 타임아웃 에러 미디어 컨테이너가 지정된 시간 내에 FINISHED 상태가 되지 않은 경우 발생합니다. """ pass # 에러 코드 → 예외 클래스 매핑 ERROR_CODE_MAPPING: dict[int, type[InstagramAPIError]] = { 4: RateLimitError, 17: RateLimitError, 190: AuthenticationError, 341: RateLimitError, } def create_exception_from_error( message: str, code: Optional[int] = None, subcode: Optional[int] = None, fbtrace_id: Optional[str] = None, ) -> InstagramAPIError: """ API 에러 응답에서 적절한 예외 객체 생성 Args: message: 에러 메시지 code: API 에러 코드 subcode: API 에러 서브코드 fbtrace_id: Facebook 트레이스 ID Returns: 적절한 예외 클래스의 인스턴스 """ exception_class = InstagramAPIError if code is not None: exception_class = ERROR_CODE_MAPPING.get(code, InstagramAPIError) return exception_class( message=message, code=code, subcode=subcode, fbtrace_id=fbtrace_id, )