mirror of
https://github.com/crazy-max/diun.git
synced 2025-04-10 22:00:13 +00:00
Add Matrix notification (#136)
* Add Matrix notification (#124) * Fix docs Co-authored-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
parent
19b54f9881
commit
b9c35e369f
14 changed files with 204 additions and 0 deletions
BIN
docs/assets/notif/matrix.png
Normal file
BIN
docs/assets/notif/matrix.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 3.8 KiB |
|
@ -201,8 +201,10 @@ Can be transposed to:
|
|||
* [watch](watch.md)
|
||||
* notif
|
||||
* [amqp](../notif/amqp.md)
|
||||
* [discord](../notif/discord.md)
|
||||
* [gotify](../notif/amqp.md)
|
||||
* [mail](../notif/amqp.md)
|
||||
* [matrix](../notif/matrix.md)
|
||||
* [rocketchat](../notif/amqp.md)
|
||||
* [script](../notif/amqp.md)
|
||||
* [slack](../notif/amqp.md)
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
# Notifications configuration
|
||||
|
||||
* [`amqp`](../notif/amqp.md)
|
||||
* [`discord`](../notif/discord.md)
|
||||
* [`gotify`](../notif/gotify.md)
|
||||
* [`mail`](../notif/mail.md)
|
||||
* [`matrix`](../notif/matrix.md)
|
||||
* [`rocketchat`](../notif/rocketchat.md)
|
||||
* [`script`](../notif/script.md)
|
||||
* [`slack`](../notif/slack.md)
|
||||
|
|
38
docs/notif/matrix.md
Normal file
38
docs/notif/matrix.md
Normal file
|
@ -0,0 +1,38 @@
|
|||
# Rocket.Chat notifications
|
||||
|
||||
Allow to send notifications to your Matrix server.
|
||||
|
||||
## Configuration
|
||||
|
||||
!!! example "File"
|
||||
```yaml
|
||||
notif:
|
||||
matrix:
|
||||
homeserverURL: https://matrix.org
|
||||
user: "@foo:matrix.org"
|
||||
password: bar
|
||||
roomID: "!abcdefGHIjklmno:matrix.org"
|
||||
```
|
||||
|
||||
| Name | Default | Description |
|
||||
|-----------------------|------------------------|-------------------|
|
||||
| `homeserverURL`[^1] | `https://matrix.org` | Matrix server URL |
|
||||
| `user` | | Username for authentication |
|
||||
| `userFile` | | Use content of secret file as username authentication if `username` not defined |
|
||||
| `password` | | Password for authentication |
|
||||
| `passwordFile` | | Use content of secret file as password authentication if `password` not defined |
|
||||
| `roomID`[^1] | | Room ID to send messages |
|
||||
|
||||
!!! abstract "Environment variables"
|
||||
* `DIUN_NOTIF_MATRIX_HOMESERVERURL`
|
||||
* `DIUN_NOTIF_MATRIX_USER`
|
||||
* `DIUN_NOTIF_MATRIX_USERFILE`
|
||||
* `DIUN_NOTIF_MATRIX_PASSWORD`
|
||||
* `DIUN_NOTIF_MATRIX_PASSWORDFILE`
|
||||
* `DIUN_NOTIF_MATRIX_ROOMID`
|
||||
|
||||
## Sample
|
||||
|
||||

|
||||
|
||||
[^1]: Value required
|
3
go.mod
3
go.mod
|
@ -14,12 +14,15 @@ require (
|
|||
github.com/hako/durafmt v0.0.0-20190612201238-650ed9f29a84
|
||||
github.com/imdario/mergo v0.3.10
|
||||
github.com/matcornic/hermes/v2 v2.1.0
|
||||
github.com/matrix-org/gomatrix v0.0.0-20200501121722-e5578b12c752
|
||||
github.com/microcosm-cc/bluemonday v1.0.3
|
||||
github.com/nlopes/slack v0.6.0
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/panjf2000/ants/v2 v2.4.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/rs/zerolog v1.19.0
|
||||
github.com/russross/blackfriday/v2 v2.0.1
|
||||
github.com/sirupsen/logrus v1.6.0
|
||||
github.com/streadway/amqp v0.0.0-20200108173154-1c71cc93ed71
|
||||
github.com/stretchr/testify v1.6.1
|
||||
|
|
9
go.sum
9
go.sum
|
@ -36,10 +36,14 @@ github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRy
|
|||
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/aokoli/goutils v1.0.1 h1:7fpzNGoJ3VA8qcrm++XEE1QUe0mIwNeLa02Nwq7RDkg=
|
||||
github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/chris-ramon/douceur v0.2.0 h1:IDMEdxlEUUBYBKE4z/mJnFyVXox+MjuEVDJNN27glkU=
|
||||
github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
||||
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
|
||||
|
@ -196,6 +200,8 @@ github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgx
|
|||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/matcornic/hermes/v2 v2.1.0 h1:9TDYFBPFv6mcXanaDmRDEp/RTWj0dTTi+LpFnnnfNWc=
|
||||
github.com/matcornic/hermes/v2 v2.1.0/go.mod h1:2+ziJeoyRfaLiATIL8VZ7f9hpzH4oDHqTmn0bhrsgVI=
|
||||
github.com/matrix-org/gomatrix v0.0.0-20200501121722-e5578b12c752 h1:xYU2vdY5uh7QX4RZqeuKpmv0ffBEGYHhgu4Mmm3RVnc=
|
||||
github.com/matrix-org/gomatrix v0.0.0-20200501121722-e5578b12c752/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
|
@ -203,6 +209,8 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
|
|||
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/microcosm-cc/bluemonday v1.0.3 h1:EjVH7OqbU219kdm8acbveoclh2zZFqPJTJw6VUlTLAQ=
|
||||
github.com/microcosm-cc/bluemonday v1.0.3/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
|
||||
github.com/mistifyio/go-zfs v2.1.1+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
|
@ -335,6 +343,7 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r
|
|||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
|
|
|
@ -70,6 +70,12 @@ func TestLoadFile(t *testing.T) {
|
|||
From: "diun@example.com",
|
||||
To: "webmaster@example.com",
|
||||
},
|
||||
Matrix: &model.NotifMatrix{
|
||||
HomeserverURL: "https://matrix.org",
|
||||
User: "@foo:matrix.org",
|
||||
Password: "bar",
|
||||
RoomID: "!abcdefGHIjklmno:matrix.org",
|
||||
},
|
||||
RocketChat: &model.NotifRocketChat{
|
||||
Endpoint: "http://rocket.foo.com:3000",
|
||||
Channel: "#general",
|
||||
|
|
|
@ -28,6 +28,11 @@ notif:
|
|||
insecureSkipVerify: false
|
||||
from: diun@example.com
|
||||
to: webmaster@example.com
|
||||
matrix:
|
||||
homeserverURL: https://matrix.org
|
||||
user: "@foo:matrix.org"
|
||||
password: bar
|
||||
roomID: "!abcdefGHIjklmno:matrix.org"
|
||||
rocketchat:
|
||||
endpoint: http://rocket.foo.com:3000
|
||||
channel: "#general"
|
||||
|
|
|
@ -28,6 +28,11 @@ notif:
|
|||
insecureSkipVerify: false
|
||||
from: diun@example.com
|
||||
to: webmaster@example.com
|
||||
matrix:
|
||||
homeserverURL: https://matrix.org
|
||||
user: "@foo:matrix.org"
|
||||
password: bar
|
||||
roomID: "!abcdefGHIjklmno:matrix.org"
|
||||
rocketchat:
|
||||
endpoint: http://rocket.foo.com:3000
|
||||
channel: "#general"
|
||||
|
|
|
@ -18,6 +18,7 @@ type Notif struct {
|
|||
Discord *NotifDiscord `yaml:"discord,omitempty" json:"discord,omitempty"`
|
||||
Gotify *NotifGotify `yaml:"gotify,omitempty" json:"gotify,omitempty"`
|
||||
Mail *NotifMail `yaml:"mail,omitempty" json:"mail,omitempty"`
|
||||
Matrix *NotifMatrix `yaml:"matrix,omitempty" json:"matrix,omitempty"`
|
||||
RocketChat *NotifRocketChat `yaml:"rocketchat,omitempty" json:"rocketchat,omitempty"`
|
||||
Script *NotifScript `yaml:"script,omitempty" json:"script,omitempty"`
|
||||
Slack *NotifSlack `yaml:"slack,omitempty" json:"slack,omitempty"`
|
||||
|
|
23
internal/model/notif_matrix.go
Normal file
23
internal/model/notif_matrix.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package model
|
||||
|
||||
// NotifMatrix holds Matrix notification configuration details
|
||||
type NotifMatrix struct {
|
||||
HomeserverURL string `yaml:"homeserverURL,omitempty" json:"homeserverURL,omitempty" validate:"required"`
|
||||
User string `yaml:"user,omitempty" json:"user,omitempty" validate:"omitempty"`
|
||||
UserFile string `yaml:"userFile,omitempty" json:"userFile,omitempty" validate:"omitempty,file"`
|
||||
Password string `yaml:"password,omitempty" json:"password,omitempty" validate:"omitempty"`
|
||||
PasswordFile string `yaml:"passwordFile,omitempty" json:"passwordFile,omitempty" validate:"omitempty,file"`
|
||||
RoomID string `yaml:"roomID,omitempty" json:"roomID,omitempty" validate:"required"`
|
||||
}
|
||||
|
||||
// GetDefaults gets the default values
|
||||
func (s *NotifMatrix) GetDefaults() *NotifMatrix {
|
||||
n := &NotifMatrix{}
|
||||
n.SetDefaults()
|
||||
return n
|
||||
}
|
||||
|
||||
// SetDefaults sets the default values
|
||||
func (s *NotifMatrix) SetDefaults() {
|
||||
s.HomeserverURL = "https://matrix.org"
|
||||
}
|
|
@ -8,6 +8,7 @@ import (
|
|||
"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/matrix"
|
||||
"github.com/crazy-max/diun/v4/internal/notif/notifier"
|
||||
"github.com/crazy-max/diun/v4/internal/notif/rocketchat"
|
||||
"github.com/crazy-max/diun/v4/internal/notif/script"
|
||||
|
@ -51,6 +52,9 @@ func New(config *model.Notif, meta model.Meta) (*Client, error) {
|
|||
if config.Mail != nil {
|
||||
c.notifiers = append(c.notifiers, mail.New(config.Mail, meta))
|
||||
}
|
||||
if config.Matrix != nil {
|
||||
c.notifiers = append(c.notifiers, matrix.New(config.Matrix, meta))
|
||||
}
|
||||
if config.RocketChat != nil {
|
||||
c.notifiers = append(c.notifiers, rocketchat.New(config.RocketChat, meta))
|
||||
}
|
||||
|
|
105
internal/notif/matrix/client.go
Normal file
105
internal/notif/matrix/client.go
Normal file
|
@ -0,0 +1,105 @@
|
|||
package matrix
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"text/template"
|
||||
|
||||
"github.com/crazy-max/diun/v4/internal/model"
|
||||
"github.com/crazy-max/diun/v4/internal/notif/notifier"
|
||||
"github.com/crazy-max/diun/v4/pkg/utl"
|
||||
"github.com/matrix-org/gomatrix"
|
||||
"github.com/microcosm-cc/bluemonday"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/russross/blackfriday/v2"
|
||||
)
|
||||
|
||||
// Client represents an active rocketchat notification object
|
||||
type Client struct {
|
||||
*notifier.Notifier
|
||||
cfg *model.NotifMatrix
|
||||
meta model.Meta
|
||||
}
|
||||
|
||||
// New creates a new rocketchat notification instance
|
||||
func New(config *model.NotifMatrix, 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 "matrix"
|
||||
}
|
||||
|
||||
// Send creates and sends a matrix notification with an entry
|
||||
func (c *Client) Send(entry model.NotifEntry) error {
|
||||
m, err := gomatrix.NewClient(c.cfg.HomeserverURL, "", "")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to initialize Matrix client")
|
||||
}
|
||||
defer m.Logout()
|
||||
|
||||
user, err := utl.GetSecret(c.cfg.User, c.cfg.UserFile)
|
||||
if err != nil {
|
||||
return errors.New("Cannot retrieve username secret for Matrix notifier")
|
||||
}
|
||||
password, err := utl.GetSecret(c.cfg.Password, c.cfg.PasswordFile)
|
||||
if err != nil {
|
||||
return errors.New("Cannot retrieve password secret for Matrix notifier")
|
||||
}
|
||||
|
||||
r, err := m.Login(&gomatrix.ReqLogin{
|
||||
Type: "m.login.password",
|
||||
User: user,
|
||||
Password: password,
|
||||
InitialDeviceDisplayName: c.meta.Name,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to authenticate Matrix user")
|
||||
}
|
||||
m.SetCredentials(r.UserID, r.AccessToken)
|
||||
|
||||
joined, err := m.JoinRoom(c.cfg.RoomID, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to join room")
|
||||
}
|
||||
|
||||
c.meta.Hostname = "myserver"
|
||||
|
||||
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 msgBuf bytes.Buffer
|
||||
msgTpl := template.Must(template.New("text").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 {{ .Meta.Hostname }}.", tagTpl)))
|
||||
if err := msgTpl.Execute(&msgBuf, struct {
|
||||
Meta model.Meta
|
||||
Entry model.NotifEntry
|
||||
}{
|
||||
Meta: c.meta,
|
||||
Entry: entry,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msgHTML := bluemonday.UGCPolicy().SanitizeBytes(
|
||||
blackfriday.Run(msgBuf.Bytes()),
|
||||
)
|
||||
|
||||
if _, err := m.SendMessageEvent(joined.RoomID, "m.room.message", gomatrix.HTMLMessage{
|
||||
Body: msgBuf.String(),
|
||||
MsgType: "m.notice",
|
||||
Format: "org.matrix.custom.html",
|
||||
FormattedBody: string(msgHTML),
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "failed to submit message to Matrix")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -93,6 +93,7 @@ nav:
|
|||
- Discord: notif/discord.md
|
||||
- Gotify: notif/gotify.md
|
||||
- Mail: notif/mail.md
|
||||
- Matrix: notif/matrix.md
|
||||
- Rocket.Chat: notif/rocketchat.md
|
||||
- Script: notif/script.md
|
||||
- Slack: notif/slack.md
|
||||
|
|
Loading…
Add table
Reference in a new issue