package model import ( "encoding/json" "time" "github.com/google/uuid" "gorm.io/gorm" ) type MediaAsset struct { ID uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"` OwnerUserID *uuid.UUID `gorm:"type:uuid" json:"owner_user_id"` StorageProvider string `json:"storage_provider"` ObjectKey string `json:"object_key"` PublicURL string `json:"public_url"` OriginalName string `json:"original_name"` DisplayName string `json:"display_name"` MimeType string `json:"mime_type"` SizeBytes int64 `json:"size_bytes"` SHA256 string `json:"sha256"` Width *int `json:"width"` Height *int `json:"height"` DurationMS *int64 `json:"duration_ms"` CreatedAt time.Time `json:"created_at"` DeletedAt *time.Time `json:"-"` } type CreativeProject struct { ID uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"` UserID uuid.UUID `gorm:"type:uuid" json:"user_id"` ProjectType string `json:"project_type"` Name string `json:"name"` CoverAssetID *uuid.UUID `gorm:"type:uuid" json:"cover_asset_id"` StyleID uuid.UUID `gorm:"type:uuid" json:"style_id"` EraType string `json:"era_type"` CustomEra *string `json:"custom_era"` AspectRatio string `json:"aspect_ratio"` Localization *string `json:"localization"` SourceVideoAssetID *uuid.UUID `gorm:"type:uuid" json:"source_video_asset_id"` SubtitleAssetID *uuid.UUID `gorm:"type:uuid" json:"subtitle_asset_id"` AudioSource string `json:"audio_source"` SourceLanguage *string `json:"source_language"` RedrawStatus string `json:"redraw_status"` AnalysisMessage string `json:"analysis_message"` RedrawScript string `json:"redraw_script"` ShortDramaType *string `json:"short_drama_type"` PlayCount *string `json:"play_count"` AudienceProfile *string `json:"audience_profile"` Producer *string `json:"producer"` CastMembers json.RawMessage `gorm:"type:jsonb;not null;default:'[]'" json:"cast_members"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt *time.Time `json:"-"` } func (project *CreativeProject) BeforeCreate(_ *gorm.DB) error { if len(project.CastMembers) == 0 { project.CastMembers = json.RawMessage("[]") } return nil } type ProjectModelConfig struct { ID uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"` ProjectID uuid.UUID `gorm:"type:uuid" json:"project_id"` Purpose string `json:"purpose"` ModelType string `json:"model_type"` ModelID uuid.UUID `gorm:"type:uuid" json:"model_id"` PromptID *uuid.UUID `gorm:"type:uuid" json:"prompt_id"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } type UserModelConfig struct { ID uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"` UserID uuid.UUID `gorm:"type:uuid" json:"user_id"` Purpose string `json:"purpose"` ProjectType string `json:"project_type"` ModelType string `json:"model_type"` ModelID uuid.UUID `gorm:"type:uuid" json:"model_id"` PromptID *uuid.UUID `gorm:"type:uuid" json:"prompt_id"` Settings json.RawMessage `gorm:"type:jsonb" json:"settings"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } type ProjectEpisode struct { ID uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"` ProjectID uuid.UUID `gorm:"type:uuid" json:"project_id"` EpisodeNo int `json:"episode_no"` Name string `json:"name"` CoverAssetID *uuid.UUID `gorm:"type:uuid" json:"cover_asset_id"` SourceVideoAssetID *uuid.UUID `gorm:"type:uuid" json:"source_video_asset_id"` SubtitleAssetID *uuid.UUID `gorm:"type:uuid" json:"subtitle_asset_id"` AudioSource string `json:"audio_source"` SourceLanguage *string `json:"source_language"` Status string `json:"status"` AnalysisMessage string `json:"analysis_message"` RedrawScript string `json:"redraw_script"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt *time.Time `json:"-"` } type ProjectAsset struct { ID uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"` ProjectID uuid.UUID `gorm:"type:uuid" json:"project_id"` SourceEpisodeID *uuid.UUID `gorm:"type:uuid" json:"source_episode_id"` AssetType string `json:"asset_type"` Name string `json:"name"` Description string `json:"description"` ImagePrompt string `json:"image_prompt"` Appearances json.RawMessage `gorm:"type:jsonb" json:"appearances"` ImageAssetID *uuid.UUID `gorm:"type:uuid" json:"image_asset_id"` AudioAssetID *uuid.UUID `gorm:"type:uuid" json:"audio_asset_id"` UserEdited bool `json:"user_edited"` Aliases json.RawMessage `gorm:"type:jsonb" json:"aliases"` Attributes json.RawMessage `gorm:"type:jsonb" json:"attributes"` AIDescription string `gorm:"column:ai_description" json:"ai_description"` SourceParseTaskID *uuid.UUID `gorm:"type:uuid" json:"source_parse_task_id"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt *time.Time `json:"-"` } func (asset *ProjectAsset) BeforeCreate(_ *gorm.DB) error { if len(asset.Appearances) == 0 { asset.Appearances = json.RawMessage("[]") } if len(asset.Aliases) == 0 { asset.Aliases = json.RawMessage("[]") } if len(asset.Attributes) == 0 { asset.Attributes = json.RawMessage("{}") } return nil } type EpisodeStoryboard struct { ID uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"` EpisodeID *uuid.UUID `gorm:"type:uuid" json:"episode_id"` ProjectID *uuid.UUID `gorm:"type:uuid" json:"project_id"` SequenceNo int `json:"sequence_no"` StableKey string `json:"stable_key"` StartMS int64 `json:"start_ms"` EndMS int64 `json:"end_ms"` DurationSeconds int `json:"duration_seconds"` Title string `json:"title"` ThumbnailAssetID *uuid.UUID `gorm:"type:uuid" json:"thumbnail_asset_id"` PromptContent string `json:"prompt_content"` ImagePrompt string `json:"image_prompt"` ScriptContent string `json:"script_content"` SourceExcerpt string `json:"source_excerpt"` Dialogue json.RawMessage `gorm:"type:jsonb" json:"dialogue"` AssetRefs json.RawMessage `gorm:"type:jsonb" json:"asset_refs"` Locked bool `json:"locked"` ActiveOutputID *uuid.UUID `gorm:"type:uuid" json:"active_output_id"` Status string `json:"status"` SourceParseTaskID *uuid.UUID `gorm:"type:uuid" json:"source_parse_task_id"` UserEdited bool `json:"user_edited"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt *time.Time `json:"-"` } type EpisodeSource struct { ID uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"` EpisodeID uuid.UUID `gorm:"type:uuid;uniqueIndex" json:"episode_id"` Title string `json:"title"` RawContent string `json:"raw_content"` CharCount int `json:"char_count"` SourceType string `json:"source_type"` SourceFilename string `json:"source_filename"` ContentSHA256 string `gorm:"column:content_sha256" json:"content_sha256"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } type DramaImportSession struct { ID uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"` UserID uuid.UUID `gorm:"type:uuid" json:"user_id"` ProjectID uuid.UUID `gorm:"type:uuid" json:"project_id"` SourceType string `json:"source_type"` SourceFilename string `json:"source_filename"` RawContent string `json:"-"` ContentSHA256 string `gorm:"column:content_sha256" json:"content_sha256"` PreviewData json.RawMessage `gorm:"type:jsonb" json:"preview_data"` ExpiresAt time.Time `json:"expires_at"` ConsumedAt *time.Time `json:"consumed_at"` CreatedAt time.Time `json:"created_at"` } type DramaParseBatch struct { ID uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"` ProjectID uuid.UUID `gorm:"type:uuid" json:"project_id"` UserID uuid.UUID `gorm:"type:uuid" json:"user_id"` Mode string `json:"mode"` Status string `json:"status"` TotalCount int `json:"total_count"` CompletedCount int `json:"completed_count"` FailedCount int `json:"failed_count"` CurrentEpisodeID *uuid.UUID `gorm:"type:uuid" json:"current_episode_id"` CancelRequestedAt *time.Time `json:"cancel_requested_at"` CreatedAt time.Time `json:"created_at"` FinishedAt *time.Time `json:"finished_at"` } type DramaParseTask struct { ID uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"` RequestID string `json:"request_id"` BatchID *uuid.UUID `gorm:"type:uuid" json:"batch_id"` UserID uuid.UUID `gorm:"type:uuid" json:"user_id"` ProjectID uuid.UUID `gorm:"type:uuid" json:"project_id"` EpisodeID uuid.UUID `gorm:"type:uuid" json:"episode_id"` ChannelID uuid.UUID `gorm:"type:uuid" json:"channel_id"` ModelID uuid.UUID `gorm:"type:uuid" json:"model_id"` SourceSHA256 string `gorm:"column:source_sha256" json:"source_sha256"` Status string `json:"status"` AttemptCount int `json:"attempt_count"` ModelSnapshot json.RawMessage `gorm:"type:jsonb" json:"model_snapshot"` PromptSnapshot string `json:"prompt_snapshot"` ContextSnapshot json.RawMessage `gorm:"type:jsonb" json:"context_snapshot"` NormalizedResult json.RawMessage `gorm:"type:jsonb" json:"normalized_result"` InputTokens *int64 `json:"input_tokens"` OutputTokens *int64 `json:"output_tokens"` TotalTokens *int64 `json:"total_tokens"` TokenCountSource string `json:"token_count_source"` UsageRaw json.RawMessage `gorm:"type:jsonb" json:"usage_raw"` BillingSnapshot json.RawMessage `gorm:"type:jsonb;not null;default:'{}'" json:"billing_snapshot"` EstimatedPoints string `gorm:"column:estimated_points" json:"estimated_points"` PrepaidPoints string `gorm:"column:prepaid_points" json:"prepaid_points"` ActualPoints *string `gorm:"column:actual_points" json:"actual_points"` CostRefunded bool `json:"cost_refunded"` RequestCharCount int64 `json:"request_char_count"` ResponseCharCount int64 `json:"response_char_count"` LeaseOwner string `json:"lease_owner"` LeaseUntil *time.Time `json:"lease_until"` CancelRequestedAt *time.Time `json:"cancel_requested_at"` ErrorCode string `json:"error_code"` ErrorMessage string `json:"error_message"` CreatedAt time.Time `json:"created_at"` StartedAt *time.Time `json:"started_at"` FinishedAt *time.Time `json:"finished_at"` } type GenerationTask struct { ID uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"` RequestID string `json:"request_id"` UserID uuid.UUID `gorm:"type:uuid" json:"user_id"` ChannelID *uuid.UUID `gorm:"type:uuid" json:"channel_id"` ModelID *uuid.UUID `gorm:"type:uuid" json:"model_id"` ProjectID *uuid.UUID `gorm:"type:uuid" json:"project_id"` EpisodeID *uuid.UUID `gorm:"type:uuid" json:"episode_id"` StoryboardID *uuid.UUID `gorm:"type:uuid" json:"storyboard_id"` ScriptAnalysisID *uuid.UUID `gorm:"type:uuid" json:"script_analysis_id"` TaskType string `json:"task_type"` Status string `json:"status"` UpstreamTaskID string `json:"upstream_task_id"` InputData json.RawMessage `gorm:"type:jsonb" json:"input_data"` BillingSnapshot json.RawMessage `gorm:"type:jsonb;not null;default:'{}'" json:"billing_snapshot"` InputTokens *int64 `json:"input_tokens"` OutputTokens *int64 `json:"output_tokens"` TotalTokens *int64 `json:"total_tokens"` TokenCountSource *string `json:"token_count_source"` UsageRaw json.RawMessage `gorm:"type:jsonb" json:"usage_raw"` ResultData json.RawMessage `gorm:"type:jsonb;not null;default:'{}'" json:"result_data"` PromptSnapshot string `json:"prompt_snapshot"` EstimatedPoints string `gorm:"column:estimated_points" json:"estimated_points"` ActualPoints *string `gorm:"column:actual_points" json:"actual_points"` PrepaidPoints string `gorm:"column:prepaid_points" json:"prepaid_points"` CostRefunded bool `json:"cost_refunded"` SlotReserved bool `json:"slot_reserved"` SlotReservedAt *time.Time `json:"slot_reserved_at"` SlotReleasedAt *time.Time `json:"slot_released_at"` SubmitAttempts int `json:"submit_attempts"` PollAttempts int `json:"poll_attempts"` DownloadAttempts int `json:"download_attempts"` NextSubmitAt *time.Time `json:"next_submit_at"` NextPollAt *time.Time `json:"next_poll_at"` LeaseOwner string `json:"lease_owner"` LeaseUntil *time.Time `json:"lease_until"` UpstreamResultURL string `json:"-"` ErrorCode string `json:"error_code"` ErrorMessage string `json:"error_message"` CreatedAt time.Time `json:"created_at"` SubmittedAt *time.Time `json:"submitted_at"` FinishedAt *time.Time `json:"finished_at"` } type GenerationOutput struct { ID uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"` TaskID uuid.UUID `gorm:"type:uuid" json:"task_id"` MediaAssetID uuid.UUID `gorm:"type:uuid" json:"media_asset_id"` OutputType string `json:"output_type"` SequenceNo int `json:"sequence_no"` Metadata json.RawMessage `gorm:"type:jsonb" json:"metadata"` CreatedAt time.Time `json:"created_at"` }