Files
pmomusic/pmocover/cache.go

130 lines
2.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package pmocover
import (
"bytes"
"crypto/sha1"
"encoding/hex"
"errors"
"image"
"io"
"net/http"
"os"
"path/filepath"
"sync"
)
// CacheEntry représente une image stockée (original + dérivés)
type CacheEntry struct {
PK string `json:"pk"`
SourceURL string `json:"source_url"`
Hits int `json:"hits"`
LastUsed string `json:"last_used"` // ISO8601
}
// Cache persistant avec SQLite
type Cache struct {
dir string
limit int
db *DB
mu sync.Mutex
}
// NewCache ouvre ou crée un cache persistant avec SQLite
func NewCache(dir string, limit int) (*Cache, error) {
if err := os.MkdirAll(dir, 0o755); err != nil {
return nil, err
}
db, err := InitDB(dir)
if err != nil {
return nil, err
}
return &Cache{
dir: dir,
limit: limit,
db: db,
}, nil
}
// AddFromURL télécharge une image et la met en cache
func (c *Cache) AddFromURL(url string) (string, error) {
resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", errors.New("bad status")
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
return c.Add(url, data)
}
// Add ajoute une image déjà téléchargée
func (c *Cache) Add(url string, data []byte) (string, error) {
pk := pkFromURL(url)
origPath := filepath.Join(c.dir, pk+".orig.webp")
c.mu.Lock()
defer c.mu.Unlock()
if _, err := os.Stat(origPath); errors.Is(err, os.ErrNotExist) {
img, _, err := image.Decode(bytes.NewReader(data))
if err != nil {
return "", err
}
buf, err := encodeWebP(img)
if err != nil {
return "", err
}
if err := os.WriteFile(origPath, buf, 0o644); err != nil {
return "", err
}
}
_ = c.db.Add(pk, url) // ajoute ou met à jour la base
return pk, nil
}
// Get renvoie le chemin du fichier original et met à jour hits/last_used
func (c *Cache) Get(pk string) (string, error) {
c.mu.Lock()
defer c.mu.Unlock()
_, err := c.db.Get(pk)
if err != nil {
return "", err
}
_ = c.db.UpdateHit(pk)
origPath := filepath.Join(c.dir, pk+".orig.webp")
if _, err := os.Stat(origPath); err != nil {
return "", err
}
return origPath, nil
}
// Purge vide complètement le cache
func (c *Cache) Purge() error {
c.mu.Lock()
defer c.mu.Unlock()
files, _ := filepath.Glob(filepath.Join(c.dir, "*"))
for _, f := range files {
os.Remove(f)
}
return c.db.Purge()
}
// pkFromURL → hash stable basé sur lURL
func pkFromURL(url string) string {
h := sha1.Sum([]byte(url))
return hex.EncodeToString(h[:8])
}