Skip to content

Commit

Permalink
send rich text
Browse files Browse the repository at this point in the history
  • Loading branch information
rnons committed Dec 23, 2024
1 parent 84129f4 commit 85b76f1
Show file tree
Hide file tree
Showing 10 changed files with 735 additions and 42 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/rs/zerolog v1.33.0
github.com/stretchr/testify v1.9.0
go.mau.fi/util v0.8.2
golang.org/x/net v0.31.0
google.golang.org/protobuf v1.35.2
maunium.net/go/mautrix v0.22.1-0.20241126202918-4b970e0ea7e6
)
Expand All @@ -34,7 +35,6 @@ require (
go.mau.fi/zeroconfig v0.1.3 // indirect
golang.org/x/crypto v0.29.0 // indirect
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
golang.org/x/net v0.31.0 // indirect
golang.org/x/sync v0.9.0 // indirect
golang.org/x/sys v0.27.0 // indirect
golang.org/x/text v0.20.0 // indirect
Expand Down
42 changes: 22 additions & 20 deletions pkg/connector/handlematrix.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ func (c *GChatClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2.Mat
}

var annotations []*proto.Annotation
var messageInfo *proto.MessageInfo
messageInfo := &proto.MessageInfo{
AcceptFormatAnnotations: true,
}

if msg.Content.MsgType.IsMedia() {
data, err := c.userLogin.Bridge.Bot.DownloadMedia(ctx, msg.Content.URL, msg.Content.File)
Expand Down Expand Up @@ -68,35 +70,35 @@ func (c *GChatClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2.Mat
if msg.ThreadRoot != nil {
topicId = string(msg.ThreadRoot.ID)
}
messageInfo = &proto.MessageInfo{
AcceptFormatAnnotations: true,
ReplyTo: &proto.SendReplyTarget{
Id: &proto.MessageId{
ParentId: &proto.MessageParentId{
Parent: &proto.MessageParentId_TopicId{
TopicId: &proto.TopicId{
GroupId: groupId,
TopicId: topicId,
},
messageInfo.ReplyTo = &proto.SendReplyTarget{
Id: &proto.MessageId{
ParentId: &proto.MessageParentId{
Parent: &proto.MessageParentId_TopicId{
TopicId: &proto.TopicId{
GroupId: groupId,
TopicId: topicId,
},
},
MessageId: replyToId,
},
CreateTime: msg.ReplyTo.Timestamp.UnixMicro(),
MessageId: replyToId,
},
CreateTime: msg.ReplyTo.Timestamp.UnixMicro(),
}
}

var msgID string
var timestamp int64

textBody := msg.Content.Body
text, entities := c.msgConv.ToGChat(ctx, msg.Content)

if entities != nil {
textBody = text
annotations = entities
}

if msg.ThreadRoot != nil {
threadId := string(msg.ThreadRoot.ID)
if messageInfo == nil {
messageInfo = &proto.MessageInfo{
AcceptFormatAnnotations: true,
}
}
req := &proto.CreateMessageRequest{
ParentId: &proto.MessageParentId{
Parent: &proto.MessageParentId_TopicId{
Expand All @@ -107,7 +109,7 @@ func (c *GChatClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2.Mat
},
},
LocalId: string(msg.Event.ID),
TextBody: msg.Content.Body,
TextBody: textBody,
Annotations: annotations,
MessageInfo: messageInfo,
}
Expand All @@ -120,7 +122,7 @@ func (c *GChatClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2.Mat
} else {
req := &proto.CreateTopicRequest{
GroupId: groupId,
TextBody: msg.Content.Body,
TextBody: textBody,
Annotations: annotations,
MessageInfo: messageInfo,
}
Expand Down
19 changes: 19 additions & 0 deletions pkg/msgconv/from-matrix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package msgconv

import (
"context"

"maunium.net/go/mautrix/event"

"go.mau.fi/mautrix-googlechat/pkg/gchatmeow/proto"
"go.mau.fi/mautrix-googlechat/pkg/msgconv/matrixfmt"
)

func (mc *MessageConverter) ToGChat(
ctx context.Context,
content *event.MessageEventContent,
) (string, []*proto.Annotation) {
parser := &matrixfmt.HTMLParser{}
body, annotations := matrixfmt.Parse(ctx, parser, content)
return body, annotations
}
26 changes: 5 additions & 21 deletions pkg/msgconv/gchatfmt/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,7 @@ import (
"go.mau.fi/mautrix-googlechat/pkg/msgconv/gchatfmt"
)

func makeAnnotation(start, length int32, format proto.FormatMetadata_FormatType) *proto.Annotation {
return &proto.Annotation{
Type: proto.AnnotationType_FORMAT_DATA,
StartIndex: start,
Length: length,
ChipRenderType: proto.Annotation_DO_NOT_RENDER,
Metadata: &proto.Annotation_FormatMetadata{
FormatMetadata: &proto.FormatMetadata{
FormatType: format,
},
},
}
}

func TestParse(t *testing.T) {
assert.Equal(t, 1, 1)

tests := []struct {
name string
ins string
Expand All @@ -43,10 +27,10 @@ func TestParse(t *testing.T) {
name: "bold italic strike underline",
ins: "a b i s u z",
ine: []*proto.Annotation{
makeAnnotation(2, 1, proto.FormatMetadata_BOLD),
makeAnnotation(4, 1, proto.FormatMetadata_ITALIC),
makeAnnotation(6, 1, proto.FormatMetadata_STRIKE),
makeAnnotation(8, 1, proto.FormatMetadata_UNDERLINE),
gchatfmt.MakeAnnotation(2, 1, proto.FormatMetadata_BOLD),
gchatfmt.MakeAnnotation(4, 1, proto.FormatMetadata_ITALIC),
gchatfmt.MakeAnnotation(6, 1, proto.FormatMetadata_STRIKE),
gchatfmt.MakeAnnotation(8, 1, proto.FormatMetadata_UNDERLINE),
},
body: "a b i s u z",
html: "a <strong>b</strong> <em>i</em> <del>s</del> <u>u</u> z",
Expand All @@ -55,7 +39,7 @@ func TestParse(t *testing.T) {
name: "emoji",
ins: "🎆 a b z",
ine: []*proto.Annotation{
makeAnnotation(5, 1, proto.FormatMetadata_BOLD),
gchatfmt.MakeAnnotation(5, 1, proto.FormatMetadata_BOLD),
},
body: "🎆 a b z",
html: "🎆 a <strong>b</strong> z",
Expand Down
18 changes: 18 additions & 0 deletions pkg/msgconv/gchatfmt/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package gchatfmt

import "go.mau.fi/mautrix-googlechat/pkg/gchatmeow/proto"

func MakeAnnotation(start, length int32, format proto.FormatMetadata_FormatType) *proto.Annotation {
return &proto.Annotation{
Type: proto.AnnotationType_FORMAT_DATA,
StartIndex: start,
Length: length,
ChipRenderType: proto.Annotation_DO_NOT_RENDER,
Metadata: &proto.Annotation_FormatMetadata{
FormatMetadata: &proto.FormatMetadata{
FormatType: format,
},
},
}

}
29 changes: 29 additions & 0 deletions pkg/msgconv/matrixfmt/convert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package matrixfmt

import (
"context"

"maunium.net/go/mautrix/event"

"go.mau.fi/mautrix-googlechat/pkg/gchatmeow/proto"
)

func Parse(ctx context.Context, parser *HTMLParser, content *event.MessageEventContent) (string, []*proto.Annotation) {
if content.Format != event.FormatHTML {
return content.Body, nil
}
parseCtx := NewContext(ctx)
parseCtx.AllowedMentions = content.Mentions
parsed := parser.Parse(content.FormattedBody, parseCtx)
if parsed == nil {
return "", nil
}
var bodyRanges []*proto.Annotation
if len(parsed.Entities) > 0 {
bodyRanges = make([]*proto.Annotation, len(parsed.Entities))
for i, ent := range parsed.Entities {
bodyRanges[i] = ent.Proto()
}
}
return parsed.String.String(), bodyRanges
}
46 changes: 46 additions & 0 deletions pkg/msgconv/matrixfmt/convert_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package matrixfmt_test

import (
"context"
"fmt"
"testing"

"github.com/stretchr/testify/assert"
"maunium.net/go/mautrix/event"

"go.mau.fi/mautrix-googlechat/pkg/gchatmeow/proto"
"go.mau.fi/mautrix-googlechat/pkg/msgconv/gchatfmt"
"go.mau.fi/mautrix-googlechat/pkg/msgconv/matrixfmt"
)

func TestParse(t *testing.T) {
tests := []struct {
name string
in string
out string
ent []*proto.Annotation
}{
{name: "Plain", in: "Hello, World!", out: "Hello, World!"},
{name: "Bold", in: "a <strong>b</strong> c", out: "a b c",
ent: []*proto.Annotation{
gchatfmt.MakeAnnotation(2, 1, proto.FormatMetadata_BOLD),
},
},
}

parser := &matrixfmt.HTMLParser{}
matrixfmt.DebugLog = func(format string, args ...any) {
fmt.Printf(format, args...)
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
parsed, entities := matrixfmt.Parse(context.TODO(), parser, &event.MessageEventContent{
Format: event.FormatHTML,
FormattedBody: test.in,
})
assert.Equal(t, test.out, parsed)
assert.Equal(t, test.ent, entities)
})
}
}
Loading

0 comments on commit 85b76f1

Please sign in to comment.