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}