~xenrox/ntfy-alertmanager

84a45a909b5cf650aedfbb45ca8d0809e3baf9a5 — Thorben Günther 30 days ago 9b9d71d
config: Allow to separate the ntfy topic from the server
4 files changed, 43 insertions(+), 8 deletions(-)

M config.scfg
M config/config.go
M config/config_test.go
M main.go
M config.scfg => config.scfg +7 -3
@@ 51,7 51,7 @@ labels {
    }

    instance "example.com" {
        topic https://ntfy.sh/homeserver
        topic homeserver
        tags "computer,example"
    }
}


@@ 64,10 64,14 @@ resolved {
}

ntfy {
    # URL of the ntfy topic.
    # URL of the ntfy server.
    # Default: "https://ntfy.sh"
    server https://ntfy.sh
    # Name of the ntfy topic. For backwards compatibility you can specify the full URL of the
    # topic (e.g. https://ntfy.sh/alertmanager-alerts) and the server will be parsed from it.
    # This setting is required.
    # Default: ""
    topic https://ntfy.sh/alertmanager-alerts
    topic alertmanager-alerts
    # ntfy authentication via Basic Auth (https://docs.ntfy.sh/publish/#username-password)
    # Default: ""
    user user

M config/config.go => config/config.go +10 -0
@@ 37,6 37,7 @@ type Config struct {
}

type ntfyConfig struct {
	Server            string
	Topic             string
	User              string
	Password          string


@@ 230,6 231,13 @@ func parseBlock(block scfg.Block, config *Config) error {

	ntfyDir := block.Get("ntfy")
	if ntfyDir != nil {
		d = ntfyDir.Children.Get("server")
		if d != nil {
			if err := d.ParseParams(&config.Ntfy.Server); err != nil {
				return err
			}
		}

		d = ntfyDir.Children.Get("topic")
		if d != nil {
			if err := d.ParseParams(&config.Ntfy.Topic); err != nil {


@@ 422,6 430,8 @@ func Read(path string) (*Config, error) {
	config.LogFormat = "text"
	config.AlertMode = Multi

	config.Ntfy.Server = "https://ntfy.sh"

	config.Cache.Type = "disabled"
	config.Cache.Duration = time.Hour * 24
	// memory

M config/config_test.go => config/config_test.go +3 -2
@@ 36,7 36,7 @@ labels {

    instance "example.com" {
        tags "computer,example"
        topic https://ntfy.sh/homeserver
        topic homeserver
    }
}



@@ 78,6 78,7 @@ cache {
		User:        "webhookUser",
		Password:    "webhookPass",
		Ntfy: ntfyConfig{
			Server:            "https://ntfy.sh",
			Topic:             "https://ntfy.sh/alertmanager-alerts",
			User:              "user",
			Password:          "pass",


@@ 96,7 97,7 @@ cache {
				"severity:info": {Priority: "1"},
				"instance:example.com": {
					Tags:  []string{"computer", "example"},
					Topic: "https://ntfy.sh/homeserver"},
					Topic: "homeserver"},
			},
		},
		Cache: CacheConfig{

M main.go => main.go +23 -3
@@ 17,6 17,7 @@ import (
	"io"
	"log/slog"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"slices"


@@ 304,9 305,9 @@ func (br *bridge) multiAlertNotification(p *payload) *notification {
}

func (br *bridge) publish(n *notification) error {
	url := br.cfg.Ntfy.Topic
	if n.topic != "" {
		url = n.topic
	url, err := br.topicURL(n.topic)
	if err != nil {
		return err
	}

	req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(n.body))


@@ 616,3 617,22 @@ func main() {
			slog.String("error", err.Error()))
	}
}

func (br *bridge) topicURL(topic string) (string, error) {
	if topic == "" {
		topic = br.cfg.Ntfy.Topic
	}

	// Check if the configured topic name already contains the ntfy server
	i := strings.Index(topic, "://")
	if i != -1 {
		return topic, nil
	}

	s, err := url.JoinPath(br.cfg.Ntfy.Server, topic)
	if err != nil {
		return "", err
	}

	return s, nil
}