diff --git a/database/config/config.go b/database/config/config.go index 91b6da7..6c0b373 100644 --- a/database/config/config.go +++ b/database/config/config.go @@ -25,17 +25,18 @@ func Get() (models.Config, error) { if err := db.First(&config).Error; err != nil { if err == gorm.ErrRecordNotFound { config = models.Config{ - ID: 1, - Sitename: "Komari", - Description: "Komari Monitor, a simple server monitoring tool.", - AllowCors: false, - OAuthEnabled: false, - GeoIpEnabled: true, - GeoIpProvider: "ip-api", - NezhaCompatEnabled: false, - NezhaCompatListen: "", - UpdatedAt: models.FromTime(time.Now()), - CreatedAt: models.FromTime(time.Now()), + ID: 1, + Sitename: "Komari", + Description: "Komari Monitor, a simple server monitoring tool.", + AllowCors: false, + OAuthEnabled: false, + GeoIpEnabled: true, + GeoIpProvider: "ipinfo", + NezhaCompatEnabled: false, + NezhaCompatListen: "", + NotificationTemplate: "{{event}}: {{client}}\n{{time}}", + UpdatedAt: models.FromTime(time.Now()), + CreatedAt: models.FromTime(time.Now()), } if err := db.Create(&config).Error; err != nil { log.Fatal("Failed to create default config:", err) diff --git a/database/models/config.go b/database/models/config.go index edd110a..e114090 100644 --- a/database/models/config.go +++ b/database/models/config.go @@ -25,6 +25,7 @@ type Config struct { // 通知 NotificationEnabled bool `json:"notification_enabled" gorm:"default:false"` // 通知总开关 NotificationMethod string `json:"notification_method" gorm:"type:varchar(64);default:'none'"` + NotificationTemplate string `json:"notification_template" gorm:"type:longtext;default:'{{event}}: {{client}}\n{{time}}'"` ExpireNotificationEnabled bool `json:"expire_notification_enabled" gorm:"default:false"` // 是否启用过期通知 ExpireNotificationLeadDays int `json:"expire_notification_lead_days" gorm:"default:7"` // 过期前多少天通知,默认7天 LoginNotification bool `json:"login_notification" gorm:"default:false"` // 登录通知 diff --git a/database/models/messageEvent/MessageEvent.go b/database/models/messageEvent/MessageEvent.go new file mode 100644 index 0000000..67f7e04 --- /dev/null +++ b/database/models/messageEvent/MessageEvent.go @@ -0,0 +1,11 @@ +package messageevent + +const ( + Offline = "Offline" + Online = "Online" + Expire = "Expire" + Renew = "Renew" + Login = "Login" + Alert = "Alert" + Traffic = "Traffic" +) diff --git a/database/models/messageSender.go b/database/models/messageSender.go index 61a1f8a..94f9ee9 100644 --- a/database/models/messageSender.go +++ b/database/models/messageSender.go @@ -1,6 +1,16 @@ package models +import "time" + type MessageSenderProvider struct { Name string `json:"name" gorm:"primaryKey;unique;not null"` Addition string `json:"addition" gorm:"type:longtext" default:"{}"` } + +type EventMessage struct { + Event string `json:"event"` + Clients []Client `json:"clients"` + Time time.Time `json:"time"` + Message string `json:"message"` + Emoji string `json:"emoji"` +} diff --git a/utils/messageSender/sender.go b/utils/messageSender/sender.go index 90fc04f..98893cb 100644 --- a/utils/messageSender/sender.go +++ b/utils/messageSender/sender.go @@ -4,7 +4,9 @@ import ( "encoding/json" "fmt" "log" + "strings" "sync" + "time" "github.com/komari-monitor/komari/database" "github.com/komari-monitor/komari/database/auditlog" @@ -89,3 +91,57 @@ func SendTextMessage(message string, title string) error { auditlog.Log("", "", "Failed to send message after 3 attempts: "+err.Error()+","+title, "error") return err } +func SendEvent(event models.EventMessage) error { + if CurrentProvider() == nil { + return fmt.Errorf("message sender provider is not initialized") + } + var err error + cfg, err := config.Get() + if err != nil { + return err + } + if !cfg.NotificationEnabled { + return nil + } + messageTemplate := cfg.NotificationTemplate + if messageTemplate == "" { + messageTemplate = "{{event}}: {{client}}\n{{time}}" + } + messageTemplate = parseTemplate(messageTemplate, event) + + for i := 0; i < 3; i++ { + err = CurrentProvider().SendTextMessage(messageTemplate, event.Event) + if err == nil { + auditlog.Log("", "", "Event message sent: "+event.Event, "info") + return nil + } + } + auditlog.Log("", "", "Failed to send event message after 3 attempts: "+err.Error()+","+event.Event, "error") + return err +} + +func parseTemplate(messageTemplate string, event models.EventMessage) string { + // Aggregate client names. If Name is empty, fall back to UUID. + clientNames := make([]string, 0, len(event.Clients)) + for _, c := range event.Clients { + name := c.Name + if strings.TrimSpace(name) == "" { + // fallback to UUID when name is not set + name = c.UUID + } + clientNames = append(clientNames, name) + } + joinedClients := strings.Join(clientNames, ", ") + + replaceMap := map[string]string{ + "{{event}}": event.Event, + "{{client}}": joinedClients, + "{{time}}": event.Time.Format(time.RFC3339), + "{{message}}": event.Message, + } + result := messageTemplate + for placeholder, value := range replaceMap { + result = strings.ReplaceAll(result, placeholder, value) + } + return result +}