145 lines
3.3 KiB
Go
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
|
|
}
|