cache/cache.go (view raw)
1package cache
2
3import (
4 "fmt"
5 "log"
6 "os"
7 "path/filepath"
8 "strings"
9 "time"
10)
11
12const (
13 CachePath = "art"
14 filenameSeparator = "-_-_-_-_-_"
15)
16
17type UpdateDBPayload struct {
18 LastUpdated string `json:"timestamp"`
19 NewEntries int `json:"new"`
20}
21
22type DB struct {
23 LastUpdated time.Time
24 Entries []Entry
25 cachedEntries []fileDetails
26 googleApi GoogleAPI
27}
28
29type fileDetails struct {
30 FileName string
31 OriginalFileName string
32 Extension string
33}
34
35func filter[T any](ss []T, test func(T) bool) (ret []T) {
36 for _, s := range ss {
37 if test(s) {
38 ret = append(ret, s)
39 }
40 }
41 return
42}
43
44func listCachedEntries(CachePath string) ([]fileDetails, error) {
45 var files []fileDetails
46
47 err := filepath.Walk(CachePath, func(path string, info os.FileInfo, err error) error {
48 if err != nil {
49 return err
50 }
51
52 if info.IsDir() {
53 return nil // Skip directories
54 }
55
56 fileName := info.Name()
57 extension := filepath.Ext(fileName)
58 fileNameWithoutExt := strings.TrimSuffix(fileName, extension)
59 originalFileName := strings.Split(fileNameWithoutExt, filenameSeparator)[1]
60
61 file := fileDetails{
62 FileName: fileNameWithoutExt,
63 OriginalFileName: originalFileName,
64 Extension: extension,
65 }
66
67 files = append(files, file)
68 return nil
69 })
70
71 if err != nil {
72 return []fileDetails{}, err
73 }
74
75 return files, nil
76}
77
78func isCached(cachedEntries []fileDetails, target string) (bool, string) {
79 for _, file := range cachedEntries {
80 fileId := strings.Split(file.FileName, filenameSeparator)[0]
81 if fileId == target {
82 return true, file.FileName + file.Extension
83 }
84 }
85 return false, ""
86}
87
88func handleEntry(entry *Entry, db *DB) string {
89 isFileCached, fileName := isCached(db.cachedEntries, entry.FileID)
90
91 if isFileCached {
92 log.Println(entry.FileID, "is cached.")
93 return fileName
94 }
95 log.Println(entry.FileID, "is not cached. Downloading.")
96 fileName, err := getFile(&db.googleApi, entry.FileID, CachePath)
97 if err != nil {
98 log.Println("Could not download file", entry.FileID)
99 }
100 return fileName
101}
102
103func InitDB(spreadsheetId string, spreadsheetRange string) *DB {
104 files, err := listCachedEntries(CachePath)
105 if err != nil {
106 log.Println("Could not list cached entries.")
107 }
108 googleApi := initGoogleAPI(spreadsheetId, spreadsheetRange)
109 db := &DB{time.Now(), []Entry{}, files, *googleApi}
110 db.update()
111 return db
112}
113
114func (db *DB) update() (int, error) {
115 entries, err := getEntries(&db.googleApi)
116 if err != nil {
117 log.Println("Could not update DB!", err)
118 return 0, err
119 }
120 newEntries := len(entries) - len(db.Entries)
121 db.Entries = entries
122 db.LastUpdated = time.Now()
123 return newEntries, nil
124}
125
126func (db *DB) UpdateCall() UpdateDBPayload {
127 newEntries, err := db.update()
128 if err != nil {
129 log.Println("Could not update DB!", err)
130 newEntries = 0
131 }
132 return UpdateDBPayload{db.LastUpdated.Format("02/01/2006 15:04"), newEntries}
133}
134
135func (db *DB) GetEntries(month string) ([]Entry, error) {
136 monthTest := func(f Entry) bool { return f.Month == month }
137 res := filter(db.Entries, monthTest)
138
139 if err := os.MkdirAll(CachePath, os.ModePerm); err != nil {
140 return nil, err
141 }
142
143 for i := range res {
144 e := &res[i]
145 fileName := handleEntry(e, db)
146 e.FilePath = filepath.Join(CachePath, fileName)
147 e.FileName = strings.Split(fileName, filenameSeparator)[1]
148 }
149
150 return res, nil
151}
152
153func (db *DB) Clear() error {
154 err := filepath.Walk(CachePath, func(path string, info os.FileInfo, err error) error {
155 if err != nil {
156 return err
157 }
158
159 if !info.IsDir() {
160 err := os.Remove(path)
161 if err != nil {
162 return err
163 }
164 fmt.Println("Deleted:", path)
165 }
166
167 return nil
168 })
169
170 if err != nil {
171 return err
172 }
173 db.cachedEntries = []fileDetails{}
174 return nil
175}