Skip to content

Commit 64cc883

Browse files
Mopchowxiaoguang
authored andcommitted
Fix discord webhook 400 status code when description limit is exceeded (go-gitea#34084)
Fixes [go-gitea#34027](go-gitea#34027) Discord does not allow for description bigger than 2048 bytes. If the description is bigger than that it will throw 400 and the event won't appear in discord. To fix that, in the createPayload method we now slice the description to ensure it doesn’t exceed the limit. --------- Co-authored-by: wxiaoguang <[email protected]> (cherry picked from commit 013b268)
1 parent 3e3a109 commit 64cc883

File tree

4 files changed

+38
-7
lines changed

4 files changed

+38
-7
lines changed

modules/util/truncate.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,12 @@ func SplitTrimSpace(input, sep string) []string {
5454

5555
return stringList
5656
}
57+
58+
// TruncateRunes returns a truncated string with given rune limit,
59+
// it returns input string if its rune length doesn't exceed the limit.
60+
func TruncateRunes(str string, limit int) string {
61+
if utf8.RuneCountInString(str) < limit {
62+
return str
63+
}
64+
return string([]rune(str)[:limit])
65+
}

modules/util/truncate_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,18 @@ func TestSplitString(t *testing.T) {
4444
}
4545
test(tc, SplitStringAtByteN)
4646
}
47+
48+
func TestTruncateRunes(t *testing.T) {
49+
assert.Empty(t, TruncateRunes("", 0))
50+
assert.Empty(t, TruncateRunes("", 1))
51+
52+
assert.Empty(t, TruncateRunes("ab", 0))
53+
assert.Equal(t, "a", TruncateRunes("ab", 1))
54+
assert.Equal(t, "ab", TruncateRunes("ab", 2))
55+
assert.Equal(t, "ab", TruncateRunes("ab", 3))
56+
57+
assert.Empty(t, TruncateRunes("测试", 0))
58+
assert.Equal(t, "测", TruncateRunes("测试", 1))
59+
assert.Equal(t, "测试", TruncateRunes("测试", 2))
60+
assert.Equal(t, "测试", TruncateRunes("测试", 3))
61+
}

services/webhook/discord.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,18 @@ var (
151151
redColor = color("ff3232")
152152
)
153153

154+
// https://discord.com/developers/docs/resources/message#embed-object-embed-limits
155+
// Discord has some limits in place for the embeds.
156+
// According to some tests, there is no consistent limit for different character sets.
157+
// For example: 4096 ASCII letters are allowed, but only 2490 emoji characters are allowed.
158+
// To keep it simple, we currently truncate at 2000.
159+
const discordDescriptionCharactersLimit = 2000
160+
161+
type discordConvertor struct {
162+
Username string
163+
AvatarURL string
164+
}
165+
154166
// Create implements PayloadConvertor Create method
155167
func (d discordConvertor) Create(p *api.CreatePayload) (DiscordPayload, error) {
156168
// created tag/branch
@@ -312,11 +324,6 @@ func (d discordConvertor) Package(p *api.PackagePayload) (DiscordPayload, error)
312324
return d.createPayload(p.Sender, text, "", p.Package.HTMLURL, color), nil
313325
}
314326

315-
type discordConvertor struct {
316-
Username string
317-
AvatarURL string
318-
}
319-
320327
var _ shared.PayloadConvertor[DiscordPayload] = discordConvertor{}
321328

322329
func (discordHandler) NewRequest(ctx context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) {
@@ -357,7 +364,7 @@ func (d discordConvertor) createPayload(s *api.User, title, text, url string, co
357364
Embeds: []DiscordEmbed{
358365
{
359366
Title: title,
360-
Description: text,
367+
Description: util.TruncateRunes(text, discordDescriptionCharactersLimit),
361368
URL: url,
362369
Color: color,
363370
Author: DiscordEmbedAuthor{

services/webhook/discord_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ func TestDiscordPayload(t *testing.T) {
175175
require.NoError(t, err)
176176

177177
assert.Len(t, pl.Embeds, 1)
178-
assert.Len(t, pl.Embeds[0].Description, 4096)
178+
assert.Len(t, pl.Embeds[0].Description, 2000)
179179
})
180180

181181
t.Run("IssueComment", func(t *testing.T) {

0 commit comments

Comments
 (0)