diff --git a/server/model/monitor.js b/server/model/monitor.js index b2fed86f..46c94e81 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -241,12 +241,18 @@ class Monitor extends BeanModel { /** * Encode user and password to Base64 encoding * for HTTP "basic" auth, as per RFC-7617 +<<<<<<< HEAD * @param {string} user Username to encode * @param {string} pass Password to encode * @returns {string} Encoded username:password +======= + * @param {string|null} user - The username (nullable if not changed by a user) + * @param {string|null} pass - The password (nullable if not changed by a user) + * @returns {string} +>>>>>>> notification-provider-cellsynt-mobile-services */ encodeBase64(user, pass) { - return Buffer.from(user + ":" + pass).toString("base64"); + return Buffer.from(`${user || ""}:${pass || ""}`).toString("base64"); } /** @@ -595,8 +601,12 @@ class Monitor extends BeanModel { let data = res.data; // convert data to object - if (typeof data === "string") { - data = JSON.parse(data); + if (typeof data === "string" && res.headers["content-type"] !== "application/json") { + try { + data = JSON.parse(data); + } catch (_) { + // Failed to parse as JSON, just process it as a string + } } let expression = jsonata(this.jsonPath); diff --git a/server/monitor-types/real-browser-monitor-type.js b/server/monitor-types/real-browser-monitor-type.js index 23493b7c..b0bff6d7 100644 --- a/server/monitor-types/real-browser-monitor-type.js +++ b/server/monitor-types/real-browser-monitor-type.js @@ -10,6 +10,10 @@ const jwt = require("jsonwebtoken"); const config = require("../config"); const { RemoteBrowser } = require("../remote-browser"); +/** + * Cached instance of a browser + * @type {import ("playwright-core").Browser} + */ let browser = null; let allowedList = []; @@ -71,10 +75,16 @@ async function isAllowedChromeExecutable(executablePath) { /** * Get the current instance of the browser. If there isn't one, create * it. +<<<<<<< HEAD * @returns {Promise} The browser +======= + * @returns {Promise} The browser +>>>>>>> notification-provider-cellsynt-mobile-services */ async function getBrowser() { - if (!browser) { + if (browser && browser.isConnected()) { + return browser; + } else { let executablePath = await Settings.get("chromeExecutable"); executablePath = await prepareChromeExecutable(executablePath); @@ -83,8 +93,9 @@ async function getBrowser() { //headless: false, executablePath, }); + + return browser; } - return browser; } /** diff --git a/server/notification-providers/cellsynt.js b/server/notification-providers/cellsynt.js new file mode 100644 index 00000000..d2c4fe6c --- /dev/null +++ b/server/notification-providers/cellsynt.js @@ -0,0 +1,127 @@ +const NotificationProvider = require("./notification-provider"); +const { default: axios } = require("axios"); + +class Cellsynt extends NotificationProvider { + + name = "Cellsynt"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + let okMsg = "Sent Successfully."; + + try { + let data = { + params: { + /* Your username (received when account is setup). + */ + "username": notification.cellsyntLogin, + + /* Your password to use together with the username for + authentication (received when account is setup). + */ + "password": notification.cellsyntPassword, + + /* Recipient's telephone number on international format with + leading 00 followed by country code, e.g. 00447920110000 for + UK number 07920 110 000 (max 17 digits in total). + To send the same message to multiple recipients, separate + numbers with comma. Max 25000 recipients per HTTP request. + */ + "destination": notification.cellsyntDestination, + + "text": msg.replace(/[^\x00-\x7F]/g, ""), + /* Character set text and other data is sent as in the HTTP + request. Possible values: ISO-8859-1 (default) and UTF-8 + */ + "charset": "UTF-8", + + /* Controls the originator type the message should be sent with. + Possible values: numeric, shortcode and alpha. + */ + "originatortype": notification.Originatortype, + + /* Identifier which will be visible on recipient's mobile phone as + originator of the message. Allowed values and function depends + on parameter originatortype's value according to below: + ** alpha ** + 3Send SMS + Alphanumeric string (max 11 characters). The following + characters are guaranteed to work: a-z, A-Z and 0-9. Other + characters may work but functionality can not be guaranteed. + Recipients can not reply to messages with alphanumeric + originators + ** numeric ** + Numeric value (max 15 digits) with telephone number on + international format without leading 00 (example UK number + 07920 110 000 should be set as 447920110000). Receiving + mobile phone will add a leading + sign and thus see the + originator as a normal mobile phone number (+447920110000). + Therefore it is also possible to reply to the message. + */ + //"originator": "uptime-kuma", + "originator": notification.cellsyntOriginator, + /* Type of message that should be sent. Possible values: text + (default), binary and unicode */ + //"type": "text", + + /* Maximum number of SMS permitted to be linked together when + needed (default value is 1, see Long SMS). Maximum value is 6 + (i.e. max 153 x 6 = 918 characters). + */ + "allowconcat": notification.cellsyntAllowLongSMS?6:1, + + /* Value can be set to true if message should be sent as "flash + message", i.e. displayed directly on phone screen instead of + being saved to inbox. This is identical to setting class=0. + Please note that support for flash messages cannot be + guaranteed to all operator networks. If flash is not supported the + message will be sent as a regular text message instead + (class=1). + */ + //"flash": "", + + /* Message class can be set to 0 (flash message), 1 (default, MEspecific), 2 (SIM-specific) or 3 (TE-specific). + */ + //"class": "", + + /* UDH (User Data Header) can be used to send concatenated + SMS, contain formatting information, convey port numbers as a + mean to cause start of an application etc. The value should be + given on hexadecimal format for the corresponding bytes you + wish to send (e.g. AABBCC). + */ + //"udh": "", + + /* Protocol Identifier (specified in GSM 03.40) says how the + message should be interpreted. Value should be given on + hexadecimal format, e.g. 00 for a regular message and 7D + (decimal 125) for a configuration message ("ME Data + download"). + */ + //"pid": "", + } + }; + try { + if (heartbeatJSON != null) { + msg = msg; + data.params.text = msg.replace(/[^\x00-\x7F]/g, ""); + } + + let resp = await axios.post("https://se-1.cellsynt.net/sms.php", null, data); + if(typeof resp.data == undefined || resp.data == null || resp.data.includes("Error")) { + this.throwGeneralAxiosError(resp.data); + } + }catch (error) { + this.throwGeneralAxiosError(error); + } + + return okMsg; + } catch (error) { + this.throwGeneralAxiosError(error); + } + } +} + +module.exports = Cellsynt; diff --git a/server/notification-providers/dingding.js b/server/notification-providers/dingding.js index be3a2fbc..6297ef49 100644 --- a/server/notification-providers/dingding.js +++ b/server/notification-providers/dingding.js @@ -21,7 +21,7 @@ class DingDing extends NotificationProvider { text: `## [${this.statusToString(heartbeatJSON["status"])}] ${monitorJSON["name"]} \n> ${heartbeatJSON["msg"]}\n> Time (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`, } }; - if (this.sendToDingDing(notification, params)) { + if (await this.sendToDingDing(notification, params)) { return okMsg; } } else { @@ -31,7 +31,7 @@ class DingDing extends NotificationProvider { content: msg } }; - if (this.sendToDingDing(notification, params)) { + if (await this.sendToDingDing(notification, params)) { return okMsg; } } @@ -62,7 +62,7 @@ class DingDing extends NotificationProvider { if (result.data.errmsg === "ok") { return true; } - return false; + throw new Error(result.data.errmsg); } /** diff --git a/server/notification.js b/server/notification.js index b21f270c..08b39a18 100644 --- a/server/notification.js +++ b/server/notification.js @@ -54,7 +54,11 @@ const GoAlert = require("./notification-providers/goalert"); const SMSManager = require("./notification-providers/smsmanager"); const ServerChan = require("./notification-providers/serverchan"); const ZohoCliq = require("./notification-providers/zoho-cliq"); +<<<<<<< HEAD const CellsyntMobileServices = require("./notification-providers/cellsyntmobileservices"); +======= +const Cellsynt = require("./notification-providers/cellsynt"); +>>>>>>> notification-provider-cellsynt-mobile-services class Notification { @@ -126,7 +130,11 @@ class Notification { new WeCom(), new GoAlert(), new ZohoCliq(), +<<<<<<< HEAD new CellsyntMobileServices() +======= + new Cellsynt() +>>>>>>> notification-provider-cellsynt-mobile-services ]; for (let item of list) { if (! item.name) { diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue index 580a1bd2..d051a022 100644 --- a/src/components/NotificationDialog.vue +++ b/src/components/NotificationDialog.vue @@ -151,7 +151,8 @@ export default { "Splunk": "Splunk", "webhook": "Webhook", "GoAlert": "GoAlert", - "ZohoCliq": "ZohoCliq" + "ZohoCliq": "ZohoCliq", + "Cellsynt": "Cellsynt" }; // Put notifications here if it's not supported in most regions or its documentation is not in English diff --git a/src/components/notifications/Cellsynt.vue b/src/components/notifications/Cellsynt.vue new file mode 100644 index 00000000..11bf3257 --- /dev/null +++ b/src/components/notifications/Cellsynt.vue @@ -0,0 +1,59 @@ + + + diff --git a/src/components/notifications/index.js b/src/components/notifications/index.js index 51f27c80..5667001f 100644 --- a/src/components/notifications/index.js +++ b/src/components/notifications/index.js @@ -52,7 +52,12 @@ import WeCom from "./WeCom.vue"; import GoAlert from "./GoAlert.vue"; import ZohoCliq from "./ZohoCliq.vue"; import Splunk from "./Splunk.vue"; +<<<<<<< HEAD import CellsyntMobileServices from "./CellsyntMobileServices.vue"; +======= +import Cellsynt from "./Cellsynt.vue"; + +>>>>>>> notification-provider-cellsynt-mobile-services /** * Manage all notification form. @@ -113,7 +118,11 @@ const NotificationFormList = { "GoAlert": GoAlert, "ServerChan": ServerChan, "ZohoCliq": ZohoCliq, +<<<<<<< HEAD "CellsyntMobileServices": CellsyntMobileServices, +======= + "Cellsynt": Cellsynt +>>>>>>> notification-provider-cellsynt-mobile-services }; export default NotificationFormList; diff --git a/src/i18n.js b/src/i18n.js index 3a636c35..cb6c5280 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -59,10 +59,16 @@ for (let lang in languageList) { const rtlLangs = [ "fa", "ar-SY", "ur" ]; -export const currentLocale = () => localStorage.locale - || languageList[navigator.language] && navigator.language - || languageList[navigator.language.substring(0, 2)] && navigator.language.substring(0, 2) - || "en"; +/** + * Find the best matching locale to display + * If no locale can be matched, the default is "en" + * @returns {string} the locale that should be displayed + */ +export function currentLocale() { + const potentialLocales = [ localStorage.locale, navigator.language, navigator.language.substring(0, 2), ...navigator.languages ]; + const availableLocales = potentialLocales.filter(l => languageList[l]); + return availableLocales[0] || "en"; +} export const localeDirection = () => { return rtlLangs.includes(currentLocale()) ? "rtl" : "ltr"; diff --git a/test/cypress/unit/i18n.spec.js b/test/cypress/unit/i18n.spec.js new file mode 100644 index 00000000..c53f341f --- /dev/null +++ b/test/cypress/unit/i18n.spec.js @@ -0,0 +1,48 @@ +import { currentLocale } from "../../../src/i18n"; + +describe("Test i18n.js", () => { + + it("currentLocale()", () => { + const setLanguage = (language) => { + Object.defineProperty(window.navigator, 'language', { + value: language, + writable: true + }); + Object.defineProperty(window.navigator, 'languages', { + value: [language], + writable: true + }); + } + setLanguage('en-EN'); + + expect(currentLocale()).equal("en"); + + setLanguage('zh-HK'); + expect(currentLocale()).equal("zh-HK"); + + // Note that in Safari on iOS prior to 10.2, the country code returned is lowercase: "en-us", "fr-fr" etc. + // https://developer.mozilla.org/en-US/docs/Web/API/Navigator/language + setLanguage('zh-hk'); + expect(currentLocale()).equal("en"); + + setLanguage('en-US'); + expect(currentLocale()).equal("en"); + + setLanguage('ja-ZZ'); + expect(currentLocale()).equal("ja"); + + setLanguage('zz-ZZ'); + expect(currentLocale()).equal("en"); + + setLanguage('zz-ZZ'); + expect(currentLocale()).equal("en"); + + setLanguage('en'); + localStorage.locale = "en"; + expect(currentLocale()).equal("en"); + + localStorage.locale = "zh-HK"; + expect(currentLocale()).equal("zh-HK"); + }); + +});