From 5bf746156688456c1594a7a87c7cf83c324af922 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Tue, 3 Mar 2026 18:06:50 +0200 Subject: [PATCH] handlematrix: convert webp images to jpeg --- go.mod | 1 + go.sum | 2 ++ pkg/connector/capabilities.go | 1 + pkg/connector/handlematrix.go | 38 ++++++++++++++++++++++++++++------- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 499aa252..59837779 100644 --- a/go.mod +++ b/go.mod @@ -37,6 +37,7 @@ require ( go.uber.org/zap v1.27.1 golang.org/x/crypto v0.48.0 golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a + golang.org/x/image v0.36.0 golang.org/x/net v0.50.0 golang.org/x/sync v0.19.0 golang.org/x/tools v0.42.0 diff --git a/go.sum b/go.sum index fe3a3331..c5b3cf2d 100644 --- a/go.sum +++ b/go.sum @@ -156,6 +156,8 @@ golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a h1:ovFr6Z0MNmU7nH8VaX5xqw+05ST2uO1exVfZPVqRC5o= golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA= +golang.org/x/image v0.36.0 h1:Iknbfm1afbgtwPTmHnS2gTM/6PPZfH+z2EFuOkSbqwc= +golang.org/x/image v0.36.0/go.mod h1:YsWD2TyyGKiIX1kZlu9QfKIsQ4nAAK9bdgdrIsE7xy4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= diff --git a/pkg/connector/capabilities.go b/pkg/connector/capabilities.go index 7a1ec175..52f623c4 100644 --- a/pkg/connector/capabilities.go +++ b/pkg/connector/capabilities.go @@ -96,6 +96,7 @@ var fileCaps = event.FileFeatureMap{ event.MsgImage: { MimeTypes: map[string]event.CapabilitySupportLevel{ "image/jpeg": event.CapLevelFullySupported, + "image/webp": event.CapLevelPartialSupport, "image/png": event.CapLevelPartialSupport, "image/gif": event.CapLevelPartialSupport, }, diff --git a/pkg/connector/handlematrix.go b/pkg/connector/handlematrix.go index f5bb7094..9ab229ce 100644 --- a/pkg/connector/handlematrix.go +++ b/pkg/connector/handlematrix.go @@ -23,8 +23,10 @@ import ( "errors" "fmt" "image" + "image/jpeg" _ "image/jpeg" _ "image/png" + "io" "math" "math/rand/v2" "os" @@ -39,6 +41,7 @@ import ( "go.mau.fi/util/variationselector" "go.mau.fi/webp" "golang.org/x/exp/maps" + _ "golang.org/x/image/webp" "maunium.net/go/mautrix/bridgev2" "maunium.net/go/mautrix/bridgev2/database" "maunium.net/go/mautrix/bridgev2/networkid" @@ -116,17 +119,17 @@ func (t *TelegramClient) transferMediaToTelegram(ctx context.Context, content *e err := t.main.Bridge.Bot.DownloadMediaToFile(ctx, content.URL, content.File, false, func(f *os.File) (err error) { uploadFilename := f.Name() if sticker && content.Info != nil && (content.Info.MimeType == "image/png" || content.Info.MimeType == "image/jpeg") { - tempFile, err := os.CreateTemp("", "telegram-sticker-*") + tempFile, err := os.CreateTemp("", "telegram-sticker-*.webp") if err != nil { return err } defer func() { - tempFile.Close() - os.Remove(tempFile.Name()) + _ = tempFile.Close() + _ = os.Remove(tempFile.Name()) }() - if image, _, err := image.Decode(f); err != nil { + if img, _, err := image.Decode(f); err != nil { return fmt.Errorf("failed to decode sticker image: %w", err) - } else if err := webp.Encode(tempFile, image, nil); err != nil { + } else if err := webp.Encode(tempFile, img, nil); err != nil { return fmt.Errorf("failed to encode sticker webp image: %w", err) } uploadFilename = tempFile.Name() @@ -158,9 +161,30 @@ func (t *TelegramClient) transferMediaToTelegram(ctx context.Context, content *e aspectRatio > 20 || cfg.Height+cfg.Width > 10000 } + if !forceDocument && !sticker && content.MsgType == event.MsgImage { + _, err = f.Seek(0, io.SeekStart) + if err != nil { + return err + } + tempFile, err := os.CreateTemp("", "telegram-nonsticker-*.jpeg") + if err != nil { + return err + } + defer func() { + _ = tempFile.Close() + _ = os.Remove(tempFile.Name()) + }() + if img, _, err := image.Decode(f); err != nil { + return fmt.Errorf("failed to decode non-sticker webp image: %w", err) + } else if err := jpeg.Encode(tempFile, img, nil); err != nil { + return fmt.Errorf("failed to encode non-sticker jpeg image: %w", err) + } + uploadFilename = tempFile.Name() + filename += ".jpeg" + content.Info.MimeType = "image/jpeg" + } - uploader := uploader.NewUploader(t.client.API()) - upload, err = uploader.FromPath(ctx, uploadFilename, filename) + upload, err = uploader.NewUploader(t.client.API()).FromPath(ctx, uploadFilename, filename) return }) if err != nil {