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