113 lines
2.6 KiB
Go
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
|
|
}
|