From f05febe5d12495bde05524b6554c2b77e767fa28 Mon Sep 17 00:00:00 2001 From: Araozu Date: Wed, 29 May 2024 17:19:47 -0500 Subject: [PATCH] Cache album covers rewritten --- albumCover.go | 101 +++++++++++++++++++++++++++++++++++++++ frontend/vite.config.mts | 9 ++++ frontend/vite.config.ts | 9 ---- session.go | 48 +------------------ types.go | 4 +- 5 files changed, 114 insertions(+), 57 deletions(-) create mode 100644 albumCover.go create mode 100644 frontend/vite.config.mts delete mode 100644 frontend/vite.config.ts diff --git a/albumCover.go b/albumCover.go new file mode 100644 index 0000000..a54cd1f --- /dev/null +++ b/albumCover.go @@ -0,0 +1,101 @@ +package main + +import ( + "errors" + "fmt" + "log" + "os" + "sync" + + "github.com/adrg/xdg" +) + +// Stores information about the album covers cache +type AlbumCoverInfo struct { + Cached bool + Error error + WaitGroup *sync.WaitGroup +} + +// Caches info about the album covers +var albumCoverCacheInfo = make(map[string]*AlbumCoverInfo) +var cacheMutex = sync.RWMutex{} + +// Loads a single album cover and caches it in XDG_CACHE_HOME +// First it checks if the cover already exists in XDG_CACHE_HOME +// If it doesn't, loads it and stores it +func loadAlbumCover(albumId string) { + // Check cache info + cacheMutex.Lock() + _, ok := albumCoverCacheInfo[albumId] + cacheMutex.Unlock() + if ok { + log.Print("album cover: cache hit: ", albumId) + return + } + + albumCacheFile, err := xdg.CacheFile(fmt.Sprintf("%s/%s", appname, albumId)) + if err != nil { + panic(fmt.Sprint("error creating cacheFile url: ", err)) + } + + // Attempt to read file + if _, err = os.Stat(albumCacheFile); err != nil { + // File exists + log.Print("album cover: cache hit (disk): ", albumId) + cacheMutex.Lock() + albumCoverCacheInfo[albumId] = &AlbumCoverInfo{ + Cached: true, + WaitGroup: &sync.WaitGroup{}, + } + cacheMutex.Unlock() + return + } + + // Load cover from network + log.Print("load album cover for ", albumId) + coverInfo := AlbumCoverInfo{ + Cached: false, + WaitGroup: &sync.WaitGroup{}, + } + coverInfo.WaitGroup.Add(1) + defer coverInfo.WaitGroup.Done() + + cacheMutex.Lock() + albumCoverCacheInfo[albumId] = &coverInfo + cacheMutex.Unlock() + + response, err := client.R(). + // TODO: replace `fernando` with the username + Get(fmt.Sprintf( + "%s/rest/getCoverArt.view?id=%s&u=%s&s=12e7f3&t=%s&v=1.13.0&c=wmusic&size=300", + serverUrl, + albumId, + "fernando", + "d7bbe92d7da363aa202ae16136887adc", + )) + + if err != nil { + log.Print("error loadAlbumCover: ", err) + return + } + + if !response.IsSuccess() { + log.Print("error loadAlbumCover") + log.Printf("%s", response.Body()) + coverInfo.Error = errors.New("error loading") + return + } + + imgBytes := response.Body() + + // Write the image to cache + err = os.WriteFile(albumCacheFile, imgBytes, 0644) + if err != nil { + coverInfo.Error = errors.New("error writing album cover to disk") + log.Fatalf("Error writing to cache file for album cover: %s", albumCacheFile) + return + } + + log.Print("Loading albumCover for ", albumId, " successful") +} diff --git a/frontend/vite.config.mts b/frontend/vite.config.mts new file mode 100644 index 0000000..6ee2282 --- /dev/null +++ b/frontend/vite.config.mts @@ -0,0 +1,9 @@ +import { defineConfig } from "vite"; +import solidPlugin from "vite-plugin-solid"; + +export default defineConfig({ + plugins: [solidPlugin()], + build: { + target: "esnext", + }, +}); diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts deleted file mode 100644 index afc5ead..0000000 --- a/frontend/vite.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { defineConfig } from 'vite'; -import solidPlugin from 'vite-plugin-solid'; - -export default defineConfig({ - plugins: [solidPlugin()], - build: { - target: 'esnext', - }, -}); diff --git a/session.go b/session.go index 4dbcadf..3b61b73 100644 --- a/session.go +++ b/session.go @@ -4,10 +4,8 @@ import ( "errors" "fmt" "log" - "os" "sync" - "github.com/adrg/xdg" "github.com/go-resty/resty/v2" ) @@ -15,6 +13,7 @@ type AuthError struct { Error string `json:"error"` } +// Name of the app, used to create directories in XDG_ and store files inside const appname = "wMusic" var LoggedUser AuthSuccess @@ -107,49 +106,4 @@ func loadAlbums(serverUrl string) { go loadAlbumCover(albumId) } } - - // TODO: Do the loading -} - -// Loads a single album cover and caches it in XDG_CACHE_HOME -func loadAlbumCover(albumId string) { - log.Print("Loading albumCover for ", albumId) - - response, err := client.R(). - // TODO: replace `fernando` with the username - Get(fmt.Sprintf( - "%s/rest/getCoverArt.view?id=%s&u=fernando&s=12e7f3&t=%s&v=1.13.0&c=wmusic&size=300", - serverUrl, - albumId, - "d7bbe92d7da363aa202ae16136887adc", - )) - - if err != nil { - log.Print("error loadAlbumCover: ", err) - return - } - - if !response.IsSuccess() { - log.Print("error loadAlbumCover") - log.Printf("%s", response.Body()) - return - } - - imgBytes := response.Body() - - // Write the image to cache - // TODO: Actually check in cache if the album art exists - cacheFile, err := xdg.CacheFile(fmt.Sprintf("%s/%s", appname, albumId)) - - if err != nil { - log.Print("error loadAlbumCover - CacheFile:", err) - return - } - - err = os.WriteFile(cacheFile, imgBytes, 0666) - if err != nil { - panic(fmt.Sprintf("Error writing to cache file for album cover: %s", cacheFile)) - } - - log.Print("Loading albumCover for ", albumId, " successful") } diff --git a/types.go b/types.go index aef9aa2..9bcd6cb 100644 --- a/types.go +++ b/types.go @@ -1,6 +1,8 @@ package main -import "time" +import ( + "time" +) // The result of a Login type AuthSuccess struct {