package worker import ( "context" "crypto/md5" "encoding/hex" "io/fs" "mime" "path/filepath" "strings" "git.sr.ht/~gabrielgio/img/pkg/components/media" ) type ( FileScanner struct { root string repository media.Repository } ) var _ ChanProcessor[string] = &FileScanner{} func NewFileScanner(root string, repository media.Repository) *FileScanner { return &FileScanner{ root: root, repository: repository, } } func (f *FileScanner) Query(ctx context.Context) (<-chan string, error) { c := make(chan string) go func() { defer close(c) _ = filepath.Walk(f.root, func(path string, info fs.FileInfo, err error) error { select { case <-ctx.Done(): return filepath.SkipAll default: } if info == nil { return nil } if info.IsDir() && filepath.Base(info.Name())[0] == '.' { return filepath.SkipDir } if info.IsDir() { return nil } c <- path return nil }) }() return c, nil } func (f *FileScanner) Process(ctx context.Context, path string) error { m := mime.TypeByExtension(filepath.Ext(path)) if !strings.HasPrefix(m, "video") && !strings.HasPrefix(m, "image") { return nil } hash := md5.Sum([]byte(path)) str := hex.EncodeToString(hash[:]) name := filepath.Base(path) exists, errResp := f.repository.Exists(ctx, str) if errResp != nil { return errResp } if exists { return nil } if errResp != nil { return errResp } return f.repository.Create(ctx, &media.CreateMedia{ Name: name, Path: path, PathHash: str, MIMEType: m, }) }