From 6f72ddbb7213a5007552974198e74b7f919a3abe Mon Sep 17 00:00:00 2001
From: Teror Fox <i@trfox.top>
Date: Sat, 22 Mar 2025 13:40:19 +0800
Subject: [PATCH] =?UTF-8?q?feat(notification):=20=E6=96=B0=E5=A2=9E=20Push?=
 =?UTF-8?q?PlusPlus=20=E9=80=9A=E7=9F=A5=E6=94=AF=E6=8C=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

- 在 notification.js 中添加 PushPlusPlus 通知提供商
- 在 NotificationDialog.vue 中添加 PushPlusPlus 选项
- 在 notifications/index.js 中导入并注册 PushPlusPlus 组件
---
 server/notification-providers/pushplusplus.js | 42 +++++++++++++++++++
 server/notification.js                        |  4 +-
 src/components/NotificationDialog.vue         |  1 +
 src/components/notifications/PushPlusPlus.vue | 16 +++++++
 src/components/notifications/index.js         |  2 +
 5 files changed, 64 insertions(+), 1 deletion(-)
 create mode 100644 server/notification-providers/pushplusplus.js
 create mode 100644 src/components/notifications/PushPlusPlus.vue

diff --git a/server/notification-providers/pushplusplus.js b/server/notification-providers/pushplusplus.js
new file mode 100644
index 000000000..1568a5b30
--- /dev/null
+++ b/server/notification-providers/pushplusplus.js
@@ -0,0 +1,42 @@
+const NotificationProvider = require("./notification-provider");
+const axios = require("axios");
+const { DOWN, UP } = require("../../src/util");
+
+class PushPlusPlus extends NotificationProvider {
+    name = "PushPlusPlus";
+
+    async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
+        const okMsg = "Sent Successfully.";
+        const url = `https://pushplus.plus/send`;
+        try {
+            await axios.post(notification.pushPlusPlusToken, {
+                "title": this.checkStatus(heartbeatJSON, monitorJSON),
+                "content": msg,
+            });
+
+            return okMsg;
+
+        } catch (error) {
+            this.throwGeneralAxiosError(error);
+        }
+    }
+
+    /**
+     * Get the formatted title for message
+     * @param {?object} heartbeatJSON Heartbeat details (For Up/Down only)
+     * @param {?object} monitorJSON Monitor details (For Up/Down only)
+     * @returns {string} Formatted title
+     */
+    checkStatus(heartbeatJSON, monitorJSON) {
+        let title = "UptimeKuma Message";
+        if (heartbeatJSON != null && heartbeatJSON["status"] === UP) {
+            title = "UptimeKuma Monitor Up " + monitorJSON["name"];
+        }
+        if (heartbeatJSON != null && heartbeatJSON["status"] === DOWN) {
+            title = "UptimeKuma Monitor Down " + monitorJSON["name"];
+        }
+        return title;
+    }
+}
+
+module.exports = PushPlusPlus;
\ No newline at end of file
diff --git a/server/notification.js b/server/notification.js
index a77094ac9..70b71b68b 100644
--- a/server/notification.js
+++ b/server/notification.js
@@ -39,6 +39,7 @@ const PromoSMS = require("./notification-providers/promosms");
 const Pushbullet = require("./notification-providers/pushbullet");
 const PushDeer = require("./notification-providers/pushdeer");
 const Pushover = require("./notification-providers/pushover");
+const PushPlusPlus = require("./notification-providers/pushplusplus");
 const Pushy = require("./notification-providers/pushy");
 const RocketChat = require("./notification-providers/rocket-chat");
 const SerwerSMS = require("./notification-providers/serwersms");
@@ -158,7 +159,8 @@ class Notification {
             new Cellsynt(),
             new Wpush(),
             new SendGrid(),
-            new YZJ()
+            new YZJ(),
+            new PushPlusPlus()
         ];
         for (let item of list) {
             if (! item.name) {
diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue
index 561637ec0..ffcb7936f 100644
--- a/src/components/NotificationDialog.vue
+++ b/src/components/NotificationDialog.vue
@@ -182,6 +182,7 @@ export default {
                 "SMSManager": "SmsManager (smsmanager.cz)",
                 "WeCom": "WeCom (企业微信群机器人)",
                 "ServerChan": "ServerChan (Server酱)",
+                "PushPlusPlus": "PushPlusPlus(推送加)",
                 "smsc": "SMSC",
                 "WPush": "WPush(wpush.cn)",
                 "YZJ": "YZJ (云之家自定义机器人)"
diff --git a/src/components/notifications/PushPlusPlus.vue b/src/components/notifications/PushPlusPlus.vue
new file mode 100644
index 000000000..285f8ffff
--- /dev/null
+++ b/src/components/notifications/PushPlusPlus.vue
@@ -0,0 +1,16 @@
+<template>
+    <div class="mb-3">
+        <label for="pushplusplus-sendkey" class="form-label">{{ $t("SendKey") }}</label>
+        <HiddenInput id="pushplusplus-sendkey" v-model="$parent.notification.pushPlusPlusSendKey" :required="true" autocomplete="new-password"></HiddenInput>
+    </div>
+</template>
+
+<script>
+import HiddenInput from "../HiddenInput.vue";
+
+export default {
+    components: {
+        HiddenInput,
+    },
+};
+</script>
\ No newline at end of file
diff --git a/src/components/notifications/index.js b/src/components/notifications/index.js
index c1162da92..d6c719722 100644
--- a/src/components/notifications/index.js
+++ b/src/components/notifications/index.js
@@ -39,6 +39,7 @@ import PromoSMS from "./PromoSMS.vue";
 import Pushbullet from "./Pushbullet.vue";
 import PushDeer from "./PushDeer.vue";
 import Pushover from "./Pushover.vue";
+import PushPlusPlus from "./PushPlusPlus.vue";
 import Pushy from "./Pushy.vue";
 import RocketChat from "./RocketChat.vue";
 import ServerChan from "./ServerChan.vue";
@@ -116,6 +117,7 @@ const NotificationFormList = {
     "PushByTechulus": TechulusPush,
     "PushDeer": PushDeer,
     "pushover": Pushover,
+    "pushplusplus": PushPlusPlus,
     "pushy": Pushy,
     "rocket.chat": RocketChat,
     "serwersms": SerwerSMS,