fix(telegram): stop auto-linking @mentions to t.me profile URLs

LLM @mentions are not necessarily Telegram usernames. Auto-wrapping
them in <a href="https://t.me/..."> caused unwanted profile cards.
Keep placeholder protection for italic conversion, restore as plain text.
This commit is contained in:
viettranx committed 2026-04-02 10:55:41 +07:00
1 parent 1a2d5789d3
commit 9d74e39625
2 files changed
+56 -4

No files matched your search

+4 -4
View File
@@ -105,11 +105,11 @@ func markdownToTelegramHTML(text string) string {
// Strikethrough
text = regexp.MustCompile(`~~(.+?)~~`).ReplaceAllString(text, "<s>$1</s>")
// Restore @mentions as clickable Telegram links
// Restore @mentions as plain text (protected from italic conversion above).
// Do NOT wrap in <a href="https://t.me/..."> — LLM @mentions are not
// necessarily Telegram usernames and auto-linking shows unwanted profile cards.
for i, mention := range mentionPlaceholders {
username := strings.TrimPrefix(mention, "@")
linked := fmt.Sprintf(`<a href="https://t.me/%s">%s</a>`, username, mention)
text = strings.ReplaceAll(text, fmt.Sprintf("\x00MN%d\x00", i), linked)
text = strings.ReplaceAll(text, fmt.Sprintf("\x00MN%d\x00", i), mention)
}
// List items
+52
View File
@@ -62,6 +62,58 @@ func TestRenderTableAsCode_Vietnamese(t *testing.T) {
}
}
func TestMarkdownToTelegramHTML_Mentions(t *testing.T) {
tests := []struct {
name string
input string
want string // substring that MUST appear
deny string // substring that must NOT appear
}{
{
name: "mention stays plain text",
input: "Hello @viettran how are you?",
want: "@viettran",
deny: `href="https://t.me/`,
},
{
name: "mention not wrapped in link tag",
input: "cc @john please review",
want: "@john",
deny: "<a ",
},
{
name: "email not treated as mention",
input: "send to user@domain.com",
want: "user@domain.com",
deny: `href=`,
},
{
name: "mention survives italic conversion",
input: "_italic_ and @bot_name end",
want: "@bot_name",
deny: `<a `,
},
{
name: "multiple mentions plain text",
input: "@alice and @bob discussed",
want: "@alice",
deny: "t.me",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := markdownToTelegramHTML(tt.input)
if !strings.Contains(got, tt.want) {
t.Errorf("expected %q in output, got: %s", tt.want, got)
}
if tt.deny != "" && strings.Contains(got, tt.deny) {
t.Errorf("unexpected %q in output, got: %s", tt.deny, got)
}
})
}
}
func TestChunkHTML(t *testing.T) {
tests := []struct {
name string