This is an automated email from the ASF dual-hosted git repository.
tomsun28 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
The following commit(s) were added to refs/heads/master by this push:
new e553f2b0e4 [alerter]feature: add WPUSH as a new alert notification
channel (#4365)
e553f2b0e4 is described below
commit e553f2b0e46de022eab5c85e4cb33c56b506a819
Author: Alone88 <[email protected]>
AuthorDate: Mon Oct 5 09:29:03 2026 +0800
[alerter]feature: add WPUSH as a new alert notification channel (#4365)
Co-authored-by: Tomsun28 <[email protected]>
---
.../apache/hertzbeat/alert/AlerterProperties.java | 5 +
.../notice/impl/WpushAlertNotifyHandlerImpl.java | 109 +++++++++++++
.../alert/util/NoticeReceiverMaskUtil.java | 3 +-
.../impl/WpushAlertNotifyHandlerImplTest.java | 173 +++++++++++++++++++++
.../alert/util/NoticeReceiverMaskUtilTest.java | 3 +
.../common/entity/alerter/NoticeReceiver.java | 21 +++
.../main/resources/templates/16-WpushTemplate.txt | 47 ++++++
web-app/src/app/pojo/NoticeReceiver.ts | 5 +-
.../alert-notice-receiver.component.html | 26 ++++
.../alert-notice-template.component.html | 8 +
web-app/src/assets/i18n/en-US.json | 4 +
web-app/src/assets/i18n/ja-JP.json | 4 +
web-app/src/assets/i18n/ko-KR.json | 4 +
web-app/src/assets/i18n/pt-BR.json | 4 +
web-app/src/assets/i18n/zh-CN.json | 4 +
web-app/src/assets/i18n/zh-TW.json | 4 +
16 files changed, 422 insertions(+), 2 deletions(-)
diff --git
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/AlerterProperties.java
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/AlerterProperties.java
index b855c647bb..022c75b4e1 100644
---
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/AlerterProperties.java
+++
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/AlerterProperties.java
@@ -79,6 +79,11 @@ public class AlerterProperties {
*/
private String ntfyDefaultServerUrl = "https://ntfy.sh";
+ /**
+ * WPUSH Notify url
+ */
+ private String wpushWebhookUrl = "https://api.wpush.cn/api/v1/send";
+
/**
* Data entry configuration properties
*/
diff --git
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/WpushAlertNotifyHandlerImpl.java
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/WpushAlertNotifyHandlerImpl.java
new file mode 100644
index 0000000000..330289df42
--- /dev/null
+++
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/WpushAlertNotifyHandlerImpl.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hertzbeat.alert.notice.impl;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hertzbeat.alert.notice.AlertNoticeException;
+import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
+import org.apache.hertzbeat.common.entity.alerter.NoticeReceiver;
+import org.apache.hertzbeat.common.entity.alerter.NoticeTemplate;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+
+/**
+ * Send alert notification through WPUSH (https://wpush.cn).
+ * Success requires HTTP 200 and response JSON {@code code == 0}.
+ */
+@Component
+@RequiredArgsConstructor
+@Slf4j
+public class WpushAlertNotifyHandlerImpl extends
AbstractAlertNotifyHandlerImpl {
+
+ @Override
+ public void send(NoticeReceiver receiver, NoticeTemplate noticeTemplate,
GroupAlert alert)
+ throws AlertNoticeException {
+ try {
+ if (StringUtils.isBlank(receiver.getWpushToken())) {
+ throw new AlertNoticeException("WPUSH apikey (wpushToken) is
required");
+ }
+ WpushNotifyDto notifyDto = new WpushNotifyDto();
+ notifyDto.setApikey(receiver.getWpushToken());
+ notifyDto.setTitle(bundle.getString("alerter.notify.title"));
+ notifyDto.setContent(renderContent(noticeTemplate, alert));
+ if (StringUtils.isNotBlank(receiver.getWpushChannel())) {
+ notifyDto.setChannel(receiver.getWpushChannel());
+ }
+ if (StringUtils.isNotBlank(receiver.getWpushTopicCode())) {
+ notifyDto.setTopicCode(receiver.getWpushTopicCode());
+ }
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ HttpEntity<WpushNotifyDto> httpEntity = new
HttpEntity<>(notifyDto, headers);
+ String webHookUrl = alerterProperties.getWpushWebhookUrl();
+ ResponseEntity<CommonRobotNotifyResp> responseEntity =
+ restTemplate.postForEntity(webHookUrl, httpEntity,
CommonRobotNotifyResp.class);
+ if (responseEntity.getStatusCode() == HttpStatus.OK) {
+ CommonRobotNotifyResp body = responseEntity.getBody();
+ // WPUSH success is defined by JSON code == 0, not HTTP 2xx
alone
+ if (body != null && body.getCode() != null && body.getCode()
== 0) {
+ log.debug("Send WPUSH notification Success");
+ } else {
+ String msg = body == null ? "empty response body"
+ : (body.getMsg() != null ? body.getMsg() : "code="
+ body.getCode());
+ log.warn("Send WPUSH notification Failed: {}", msg);
+ throw new AlertNoticeException("WPUSH response code not 0:
" + msg);
+ }
+ } else {
+ log.warn("Send WPUSH notification Failed: Http StatusCode {}",
responseEntity.getStatusCode());
+ throw new AlertNoticeException("Http StatusCode " +
responseEntity.getStatusCode());
+ }
+ } catch (AlertNoticeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new AlertNoticeException("[WPUSH Notify Error] " +
e.getMessage());
+ }
+ }
+
+ @Override
+ public byte type() {
+ return 16;
+ }
+
+ @Data
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ protected static class WpushNotifyDto {
+ /**
+ * WPUSH API key — never log this field in cleartext
+ */
+ private String apikey;
+ private String title;
+ private String content;
+ private String channel;
+ @JsonProperty("topic_code")
+ private String topicCode;
+ }
+}
diff --git
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/util/NoticeReceiverMaskUtil.java
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/util/NoticeReceiverMaskUtil.java
index 51da9d0f52..868f82bbce 100644
---
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/util/NoticeReceiverMaskUtil.java
+++
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/util/NoticeReceiverMaskUtil.java
@@ -65,7 +65,8 @@ public final class NoticeReceiverMaskUtil {
new SecretField(NoticeReceiver::getSmnSk,
NoticeReceiver::setSmnSk),
new SecretField(NoticeReceiver::getServerChanToken,
NoticeReceiver::setServerChanToken),
new SecretField(NoticeReceiver::getGotifyToken,
NoticeReceiver::setGotifyToken),
- new SecretField(NoticeReceiver::getNtfyToken,
NoticeReceiver::setNtfyToken));
+ new SecretField(NoticeReceiver::getNtfyToken,
NoticeReceiver::setNtfyToken),
+ new SecretField(NoticeReceiver::getWpushToken,
NoticeReceiver::setWpushToken));
private NoticeReceiverMaskUtil() {
}
diff --git
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/notice/impl/WpushAlertNotifyHandlerImplTest.java
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/notice/impl/WpushAlertNotifyHandlerImplTest.java
new file mode 100644
index 0000000000..50ea34c096
--- /dev/null
+++
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/notice/impl/WpushAlertNotifyHandlerImplTest.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hertzbeat.alert.notice.impl;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ResourceBundle;
+import org.apache.hertzbeat.alert.AlerterProperties;
+import org.apache.hertzbeat.alert.notice.AlertNoticeException;
+import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
+import org.apache.hertzbeat.common.entity.alerter.NoticeReceiver;
+import org.apache.hertzbeat.common.entity.alerter.NoticeTemplate;
+import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * Test case for {@link WpushAlertNotifyHandlerImpl}
+ */
+@ExtendWith(MockitoExtension.class)
+class WpushAlertNotifyHandlerImplTest {
+
+ @Mock
+ private RestTemplate restTemplate;
+
+ @Mock
+ private AlerterProperties alerterProperties;
+
+ @Mock
+ private ResourceBundle bundle;
+
+ @InjectMocks
+ private WpushAlertNotifyHandlerImpl wpushAlertNotifyHandler;
+
+ private NoticeReceiver receiver;
+ private GroupAlert groupAlert;
+ private NoticeTemplate template;
+
+ @BeforeEach
+ public void setUp() {
+ receiver = new NoticeReceiver();
+ receiver.setId(1L);
+ receiver.setName("test-receiver");
+ receiver.setWpushToken("wpush-test-apikey-xxxxx");
+ receiver.setWpushChannel("wechat");
+ receiver.setWpushTopicCode("topic-demo");
+
+ groupAlert = new GroupAlert();
+ SingleAlert singleAlert = new SingleAlert();
+ singleAlert.setLabels(new HashMap<>());
+ singleAlert.getLabels().put("severity", "critical");
+ singleAlert.getLabels().put("alertname", "Test Alert");
+
+ List<SingleAlert> alerts = new ArrayList<>();
+ alerts.add(singleAlert);
+ groupAlert.setAlerts(alerts);
+
+ template = new NoticeTemplate();
+ template.setId(1L);
+ template.setName("test-template");
+ template.setContent("test content");
+
+ lenient().when(alerterProperties.getWpushWebhookUrl())
+ .thenReturn("https://api.wpush.cn/api/v1/send");
+
lenient().when(bundle.getString("alerter.notify.title")).thenReturn("Alert
Notification");
+ }
+
+ @Test
+ public void testType() {
+ assertEquals(16, wpushAlertNotifyHandler.type());
+ }
+
+ @Test
+ public void testNotifyAlertSuccessWhenCodeIsZero() {
+ CommonRobotNotifyResp successResp = new CommonRobotNotifyResp();
+ successResp.setCode(0);
+ successResp.setMsg("success");
+ ResponseEntity<CommonRobotNotifyResp> responseEntity =
+ new ResponseEntity<>(successResp, HttpStatus.OK);
+
+ when(restTemplate.postForEntity(
+ any(String.class),
+ any(),
+ eq(CommonRobotNotifyResp.class))).thenReturn(responseEntity);
+
+ wpushAlertNotifyHandler.send(receiver, template, groupAlert);
+
+ ArgumentCaptor<HttpEntity> entityCaptor =
ArgumentCaptor.forClass(HttpEntity.class);
+ verify(restTemplate).postForEntity(
+ eq("https://api.wpush.cn/api/v1/send"),
+ entityCaptor.capture(),
+ eq(CommonRobotNotifyResp.class));
+ WpushAlertNotifyHandlerImpl.WpushNotifyDto body =
+ (WpushAlertNotifyHandlerImpl.WpushNotifyDto)
entityCaptor.getValue().getBody();
+ assertEquals("wpush-test-apikey-xxxxx", body.getApikey());
+ assertEquals("Alert Notification", body.getTitle());
+ assertEquals("wechat", body.getChannel());
+ assertEquals("topic-demo", body.getTopicCode());
+ }
+
+ @Test
+ public void testNotifyAlertFailureWhenCodeNonZero() {
+ CommonRobotNotifyResp failResp = new CommonRobotNotifyResp();
+ failResp.setCode(1);
+ failResp.setMsg("invalid apikey");
+ ResponseEntity<CommonRobotNotifyResp> responseEntity =
+ new ResponseEntity<>(failResp, HttpStatus.OK);
+
+ when(restTemplate.postForEntity(
+ any(String.class),
+ any(),
+ eq(CommonRobotNotifyResp.class))).thenReturn(responseEntity);
+
+ assertThrows(AlertNoticeException.class,
+ () -> wpushAlertNotifyHandler.send(receiver, template,
groupAlert));
+ }
+
+ @Test
+ public void testNotifyAlertFailureWhenHttpNotOk() {
+ CommonRobotNotifyResp failResp = new CommonRobotNotifyResp();
+ failResp.setCode(0);
+ ResponseEntity<CommonRobotNotifyResp> responseEntity =
+ new ResponseEntity<>(failResp, HttpStatus.BAD_REQUEST);
+
+ when(restTemplate.postForEntity(
+ any(String.class),
+ any(),
+ eq(CommonRobotNotifyResp.class))).thenReturn(responseEntity);
+
+ assertThrows(AlertNoticeException.class,
+ () -> wpushAlertNotifyHandler.send(receiver, template,
groupAlert));
+ }
+
+ @Test
+ public void testNotifyAlertFailureWhenMissingToken() {
+ receiver.setWpushToken(null);
+ assertThrows(AlertNoticeException.class,
+ () -> wpushAlertNotifyHandler.send(receiver, template,
groupAlert));
+ }
+}
diff --git
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/util/NoticeReceiverMaskUtilTest.java
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/util/NoticeReceiverMaskUtilTest.java
index cdac126c46..4133b44fc7 100644
---
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/util/NoticeReceiverMaskUtilTest.java
+++
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/util/NoticeReceiverMaskUtilTest.java
@@ -47,6 +47,7 @@ class NoticeReceiverMaskUtilTest {
receiver.setServerChanToken("SCT193569TSNm6xIabdjqeZPtOGOWcvU1e");
receiver.setGotifyToken("A845h__ZMqDxZlO");
receiver.setNtfyToken("tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2");
+ receiver.setWpushToken("wpush-test-apikey-xxxx");
return receiver;
}
@@ -66,6 +67,7 @@ class NoticeReceiverMaskUtilTest {
assertEquals(SECRET_MASK + "vU1e", masked.getServerChanToken());
assertEquals(SECRET_MASK + "xZlO", masked.getGotifyToken());
assertEquals(SECRET_MASK + "NIz2", masked.getNtfyToken());
+ assertEquals(SECRET_MASK + "xxxx", masked.getWpushToken());
assertEquals(receiver.getId(), masked.getId());
assertEquals(receiver.getName(), masked.getName());
@@ -119,6 +121,7 @@ class NoticeReceiverMaskUtilTest {
assertEquals("NCVBODJOEYHSW3VNSMAK", incoming.getSmnAk());
assertEquals("nmSNhUJN9MlpPl8lfCsgdA0KvHCL9JSMSK",
incoming.getSmnSk());
assertEquals("SCT193569TSNm6xIabdjqeZPtOGOWcvU1e",
incoming.getServerChanToken());
+ assertEquals("wpush-test-apikey-xxxx", incoming.getWpushToken());
}
@Test
diff --git
a/hertzbeat-common-spring/src/main/java/org/apache/hertzbeat/common/entity/alerter/NoticeReceiver.java
b/hertzbeat-common-spring/src/main/java/org/apache/hertzbeat/common/entity/alerter/NoticeReceiver.java
index e31a1ac29c..edb8b84875 100644
---
a/hertzbeat-common-spring/src/main/java/org/apache/hertzbeat/common/entity/alerter/NoticeReceiver.java
+++
b/hertzbeat-common-spring/src/main/java/org/apache/hertzbeat/common/entity/alerter/NoticeReceiver.java
@@ -279,6 +279,27 @@ public class NoticeReceiver {
@Column(length = 300)
private String ntfyToken;
+ @Schema(title = "WPUSH API key (apikey) : The notification method is valid
for WPUSH",
+ description = "WPUSH API key (apikey) : The notification method is
valid for WPUSH",
+ example = "wpush-xxxxxxxxxxxxxxxx", accessMode = READ_WRITE)
+ @Size(max = 300)
+ @Column(length = 300)
+ private String wpushToken;
+
+ @Schema(title = "WPUSH channel : Optional channel, default wechat",
+ description = "WPUSH channel : Optional channel such as wechat,
default wechat",
+ example = "wechat", accessMode = READ_WRITE)
+ @Size(max = 64)
+ @Column(length = 64)
+ private String wpushChannel;
+
+ @Schema(title = "WPUSH topic_code : Optional topic code for channel
subscription",
+ description = "WPUSH topic_code : Optional topic code for channel
subscription",
+ example = "topic_demo", accessMode = READ_WRITE)
+ @Size(max = 300)
+ @Column(length = 300)
+ private String wpushTopicCode;
+
@Schema(title = "The creator of this record", example = "tom",
accessMode = READ_ONLY)
@CreatedBy
diff --git
a/hertzbeat-manager/src/main/resources/templates/16-WpushTemplate.txt
b/hertzbeat-manager/src/main/resources/templates/16-WpushTemplate.txt
new file mode 100644
index 0000000000..4f9e8deed1
--- /dev/null
+++ b/hertzbeat-manager/src/main/resources/templates/16-WpushTemplate.txt
@@ -0,0 +1,47 @@
+## 🔔 HertzBeat Alert Notification
+
+### Alert Summary
+> - Status: ${status}
+<#if commonLabels??>
+<#if commonLabels.severity??>
+> - Severity: ${commonLabels.severity?switch("critical", "❤️ Critical",
"warning", "💛 Warning", "info", "💚 Info", "Unknown")}
+</#if>
+<#if commonLabels.alertname??>
+> - Alert Name: ${commonLabels.alertname}
+</#if>
+</#if>
+
+### Alert Details
+<#list alerts as alert>
+#### Alert ${alert?index + 1}
+<#if alert.labels??>
+<#list alert.labels?keys as key>
+> - ${key}: ${alert.labels[key]}
+</#list>
+</#if>
+<#if alert.content?? && alert.content != "">
+> - Content: ${alert.content}
+</#if>
+> - Trigger Count: ${alert.triggerTimes}
+> - Start Time: ${(alert.startAt?number_to_datetime)?string('yyyy-MM-dd
HH:mm:ss')}
+<#if alert.activeAt??>
+> - Active Time: ${(alert.activeAt?number_to_datetime)?string('yyyy-MM-dd
HH:mm:ss')}
+</#if>
+<#if alert.endAt??>
+> - End Time: ${(alert.endAt?number_to_datetime)?string('yyyy-MM-dd HH:mm:ss')}
+</#if>
+
+<#if alert.annotations?? && alert.annotations?size gt 0>
+##### Additional Information
+<#list alert.annotations?keys as key>
+> - ${key}: ${alert.annotations[key]}
+</#list>
+</#if>
+</#list>
+
+<#if commonAnnotations?? && commonAnnotations?size gt 0>
+### Common Information
+<#list commonAnnotations?keys as key>
+> - ${key}: ${commonAnnotations[key]}
+</#list>
+</#if>
diff --git a/web-app/src/app/pojo/NoticeReceiver.ts
b/web-app/src/app/pojo/NoticeReceiver.ts
index d9bf032d32..8c9c7c75f7 100644
--- a/web-app/src/app/pojo/NoticeReceiver.ts
+++ b/web-app/src/app/pojo/NoticeReceiver.ts
@@ -22,7 +22,7 @@ export class NoticeReceiver {
name!: string;
// notification mode: 0-sms 1-email 2-webhook 3-wechat public account 4-work
wechat robot 5-Dingding robot 6-Feishu robot
// 7-Telegram robot 8-SlackWebHook 9-Discord robot 10-work wechat app
message 11-Huawei cloud SMN 12-ServerChan 13-Gotify
- // 14-FeiShu app message 15-Ntfy
+ // 14-FeiShu app message 15-Ntfy 16-WPUSH
type: number = 1;
phone!: string;
email!: string;
@@ -53,6 +53,9 @@ export class NoticeReceiver {
ntfyServerUrl!: string;
ntfyTopic!: string;
ntfyToken!: string;
+ wpushToken!: string;
+ wpushChannel!: string;
+ wpushTopicCode!: string;
creator!: string;
modifier!: string;
gmtCreate!: number;
diff --git
a/web-app/src/app/routes/alert/alert-notice/alert-notice-receiver/alert-notice-receiver.component.html
b/web-app/src/app/routes/alert/alert-notice/alert-notice-receiver/alert-notice-receiver.component.html
index 1469982ce0..785da7f07e 100644
---
a/web-app/src/app/routes/alert/alert-notice/alert-notice-receiver/alert-notice-receiver.component.html
+++
b/web-app/src/app/routes/alert/alert-notice/alert-notice-receiver/alert-notice-receiver.component.html
@@ -135,6 +135,10 @@
<i nz-icon nzTheme="outline" nzType="notification"></i>
<span>{{ 'alert.notice.type.ntfy' | i18n }}</span>
</nz-tag>
+ <nz-tag *ngIf="data.type == 16" nzColor="orange">
+ <i nz-icon nzTheme="outline" nzType="notification"></i>
+ <span>{{ 'alert.notice.type.wpush' | i18n }}</span>
+ </nz-tag>
</td>
<td nzAlign="center">
<span *ngIf="data.type == 0">{{ data.phone }}</span>
@@ -153,6 +157,7 @@
<span *ngIf="data.type == 13">{{ data.gotifyToken }}</span>
<span *ngIf="data.type == 14">{{ data.appId }}</span>
<span *ngIf="data.type == 15">{{ data.ntfyServerUrl }}/{{
data.ntfyTopic }}</span>
+ <span *ngIf="data.type == 16">{{ data.wpushChannel || 'wechat'
}}</span>
</td>
<td nzAlign="center">{{ (data.gmtUpdate ? data.gmtUpdate :
data.gmtCreate) | date : 'YYYY-MM-dd HH:mm:ss' }}</td>
<td nzAlign="center" nzRight>
@@ -236,6 +241,7 @@
<nz-option [nzLabel]="'alert.notice.type.gotify' | i18n"
[nzValue]="13"></nz-option>
<nz-option [nzLabel]="'alert.notice.type.lark-app' | i18n"
[nzValue]="14"></nz-option>
<nz-option [nzLabel]="'alert.notice.type.ntfy' | i18n"
[nzValue]="15"></nz-option>
+ <nz-option [nzLabel]="'alert.notice.type.wpush' | i18n"
[nzValue]="16"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
@@ -554,6 +560,26 @@
<input [(ngModel)]="receiver.ntfyToken" name="ntfyToken" nz-input
type="password" placeholder="" />
</nz-form-control>
</nz-form-item>
+ <nz-form-item *ngIf="receiver.type === 16">
+ <nz-form-label [nzRequired]="receiver.type === 16" [nzSpan]="7"
nzFor="wpushToken"
+ >{{ 'alert.notice.type.wpush-token' | i18n }}
+ </nz-form-label>
+ <nz-form-control [nzErrorTip]="'validation.required' | i18n"
[nzSpan]="12">
+ <input [(ngModel)]="receiver.wpushToken" [required]="receiver.type
=== 16" name="wpushToken" nz-input type="password" />
+ </nz-form-control>
+ </nz-form-item>
+ <nz-form-item *ngIf="receiver.type === 16">
+ <nz-form-label [nzSpan]="7" nzFor="wpushChannel">{{
'alert.notice.type.wpush-channel' | i18n }}</nz-form-label>
+ <nz-form-control [nzSpan]="12">
+ <input [(ngModel)]="receiver.wpushChannel" name="wpushChannel"
nz-input type="text" placeholder="wechat" />
+ </nz-form-control>
+ </nz-form-item>
+ <nz-form-item *ngIf="receiver.type === 16">
+ <nz-form-label [nzSpan]="7" nzFor="wpushTopicCode">{{
'alert.notice.type.wpush-topic-code' | i18n }}</nz-form-label>
+ <nz-form-control [nzSpan]="12">
+ <input [(ngModel)]="receiver.wpushTopicCode" name="wpushTopicCode"
nz-input type="text" />
+ </nz-form-control>
+ </nz-form-item>
<nz-form-item *ngIf="receiver.type === 14">
<nz-form-label [nzRequired]="receiver.type === 14" [nzSpan]="7"
nzFor="appId">
{{ 'alert.notice.type.lark-app-appId' | i18n }}
diff --git
a/web-app/src/app/routes/alert/alert-notice/alert-notice-template/alert-notice-template.component.html
b/web-app/src/app/routes/alert/alert-notice/alert-notice-template/alert-notice-template.component.html
index c5ca96413c..c29935aac4 100644
---
a/web-app/src/app/routes/alert/alert-notice/alert-notice-template/alert-notice-template.component.html
+++
b/web-app/src/app/routes/alert/alert-notice/alert-notice-template/alert-notice-template.component.html
@@ -120,6 +120,12 @@
<nz-tag *ngIf="data.type == 14" nzColor="orange">
<span>{{ 'alert.notice.type.lark-app' | i18n }}</span>
</nz-tag>
+ <nz-tag *ngIf="data.type == 15" nzColor="orange">
+ <span>{{ 'alert.notice.type.ntfy' | i18n }}</span>
+ </nz-tag>
+ <nz-tag *ngIf="data.type == 16" nzColor="orange">
+ <span>{{ 'alert.notice.type.wpush' | i18n }}</span>
+ </nz-tag>
</span>
</td>
<td nzAlign="center">
@@ -216,6 +222,8 @@
<nz-option [nzLabel]="'alert.notice.type.serverchan' | i18n"
[nzValue]="12"></nz-option>
<nz-option [nzLabel]="'alert.notice.type.gotify' | i18n"
[nzValue]="13"></nz-option>
<nz-option [nzLabel]="'alert.notice.type.lark-app' | i18n"
[nzValue]="14"></nz-option>
+ <nz-option [nzLabel]="'alert.notice.type.ntfy' | i18n"
[nzValue]="15"></nz-option>
+ <nz-option [nzLabel]="'alert.notice.type.wpush' | i18n"
[nzValue]="16"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
diff --git a/web-app/src/assets/i18n/en-US.json
b/web-app/src/assets/i18n/en-US.json
index 3b0607042b..9e22fd842a 100644
--- a/web-app/src/assets/i18n/en-US.json
+++ b/web-app/src/assets/i18n/en-US.json
@@ -219,6 +219,10 @@
"alert.notice.type.ntfy-server-url": "Ntfy Server URL",
"alert.notice.type.ntfy-topic": "Ntfy Topic",
"alert.notice.type.ntfy-token": "Ntfy Access Token",
+ "alert.notice.type.wpush": "WPUSH",
+ "alert.notice.type.wpush-token": "WPUSH API Key",
+ "alert.notice.type.wpush-channel": "WPUSH Channel",
+ "alert.notice.type.wpush-topic-code": "WPUSH Topic Code",
"alert.notice.type.phone": "Phone",
"alert.notice.type.serverchan": "ServerChan",
"alert.notice.type.serverchan-token": "ServerChanToken",
diff --git a/web-app/src/assets/i18n/ja-JP.json
b/web-app/src/assets/i18n/ja-JP.json
index e523c9d9ef..b7af980c88 100644
--- a/web-app/src/assets/i18n/ja-JP.json
+++ b/web-app/src/assets/i18n/ja-JP.json
@@ -206,6 +206,10 @@
"alert.notice.type.ntfy-server-url": "Ntfy サーバーURL",
"alert.notice.type.ntfy-topic": "Ntfy トピック",
"alert.notice.type.ntfy-token": "Ntfy アクセストークン",
+ "alert.notice.type.wpush": "WPUSH",
+ "alert.notice.type.wpush-token": "WPUSH API Key",
+ "alert.notice.type.wpush-channel": "WPUSH チャネル",
+ "alert.notice.type.wpush-topic-code": "WPUSH Topic Code",
"alert.notice.type.phone": "電話",
"alert.notice.type.serverchan": "ServerChan",
"alert.notice.type.serverchan-token": "ServerChanトークン",
diff --git a/web-app/src/assets/i18n/ko-KR.json
b/web-app/src/assets/i18n/ko-KR.json
index 8f4641fbd2..46bc31dd69 100644
--- a/web-app/src/assets/i18n/ko-KR.json
+++ b/web-app/src/assets/i18n/ko-KR.json
@@ -219,6 +219,10 @@
"alert.notice.type.ntfy-server-url": "Ntfy 서버 URL",
"alert.notice.type.ntfy-topic": "Ntfy Topic",
"alert.notice.type.ntfy-token": "Ntfy 액세스 토큰",
+ "alert.notice.type.wpush": "WPUSH",
+ "alert.notice.type.wpush-token": "WPUSH API Key",
+ "alert.notice.type.wpush-channel": "WPUSH 채널",
+ "alert.notice.type.wpush-topic-code": "WPUSH Topic Code",
"alert.notice.type.phone": "전화",
"alert.notice.type.serverchan": "ServerChan",
"alert.notice.type.serverchan-token": "ServerChanToken",
diff --git a/web-app/src/assets/i18n/pt-BR.json
b/web-app/src/assets/i18n/pt-BR.json
index bec7bae3f7..f0cf435aed 100644
--- a/web-app/src/assets/i18n/pt-BR.json
+++ b/web-app/src/assets/i18n/pt-BR.json
@@ -205,6 +205,10 @@
"alert.notice.type.ntfy-server-url": "URL do Servidor Ntfy",
"alert.notice.type.ntfy-topic": "Tópico Ntfy",
"alert.notice.type.ntfy-token": "Token de Acesso Ntfy",
+ "alert.notice.type.wpush": "WPUSH",
+ "alert.notice.type.wpush-token": "Chave API do WPUSH",
+ "alert.notice.type.wpush-channel": "Canal WPUSH",
+ "alert.notice.type.wpush-topic-code": "Código do Tópico WPUSH",
"alert.notice.rule": "Política de Notificação",
"alert.notice.rule.new": "Nova Política de Notificação",
"alert.notice.rule.edit": "Editar Política de Notificação",
diff --git a/web-app/src/assets/i18n/zh-CN.json
b/web-app/src/assets/i18n/zh-CN.json
index 54fc54453b..723dc68118 100644
--- a/web-app/src/assets/i18n/zh-CN.json
+++ b/web-app/src/assets/i18n/zh-CN.json
@@ -219,6 +219,10 @@
"alert.notice.type.ntfy-server-url": "Ntfy 服务器地址",
"alert.notice.type.ntfy-topic": "Ntfy 主题",
"alert.notice.type.ntfy-token": "Ntfy 访问令牌",
+ "alert.notice.type.wpush": "WPUSH",
+ "alert.notice.type.wpush-token": "WPUSH API Key",
+ "alert.notice.type.wpush-channel": "WPUSH 渠道",
+ "alert.notice.type.wpush-topic-code": "WPUSH Topic Code",
"alert.notice.type.phone": "手机号",
"alert.notice.type.serverchan": "Server酱(ServerChan)",
"alert.notice.type.serverchan-token": "Server酱Token",
diff --git a/web-app/src/assets/i18n/zh-TW.json
b/web-app/src/assets/i18n/zh-TW.json
index 145f01493b..276a5f8444 100644
--- a/web-app/src/assets/i18n/zh-TW.json
+++ b/web-app/src/assets/i18n/zh-TW.json
@@ -205,6 +205,10 @@
"alert.notice.type.ntfy-server-url": "Ntfy 伺服器地址",
"alert.notice.type.ntfy-topic": "Ntfy 主題",
"alert.notice.type.ntfy-token": "Ntfy 存取權杖",
+ "alert.notice.type.wpush": "WPUSH",
+ "alert.notice.type.wpush-token": "WPUSH API Key",
+ "alert.notice.type.wpush-channel": "WPUSH 渠道",
+ "alert.notice.type.wpush-topic-code": "WPUSH Topic Code",
"alert.notice.type.phone": "手機號",
"alert.notice.type.serverchan": "ServerChan",
"alert.notice.type.serverchan-token": "ServerChanToken",
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]