mirror of
https://github.com/louislam/uptime-kuma.git
synced 2026-08-07 09:14:58 +00:00
feat: add Ooredoo (Maldives) SMS notification provider (#7571)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
ffa791da8b
commit
8854e00a92
@@ -0,0 +1,89 @@
|
||||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
|
||||
// The Ooredoo bulk_sms/v2 gateway accepts at most this many recipients per
|
||||
// request, so larger recipient lists are split into batches of this size.
|
||||
const MAX_RECIPIENTS_PER_REQUEST = 20;
|
||||
|
||||
class Ooredoo extends NotificationProvider {
|
||||
name = "Ooredoo";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
const okMsg = "Sent Successfully.";
|
||||
const url = notification.ooredooServerUrl || "https://o-papi1-lb01.ooredoo.mv/bulk_sms/v2";
|
||||
|
||||
// Users may enter recipients separated by comma, semicolon, space or
|
||||
// newline.
|
||||
const recipients = notification.ooredooToNumber
|
||||
.split(/[\s,;]+/)
|
||||
.map((number) => this.normalizePhoneNumber(number))
|
||||
.filter((number) => number !== "");
|
||||
|
||||
if (recipients.length === 0) {
|
||||
throw new Error("No valid recipient phone number was provided.");
|
||||
}
|
||||
|
||||
try {
|
||||
let config = {
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
Authorization: "Bearer " + notification.ooredooBearerToken,
|
||||
},
|
||||
};
|
||||
config = this.getAxiosConfigWithProxy(config);
|
||||
|
||||
// The gateway only accepts MAX_RECIPIENTS_PER_REQUEST numbers per
|
||||
// call, so send the recipients in batches of that size.
|
||||
for (let i = 0; i < recipients.length; i += MAX_RECIPIENTS_PER_REQUEST) {
|
||||
const batch = recipients.slice(i, i + MAX_RECIPIENTS_PER_REQUEST);
|
||||
const data = new URLSearchParams({
|
||||
username: notification.ooredooUsername,
|
||||
// The gateway expects the access key to be Base64 encoded.
|
||||
access_key: Buffer.from(notification.ooredooAccessKey).toString("base64"),
|
||||
message: msg,
|
||||
batch: batch.join(" "),
|
||||
});
|
||||
|
||||
const resp = await axios.post(url, data.toString(), config);
|
||||
|
||||
// The gateway returns HTTP 200 even on failure; the real outcome
|
||||
// is carried in "response_code" (0 means the batch was accepted).
|
||||
if (!resp.data || Number(resp.data.response_code) !== 0) {
|
||||
const reason =
|
||||
resp.data && resp.data.response_message
|
||||
? resp.data.response_message
|
||||
: "response_code=" + (resp.data ? resp.data.response_code : "unknown");
|
||||
throw new Error("Ooredoo rejected the message: " + reason);
|
||||
}
|
||||
}
|
||||
|
||||
return okMsg;
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a Maldivian phone number to the "960XXXXXXX" format expected
|
||||
* by the Ooredoo gateway. Numbers already in that form are returned as is.
|
||||
* @param {string} phoneNumber The phone number to normalize
|
||||
* @returns {string} The normalized phone number, or "" if it is empty
|
||||
*/
|
||||
normalizePhoneNumber(phoneNumber) {
|
||||
const number = phoneNumber.replace(/[\s+]/g, "");
|
||||
|
||||
if (number === "") {
|
||||
return "";
|
||||
}
|
||||
// A bare 7-digit local number gets the Maldives (960) country code.
|
||||
if (/^\d{7}$/.test(number)) {
|
||||
return "960" + number;
|
||||
}
|
||||
return number;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Ooredoo;
|
||||
@@ -37,6 +37,7 @@ const Ntfy = require("./notification-providers/ntfy");
|
||||
const Octopush = require("./notification-providers/octopush");
|
||||
const OneChat = require("./notification-providers/onechat");
|
||||
const OneBot = require("./notification-providers/onebot");
|
||||
const Ooredoo = require("./notification-providers/ooredoo");
|
||||
const Opsgenie = require("./notification-providers/opsgenie");
|
||||
const JiraServiceManagement = require("./notification-providers/jira-service-management");
|
||||
const PagerDuty = require("./notification-providers/pagerduty");
|
||||
@@ -150,6 +151,7 @@ class Notification {
|
||||
new OneChat(),
|
||||
new OneBot(),
|
||||
new Onesender(),
|
||||
new Ooredoo(),
|
||||
new Opsgenie(),
|
||||
new JiraServiceManagement(),
|
||||
new PagerDuty(),
|
||||
|
||||
@@ -324,6 +324,7 @@ export default {
|
||||
Feishu: "Feishu (飞书)",
|
||||
FlashDuty: "FlashDuty (快猫星云)",
|
||||
FreeMobile: "FreeMobile (mobile.free.fr)",
|
||||
Ooredoo: "Ooredoo (Maldives)",
|
||||
PushDeer: "PushDeer",
|
||||
promosms: "PromoSMS",
|
||||
serwersms: "SerwerSMS.pl",
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="ooredoo-username" class="form-label">{{ $t("Username") }}</label>
|
||||
<input
|
||||
id="ooredoo-username"
|
||||
v-model="$parent.notification.ooredooUsername"
|
||||
type="text"
|
||||
class="form-control"
|
||||
required
|
||||
/>
|
||||
<div class="form-text">{{ $t("ooredooUsernameDescription") }}</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="ooredoo-access-key" class="form-label">{{ $t("Access Key") }}</label>
|
||||
<HiddenInput
|
||||
id="ooredoo-access-key"
|
||||
v-model="$parent.notification.ooredooAccessKey"
|
||||
:required="true"
|
||||
autocomplete="new-password"
|
||||
></HiddenInput>
|
||||
<div class="form-text">{{ $t("ooredooAccessKeyDescription") }}</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="ooredoo-bearer-token" class="form-label">{{ $t("Bearer Token") }}</label>
|
||||
<HiddenInput
|
||||
id="ooredoo-bearer-token"
|
||||
v-model="$parent.notification.ooredooBearerToken"
|
||||
:required="true"
|
||||
autocomplete="new-password"
|
||||
></HiddenInput>
|
||||
<div class="form-text">{{ $t("ooredooBearerTokenDescription") }}</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="ooredoo-to-number" class="form-label">{{ $t("Recipient Number") }}</label>
|
||||
<input
|
||||
id="ooredoo-to-number"
|
||||
v-model="$parent.notification.ooredooToNumber"
|
||||
type="text"
|
||||
class="form-control"
|
||||
required
|
||||
/>
|
||||
<div class="form-text">{{ $t("ooredooRecipientDescription") }}</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="ooredoo-server-url" class="form-label">{{ $t("API URL") }}</label>
|
||||
<input
|
||||
id="ooredoo-server-url"
|
||||
v-model="$parent.notification.ooredooServerUrl"
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="https://o-papi1-lb01.ooredoo.mv/bulk_sms/v2"
|
||||
/>
|
||||
<div class="form-text">{{ $t("Leave blank to use the default Ooredoo endpoint.") }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import HiddenInput from "../HiddenInput.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HiddenInput,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -37,6 +37,7 @@ import Octopush from "./Octopush.vue";
|
||||
import OneChat from "./OneChat.vue";
|
||||
import OneBot from "./OneBot.vue";
|
||||
import Onesender from "./Onesender.vue";
|
||||
import Ooredoo from "./Ooredoo.vue";
|
||||
import Opsgenie from "./Opsgenie.vue";
|
||||
import JiraServiceManagement from "./JiraServiceManagement.vue";
|
||||
import PagerDuty from "./PagerDuty.vue";
|
||||
@@ -138,6 +139,7 @@ const NotificationFormList = {
|
||||
OneChat: OneChat,
|
||||
OneBot: OneBot,
|
||||
Onesender: Onesender,
|
||||
Ooredoo: Ooredoo,
|
||||
Opsgenie: Opsgenie,
|
||||
JiraServiceManagement: JiraServiceManagement,
|
||||
PagerDuty: PagerDuty,
|
||||
|
||||
@@ -957,6 +957,12 @@
|
||||
"smspartnerSenderName": "SMS Sender Name",
|
||||
"smspartnerSenderNameInfo": "Must be between 3..=11 regular characters",
|
||||
"Recipient Number": "Recipient Number",
|
||||
"Access Key": "Access Key",
|
||||
"ooredooUsernameDescription": "The email address you use to sign in to the Ooredoo bulk SMS dashboard.",
|
||||
"ooredooAccessKeyDescription": "Found under \"API Access Key\" on your Ooredoo SMS dashboard. Paste it exactly as shown — it is base64-encoded automatically before sending.",
|
||||
"ooredooBearerTokenDescription": "The token shown after \"Authorization: Bearer\" in the sample cURL command on your Ooredoo SMS dashboard.",
|
||||
"ooredooRecipientDescription": "Enter one or more numbers separated by a comma or space. Local 7-digit numbers are automatically prefixed with 960.",
|
||||
"Leave blank to use the default Ooredoo endpoint.": "Leave blank to use the default Ooredoo endpoint.",
|
||||
"From Name/Number": "From Name/Number",
|
||||
"Leave blank to use a shared sender number.": "Leave blank to use a shared sender number.",
|
||||
"Octopush API Version": "Octopush API Version",
|
||||
|
||||
Reference in New Issue
Block a user