Files
lambda/cache.go
T

131 lines
2.7 KiB
Go
Raw Normal View History

2026-01-29 21:35:36 +00:00
package main
// This file caches images in memory so we are not loading them from disk every time we need them
// It also does the same for images that need to be grabbed from HTTP.
import (
"crypto/sha256"
"fmt"
2026-01-30 10:40:38 +00:00
"github.com/diamondburned/gotk4/pkg/gdk/v4"
"github.com/diamondburned/gotk4/pkg/gtk/v4"
2026-01-30 15:56:58 +00:00
"github.com/kirsle/configdir"
2026-01-29 21:35:36 +00:00
"io"
2026-01-30 10:40:38 +00:00
"net/http"
2026-01-29 21:35:36 +00:00
"os"
2026-01-30 10:40:38 +00:00
"path/filepath"
2026-05-02 06:56:08 +01:00
"sync"
2026-01-29 21:35:36 +00:00
)
// global or app-level map/cache
2026-05-02 06:56:08 +01:00
// var textureCache = make(map[string]gdk.Paintabler)
var textureCache sync.Map
2026-01-29 21:35:36 +00:00
// Invalid images, if an image/avatar cannot be loaded on the system (e.g: incompatible format) it's put here
var invalidImages = make(map[string]bool)
2026-01-30 10:40:38 +00:00
func ensureCache() (string, error) {
cachePath := configdir.LocalCache("lambda-im")
err := configdir.MakePath(cachePath) // Ensure it exists.
if err != nil {
return "", err
}
2026-01-29 21:35:36 +00:00
2026-01-30 10:40:38 +00:00
return cachePath, nil
}
2026-01-29 21:35:36 +00:00
2026-05-02 06:56:08 +01:00
func getTexture(path string) (gdk.Paintabler, error) {
tex, exists := textureCache.Load(path)
if exists {
return tex.(gdk.Paintabler), nil
2026-01-29 21:35:36 +00:00
}
2026-05-02 06:56:08 +01:00
2026-01-29 21:35:36 +00:00
tex, err := gdk.NewTextureFromFilename(path) // load once
if err != nil {
2026-05-02 06:56:08 +01:00
return nil, err
2026-01-29 21:35:36 +00:00
}
2026-05-02 06:56:08 +01:00
textureCache.Store(path, tex)
return tex.(gdk.Paintabler), nil
2026-01-29 21:35:36 +00:00
}
2026-05-02 06:56:08 +01:00
func newPictureFromPath(path string) (*gtk.Picture, error) {
tex, err := getTexture(path)
if err != nil {
return nil, err
}
2026-01-29 21:35:36 +00:00
img := gtk.NewPictureForPaintable(tex)
2026-05-02 06:56:08 +01:00
return img, nil
2026-01-29 21:35:36 +00:00
}
2026-05-02 06:56:08 +01:00
func newImageFromPath(path string) (*gtk.Image, error) {
tex, err := getTexture(path)
if err != nil {
return nil, err
}
2026-01-29 21:35:36 +00:00
img := gtk.NewImageFromPaintable(tex)
2026-05-02 06:56:08 +01:00
return img, nil
2026-01-29 21:35:36 +00:00
}
2026-05-02 06:56:08 +01:00
func newPictureFromWeb(url string) (*gtk.Picture, error) {
2026-01-30 10:40:38 +00:00
pa, _ := ensureCache()
2026-01-29 21:35:36 +00:00
// step 1: get a sha256 sum of the URL
sum := fmt.Sprintf("%x", sha256.Sum256([]byte(url)))
2026-05-02 06:56:08 +01:00
p, ok := textureCache.Load(sum)
2026-01-29 21:35:36 +00:00
if ok {
2026-05-02 06:56:08 +01:00
return gtk.NewPictureForPaintable(p.(gdk.Paintabler)), nil
2026-01-29 21:35:36 +00:00
}
// step 2: download it
resp, err := http.Get(url)
if err != nil {
2026-05-02 06:56:08 +01:00
return nil, err
2026-01-29 21:35:36 +00:00
}
b, err := io.ReadAll(resp.Body)
if err != nil {
2026-05-02 06:56:08 +01:00
return nil, err
2026-01-29 21:35:36 +00:00
}
2026-01-30 10:40:38 +00:00
fullpath := filepath.Join(pa, sum)
2026-01-29 21:35:36 +00:00
// step 3: save it
2026-01-30 10:40:38 +00:00
err = os.WriteFile(fullpath, b, 0644)
2026-01-29 21:35:36 +00:00
if err != nil {
2026-05-02 06:56:08 +01:00
return nil, err
2026-01-29 21:35:36 +00:00
}
2026-01-30 10:40:38 +00:00
return newPictureFromPath(fullpath)
2026-01-29 21:35:36 +00:00
}
2026-05-02 06:56:08 +01:00
func newImageFromWeb(url string) (*gtk.Image, error) {
2026-01-30 10:40:38 +00:00
pa, _ := ensureCache()
2026-01-29 21:35:36 +00:00
// step 1: get a sha256 sum of the URL
sum := fmt.Sprintf("%x", sha256.Sum256([]byte(url)))
2026-05-02 06:56:08 +01:00
p, ok := textureCache.Load(sum)
2026-01-29 21:35:36 +00:00
if ok {
2026-05-02 06:56:08 +01:00
return gtk.NewImageFromPaintable(p.(gdk.Paintabler)), nil
2026-01-29 21:35:36 +00:00
}
// step 2: download it
resp, err := http.Get(url)
if err != nil {
2026-05-02 06:56:08 +01:00
return nil, err
2026-01-29 21:35:36 +00:00
}
b, err := io.ReadAll(resp.Body)
if err != nil {
2026-05-02 06:56:08 +01:00
return nil, err
2026-01-29 21:35:36 +00:00
}
2026-01-30 10:40:38 +00:00
fullpath := filepath.Join(pa, sum)
2026-01-29 21:35:36 +00:00
// step 3: save it
2026-01-30 10:40:38 +00:00
err = os.WriteFile(fullpath, b, 0644)
2026-01-29 21:35:36 +00:00
if err != nil {
2026-05-02 06:56:08 +01:00
return nil, err
2026-01-29 21:35:36 +00:00
}
2026-01-30 10:40:38 +00:00
return newImageFromPath(fullpath)
2026-01-29 21:35:36 +00:00
}