all repos — artbound-go @ 79e63cd2787ece34f59ee8d885803aefcccf2945

The official administration panel for ArtBound, by EarthBound Café.

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.Fatal("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.Fatal("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.Fatal("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.Fatal("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}