feat: notification provider gotify

This commit is contained in:
2024-08-11 10:12:18 +02:00
parent 12898535e6
commit 9749d4a28d
4 changed files with 189 additions and 2 deletions

View File

@@ -2,12 +2,18 @@
ip_provider: ip_provider:
type: plain type: plain
config: config:
url: https://ifconfig.me url: https://ifconfig.me
dns_provider: dns_provider:
type: ionos type: ionos
config: config:
api_key: <your-api-key> api_key: <your-api-key>
base_url: https://api.hosting.ionos.com/dns base_url: https://api.hosting.ionos.com/dns
notification_provider:
type: gotify
config:
url: <your-gotify-host>
token: <your-token>
priority: 0
domains: domains:
- tld: example.com - tld: example.com
subdomains: subdomains:

15
main.go
View File

@@ -2,6 +2,8 @@ package main
import ( import (
"fmt" "fmt"
"time"
"realdnydns/pkg/changeDetector" "realdnydns/pkg/changeDetector"
"realdnydns/pkg/config" "realdnydns/pkg/config"
"realdnydns/pkg/dnsProvider" "realdnydns/pkg/dnsProvider"
@@ -10,7 +12,7 @@ import (
plainExternalIpProvider "realdnydns/pkg/externalIpProvider/plain" plainExternalIpProvider "realdnydns/pkg/externalIpProvider/plain"
"realdnydns/pkg/notificationProvider" "realdnydns/pkg/notificationProvider"
notificationProviderConsole "realdnydns/pkg/notificationProvider/console" notificationProviderConsole "realdnydns/pkg/notificationProvider/console"
"time" gotify "realdnydns/pkg/notificationProvider/gotify"
"github.com/go-co-op/gocron" "github.com/go-co-op/gocron"
) )
@@ -54,6 +56,17 @@ func main() {
var notificationProvider notificationProvider.NotificationProvider var notificationProvider notificationProvider.NotificationProvider
switch configClient.NotificationProvider.Type { switch configClient.NotificationProvider.Type {
case "gotify":
var gotifyConfig gotify.NotificationProviderImplGotifyConfig
err := configClient.NotificationProvider.ProviderConfig.Decode(&gotifyConfig)
if err != nil {
panic(err)
}
notificationProvider, err = gotify.New(gotifyConfig)
if err != nil {
panic(err)
}
default: default:
// Use default console notification provider // Use default console notification provider
notificationProvider = notificationProviderConsole.New() notificationProvider = notificationProviderConsole.New()

View File

@@ -0,0 +1,87 @@
package notificationProviderGotify
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/url"
)
type NotificationProviderImplGotifyConfig struct {
Url string `yaml:"url"`
Token string `yaml:"token"`
Priority int `yaml:"priority"`
}
type NotificationProviderImplGotify struct {
Url url.URL
Token string
Priority int
HTTPClient *http.Client
}
func New(config NotificationProviderImplGotifyConfig) (*NotificationProviderImplGotify, error) {
if config.Url == "" {
return nil, fmt.Errorf("url is required")
}
url, err := url.Parse(config.Url)
if err != nil {
return nil, err
}
if config.Token == "" {
return nil, fmt.Errorf("token is required")
}
if config.Priority < 0 || config.Priority > 4 {
return nil, fmt.Errorf("priority must be between 0 and 4")
}
return &NotificationProviderImplGotify{
*url,
config.Token,
config.Priority,
&http.Client{},
}, nil
}
func (p *NotificationProviderImplGotify) SendNotification(title string, message string) error {
type GotifyMessage struct {
Message string `json:"message"`
Title string `json:"title"`
Priority int `json:"priority"`
}
messageJson, err := json.Marshal(GotifyMessage{
message,
title,
p.Priority,
})
if err != nil {
return err
}
messageUrl := p.Url
messageUrl.JoinPath("message")
messageUrl.Query().Add("token", p.Token)
req, err := http.NewRequest("POST", messageUrl.String(), bytes.NewBuffer(messageJson))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
res, err := p.HTTPClient.Do(req)
if err != nil {
return err
}
if res.StatusCode != 200 {
return fmt.Errorf("unexpected status code: %d", res.StatusCode)
}
return nil
}

View File

@@ -0,0 +1,81 @@
package notificationProviderGotify_test
import (
"net/http"
"net/http/httptest"
"testing"
gotify "realdnydns/pkg/notificationProvider/gotify"
)
func TestNew(t *testing.T) {
t.Run("URL is required", testNewEmptyUrl())
t.Run("Token is required", testNewEmptyToken())
t.Run("Priority must be between 0 and 4", testNewInvalidPriority())
t.Run("Sends POST request to url", testNewSendsPostRequest())
}
func testNewEmptyUrl() func(t *testing.T) {
return func(t *testing.T) {
_, err := gotify.New(gotify.NotificationProviderImplGotifyConfig{
Token: "1234",
Priority: 1,
})
if err.Error() != "url is required" {
t.Errorf("Expected error 'url is required', got %v", err)
}
}
}
func testNewEmptyToken() func(t *testing.T) {
return func(t *testing.T) {
_, err := gotify.New(gotify.NotificationProviderImplGotifyConfig{
Url: "http://localhost:1234",
Priority: 0,
})
if err.Error() != "token is required" {
t.Errorf("Expected error 'token is required', got %v", err)
}
}
}
func testNewInvalidPriority() func(t *testing.T) {
return func(t *testing.T) {
_, err := gotify.New(gotify.NotificationProviderImplGotifyConfig{
Url: "http://localhost:1234",
Token: "token",
Priority: 5,
})
if err.Error() != "priority must be between 0 and 4" {
t.Errorf("Expected error 'priority must be between 0 and 4', got %v", err)
}
}
}
func testNewSendsPostRequest() func(t *testing.T) {
return func(t *testing.T) {
mockServer := httptest.NewServer(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
},
))
defer mockServer.Close()
provider, err := gotify.New(gotify.NotificationProviderImplGotifyConfig{
Url: mockServer.URL,
Token: "1234",
Priority: 0,
})
if err != nil {
t.Fatalf("New() returned unexpected error: %v", err)
}
err = provider.SendNotification("title", "message")
if err != nil {
t.Fatalf("SendNotification() returned unexpected error: %v", err)
}
}
}