diff --git a/agent/app/service/alert_helper.go b/agent/app/service/alert_helper.go index 556f6d5454ef..adcada572cd3 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 9adf20389aee..9d1df8f053a1 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 67915121d88f..546ae1bb8a82 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 c1366f08351a..90f2dac18372 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 ac32310027f6..e28765d0a2ca 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 000000000000..1a841e680915 --- /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 400e2e0a324b..9b3592df5ab9 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -4076,6 +4076,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', @@ -4245,6 +4246,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 158435e0bb2a..036dd6910c3f 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -4088,6 +4088,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', @@ -4256,6 +4257,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 10a76cd09821..be1b588bdd7d 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -4081,6 +4081,7 @@ const message = { feiShu: 'FeiShu', mail: 'メール', weCom: 'WeCom', + bark: 'Bark', sendCountRulesHelper: '期限前に送信されるアラートの合計(1日1回)', panelUpdateRulesHelper: '新しいパネルバージョンに関するアラートの合計(1日1回)', oneDaySendCountRulesHelper: '1日に送信できる最大アラート回数', @@ -4254,6 +4255,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 214e1d08e7ab..9f5f715bc12e 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -3990,6 +3990,7 @@ const message = { feiShu: '페이슈', mail: '이메일', weCom: 'WeCom', + bark: 'Bark', sendCountRulesHelper: '만료 전 발송된 총 알림 수 (하루 1회)', panelUpdateRulesHelper: '새 패널 버전에 대한 총 알림 수 (하루 1회)', oneDaySendCountRulesHelper: '하루 최대 발송 가능한 알림 수', @@ -4158,6 +4159,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 ccdb79a2270f..d3d7f270f9e8 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -4135,6 +4135,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', @@ -4312,6 +4313,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 7b3b58a96c42..2681a20bc7bd 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -4285,6 +4285,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', @@ -4461,6 +4462,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 9ef6093b14c8..be706762c8ae 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -4137,6 +4137,7 @@ const message = { feiShu: 'FeiShu', mail: 'Электронная Почта', weCom: 'WeCom', + bark: 'Bark', sendCountRulesHelper: 'Общее количество уведомлений до истечения срока действия (раз в день)', panelUpdateRulesHelper: 'Общее количество уведомлений для новой версии панели (раз в день)', oneDaySendCountRulesHelper: 'Максимальное количество уведомлений в день', @@ -4317,6 +4318,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 031a5bf5b9a3..ca3478ed5f54 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -4127,6 +4127,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)', @@ -4305,6 +4306,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 a7cacb13f4cc..3e675dd272a7 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -3750,6 +3750,7 @@ const message = { feiShu: '飛書通知', mail: '信箱通知', weCom: '企業微信', + bark: 'Bark', sendCountRulesHelper: '到期前發送告警的總數(每日僅發送一次)', panelUpdateRulesHelper: '新版本發送告警總數(每日僅發送一次)', oneDaySendCountRulesHelper: '每日發送告警的總數', @@ -3915,6 +3916,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 2ad78023fecd..a98f042d9615 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -3747,6 +3747,7 @@ const message = { feiShu: '飞书通知', mail: '邮箱通知', weCom: '企业微信', + bark: 'Bark', sendCountRulesHelper: '到期前发送告警的总数(每日仅发送一次)', panelUpdateRulesHelper: '新版本发送告警总数(每日仅发送一次)', oneDaySendCountRulesHelper: '每日发送告警的总数', @@ -3913,6 +3914,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 168fd85e278a..fe8d7d9af40d 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 3820033d3023..342b2b805bb7 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) {