Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions pkg/connector/handlers/sticker.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package handlers

import (
"bytes"
"context"
"encoding/binary"
"fmt"
"hash/crc32"
"image"
_ "image/png"
"io"
"strings"

Expand All @@ -14,7 +17,7 @@ import (
"github.com/beeper/line/pkg/line"
)

// ConvertSticker converts a LINE sticker message to a Matrix image or text fallback.
// ConvertSticker converts a LINE sticker message to a Matrix sticker or text fallback.
func (h *Handler) ConvertSticker(ctx context.Context, portal *bridgev2.Portal, intent bridgev2.MatrixAPI, data line.Message, relatesTo *event.RelatesTo) (*bridgev2.ConvertedMessage, error) {
stkID := data.ContentMetadata["STKID"]
stkTxt := data.ContentMetadata["STKTXT"]
Expand Down Expand Up @@ -77,23 +80,28 @@ func (h *Handler) ConvertSticker(ctx context.Context, portal *bridgev2.Portal, i

bodyName := "sticker." + ext

info := &event.FileInfo{
MimeType: mimeType,
Size: len(stkData),
}
if cfg, _, err := image.DecodeConfig(bytes.NewReader(stkData)); err == nil {
info.Width = cfg.Width * 2 / 3
info.Height = cfg.Height * 2 / 3
}

mxc, file, err := intent.UploadMedia(ctx, portal.MXID, stkData, bodyName, mimeType)
if err != nil {
h.Log.Warn().Err(err).Msg("Failed to upload sticker to Matrix")
} else {
return &bridgev2.ConvertedMessage{
Parts: []*bridgev2.ConvertedMessagePart{
{
Type: event.EventMessage,
Type: event.EventSticker,
Content: &event.MessageEventContent{
MsgType: event.MsgImage,
Body: bodyName,
URL: mxc,
File: file,
Info: &event.FileInfo{
MimeType: mimeType,
Size: len(stkData),
},
Body: bodyName,
URL: mxc,
File: file,
Info: info,
RelatesTo: relatesTo,
},
},
Expand Down
4 changes: 3 additions & 1 deletion pkg/connector/send_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,9 @@ func (lc *LineClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2.Mat
// Matrix clients often send media as MsgFile (e.g. drag-and-drop), which would otherwise
// be sent as ContentFile (14) instead of the appropriate media type on LINE.
effectiveMsgType := msg.Content.MsgType
if effectiveMsgType == event.MsgFile && msg.Content.Info != nil {
if effectiveMsgType == event.CapMsgSticker {
effectiveMsgType = event.MsgImage
} else if effectiveMsgType == event.MsgFile && msg.Content.Info != nil {
mime := msg.Content.Info.MimeType
if strings.HasPrefix(mime, "audio/") {
effectiveMsgType = event.MsgAudio
Expand Down
12 changes: 11 additions & 1 deletion pkg/connector/userinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (lc *LineClient) HandleMatrixReadReceipt(ctx context.Context, read *bridgev

func (lc *LineClient) GetCapabilities(ctx context.Context, portal *bridgev2.Portal) *event.RoomFeatures {
caps := &event.RoomFeatures{
ID: "dev.highest.matrix.line.capabilities.2026_10_14",
ID: "dev.highest.matrix.line.capabilities.2026_10_21",
MaxTextLength: 5000,
Reply: event.CapLevelFullySupported,
Reaction: event.CapLevelPartialSupport,
Expand Down Expand Up @@ -81,6 +81,16 @@ func (lc *LineClient) GetCapabilities(ctx context.Context, portal *bridgev2.Port
"image/jxl": event.CapLevelFullySupported,
},
},
event.CapMsgSticker: {
Caption: event.CapLevelRejected,
MaxSize: handlers.BeeperMaxFileSize,
MimeTypes: map[string]event.CapabilitySupportLevel{
"image/png": event.CapLevelFullySupported,
"image/gif": event.CapLevelFullySupported,
"image/webp": event.CapLevelFullySupported,
"image/jpeg": event.CapLevelFullySupported,
},
},
event.MsgFile: {
Caption: event.CapLevelRejected,
MaxSize: handlers.BeeperMaxFileSize,
Expand Down
Loading