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 InitDB(spreadsheetId string, spreadsheetRange string) *DB {
82 files, err := listCachedEntries(cachePath)
83 if err != nil {
84 log.Fatal("Could not list cached entries.")
85 }
86 googleApi := initGoogleAPI(spreadsheetId, spreadsheetRange)
87 db := &DB{time.Now(), []Entry{}, files, *googleApi}
88 db.update()
89 return db
90}
91
92func (db *DB) update() (error, int) {
93 entries, err := getEntries(&db.googleApi)
94 if err != nil {
95 log.Fatal("Could not update DB!", err)
96 return err, 0
97 }
98 newEntries := len(entries) - len(db.Entries)
99 db.Entries = entries
100 db.LastUpdated = time.Now()
101 return nil, newEntries
102}
103
104func (db *DB) UpdateCall() UpdateDBPayload {
105 err, newEntries := db.update()
106 if err != nil {
107 log.Fatal("Could not update DB!", err)
108 newEntries = 0
109 }
110 return UpdateDBPayload{db.LastUpdated.Format("02/01/2006 15:04"), newEntries}
111}
112
113func (db *DB) GetEntries(month string) ([]Entry, error) {
114 monthTest := func(f Entry) bool { return f.Month == month }
115 res := filter(db.Entries, monthTest)
116
117 if err := os.MkdirAll(cachePath, os.ModePerm); err != nil {
118 return nil, err
119 }
120
121 for i := range res {
122 e := &res[i]
123 isFileCached, ext := isCached(db.cachedEntries, e.FileID)
124 if isFileCached {
125 log.Println(e.FileID, "is cached.")
126 e.FilePath = filepath.Join(cachePath, e.FileID+ext)
127 } else {
128 log.Println(e.FileID, "is not cached. Downloading.")
129 ext, err := getFile(&db.googleApi, e.FileID, cachePath)
130 if err != nil {
131 log.Fatal("Could not download file", e.FileID)
132 }
133 e.FilePath = filepath.Join(cachePath, e.FileID+ext)
134 }
135 }
136
137 return res, nil
138}
139
140func (db *DB) Clear() error {
141 err := filepath.Walk(cachePath, func(path string, info os.FileInfo, err error) error {
142 if err != nil {
143 return err
144 }
145
146 if !info.IsDir() {
147 err := os.Remove(path)
148 if err != nil {
149 return err
150 }
151 fmt.Println("Deleted:", path)
152 }
153
154 return nil
155 })
156
157 if err != nil {
158 return err
159 }
160 db.cachedEntries = []fileDetails{}
161 return nil
162}