diff --git a/agent/app/service/alert_helper.go b/agent/app/service/alert_helper.go index 556f6d545..adcada572 100644 --- a/agent/app/service/alert_helper.go +++ b/agent/app/service/alert_helper.go @@ -650,6 +650,28 @@ func sendAlerts(alert dto.AlertDTO, alertType, quota, quotaType string, params [ continue } alertUtil.CreateNewAlertTask(quota, alertType, quotaType, m) + case constant.Bark: + todayCount, isValid := canSendAlertToday(alertType, quotaType, alert.SendCount, m) + if !isValid { + continue + } + var create = dto.AlertLogCreate{ + Type: alertUtil.GetCronJobType(alert.Type), + AlertId: alert.ID, + Count: todayCount + 1, + } + alertInfo := alert + alertInfo.Type = alertType + create.AlertRule = alertUtil.ProcessAlertRule(alert) + create.AlertDetail = alertUtil.ProcessAlertDetail(alertInfo, quotaType, params, m) + transport := xpack.LoadRequestTransport() + agentInfo, _ := xpack.GetAgentInfo() + alertErr := alertUtil.CreateBarkAlertLog(create, alertInfo, params, transport, agentInfo) + if alertErr != nil { + global.LOG.Infof("%s alert %s push failed, err: %v", alertType, m, alertErr.Error()) + continue + } + alertUtil.CreateNewAlertTask(quota, alertType, quotaType, m) default: } } diff --git a/agent/app/service/alert_sender.go b/agent/app/service/alert_sender.go index 9adf20389..9d1df8f05 100644 --- a/agent/app/service/alert_sender.go +++ b/agent/app/service/alert_sender.go @@ -30,6 +30,8 @@ func (s *AlertSender) Send(quota string, params []dto.Param) { s.sendSMS(quota, params) case constant.Email: s.sendEmail(quota, params) + case constant.Bark: + s.sendBark(quota, params) case constant.WeCom, constant.DingTalk, constant.FeiShu: s.sendWebhook(quota, params, method) } @@ -45,6 +47,8 @@ func (s *AlertSender) ResourceSend(quota string, params []dto.Param) { s.sendResourceSMS(quota, params) case constant.Email: s.sendResourceEmail(quota, params) + case constant.Bark: + s.sendResourceBark(quota, params) case constant.WeCom, constant.DingTalk, constant.FeiShu: s.sendResourceWebhook(quota, params, method) } @@ -101,6 +105,31 @@ func (s *AlertSender) sendEmail(quota string, params []dto.Param) { alertUtil.CreateNewAlertTask(quota, s.alert.Type, s.quotaType, constant.Email) } +func (s *AlertSender) sendBark(quota string, params []dto.Param) { + totalCount, isValid := s.canSendAlert(constant.Bark) + if !isValid { + return + } + + create := dto.AlertLogCreate{ + Status: constant.AlertSuccess, + Count: totalCount + 1, + AlertId: s.alert.ID, + Type: s.alert.Type, + AlertRule: alertUtil.ProcessAlertRule(s.alert), + AlertDetail: alertUtil.ProcessAlertDetail(s.alert, quota, params, constant.Bark), + } + + transport := xpack.LoadRequestTransport() + agentInfo, _ := xpack.GetAgentInfo() + err := alertUtil.CreateBarkAlertLog(create, s.alert, params, transport, agentInfo) + if err != nil { + global.LOG.Errorf("%s alert bark push failed: %v", s.alert.Type, err) + return + } + alertUtil.CreateNewAlertTask(quota, s.alert.Type, s.quotaType, constant.Bark) +} + func (s *AlertSender) sendWebhook(quota string, params []dto.Param, method string) { totalCount, isValid := s.canSendAlert(method) if !isValid { @@ -171,6 +200,30 @@ func (s *AlertSender) sendResourceEmail(quota string, params []dto.Param) { alertUtil.CreateNewAlertTask(quota, s.alert.Type, s.quotaType, constant.Email) } +func (s *AlertSender) sendResourceBark(quota string, params []dto.Param) { + todayCount, isValid := s.canResourceSendAlert(constant.Bark) + if !isValid { + return + } + + create := dto.AlertLogCreate{ + Status: constant.AlertSuccess, + Count: todayCount + 1, + AlertId: s.alert.ID, + Type: s.alert.Type, + AlertRule: alertUtil.ProcessAlertRule(s.alert), + AlertDetail: alertUtil.ProcessAlertDetail(s.alert, quota, params, constant.Bark), + } + + transport := xpack.LoadRequestTransport() + agentInfo, _ := xpack.GetAgentInfo() + if err := alertUtil.CreateBarkAlertLog(create, s.alert, params, transport, agentInfo); err != nil { + global.LOG.Errorf("failed to send Bark alert: %v", err) + return + } + alertUtil.CreateNewAlertTask(quota, s.alert.Type, s.quotaType, constant.Bark) +} + func (s *AlertSender) sendResourceWebhook(quota string, params []dto.Param, method string) { todayCount, isValid := s.canResourceSendAlert(method) if !isValid { diff --git a/agent/constant/alert.go b/agent/constant/alert.go index 67915121d..546ae1bb8 100644 --- a/agent/constant/alert.go +++ b/agent/constant/alert.go @@ -25,4 +25,5 @@ const ( DingTalk = "dingTalk" FeiShu = "feiShu" Custom = "custom" + Bark = "bark" ) diff --git a/agent/utils/alert/alert.go b/agent/utils/alert/alert.go index c1366f083..90f2dac18 100644 --- a/agent/utils/alert/alert.go +++ b/agent/utils/alert/alert.go @@ -11,6 +11,7 @@ import ( "github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/i18n" + "github.com/1Panel-dev/1Panel/agent/utils/bark" "github.com/1Panel-dev/1Panel/agent/utils/email" "github.com/1Panel-dev/1Panel/agent/utils/psutil" "github.com/1Panel-dev/1Panel/agent/utils/re" @@ -103,6 +104,40 @@ func CreateEmailAlertLog(create dto.AlertLogCreate, alert dto.AlertDTO, params [ } } +func CreateBarkAlertLog(create dto.AlertLogCreate, alert dto.AlertDTO, params []dto.Param, transport *http.Transport, agentInfo *dto.AgentInfo) error { + var alertLog model.AlertLog + alertRepo := repo.NewIAlertRepo() + + create.Method = constant.Bark + barkConfig, err := alertRepo.GetConfig(alertRepo.WithByType(constant.Bark)) + if err != nil { + return err + } + var barkInfo dto.AlertWebhookConfig + err = json.Unmarshal([]byte(barkConfig.Config), &barkInfo) + if err != nil { + return err + } + if barkInfo.Url == "" { + create.Message = "bark config url is required" + create.Status = constant.AlertError + return SaveAlertLog(create, &alertLog) + } + + content := GetSendContent(alert.Type, params, agentInfo) + if content == "" { + content = i18n.GetMsgWithMap("CommonAlert", map[string]interface{}{"msg": alert.Title}) + } + + if err = bark.SendMessage(barkInfo.Url, i18n.GetMsgByKey("PanelAlertTitle"), content, transport); err != nil { + create.Message = err.Error() + create.Status = constant.AlertError + return SaveAlertLog(create, &alertLog) + } + create.Status = constant.AlertSuccess + return SaveAlertLog(create, &alertLog) +} + func SaveAlertLog(create dto.AlertLogCreate, alertLog *model.AlertLog) error { alertRepo := repo.NewIAlertRepo() if err := copier.Copy(&alertLog, &create); err != nil { diff --git a/agent/utils/alert_push/alert_push.go b/agent/utils/alert_push/alert_push.go index ac3231002..e28765d0a 100644 --- a/agent/utils/alert_push/alert_push.go +++ b/agent/utils/alert_push/alert_push.go @@ -66,6 +66,29 @@ func PushAlert(pushAlert dto.PushAlert) error { continue } alertUtil.CreateNewAlertTask(strconv.Itoa(int(pushAlert.EntryID)), alertUtil.GetCronJobType(alert.Type), strconv.Itoa(int(pushAlert.EntryID)), constant.Email) + case constant.Bark: + todayCount, _, err := alertRepo.LoadTaskCount(alertUtil.GetCronJobType(alert.Type), strconv.Itoa(int(pushAlert.EntryID)), constant.Bark) + if err != nil || alert.SendCount <= todayCount { + continue + } + var create = dto.AlertLogCreate{ + Type: alertUtil.GetCronJobType(alert.Type), + AlertId: alert.ID, + Count: todayCount + 1, + } + transport := xpack.LoadRequestTransport() + agentInfo, _ := xpack.GetAgentInfo() + params := alertUtil.CreateAlertParams(alertUtil.GetCronJobTypeName(pushAlert.Param)) + alertDetail := alertUtil.ProcessAlertDetail(alert, pushAlert.TaskName, params, constant.Bark) + alertRule := alertUtil.ProcessAlertRule(alert) + create.AlertRule = alertRule + create.AlertDetail = alertDetail + err = alertUtil.CreateBarkAlertLog(create, alert, params, transport, agentInfo) + if err != nil { + global.LOG.Errorf("%s alert bark push failed: %v", alert.Type, err) + continue + } + alertUtil.CreateNewAlertTask(strconv.Itoa(int(pushAlert.EntryID)), alertUtil.GetCronJobType(alert.Type), strconv.Itoa(int(pushAlert.EntryID)), constant.Bark) case constant.WeCom, constant.DingTalk, constant.FeiShu: todayCount, _, err := alertRepo.LoadTaskCount(alertUtil.GetCronJobType(alert.Type), strconv.Itoa(int(pushAlert.EntryID)), m) if err != nil || alert.SendCount <= todayCount { diff --git a/agent/utils/bark/bark.go b/agent/utils/bark/bark.go new file mode 100644 index 000000000..1a841e680 --- /dev/null +++ b/agent/utils/bark/bark.go @@ -0,0 +1,46 @@ +package bark + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" +) + +type BarkMessage struct { + Title string `json:"title"` + Body string `json:"body"` +} + +func SendMessage(url string, title string, body string, transport *http.Transport) error { + msg := BarkMessage{ + Title: title, + Body: body, + } + data, err := json.Marshal(msg) + if err != nil { + return err + } + + client := &http.Client{ + Transport: transport, + } + + req, err := http.NewRequest("POST", url, bytes.NewBuffer(data)) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json; charset=utf-8") + + resp, err := client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("bark push failed with status code %d", resp.StatusCode) + } + + return nil +} diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 2f5ed5c4b..d88d29fdb 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -4085,6 +4085,7 @@ const message = { feiShu: 'FeiShu', mail: 'Email', weCom: 'WeCom', + bark: 'Bark', sendCountRulesHelper: 'Total alerts sent before expiry (once daily)', panelUpdateRulesHelper: 'Total alerts sent for new panel version (once daily)', oneDaySendCountRulesHelper: 'Maximum alerts sent per day', @@ -4254,6 +4255,7 @@ const message = { userNameHelper: 'Username is empty, the sender address will be used by default', alertConfigHelper: 'Configure alert notification channels to receive panel message push', weComConfigHelper: 'WeCom alert notification configuration', + barkConfigHelper: 'Bark alert notification configuration', wechatConfigHelper: 'WeChat Official Account alert notification configuration', dingTalkConfigHelper: 'DingTalk alert notification configuration', feiShuConfigHelper: 'Feishu alert notification configuration', diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index 781afe2ff..7dab63f93 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -4097,6 +4097,7 @@ const message = { feiShu: 'FeiShu', mail: 'Correo', weCom: 'WeCom', + bark: 'Bark', sendCountRulesHelper: 'Número total de alertas enviadas antes de expirar (una vez al día)', panelUpdateRulesHelper: 'Alertas totales enviadas por nueva versión del panel (una vez al día)', oneDaySendCountRulesHelper: 'Número máximo de alertas diarias', @@ -4265,6 +4266,7 @@ const message = { wechatConfigHelper: 'Configuración de notificación de alerta de Cuenta Oficial WeChat', dingTalkConfigHelper: 'Configuración de notificación de alerta DingTalk', feiShuConfigHelper: 'Configuración de notificación de alerta Feishu', + barkConfigHelper: 'Configuración de notificación de alerta Bark', webhookName: 'Nombre del bot', webhookUrl: 'URL de Webhook', alertConfigProHelper: diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index 245db5ed7..eec206e7b 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -4090,6 +4090,7 @@ const message = { feiShu: 'FeiShu', mail: 'メール', weCom: 'WeCom', + bark: 'Bark', sendCountRulesHelper: '期限前に送信されるアラートの合計(1日1回)', panelUpdateRulesHelper: '新しいパネルバージョンに関するアラートの合計(1日1回)', oneDaySendCountRulesHelper: '1日に送信できる最大アラート回数', @@ -4263,6 +4264,7 @@ const message = { wechatConfigHelper: 'WeChat公式アカウントアラート通知設定', dingTalkConfigHelper: 'DingTalkアラート通知設定', feiShuConfigHelper: 'Feishuアラート通知設定', + barkConfigHelper: 'Barkアラート通知設定', webhookName: 'ボット名', webhookUrl: 'Webhook URL', alertConfigProHelper: diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index 3031a4ffe..a96274a32 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -3998,6 +3998,7 @@ const message = { feiShu: '페이슈', mail: '이메일', weCom: 'WeCom', + bark: 'Bark', sendCountRulesHelper: '만료 전 발송된 총 알림 수 (하루 1회)', panelUpdateRulesHelper: '새 패널 버전에 대한 총 알림 수 (하루 1회)', oneDaySendCountRulesHelper: '하루 최대 발송 가능한 알림 수', @@ -4166,6 +4167,7 @@ const message = { wechatConfigHelper: 'WeChat 공식 계정 알림 구성', dingTalkConfigHelper: 'DingTalk 알림 구성', feiShuConfigHelper: 'Feishu 알림 구성', + barkConfigHelper: 'Bark 알림 구성', webhookName: '봇 이름', webhookUrl: 'Webhook URL', alertConfigProHelper: diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index 46d034efc..d7b7b5d50 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -4144,6 +4144,7 @@ const message = { feiShu: 'FeiShu', mail: 'E-mel', weCom: 'WeCom', + bark: 'Bark', sendCountRulesHelper: 'Jumlah amaran dihantar sebelum tamat tempoh (sekali sehari)', panelUpdateRulesHelper: 'Jumlah amaran dihantar untuk versi panel baharu (sekali sehari)', oneDaySendCountRulesHelper: 'Maksimum amaran dihantar setiap hari', @@ -4321,6 +4322,7 @@ const message = { wechatConfigHelper: 'Konfigurasi pemberitahuan amaran Akaun Rasmi WeChat', dingTalkConfigHelper: 'Konfigurasi pemberitahuan amaran DingTalk', feiShuConfigHelper: 'Konfigurasi pemberitahuan amaran Feishu', + barkConfigHelper: 'Konfigurasi pemberitahuan amaran Bark', webhookName: 'Nama bot', webhookUrl: 'URL Webhook', alertConfigProHelper: 'Edisi Profesional turut menyokong amaran WeCom, DingTalk, Feishu dan SMS.', diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index 83baf60b8..bbb79f379 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -4294,6 +4294,7 @@ const message = { feiShu: 'FeiShu', mail: 'E-mail', weCom: 'WeCom', + bark: 'Bark', sendCountRulesHelper: 'Alertas totais enviados antes da expiração (uma vez por dia)', panelUpdateRulesHelper: 'Alertas totais enviados para nova versão do painel (uma vez por dia)', oneDaySendCountRulesHelper: 'Número máximo de alertas enviados por dia', @@ -4470,6 +4471,7 @@ const message = { wechatConfigHelper: 'Configuração de notificação de alerta da Conta Oficial WeChat', dingTalkConfigHelper: 'Configuração de notificação de alerta DingTalk', feiShuConfigHelper: 'Configuração de notificação de alerta Feishu', + barkConfigHelper: 'Configuração de notificação de alerta Bark', webhookName: 'Nome do bot', webhookUrl: 'URL do Webhook', alertConfigProHelper: diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index 840e22db5..dc3121e93 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -4146,6 +4146,7 @@ const message = { feiShu: 'FeiShu', mail: 'Электронная Почта', weCom: 'WeCom', + bark: 'Bark', sendCountRulesHelper: 'Общее количество уведомлений до истечения срока действия (раз в день)', panelUpdateRulesHelper: 'Общее количество уведомлений для новой версии панели (раз в день)', oneDaySendCountRulesHelper: 'Максимальное количество уведомлений в день', @@ -4326,6 +4327,7 @@ const message = { wechatConfigHelper: 'Конфигурация уведомлений официального аккаунта WeChat', dingTalkConfigHelper: 'Конфигурация уведомлений DingTalk', feiShuConfigHelper: 'Конфигурация уведомлений Feishu', + barkConfigHelper: 'Конфигурация уведомлений Bark', webhookName: 'Имя бота', webhookUrl: 'URL Webhook', alertConfigProHelper: diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index 42827e34b..d417a9e6a 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -4136,6 +4136,7 @@ const message = { feiShu: 'FeiShu', mail: 'E-posta', weCom: 'WeCom', + bark: 'Bark', sendCountRulesHelper: 'Sona ermeden önce gönderilen toplam uyarılar (günde bir kez)', panelUpdateRulesHelper: 'Yeni panel sürümü algılandığında bir kez uyarı gönder (işlenmezse ertesi gün tekrar gönderilir)', @@ -4314,6 +4315,7 @@ const message = { wechatConfigHelper: 'WeChat Resmi Hesap uyarı bildirim yapılandırması', dingTalkConfigHelper: 'DingTalk uyarı bildirim yapılandırması', feiShuConfigHelper: 'Feishu uyarı bildirim yapılandırması', + barkConfigHelper: 'Bark uyarı bildirim yapılandırması', webhookName: 'Bot adı', webhookUrl: 'Webhook URL', alertConfigProHelper: diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index 0fbd18573..9fff42b30 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -3759,6 +3759,7 @@ const message = { feiShu: '飛書通知', mail: '信箱通知', weCom: '企業微信', + bark: 'Bark', sendCountRulesHelper: '到期前發送告警的總數(每日僅發送一次)', panelUpdateRulesHelper: '新版本發送告警總數(每日僅發送一次)', oneDaySendCountRulesHelper: '每日發送告警的總數', @@ -3924,6 +3925,7 @@ const message = { wechatConfigHelper: '微信公眾號告警通知設定', dingTalkConfigHelper: '釘釘告警通知設定', feiShuConfigHelper: '飛書告警通知設定', + barkConfigHelper: 'Bark 告警通知設定', webhookName: '機器人名稱', webhookUrl: 'Webhook 位址', alertConfigProHelper: '專業版額外支援企業微信、釘釘、飛書及簡訊告警。', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 8d2782532..b6a460959 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -3756,6 +3756,7 @@ const message = { feiShu: '飞书通知', mail: '邮箱通知', weCom: '企业微信', + bark: 'Bark', sendCountRulesHelper: '到期前发送告警的总数(每日仅发送一次)', panelUpdateRulesHelper: '新版本发送告警总数(每日仅发送一次)', oneDaySendCountRulesHelper: '每日发送告警的总数', @@ -3922,6 +3923,7 @@ const message = { wechatConfigHelper: '微信公众号告警通知配置', dingTalkConfigHelper: '钉钉告警通知配置', feiShuConfigHelper: '飞书告警通知配置', + barkConfigHelper: 'Bark 告警通知配置', webhookName: '机器人名称', webhookUrl: 'Webhook 地址', alertConfigProHelper: '专业版额外支持企业微信、钉钉、飞书及短信告警。', diff --git a/frontend/src/views/setting/alert/dash/task/index.vue b/frontend/src/views/setting/alert/dash/task/index.vue index 168fd85e2..fe8d7d9af 100644 --- a/frontend/src/views/setting/alert/dash/task/index.vue +++ b/frontend/src/views/setting/alert/dash/task/index.vue @@ -322,6 +322,7 @@ + { return t('xpack.alert.sms'); case 'webhook': return t('xpack.alert.webhook'); + case 'bark': + return t('xpack.alert.bark'); default: return t('xpack.alert.unknown'); } diff --git a/frontend/src/views/setting/alert/setting/index.vue b/frontend/src/views/setting/alert/setting/index.vue index 3820033d3..342b2b805 100644 --- a/frontend/src/views/setting/alert/setting/index.vue +++ b/frontend/src/views/setting/alert/setting/index.vue @@ -121,6 +121,59 @@ + +
+
{{ $t('xpack.alert.bark') }}
+
+ + {{ $t('commons.button.edit') }} + + + {{ $t('commons.button.delete') }} + +
+
+
{{ $t('xpack.alert.barkConfigHelper') }}
+ +
+ + + {{ barkConfig.config.displayName }} + + +
+ + + {{ barkConfig.config.url }} + + +
+
+
+
+
+ + {{ $t('commons.button.create') }} + +
+
({ ...defaultSmsConfig }); +const defaultBarkConfig: Alert.WebhookConfig = { + id: undefined, + type: 'bark', + title: 'xpack.alert.bark', + status: 'Enable', + config: { + displayName: '', + url: 'https://api.day.app/YOUR_KEY', + }, +}; +const barkConfig = ref({ ...defaultBarkConfig }); + const defaultWeComConfig: Alert.WebhookConfig = { id: undefined, type: 'weCom', @@ -566,6 +631,10 @@ const search = async () => { const feiShuFound = res.data.find((s: any) => s.type === 'feiShu'); assignConfig(feiShuFound, feiShuConfig, defaultFeiShuConfig); + + const barkFound = res.data.find((s: any) => s.type === 'bark'); + assignConfig(barkFound, barkConfig, defaultBarkConfig); + isInitialized.value = true; } finally { loading.value = false; @@ -680,6 +749,15 @@ const onChangeFeiShu = (id: number) => { }); }; +const onChangeBark = (id: number) => { + webHookRef.value.acceptParams({ + id: id, + config: barkConfig.value.config, + type: 'bark', + title: barkConfig.value.title, + }); +}; + onMounted(async () => { await search(); if (globalStore.isProductPro && !globalStore.isIntl) {