From 9c8927bab007f9e709d39ca0f6b6c8765d14ac60 Mon Sep 17 00:00:00 2001 From: highesttt Date: Wed, 21 Jan 2026 13:19:57 -0600 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Add=20support=20for=20lo?= =?UTF-8?q?oping=20APNG=20stickers=20in=20message=20queue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/connector/client.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/pkg/connector/client.go b/pkg/connector/client.go index 5b2da25..69c5312 100644 --- a/pkg/connector/client.go +++ b/pkg/connector/client.go @@ -9,8 +9,10 @@ import ( "crypto/rand" "crypto/sha256" "encoding/base64" + "encoding/binary" "encoding/json" "fmt" + "hash/crc32" "image" _ "image/gif" "image/jpeg" @@ -1388,6 +1390,9 @@ func (lc *LineClient) queueIncomingMessage(msg *line.Message, opType int) { if err != nil { lc.UserLogin.Bridge.Log.Warn().Err(err).Str("stk_id", stkID).Msg("Failed to read sticker body") } else { + if strings.Contains(stkOpt, "A") { + stkData = forceAPNGLoop(stkData) + } mxc, file, err := intent.UploadMedia(ctx, portal.MXID, stkData, "sticker.png", "image/png") if err != nil { lc.UserLogin.Bridge.Log.Warn().Err(err).Msg("Failed to upload sticker to Matrix") @@ -2271,3 +2276,34 @@ func (lc *LineClient) GetAvatar(ctx context.Context, id networkid.AvatarID) ([]b defer resp.Body.Close() return io.ReadAll(resp.Body) } + +func forceAPNGLoop(data []byte) []byte { + if len(data) < 8 || string(data[:8]) != "\x89PNG\r\n\x1a\n" { + return data + } + + offset := 8 + for offset < len(data) { + if offset+8 > len(data) { + break + } + length := binary.BigEndian.Uint32(data[offset : offset+4]) + chunkType := string(data[offset+4 : offset+8]) + + if chunkType == "acTL" { + if length >= 8 && offset+8+8 <= len(data) { + binary.BigEndian.PutUint32(data[offset+8+4:offset+8+8], 0) + + crc := crc32.NewIEEE() + crc.Write(data[offset+4 : offset+8+int(length)]) + newCRC := crc.Sum32() + + binary.BigEndian.PutUint32(data[offset+8+int(length):offset+8+int(length)+4], newCRC) + } + break + } + + offset += 4 + 4 + int(length) + 4 + } + return data +}