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 }