media.go
⎇
Raw
1package service
2
3import (
4 "fmt"
5 "os"
6 "path/filepath"
7 "strings"
8
9 "vidarchive/internal/models"
10 "vidarchive/internal/repository"
11)
12
13type MediaService struct {
14 repo *repository.MediaRepository
15 downloadDir string
16}
17
18func NewMediaService(repo *repository.MediaRepository, downloadDir string) *MediaService {
19 return &MediaService{repo: repo, downloadDir: downloadDir}
20}
21
22func (s *MediaService) GetByID(id int64) (*models.Media, error) {
23 return s.repo.GetByID(id)
24}
25
26func (s *MediaService) GetByRelativePath(relPath string) (*models.Media, error) {
27 return s.repo.GetByRelativePath(relPath)
28}
29
30func (s *MediaService) GetAll(path, sortBy, filter string) ([]*models.Media, []string, error) {
31 if path != "" && !strings.HasSuffix(path, "/") {
32 path += "/"
33 }
34
35 media, err := s.repo.GetAll(path, sortBy, filter)
36 if err != nil {
37 return nil, nil, err
38 }
39
40 folders, err := s.repo.GetFolders(path)
41 if err != nil {
42 return nil, nil, err
43 }
44
45 return media, folders, nil
46}
47
48func (s *MediaService) ScanLibrary() error {
49 return filepath.Walk(s.downloadDir, func(path string, info os.FileInfo, err error) error {
50 if err != nil {
51 return err
52 }
53 if info.IsDir() {
54 return nil
55 }
56
57 // Check if this file is already in DB
58 relPath, _ := filepath.Rel(s.downloadDir, path)
59 relPath = filepath.ToSlash(relPath)
60
61 _, err = s.repo.GetByRelativePath(relPath)
62 if err == nil {
63 return nil // already exists
64 }
65
66 // Determine file type
67 ext := strings.ToLower(filepath.Ext(path))
68 isAudio := ext == ".mp3" || ext == ".m4a" || ext == ".ogg" || ext == ".wav" || ext == ".flac" || ext == ".aac" || ext == ".opus"
69 isVideo := ext == ".mp4" || ext == ".webm" || ext == ".mkv" || ext == ".avi" || ext == ".mov"
70
71 if !isAudio && !isVideo {
72 return nil
73 }
74
75 // Try to find info.json
76 basePath := strings.TrimSuffix(path, ext)
77 infoJSONPath := basePath + ".info.json"
78 if _, err := os.Stat(infoJSONPath); err != nil {
79 infoJSONPath = ""
80 }
81
82 media := &models.Media{
83 Filepath: path,
84 RelativePath: relPath,
85 IsAudio: isAudio,
86 InfoJSONPath: infoJSONPath,
87 }
88
89 // Try to extract title from filename
90 media.Title = strings.TrimSuffix(filepath.Base(path), ext)
91
92 return s.repo.Create(media)
93 })
94}
95
96func (s *MediaService) Delete(id int64) error {
97 media, err := s.repo.GetByID(id)
98 if err != nil {
99 return err
100 }
101
102 // Delete file
103 if err := os.Remove(media.Filepath); err != nil && !os.IsNotExist(err) {
104 return fmt.Errorf("remove file: %w", err)
105 }
106
107 // Delete info json if exists
108 if media.InfoJSONPath != "" {
109 os.Remove(media.InfoJSONPath)
110 }
111
112 return s.repo.Delete(id)
113}
114