matrixfmt: add support for sending pre-bridged custom emojis in text

This commit is contained in:
Tulir Asokan
2026-03-29 14:25:23 +03:00
parent 5d05d7ab05
commit b6aff6784f
6 changed files with 31 additions and 5 deletions
+1
View File
@@ -329,6 +329,7 @@ func NewTelegramClient(ctx context.Context, tc *TelegramConnector, login *bridge
},
}
client.matrixParser = &matrixfmt.HTMLParser{
Store: tc.Store,
GetGhostDetails: func(ctx context.Context, ui id.UserID) (networkid.UserID, string, int64, bool) {
if userID, ok := tc.Bridge.Matrix.ParseGhostMXID(ui); !ok {
return "", "", 0, false
+3 -2
View File
@@ -69,6 +69,7 @@ func GetEmojiDocumentID(emoji string) (int64, bool) {
// EmojiInfo contains information about an emoji.
type EmojiInfo struct {
Emoji string
EmojiURI id.ContentURIString
Emoji string
DocumentID int64
EmojiURI id.ContentURIString
}
+2 -2
View File
@@ -1264,7 +1264,7 @@ func (t *TelegramClient) transferEmojisToMatrix(ctx context.Context, customEmoji
if mxcURI, err := t.main.Bridge.Matrix.GenerateContentURI(ctx, mediaID); err != nil {
return nil, err
} else {
result[ids.MakeEmojiIDFromDocumentID(emojiID)] = emojis.EmojiInfo{EmojiURI: mxcURI}
result[ids.MakeEmojiIDFromDocumentID(emojiID)] = emojis.EmojiInfo{EmojiURI: mxcURI, DocumentID: emojiID}
}
}
@@ -1284,7 +1284,7 @@ func (t *TelegramClient) transferEmojisToMatrix(ctx context.Context, customEmoji
if err != nil {
return nil, err
}
result[ids.MakeEmojiIDFromDocumentID(customEmojiDocument.GetID())] = emojis.EmojiInfo{EmojiURI: mxcURI}
result[ids.MakeEmojiIDFromDocumentID(customEmojiDocument.GetID())] = emojis.EmojiInfo{EmojiURI: mxcURI, DocumentID: customEmojiDocument.GetID()}
}
return
}
+2
View File
@@ -77,6 +77,8 @@ func toTelegramEntity(br telegramfmt.BodyRange) tg.MessageEntityClass {
return &tg.MessageEntitySpoiler{Offset: br.Start, Length: br.Length}
case telegramfmt.StyleBankCard:
return &tg.MessageEntityBankCard{Offset: br.Start, Length: br.Length}
case telegramfmt.StyleCustomEmoji:
return &tg.MessageEntityCustomEmoji{Offset: br.Start, Length: br.Length, DocumentID: val.EmojiInfo.DocumentID}
default:
panic("unsupported style type")
}
+22
View File
@@ -29,6 +29,8 @@ import (
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
"go.mau.fi/mautrix-telegram/pkg/connector/emojis"
"go.mau.fi/mautrix-telegram/pkg/connector/store"
"go.mau.fi/mautrix-telegram/pkg/connector/telegramfmt"
)
@@ -250,6 +252,7 @@ func (ctx Context) WithIncrementedListDepth() Context {
// HTMLParser is a somewhat customizable Matrix HTML parser.
type HTMLParser struct {
GetGhostDetails func(context.Context, id.UserID) (networkid.UserID, string, int64, bool)
Store *store.Container
}
// TaggedString is a string that also contains a HTML tag.
@@ -395,6 +398,23 @@ func (parser *HTMLParser) linkToString(node *html.Node, ctx Context) *EntityStri
}
}
func (parser *HTMLParser) imgToString(node *html.Node, ctx Context) *EntityString {
src := parser.getAttribute(node, "src")
alt := parser.getAttribute(node, "alt")
_, isEmoji := parser.maybeGetAttribute(node, "data-mx-emoticon")
if !isEmoji {
return NewEntityString(alt)
}
if file, _ := parser.Store.TelegramFile.GetByMXC(ctx.Ctx, src); file != nil {
if documentID, err := strconv.ParseInt(string(file.LocationID), 10, 64); err == nil {
// Hardcode to a sparkle emoji because telegram requires the custom emoji fallback to be an emoji,
// but we don't know the actual emoji that should be used.
return NewEntityString("\u2728\ufe0f").Format(telegramfmt.Style{Type: telegramfmt.StyleCustomEmoji, EmojiInfo: emojis.EmojiInfo{DocumentID: documentID}})
}
}
return NewEntityString(alt)
}
func (parser *HTMLParser) tagToString(node *html.Node, ctx Context) *EntityString {
ctx = ctx.WithTag(node.Data)
switch node.Data {
@@ -416,6 +436,8 @@ func (parser *HTMLParser) tagToString(node *html.Node, ctx Context) *EntityStrin
return parser.linkToString(node, ctx)
case "p":
return parser.nodeToTagAwareString(node.FirstChild, ctx)
case "img":
return parser.imgToString(node, ctx)
case "hr":
return NewEntityString("---")
case "pre":
+1 -1
View File
@@ -63,7 +63,7 @@ func (s Style) Format(message string) string {
return s.EmojiInfo.Emoji
} else if s.EmojiInfo.EmojiURI != "" {
return fmt.Sprintf(
`<img data-mx-emoticon data-mau-animated-emoji src="%s" height="32" width="32" alt="%s" title="%s"/>`,
`<img data-mx-emoticon src="%s" height="32" width="32" alt="%s" title="%s"/>`,
s.EmojiInfo.EmojiURI, message, message,
)
}