from datetime import datetime, timezone from fansifter_common.httpclient.base import HTTPClient from fansifter_common.httpclient.exceptions import HTTPClientError from app.adapters.opus_clip.enums import CurationModel, ProjectStage from app.adapters.opus_clip.models import ( OpusClipProjectParams, OpusClipProject, OpusClipClip, OpusClipResponse, ) import uuid from app.assets.utils import get_assets_url class OpusClipClientError(HTTPClientError): name = "opus_clip_client_" class OpusClipClient(HTTPClient): base_url = "https://api.opus.pro/api" exception_class = OpusClipClientError DEFAULT_REQUEST_TIMEOUT = 30 def __init__( self, api_token: str, default_timeout: int | None = None, ) -> None: self.api_token = api_token self.headers = { "Content-Type": "application/json", "Authorization": f"Bearer {self.api_token}", } super().__init__( client_options={"timeout": default_timeout or self.DEFAULT_REQUEST_TIMEOUT} ) def build_url(self, path: str) -> str: return f"{self.base_url}/{path}" def create_project(self, params: OpusClipProjectParams) -> OpusClipProject: return self.request( "POST", self.build_url("clip-projects"), headers=self.headers, json={ **params.model_dump(by_alias=True), }, type=OpusClipProject, ) def get_clips_by_project_id(self, project_id: str) -> list[OpusClipClip]: response = self.request( "GET", self.build_url("exportable-clips"), headers=self.headers, params={"q": "findByProjectId", "projectId": project_id}, type=OpusClipResponse, ) return response.data class OpusClipClientMock(OpusClipClient): def __init__(self): super().__init__(api_token="dummy_token") def create_project(self, params: OpusClipProjectParams) -> OpusClipProject: project_data = { "id": str(uuid.uuid4()), "project_id": str(uuid.uuid4()), "model": CurationModel.CLIP_ANYTHING, "stage": ProjectStage.PENDING, "render_pref": params.render_pref.json(), "created_at": datetime.now(timezone.utc).isoformat(), "updated_at": datetime.now(timezone.utc).isoformat(), } return OpusClipProject.model_validate(project_data) def get_clips_by_project_id(self, project_id: str) -> list[OpusClipClip]: key = "test_result_video.mp4" clip_url = get_assets_url(key) clip_data = { "id": str(uuid.uuid4()), "project_id": project_id, "uri_for_preview": clip_url, "uri_for_export": clip_url, "title": "Title Example", "description": "This description is an example", "duration_ms": 1234, "virality_score": 90, } return [OpusClipClip.model_validate(clip_data)]