Skip to content

Commit 6046d5a

Browse files
committed
send mention
1 parent 85b76f1 commit 6046d5a

File tree

8 files changed

+108
-9
lines changed

8 files changed

+108
-9
lines changed

pkg/connector/client.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func NewClient(userLogin *bridgev2.UserLogin, client *gchatmeow.Client) *GChatCl
3434
userLogin: userLogin,
3535
client: client,
3636
users: map[string]*proto.User{},
37-
msgConv: msgconv.NewMessageConverter(client),
37+
msgConv: msgconv.NewMessageConverter(userLogin.Bridge, client),
3838
}
3939
}
4040

pkg/gchatmeow/proto/extra.go

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package proto
2+
3+
type MetadataAssociatedValue = isAnnotation_Metadata

pkg/msgconv/from-matrix.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ func (mc *MessageConverter) ToGChat(
1313
ctx context.Context,
1414
content *event.MessageEventContent,
1515
) (string, []*proto.Annotation) {
16-
parser := &matrixfmt.HTMLParser{}
17-
body, annotations := matrixfmt.Parse(ctx, parser, content)
16+
body, annotations := matrixfmt.Parse(ctx, mc.matrixFmtParams, content)
1817
return body, annotations
1918
}

pkg/msgconv/gchatfmt/utils.go

+10
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,15 @@ func MakeAnnotation(start, length int32, format proto.FormatMetadata_FormatType)
1414
},
1515
},
1616
}
17+
}
18+
19+
func MakeAnnotationFromMetadata(typ proto.AnnotationType, start, length int32, metadata proto.MetadataAssociatedValue) *proto.Annotation {
20+
return &proto.Annotation{
21+
Type: typ,
22+
StartIndex: start,
23+
Length: length,
24+
ChipRenderType: proto.Annotation_DO_NOT_RENDER,
25+
Metadata: metadata,
26+
}
1727

1828
}

pkg/msgconv/matrixfmt/html.go

