lens @ c2d666b43477ea7042b574ad940c508216cb0e83

 1package worker
 2
 3import (
 4	"context"
 5	"io/fs"
 6	"mime"
 7	"path/filepath"
 8
 9	"git.sr.ht/~gabrielgio/img/pkg/database/repository"
10	"git.sr.ht/~gabrielgio/img/pkg/fileop"
11)
12
13type (
14	FileScanner struct {
15		root       string
16		repository repository.MediaRepository
17	}
18)
19
20var _ ChanProcessor[string] = &FileScanner{}
21
22func NewFileScanner(root string, repository repository.MediaRepository) *FileScanner {
23	return &FileScanner{
24		root:       root,
25		repository: repository,
26	}
27}
28
29func (f *FileScanner) Query(ctx context.Context) (<-chan string, error) {
30	c := make(chan string)
31	go func() {
32		defer close(c)
33		_ = filepath.Walk(f.root, func(path string, info fs.FileInfo, err error) error {
34			select {
35			case <-ctx.Done():
36				return filepath.SkipAll
37			default:
38			}
39
40			if info == nil {
41				return nil
42			}
43
44			if info.IsDir() && filepath.Base(info.Name())[0] == '.' {
45				return filepath.SkipDir
46			}
47
48			if info.IsDir() {
49				return nil
50			}
51
52			c <- path
53			return nil
54		})
55	}()
56	return c, nil
57}
58
59func (f *FileScanner) Process(ctx context.Context, path string) error {
60	mimetype := mime.TypeByExtension(filepath.Ext(path))
61	supported := fileop.IsMimeTypeSupported(mimetype)
62	if !supported {
63		return nil
64	}
65
66	hash := fileop.GetHashFromPath(path)
67
68	exists, err := f.repository.Exists(ctx, hash)
69	if err != nil {
70		return err
71	}
72
73	if exists {
74		return nil
75	}
76
77	return f.repository.Create(ctx, &repository.CreateMedia{
78		Name:     filepath.Base(path),
79		Path:     path,
80		PathHash: hash,
81		MIMEType: mimetype,
82	})
83}