2022-01-08 22:54:14 -05:00
|
|
|
package singleton
|
2021-01-23 20:41:35 -05:00
|
|
|
|
|
|
|
import (
|
2021-09-04 00:42:51 -04:00
|
|
|
"crypto/md5" // #nosec
|
2021-01-23 20:41:35 -05:00
|
|
|
"encoding/hex"
|
2021-06-21 09:30:42 -04:00
|
|
|
"log"
|
2021-01-23 20:41:35 -05:00
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/naiba/nezha/model"
|
|
|
|
)
|
|
|
|
|
|
|
|
const firstNotificationDelay = time.Minute * 15
|
|
|
|
|
|
|
|
// 通知方式
|
2022-04-14 09:06:42 -04:00
|
|
|
var (
|
|
|
|
NotificationList map[string]map[uint64]*model.Notification // [NotificationMethodTag][NotificationID] -> model.Notification
|
|
|
|
NotificationIDToTag map[uint64]string // [NotificationID] -> NotificationTag
|
|
|
|
notificationsLock sync.RWMutex
|
|
|
|
)
|
|
|
|
|
|
|
|
// InitNotification 初始化 Tag <-> ID <-> Notification 的映射
|
|
|
|
func InitNotification() {
|
|
|
|
NotificationList = make(map[string]map[uint64]*model.Notification)
|
|
|
|
NotificationIDToTag = make(map[uint64]string)
|
|
|
|
}
|
2021-01-23 20:41:35 -05:00
|
|
|
|
2022-04-14 09:06:42 -04:00
|
|
|
// LoadNotifications 从 DB 初始化通知方式相关参数
|
2021-09-29 12:01:04 -04:00
|
|
|
func LoadNotifications() {
|
2022-04-14 09:06:42 -04:00
|
|
|
InitNotification()
|
2021-09-29 12:01:04 -04:00
|
|
|
notificationsLock.Lock()
|
2022-04-14 09:06:42 -04:00
|
|
|
defer notificationsLock.Unlock()
|
|
|
|
|
|
|
|
var notifications []model.Notification
|
2021-09-29 12:01:04 -04:00
|
|
|
if err := DB.Find(¬ifications).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2022-04-14 09:06:42 -04:00
|
|
|
for _, n := range notifications {
|
|
|
|
// 旧版本的Tag可能不存在 自动设置为默认值
|
|
|
|
if n.Tag == "" {
|
|
|
|
SetDefaultNotificationTagInDB(&n)
|
|
|
|
}
|
|
|
|
AddNotificationToList(&n)
|
|
|
|
}
|
2021-09-29 12:01:04 -04:00
|
|
|
}
|
|
|
|
|
2022-04-14 09:06:42 -04:00
|
|
|
// SetDefaultNotificationTagInDB 设置默认通知方式的 Tag
|
|
|
|
func SetDefaultNotificationTagInDB(n *model.Notification) {
|
|
|
|
n.Tag = "default"
|
|
|
|
if err := DB.Save(n).Error; err != nil {
|
|
|
|
log.Println("[ERROR]", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// OnRefreshOrAddNotification 刷新通知方式相关参数
|
|
|
|
func OnRefreshOrAddNotification(n *model.Notification) {
|
2021-01-23 20:41:35 -05:00
|
|
|
notificationsLock.Lock()
|
|
|
|
defer notificationsLock.Unlock()
|
2022-04-14 09:06:42 -04:00
|
|
|
|
2021-01-23 20:41:35 -05:00
|
|
|
var isEdit bool
|
2022-04-14 09:06:42 -04:00
|
|
|
if _, ok := NotificationList[n.Tag][n.ID]; ok {
|
|
|
|
isEdit = true
|
2021-01-23 20:41:35 -05:00
|
|
|
}
|
|
|
|
if !isEdit {
|
2022-04-14 09:06:42 -04:00
|
|
|
AddNotificationToList(n)
|
|
|
|
} else {
|
|
|
|
UpdateNotificationInList(n)
|
2021-01-23 20:41:35 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-14 09:06:42 -04:00
|
|
|
// AddNotificationToList 添加通知方式到map中
|
|
|
|
func AddNotificationToList(n *model.Notification) {
|
2021-01-23 20:41:35 -05:00
|
|
|
notificationsLock.Lock()
|
|
|
|
defer notificationsLock.Unlock()
|
2022-04-14 09:06:42 -04:00
|
|
|
|
|
|
|
// 当前 Tag 不存在,创建对应该 Tag 的 子 map 后再添加
|
|
|
|
if _, ok := NotificationList[n.Tag]; !ok {
|
|
|
|
NotificationList[n.Tag] = make(map[uint64]*model.Notification)
|
2021-01-23 20:41:35 -05:00
|
|
|
}
|
2022-04-14 09:06:42 -04:00
|
|
|
NotificationList[n.Tag][n.ID] = n
|
|
|
|
NotificationIDToTag[n.ID] = n.Tag
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// UpdateNotificationInList 在 map 中更新通知方式
|
|
|
|
func UpdateNotificationInList(n *model.Notification) {
|
|
|
|
notificationsLock.Lock()
|
|
|
|
defer notificationsLock.Unlock()
|
|
|
|
|
|
|
|
NotificationList[n.Tag][n.ID] = n
|
2021-01-23 20:41:35 -05:00
|
|
|
}
|
|
|
|
|
2022-04-14 09:06:42 -04:00
|
|
|
// OnDeleteNotification 在map中删除通知方式
|
|
|
|
func OnDeleteNotification(id uint64) {
|
|
|
|
notificationsLock.Lock()
|
|
|
|
defer notificationsLock.Unlock()
|
|
|
|
|
|
|
|
delete(NotificationList[NotificationIDToTag[id]], id)
|
|
|
|
delete(NotificationIDToTag, id)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SendNotification 向指定的通知方式组的所有通知方式发送通知
|
|
|
|
func SendNotification(notificationTag string, desc string, mutable bool) {
|
|
|
|
if mutable {
|
2021-01-23 20:41:35 -05:00
|
|
|
// 通知防骚扰策略
|
2021-09-04 00:42:51 -04:00
|
|
|
nID := hex.EncodeToString(md5.New().Sum([]byte(desc))) // #nosec
|
2021-01-23 20:41:35 -05:00
|
|
|
var flag bool
|
|
|
|
if cacheN, has := Cache.Get(nID); has {
|
|
|
|
nHistory := cacheN.(NotificationHistory)
|
|
|
|
// 每次提醒都增加一倍等待时间,最后每天最多提醒一次
|
|
|
|
if time.Now().After(nHistory.Until) {
|
|
|
|
flag = true
|
|
|
|
nHistory.Duration *= 2
|
|
|
|
if nHistory.Duration > time.Hour*24 {
|
|
|
|
nHistory.Duration = time.Hour * 24
|
|
|
|
}
|
|
|
|
nHistory.Until = time.Now().Add(nHistory.Duration)
|
|
|
|
// 缓存有效期加 10 分钟
|
|
|
|
Cache.Set(nID, nHistory, nHistory.Duration+time.Minute*10)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// 新提醒直接通知
|
|
|
|
flag = true
|
|
|
|
Cache.Set(nID, NotificationHistory{
|
|
|
|
Duration: firstNotificationDelay,
|
|
|
|
Until: time.Now().Add(firstNotificationDelay),
|
|
|
|
}, firstNotificationDelay+time.Minute*10)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !flag {
|
2021-06-21 09:30:42 -04:00
|
|
|
if Conf.Debug {
|
2022-04-14 09:06:42 -04:00
|
|
|
log.Println("NEZHA>> 静音的重复通知:", desc, mutable)
|
2021-06-21 09:30:42 -04:00
|
|
|
}
|
2021-01-23 20:41:35 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2022-04-14 09:06:42 -04:00
|
|
|
// 向该通知方式组的所有通知方式发出通知
|
2021-01-23 20:41:35 -05:00
|
|
|
notificationsLock.RLock()
|
|
|
|
defer notificationsLock.RUnlock()
|
2022-04-14 09:06:42 -04:00
|
|
|
|
|
|
|
for _, n := range NotificationList[notificationTag] {
|
|
|
|
if err := n.Send(desc); err != nil {
|
2021-09-27 09:18:09 -04:00
|
|
|
log.Println("NEZHA>> 发送通知失败:", err)
|
2021-08-27 09:04:37 -04:00
|
|
|
}
|
2021-01-23 20:41:35 -05:00
|
|
|
}
|
|
|
|
}
|