Documentation
¶
Index ¶
- Variables
- func LogServerInfo(cfg *config.Config)
- func NewServer(deps *ServerDependencies) *gin.Engine
- type AvailableScrapersResponse
- type BatchFileResult
- type BatchJobResponse
- type BatchRescrapeRequest
- type BatchRescrapeResponse
- type BatchScrapeRequest
- type BatchScrapeResponse
- type BrowseRequest
- type BrowseResponse
- type DataSource
- type DeleteHistoryBulkResponse
- type ErrorResponse
- type FieldDifference
- type FileInfo
- type HealthResponse
- type HistoryListResponse
- type HistoryRecord
- type HistoryStats
- type MergeStatistics
- type MovieResponse
- type MoviesResponse
- type NFOComparisonRequest
- type NFOComparisonResponse
- type OrganizePreviewRequest
- type OrganizePreviewResponse
- type OrganizeRequest
- type PathAutocompleteRequest
- type PathAutocompleteResponse
- type PathAutocompleteSuggestion
- type PosterCropRequest
- type PosterCropResponse
- type ProgressAdapter
- func (a *ProgressAdapter) GetChannel() chan<- worker.ProgressUpdate
- func (a *ProgressAdapter) GetRegisteredTaskCount() int
- func (a *ProgressAdapter) RegisterTask(taskID string, fileIndex int, filePath string)
- func (a *ProgressAdapter) Start()
- func (a *ProgressAdapter) Stop()
- func (a *ProgressAdapter) UnregisterTask(taskID string)
- type ProgressBroadcaster
- type ProxyTestRequest
- type ProxyTestResponse
- type RescrapeRequest
- type ScanRequest
- type ScanResponse
- type ScrapeRequest
- type ScrapeResponse
- type ScraperChoice
- type ScraperInfo
- type ScraperOption
- type ServerDependencies
- func (d *ServerDependencies) GetAggregator() *aggregator.Aggregator
- func (d *ServerDependencies) GetConfig() *config.Config
- func (d *ServerDependencies) GetMatcher() *matcher.Matcher
- func (d *ServerDependencies) GetRegistry() *models.ScraperRegistry
- func (d *ServerDependencies) SetConfig(cfg *config.Config)
- func (d *ServerDependencies) Shutdown()
- type TranslationModelsRequest
- type TranslationModelsResponse
- type UpdateMovieRequest
Constants ¶
This section is empty.
Variables ¶
var ( ErrNFONotFound = errors.New("nfo file not found") ErrNFOAccessDenied = errors.New("access denied: path is outside allowed directories") ErrNFOInvalidPath = errors.New("invalid file path") ErrNFOIsDirectory = errors.New("path is a directory, not a file") )
Sentinel errors for NFO validation
Functions ¶
func LogServerInfo ¶
LogServerInfo logs information about the running server
func NewServer ¶
func NewServer(deps *ServerDependencies) *gin.Engine
NewServer creates and configures the Gin router with all API endpoints
Types ¶
type AvailableScrapersResponse ¶
type AvailableScrapersResponse struct {
Scrapers []ScraperInfo `json:"scrapers"`
}
AvailableScrapersResponse represents the list of available scrapers
type BatchFileResult ¶
type BatchFileResult struct {
FilePath string `json:"file_path"`
MovieID string `json:"movie_id"`
Status string `json:"status"`
Error string `json:"error,omitempty"`
FieldSources map[string]string `json:"field_sources,omitempty"` // Field-level source by scraper/NFO
ActressSources map[string]string `json:"actress_sources,omitempty"` // Actress-level source by scraper/NFO
Data interface{} `json:"data,omitempty"` // Movie data
StartedAt string `json:"started_at"`
EndedAt *string `json:"ended_at,omitempty"`
IsMultiPart bool `json:"is_multi_part,omitempty"`
PartNumber int `json:"part_number,omitempty"`
PartSuffix string `json:"part_suffix,omitempty"`
}
BatchFileResult wraps worker.FileResult with additional API-specific fields
type BatchJobResponse ¶
type BatchJobResponse struct {
ID string `json:"id"`
Status string `json:"status"`
TotalFiles int `json:"total_files"`
Completed int `json:"completed"`
Failed int `json:"failed"`
Excluded map[string]bool `json:"excluded"` // Files excluded from organization
Progress float64 `json:"progress"`
Results map[string]*BatchFileResult `json:"results"`
StartedAt string `json:"started_at"`
CompletedAt *string `json:"completed_at,omitempty"`
}
BatchJobResponse represents a batch job status
type BatchRescrapeRequest ¶
type BatchRescrapeRequest struct {
Force bool `json:"force" example:"false"`
SelectedScrapers []string `json:"selected_scrapers,omitempty" example:"r18dev,dmm"`
ManualSearchInput string `json:"manual_search_input,omitempty" example:"IPX-535"`
Preset string `json:"preset,omitempty" example:"conservative"` // Merge strategy preset: conservative, gap-fill, aggressive (overrides scalar/array strategies)
ScalarStrategy string `json:"scalar_strategy,omitempty" example:"prefer-nfo"` // For Update mode: prefer-nfo, prefer-scraper, preserve-existing, fill-missing-only
ArrayStrategy string `json:"array_strategy,omitempty" example:"merge"` // For Update mode: merge, replace
}
BatchRescrapeRequest represents a batch rescrape request for manual search/rescraping
type BatchRescrapeResponse ¶
type BatchRescrapeResponse struct {
Movie *models.Movie `json:"movie"`
FieldSources map[string]string `json:"field_sources,omitempty"`
ActressSources map[string]string `json:"actress_sources,omitempty"`
}
BatchRescrapeResponse represents a batch rescrape response with movie
type BatchScrapeRequest ¶
type BatchScrapeRequest struct {
Files []string `json:"files" binding:"required"`
Strict bool `json:"strict" example:"false"`
Force bool `json:"force" example:"false"`
Destination string `json:"destination,omitempty" example:"/path/to/output"`
Update bool `json:"update" example:"false"` // Update mode: only create/update metadata files without moving video files
SelectedScrapers []string `json:"selected_scrapers,omitempty" example:"r18dev,dmm"`
Preset string `json:"preset,omitempty" example:"conservative"` // Merge strategy preset: conservative, gap-fill, aggressive (overrides scalar/array strategies)
ScalarStrategy string `json:"scalar_strategy,omitempty" example:"prefer-nfo"` // For Update mode: prefer-nfo, prefer-scraper, preserve-existing, fill-missing-only
ArrayStrategy string `json:"array_strategy,omitempty" example:"merge"` // For Update mode: merge, replace
}
BatchScrapeRequest represents a batch scrape request
type BatchScrapeResponse ¶
type BatchScrapeResponse struct {
JobID string `json:"job_id" example:"550e8400-e29b-41d4-a716-446655440000"`
}
BatchScrapeResponse represents batch scrape response
type BrowseRequest ¶
type BrowseRequest struct {
Path string `json:"path" example:"/path/to/directory"`
}
BrowseRequest represents a browse request
type BrowseResponse ¶
type BrowseResponse struct {
CurrentPath string `json:"current_path" example:"/path/to/directory"`
ParentPath string `json:"parent_path,omitempty" example:"/path/to"`
Items []FileInfo `json:"items"`
}
BrowseResponse represents browse results
type DataSource ¶
type DataSource struct {
Source string `json:"source" example:"nfo"` // "scraper" or "nfo"
Confidence float64 `json:"confidence" example:"0.9"` // Confidence score (0.0-1.0)
LastUpdated *string `json:"last_updated,omitempty" example:"2024-01-15T10:30:00Z"` // ISO 8601 timestamp
}
DataSource represents the source of a metadata field
type DeleteHistoryBulkResponse ¶
type DeleteHistoryBulkResponse struct {
Deleted int64 `json:"deleted"`
}
DeleteHistoryBulkResponse is the response for bulk deletion
type ErrorResponse ¶
type ErrorResponse struct {
Error string `json:"error" example:"Movie not found"`
Errors []string `json:"errors,omitempty"`
}
ErrorResponse represents an error response
type FieldDifference ¶
type FieldDifference struct {
Field string `json:"field" example:"title"`
NFOValue interface{} `json:"nfo_value,omitempty" example:"Beautiful Woman"`
ScrapedValue interface{} `json:"scraped_value,omitempty" example:"Pretty Lady"`
MergedValue interface{} `json:"merged_value,omitempty" example:"Beautiful Woman"`
Reason string `json:"reason,omitempty" example:"NFO preferred by merge strategy"`
}
FieldDifference represents a difference between NFO and scraped data
type FileInfo ¶
type FileInfo struct {
Name string `json:"name" example:"video.mp4"`
Path string `json:"path" example:"/path/to/video.mp4"`
IsDir bool `json:"is_dir" example:"false"`
Size int64 `json:"size" example:"1024000000"`
ModTime string `json:"mod_time" example:"2024-01-15T10:30:00Z"`
MovieID string `json:"movie_id,omitempty" example:"IPX-535"`
Matched bool `json:"matched" example:"true"`
IsMultiPart bool `json:"is_multi_part,omitempty" example:"true"`
PartNumber int `json:"part_number,omitempty" example:"1"`
PartSuffix string `json:"part_suffix,omitempty" example:"-pt1"`
}
FileInfo represents file or directory information
type HealthResponse ¶
type HealthResponse struct {
Status string `json:"status" example:"ok"`
Scrapers []string `json:"scrapers" example:"r18dev,dmm"`
Version string `json:"version" example:"v1.2.3"`
Commit string `json:"commit" example:"abc123def456"`
BuildDate string `json:"build_date" example:"2026-02-23T00:00:00Z"`
}
HealthResponse represents the health check response
type HistoryListResponse ¶
type HistoryListResponse struct {
Records []HistoryRecord `json:"records"`
Total int64 `json:"total"`
Limit int `json:"limit"`
Offset int `json:"offset"`
}
HistoryListResponse is the response for listing history records
type HistoryRecord ¶
type HistoryRecord struct {
ID uint `json:"id"`
MovieID string `json:"movie_id"`
Operation string `json:"operation"`
OriginalPath string `json:"original_path"`
NewPath string `json:"new_path"`
Status string `json:"status"`
ErrorMessage string `json:"error_message"`
Metadata string `json:"metadata"`
DryRun bool `json:"dry_run"`
CreatedAt string `json:"created_at"`
}
HistoryRecord represents a single history record in API responses
type HistoryStats ¶
type HistoryStats struct {
Total int64 `json:"total"`
Success int64 `json:"success"`
Failed int64 `json:"failed"`
Reverted int64 `json:"reverted"`
ByOperation map[string]int64 `json:"by_operation"`
}
HistoryStats represents aggregated history statistics
type MergeStatistics ¶
type MergeStatistics struct {
TotalFields int `json:"total_fields" example:"15"`
FromScraper int `json:"from_scraper" example:"10"`
FromNFO int `json:"from_nfo" example:"3"`
MergedArrays int `json:"merged_arrays" example:"2"`
ConflictsResolved int `json:"conflicts_resolved" example:"5"`
EmptyFields int `json:"empty_fields" example:"2"`
}
MergeStatistics represents statistics about a merge operation
type MovieResponse ¶
type MovieResponse struct {
Movie *models.Movie `json:"movie"`
Provenance map[string]DataSource `json:"provenance,omitempty"` // Field-level data source tracking
MergeStats *MergeStatistics `json:"merge_stats,omitempty"` // Merge statistics when NFO merging occurred
}
MovieResponse represents a movie response
type MoviesResponse ¶
type MoviesResponse struct {
Movies []models.Movie `json:"movies"`
Count int `json:"count" example:"20"`
}
MoviesResponse represents a list of movies response
type NFOComparisonRequest ¶
type NFOComparisonRequest struct {
NFOPath string `json:"nfo_path,omitempty" example:"/path/to/movie.nfo"` // Optional: explicit NFO path
MergeStrategy string `json:"merge_strategy,omitempty" example:"prefer-scraper"` // Deprecated: prefer-scraper, prefer-nfo, merge-arrays (use preset or scalar/array strategies instead)
Preset string `json:"preset,omitempty" example:"conservative"` // Merge strategy preset: conservative, gap-fill, or aggressive (overrides scalar/array strategies)
ScalarStrategy string `json:"scalar_strategy,omitempty" example:"prefer-nfo"` // Scalar field merge strategy: prefer-nfo, prefer-scraper, preserve-existing, or fill-missing-only
ArrayStrategy string `json:"array_strategy,omitempty" example:"merge"` // Array field merge strategy: merge or replace
SelectedScrapers []string `json:"selected_scrapers,omitempty" example:"r18dev,dmm"` // Optional: custom scrapers for comparison
}
NFOComparisonRequest represents a request to compare NFO with scraped data
type NFOComparisonResponse ¶
type NFOComparisonResponse struct {
MovieID string `json:"movie_id" example:"IPX-535"`
NFOExists bool `json:"nfo_exists" example:"true"`
NFOPath string `json:"nfo_path,omitempty" example:"movie.nfo"` // Returns filename only for security
NFOData *models.Movie `json:"nfo_data,omitempty"` // Data from NFO file
ScrapedData *models.Movie `json:"scraped_data,omitempty"` // Fresh scraped data
MergedData *models.Movie `json:"merged_data,omitempty"` // Result of merging
Provenance map[string]DataSource `json:"provenance,omitempty"` // Field-level provenance
MergeStats *MergeStatistics `json:"merge_stats,omitempty"` // Merge statistics
Differences []FieldDifference `json:"differences,omitempty"` // List of fields that differ
}
NFOComparisonResponse represents the result of comparing NFO with scraped data
type OrganizePreviewRequest ¶
type OrganizePreviewRequest struct {
Destination string `json:"destination" binding:"required" example:"/path/to/output"`
CopyOnly bool `json:"copy_only" example:"false"`
LinkMode string `json:"link_mode,omitempty" binding:"omitempty,oneof=hard soft" example:"hard"`
}
OrganizePreviewRequest represents a preview request
type OrganizePreviewResponse ¶
type OrganizePreviewResponse struct {
FolderName string `json:"folder_name" example:"IPX-535 [IdeaPocket] - Beautiful Woman (2021)"`
FileName string `json:"file_name" example:"IPX-535"`
FullPath string `json:"full_path" example:"/path/to/output/IPX-535 [IdeaPocket] - Beautiful Woman (2021)/IPX-535.mp4"`
VideoFiles []string `json:"video_files,omitempty"` // For multi-part files: all video file paths
NFOPath string `json:"nfo_path" example:"/path/to/output/IPX-535 [IdeaPocket] - Beautiful Woman (2021)/IPX-535.nfo"` // Single NFO (backward compatibility)
NFOPaths []string `json:"nfo_paths,omitempty"` // For per_file=true multi-part: all NFO file paths
PosterPath string `json:"poster_path" example:"/path/to/output/IPX-535 [IdeaPocket] - Beautiful Woman (2021)/IPX-535-poster.jpg"`
FanartPath string `json:"fanart_path" example:"/path/to/output/IPX-535 [IdeaPocket] - Beautiful Woman (2021)/IPX-535-fanart.jpg"`
ExtrafanartPath string `json:"extrafanart_path" example:"/path/to/output/IPX-535 [IdeaPocket] - Beautiful Woman (2021)/extrafanart"`
Screenshots []string `json:"screenshots" example:"fanart1.jpg,fanart2.jpg,fanart3.jpg"`
}
OrganizePreviewResponse represents the expected output structure
type OrganizeRequest ¶
type OrganizeRequest struct {
Destination string `json:"destination" binding:"required" example:"/path/to/output"`
CopyOnly bool `json:"copy_only" example:"false"`
LinkMode string `json:"link_mode,omitempty" binding:"omitempty,oneof=hard soft" example:"hard"`
}
OrganizeRequest represents an organize request
type PathAutocompleteRequest ¶
type PathAutocompleteRequest struct {
Path string `json:"path" binding:"required" example:"/path/to/vid"`
Limit int `json:"limit,omitempty" example:"10"`
}
PathAutocompleteRequest represents a partial path autocomplete request.
type PathAutocompleteResponse ¶
type PathAutocompleteResponse struct {
InputPath string `json:"input_path" example:"/path/to/vid"`
BasePath string `json:"base_path" example:"/path/to"`
Suggestions []PathAutocompleteSuggestion `json:"suggestions"`
}
PathAutocompleteResponse represents directory suggestions for a partial path.
type PathAutocompleteSuggestion ¶
type PathAutocompleteSuggestion struct {
Name string `json:"name" example:"videos"`
Path string `json:"path" example:"/path/to/videos"`
IsDir bool `json:"is_dir" example:"true"`
}
PathAutocompleteSuggestion represents a single autocomplete suggestion.
type PosterCropRequest ¶
type PosterCropRequest struct {
X int `json:"x" binding:"min=0"`
Y int `json:"y" binding:"min=0"`
Width int `json:"width" binding:"min=1"`
Height int `json:"height" binding:"min=1"`
}
PosterCropRequest represents manual poster crop coordinates in source-image pixels.
type PosterCropResponse ¶
type PosterCropResponse struct {
CroppedPosterURL string `json:"cropped_poster_url"`
}
PosterCropResponse returns the updated temp cropped poster URL.
type ProgressAdapter ¶
type ProgressAdapter struct {
// contains filtered or unexported fields
}
ProgressAdapter bridges worker.ProgressTracker updates to WebSocket broadcasts for API batch jobs. It provides thread-safe mapping between task IDs and file paths for real-time progress tracking.
Usage Example:
// Create adapter for a batch job
adapter := NewProgressAdapter(job.ID, job, nil) // nil uses global wsHub
// Create progress tracker with adapter's channel
progressTracker := worker.NewProgressTracker(adapter.GetChannel())
// Start adapter (non-blocking)
adapter.Start()
defer adapter.Stop() // Safe to call multiple times
// Register each task before submitting to worker pool
for i, filePath := range job.Files {
taskID := fmt.Sprintf("batch-scrape-%s-%d", job.ID, i)
adapter.RegisterTask(taskID, i, filePath)
task := NewBatchScrapeTask(taskID, filePath, progressTracker, ...)
pool.Submit(task)
}
// Progress updates are automatically broadcast to WebSocket clients
func NewProgressAdapter ¶
func NewProgressAdapter(jobID string, job *worker.BatchJob, broadcaster ProgressBroadcaster) *ProgressAdapter
NewProgressAdapter creates a new progress adapter for a batch job. The adapter listens to progress updates and broadcasts them via WebSocket. If broadcaster is nil, the global wsHub will be used.
func (*ProgressAdapter) GetChannel ¶
func (a *ProgressAdapter) GetChannel() chan<- worker.ProgressUpdate
GetChannel returns a write-only channel for ProgressTracker to send updates. This channel should be passed to worker.NewProgressTracker().
func (*ProgressAdapter) GetRegisteredTaskCount ¶
func (a *ProgressAdapter) GetRegisteredTaskCount() int
GetRegisteredTaskCount returns the number of currently registered tasks. Useful for debugging and monitoring.
func (*ProgressAdapter) RegisterTask ¶
func (a *ProgressAdapter) RegisterTask(taskID string, fileIndex int, filePath string)
RegisterTask maps a task ID to its corresponding file index and path. This mapping is used to correlate progress updates with specific files. Thread-safe for concurrent registration during task submission.
func (*ProgressAdapter) Start ¶
func (a *ProgressAdapter) Start()
Start launches the adapter's update processing goroutine. It listens for progress updates and converts them to WebSocket messages. This method is non-blocking; use Stop() to shut down gracefully.
func (*ProgressAdapter) Stop ¶
func (a *ProgressAdapter) Stop()
Stop signals the adapter to shut down and waits for the processing goroutine to finish. This ensures graceful cleanup of resources. Stop is idempotent and safe to call multiple times.
func (*ProgressAdapter) UnregisterTask ¶
func (a *ProgressAdapter) UnregisterTask(taskID string)
UnregisterTask removes a task from the mapping (optional cleanup). Not strictly necessary as the adapter is typically short-lived per job, but provided for completeness and memory efficiency in long-running jobs.
type ProgressBroadcaster ¶
type ProgressBroadcaster interface {
BroadcastProgress(msg *websocket.ProgressMessage) error
}
ProgressBroadcaster is an interface for broadcasting progress messages. This interface allows for dependency injection and testing with mocks.
type ProxyTestRequest ¶
type ProxyTestRequest struct {
Mode string `json:"mode" binding:"required,oneof=direct flaresolverr"` // direct or flaresolverr
Proxy config.ProxyConfig `json:"proxy"`
TargetURL string `json:"target_url,omitempty"` // Optional override target URL
}
ProxyTestRequest represents a proxy connectivity test request.
type ProxyTestResponse ¶
type ProxyTestResponse struct {
Success bool `json:"success"`
Mode string `json:"mode"`
TargetURL string `json:"target_url"`
StatusCode int `json:"status_code,omitempty"`
DurationMS int64 `json:"duration_ms"`
Message string `json:"message"`
ProxyURL string `json:"proxy_url,omitempty"` // Redacted proxy URL
FlareSolverrURL string `json:"flaresolverr_url,omitempty"` // FlareSolverr endpoint used
}
ProxyTestResponse represents proxy connectivity test results.
type RescrapeRequest ¶
type RescrapeRequest struct {
SelectedScrapers []string `json:"selected_scrapers" binding:"required" example:"r18dev,dmm"`
Force bool `json:"force" example:"false"`
}
RescrapeRequest represents a request to rescrape with specific scrapers
type ScanRequest ¶
type ScanRequest struct {
Path string `json:"path" binding:"required" example:"/path/to/videos"`
Recursive bool `json:"recursive" example:"true"`
Filter string `json:"filter,omitempty" example:"STSK"` // Filter folder/file names (case-insensitive substring match)
}
ScanRequest represents a directory scan request
type ScanResponse ¶
type ScanResponse struct {
Files []FileInfo `json:"files"`
Count int `json:"count" example:"10"`
Skipped []string `json:"skipped,omitempty"`
}
ScanResponse represents scan results
type ScrapeRequest ¶
type ScrapeRequest struct {
ID string `json:"id" binding:"required" example:"IPX-535"`
Force bool `json:"force" example:"false"`
SelectedScrapers []string `json:"selected_scrapers,omitempty" example:"r18dev,dmm"`
}
ScrapeRequest represents the scrape request payload
type ScrapeResponse ¶
type ScrapeResponse struct {
Cached bool `json:"cached" example:"false"`
Movie *models.Movie `json:"movie"`
SourcesUsed int `json:"sources_used,omitempty" example:"2"`
Errors []string `json:"errors,omitempty"`
}
ScrapeResponse represents the scrape response
type ScraperChoice ¶
type ScraperChoice struct {
Value string `json:"value" example:"en"`
Label string `json:"label" example:"English"`
}
ScraperChoice represents a choice for a select-type scraper option
type ScraperInfo ¶
type ScraperInfo struct {
Name string `json:"name" example:"r18dev"`
DisplayName string `json:"display_name" example:"R18.dev"`
Enabled bool `json:"enabled" example:"true"`
Options []ScraperOption `json:"options,omitempty"`
}
ScraperInfo represents information about a scraper
type ScraperOption ¶
type ScraperOption struct {
Key string `json:"key" example:"scrape_actress"`
Label string `json:"label" example:"Scrape Actress Information"`
Description string `json:"description" example:"Enable detailed actress data scraping from DMM (may be slower)"`
Type string `json:"type" example:"boolean"` // boolean, string, number, select
Min *int `json:"min,omitempty" example:"5"`
Max *int `json:"max,omitempty" example:"120"`
Unit string `json:"unit,omitempty" example:"seconds"`
Choices []ScraperChoice `json:"choices,omitempty"` // For select type: available choices
}
ScraperOption represents a configurable option for a scraper
type ServerDependencies ¶
type ServerDependencies struct {
ConfigFile string
Registry *models.ScraperRegistry
DB *database.DB
Aggregator *aggregator.Aggregator
MovieRepo *database.MovieRepository
ActressRepo *database.ActressRepository
HistoryRepo *database.HistoryRepository
Matcher *matcher.Matcher
JobQueue *worker.JobQueue
// contains filtered or unexported fields
}
ServerDependencies holds all dependencies needed to create the API server Access to Config, Registry, Aggregator, and Matcher must be synchronized to prevent data races during config reload.
func (*ServerDependencies) GetAggregator ¶
func (d *ServerDependencies) GetAggregator() *aggregator.Aggregator
GetAggregator returns the current aggregator (thread-safe)
func (*ServerDependencies) GetConfig ¶
func (d *ServerDependencies) GetConfig() *config.Config
GetConfig returns the current configuration (thread-safe)
func (*ServerDependencies) GetMatcher ¶
func (d *ServerDependencies) GetMatcher() *matcher.Matcher
GetMatcher returns the current matcher (thread-safe)
func (*ServerDependencies) GetRegistry ¶
func (d *ServerDependencies) GetRegistry() *models.ScraperRegistry
GetRegistry returns the current scraper registry (thread-safe)
func (*ServerDependencies) SetConfig ¶
func (d *ServerDependencies) SetConfig(cfg *config.Config)
SetConfig atomically sets the configuration (thread-safe)
func (*ServerDependencies) Shutdown ¶
func (d *ServerDependencies) Shutdown()
Shutdown gracefully shuts down server resources, including the WebSocket hub
type TranslationModelsRequest ¶
type TranslationModelsRequest struct {
Provider string `json:"provider" binding:"required"` // openai (OpenAI-compatible only for now)
BaseURL string `json:"base_url" binding:"required"` // API base URL (e.g., https://api.openai.com/v1)
APIKey string `json:"api_key"` // Provider API key
}
TranslationModelsRequest represents a request to fetch available translation models.
type TranslationModelsResponse ¶
type TranslationModelsResponse struct {
Models []string `json:"models"`
}
TranslationModelsResponse represents the model discovery response.
type UpdateMovieRequest ¶
UpdateMovieRequest represents the update movie request payload