import datetime from typing import Any from pydantic import BaseModel, Field, ConfigDict from app.adapters.opus_clip.enums import ( ClipGenre, ProjectStage, LayoutAspectRatio, CurationModel, ) from pydantic import model_validator class OpusClipProject(BaseModel): model_config = ConfigDict(populate_by_name=True, from_attributes=True) id: str project_id: str = Field(alias="projectId") model: CurationModel stage: ProjectStage render_pref: dict[str, Any] = Field(alias="renderPref") created_at: datetime.datetime = Field(alias="createdAt") updated_at: datetime.datetime = Field(alias="updatedAt") params: dict[str, Any] @model_validator(mode="before") @classmethod def group_extra_fields_into_params(cls, data: Any) -> Any: if not isinstance(data, dict): return data model_fields = set() for field_name, field_info in cls.model_fields.items(): model_fields.add(field_name) if field_info.alias: model_fields.add(field_info.alias) params_data = {} for key in list(data.keys()): if key not in model_fields: params_data[key] = data.pop(key) data["params"] = params_data return data class OpusClipClip(BaseModel): model_config = ConfigDict(populate_by_name=True, from_attributes=True) id: str project_id: str = Field(alias="projectId") uri_for_preview: str = Field(alias="uriForPreview") uri_for_export: str = Field(alias="uriForExport") title: str = Field(default="") description: str = Field(default="") duration_ms: int = Field(alias="durationMs") virality_score: int = Field(alias="viralityScore", default=0) @property def score(self) -> int: return self.virality_score class OpusClipResponse(BaseModel): data: list[OpusClipClip] class CurationPref(BaseModel): model_config = ConfigDict(populate_by_name=True, from_attributes=True) clip_durations: list[list[int]] = Field(alias="curationPref") custom_prompt: str = Field(alias="customPrompt") genre: ClipGenre = Field(default=ClipGenre.MUSIC) skip_curate: bool = Field(alias="skipCurate", default=False) model: CurationModel = Field(default=CurationModel.CLIP_ANYTHING) class ImportPref(BaseModel): model_config = ConfigDict(populate_by_name=True, from_attributes=True) source_lang: str = Field(alias="sourceLang", default="auto") class RenderPref(BaseModel): model_config = ConfigDict(populate_by_name=True, from_attributes=True) layout_aspect_ratio: LayoutAspectRatio = Field(alias="layoutAspectRatio") fit_layout_crop_ratio: str = Field(alias="fitLayoutCropRatio", default="4:3") class UploadedVideoAttr(BaseModel): model_config = ConfigDict(populate_by_name=True, from_attributes=True) title: str description: str class OpusClipProjectParams(BaseModel): model_config = ConfigDict(populate_by_name=True, from_attributes=True) video_url: str = Field(alias="videoUrl") uploaded_video_attr: UploadedVideoAttr = Field(alias="uploadedVideoAttr") curation_pref: CurationPref = Field(alias="curationPref") import_pref: ImportPref = Field(alias="importPref") render_pref: RenderPref = Field(alias="renderPref") brand_template_id: str = Field( alias="brandTemplateId", default="cmg7waigs006e10spkr2m7lgc" )