lens @ 9ba05d26ee2382f3191e25ae7af5d462ba2a35e4

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