"""썰박스 예외. app/dashboard/exceptions.py 와 동일한 (message, status_code, code) 형태를 따른다. 전역 핸들러가 code 를 그대로 응답 본문에 실어 보내므로, 프론트가 분기에 쓰는 문자열이다 — 이미 나간 code 값은 함부로 바꾸지 말 것. """ from fastapi import status class SsulboxException(Exception): """썰박스 기본 예외""" def __init__( self, message: str, status_code: int = status.HTTP_500_INTERNAL_SERVER_ERROR, code: str = "SSULBOX_ERROR", ): self.message = message self.status_code = status_code self.code = code super().__init__(self.message) # ============================================================================= # 생성 요청 관련 # ============================================================================= class InvalidScenarioError(SsulboxException): """지원하지 않는 시나리오 코드""" def __init__(self, scenario: str = ""): message = "지원하지 않는 시나리오입니다." if scenario: message += f" ({scenario})" super().__init__( message=message, status_code=status.HTTP_400_BAD_REQUEST, code="SSUL_INVALID_SCENARIO", ) class GenerationUnavailableError(SsulboxException): """생성 엔진 사용 불가 (Gemini API 키 미설정 등)""" def __init__(self, detail: str = ""): message = "썰박스 생성 기능이 현재 비활성화되어 있습니다." if detail: message += f" ({detail})" super().__init__( message=message, status_code=status.HTTP_503_SERVICE_UNAVAILABLE, code="SSUL_GENERATION_UNAVAILABLE", ) class TaskAlreadyRunningError(SsulboxException): """이미 진행 중인 생성 잡이 있음""" def __init__(self): super().__init__( message="이미 생성 중인 썰박스가 있습니다. 완료 후 다시 시도해주세요.", status_code=status.HTTP_409_CONFLICT, code="SSUL_TASK_ALREADY_RUNNING", ) # ============================================================================= # 조회 관련 # ============================================================================= class TaskNotFoundError(SsulboxException): """생성 잡을 찾을 수 없음 (없거나 남의 것)""" def __init__(self): super().__init__( message="생성 요청을 찾을 수 없습니다.", status_code=status.HTTP_404_NOT_FOUND, code="SSUL_TASK_NOT_FOUND", ) class ContentNotFoundError(SsulboxException): """콘텐츠를 찾을 수 없음""" def __init__(self): super().__init__( message="썰박스 콘텐츠를 찾을 수 없습니다.", status_code=status.HTTP_404_NOT_FOUND, code="SSUL_CONTENT_NOT_FOUND", ) class CommentNotFoundError(SsulboxException): """댓글을 찾을 수 없음""" def __init__(self): super().__init__( message="댓글을 찾을 수 없습니다.", status_code=status.HTTP_404_NOT_FOUND, code="SSUL_COMMENT_NOT_FOUND", ) class CommentDepthExceededError(SsulboxException): """댓글은 2-depth(댓글 + 대댓글)까지만 허용""" def __init__(self): super().__init__( message="대댓글에는 답글을 달 수 없습니다.", status_code=status.HTTP_400_BAD_REQUEST, code="SSUL_COMMENT_DEPTH_EXCEEDED", ) # ============================================================================= # 생성 실행 관련 # ============================================================================= class GenerationFailedError(SsulboxException): """생성 엔진 실행 실패""" def __init__(self, detail: str = ""): message = "썰박스 생성에 실패했습니다." if detail: message += f" ({detail})" super().__init__( message=message, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, code="SSUL_GENERATION_FAILED", ) class GenerationTimeoutError(SsulboxException): """생성 엔진 실행 시간 초과""" def __init__(self): super().__init__( message="썰박스 생성 시간이 초과되었습니다. 크레딧은 환불됩니다.", status_code=status.HTTP_504_GATEWAY_TIMEOUT, code="SSUL_GENERATION_TIMEOUT", )