diff --git a/README.md b/README.md
index 4d4309e3..d7392c9f 100644
--- a/README.md
+++ b/README.md
@@ -27,12 +27,14 @@ a Docker registry.
Documentation can be found on https://crazymax.dev/diun/
-## How can I help?
+## Contributing
-All kinds of contributions are welcome :raised_hands:! The most basic way to show your support is to star :star2: the
-project, or to raise issues :speech_balloon: You can also support this project by
-[**becoming a sponsor on GitHub**](https://github.com/sponsors/crazy-max) :clap: or by making a
-[Paypal donation](https://www.paypal.me/crazyws) to ensure this journey continues indefinitely! :rocket:
+Want to contribute? Awesome! The most basic way to show your support is to star :star2: the project,
+or to raise issues :speech_balloon:. If you want to open a pull request, please read the
+[contributing guidelines](.github/CONTRIBUTING.md).
+
+You can also support this project by [**becoming a sponsor on GitHub**](https://github.com/sponsors/crazy-max) or by
+making a [Paypal donation](https://www.paypal.me/crazyws) to ensure this journey continues indefinitely!
Thanks again for your support, it is much appreciated! :pray:
diff --git a/docs/_overrides/main.html b/docs/_overrides/main.html
index 9d90a811..ec3ec0eb 100644
--- a/docs/_overrides/main.html
+++ b/docs/_overrides/main.html
@@ -10,48 +10,48 @@
{% set assets = config.site_url ~ 'assets' %}
{% block extrahead %}
-
-
+
+
-
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
{% endblock %}
diff --git a/docs/contributing.md b/docs/contributing.md
index 1e088ee7..199ce887 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -3,18 +3,18 @@
Hi there! I'm thrilled that you'd like to contribute to this project. Your help is essential for keeping it great.
Contributions to this project are [released](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license)
-to the public under the [project's open source license]({{ config.repo_url }}/blob/master/LICENSE).
+to the public under the [project's open source license]([[ config.repo_url ]]/blob/master/LICENSE).
## Submitting a pull request
-1. [Fork]({{ config.repo_url }}fork) and clone the repository
+1. [Fork]([[ config.repo_url ]]fork) and clone the repository
2. Configure and install the dependencies: `go mod download`
3. Create a new branch: `git checkout -b my-branch-name`
4. Make your changes
5. Validate: `docker buildx bake validate`
6. Test your code: `docker buildx bake test`
7. Build the project: `docker buildx bake artifact-all image-all`
-8. Push to your fork and [submit a pull request]({{ config.repo_url }}compare)
+8. Push to your fork and [submit a pull request]([[ config.repo_url ]]compare)
9. Pat your self on the back and wait for your pull request to be reviewed and merged.
Here are a few things you can do that will increase the likelihood of your pull request being accepted:
diff --git a/docs/donate.md b/docs/donate.md
index 5a1c3cfc..4ed9e964 100644
--- a/docs/donate.md
+++ b/docs/donate.md
@@ -1,7 +1,7 @@
**Diun** :bell: is free and open source and always will be.
All kinds of contributions are welcome! The most basic way to show your support is to
-[star the project]({{ config.repo_url }}), or to raise issues.
+[star the project]([[ config.repo_url ]]), or to raise issues.
You can also support this project by [**becoming a sponsor on GitHub**](https://github.com/sponsors/crazy-max) or
by making a [Paypal donation](https://www.paypal.me/crazyws) to ensure this journey continues indefinitely!
diff --git a/docs/faq.md b/docs/faq.md
index 8b9f8d96..ac3cf6e9 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -26,6 +26,43 @@ Or within a container:
docker-compose exec diun diun notif test
```
+## Notification template
+
+The title and body of a notification message can be customized for each notifier through `templateTitle` and
+`templateBody` fields except for those rendering _JSON_ or _Env_ like [Amqp](notif/amqp.md),
+[MQTT](notif/mqtt.md), [Script](notif/script.md) and [Webhook](notif/webhook.md).
+
+Templating is supported with the following fields:
+
+| Key | Description |
+|----------------------------------|-------------|
+| `.Meta.ID` | App ID: `diun` |
+| `.Meta.Name` | App Name: `Diun` |
+| `.Meta.Desc` | App description: `Docker image update notifier` |
+| `.Meta.URL` | App repo URL: `https://github.com/crazy-max/diun` |
+| `.Meta.Logo` | App logo URL: `https://raw.githubusercontent.com/crazy-max/diun/master/.res/diun.png` |
+| `.Meta.Author` | App author: `CrazyMax` |
+| `.Meta.Version` | App version: `v4.19.0` |
+| `.Meta.UserAgent` | App user-agent used to talk with registries: `diun/4.19.0 go/1.16 Linux` |
+| `.Meta.Hostname` | Hostname |
+| `.Entry.Status` | Entry status. Can be `new`, `update`, `unchange`, `skip` or `error` |
+| `.Entry.Provider` | [Provider](config/providers.md) used |
+| `.Entry.Image` | Docker image name. e.g. `docker.io/crazymax/diun:latest` |
+| `.Entry.Image.Domain` | Docker image domain. e.g. `docker.io` |
+| `.Entry.Image.Path` | Docker image path. e.g. `crazymax/diun` |
+| `.Entry.Image.Tag` | Docker image tag. e.g. `latest` |
+| `.Entry.Image.Digest` | Docker image digest |
+| `.Entry.Image.HubLink` | Docker image hub link (if available). e.g. `https://hub.docker.com/r/crazymax/diun` |
+| `.Entry.Manifest.Name` | Manifest name. e.g. `docker.io/crazymax/diun` |
+| `.Entry.Manifest.Tag` | Manifest tag. e.g. `latest` |
+| `.Entry.Manifest.MIMEType` | Manifest MIME type. e.g. `application/vnd.docker.distribution.manifest.list.v2+json` |
+| `.Entry.Manifest.Digest` | Manifest digest |
+| `.Entry.Manifest.Created` | Manifest created date. e.g. `2021-06-20T12:23:56Z` |
+| `.Entry.Manifest.DockerVersion` | Version of Docker that was used to build the image. e.g. `20.10.7` |
+| `.Entry.Manifest.Labels` | Image labels |
+| `.Entry.Manifest.Layers` | Image layers |
+| `.Entry.Manifest.Platform` | Platform that the image is runs on. e.g. `linux/amd64` |
+
## Authentication against the registry
You can authenticate against the registry through the [`regopts` settings](config/regopts.md) or you can mount
diff --git a/docs/install/binary.md b/docs/install/binary.md
index da26e169..27bff058 100644
--- a/docs/install/binary.md
+++ b/docs/install/binary.md
@@ -2,27 +2,27 @@
## Download
-Diun binaries are available on [releases]({{ config.repo_url }}releases) page.
+Diun binaries are available on [releases]([[ config.repo_url ]]releases) page.
Choose the archive matching the destination platform:
-* [diun_{{ git.tag | trim('v') }}_darwin_arm64.tar.gz]({{ config.repo_url }}/releases/download/v{{ git.tag | trim('v') }}/diun_{{ git.tag | trim('v') }}_darwin_arm64.tar.gz)
-* [diun_{{ git.tag | trim('v') }}_darwin_x86_64.tar.gz]({{ config.repo_url }}/releases/download/v{{ git.tag | trim('v') }}/diun_{{ git.tag | trim('v') }}_darwin_x86_64.tar.gz)
-* [diun_{{ git.tag | trim('v') }}_linux_arm64.tar.gz]({{ config.repo_url }}/releases/download/v{{ git.tag | trim('v') }}/diun_{{ git.tag | trim('v') }}_linux_arm64.tar.gz)
-* [diun_{{ git.tag | trim('v') }}_linux_armv5.tar.gz]({{ config.repo_url }}/releases/download/v{{ git.tag | trim('v') }}/diun_{{ git.tag | trim('v') }}_linux_armv5.tar.gz)
-* [diun_{{ git.tag | trim('v') }}_linux_armv6.tar.gz]({{ config.repo_url }}/releases/download/v{{ git.tag | trim('v') }}/diun_{{ git.tag | trim('v') }}_linux_armv6.tar.gz)
-* [diun_{{ git.tag | trim('v') }}_linux_armv7.tar.gz]({{ config.repo_url }}/releases/download/v{{ git.tag | trim('v') }}/diun_{{ git.tag | trim('v') }}_linux_armv7.tar.gz)
-* [diun_{{ git.tag | trim('v') }}_linux_i386.tar.gz]({{ config.repo_url }}/releases/download/v{{ git.tag | trim('v') }}/diun_{{ git.tag | trim('v') }}_linux_i386.tar.gz)
-* [diun_{{ git.tag | trim('v') }}_linux_ppc64le.tar.gz]({{ config.repo_url }}/releases/download/v{{ git.tag | trim('v') }}/diun_{{ git.tag | trim('v') }}_linux_ppc64le.tar.gz)
-* [diun_{{ git.tag | trim('v') }}_linux_s390x.tar.gz]({{ config.repo_url }}/releases/download/v{{ git.tag | trim('v') }}/diun_{{ git.tag | trim('v') }}_linux_s390x.tar.gz)
-* [diun_{{ git.tag | trim('v') }}_linux_x86_64.tar.gz]({{ config.repo_url }}/releases/download/v{{ git.tag | trim('v') }}/diun_{{ git.tag | trim('v') }}_linux_x86_64.tar.gz)
-* [diun_{{ git.tag | trim('v') }}_windows_i386.zip]({{ config.repo_url }}/releases/download/v{{ git.tag | trim('v') }}/diun_{{ git.tag | trim('v') }}_windows_i386.zip)
-* [diun_{{ git.tag | trim('v') }}_windows_x86_64.zip]({{ config.repo_url }}/releases/download/v{{ git.tag | trim('v') }}/diun_{{ git.tag | trim('v') }}_windows_x86_64.zip)
+* [diun_[[ git.tag | trim('v') ]]_darwin_arm64.tar.gz]([[ config.repo_url ]]/releases/download/v[[ git.tag | trim('v') ]]/diun_[[ git.tag | trim('v') ]]_darwin_arm64.tar.gz)
+* [diun_[[ git.tag | trim('v') ]]_darwin_x86_64.tar.gz]([[ config.repo_url ]]/releases/download/v[[ git.tag | trim('v') ]]/diun_[[ git.tag | trim('v') ]]_darwin_x86_64.tar.gz)
+* [diun_[[ git.tag | trim('v') ]]_linux_arm64.tar.gz]([[ config.repo_url ]]/releases/download/v[[ git.tag | trim('v') ]]/diun_[[ git.tag | trim('v') ]]_linux_arm64.tar.gz)
+* [diun_[[ git.tag | trim('v') ]]_linux_armv5.tar.gz]([[ config.repo_url ]]/releases/download/v[[ git.tag | trim('v') ]]/diun_[[ git.tag | trim('v') ]]_linux_armv5.tar.gz)
+* [diun_[[ git.tag | trim('v') ]]_linux_armv6.tar.gz]([[ config.repo_url ]]/releases/download/v[[ git.tag | trim('v') ]]/diun_[[ git.tag | trim('v') ]]_linux_armv6.tar.gz)
+* [diun_[[ git.tag | trim('v') ]]_linux_armv7.tar.gz]([[ config.repo_url ]]/releases/download/v[[ git.tag | trim('v') ]]/diun_[[ git.tag | trim('v') ]]_linux_armv7.tar.gz)
+* [diun_[[ git.tag | trim('v') ]]_linux_i386.tar.gz]([[ config.repo_url ]]/releases/download/v[[ git.tag | trim('v') ]]/diun_[[ git.tag | trim('v') ]]_linux_i386.tar.gz)
+* [diun_[[ git.tag | trim('v') ]]_linux_ppc64le.tar.gz]([[ config.repo_url ]]/releases/download/v[[ git.tag | trim('v') ]]/diun_[[ git.tag | trim('v') ]]_linux_ppc64le.tar.gz)
+* [diun_[[ git.tag | trim('v') ]]_linux_s390x.tar.gz]([[ config.repo_url ]]/releases/download/v[[ git.tag | trim('v') ]]/diun_[[ git.tag | trim('v') ]]_linux_s390x.tar.gz)
+* [diun_[[ git.tag | trim('v') ]]_linux_x86_64.tar.gz]([[ config.repo_url ]]/releases/download/v[[ git.tag | trim('v') ]]/diun_[[ git.tag | trim('v') ]]_linux_x86_64.tar.gz)
+* [diun_[[ git.tag | trim('v') ]]_windows_i386.zip]([[ config.repo_url ]]/releases/download/v[[ git.tag | trim('v') ]]/diun_[[ git.tag | trim('v') ]]_windows_i386.zip)
+* [diun_[[ git.tag | trim('v') ]]_windows_x86_64.zip]([[ config.repo_url ]]/releases/download/v[[ git.tag | trim('v') ]]/diun_[[ git.tag | trim('v') ]]_windows_x86_64.zip)
And extract diun:
```shell
-wget -qO- {{ config.repo_url }}releases/download/v{{ git.tag | trim('v') }}/diun_{{ git.tag | trim('v') }}_linux_x86_64.tar.gz | tar -zxvf - diun
+wget -qO- [[ config.repo_url ]]releases/download/v[[ git.tag | trim('v') ]]/diun_[[ git.tag | trim('v') ]]_linux_x86_64.tar.gz | tar -zxvf - diun
```
After getting the binary, it can be tested with [`./diun --help`](../usage/command-line.md#global-options) command
diff --git a/docs/install/linux-service.md b/docs/install/linux-service.md
index 0a2cb250..51e0c09f 100644
--- a/docs/install/linux-service.md
+++ b/docs/install/linux-service.md
@@ -10,7 +10,7 @@ To create a new service, paste this content in `/etc/systemd/system/diun.service
```
[Unit]
Description=Diun
-Documentation={{ config.site_url }}
+Documentation=[[ config.site_url ]]
After=syslog.target
After=network.target
diff --git a/docs/notif/discord.md b/docs/notif/discord.md
index 5085383b..e08629a1 100644
--- a/docs/notif/discord.md
+++ b/docs/notif/discord.md
@@ -16,18 +16,37 @@ Allow to send notifications to your Discord channel.
- "<@125>"
- "<@&200>"
timeout: 10s
+ templateTitle: "{{ .Entry.Image }} released"
+ templateBody: |
+ Docker tag {{ .Entry.Image }} which you subscribed to through {{ .Entry.Provider }} provider has been released.
```
-| Name | Default | Description |
-|--------------------|---------------|---------------|
-| `webhookURL`[^1] | | Discord [incoming webhook URL](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) |
-| `mentions` | | List of users or roles to notify |
-| `timeout` | `10s` | Timeout specifies a time limit for the request to be made |
+| Name | Default | Description |
+|---------------------|---------------------------------------|---------------|
+| `webhookURL`[^1] | | Discord [incoming webhook URL](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) |
+| `mentions` | | List of users or roles to notify |
+| `timeout` | `10s` | Timeout specifies a time limit for the request to be made |
+| `templateTitle`[^1] | See [below](#default-templatetitle) | [Notification template](../faq.md#notification-template) for message title |
+| `templateBody`[^1] | See [below](#default-templatebody) | [Notification template](../faq.md#notification-template) for message body |
!!! abstract "Environment variables"
* `DIUN_NOTIF_DISCORD_WEBHOOKURL`
* `DIUN_NOTIF_DISCORD_MENTIONS` (comma separated)
* `DIUN_NOTIF_DISCORD_TIMEOUT`
+ * `DIUN_NOTIF_DISCORD_TEMPLATETITLE`
+ * `DIUN_NOTIF_DISCORD_TEMPLATEBODY`
+
+### Default `templateTitle`
+
+```
+[[ config.extra.template.defaultTitle ]]
+```
+
+### Default `templateBody`
+
+```
+[[ config.extra.template.defaultBody ]]
+```
## Sample
diff --git a/docs/notif/gotify.md b/docs/notif/gotify.md
index 47af8ae6..b2fe0ea1 100644
--- a/docs/notif/gotify.md
+++ b/docs/notif/gotify.md
@@ -12,15 +12,20 @@ Notifications can be sent using a [Gotify](https://gotify.net/) instance.
token: Token123456
priority: 1
timeout: 10s
+ templateTitle: "{{ .Entry.Image }} released"
+ templateBody: |
+ Docker tag {{ .Entry.Image }} which you subscribed to through {{ .Entry.Provider }} provider has been released.
```
-| Name | Default | Description |
-|--------------------|---------------|---------------|
-| `endpoint`[^1] | | Gotify base URL |
-| `token` | | Application token |
-| `tokenFile` | | Use content of secret file as application token if `token` not defined |
-| `priority` | `1` | The priority of the message |
-| `timeout` | `10s` | Timeout specifies a time limit for the request to be made |
+| Name | Default | Description |
+|---------------------|---------------------------------------|---------------|
+| `endpoint`[^1] | | Gotify base URL |
+| `token` | | Application token |
+| `tokenFile` | | Use content of secret file as application token if `token` not defined |
+| `priority` | `1` | The priority of the message |
+| `timeout` | `10s` | Timeout specifies a time limit for the request to be made |
+| `templateTitle`[^1] | See [below](#default-templatetitle) | [Notification template](../faq.md#notification-template) for message title |
+| `templateBody`[^1] | See [below](#default-templatebody) | [Notification template](../faq.md#notification-template) for message body |
!!! abstract "Environment variables"
* `DIUN_NOTIF_GOTIFY_ENDPOINT`
@@ -28,6 +33,20 @@ Notifications can be sent using a [Gotify](https://gotify.net/) instance.
* `DIUN_NOTIF_GOTIFY_TOKENFILE`
* `DIUN_NOTIF_GOTIFY_PRIORITY`
* `DIUN_NOTIF_GOTIFY_TIMEOUT`
+ * `DIUN_NOTIF_GOTIFY_TEMPLATETITLE`
+ * `DIUN_NOTIF_GOTIFY_TEMPLATEBODY`
+
+### Default `templateTitle`
+
+```
+[[ config.extra.template.defaultTitle ]]
+```
+
+### Default `templateBody`
+
+```
+[[ config.extra.template.defaultBody ]]
+```
## Sample
diff --git a/docs/notif/mail.md b/docs/notif/mail.md
index 539be533..dd4733b8 100644
--- a/docs/notif/mail.md
+++ b/docs/notif/mail.md
@@ -14,21 +14,26 @@ Notifications can be sent through SMTP.
insecureSkipVerify: false
from: diun@example.com
to: webmaster@example.com
+ templateTitle: "{{ .Entry.Image }} released"
+ templateBody: |
+ Docker tag {{ .Entry.Image }} which you subscribed to through {{ .Entry.Provider }} provider has been released.
```
-| Name | Default | Description |
-|-----------------------|---------------|---------------|
-| `host`[^1] | `localhost` | SMTP server host |
-| `port`[^1] | `25` | SMTP server port |
-| `ssl` | `false` | SSL defines whether an SSL connection is used. Should be false in most cases since the auth mechanism should use STARTTLS |
-| `insecureSkipVerify` | `false` | Controls whether a client verifies the server's certificate chain and hostname |
-| `localName` | `localhost` | Hostname sent to the SMTP server with the HELO command |
-| `username` | | SMTP username |
-| `usernameFile` | | Use content of secret file as SMTP username if `username` not defined |
-| `password` | | SMTP password |
-| `passwordFile` | | Use content of secret file as SMTP password if `password` not defined |
-| `from`[^1] | | Sender email address |
-| `to`[^1] | | Recipient email address |
+| Name | Default | Description |
+|-----------------------|--------------------------------------------|---------------|
+| `host`[^1] | `localhost` | SMTP server host |
+| `port`[^1] | `25` | SMTP server port |
+| `ssl` | `false` | SSL defines whether an SSL connection is used. Should be false in most cases since the auth mechanism should use STARTTLS |
+| `insecureSkipVerify` | `false` | Controls whether a client verifies the server's certificate chain and hostname |
+| `localName` | `localhost` | Hostname sent to the SMTP server with the HELO command |
+| `username` | | SMTP username |
+| `usernameFile` | | Use content of secret file as SMTP username if `username` not defined |
+| `password` | | SMTP password |
+| `passwordFile` | | Use content of secret file as SMTP password if `password` not defined |
+| `from`[^1] | | Sender email address |
+| `to`[^1] | | Recipient email address |
+| `templateTitle`[^1] | See [below](#default-templatetitle) | [Notification template](../faq.md#notification-template) for message title |
+| `templateBody`[^1] | See [below](#default-templatebody) | [Notification template](../faq.md#notification-template) for message body |
!!! abstract "Environment variables"
* `DIUN_NOTIF_MAIL_HOST`
@@ -42,6 +47,28 @@ Notifications can be sent through SMTP.
* `DIUN_NOTIF_MAIL_PASSWORDFILE`
* `DIUN_NOTIF_MAIL_FROM`
* `DIUN_NOTIF_MAIL_TO`
+ * `DIUN_NOTIF_MAIL_TEMPLATETITLE`
+ * `DIUN_NOTIF_MAIL_TEMPLATEBODY`
+
+### Default `templateTitle`
+
+```
+[[ config.extra.template.defaultTitle ]]
+```
+
+### Default `templateBody`
+
+```
+Docker tag {{ if .Entry.Image.HubLink }}[**{{ .Entry.Image }}**]({{ .Entry.Image.HubLink }}){{ else }}**{{ .Entry.Image }}**{{ end }}
+which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }}
+on {{ .Meta.Hostname }}.
+
+This image has been {{ if (eq .Entry.Status "new") }}created{{ else }}updated{{ end }} at
+{{ .Entry.Manifest.Created.Format "Jan 02, 2006 15:04:05 UTC" }} with digest {{ .Entry.Manifest.Digest }}
+for {{ .Entry.Manifest.Platform }} platform.
+
+Need help, or have questions? Go to {{ .Meta.URL }} and leave an issue.
+```
## Sample
diff --git a/docs/notif/matrix.md b/docs/notif/matrix.md
index bdda9525..26488784 100644
--- a/docs/notif/matrix.md
+++ b/docs/notif/matrix.md
@@ -13,17 +13,20 @@ Allow to send notifications to your Matrix server.
password: bar
roomID: "!abcdefGHIjklmno:matrix.org"
msgType: notice
+ templateBody: |
+ Docker tag {{ .Entry.Image }} which you subscribed to through {{ .Entry.Provider }} provider has been released.
```
-| Name | Default | Description |
-|-----------------------|------------------------|-------------------|
-| `homeserverURL` | `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` | | Room ID to send messages |
-| `msgType` | `notice` | Type of message being sent. Can be `notice` or `text` |
+| Name | Default | Description |
+|-----------------------|--------------------------------------------|-------------------|
+| `homeserverURL` | `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` | | Room ID to send messages |
+| `msgType` | `notice` | Type of message being sent. Can be `notice` or `text` |
+| `templateBody`[^1] | See [below](#default-templatebody) | [Notification template](../faq.md#notification-template) for message body |
!!! abstract "Environment variables"
* `DIUN_NOTIF_MATRIX_HOMESERVERURL`
@@ -33,6 +36,13 @@ Allow to send notifications to your Matrix server.
* `DIUN_NOTIF_MATRIX_PASSWORDFILE`
* `DIUN_NOTIF_MATRIX_ROOMID`
* `DIUN_NOTIF_MATRIX_MSGTYPE`
+ * `DIUN_NOTIF_MATRIX_TEMPLATEBODY`
+
+### Default `templateBody`
+
+```
+[[ config.extra.template.defaultBody ]]
+```
## Sample
diff --git a/docs/notif/pushover.md b/docs/notif/pushover.md
index 0a7f2e6f..56d57752 100644
--- a/docs/notif/pushover.md
+++ b/docs/notif/pushover.md
@@ -10,20 +10,39 @@ You can send notifications using [Pushover](https://pushover.net/).
pushover:
token: uQiRzpo4DXghDmr9QzzfQu27cmVRsG
recipient: gznej3rKEVAvPUxu9vvNnqpmZpokzF
+ templateTitle: "{{ .Entry.Image }} released"
+ templateBody: |
+ Docker tag {{ .Entry.Image }} which you subscribed to through {{ .Entry.Provider }} provider has been released.
```
-| Name | Default | Description |
-|--------------------|---------------|---------------|
-| `token` | | Pushover [application/API token](https://pushover.net/api#registration) |
-| `tokenFile` | | Use content of secret file as Pushover application/API token if `token` not defined |
-| `recipient` | | User key to send notification to |
-| `recipientFile` | | Use content of secret file as User key if `recipient` not defined |
+| Name | Default | Description |
+|---------------------|--------------------------------------------|---------------|
+| `token` | | Pushover [application/API token](https://pushover.net/api#registration) |
+| `tokenFile` | | Use content of secret file as Pushover application/API token if `token` not defined |
+| `recipient` | | User key to send notification to |
+| `recipientFile` | | Use content of secret file as User key if `recipient` not defined |
+| `templateTitle`[^1] | See [below](#default-templatetitle) | [Notification template](../faq.md#notification-template) for message title |
+| `templateBody`[^1] | See [below](#default-templatebody) | [Notification template](../faq.md#notification-template) for message body |
!!! abstract "Environment variables"
* `DIUN_NOTIF_PUSHOVER_TOKEN`
* `DIUN_NOTIF_PUSHOVER_TOKENFILE`
* `DIUN_NOTIF_PUSHOVER_RECIPIENT`
* `DIUN_NOTIF_PUSHOVER_RECIPIENTFILE`
+ * `DIUN_NOTIF_PUSHOVER_TEMPLATETITLE`
+ * `DIUN_NOTIF_PUSHOVER_TEMPLATEBODY`
+
+### Default `templateTitle`
+
+```
+[[ config.extra.template.defaultTitle ]]
+```
+
+### Default `templateBody`
+
+```
+[[ config.extra.template.defaultBody ]]
+```
## Sample
diff --git a/docs/notif/rocketchat.md b/docs/notif/rocketchat.md
index 5fd44baf..591d3908 100644
--- a/docs/notif/rocketchat.md
+++ b/docs/notif/rocketchat.md
@@ -13,16 +13,21 @@ Allow to send notifications to your Rocket.Chat channel.
userID: abcdEFGH012345678
token: Token123456
timeout: 10s
+ templateTitle: "{{ .Entry.Image }} released"
+ templateBody: |
+ Docker tag {{ .Entry.Image }} which you subscribed to through {{ .Entry.Provider }} provider has been released.
```
-| Name | Default | Description |
-|--------------------|---------------|---------------|
-| `endpoint`[^1] | | Rocket.Chat base URL |
-| `channel`[^1] | | Channel name with the prefix in front of it |
-| `userID`[^1] | | User ID |
-| `token` | | Authentication token |
-| `tokenFile` | | Use content of secret file as authentication token if `token` not defined |
-| `timeout` | `10s` | Timeout specifies a time limit for the request to be made |
+| Name | Default | Description |
+|---------------------|--------------------------------------------|---------------|
+| `endpoint`[^1] | | Rocket.Chat base URL |
+| `channel`[^1] | | Channel name with the prefix in front of it |
+| `userID`[^1] | | User ID |
+| `token` | | Authentication token |
+| `tokenFile` | | Use content of secret file as authentication token if `token` not defined |
+| `timeout` | `10s` | Timeout specifies a time limit for the request to be made |
+| `templateTitle`[^1] | See [below](#default-templatetitle) | [Notification template](../faq.md#notification-template) for message title |
+| `templateBody`[^1] | See [below](#default-templatebody) | [Notification template](../faq.md#notification-template) for message body |
!!! warning
You must first create a _Personal Access Token_ through your account settings on your Rocket.Chat instance.
@@ -34,6 +39,20 @@ Allow to send notifications to your Rocket.Chat channel.
* `DIUN_NOTIF_ROCKETCHAT_TOKEN`
* `DIUN_NOTIF_ROCKETCHAT_TOKENFILE`
* `DIUN_NOTIF_ROCKETCHAT_TIMEOUT`
+ * `DIUN_NOTIF_ROCKETCHAT_TEMPLATETITLE`
+ * `DIUN_NOTIF_ROCKETCHAT_TEMPLATEBODY`
+
+### Default `templateTitle`
+
+```
+[[ config.extra.template.defaultTitle ]]
+```
+
+### Default `templateBody`
+
+```
+Docker tag {{ .Entry.Image }} which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }} on {{ .Meta.Hostname }}.
+```
## Sample
diff --git a/docs/notif/slack.md b/docs/notif/slack.md
index c8513c59..f76fdabc 100644
--- a/docs/notif/slack.md
+++ b/docs/notif/slack.md
@@ -12,14 +12,24 @@ You can send notifications to your Slack channel using an [incoming webhook URL]
notif:
slack:
webhookURL: https://hooks.slack.com/services/ABCD12EFG/HIJK34LMN/01234567890abcdefghij
+ templateBody: |
+ Docker tag {{ .Entry.Image }} which you subscribed to through {{ .Entry.Provider }} provider has been released.
```
-| Name | Default | Description |
-|--------------------|---------------|---------------|
-| `webhookURL`[^1] | | Slack [incoming webhook URL](https://api.slack.com/messaging/webhooks) |
+| Name | Default | Description |
+|--------------------|--------------------------------------------|---------------|
+| `webhookURL`[^1] | | Slack [incoming webhook URL](https://api.slack.com/messaging/webhooks) |
+| `templateBody`[^1] | See [below](#default-templatebody) | [Notification template](../faq.md#notification-template) for message body |
!!! abstract "Environment variables"
* `DIUN_NOTIF_SLACK_WEBHOOKURL`
+ * `DIUN_NOTIF_SLACK_TEMPLATEBODY`
+
+### Default `templateBody`
+
+```
+ Docker tag `{{ .Entry.Image }}` {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }}.
+```
## Sample
diff --git a/docs/notif/teams.md b/docs/notif/teams.md
index 9c418e76..089c473c 100644
--- a/docs/notif/teams.md
+++ b/docs/notif/teams.md
@@ -9,14 +9,24 @@ You can send notifications to your Teams team-channel using an [incoming webhook
notif:
teams:
webhookURL: https://outlook.office.com/webhook/ABCD12EFG/HIJK34LMN/01234567890abcdefghij
+ templateBody: |
+ Docker tag {{ .Entry.Image }} which you subscribed to through {{ .Entry.Provider }} provider has been released.
```
-| Name | Default | Description |
-|--------------------|---------------|---------------|
-| `webhookURL`[^1] | | Teams [incoming webhook URL](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/what-are-webhooks-and-connectors) |
+| Name | Default | Description |
+|--------------------|--------------------------------------------|---------------|
+| `webhookURL`[^1] | | Teams [incoming webhook URL](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/what-are-webhooks-and-connectors) |
+| `templateBody`[^1] | See [below](#default-templatebody) | [Notification template](../faq.md#notification-template) for message body |
!!! abstract "Environment variables"
* `DIUN_NOTIF_TEAMS_WEBHOOKURL`
+ * `DIUN_NOTIF_TEAMS_TEMPLATEBODY`
+
+### Default `templateBody`
+
+```
+Docker tag {{ if .Entry.Image.HubLink }}[`{{ .Entry.Image }}`]({{ .Entry.Image.HubLink }}){{ else }}`{{ .Entry.Image }}`{{ end }}{{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }}.
+```
## Sample
diff --git a/docs/notif/telegram.md b/docs/notif/telegram.md
index 46f49e56..c68cbda9 100644
--- a/docs/notif/telegram.md
+++ b/docs/notif/telegram.md
@@ -17,24 +17,37 @@ Multiple chat IDs can be provided in order to deliver notifications to multiple
chatIDs:
- 123456789
- 987654321
+ templateBody: |
+ Docker tag {{ .Entry.Image }} which you subscribed to through {{ .Entry.Provider }} provider has been released.
```
-| Name | Default | Description |
-|--------------------|---------------|---------------|
-| `token` | | Telegram bot token |
-| `tokenFile` | | Use content of secret file as Telegram bot token if `token` not defined |
-| `chatIDs` | | List of chat IDs to send notifications to |
-| `chatIDsFile` | | Use content of secret file as chat IDs if `chatIDs` not defined |
+| Name | Default | Description |
+|--------------------|--------------------------------------------|---------------|
+| `token` | | Telegram bot token |
+| `tokenFile` | | Use content of secret file as Telegram bot token if `token` not defined |
+| `chatIDs` | | List of chat IDs to send notifications to |
+| `chatIDsFile` | | Use content of secret file as chat IDs if `chatIDs` not defined |
+| `templateBody`[^1] | See [below](#default-templatebody) | [Notification template](../faq.md#notification-template) for message body |
!!! abstract "Environment variables"
* `DIUN_NOTIF_TELEGRAM_TOKEN`
* `DIUN_NOTIF_TELEGRAM_TOKENFILE`
* `DIUN_NOTIF_TELEGRAM_CHATIDS` (comma separated)
* `DIUN_NOTIF_TELEGRAM_CHATIDSFILE`
+ * `DIUN_NOTIF_TELEGRAM_TEMPLATEBODY`
!!! example "chat IDs secret file"
Chat IDs secret file must be a valid JSON array like: `[123456789,987654321]`
+### Default `templateBody`
+
+```
+Docker tag {{ if .Entry.Image.HubLink }}[{{ .Entry.Image }}]({{ .Entry.Image.HubLink }}){{ else }}{{ .Entry.Image }}{{ end }} which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }} on {{ escapeMarkdown .Meta.Hostname }}.
+```
+
+!!! note
+ `escapeMarkdown` is a special function to deal with a [makrdown strict parsing issue](https://github.com/crazy-max/diun/issues/162#issuecomment-683095898) on Telegram server.
+
## Sample

diff --git a/docs/reporting-issue.md b/docs/reporting-issue.md
index 3764fdce..4265a2a8 100644
--- a/docs/reporting-issue.md
+++ b/docs/reporting-issue.md
@@ -4,7 +4,7 @@
First, [be a good guy](https://github.com/kossnocorp/etiquette/blob/master/README.md).
-Please do a search in [open issues]({{ config.repo_url }}issues?utf8=%E2%9C%93&q=) to see if the issue or feature request has already been filed and read the [FAQ](faq.md) page first.
+Please do a search in [open issues]([[ config.repo_url ]]issues?utf8=%E2%9C%93&q=) to see if the issue or feature request has already been filed and read the [FAQ](faq.md) page first.
If you find your issue already exists, make relevant comments and add your [reaction](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments). Use a reaction in place of a "+1" comment.
@@ -23,7 +23,7 @@ File a single issue per problem and feature request.
The more information you can provide, the more likely someone will be successful reproducing the issue and finding a fix.
-You are now ready to [create a new issue]({{ config.repo_url }}issues/new/choose)!
+You are now ready to [create a new issue]([[ config.repo_url ]]issues/new/choose)!
## Closure policy
diff --git a/internal/config/config_test.go b/internal/config/config_test.go
index 3314ea29..66a9b371 100644
--- a/internal/config/config_test.go
+++ b/internal/config/config_test.go
@@ -76,13 +76,17 @@ func TestLoadFile(t *testing.T) {
"<@125>",
"<@&200>",
},
- Timeout: utl.NewDuration(10 * time.Second),
+ Timeout: utl.NewDuration(10 * time.Second),
+ TemplateTitle: model.NotifDefaultTemplateTitle,
+ TemplateBody: model.NotifDefaultTemplateBody,
},
Gotify: &model.NotifGotify{
- Endpoint: "http://gotify.foo.com",
- Token: "Token123456",
- Priority: 1,
- Timeout: utl.NewDuration(10 * time.Second),
+ Endpoint: "http://gotify.foo.com",
+ Token: "Token123456",
+ Priority: 1,
+ Timeout: utl.NewDuration(10 * time.Second),
+ TemplateTitle: model.NotifDefaultTemplateTitle,
+ TemplateBody: model.NotifDefaultTemplateBody,
},
Mail: &model.NotifMail{
Host: "localhost",
@@ -92,6 +96,14 @@ func TestLoadFile(t *testing.T) {
LocalName: "localhost",
From: "diun@example.com",
To: "webmaster@example.com",
+ TemplateTitle: model.NotifDefaultTemplateTitle,
+ TemplateBody: `Docker tag {{ if .Entry.Image.HubLink }}[**{{ .Entry.Image }}**]({{ .Entry.Image.HubLink }}){{ else }}**{{ .Entry.Image }}**{{ end }}
+which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }}.
+
+This image has been {{ if (eq .Entry.Status "new") }}created{{ else }}updated{{ end }} at
+{{ .Entry.Manifest.Created.Format "Jan 02, 2006 15:04:05 UTC" }} with digest {{ .Entry.Manifest.Digest }}
+for {{ .Entry.Manifest.Platform }} platform.
+`,
},
Matrix: &model.NotifMatrix{
HomeserverURL: "https://matrix.org",
@@ -99,6 +111,7 @@ func TestLoadFile(t *testing.T) {
Password: "bar",
RoomID: "!abcdefGHIjklmno:matrix.org",
MsgType: model.NotifMatrixMsgTypeNotice,
+ TemplateBody: model.NotifDefaultTemplateBody,
},
Mqtt: &model.NotifMqtt{
Scheme: "mqtt",
@@ -111,15 +124,19 @@ func TestLoadFile(t *testing.T) {
QoS: 0,
},
Pushover: &model.NotifPushover{
- Token: "uQiRzpo4DXghDmr9QzzfQu27cmVRsG",
- Recipient: "gznej3rKEVAvPUxu9vvNnqpmZpokzF",
+ Token: "uQiRzpo4DXghDmr9QzzfQu27cmVRsG",
+ Recipient: "gznej3rKEVAvPUxu9vvNnqpmZpokzF",
+ TemplateTitle: model.NotifDefaultTemplateTitle,
+ TemplateBody: model.NotifDefaultTemplateBody,
},
RocketChat: &model.NotifRocketChat{
- Endpoint: "http://rocket.foo.com:3000",
- Channel: "#general",
- UserID: "abcdEFGH012345678",
- Token: "Token123456",
- Timeout: utl.NewDuration(10 * time.Second),
+ Endpoint: "http://rocket.foo.com:3000",
+ Channel: "#general",
+ UserID: "abcdEFGH012345678",
+ Token: "Token123456",
+ Timeout: utl.NewDuration(10 * time.Second),
+ TemplateTitle: model.NotifDefaultTemplateTitle,
+ TemplateBody: model.NotifRocketChatDefaultTemplateBody,
},
Script: &model.NotifScript{
Cmd: "uname",
@@ -128,14 +145,17 @@ func TestLoadFile(t *testing.T) {
},
},
Slack: &model.NotifSlack{
- WebhookURL: "https://hooks.slack.com/services/ABCD12EFG/HIJK34LMN/01234567890abcdefghij",
+ WebhookURL: "https://hooks.slack.com/services/ABCD12EFG/HIJK34LMN/01234567890abcdefghij",
+ TemplateBody: model.NotifSlackDefaultTemplateBody,
},
Teams: &model.NotifTeams{
- WebhookURL: "https://outlook.office.com/webhook/ABCD12EFG/HIJK34LMN/01234567890abcdefghij",
+ WebhookURL: "https://outlook.office.com/webhook/ABCD12EFG/HIJK34LMN/01234567890abcdefghij",
+ TemplateBody: model.NotifTeamsDefaultTemplateBody,
},
Telegram: &model.NotifTelegram{
- Token: "abcdef123456",
- ChatIDs: []int64{8547439, 1234567},
+ Token: "abcdef123456",
+ ChatIDs: []int64{8547439, 1234567},
+ TemplateBody: model.NotifTelegramDefaultTemplateBody,
},
Webhook: &model.NotifWebhook{
Endpoint: "http://webhook.foo.com/sd54qad89azd5a",
@@ -291,8 +311,9 @@ func TestLoadEnv(t *testing.T) {
Watch: (&model.Watch{}).GetDefaults(),
Notif: &model.Notif{
Telegram: &model.NotifTelegram{
- Token: "abcdef123456",
- ChatIDs: []int64{8547439, 1234567},
+ Token: "abcdef123456",
+ ChatIDs: []int64{8547439, 1234567},
+ TemplateBody: model.NotifTelegramDefaultTemplateBody,
},
},
Providers: &model.Providers{
@@ -398,6 +419,14 @@ func TestLoadMixed(t *testing.T) {
LocalName: "foo.com",
From: "diun@foo.com",
To: "webmaster@foo.com",
+ TemplateTitle: model.NotifDefaultTemplateTitle,
+ TemplateBody: `Docker tag {{ if .Entry.Image.HubLink }}[**{{ .Entry.Image }}**]({{ .Entry.Image.HubLink }}){{ else }}**{{ .Entry.Image }}**{{ end }}
+which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }}.
+
+This image has been {{ if (eq .Entry.Status "new") }}created{{ else }}updated{{ end }} at
+{{ .Entry.Manifest.Created.Format "Jan 02, 2006 15:04:05 UTC" }} with digest {{ .Entry.Manifest.Digest }}
+for {{ .Entry.Manifest.Platform }} platform.
+`,
},
},
RegOpts: nil,
diff --git a/internal/config/fixtures/config.docker.yml b/internal/config/fixtures/config.docker.yml
index 6922649a..633f2947 100644
--- a/internal/config/fixtures/config.docker.yml
+++ b/internal/config/fixtures/config.docker.yml
@@ -6,6 +6,13 @@ notif:
insecureSkipVerify: false
from: diun@example.com
to: webmaster@example.com
+ templateBody: |
+ Docker tag {{ if .Entry.Image.HubLink }}[**{{ .Entry.Image }}**]({{ .Entry.Image.HubLink }}){{ else }}**{{ .Entry.Image }}**{{ end }}
+ which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }}.
+
+ This image has been {{ if (eq .Entry.Status "new") }}created{{ else }}updated{{ end }} at
+ {{ .Entry.Manifest.Created.Format "Jan 02, 2006 15:04:05 UTC" }} with digest {{ .Entry.Manifest.Digest }}
+ for {{ .Entry.Manifest.Platform }} platform.
providers:
docker: {}
diff --git a/internal/config/fixtures/config.test.yml b/internal/config/fixtures/config.test.yml
index 17fb777b..092a6848 100644
--- a/internal/config/fixtures/config.test.yml
+++ b/internal/config/fixtures/config.test.yml
@@ -38,6 +38,13 @@ notif:
insecureSkipVerify: false
from: diun@example.com
to: webmaster@example.com
+ templateBody: |
+ Docker tag {{ if .Entry.Image.HubLink }}[**{{ .Entry.Image }}**]({{ .Entry.Image.HubLink }}){{ else }}**{{ .Entry.Image }}**{{ end }}
+ which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }}.
+
+ This image has been {{ if (eq .Entry.Status "new") }}created{{ else }}updated{{ end }} at
+ {{ .Entry.Manifest.Created.Format "Jan 02, 2006 15:04:05 UTC" }} with digest {{ .Entry.Manifest.Digest }}
+ for {{ .Entry.Manifest.Platform }} platform.
matrix:
homeserverURL: https://matrix.org
user: "@foo:matrix.org"
diff --git a/internal/config/fixtures/config.validate.yml b/internal/config/fixtures/config.validate.yml
index c631d0b9..f7bbe2b5 100644
--- a/internal/config/fixtures/config.validate.yml
+++ b/internal/config/fixtures/config.validate.yml
@@ -38,6 +38,13 @@ notif:
insecureSkipVerify: false
from: diun@example.com
to: webmaster@example.com
+ templateBody: |
+ Docker tag {{ if .Entry.Image.HubLink }}[**{{ .Entry.Image }}**]({{ .Entry.Image.HubLink }}){{ else }}**{{ .Entry.Image }}**{{ end }}
+ which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }}.
+
+ This image has been {{ if (eq .Entry.Status "new") }}created{{ else }}updated{{ end }} at
+ {{ .Entry.Manifest.Created.Format "Jan 02, 2006 15:04:05 UTC" }} with digest {{ .Entry.Manifest.Digest }}
+ for {{ .Entry.Manifest.Platform }} platform.
matrix:
homeserverURL: https://matrix.org
user: "@foo:matrix.org"
diff --git a/internal/model/notif.go b/internal/model/notif.go
index d8c7a705..f2ec4dfd 100644
--- a/internal/model/notif.go
+++ b/internal/model/notif.go
@@ -4,6 +4,12 @@ import (
"github.com/crazy-max/diun/v4/pkg/registry"
)
+// Defaults used for notification template
+const (
+ NotifDefaultTemplateTitle = `{{ if (eq .Entry.Status "new") }}New image {{ .Entry.Image }} has been added{{ else }}Image update for {{ .Entry.Image }}{{ end }}`
+ NotifDefaultTemplateBody = `Docker tag {{ if .Entry.Image.HubLink }}[**{{ .Entry.Image }}**]({{ .Entry.Image.HubLink }}){{ else }}**{{ .Entry.Image }}**{{ end }} which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }} on {{ .Meta.Hostname }}.`
+)
+
// NotifEntries represents a list of notification entries
type NotifEntries struct {
Entries []NotifEntry
diff --git a/internal/model/notif_discord.go b/internal/model/notif_discord.go
index f3a395d7..b2e18dfd 100644
--- a/internal/model/notif_discord.go
+++ b/internal/model/notif_discord.go
@@ -8,9 +8,11 @@ import (
// NotifDiscord holds Discord notification configuration details
type NotifDiscord struct {
- WebhookURL string `yaml:"webhookURL,omitempty" json:"webhookURL,omitempty" validate:"required"`
- Mentions []string `yaml:"mentions,omitempty" json:"mentions,omitempty"`
- Timeout *time.Duration `yaml:"timeout,omitempty" json:"timeout,omitempty" validate:"required"`
+ WebhookURL string `yaml:"webhookURL,omitempty" json:"webhookURL,omitempty" validate:"required"`
+ Mentions []string `yaml:"mentions,omitempty" json:"mentions,omitempty"`
+ Timeout *time.Duration `yaml:"timeout,omitempty" json:"timeout,omitempty" validate:"required"`
+ TemplateTitle string `yaml:"templateTitle,omitempty" json:"templateTitle,omitempty" validate:"required"`
+ TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"`
}
// GetDefaults gets the default values
@@ -23,4 +25,6 @@ func (s *NotifDiscord) GetDefaults() *NotifDiscord {
// SetDefaults sets the default values
func (s *NotifDiscord) SetDefaults() {
s.Timeout = utl.NewDuration(10 * time.Second)
+ s.TemplateTitle = NotifDefaultTemplateTitle
+ s.TemplateBody = NotifDefaultTemplateBody
}
diff --git a/internal/model/notif_gotify.go b/internal/model/notif_gotify.go
index cb28ddaf..19bc7481 100644
--- a/internal/model/notif_gotify.go
+++ b/internal/model/notif_gotify.go
@@ -8,11 +8,13 @@ import (
// NotifGotify holds gotify notification configuration details
type NotifGotify struct {
- Endpoint string `yaml:"endpoint,omitempty" json:"endpoint,omitempty" validate:"required"`
- Token string `yaml:"token,omitempty" json:"token,omitempty" validate:"omitempty"`
- TokenFile string `yaml:"tokenFile,omitempty" json:"tokenFile,omitempty" validate:"omitempty,file"`
- Priority int `yaml:"priority,omitempty" json:"priority,omitempty" validate:"omitempty,min=0"`
- Timeout *time.Duration `yaml:"timeout,omitempty" json:"timeout,omitempty" validate:"required"`
+ Endpoint string `yaml:"endpoint,omitempty" json:"endpoint,omitempty" validate:"required"`
+ Token string `yaml:"token,omitempty" json:"token,omitempty" validate:"omitempty"`
+ TokenFile string `yaml:"tokenFile,omitempty" json:"tokenFile,omitempty" validate:"omitempty,file"`
+ Priority int `yaml:"priority,omitempty" json:"priority,omitempty" validate:"omitempty,min=0"`
+ Timeout *time.Duration `yaml:"timeout,omitempty" json:"timeout,omitempty" validate:"required"`
+ TemplateTitle string `yaml:"templateTitle,omitempty" json:"templateTitle,omitempty" validate:"required"`
+ TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"`
}
// GetDefaults gets the default values
@@ -26,4 +28,6 @@ func (s *NotifGotify) GetDefaults() *NotifGotify {
func (s *NotifGotify) SetDefaults() {
s.Priority = 1
s.Timeout = utl.NewDuration(10 * time.Second)
+ s.TemplateTitle = NotifDefaultTemplateTitle
+ s.TemplateBody = NotifDefaultTemplateBody
}
diff --git a/internal/model/notif_mail.go b/internal/model/notif_mail.go
index 72e61803..4447afaf 100644
--- a/internal/model/notif_mail.go
+++ b/internal/model/notif_mail.go
@@ -4,6 +4,17 @@ import (
"github.com/crazy-max/diun/v4/pkg/utl"
)
+// NotifMailDefaultTemplateBody ...
+const NotifMailDefaultTemplateBody = `Docker tag {{ if .Entry.Image.HubLink }}[**{{ .Entry.Image }}**]({{ .Entry.Image.HubLink }}){{ else }}**{{ .Entry.Image }}**{{ end }}
+which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }}
+on {{ .Meta.Hostname }}.
+
+This image has been {{ if (eq .Entry.Status "new") }}created{{ else }}updated{{ end }} at
+{{ .Entry.Manifest.Created.Format "Jan 02, 2006 15:04:05 UTC" }} with digest {{ .Entry.Manifest.Digest }}
+for {{ .Entry.Manifest.Platform }} platform.
+
+Need help, or have questions? Go to {{ .Meta.URL }} and leave an issue.`
+
// NotifMail holds mail notification configuration details
type NotifMail struct {
Host string `yaml:"host,omitempty" json:"host,omitempty" validate:"required"`
@@ -17,6 +28,8 @@ type NotifMail struct {
PasswordFile string `yaml:"passwordFile,omitempty" json:"passwordFile,omitempty" validate:"omitempty,file"`
From string `yaml:"from,omitempty" json:"from,omitempty" validate:"required,email"`
To string `yaml:"to,omitempty" json:"to,omitempty" validate:"required,email"`
+ TemplateTitle string `yaml:"templateTitle,omitempty" json:"templateTitle,omitempty" validate:"required"`
+ TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"`
}
// GetDefaults gets the default values
@@ -33,4 +46,6 @@ func (s *NotifMail) SetDefaults() {
s.SSL = utl.NewFalse()
s.InsecureSkipVerify = utl.NewFalse()
s.LocalName = "localhost"
+ s.TemplateTitle = NotifDefaultTemplateTitle
+ s.TemplateBody = NotifMailDefaultTemplateBody
}
diff --git a/internal/model/notif_matrix.go b/internal/model/notif_matrix.go
index 5357aa63..9fe935a1 100644
--- a/internal/model/notif_matrix.go
+++ b/internal/model/notif_matrix.go
@@ -9,6 +9,7 @@ type NotifMatrix struct {
PasswordFile string `yaml:"passwordFile,omitempty" json:"passwordFile,omitempty" validate:"omitempty,file"`
RoomID string `yaml:"roomID,omitempty" json:"roomID,omitempty" validate:"required"`
MsgType NotifMatrixMsgType `yaml:"msgType,omitempty" json:"msgType,omitempty" validate:"required,oneof=notice text"`
+ TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"`
}
// NotifMatrix message type constants
@@ -31,4 +32,5 @@ func (s *NotifMatrix) GetDefaults() *NotifMatrix {
func (s *NotifMatrix) SetDefaults() {
s.HomeserverURL = "https://matrix.org"
s.MsgType = NotifMatrixMsgTypeNotice
+ s.TemplateBody = NotifDefaultTemplateBody
}
diff --git a/internal/model/notif_pushover.go b/internal/model/notif_pushover.go
index 5b496966..df709fba 100644
--- a/internal/model/notif_pushover.go
+++ b/internal/model/notif_pushover.go
@@ -7,14 +7,19 @@ type NotifPushover struct {
Recipient string `yaml:"recipient,omitempty" json:"recipient,omitempty" validate:"omitempty"`
RecipientFile string `yaml:"recipientFile,omitempty" json:"recipientFile,omitempty" validate:"omitempty,file"`
Priority int `yaml:"priority,omitempty" json:"priority,omitempty" validate:"omitempty,min=-2,max=2"`
+ TemplateTitle string `yaml:"templateTitle,omitempty" json:"templateTitle,omitempty" validate:"required"`
+ TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"`
}
// GetDefaults gets the default values
func (s *NotifPushover) GetDefaults() *NotifPushover {
- return nil
+ n := &NotifPushover{}
+ n.SetDefaults()
+ return n
}
// SetDefaults sets the default values
func (s *NotifPushover) SetDefaults() {
- // noop
+ s.TemplateTitle = NotifDefaultTemplateTitle
+ s.TemplateBody = NotifDefaultTemplateBody
}
diff --git a/internal/model/notif_rocketchat.go b/internal/model/notif_rocketchat.go
index 71e7ee3c..36c7dc41 100644
--- a/internal/model/notif_rocketchat.go
+++ b/internal/model/notif_rocketchat.go
@@ -6,14 +6,19 @@ import (
"github.com/crazy-max/diun/v4/pkg/utl"
)
+// NotifRocketChatDefaultTemplateBody ...
+const NotifRocketChatDefaultTemplateBody = `Docker tag {{ .Entry.Image }} which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }} on {{ .Meta.Hostname }}.`
+
// NotifRocketChat holds Rocket.Chat notification configuration details
type NotifRocketChat struct {
- Endpoint string `yaml:"endpoint,omitempty" json:"endpoint,omitempty" validate:"required"`
- Channel string `yaml:"channel,omitempty" json:"channel,omitempty" validate:"required"`
- UserID string `yaml:"userID,omitempty" json:"userID,omitempty" validate:"required"`
- Token string `yaml:"token,omitempty" json:"token,omitempty" validate:"omitempty"`
- TokenFile string `yaml:"tokenFile,omitempty" json:"tokenFile,omitempty" validate:"omitempty,file"`
- Timeout *time.Duration `yaml:"timeout,omitempty" json:"timeout,omitempty" validate:"required"`
+ Endpoint string `yaml:"endpoint,omitempty" json:"endpoint,omitempty" validate:"required"`
+ Channel string `yaml:"channel,omitempty" json:"channel,omitempty" validate:"required"`
+ UserID string `yaml:"userID,omitempty" json:"userID,omitempty" validate:"required"`
+ Token string `yaml:"token,omitempty" json:"token,omitempty" validate:"omitempty"`
+ TokenFile string `yaml:"tokenFile,omitempty" json:"tokenFile,omitempty" validate:"omitempty,file"`
+ Timeout *time.Duration `yaml:"timeout,omitempty" json:"timeout,omitempty" validate:"required"`
+ TemplateTitle string `yaml:"templateTitle,omitempty" json:"templateTitle,omitempty" validate:"required"`
+ TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"`
}
// GetDefaults gets the default values
@@ -26,4 +31,6 @@ func (s *NotifRocketChat) GetDefaults() *NotifRocketChat {
// SetDefaults sets the default values
func (s *NotifRocketChat) SetDefaults() {
s.Timeout = utl.NewDuration(10 * time.Second)
+ s.TemplateTitle = NotifDefaultTemplateTitle
+ s.TemplateBody = NotifRocketChatDefaultTemplateBody
}
diff --git a/internal/model/notif_slack.go b/internal/model/notif_slack.go
index 4d2dd68a..fa998684 100644
--- a/internal/model/notif_slack.go
+++ b/internal/model/notif_slack.go
@@ -1,16 +1,22 @@
package model
+// NotifSlackDefaultTemplateBody ...
+const NotifSlackDefaultTemplateBody = " Docker tag `{{ .Entry.Image }}` {{ if (eq .Entry.Status \"new\") }}newly added{{ else }}updated{{ end }}."
+
// NotifSlack holds slack notification configuration details
type NotifSlack struct {
- WebhookURL string `yaml:"webhookURL,omitempty" json:"webhookURL,omitempty" validate:"required"`
+ WebhookURL string `yaml:"webhookURL,omitempty" json:"webhookURL,omitempty" validate:"required"`
+ TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"`
}
// GetDefaults gets the default values
func (s *NotifSlack) GetDefaults() *NotifSlack {
- return nil
+ n := &NotifSlack{}
+ n.SetDefaults()
+ return n
}
// SetDefaults sets the default values
func (s *NotifSlack) SetDefaults() {
- // noop
+ s.TemplateBody = NotifSlackDefaultTemplateBody
}
diff --git a/internal/model/notif_teams.go b/internal/model/notif_teams.go
index e2245308..81d93577 100644
--- a/internal/model/notif_teams.go
+++ b/internal/model/notif_teams.go
@@ -1,16 +1,22 @@
package model
+// NotifTeamsDefaultTemplateBody ...
+const NotifTeamsDefaultTemplateBody = "Docker tag {{ if .Entry.Image.HubLink }}[`{{ .Entry.Image }}`]({{ .Entry.Image.HubLink }}){{ else }}`{{ .Entry.Image }}`{{ end }}{{ if (eq .Entry.Status \"new\") }}newly added{{ else }}updated{{ end }}."
+
// NotifTeams holds Teams notification configuration details
type NotifTeams struct {
- WebhookURL string `yaml:"webhookURL,omitempty" json:"webhookURL,omitempty" validate:"required"`
+ WebhookURL string `yaml:"webhookURL,omitempty" json:"webhookURL,omitempty" validate:"required"`
+ TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"`
}
// GetDefaults gets the default values
func (s *NotifTeams) GetDefaults() *NotifTeams {
- return nil
+ n := &NotifTeams{}
+ n.SetDefaults()
+ return n
}
// SetDefaults sets the default values
func (s *NotifTeams) SetDefaults() {
- // noop
+ s.TemplateBody = NotifTeamsDefaultTemplateBody
}
diff --git a/internal/model/notif_telegram.go b/internal/model/notif_telegram.go
index 42fc7bf4..8ddf1a08 100644
--- a/internal/model/notif_telegram.go
+++ b/internal/model/notif_telegram.go
@@ -1,19 +1,25 @@
package model
+// NotifTelegramDefaultTemplateBody ...
+const NotifTelegramDefaultTemplateBody = `Docker tag {{ if .Entry.Image.HubLink }}[{{ .Entry.Image }}]({{ .Entry.Image.HubLink }}){{ else }}{{ .Entry.Image }}{{ end }} which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }} on {{ escapeMarkdown .Meta.Hostname }}.`
+
// NotifTelegram holds Telegram notification configuration details
type NotifTelegram struct {
- Token string `yaml:"token,omitempty" json:"token,omitempty" validate:"omitempty"`
- TokenFile string `yaml:"tokenFile,omitempty" json:"tokenFile,omitempty" validate:"omitempty,file"`
- ChatIDs []int64 `yaml:"chatIDs,omitempty" json:"chatIDs,omitempty" validate:"omitempty"`
- ChatIDsFile string `yaml:"chatIDsFile,omitempty" json:"chatIDsFile,omitempty" validate:"omitempty,file"`
+ Token string `yaml:"token,omitempty" json:"token,omitempty" validate:"omitempty"`
+ TokenFile string `yaml:"tokenFile,omitempty" json:"tokenFile,omitempty" validate:"omitempty,file"`
+ ChatIDs []int64 `yaml:"chatIDs,omitempty" json:"chatIDs,omitempty" validate:"omitempty"`
+ ChatIDsFile string `yaml:"chatIDsFile,omitempty" json:"chatIDsFile,omitempty" validate:"omitempty,file"`
+ TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"`
}
// GetDefaults gets the default values
func (s *NotifTelegram) GetDefaults() *NotifTelegram {
- return nil
+ n := &NotifTelegram{}
+ n.SetDefaults()
+ return n
}
// SetDefaults sets the default values
func (s *NotifTelegram) SetDefaults() {
- // noop
+ s.TemplateBody = NotifTelegramDefaultTemplateBody
}
diff --git a/internal/msg/client.go b/internal/msg/client.go
index af6e353b..76e33249 100644
--- a/internal/msg/client.go
+++ b/internal/msg/client.go
@@ -11,6 +11,7 @@ import (
"github.com/crazy-max/diun/v4/internal/model"
"github.com/microcosm-cc/bluemonday"
"github.com/opencontainers/go-digest"
+ "github.com/pkg/errors"
"github.com/russross/blackfriday/v2"
)
@@ -21,15 +22,13 @@ type Client struct {
// Options holds msg client object options
type Options struct {
- Meta model.Meta
- Entry model.NotifEntry
- TplFuncs template.FuncMap
+ Meta model.Meta
+ Entry model.NotifEntry
+ TemplateTitle string
+ TemplateBody string
+ TemplateFuncs template.FuncMap
}
-const defaultTpl = `Docker tag {{ if .Entry.Image.HubLink }}[**{{ .Entry.Image }}**]({{ .Entry.Image.HubLink }}){{ else }}**{{ .Entry.Image }}**{{ end }}
-which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }}
-on {{ .Meta.Hostname }}.`
-
// New initializes a new msg client
func New(opts Options) (*Client, error) {
return &Client{
@@ -38,47 +37,49 @@ func New(opts Options) (*Client, error) {
}
// RenderMarkdown returns a notification message as markdown
-func (c *Client) RenderMarkdown() (title string, text []byte, err error) {
- return c.RenderMarkdownTemplate(strings.ReplaceAll(defaultTpl, "\n", " "))
-}
-
-// RenderMarkdownTemplate returns a notification message as markdown with a custom template
-func (c *Client) RenderMarkdownTemplate(tpl string) (title string, text []byte, err error) {
- title = fmt.Sprintf("Image update for %s", c.opts.Entry.Image.String())
- if c.opts.Entry.Status == model.ImageStatusNew {
- title = fmt.Sprintf("New image %s has been added", c.opts.Entry.Image.String())
- }
-
- var msgBuf bytes.Buffer
- msgTpl := template.Must(template.New("notif").Funcs(c.opts.TplFuncs).Parse(tpl))
- err = msgTpl.Execute(&msgBuf, struct {
+func (c *Client) RenderMarkdown() (title []byte, body []byte, err error) {
+ var titleBuf bytes.Buffer
+ titleTpl := template.Must(template.New("title").Funcs(c.opts.TemplateFuncs).Parse(strings.TrimSuffix(strings.TrimSpace(c.opts.TemplateTitle), "\n")))
+ err = titleTpl.Execute(&titleBuf, struct {
Meta model.Meta
Entry model.NotifEntry
}{
Meta: c.opts.Meta,
Entry: c.opts.Entry,
})
+ if err != nil {
+ return title, body, errors.Wrap(err, "Cannot render notif title")
+ }
+ title = titleBuf.Bytes()
+
+ var bodyBuf bytes.Buffer
+ bodyTpl := template.Must(template.New("body").Funcs(c.opts.TemplateFuncs).Parse(strings.TrimSuffix(strings.TrimSpace(c.opts.TemplateBody), "\n")))
+ err = bodyTpl.Execute(&bodyBuf, struct {
+ Meta model.Meta
+ Entry model.NotifEntry
+ }{
+ Meta: c.opts.Meta,
+ Entry: c.opts.Entry,
+ })
+ if err != nil {
+ return title, body, errors.Wrap(err, "Cannot render notif body")
+ }
+ body = bodyBuf.Bytes()
- text = msgBuf.Bytes()
return
}
// RenderHTML returns a notification message as html
-func (c *Client) RenderHTML() (title string, text []byte, err error) {
- return c.RenderHTMLTemplate(strings.ReplaceAll(defaultTpl, "\n", " "))
-}
-
-// RenderHTMLTemplate returns a notification message as html with a custom template
-func (c *Client) RenderHTMLTemplate(tpl string) (title string, text []byte, err error) {
- title, text, err = c.RenderMarkdownTemplate(tpl)
+func (c *Client) RenderHTML() (title []byte, body []byte, err error) {
+ title, body, err = c.RenderMarkdown()
if err != nil {
- return
+ return title, body, err
}
- text = []byte(bluemonday.UGCPolicy().Sanitize(
+ body = []byte(bluemonday.UGCPolicy().Sanitize(
// Dirty way to remove wrapped
"), "
"), + strings.TrimRight(strings.TrimLeft(strings.TrimSpace(string(blackfriday.Run(body))), ""), "
"), )) return } diff --git a/internal/notif/discord/client.go b/internal/notif/discord/client.go index b7bb4fa0..0e777d77 100644 --- a/internal/notif/discord/client.go +++ b/internal/notif/discord/client.go @@ -45,14 +45,16 @@ func (c *Client) Send(entry model.NotifEntry) error { } message, err := msg.New(msg.Options{ - Meta: c.meta, - Entry: entry, + Meta: c.meta, + Entry: entry, + TemplateTitle: c.cfg.TemplateTitle, + TemplateBody: c.cfg.TemplateBody, }) if err != nil { return err } - title, text, err := message.RenderMarkdown() + title, body, err := message.RenderMarkdown() if err != nil { return err } @@ -62,7 +64,7 @@ func (c *Client) Send(entry model.NotifEntry) error { content.WriteString(fmt.Sprintf("%s ", mention)) } } - content.WriteString(title) + content.WriteString(string(title)) fields := []EmbedField{ { @@ -100,7 +102,7 @@ func (c *Client) Send(entry model.NotifEntry) error { AvatarURL: c.meta.Logo, Embeds: []Embed{ { - Description: string(text), + Description: string(body), 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, diff --git a/internal/notif/gotify/client.go b/internal/notif/gotify/client.go index 71717c11..46114123 100644 --- a/internal/notif/gotify/client.go +++ b/internal/notif/gotify/client.go @@ -50,26 +50,28 @@ func (c *Client) Send(entry model.NotifEntry) error { } message, err := msg.New(msg.Options{ - Meta: c.meta, - Entry: entry, + Meta: c.meta, + Entry: entry, + TemplateTitle: c.cfg.TemplateTitle, + TemplateBody: c.cfg.TemplateBody, }) if err != nil { return err } - title, text, err := message.RenderMarkdown() + title, body, err := message.RenderMarkdown() if err != nil { return err } - body, err := json.Marshal(struct { + jsonBody, err := json.Marshal(struct { Message string `json:"message"` Title string `json:"title"` Priority int `json:"priority"` Extras map[string]interface{} `json:"extras"` }{ - Message: string(text), - Title: title, + Message: string(body), + Title: string(title), Priority: c.cfg.Priority, Extras: map[string]interface{}{ "client::display": map[string]string{ @@ -91,13 +93,13 @@ func (c *Client) Send(entry model.NotifEntry) error { q.Set("token", token) u.RawQuery = q.Encode() - req, err := http.NewRequest("POST", u.String(), bytes.NewBuffer(body)) + req, err := http.NewRequest("POST", u.String(), bytes.NewBuffer(jsonBody)) if err != nil { return err } req.Header.Set("Content-Type", "application/json") - req.Header.Add("Content-Length", strconv.Itoa(len(string(body)))) + req.Header.Add("Content-Length", strconv.Itoa(len(string(jsonBody)))) req.Header.Set("User-Agent", c.meta.UserAgent) resp, err := hc.Do(req) diff --git a/internal/notif/mail/client.go b/internal/notif/mail/client.go index 506d8b49..332acd38 100644 --- a/internal/notif/mail/client.go +++ b/internal/notif/mail/client.go @@ -21,16 +21,6 @@ type Client struct { meta model.Meta } -const customTpl = `Docker tag {{ if .Entry.Image.HubLink }}[**{{ .Entry.Image }}**]({{ .Entry.Image.HubLink }}){{ else }}**{{ .Entry.Image }}**{{ end }} -which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }} -on {{ .Meta.Hostname }}. - -This image has been {{ if (eq .Entry.Status "new") }}created{{ else }}updated{{ end }} at -{{ .Entry.Manifest.Created.Format "Jan 02, 2006 15:04:05 UTC" }} with digest {{ .Entry.Manifest.Digest }}
-for {{ .Entry.Manifest.Platform }} platform.
-
-Need help, or have questions? Go to {{ .Meta.URL }} and leave an issue.`
-
// New creates a new mail notification instance
func New(config *model.NotifMail, meta model.Meta) notifier.Notifier {
return notifier.Notifier{
@@ -63,14 +53,16 @@ func (c *Client) Send(entry model.NotifEntry) error {
}
message, err := msg.New(msg.Options{
- Meta: c.meta,
- Entry: entry,
+ Meta: c.meta,
+ Entry: entry,
+ TemplateTitle: c.cfg.TemplateTitle,
+ TemplateBody: c.cfg.TemplateBody,
})
if err != nil {
return err
}
- title, text, err := message.RenderMarkdownTemplate(customTpl)
+ title, body, err := message.RenderMarkdown()
if err != nil {
return err
}
@@ -78,7 +70,7 @@ func (c *Client) Send(entry model.NotifEntry) error {
email := hermes.Email{
Body: hermes.Body{
Title: fmt.Sprintf("%s 🔔 notification", c.meta.Name),
- FreeMarkdown: hermes.Markdown(text),
+ FreeMarkdown: hermes.Markdown(body),
Signature: "Thanks for your support!",
},
}
@@ -95,12 +87,12 @@ func (c *Client) Send(entry model.NotifEntry) error {
return fmt.Errorf("hermes: %v", err)
}
- msg := gomail.NewMessage()
- msg.SetHeader("From", fmt.Sprintf("%s <%s>", c.meta.Name, c.cfg.From))
- msg.SetHeader("To", c.cfg.To)
- msg.SetHeader("Subject", title)
- msg.SetBody("text/plain", textpart)
- msg.AddAlternative("text/html", htmlpart)
+ mailMessage := gomail.NewMessage()
+ mailMessage.SetHeader("From", fmt.Sprintf("%s <%s>", c.meta.Name, c.cfg.From))
+ mailMessage.SetHeader("To", c.cfg.To)
+ mailMessage.SetHeader("Subject", string(title))
+ mailMessage.SetBody("text/plain", textpart)
+ mailMessage.AddAlternative("text/html", htmlpart)
var tlsConfig *tls.Config
if *c.cfg.InsecureSkipVerify {
@@ -128,5 +120,5 @@ func (c *Client) Send(entry model.NotifEntry) error {
LocalName: c.cfg.LocalName,
}
- return dialer.DialAndSend(msg)
+ return dialer.DialAndSend(mailMessage)
}
diff --git a/internal/notif/matrix/client.go b/internal/notif/matrix/client.go
index b11c54e0..9f121de1 100644
--- a/internal/notif/matrix/client.go
+++ b/internal/notif/matrix/client.go
@@ -72,8 +72,9 @@ func (c *Client) Send(entry model.NotifEntry) error {
}
message, err := msg.New(msg.Options{
- Meta: c.meta,
- Entry: entry,
+ Meta: c.meta,
+ Entry: entry,
+ TemplateBody: c.cfg.TemplateBody,
})
if err != nil {
return err
diff --git a/internal/notif/mqtt/client.go b/internal/notif/mqtt/client.go
index 1257f346..d3b55a76 100644
--- a/internal/notif/mqtt/client.go
+++ b/internal/notif/mqtt/client.go
@@ -8,8 +8,6 @@ import (
"github.com/crazy-max/diun/v4/internal/notif/notifier"
"github.com/crazy-max/diun/v4/pkg/utl"
MQTT "github.com/eclipse/paho.mqtt.golang"
- "github.com/rs/zerolog"
- "github.com/rs/zerolog/log"
)
// Client represents an active mqtt notification object
@@ -17,7 +15,6 @@ type Client struct {
*notifier.Notifier
cfg *model.NotifMqtt
meta model.Meta
- logger zerolog.Logger
mqttClient MQTT.Client
}
@@ -25,9 +22,8 @@ type Client struct {
func New(config *model.NotifMqtt, meta model.Meta) notifier.Notifier {
return notifier.Notifier{
Handler: &Client{
- cfg: config,
- meta: meta,
- logger: log.With().Str("notif", "mqtt").Logger(),
+ cfg: config,
+ meta: meta,
},
}
}
diff --git a/internal/notif/pushover/client.go b/internal/notif/pushover/client.go
index 16f55285..dd871bcf 100644
--- a/internal/notif/pushover/client.go
+++ b/internal/notif/pushover/client.go
@@ -46,21 +46,23 @@ func (c *Client) Send(entry model.NotifEntry) error {
}
message, err := msg.New(msg.Options{
- Meta: c.meta,
- Entry: entry,
+ Meta: c.meta,
+ Entry: entry,
+ TemplateTitle: c.cfg.TemplateTitle,
+ TemplateBody: c.cfg.TemplateBody,
})
if err != nil {
return err
}
- title, text, err := message.RenderHTML()
+ title, body, err := message.RenderHTML()
if err != nil {
return err
}
_, err = pushover.New(token).SendMessage(&pushover.Message{
- Message: string(text),
- Title: title,
+ Title: string(title),
+ Message: string(body),
Priority: c.cfg.Priority,
URL: c.meta.URL,
URLTitle: c.meta.Name,
diff --git a/internal/notif/rocketchat/client.go b/internal/notif/rocketchat/client.go
index 8b3f852c..d7beb63a 100644
--- a/internal/notif/rocketchat/client.go
+++ b/internal/notif/rocketchat/client.go
@@ -24,8 +24,6 @@ type Client struct {
meta model.Meta
}
-const customTpl = `Docker tag {{ .Entry.Image }} which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }} on {{ .Meta.Hostname }}.`
-
// New creates a new rocketchat notification instance
func New(config *model.NotifRocketChat, meta model.Meta) notifier.Notifier {
return notifier.Notifier{
@@ -54,14 +52,16 @@ func (c *Client) Send(entry model.NotifEntry) error {
}
message, err := msg.New(msg.Options{
- Meta: c.meta,
- Entry: entry,
+ Meta: c.meta,
+ Entry: entry,
+ TemplateTitle: c.cfg.TemplateTitle,
+ TemplateBody: c.cfg.TemplateBody,
})
if err != nil {
return err
}
- title, text, err := message.RenderMarkdownTemplate(customTpl)
+ title, body, err := message.RenderMarkdown()
if err != nil {
return err
}
@@ -106,10 +106,10 @@ func (c *Client) Send(entry model.NotifEntry) error {
Alias: c.meta.Name,
Avatar: c.meta.Logo,
Channel: c.cfg.Channel,
- Text: title,
+ Text: string(title),
Attachments: []Attachment{
{
- Text: string(text),
+ Text: string(body),
Ts: json.Number(strconv.FormatInt(time.Now().Unix(), 10)),
Fields: fields,
},
diff --git a/internal/notif/slack/client.go b/internal/notif/slack/client.go
index ac1e076c..7fcd1a17 100644
--- a/internal/notif/slack/client.go
+++ b/internal/notif/slack/client.go
@@ -19,8 +19,6 @@ type Client struct {
meta model.Meta
}
-const customTpl = " Docker tag `{{ .Entry.Image }}` {{ if (eq .Entry.Status \"new\") }}newly added{{ else }}updated{{ end }}."
-
// New creates a new slack notification instance
func New(config *model.NotifSlack, meta model.Meta) notifier.Notifier {
return notifier.Notifier{
@@ -39,14 +37,15 @@ func (c *Client) Name() string {
// Send creates and sends a slack notification with an entry
func (c *Client) Send(entry model.NotifEntry) error {
message, err := msg.New(msg.Options{
- Meta: c.meta,
- Entry: entry,
+ Meta: c.meta,
+ Entry: entry,
+ TemplateBody: c.cfg.TemplateBody,
})
if err != nil {
return err
}
- _, text, err := message.RenderMarkdownTemplate(customTpl)
+ _, body, err := message.RenderMarkdown()
if err != nil {
return err
}
@@ -99,7 +98,7 @@ func (c *Client) Send(entry model.NotifEntry) error {
AuthorSubname: "github.com/crazy-max/diun",
AuthorLink: c.meta.URL,
AuthorIcon: c.meta.Logo,
- Text: string(text),
+ Text: string(body),
Footer: fmt.Sprintf("%s © %d %s %s", c.meta.Author, time.Now().Year(), c.meta.Name, c.meta.Version),
Fields: fields,
Ts: json.Number(strconv.FormatInt(time.Now().Unix(), 10)),
diff --git a/internal/notif/teams/client.go b/internal/notif/teams/client.go
index 379438dd..a25fb53b 100644
--- a/internal/notif/teams/client.go
+++ b/internal/notif/teams/client.go
@@ -18,9 +18,6 @@ type Client struct {
meta model.Meta
}
-const customTpl = "Docker tag {{ if .Entry.Image.HubLink }}[`{{ .Entry.Image }}`]({{ .Entry.Image.HubLink }}){{ else }}`{{ .Entry.Image }}`{{ end }}" +
- "{{ if (eq .Entry.Status \"new\") }}newly added{{ else }}updated{{ end }}."
-
// New creates a new webhook notification instance
func New(config *model.NotifTeams, meta model.Meta) notifier.Notifier {
return notifier.Notifier{
@@ -56,14 +53,15 @@ func (c *Client) Send(entry model.NotifEntry) error {
}
message, err := msg.New(msg.Options{
- Meta: c.meta,
- Entry: entry,
+ Meta: c.meta,
+ Entry: entry,
+ TemplateBody: c.cfg.TemplateBody,
})
if err != nil {
return err
}
- _, text, err := message.RenderMarkdownTemplate(customTpl)
+ _, body, err := message.RenderMarkdown()
if err != nil {
return err
}
@@ -73,7 +71,7 @@ func (c *Client) Send(entry model.NotifEntry) error {
themeColor = "0076D7"
}
- body, err := json.Marshal(struct {
+ jsonBody, err := json.Marshal(struct {
Type string `json:"@type"`
Context string `json:"@context"`
ThemeColor string `json:"themeColor"`
@@ -81,11 +79,11 @@ func (c *Client) Send(entry model.NotifEntry) error {
Sections []Sections `json:"sections"`
}{
Type: "MessageCard",
- Context: "http://schema.org/extensions",
+ Context: "https://schema.org/extensions",
ThemeColor: themeColor,
- Summary: string(text),
+ Summary: string(body),
Sections: []Sections{{
- ActivityTitle: string(text),
+ ActivityTitle: string(body),
ActivitySubtitle: "Provider: " + entry.Provider,
Facts: []Fact{
{"Hostname", c.meta.Hostname},
@@ -99,7 +97,7 @@ func (c *Client) Send(entry model.NotifEntry) error {
return err
}
- req, err := http.NewRequest("POST", c.cfg.WebhookURL, bytes.NewBuffer(body))
+ req, err := http.NewRequest("POST", c.cfg.WebhookURL, bytes.NewBuffer(jsonBody))
if err != nil {
return err
}
diff --git a/internal/notif/telegram/client.go b/internal/notif/telegram/client.go
index f342cad0..6f43a120 100644
--- a/internal/notif/telegram/client.go
+++ b/internal/notif/telegram/client.go
@@ -20,10 +20,6 @@ type Client struct {
meta model.Meta
}
-const customTpl = `Docker tag {{ if .Entry.Image.HubLink }}[{{ .Entry.Image }}]({{ .Entry.Image.HubLink }}){{ else }}{{ .Entry.Image }}{{ end }}
-which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }}
-on {{ escapeMarkdown .Meta.Hostname }}.`
-
// New creates a new Telegram notification instance
func New(config *model.NotifTelegram, meta model.Meta) notifier.Notifier {
return notifier.Notifier{
@@ -63,9 +59,10 @@ func (c *Client) Send(entry model.NotifEntry) error {
}
message, err := msg.New(msg.Options{
- Meta: c.meta,
- Entry: entry,
- TplFuncs: template.FuncMap{
+ Meta: c.meta,
+ Entry: entry,
+ TemplateBody: c.cfg.TemplateBody,
+ TemplateFuncs: template.FuncMap{
"escapeMarkdown": func(text string) string {
text = strings.ReplaceAll(text, "_", "\\_")
text = strings.ReplaceAll(text, "*", "\\*")
@@ -79,7 +76,7 @@ func (c *Client) Send(entry model.NotifEntry) error {
return err
}
- _, text, err := message.RenderMarkdownTemplate(strings.ReplaceAll(customTpl, "\n", " "))
+ _, body, err := message.RenderMarkdown()
if err != nil {
return err
}
@@ -89,7 +86,7 @@ func (c *Client) Send(entry model.NotifEntry) error {
BaseChat: tgbotapi.BaseChat{
ChatID: chatID,
},
- Text: string(text),
+ Text: string(body),
ParseMode: "markdown",
DisableWebPagePreview: true,
})
diff --git a/mkdocs.yml b/mkdocs.yml
index 8a36c60b..9e2ad73b 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -22,6 +22,13 @@ extra:
plausible:
server: plausible.re4per.com
domain: crazymax.dev/diun
+ template:
+ defaultTitle: |
+ {{ if (eq .Entry.Status "new") }}New image {{ .Entry.Image }} has been added{{ else }}Image update for {{ .Entry.Image }}{{ end }}
+ defaultBody: |
+ Docker tag {{ if .Entry.Image.HubLink }}[**{{ .Entry.Image }}**]({{ .Entry.Image.HubLink }}){{ else }}**{{ .Entry.Image }}**{{ end }}
+ which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status "new") }}newly added{{ else }}updated{{ end }}
+ on {{ .Meta.Hostname }}.
theme:
name: material
@@ -76,7 +83,11 @@ plugins:
- git-revision-date-localized:
type: iso_datetime
enable_creation_date: true
- - macros
+ - macros:
+ j2_block_start_string: '[[%'
+ j2_block_end_string: '%]]'
+ j2_variable_start_string: '[['
+ j2_variable_end_string: ']]'
- search:
prebuild_index: python
lang: