feat(notification): add BearSMS SMS provider for Israel (#7638)

This commit is contained in:
Nitay Caspi
2026-08-04 16:15:22 +03:00
committed by GitHub
parent 948fdd78a9
commit 540340488b
6 changed files with 119 additions and 0 deletions
+54
View File
@@ -0,0 +1,54 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
class BearSMS extends NotificationProvider {
name = "bearsms";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
const okMsg = "Sent Successfully.";
try {
// BearSMS rejects messages containing emoji (astral characters) with error 200
const cleanMsg = msg.replaceAll("🔴 ", "").replaceAll("✅ ", "");
const params = new URLSearchParams({
app: "ws",
u: notification.bearsmsUsername,
h: notification.bearsmsHashKey,
op: "pv",
to: notification.bearsmsPhoneNumber,
msg: cleanMsg,
});
if (notification.bearsmsSenderId) {
params.append("from", notification.bearsmsSenderId);
}
// Non-GSM text (e.g. Hebrew) must be flagged as unicode
if (/[^\x00-\x7F]/.test(cleanMsg)) {
params.append("unicode", "1");
}
const url = `https://app.bearsms.com/index.php?${params.toString()}`;
let config = this.getAxiosConfigWithProxy({});
const response = await axios.get(url, config);
// BearSMS responds with HTTP 200 even on failure.
// Failure: {"status":"ERR","error":"100","error_string":"authentication failed"}
// Success: {"data":[{"status":"OK","error":"0","smslog_id":"..."}],"error_string":null}
const data = response.data;
const results = Array.isArray(data?.data) ? data.data : [];
if (data?.status === "ERR" || data?.error_string || !results.some((r) => r.status === "OK")) {
throw new Error(data?.error_string || JSON.stringify(data));
}
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
}
module.exports = BearSMS;
+2
View File
@@ -6,6 +6,7 @@ const AliyunSms = require("./notification-providers/aliyun-sms");
const Apprise = require("./notification-providers/apprise"); const Apprise = require("./notification-providers/apprise");
const Bale = require("./notification-providers/bale"); const Bale = require("./notification-providers/bale");
const Bark = require("./notification-providers/bark"); const Bark = require("./notification-providers/bark");
const BearSMS = require("./notification-providers/bearsms");
const Bitrix24 = require("./notification-providers/bitrix24"); const Bitrix24 = require("./notification-providers/bitrix24");
const ClickSendSMS = require("./notification-providers/clicksendsms"); const ClickSendSMS = require("./notification-providers/clicksendsms");
const CallMeBot = require("./notification-providers/call-me-bot"); const CallMeBot = require("./notification-providers/call-me-bot");
@@ -124,6 +125,7 @@ class Notification {
new Apprise(), new Apprise(),
new Bale(), new Bale(),
new Bark(), new Bark(),
new BearSMS(),
new Bitrix24(), new Bitrix24(),
new ClickSendSMS(), new ClickSendSMS(),
new CallMeBot(), new CallMeBot(),
+1
View File
@@ -323,6 +323,7 @@ export default {
// Regional - Not supported in most regions or documentation is not in English // Regional - Not supported in most regions or documentation is not in English
let regional = { let regional = {
AliyunSMS: "AliyunSMS (阿里云短信服务)", AliyunSMS: "AliyunSMS (阿里云短信服务)",
bearsms: "BearSMS (Israel)",
egosms: "EgoSMS (Uganda)", egosms: "EgoSMS (Uganda)",
DingDing: "DingDing (钉钉自定义机器人)", DingDing: "DingDing (钉钉自定义机器人)",
Feishu: "Feishu (飞书)", Feishu: "Feishu (飞书)",
+56
View File
@@ -0,0 +1,56 @@
<template>
<div class="mb-3">
<label for="bearsms-username" class="form-label">{{ $t("API Username") }}</label>
<i18n-t tag="div" class="form-text" keypath="wayToGetBearSMSToken">
<a href="https://app.bearsms.com/" target="_blank">{{ $t("here") }}</a>
</i18n-t>
<input
id="bearsms-username"
v-model="$parent.notification.bearsmsUsername"
type="text"
class="form-control"
required
/>
</div>
<div class="mb-3">
<label for="bearsms-hashkey" class="form-label">{{ $t("Hash Key") }}</label>
<HiddenInput
id="bearsms-hashkey"
v-model="$parent.notification.bearsmsHashKey"
:required="true"
autocomplete="new-password"
></HiddenInput>
</div>
<div class="mb-3">
<label for="bearsms-senderId" class="form-label">{{ $t("From Name/Number") }}</label>
<input
id="bearsms-senderId"
v-model="$parent.notification.bearsmsSenderId"
type="text"
maxlength="11"
class="form-control"
/>
<div class="form-text">{{ $t("bearsmsSenderDescription") }}</div>
</div>
<div class="mb-3">
<label for="bearsms-phoneNumber" class="form-label">{{ $t("Recipient Number") }}</label>
<input
id="bearsms-phoneNumber"
v-model="$parent.notification.bearsmsPhoneNumber"
type="text"
class="form-control"
placeholder="9725XXXXXXXX"
required
/>
<div class="form-text">{{ $t("bearsmsPhoneNumberDescription") }}</div>
</div>
</template>
<script>
import HiddenInput from "../HiddenInput.vue";
export default {
components: {
HiddenInput,
},
};
</script>
+2
View File
@@ -4,6 +4,7 @@ import AliyunSMS from "./AliyunSms.vue";
import Apprise from "./Apprise.vue"; import Apprise from "./Apprise.vue";
import Bale from "./Bale.vue"; import Bale from "./Bale.vue";
import Bark from "./Bark.vue"; import Bark from "./Bark.vue";
import BearSMS from "./BearSMS.vue";
import Bitrix24 from "./Bitrix24.vue"; import Bitrix24 from "./Bitrix24.vue";
import Notifery from "./Notifery.vue"; import Notifery from "./Notifery.vue";
import ClickSendSMS from "./ClickSendSMS.vue"; import ClickSendSMS from "./ClickSendSMS.vue";
@@ -111,6 +112,7 @@ const NotificationFormList = {
apprise: Apprise, apprise: Apprise,
bale: Bale, bale: Bale,
Bark: Bark, Bark: Bark,
bearsms: BearSMS,
Bitrix24: Bitrix24, Bitrix24: Bitrix24,
clicksendsms: ClickSendSMS, clicksendsms: ClickSendSMS,
CallMeBot: CallMeBot, CallMeBot: CallMeBot,
+4
View File
@@ -987,6 +987,10 @@
"wayToGetEgoSMSToken": "You can get your EgoSMS API username and password from {here}.", "wayToGetEgoSMSToken": "You can get your EgoSMS API username and password from {here}.",
"egosmsSenderDescription": "Sender ID shown to recipients (max 11 characters). Defaults to EGOSMS if empty.", "egosmsSenderDescription": "Sender ID shown to recipients (max 11 characters). Defaults to EGOSMS if empty.",
"egosmsPhoneNumberDescription": "Recipient number with country code, without + or 00 (e.g. 2567XXXXXXXX).", "egosmsPhoneNumberDescription": "Recipient number with country code, without + or 00 (e.g. 2567XXXXXXXX).",
"Hash Key": "Hash Key",
"wayToGetBearSMSToken": "You can get your BearSMS API username and hash key from {0}.",
"bearsmsPhoneNumberDescription": "Recipient number with country code, without + or 00 (e.g. 9725XXXXXXXX).",
"bearsmsSenderDescription": "Optional sender ID shown to recipients (max 11 characters). It must be approved in your BearSMS account, otherwise the account's default sender is used.",
"Custom Monitor Type": "Custom Monitor Type", "Custom Monitor Type": "Custom Monitor Type",
"Google Analytics ID": "Google Analytics ID", "Google Analytics ID": "Google Analytics ID",
"Analytics Type": "Analytics Type", "Analytics Type": "Analytics Type",