loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix discord webhook 400 status code when description limit is exceeded (#34084)

Fixes [#34027](https://github.com/go-gitea/gitea/issues/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 <wxiaoguang@gmail.com>
(cherry picked from commit 013b2686fe6d306c4fb800147207b099866683b9)

authored by

Mopcho
wxiaoguang
and committed by
Michael Jerger
64cc883a 3e3a109d

+38 -7
+9
modules/util/truncate.go
··· 54 54 55 55 return stringList 56 56 } 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 + }
+15
modules/util/truncate_test.go
··· 44 44 } 45 45 test(tc, SplitStringAtByteN) 46 46 } 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 + }
+13 -6
services/webhook/discord.go
··· 151 151 redColor = color("ff3232") 152 152 ) 153 153 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 + 154 166 // Create implements PayloadConvertor Create method 155 167 func (d discordConvertor) Create(p *api.CreatePayload) (DiscordPayload, error) { 156 168 // created tag/branch ··· 312 324 return d.createPayload(p.Sender, text, "", p.Package.HTMLURL, color), nil 313 325 } 314 326 315 - type discordConvertor struct { 316 - Username string 317 - AvatarURL string 318 - } 319 - 320 327 var _ shared.PayloadConvertor[DiscordPayload] = discordConvertor{} 321 328 322 329 func (discordHandler) NewRequest(ctx context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) { ··· 357 364 Embeds: []DiscordEmbed{ 358 365 { 359 366 Title: title, 360 - Description: text, 367 + Description: util.TruncateRunes(text, discordDescriptionCharactersLimit), 361 368 URL: url, 362 369 Color: color, 363 370 Author: DiscordEmbedAuthor{
+1 -1
services/webhook/discord_test.go
··· 175 175 require.NoError(t, err) 176 176 177 177 assert.Len(t, pl.Embeds, 1) 178 - assert.Len(t, pl.Embeds[0].Description, 4096) 178 + assert.Len(t, pl.Embeds[0].Description, 2000) 179 179 }) 180 180 181 181 t.Run("IssueComment", func(t *testing.T) {