2025-05-29 11:49:16 +02:00

145 lines
3.3 KiB
Go

package webpconverter
import (
"bytes"
"image"
"image/png"
"io"
"path/filepath"
"strings"
"github.com/chai2010/webp"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/tools/filesystem"
"github.com/pocketbase/pocketbase/tools/hook"
)
func CreateEventHandler(app *pocketbase.PocketBase) *hook.Handler[*core.RecordEvent] {
return &hook.Handler[*core.RecordEvent]{
Func: func(e *core.RecordEvent) error {
fieldsData := e.Record.FieldsData()
for _, v := range fieldsData {
if files, ok := v.([]interface{}); ok {
for _, f := range files {
if file, ok := f.(*filesystem.File); ok {
if shouldBeReplacedWithWebp(file.Name) {
convertToWebp(file)
}
}
}
}
if f, ok := v.(interface{}); ok {
if file, ok := f.(*filesystem.File); ok {
if shouldBeReplacedWithWebp(file.Name) {
convertToWebp(file)
}
}
}
}
return e.Next()
},
Priority: 100,
}
}
func ThumbEventHandler(app *pocketbase.PocketBase) *hook.Handler[*core.FileDownloadRequestEvent] {
return &hook.Handler[*core.FileDownloadRequestEvent]{
Func: func(fdre *core.FileDownloadRequestEvent) error {
if filepath.Ext(fdre.ServedName) == ".webp" {
filename := fdre.Request.PathValue("filename")
baseFilesPath := fdre.Record.BaseFilesPath()
fs, err := app.App.NewFilesystem()
if err != nil {
return err
}
defer fs.Close()
blob, err := fs.GetReader(baseFilesPath + "/thumbs_" + filename + "/" + fdre.ServedName)
if err != nil {
blob, err = fs.GetReader(baseFilesPath + "/" + fdre.ServedName)
if err != nil {
return err
}
}
defer blob.Close()
img, err := png.Decode(blob)
if err != nil {
return fdre.Next()
}
buf := bytes.Buffer{}
err = webp.Encode(&buf, img, &webp.Options{Quality: 80})
if err != nil {
return err
}
err = fs.Upload(buf.Bytes(), baseFilesPath+"/thumbs_"+filename+"/"+fdre.ServedName)
if err != nil {
_, err := fdre.Response.Write(buf.Bytes())
if err != nil {
return err
}
return nil
}
return fdre.Next()
}
return fdre.Next()
},
Priority: 99,
}
}
func convertToWebp(file *filesystem.File) error {
file.Name = replaceExtWithWebp(file.Name)
file.OriginalName = replaceExtWithWebp(file.OriginalName)
ff, err := file.Reader.Open()
if err != nil {
return err
}
defer ff.Close()
fff, err := io.ReadAll(ff)
if err != nil {
return err
}
img, _, err := image.Decode(bytes.NewReader(fff))
if err != nil {
return err
}
buf := bytes.Buffer{}
err = webp.Encode(&buf, img, &webp.Options{Quality: 80})
if err != nil {
return err
}
file.Reader = &memFileReader{data: buf.Bytes()}
file.Size = int64(buf.Len())
return nil
}
func replaceExtWithWebp(path string) string {
// List of image extensions to convert
exts := []string{".png", ".jpg", ".jpeg", ".bmp", ".tiff"}
for _, ext := range exts {
if strings.HasSuffix(strings.ToLower(path), ext) {
return strings.TrimSuffix(path, ext) + ".webp"
}
}
return path
}
func shouldBeReplacedWithWebp(path string) bool {
// List of image extensions to convert
exts := []string{".png", ".jpg", ".jpeg", ".bmp", ".tiff"}
for _, ext := range exts {
if strings.HasSuffix(strings.ToLower(path), ext) {
return true
}
}
return false
}