package ytdl import ( "io" "go.fifitido.net/ytdl-web/config" "go.fifitido.net/ytdl-web/ytdl/cache" "go.fifitido.net/ytdl-web/ytdl/metadata" "golang.org/x/exp/slog" ) type Ytdl interface { GetMetadata(url string) (*metadata.Metadata, error) Download(w io.Writer, url, format string, index int) error } type ytdlImpl struct { cfg *config.Config logger *slog.Logger cache cache.MetadataCache } func NewYtdl(cfg *config.Config, logger *slog.Logger, cache cache.MetadataCache) Ytdl { return &ytdlImpl{ cfg: cfg, logger: logger.With(slog.String("module", "ytdl")), cache: cache, } } func (y *ytdlImpl) baseOptions(url string) []Option { options := []Option{} metadata, err := y.cache.Get(url) if err == nil { options = append(options, WithLoadJson(metadata)) } if y.cfg.Cookies.Enabled { if y.cfg.Cookies.FromBrowser != nil { options = append(options, WithBrowserCookies( y.cfg.Cookies.FromBrowser.Browser, y.cfg.Cookies.FromBrowser.Keyring, y.cfg.Cookies.FromBrowser.Profile, y.cfg.Cookies.FromBrowser.Container, )) } else { options = append(options, WithCookieFile(y.cfg.Cookies.FilePath)) } } if y.cfg.IsDevelopment() { options = append(options, WithDebug()) } return options } // GetMetadata implements Ytdl func (y *ytdlImpl) GetMetadata(url string) (*metadata.Metadata, error) { meta, err := y.cache.Get(url) if err == nil { return meta, nil } meta = &metadata.Metadata{} options := append( y.baseOptions(url), WithDumpJson(meta), ) if err := Exec(y.cfg.BinaryPath, url, options...); err != nil { y.logger.Error("failed to get metadata", slog.String("url", url), slog.String("error", err.Error())) return nil, err } if err := y.cache.Set(url, meta, y.cfg.Cache.TTL); err != nil { y.logger.Warn("failed to cache metadata", slog.String("url", url), slog.String("error", err.Error())) } return meta, nil } // Download implements Ytdl func (y *ytdlImpl) Download(w io.Writer, url, format string, index int) error { options := append( y.baseOptions(url), WithFormat(format), WithStreamOutput(w), ) if index >= 0 { options = append(options, WithPlaylistIndex(index)) } if err := Exec(y.cfg.BinaryPath, url, options...); err != nil { return err } return nil }