package ytdlp import ( "context" "encoding/json" "fmt" "path" "sync" "time" "git.kmsign.ru/royalcat/tstor/pkg/ctxbilly" "git.kmsign.ru/royalcat/tstor/src/vfs" "github.com/go-git/go-billy/v5/osfs" "github.com/royalcat/ctxio" "github.com/royalcat/ctxprogress" ) func NewService(dataDir string) *Service { s := &Service{ dataDir: dataDir, sources: make(map[string]ytdlpSource, 0), } go func() { for { ctx := context.Background() ctx = ctxprogress.New(ctx) ctxprogress.AddCallback(ctx, func(p ctxprogress.Progress) { cur, total := p.Progress() fmt.Printf("updating sources: %d/%d\n", cur, total) }) err := s.Update(ctx) if err != nil { fmt.Println("failed to update sources:", err) } time.Sleep(time.Minute) } }() return s } type Service struct { mu sync.Mutex dataDir string sources map[string]ytdlpSource } func (c *Service) addSource(s ytdlpSource) { c.mu.Lock() defer c.mu.Unlock() c.sources[s.Name()] = s } func (c *Service) sourceDir(s ytdlpSource) string { return path.Join(c.dataDir, s.Name()) } func (c *Service) Update(ctx context.Context) error { for name, s := range c.sources { if ctx.Err() != nil { return ctx.Err() } dir := c.sourceDir(s) err := s.Download(ctx, nil, dir) if err != nil { return fmt.Errorf("failed to fetch source %s: %w", name, err) } } return nil } func (c *Service) BuildFS(ctx context.Context, f vfs.File) (vfs.Filesystem, error) { data, err := ctxio.ReadAll(ctx, f) if err != nil { return nil, fmt.Errorf("failed to read source file: %w", err) } var s ytdlpSource err = json.Unmarshal(data, &s) if err != nil { return nil, err } c.addSource(s) downloadFS := ctxbilly.WrapFileSystem(osfs.New(c.sourceDir(s))) return newSourceFS(path.Base(f.Name()), downloadFS, c, s), nil }