Discord notifier: Add username and avatar_url (#4081)

* Feat(discord):

Allow for custom username and avatar URLs to be set in discord notifications.

Add `username` and `avatar_url` to discord configuration, default empty string.

Re-implement #3821

Signed-off-by: Jeff Wong <awole20@gmail.com>

* Test the new fields

Signed-off-by: gotjosh <josue.abreu@gmail.com>

* These are not templeatable strings

Signed-off-by: gotjosh <josue.abreu@gmail.com>

---------

Signed-off-by: Jeff Wong <awole20@gmail.com>
Signed-off-by: gotjosh <josue.abreu@gmail.com>
Co-authored-by: gotjosh <josue.abreu@gmail.com>
This commit is contained in:
Jeff Wong 2024-10-24 13:12:05 -07:00 committed by GitHub
parent 615d5ffa30
commit 95655dccb8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 29 additions and 7 deletions

View File

@ -254,6 +254,8 @@ type DiscordConfig struct {
Content string `yaml:"content,omitempty" json:"content,omitempty"` Content string `yaml:"content,omitempty" json:"content,omitempty"`
Title string `yaml:"title,omitempty" json:"title,omitempty"` Title string `yaml:"title,omitempty" json:"title,omitempty"`
Message string `yaml:"message,omitempty" json:"message,omitempty"` Message string `yaml:"message,omitempty" json:"message,omitempty"`
Username string `yaml:"username,omitempty" json:"username,omitempty"`
AvatarURL string `yaml:"avatar_url,omitempty" json:"avatar_url,omitempty"`
} }
// UnmarshalYAML implements the yaml.Unmarshaler interface. // UnmarshalYAML implements the yaml.Unmarshaler interface.

View File

@ -886,6 +886,12 @@ webhook_url_file: <filepath>
# Message content template. Limited to 2000 characters. # Message content template. Limited to 2000 characters.
[ content: <tmpl_string> | default = '{{ template "discord.default.content" . }}' ] [ content: <tmpl_string> | default = '{{ template "discord.default.content" . }}' ]
# Message username.
[ username: <string> | default = '' ]
# Message avatar URL.
[ avatar_url: <string> | default = '' ]
# The HTTP client's configuration. # The HTTP client's configuration.
[ http_config: <http_config> | default = global.http_config ] [ http_config: <http_config> | default = global.http_config ]
``` ```

View File

@ -19,6 +19,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
netUrl "net/url"
"os" "os"
"strings" "strings"
@ -78,6 +79,8 @@ func New(c *config.DiscordConfig, t *template.Template, l log.Logger, httpOpts .
type webhook struct { type webhook struct {
Content string `json:"content"` Content string `json:"content"`
Embeds []webhookEmbed `json:"embeds"` Embeds []webhookEmbed `json:"embeds"`
Username string `json:"username,omitempty"`
AvatarURL string `json:"avatar_url,omitempty"`
} }
type webhookEmbed struct { type webhookEmbed struct {
@ -146,6 +149,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
w := webhook{ w := webhook{
Content: content, Content: content,
Username: n.conf.Username,
Embeds: []webhookEmbed{{ Embeds: []webhookEmbed{{
Title: title, Title: title,
Description: description, Description: description,
@ -153,6 +157,14 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
}}, }},
} }
if len(n.conf.AvatarURL) != 0 {
if _, err := netUrl.Parse(n.conf.AvatarURL); err == nil {
w.AvatarURL = n.conf.AvatarURL
} else {
level.Warn(n.logger).Log("msg", "Bad avatar url", "key", key)
}
}
var payload bytes.Buffer var payload bytes.Buffer
if err = json.NewEncoder(&payload).Encode(w); err != nil { if err = json.NewEncoder(&payload).Encode(w); err != nil {
return false, err return false, err

View File

@ -201,6 +201,8 @@ func TestDiscord_Notify(t *testing.T) {
Title: "Test Title", Title: "Test Title",
Message: "Test Message", Message: "Test Message",
Content: "Test Content", Content: "Test Content",
Username: "Test Username",
AvatarURL: "http://example.com/avatar.png",
} }
// Create a new Discord notifier // Create a new Discord notifier
@ -227,5 +229,5 @@ func TestDiscord_Notify(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.False(t, ok) require.False(t, ok)
require.Equal(t, "{\"content\":\"Test Content\",\"embeds\":[{\"title\":\"Test Title\",\"description\":\"Test Message\",\"color\":10038562}]}\n", resp) require.Equal(t, "{\"content\":\"Test Content\",\"embeds\":[{\"title\":\"Test Title\",\"description\":\"Test Message\",\"color\":10038562}],\"username\":\"Test Username\",\"avatar_url\":\"http://example.com/avatar.png\"}\n", resp)
} }