matrixfmt,telegramfmt: correctly bridge mentions of other logged-in users

This commit is contained in:
Tulir Asokan
2026-04-02 23:56:08 +03:00
parent 693ced7dea
commit 835afb0100
5 changed files with 32 additions and 12 deletions
+17 -4
View File
@@ -236,6 +236,8 @@ func NewTelegramClient(ctx context.Context, tc *TelegramConnector, login *bridge
// FIXME this should look for user logins by ID, not hardcode the current user // FIXME this should look for user logins by ID, not hardcode the current user
if id == client.telegramUserID { if id == client.telegramUserID {
userInfo.MXID = client.userLogin.UserMXID userInfo.MXID = client.userLogin.UserMXID
} else if login := tc.Bridge.GetCachedUserLoginByID(ids.MakeUserLoginID(id)); login != nil {
userInfo.MXID = login.UserMXID
} }
return userInfo, nil return userInfo, nil
}, },
@@ -250,6 +252,8 @@ func NewTelegramClient(ctx context.Context, tc *TelegramConnector, login *bridge
userInfo := telegramfmt.UserInfo{MXID: ghost.Intent.GetMXID(), Name: ghost.Name} userInfo := telegramfmt.UserInfo{MXID: ghost.Intent.GetMXID(), Name: ghost.Name}
if ghost.ID == client.userID { if ghost.ID == client.userID {
userInfo.MXID = client.userLogin.UserMXID userInfo.MXID = client.userLogin.UserMXID
} else if login := tc.Bridge.GetCachedUserLoginByID(ids.MakeUserLoginID(userID)); login != nil {
userInfo.MXID = login.UserMXID
} }
return userInfo, nil return userInfo, nil
} }
@@ -334,10 +338,19 @@ func NewTelegramClient(ctx context.Context, tc *TelegramConnector, login *bridge
} }
client.matrixParser = &matrixfmt.HTMLParser{ client.matrixParser = &matrixfmt.HTMLParser{
Store: tc.Store, Store: tc.Store,
GetGhostDetails: func(ctx context.Context, ui id.UserID) (networkid.UserID, string, int64, bool) { GetGhostDetails: func(ctx context.Context, portal *bridgev2.Portal, ui id.UserID) (networkid.UserID, string, int64, bool) {
if userID, ok := tc.Bridge.Matrix.ParseGhostMXID(ui); !ok { userID, ok := tc.Bridge.Matrix.ParseGhostMXID(ui)
return "", "", 0, false if !ok {
} else if peerType, telegramUserID, err := ids.ParseUserID(userID); err != nil { user, err := tc.Bridge.GetExistingUserByMXID(ctx, ui)
if err != nil {
return "", "", 0, false
} else if login, _, _ := portal.FindPreferredLogin(ctx, user, false); login != nil {
userID = ids.UserLoginIDToUserID(login.ID)
} else {
return "", "", 0, false
}
}
if peerType, telegramUserID, err := ids.ParseUserID(userID); err != nil {
return "", "", 0, false return "", "", 0, false
} else if accessHash, err := client.ScopedStore.GetAccessHash(ctx, peerType, telegramUserID); err != nil || accessHash == 0 { } else if accessHash, err := client.ScopedStore.GetAccessHash(ctx, peerType, telegramUserID); err != nil || accessHash == 0 {
return "", "", 0, false return "", "", 0, false
+2 -2
View File
@@ -418,7 +418,7 @@ func (t *TelegramClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2.
noWebpage := msg.Content.BeeperLinkPreviews != nil && len(msg.Content.BeeperLinkPreviews) == 0 noWebpage := msg.Content.BeeperLinkPreviews != nil && len(msg.Content.BeeperLinkPreviews) == 0
message, entities := matrixfmt.Parse(ctx, t.matrixParser, msg.Content) message, entities := matrixfmt.Parse(ctx, t.matrixParser, msg.Content, msg.Portal)
var replyTo tg.InputReplyToClass var replyTo tg.InputReplyToClass
if msg.ReplyTo != nil { if msg.ReplyTo != nil {
@@ -611,7 +611,7 @@ func (t *TelegramClient) HandleMatrixEdit(ctx context.Context, msg *bridgev2.Mat
return err return err
} }
message, entities := matrixfmt.Parse(ctx, t.matrixParser, msg.Content) message, entities := matrixfmt.Parse(ctx, t.matrixParser, msg.Content, msg.Portal)
var newContentURI id.ContentURIString var newContentURI id.ContentURIString
req := tg.MessagesEditMessageRequest{ req := tg.MessagesEditMessageRequest{
+4
View File
@@ -56,6 +56,10 @@ func ParseUserLoginID(userID networkid.UserLoginID) (int64, error) {
return strconv.ParseInt(string(userID), 10, 64) return strconv.ParseInt(string(userID), 10, 64)
} }
func UserLoginIDToUserID(userLoginID networkid.UserLoginID) networkid.UserID {
return networkid.UserID(userLoginID)
}
func MakeUserLoginID(userID int64) networkid.UserLoginID { func MakeUserLoginID(userID int64) networkid.UserLoginID {
if userID == 0 { if userID == 0 {
return "" return ""
+3 -2
View File
@@ -20,6 +20,7 @@ import (
"context" "context"
"fmt" "fmt"
"maunium.net/go/mautrix/bridgev2"
"maunium.net/go/mautrix/event" "maunium.net/go/mautrix/event"
"go.mau.fi/mautrix-telegram/pkg/connector/ids" "go.mau.fi/mautrix-telegram/pkg/connector/ids"
@@ -87,7 +88,7 @@ func toTelegramEntity(br telegramfmt.BodyRange) tg.MessageEntityClass {
} }
} }
func Parse(ctx context.Context, parser *HTMLParser, content *event.MessageEventContent) (string, []tg.MessageEntityClass) { func Parse(ctx context.Context, parser *HTMLParser, content *event.MessageEventContent, portal *bridgev2.Portal) (string, []tg.MessageEntityClass) {
if content.MsgType.IsMedia() && (content.FileName == "" || content.FileName == content.Body) { if content.MsgType.IsMedia() && (content.FileName == "" || content.FileName == content.Body) {
// The body is the filename. // The body is the filename.
return "", nil return "", nil
@@ -96,7 +97,7 @@ func Parse(ctx context.Context, parser *HTMLParser, content *event.MessageEventC
if content.Format != event.FormatHTML { if content.Format != event.FormatHTML {
return content.Body, nil return content.Body, nil
} }
parseCtx := NewContext(ctx) parseCtx := NewContext(ctx, portal)
parseCtx.AllowedMentions = content.Mentions parseCtx.AllowedMentions = content.Mentions
parsed := parser.Parse(content.FormattedBody, parseCtx) parsed := parser.Parse(content.FormattedBody, parseCtx)
if parsed == nil { if parsed == nil {
+6 -4
View File
@@ -25,6 +25,7 @@ import (
"strings" "strings"
"golang.org/x/net/html" "golang.org/x/net/html"
"maunium.net/go/mautrix/bridgev2"
"maunium.net/go/mautrix/bridgev2/networkid" "maunium.net/go/mautrix/bridgev2/networkid"
"maunium.net/go/mautrix/event" "maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id" "maunium.net/go/mautrix/id"
@@ -221,16 +222,18 @@ func (ts TagStack) Has(tag string) bool {
type Context struct { type Context struct {
Ctx context.Context Ctx context.Context
Portal *bridgev2.Portal
AllowedMentions *event.Mentions AllowedMentions *event.Mentions
TagStack TagStack TagStack TagStack
PreserveWhitespace bool PreserveWhitespace bool
ListDepth int ListDepth int
} }
func NewContext(ctx context.Context) Context { func NewContext(ctx context.Context, portal *bridgev2.Portal) Context {
return Context{ return Context{
Ctx: ctx, Ctx: ctx,
TagStack: make(TagStack, 0, 4), TagStack: make(TagStack, 0, 4),
Portal: portal,
} }
} }
@@ -251,7 +254,7 @@ func (ctx Context) WithIncrementedListDepth() Context {
// HTMLParser is a somewhat customizable Matrix HTML parser. // HTMLParser is a somewhat customizable Matrix HTML parser.
type HTMLParser struct { type HTMLParser struct {
GetGhostDetails func(context.Context, id.UserID) (networkid.UserID, string, int64, bool) GetGhostDetails func(context.Context, *bridgev2.Portal, id.UserID) (networkid.UserID, string, int64, bool)
Store *store.Container Store *store.Container
} }
@@ -381,8 +384,7 @@ func (parser *HTMLParser) linkToString(node *html.Node, ctx Context) *EntityStri
// Mention not allowed, use name as-is // Mention not allowed, use name as-is
return str return str
} }
// FIXME this or GetGhostDetails needs to support non-ghost users too userID, username, accessHash, ok := parser.GetGhostDetails(ctx.Ctx, ctx.Portal, mxid)
userID, username, accessHash, ok := parser.GetGhostDetails(ctx.Ctx, mxid)
if !ok { if !ok {
return str return str
} else if username == "" { } else if username == "" {