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