shoutrrr alerts / settings page

This commit is contained in:
Henry Dollman
2024-09-12 19:39:27 -04:00
parent 2889d151ea
commit 9710d0d2f1
16 changed files with 450 additions and 78 deletions

View File

@@ -7,7 +7,6 @@ import (
"log"
"net/mail"
"net/url"
"os"
"github.com/containrrr/shoutrrr"
"github.com/labstack/echo/v5"
@@ -18,16 +17,21 @@ import (
"github.com/pocketbase/pocketbase/tools/mailer"
)
type AlertManager struct {
app *pocketbase.PocketBase
}
type AlertData struct {
User *models.Record
UserID string
Title string
Message string
Link string
LinkText string
}
type AlertManager struct {
app *pocketbase.PocketBase
type UserAlertSettings struct {
Emails []string `json:"emails"`
Webhooks []string `json:"webhooks"`
}
func NewAlertManager(app *pocketbase.PocketBase) *AlertManager {
@@ -107,7 +111,7 @@ func (am *AlertManager) handleSlidingValueAlert(newRecord *models.Record, alertR
}
if user := alertRecord.ExpandedOne("user"); user != nil {
am.sendAlert(AlertData{
User: user,
UserID: user.GetId(),
Title: subject,
Message: body,
Link: am.app.Settings().Meta.AppUrl + "/system/" + url.QueryEscape(systemName),
@@ -146,7 +150,7 @@ func (am *AlertManager) handleStatusAlerts(newStatus string, oldRecord *models.R
// send alert
systemName := oldRecord.GetString("name")
am.sendAlert(AlertData{
User: user,
UserID: user.GetId(),
Title: fmt.Sprintf("Connection to %s is %s %v", systemName, alertStatus, emoji),
Message: fmt.Sprintf("Connection to %s is %s", systemName, alertStatus),
Link: am.app.Settings().Meta.AppUrl + "/system/" + url.QueryEscape(systemName),
@@ -156,18 +160,42 @@ func (am *AlertManager) handleStatusAlerts(newStatus string, oldRecord *models.R
}
func (am *AlertManager) sendAlert(data AlertData) {
shoutrrrUrl := os.Getenv("SHOUTRRR_URL")
if shoutrrrUrl != "" {
err := am.SendShoutrrrAlert(shoutrrrUrl, data.Title, data.Message, data.Link, data.LinkText)
if err == nil {
log.Println("Sent shoutrrr alert")
return
}
log.Println("Failed to send alert via shoutrrr, falling back to email notification. ", "err", err.Error())
// get user settings
record, err := am.app.Dao().FindFirstRecordByFilter(
"user_settings", "user={:user}",
dbx.Params{"user": data.UserID},
)
if err != nil {
log.Println("Failed to get user settings", "err", err.Error())
return
}
// unmarshal user settings
userAlertSettings := UserAlertSettings{
Emails: []string{},
Webhooks: []string{},
}
if err := record.UnmarshalJSONField("settings", &userAlertSettings); err != nil {
log.Println("Failed to unmarshal user settings", "err", err.Error())
}
// send alerts via webhooks
for _, webhook := range userAlertSettings.Webhooks {
err := am.SendShoutrrrAlert(webhook, data.Title, data.Message, data.Link, data.LinkText)
if err != nil {
am.app.Logger().Error("Failed to send shoutrrr alert", "err", err.Error())
}
}
// send alerts via email
if len(userAlertSettings.Emails) == 0 {
log.Println("No email addresses found")
return
}
addresses := []mail.Address{}
for _, email := range userAlertSettings.Emails {
addresses = append(addresses, mail.Address{Address: email})
log.Println("Sending alert via email to", email)
}
// todo: email enable / disable and testing
message := mailer.Message{
To: []mail.Address{{Address: data.User.GetString("email")}},
To: addresses,
Subject: data.Title,
Text: data.Message + fmt.Sprintf("\n\n%s", data.Link),
From: mail.Address{

View File

@@ -0,0 +1,8 @@
package user
type UserSettings struct {
// Language string `json:"lang"`
ChartTime string `json:"chartTime"`
NotificationEmails []string `json:"emails"`
NotificationWebhooks []string `json:"webhooks"`
}

View File

@@ -4,6 +4,7 @@ import (
"beszel"
"beszel/internal/alerts"
"beszel/internal/entities/system"
"beszel/internal/entities/user"
"beszel/internal/records"
"beszel/site"
"context"
@@ -167,6 +168,36 @@ func (h *Hub) Run() {
go h.updateSystem(e.Model.(*models.Record))
return nil
})
// default user settings
h.app.OnModelBeforeCreate("user_settings").Add(func(e *core.ModelEvent) error {
record := e.Model.(*models.Record)
// intialize settings with defaults
settings := user.UserSettings{
// Language: "en",
ChartTime: "1h",
NotificationEmails: []string{},
NotificationWebhooks: []string{},
}
record.UnmarshalJSONField("settings", &settings)
if len(settings.NotificationEmails) == 0 {
// get user email from auth record
if errs := h.app.Dao().ExpandRecord(record, []string{"user"}, nil); len(errs) == 0 {
// app.Logger().Error("failed to expand user relation", "errs", errs)
if user := record.ExpandedOne("user"); user != nil {
settings.NotificationEmails = []string{user.GetString("email")}
} else {
log.Println("Failed to get user email from auth record")
}
} else {
log.Println("failed to expand user relation", "errs", errs)
}
}
// if len(settings.NotificationWebhooks) == 0 {
// settings.NotificationWebhooks = []string{""}
// }
record.Set("settings", settings)
return nil
})
// do things after a systems record is updated
h.app.OnModelAfterUpdate("systems").Add(func(e *core.ModelEvent) error {