package ytdlp import ( "context" "os" "git.kmsign.ru/royalcat/tstor/pkg/ctxbilly" "git.kmsign.ru/royalcat/tstor/pkg/kvsingle" "git.kmsign.ru/royalcat/tstor/pkg/rlog" "git.kmsign.ru/royalcat/tstor/pkg/ytdlp" "git.kmsign.ru/royalcat/tstor/src/tasks" "github.com/royalcat/ctxio" "github.com/royalcat/ctxprogress" "github.com/royalcat/kv" ) type Controller struct { datafs ctxbilly.Filesystem source Source client *ytdlp.Client cachedinfo *kvsingle.Value[string, ytdlp.Info] } func newYtdlpController(datafs ctxbilly.Filesystem, source Source, client *ytdlp.Client) *Controller { return &Controller{ datafs: datafs, source: source, client: client, } } func (c *Controller) Source() Source { return c.source } const sizeApprox = 1024 * 1024 * 1024 func (c *Controller) Update(ctx context.Context, updater tasks.Updater) error { log := updater.Logger() ctxprogress.New(ctx) ctxprogress.Set(ctx, ctxprogress.RangeProgress{Current: 0, Total: 10}) plst, err := c.client.Playlist(ctx, c.source.Url) ctxprogress.Set(ctx, ctxprogress.RangeProgress{Current: 1, Total: 10}) ctxprogress.Range(ctx, plst, func(ctx context.Context, _ int, e ytdlp.Entry) bool { if e.OriginalURL == "" { log.Error("no URL in entry", rlog.Error(err)) return true } info, err := c.Info(ctx) if err != nil { log.Error("error getting info", rlog.Error(err)) return true } dwl := info.RequestedDownloads[0] fileinfo, err := c.datafs.Stat(ctx, dwl.Filename) if err != nil { log.Error("error getting file info", rlog.Error(err)) return true } if fileinfo.Size()+sizeApprox > dwl.FilesizeApprox && fileinfo.Size()-sizeApprox < dwl.FilesizeApprox { log.Debug("file already downloaded", "filename", dwl.Filename) return true } file, err := c.datafs.OpenFile(ctx, dwl.Filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666) if err != nil { log.Error("error opening destination file", rlog.Error(err)) return true } err = c.client.Download(ctx, info.OriginalURL, ctxio.IoWriter(ctx, file)) if err != nil { return false } return true }) ctxprogress.Set(ctx, ctxprogress.RangeProgress{Current: 2, Total: 2}) if err != nil { return err } return nil } func (c *Controller) Info(ctx context.Context) (ytdlp.Info, error) { info, err := c.cachedinfo.Get(ctx) if err == nil { return info, nil } if err != kv.ErrKeyNotFound { return info, err } info, err = c.Info(ctx) if err != nil { return info, err } err = c.cachedinfo.Set(ctx, info) if err != nil { return info, err } return info, nil } func (c *Controller) Downloaded() error { return nil }