diff --git a/pkg/connector/client.go b/pkg/connector/client.go index 6ecb78dd..5fead172 100644 --- a/pkg/connector/client.go +++ b/pkg/connector/client.go @@ -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 diff --git a/pkg/connector/emojis/emojis.go b/pkg/connector/emojis/emojis.go index f7cc75d6..04dace8d 100644 --- a/pkg/connector/emojis/emojis.go +++ b/pkg/connector/emojis/emojis.go @@ -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 } diff --git a/pkg/connector/handletelegram.go b/pkg/connector/handletelegram.go index 1e7e06dc..685dd18c 100644 --- a/pkg/connector/handletelegram.go +++ b/pkg/connector/handletelegram.go @@ -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 } diff --git a/pkg/connector/matrixfmt/convert.go b/pkg/connector/matrixfmt/convert.go index 18f752c3..e1340a36 100644 --- a/pkg/connector/matrixfmt/convert.go +++ b/pkg/connector/matrixfmt/convert.go @@ -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") } diff --git a/pkg/connector/matrixfmt/html.go b/pkg/connector/matrixfmt/html.go index 360a0433..6a2c932f 100644 --- a/pkg/connector/matrixfmt/html.go +++ b/pkg/connector/matrixfmt/html.go @@ -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": diff --git a/pkg/connector/telegramfmt/html.go b/pkg/connector/telegramfmt/html.go index 7e342b8e..679df35b 100644 --- a/pkg/connector/telegramfmt/html.go +++ b/pkg/connector/telegramfmt/html.go @@ -63,7 +63,7 @@ func (s Style) Format(message string) string { return s.EmojiInfo.Emoji } else if s.EmojiInfo.EmojiURI != "" { return fmt.Sprintf( - `%s`, + `%s`, s.EmojiInfo.EmojiURI, message, message, ) }