From d06ec05c1cb8e28ef2e824c5ec67375dc3eb5098 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Fri, 26 Jun 2020 16:06:47 +0000 Subject: [PATCH] Discord notif (#111) Co-authored-by: CrazyMax --- docs/assets/notif/discord-1.png | Bin 0 -> 4311 bytes docs/assets/notif/discord-2.png | Bin 0 -> 16186 bytes docs/notif/discord.md | 30 ++++ internal/config/config_test.go | 4 + internal/config/fixtures/config.test.yml | 3 + internal/config/fixtures/config.validate.yml | 3 + internal/model/notif.go | 1 + internal/model/notif_discord.go | 25 ++++ internal/notif/client.go | 4 + internal/notif/discord/client.go | 143 +++++++++++++++++++ internal/notif/discord/model.go | 52 +++++++ mkdocs.yml | 1 + 12 files changed, 266 insertions(+) create mode 100644 docs/assets/notif/discord-1.png create mode 100644 docs/assets/notif/discord-2.png create mode 100644 docs/notif/discord.md create mode 100644 internal/model/notif_discord.go create mode 100644 internal/notif/discord/client.go create mode 100644 internal/notif/discord/model.go diff --git a/docs/assets/notif/discord-1.png b/docs/assets/notif/discord-1.png new file mode 100644 index 0000000000000000000000000000000000000000..b06cb062dc6a3d220ef0263a61ceb6d4bb4ff9dd GIT binary patch literal 4311 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 literal 0 HcmV?d00001 diff --git a/docs/notif/discord.md b/docs/notif/discord.md new file mode 100644 index 00000000..e72d65dd --- /dev/null +++ b/docs/notif/discord.md @@ -0,0 +1,30 @@ +# Discord notifications + +Allow to send notifications to your Discord channel. + +## Configuration + +!!! example "File" + ```yaml + notif: + discord: + webhookURL: https://discordapp.com/api/webhooks/1234567890/Abcd-eFgh-iJklmNo_pqr + timeout: 10s + ``` + +!!! abstract "Environment variables" + * `DIUN_NOTIF_DISCORD_WEBHOOK` + * `DIUN_NOTIF_DISCORD_TIMEOUT` + +| Name | Default | Description | +|--------------------|---------------|---------------| +| `webhookURL`[^1] | | Discord [incoming webhook URL](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) | +| `timeout` | `10s` | Timeout specifies a time limit for the request to be made | + +## Sample + +![](../assets/notif/discord-1.png) + +![](../assets/notif/discord-2.png) + +[^1]: Value required diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 029da8ea..0411e908 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -50,6 +50,10 @@ func TestLoadFile(t *testing.T) { Password: "guest", Queue: "queue", }, + Discord: &model.NotifDiscord{ + WebhookURL: "https://discordapp.com/api/webhooks/1234567890/Abcd-eFgh-iJklmNo_pqr", + Timeout: utl.NewDuration(10 * time.Second), + }, Gotify: &model.NotifGotify{ Endpoint: "http://gotify.foo.com", Token: "Token123456", diff --git a/internal/config/fixtures/config.test.yml b/internal/config/fixtures/config.test.yml index 208256ae..c3efe1d9 100644 --- a/internal/config/fixtures/config.test.yml +++ b/internal/config/fixtures/config.test.yml @@ -13,6 +13,9 @@ notif: username: guest password: guest queue: queue + discord: + webhookURL: https://discordapp.com/api/webhooks/1234567890/Abcd-eFgh-iJklmNo_pqr + timeout: 10s gotify: endpoint: http://gotify.foo.com token: Token123456 diff --git a/internal/config/fixtures/config.validate.yml b/internal/config/fixtures/config.validate.yml index cfe83ba6..38a5724a 100644 --- a/internal/config/fixtures/config.validate.yml +++ b/internal/config/fixtures/config.validate.yml @@ -13,6 +13,9 @@ notif: username: guest password: guest queue: queue + discord: + webhookURL: https://discordapp.com/api/webhooks/1234567890/Abcd-eFgh-iJklmNo_pqr + timeout: 10s gotify: endpoint: http://gotify.foo.com token: Token123456 diff --git a/internal/model/notif.go b/internal/model/notif.go index becafce9..4a3ffe49 100644 --- a/internal/model/notif.go +++ b/internal/model/notif.go @@ -15,6 +15,7 @@ type NotifEntry struct { // Notif holds data necessary for notification configuration type Notif struct { Amqp *NotifAmqp `yaml:"amqp,omitempty" json:"amqp,omitempty"` + Discord *NotifDiscord `yaml:"discord,omitempty" json:"discord,omitempty"` Gotify *NotifGotify `yaml:"gotify,omitempty" json:"gotify,omitempty"` Mail *NotifMail `yaml:"mail,omitempty" json:"mail,omitempty"` RocketChat *NotifRocketChat `yaml:"rocketchat,omitempty" json:"rocketchat,omitempty"` diff --git a/internal/model/notif_discord.go b/internal/model/notif_discord.go new file mode 100644 index 00000000..a4b94dd9 --- /dev/null +++ b/internal/model/notif_discord.go @@ -0,0 +1,25 @@ +package model + +import ( + "time" + + "github.com/crazy-max/diun/v4/pkg/utl" +) + +// NotifDiscord holds Discord notification configuration details +type NotifDiscord struct { + WebhookURL string `yaml:"webhookURL,omitempty" json:"webhookURL,omitempty" validate:"required"` + Timeout *time.Duration `yaml:"timeout,omitempty" json:"timeout,omitempty" validate:"required"` +} + +// GetDefaults gets the default values +func (s *NotifDiscord) GetDefaults() *NotifDiscord { + n := &NotifDiscord{} + n.SetDefaults() + return n +} + +// SetDefaults sets the default values +func (s *NotifDiscord) SetDefaults() { + s.Timeout = utl.NewDuration(10 * time.Second) +} diff --git a/internal/notif/client.go b/internal/notif/client.go index 337ca669..12c70094 100644 --- a/internal/notif/client.go +++ b/internal/notif/client.go @@ -5,6 +5,7 @@ import ( "github.com/crazy-max/diun/v4/internal/model" "github.com/crazy-max/diun/v4/internal/notif/amqp" + "github.com/crazy-max/diun/v4/internal/notif/discord" "github.com/crazy-max/diun/v4/internal/notif/gotify" "github.com/crazy-max/diun/v4/internal/notif/mail" "github.com/crazy-max/diun/v4/internal/notif/notifier" @@ -41,6 +42,9 @@ func New(config *model.Notif, meta model.Meta) (*Client, error) { if config.Amqp != nil { c.notifiers = append(c.notifiers, amqp.New(config.Amqp, meta)) } + if config.Discord != nil { + c.notifiers = append(c.notifiers, discord.New(config.Discord, meta)) + } if config.Gotify != nil { c.notifiers = append(c.notifiers, gotify.New(config.Gotify, meta)) } diff --git a/internal/notif/discord/client.go b/internal/notif/discord/client.go new file mode 100644 index 00000000..693c5fce --- /dev/null +++ b/internal/notif/discord/client.go @@ -0,0 +1,143 @@ +package discord + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "net/url" + "text/template" + "time" + + "github.com/crazy-max/diun/v4/internal/model" + "github.com/crazy-max/diun/v4/internal/notif/notifier" +) + +// Client represents an active discord notification object +type Client struct { + *notifier.Notifier + cfg *model.NotifDiscord + meta model.Meta +} + +// New creates a new discord notification instance +func New(config *model.NotifDiscord, meta model.Meta) notifier.Notifier { + return notifier.Notifier{ + Handler: &Client{ + cfg: config, + meta: meta, + }, + } +} + +// Name returns notifier's name +func (c *Client) Name() string { + return "discord" +} + +// Send creates and sends a discord notification with an entry +// https://discord.com/developers/docs/resources/webhook#execute-webhook +func (c *Client) Send(entry model.NotifEntry) error { + hc := http.Client{ + Timeout: *c.cfg.Timeout, + } + + content := fmt.Sprintf("@here Image update for %s", entry.Image.String()) + if entry.Status == model.ImageStatusNew { + content = fmt.Sprintf("@here New image %s has been added", entry.Image.String()) + } + + tagTpl := "**{{ .Entry.Image.Domain }}/{{ .Entry.Image.Path }}:{{ .Entry.Image.Tag }}**" + if len(entry.Image.HubLink) > 0 { + tagTpl = "[**{{ .Entry.Image.Domain }}/{{ .Entry.Image.Path }}:{{ .Entry.Image.Tag }}**]({{ .Entry.Image.HubLink }})" + } + + var textBuf bytes.Buffer + textTpl := template.Must(template.New("discord").Parse(fmt.Sprintf(`Docker tag %s which you subscribed to through **{{ .Entry.Provider }}** provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }} on **myserver**.`, tagTpl))) + if err := textTpl.Execute(&textBuf, struct { + Meta model.Meta + Entry model.NotifEntry + }{ + Meta: c.meta, + Entry: entry, + }); err != nil { + return err + } + + fields := []EmbedField{ + { + Name: "Hostname", + Value: c.meta.Hostname, + }, + { + Name: "Provider", + Value: entry.Provider, + }, + { + Name: "Created", + Value: entry.Manifest.Created.Format("Jan 02, 2006 15:04:05 UTC"), + }, + { + Name: "Digest", + Value: entry.Manifest.Digest.String(), + }, + { + Name: "Platform", + Value: entry.Manifest.Platform, + }, + } + if len(entry.Image.HubLink) > 0 { + fields = append(fields, EmbedField{ + Name: "HubLink", + Value: entry.Image.HubLink, + }) + } + + dataBuf := new(bytes.Buffer) + if err := json.NewEncoder(dataBuf).Encode(Message{ + Content: content, + Username: c.meta.Name, + AvatarURL: c.meta.Logo, + Embeds: []Embed{ + { + Description: textBuf.String(), + Footer: EmbedFooter{ + Text: fmt.Sprintf("%s © %d %s %s", c.meta.Author, time.Now().Year(), c.meta.Name, c.meta.Version), + IconURL: c.meta.Logo, + }, + Author: EmbedAuthor{ + Name: c.meta.Name, + URL: c.meta.URL, + IconURL: c.meta.Logo, + }, + Fields: fields, + }, + }, + }); err != nil { + return err + } + + u, err := url.Parse(c.cfg.WebhookURL) + if err != nil { + return err + } + + req, err := http.NewRequest("POST", u.String(), dataBuf) + if err != nil { + return err + } + + req.Header.Set("Content-Type", "application/json") + req.Header.Set("User-Agent", c.meta.UserAgent) + + resp, err := hc.Do(req) + if err != nil { + return err + } + + if resp.StatusCode != http.StatusNoContent { + return fmt.Errorf("unexpected HTTP status %d: %s", resp.StatusCode, resp.Body) + } + + return nil +} diff --git a/internal/notif/discord/model.go b/internal/notif/discord/model.go new file mode 100644 index 00000000..4a408284 --- /dev/null +++ b/internal/notif/discord/model.go @@ -0,0 +1,52 @@ +package discord + +// Message contains all the information for a message +type Message struct { + Content string `json:"content"` + Username string `json:"username"` + AvatarURL string `json:"avatar_url"` + Embeds []Embed `json:"embeds"` +} + +// Embed contains all the information for an embed object +type Embed struct { + Title string `json:"title,omitempty"` + Description string `json:"description,omitempty"` + URL string `json:"url,omitempty"` + Color int `json:"color,omitempty"` + Footer EmbedFooter `json:"footer,omitempty"` + Image EmbedImage `json:"image,omitempty"` + Thumbnail EmbedThumbnail `json:"thumbnail,omitempty"` + Author EmbedAuthor `json:"author,omitempty"` + Fields []EmbedField `json:"fields,omitempty"` +} + +// EmbedFooter contains all the information for an embed footer object +type EmbedFooter struct { + Text string `json:"text"` + IconURL string `json:"icon_url"` +} + +// EmbedImage contains all the information for an embed image object +type EmbedImage struct { + URL string `json:"url"` +} + +// EmbedThumbnail contains all the information for an embed thumbnail object +type EmbedThumbnail struct { + URL string `json:"url"` +} + +// EmbedAuthor contains all the information for an embed author object +type EmbedAuthor struct { + Name string `json:"name"` + URL string `json:"url"` + IconURL string `json:"icon_url"` +} + +// EmbedField contains all the information for an embed field object +type EmbedField struct { + Name string `json:"name"` + Value string `json:"value"` + Inline bool `json:"inline,omitempty"` +} diff --git a/mkdocs.yml b/mkdocs.yml index 83cdafe2..57b07221 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -66,6 +66,7 @@ nav: - .providers: config/providers.md - Notifications: - Amqp: notif/amqp.md + - Discord: notif/discord.md - Gotify: notif/gotify.md - Mail: notif/mail.md - Rocket.Chat: notif/rocketchat.md