+18-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import (
44
"context"
55
"fmt"
66
"math"
7+
"slices"
78
"strconv"
89
"strings"
910

1011
"golang.org/x/net/html"
1112
"maunium.net/go/mautrix/event"
13+
"maunium.net/go/mautrix/id"
1214

1315
"go.mau.fi/mautrix-googlechat/pkg/gchatmeow"
1416
)
@@ -228,7 +230,7 @@ func (ctx Context) WithWhitespace() Context {
228230

229231
// HTMLParser is a somewhat customizable Matrix HTML parser.
230232
type HTMLParser struct {
231-
// GetUUIDFromMXID func(context.Context, id.UserID) uuid.UUID
233+
GetUIDFromMXID func(context.Context, id.UserID) string
232234
}
233235

234236
// TaggedString is a string that also contains a HTML tag.
@@ -345,6 +347,21 @@ func (parser *HTMLParser) linkToString(node *html.Node, ctx Context) *EntityStri
345347
if len(href) == 0 {
346348
return str
347349
}
350+
parsedMatrix, err := id.ParseMatrixURIOrMatrixToURL(href)
351+
if err == nil && parsedMatrix != nil && parsedMatrix.Sigil1 == '@' {
352+
mxid := parsedMatrix.UserID()
353+
if ctx.AllowedMentions != nil && !slices.Contains(ctx.AllowedMentions.UserIDs, mxid) {
354+
// Mention not allowed, use name as-is
355+
return str
356+
}
357+
u := parser.GetUIDFromMXID(ctx.Ctx, mxid)
358+
if u == "" {
359+
return str
360+
}
361+
return NewEntityString("@" + str.String.String()).Format(Mention{
362+
ID: u,
363+
})
364+
}
348365
if str.String.String() == href {
349366
return str
350367
}

pkg/msgconv/matrixfmt/tags.go

+30-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,30 @@ import (
99
type BodyRangeValue interface {
1010
String() string
1111
Format(message string) string
12-
Proto() proto.FormatMetadata_FormatType
12+
Proto() proto.MetadataAssociatedValue
13+
}
14+
15+
type Mention struct {
16+
ID string
17+
}
18+
19+
func (m Mention) String() string {
20+
return fmt.Sprintf("Mention{ID: (%s)}", m.ID)
21+
}
22+
23+
func (m Mention) Proto() proto.MetadataAssociatedValue {
24+
return &proto.Annotation_UserMentionMetadata{
25+
UserMentionMetadata: &proto.UserMentionMetadata{
26+
Type: proto.UserMentionMetadata_MENTION,
27+
Id: &proto.UserId{
28+
Id: m.ID,
29+
},
30+
},
31+
}
32+
}
33+
34+
func (m Mention) Format(message string) string {
35+
return message
1336
}
1437

1538
type Style int
@@ -27,8 +50,12 @@ const (
2750
StyleFontColor
2851
)
2952

30-
func (s Style) Proto() proto.FormatMetadata_FormatType {
31-
return proto.FormatMetadata_FormatType(s)
53+
func (s Style) Proto() proto.MetadataAssociatedValue {
54+
return &proto.Annotation_FormatMetadata{
55+
FormatMetadata: &proto.FormatMetadata{
56+
FormatType: proto.FormatMetadata_FormatType(s),
57+
},
58+
}
3259
}
3360

3461
func (s Style) String() string {

pkg/msgconv/matrixfmt/tree.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,13 @@ func (b BodyRange) TruncateEnd(maxEnd int) *BodyRange {
6363
}
6464

6565
func (b BodyRange) Proto() *proto.Annotation {
66-
return gchatfmt.MakeAnnotation(int32(b.Start), int32(b.Length), b.Value.Proto())
66+
metadata := b.Value.Proto()
67+
typ := proto.AnnotationType_FORMAT_DATA
68+
_, ok := metadata.(*proto.Annotation_UserMentionMetadata)
69+
if ok {
70+
typ = proto.AnnotationType_USER_MENTION
71+
}
72+
return gchatfmt.MakeAnnotationFromMetadata(typ, int32(b.Start), int32(b.Length), b.Value.Proto())
6773
}
6874

6975
// LinkedRangeTree is a linked tree of formatting entities.

pkg/msgconv/msgconv.go

+38-1
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,52 @@
11
package msgconv
22

33
import (
4+
"context"
5+
6+
"maunium.net/go/mautrix/bridgev2"
7+
"maunium.net/go/mautrix/id"
8+
49
"go.mau.fi/mautrix-googlechat/pkg/gchatmeow"
10+
"go.mau.fi/mautrix-googlechat/pkg/msgconv/matrixfmt"
11+
)
12+
13+
type contextKey int
14+
15+
const (
16+
contextKeyPortal contextKey = iota
17+
contextKeyClient
18+
contextKeyIntent
519
)
620

721
type MessageConverter struct {
822
client *gchatmeow.Client
23+
24+
matrixFmtParams *matrixfmt.HTMLParser
925
}
1026

11-
func NewMessageConverter(client *gchatmeow.Client) *MessageConverter {
27+
func NewMessageConverter(br *bridgev2.Bridge, client *gchatmeow.Client) *MessageConverter {
1228
return &MessageConverter{
1329
client: client,
30+
31+
matrixFmtParams: &matrixfmt.HTMLParser{
32+
GetUIDFromMXID: func(ctx context.Context, userID id.UserID) string {
33+
parsed, ok := br.Matrix.ParseGhostMXID(userID)
34+
if ok {
35+
return string(parsed)
36+
}
37+
user, _ := br.GetExistingUserByMXID(ctx, userID)
38+
if user != nil {
39+
preferredLogin, _, _ := getPortal(ctx).FindPreferredLogin(ctx, user, true)
40+
if preferredLogin != nil {
41+
return string(preferredLogin.ID)
42+
}
43+
}
44+
return ""
45+
},
46+
},
1447
}
1548
}
49+
50+
func getPortal(ctx context.Context) *bridgev2.Portal {
51+
return ctx.Value(contextKeyPortal).(*bridgev2.Portal)
52+
}

0 commit comments

Comments
 (0)