all repos — artbound-go @ main

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