From 02da29f2da8941e761b9ba34167da40353578407 Mon Sep 17 00:00:00 2001 From: KShot Date: Thu, 8 Oct 2026 04:16:17 -0500 Subject: [PATCH] fix(webhook): keep line breaks in Telegram rich messages (#39650) Restore the old layout by converting line breaks (`\n`, `\r\n`, `\r`) to `
` in `createTelegramPayloadHTML`, after sanitizing, covering every Telegram payload type at once. Fixes https://github.com/go-gitea/gitea/issues/39649 --- services/webhook/telegram.go | 5 ++++- services/webhook/telegram_test.go | 30 +++++++++++++----------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/services/webhook/telegram.go b/services/webhook/telegram.go index 4f1d98407da..d661786d7ee 100644 --- a/services/webhook/telegram.go +++ b/services/webhook/telegram.go @@ -201,9 +201,12 @@ func (telegramConvertor) WorkflowJob(p *api.WorkflowJobPayload) (TelegramPayload func createTelegramPayloadHTML(msgHTML string) TelegramPayload { // https://core.telegram.org/bots/api#formatting-options + sanitized := strings.TrimSpace(string(markup.Sanitize(msgHTML))) + // Rich messages collapse bare newlines like HTML, so keep line breaks as
. + sanitized = strings.NewReplacer("\r\n", "
", "\r", "
", "\n", "
").Replace(sanitized) return TelegramPayload{ RichMessage: InputRichMessage{ - HTML: strings.TrimSpace(string(markup.Sanitize(msgHTML))), + HTML: sanitized, }, } } diff --git a/services/webhook/telegram_test.go b/services/webhook/telegram_test.go index 3e615af8140..64c3f70e2f4 100644 --- a/services/webhook/telegram_test.go +++ b/services/webhook/telegram_test.go @@ -27,6 +27,12 @@ func TestTelegramPayload(t *testing.T) { }, p) }) + t.Run("Line breaks are kept in rich messages", func(t *testing.T) { + // Rich messages collapse bare newlines, so they must become
. + p := createTelegramPayloadHTML("first line\r\nsecond line\nthird line") + assert.Equal(t, "first line
second line
third line", p.RichMessage.HTML) + }) + t.Run("Create", func(t *testing.T) { p := createTestPayload() @@ -60,9 +66,7 @@ func TestTelegramPayload(t *testing.T) { pl, err := tc.Push(p) require.NoError(t, err) - assert.Equal(t, `[test/repo:test] 2 new commits -[2020558] commit message - user1 -[2020558] commit message - user1`, pl.RichMessage.HTML) + assert.Equal(t, `[test/repo:test] 2 new commits
[2020558] commit message - user1
[2020558] commit message - user1`, pl.RichMessage.HTML) }) t.Run("Issue", func(t *testing.T) { @@ -72,9 +76,7 @@ func TestTelegramPayload(t *testing.T) { pl, err := tc.Issue(p) require.NoError(t, err) - assert.Equal(t, `[test/repo] Issue opened: #2 crash by user1 - -issue body`, pl.RichMessage.HTML) + assert.Equal(t, `[test/repo] Issue opened: #2 crash by user1

issue body`, pl.RichMessage.HTML) p.Action = api.HookIssueClosed pl, err = tc.Issue(p) @@ -89,8 +91,7 @@ issue body`, pl.RichMessage.HTML) pl, err := tc.IssueComment(p) require.NoError(t, err) - assert.Equal(t, `[test/repo] New comment on issue #2 crash by user1 -more info needed`, pl.RichMessage.HTML) + assert.Equal(t, `[test/repo] New comment on issue #2 crash by user1
more info needed`, pl.RichMessage.HTML) }) t.Run("PullRequest", func(t *testing.T) { @@ -99,8 +100,7 @@ more info needed`, pl.RichMessage.HTML) pl, err := tc.PullRequest(p) require.NoError(t, err) - assert.Equal(t, `[test/repo] Pull request opened: #12 Fix bug by user1 -fixes bug #2`, pl.RichMessage.HTML) + assert.Equal(t, `[test/repo] Pull request opened: #12 Fix bug by user1
fixes bug #2`, pl.RichMessage.HTML) }) t.Run("PullRequestComment", func(t *testing.T) { @@ -109,8 +109,7 @@ fixes bug #2`, pl.RichMessage.HTML) pl, err := tc.IssueComment(p) require.NoError(t, err) - assert.Equal(t, `[test/repo] New comment on pull request #12 Fix bug by user1 -changes requested`, pl.RichMessage.HTML) + assert.Equal(t, `[test/repo] New comment on pull request #12 Fix bug by user1
changes requested`, pl.RichMessage.HTML) }) t.Run("Review", func(t *testing.T) { @@ -120,8 +119,7 @@ changes requested`, pl.RichMessage.HTML) pl, err := tc.Review(p, webhook_module.HookEventPullRequestReviewApproved) require.NoError(t, err) - assert.Equal(t, `[test/repo] Pull request review approved: #12 Fix bug -good job`, pl.RichMessage.HTML) + assert.Equal(t, `[test/repo] Pull request review approved: #12 Fix bug
good job`, pl.RichMessage.HTML) }) t.Run("Repository", func(t *testing.T) { @@ -206,7 +204,5 @@ func TestTelegramJSONPayload(t *testing.T) { var body TelegramPayload err = json.NewDecoder(req.Body).Decode(&body) assert.NoError(t, err) - assert.Equal(t, `[test/repo:test] 2 new commits -[2020558] commit message - user1 -[2020558] commit message - user1`, body.RichMessage.HTML) + assert.Equal(t, `[test/repo:test] 2 new commits
[2020558] commit message - user1
[2020558] commit message - user1`, body.RichMessage.HTML) }