all repos — artbound-go @ fb0e632d3bc35cf68935216fc12703c02e8c20e1

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 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}