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: improve discord webhook api conformance

This commit corrects some cases in the discord webhook payload that do
not align with the discord documentation

Kidsan 6ea6f224 cf3ebab4

+76 -13
+15 -9
services/webhook/discord.go
··· 14 14 "strings" 15 15 "unicode/utf8" 16 16 17 - "gitea.com/go-chi/binding" 18 - 19 17 webhook_model "code.gitea.io/gitea/models/webhook" 20 18 "code.gitea.io/gitea/modules/git" 21 19 "code.gitea.io/gitea/modules/json" ··· 27 25 gitea_context "code.gitea.io/gitea/services/context" 28 26 "code.gitea.io/gitea/services/forms" 29 27 "code.gitea.io/gitea/services/webhook/shared" 28 + 29 + "gitea.com/go-chi/binding" 30 30 ) 31 31 32 32 type discordHandler struct{} ··· 37 37 type discordForm struct { 38 38 forms.WebhookCoreForm 39 39 PayloadURL string `binding:"Required;ValidUrl"` 40 - Username string 41 - IconURL string 40 + Username string `binding:"Required;MaxSize(80)"` 41 + IconURL string `binding:"ValidUrl"` 42 42 } 43 43 44 44 var _ binding.Validator = &discordForm{} ··· 75 75 type ( 76 76 // DiscordEmbedFooter for Embed Footer Structure. 77 77 DiscordEmbedFooter struct { 78 - Text string `json:"text"` 78 + Text string `json:"text,omitempty"` 79 79 } 80 80 81 81 // DiscordEmbedAuthor for Embed Author Structure ··· 99 99 Color int `json:"color"` 100 100 Footer DiscordEmbedFooter `json:"footer"` 101 101 Author DiscordEmbedAuthor `json:"author"` 102 - Fields []DiscordEmbedField `json:"fields"` 102 + Fields []DiscordEmbedField `json:"fields,omitempty"` 103 103 } 104 104 105 105 // DiscordPayload represents 106 106 DiscordPayload struct { 107 - Wait bool `json:"wait"` 108 - Content string `json:"content"` 107 + Wait bool `json:"-"` 108 + Content string `json:"-"` 109 109 Username string `json:"username"` 110 110 AvatarURL string `json:"avatar_url,omitempty"` 111 - TTS bool `json:"tts"` 111 + TTS bool `json:"-"` 112 112 Embeds []DiscordEmbed `json:"embeds"` 113 113 } 114 114 ··· 341 341 } 342 342 343 343 func (d discordConvertor) createPayload(s *api.User, title, text, url string, color int) DiscordPayload { 344 + if len([]rune(title)) > 256 { 345 + title = fmt.Sprintf("%.253s...", title) 346 + } 347 + if len([]rune(text)) > 4096 { 348 + text = fmt.Sprintf("%.4093s...", text) 349 + } 344 350 return DiscordPayload{ 345 351 Username: d.Username, 346 352 AvatarURL: d.AvatarURL,
+43
services/webhook/discord_test.go
··· 120 120 assert.Equal(t, p.Sender.UserName, pl.Embeds[0].Author.Name) 121 121 assert.Equal(t, setting.AppURL+p.Sender.UserName, pl.Embeds[0].Author.URL) 122 122 assert.Equal(t, p.Sender.AvatarURL, pl.Embeds[0].Author.IconURL) 123 + 124 + j, err := json.Marshal(pl) 125 + require.NoError(t, err) 126 + 127 + unsetFields := struct { 128 + Content *string `json:"content"` 129 + TTS *bool `json:"tts"` 130 + Wait *bool `json:"wait"` 131 + Fields []any `json:"fields"` 132 + Footer struct { 133 + Text *string `json:"text"` 134 + } `json:"footer"` 135 + }{} 136 + 137 + err = json.Unmarshal(j, &unsetFields) 138 + require.NoError(t, err) 139 + assert.Nil(t, unsetFields.Content) 140 + assert.Nil(t, unsetFields.TTS) 141 + assert.Nil(t, unsetFields.Wait) 142 + assert.Nil(t, unsetFields.Fields) 143 + assert.Nil(t, unsetFields.Footer.Text) 144 + }) 145 + 146 + t.Run("Issue with long title", func(t *testing.T) { 147 + p := issueTestPayloadWithLongTitle() 148 + 149 + p.Action = api.HookIssueOpened 150 + pl, err := dc.Issue(p) 151 + require.NoError(t, err) 152 + 153 + assert.Len(t, pl.Embeds, 1) 154 + assert.Len(t, pl.Embeds[0].Title, 256) 155 + }) 156 + 157 + t.Run("Issue with long body", func(t *testing.T) { 158 + p := issueTestPayloadWithLongBody() 159 + 160 + p.Action = api.HookIssueOpened 161 + pl, err := dc.Issue(p) 162 + require.NoError(t, err) 163 + 164 + assert.Len(t, pl.Embeds, 1) 165 + assert.Len(t, pl.Embeds[0].Description, 4096) 123 166 }) 124 167 125 168 t.Run("IssueComment", func(t *testing.T) {
+15 -2
services/webhook/general_test.go
··· 4 4 package webhook 5 5 6 6 import ( 7 + "strings" 7 8 "testing" 8 9 9 10 api "code.gitea.io/gitea/modules/structs" ··· 113 114 } 114 115 115 116 func issueTestPayload() *api.IssuePayload { 117 + return issuePayloadWithTitleAndBody("crash", "issue body") 118 + } 119 + 120 + func issueTestPayloadWithLongBody() *api.IssuePayload { 121 + return issuePayloadWithTitleAndBody("crash", strings.Repeat("issue body", 4097)) 122 + } 123 + 124 + func issueTestPayloadWithLongTitle() *api.IssuePayload { 125 + return issuePayloadWithTitleAndBody(strings.Repeat("a", 257), "issue body") 126 + } 127 + 128 + func issuePayloadWithTitleAndBody(title, body string) *api.IssuePayload { 116 129 return &api.IssuePayload{ 117 130 Index: 2, 118 131 Sender: &api.User{ ··· 129 142 Index: 2, 130 143 URL: "http://localhost:3000/api/v1/repos/test/repo/issues/2", 131 144 HTMLURL: "http://localhost:3000/test/repo/issues/2", 132 - Title: "crash", 133 - Body: "issue body", 145 + Title: title, 146 + Body: body, 134 147 Poster: &api.User{ 135 148 UserName: "user1", 136 149 AvatarURL: "http://localhost:3000/user1/avatar",
+2 -2
templates/webhook/new/discord.tmpl
··· 5 5 <label for="payload_url">{{ctx.Locale.Tr "repo.settings.payload_url"}}</label> 6 6 <input id="payload_url" name="payload_url" type="url" value="{{.Webhook.URL}}" autofocus required> 7 7 </div> 8 - <div class="field"> 8 + <div class="required field {{if .Err_PayloadURL}}error{{end}}"> 9 9 <label for="username">{{ctx.Locale.Tr "repo.settings.discord_username"}}</label> 10 - <input id="username" name="username" value="{{.HookMetadata.Username}}" placeholder="Forgejo"> 10 + <input id="username" name="username" value="{{.HookMetadata.Username}}" autofocus required placeholder="Forgejo"> 11 11 </div> 12 12 <div class="field"> 13 13 <label for="icon_url">{{ctx.Locale.Tr "repo.settings.discord_icon_url"}}</label>
+1
tests/integration/repo_webhook_test.go
··· 172 172 })) 173 173 174 174 t.Run("discord/required", testWebhookForms("discord", session, map[string]string{ 175 + "username": "john", 175 176 "payload_url": "https://discord.example.com", 176 177 })) 177 178 t.Run("discord/optional", testWebhookForms("discord", session, map[string]string{