Files
unified-media-manager/internal/worker/subtitle_search.go
2026-04-24 10:45:19 -07:00

113 lines
2.6 KiB
Go

package worker
import (
"context"
"log/slog"
"os"
"path/filepath"
"time"
"github.com/TopherMayor/unified-media-manager/internal/config"
"github.com/TopherMayor/unified-media-manager/internal/db"
"github.com/TopherMayor/unified-media-manager/internal/service"
)
type SubtitleSearchWorker struct {
database *db.DB
subtitleSvc *service.SubtitleService
cfg *config.Config
}
func NewSubtitleSearchWorker(database *db.DB, subtitleSvc *service.SubtitleService, cfg *config.Config) *SubtitleSearchWorker {
return &SubtitleSearchWorker{
database: database,
subtitleSvc: subtitleSvc,
cfg: cfg,
}
}
func (w *SubtitleSearchWorker) Name() string {
return "subtitle_search"
}
func (w *SubtitleSearchWorker) CronExpr() string {
return w.cfg.WorkerSubtitleInterval
}
func (w *SubtitleSearchWorker) Run(ctx context.Context) error {
ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
defer cancel()
searched := 0
downloaded := 0
errors := 0
rows, err := w.database.Pool.Query(ctx,
`SELECT m.id, m.media_type, m.title, mf.path
FROM media m
JOIN media_files mf ON m.id = mf.media_id AND mf.deleted_at IS NULL
WHERE m.deleted_at IS NULL AND m.status = 'available'
ORDER BY m.id`)
if err != nil {
return err
}
defer rows.Close()
type mediaFile struct {
mediaID int64
mediaType string
title string
path string
}
var files []mediaFile
for rows.Next() {
var f mediaFile
if err := rows.Scan(&f.mediaID, &f.mediaType, &f.title, &f.path); err != nil {
slog.Error("failed to scan media file", "error", err)
continue
}
files = append(files, f)
}
for _, f := range files {
ext := filepath.Ext(f.path)
basePath := f.path[:len(f.path)-len(ext)]
srtPath := basePath + ".eng.srt"
sdhPath := basePath + ".eng.sdh.srt"
if _, err := os.Stat(srtPath); err == nil {
continue
}
if _, err := os.Stat(sdhPath); err == nil {
continue
}
results, err := w.subtitleSvc.Search(ctx, f.title, service.SubtitleSearchOptions{
LanguageCodes: []string{"eng"},
})
if err != nil {
slog.Error("failed to search subtitles", "media_id", f.mediaID, "error", err)
errors++
continue
}
searched++
if len(results) == 0 {
continue
}
baseName := filepath.Base(basePath)
_, err = w.subtitleSvc.Download(ctx, results[0].ID, filepath.Dir(f.path), baseName, results[0].LanguageCode, results[0].HI, results[0].Forced)
if err != nil {
slog.Error("failed to download subtitle", "media_id", f.mediaID, "error", err)
errors++
continue
}
downloaded++
}
slog.Info("subtitle search completed", "searched", searched, "downloaded", downloaded, "errors", errors)
return nil
}