Merge remote-tracking branch 'origin/master'

This commit is contained in:
Weblate 2023-03-27 08:38:00 +00:00
commit 8c69c18f6d
12 changed files with 255 additions and 5 deletions

View file

@ -26,6 +26,12 @@ body:
label: "📝 Describe your problem" label: "📝 Describe your problem"
description: "Please walk us through it step by step." description: "Please walk us through it step by step."
placeholder: "Describe what are you asking for..." placeholder: "Describe what are you asking for..."
- type: textarea
id: error-msg
validations:
required: false
attributes:
label: "📝 Error Message(s) or Log"
- type: input - type: input
id: uptime-kuma-version id: uptime-kuma-version
attributes: attributes:

View file

@ -0,0 +1,25 @@
name: json-yaml-validate
on:
push:
branches:
- master
pull_request:
branches:
- master
workflow_dispatch:
permissions:
contents: read
pull-requests: write # enable write permissions for pull request comments
jobs:
json-yaml-validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: json-yaml-validate
id: json-yaml-validate
uses: GrantBirki/json-yaml-validate@v1.2.0
with:
comment: "true" # enable comment mode

View file

@ -1245,7 +1245,7 @@ class Monitor extends BeanModel {
if (notificationList.length > 0) { if (notificationList.length > 0) {
let row = await R.getRow("SELECT * FROM notification_sent_history WHERE type = ? AND monitor_id = ? AND days = ?", [ let row = await R.getRow("SELECT * FROM notification_sent_history WHERE type = ? AND monitor_id = ? AND days <= ?", [
"certificate", "certificate",
this.id, this.id,
targetDays, targetDays,

View file

@ -0,0 +1,97 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const opsgenieAlertsUrlEU = "https://api.eu.opsgenie.com/v2/alerts";
const opsgenieAlertsUrlUS = "https://api.opsgenie.com/v2/alerts";
let okMsg = "Sent Successfully.";
class Opsgenie extends NotificationProvider {
name = "Opsgenie";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let opsgenieAlertsUrl;
let priority = (notification.opsgeniePriority == "") ? 3 : notification.opsgeniePriority;
const textMsg = "Uptime Kuma Alert";
try {
switch (notification.opsgenieRegion) {
case "US":
opsgenieAlertsUrl = opsgenieAlertsUrlUS;
break;
case "EU":
opsgenieAlertsUrl = opsgenieAlertsUrlEU;
break;
default:
opsgenieAlertsUrl = opsgenieAlertsUrlUS;
}
if (heartbeatJSON == null) {
let notificationTestAlias = "uptime-kuma-notification-test";
let data = {
"message": msg,
"alias": notificationTestAlias,
"source": "Uptime Kuma",
"priority": "P5"
};
return this.post(notification, opsgenieAlertsUrl, data);
}
if (heartbeatJSON.status === DOWN) {
let data = {
"message": monitorJSON ? textMsg + `: ${monitorJSON.name}` : textMsg,
"alias": monitorJSON.name,
"description": msg,
"source": "Uptime Kuma",
"priority": `P${priority}`
};
return this.post(notification, opsgenieAlertsUrl, data);
}
if (heartbeatJSON.status === UP) {
let opsgenieAlertsCloseUrl = `${opsgenieAlertsUrl}/${encodeURIComponent(monitorJSON.name)}/close?identifierType=alias`;
let data = {
"source": "Uptime Kuma",
};
return this.post(notification, opsgenieAlertsCloseUrl, data);
}
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
/**
*
* @param {BeanModel} notification
* @param {string} url Request url
* @param {Object} data Request body
* @returns {Promise<string>}
*/
async post(notification, url, data) {
let config = {
headers: {
"Content-Type": "application/json",
"Authorization": `GenieKey ${notification.opsgenieApiKey}`,
}
};
let res = await axios.post(url, data, config);
if (res.status == null) {
return "Opsgenie notification failed with invalid response!";
}
if (res.status < 200 || res.status >= 300) {
return `Opsgenie notification failed with status code ${res.status}`;
}
return okMsg;
}
}
module.exports = Opsgenie;

View file

@ -0,0 +1,41 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
class Twilio extends NotificationProvider {
name = "twilio";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully.";
let accountSID = notification.twilioAccountSID;
let authToken = notification.twilioAuthToken;
try {
let config = {
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
"Authorization": "Basic " + Buffer.from(accountSID + ":" + authToken).toString("base64"),
}
};
let data = new URLSearchParams();
data.append("To", notification.twilioToNumber);
data.append("From", notification.twilioFromNumber);
data.append("Body", msg);
let url = "https://api.twilio.com/2010-04-01/Accounts/" + accountSID + "/Messages.json";
await axios.post(url, data, config);
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
}
module.exports = Twilio;

View file

@ -23,6 +23,7 @@ const Mattermost = require("./notification-providers/mattermost");
const Ntfy = require("./notification-providers/ntfy"); const Ntfy = require("./notification-providers/ntfy");
const Octopush = require("./notification-providers/octopush"); const Octopush = require("./notification-providers/octopush");
const OneBot = require("./notification-providers/onebot"); const OneBot = require("./notification-providers/onebot");
const Opsgenie = require("./notification-providers/opsgenie");
const PagerDuty = require("./notification-providers/pagerduty"); const PagerDuty = require("./notification-providers/pagerduty");
const PagerTree = require("./notification-providers/pagertree"); const PagerTree = require("./notification-providers/pagertree");
const PromoSMS = require("./notification-providers/promosms"); const PromoSMS = require("./notification-providers/promosms");
@ -41,6 +42,7 @@ const Stackfield = require("./notification-providers/stackfield");
const Teams = require("./notification-providers/teams"); const Teams = require("./notification-providers/teams");
const TechulusPush = require("./notification-providers/techulus-push"); const TechulusPush = require("./notification-providers/techulus-push");
const Telegram = require("./notification-providers/telegram"); const Telegram = require("./notification-providers/telegram");
const Twilio = require("./notification-providers/twilio");
const Splunk = require("./notification-providers/splunk"); const Splunk = require("./notification-providers/splunk");
const Webhook = require("./notification-providers/webhook"); const Webhook = require("./notification-providers/webhook");
const WeCom = require("./notification-providers/wecom"); const WeCom = require("./notification-providers/wecom");
@ -83,6 +85,7 @@ class Notification {
new Ntfy(), new Ntfy(),
new Octopush(), new Octopush(),
new OneBot(), new OneBot(),
new Opsgenie(),
new PagerDuty(), new PagerDuty(),
new PagerTree(), new PagerTree(),
new PromoSMS(), new PromoSMS(),
@ -103,6 +106,7 @@ class Notification {
new Teams(), new Teams(),
new TechulusPush(), new TechulusPush(),
new Telegram(), new Telegram(),
new Twilio(),
new Splunk(), new Splunk(),
new Webhook(), new Webhook(),
new WeCom(), new WeCom(),

View file

@ -147,7 +147,11 @@ router.get("/api/badge/:id/status", cache("5 minutes"), async (request, response
const heartbeat = await Monitor.getPreviousHeartbeat(requestedMonitorId); const heartbeat = await Monitor.getPreviousHeartbeat(requestedMonitorId);
const state = overrideValue !== undefined ? overrideValue : heartbeat.status; const state = overrideValue !== undefined ? overrideValue : heartbeat.status;
badgeValues.label = label ?? "Status"; if (label === undefined) {
badgeValues.label = "Status";
} else {
badgeValues.label = label;
}
switch (state) { switch (state) {
case DOWN: case DOWN:
badgeValues.color = downColor; badgeValues.color = downColor;
@ -224,7 +228,7 @@ router.get("/api/badge/:id/uptime/:duration?", cache("5 minutes"), async (reques
); );
// limit the displayed uptime percentage to four (two, when displayed as percent) decimal digits // limit the displayed uptime percentage to four (two, when displayed as percent) decimal digits
const cleanUptime = parseFloat(uptime.toPrecision(4)); const cleanUptime = (uptime * 100).toPrecision(4);
// use a given, custom color or calculate one based on the uptime value // use a given, custom color or calculate one based on the uptime value
badgeValues.color = color ?? percentageToColor(uptime); badgeValues.color = color ?? percentageToColor(uptime);
@ -235,7 +239,7 @@ router.get("/api/badge/:id/uptime/:duration?", cache("5 minutes"), async (reques
labelPrefix, labelPrefix,
label ?? `Uptime (${requestedDuration}${labelSuffix})`, label ?? `Uptime (${requestedDuration}${labelSuffix})`,
]); ]);
badgeValues.message = filterAndJoin([ prefix, `${cleanUptime * 100}`, suffix ]); badgeValues.message = filterAndJoin([ prefix, cleanUptime, suffix ]);
} }
// build the SVG based on given values // build the SVG based on given values

View file

@ -129,6 +129,7 @@ export default {
"ntfy": "Ntfy", "ntfy": "Ntfy",
"octopush": "Octopush", "octopush": "Octopush",
"OneBot": "OneBot", "OneBot": "OneBot",
"Opsgenie": "Opsgenie",
"PagerDuty": "PagerDuty", "PagerDuty": "PagerDuty",
"pushbullet": "Pushbullet", "pushbullet": "Pushbullet",
"PushByTechulus": "Push by Techulus", "PushByTechulus": "Push by Techulus",
@ -143,6 +144,7 @@ export default {
"stackfield": "Stackfield", "stackfield": "Stackfield",
"teams": "Microsoft Teams", "teams": "Microsoft Teams",
"telegram": "Telegram", "telegram": "Telegram",
"twilio": "Twilio",
"Splunk": "Splunk", "Splunk": "Splunk",
"webhook": "Webhook", "webhook": "Webhook",
"GoAlert": "GoAlert", "GoAlert": "GoAlert",

View file

@ -0,0 +1,36 @@
<template>
<div class="mb-3">
<label for="opsgenie-region" class="form-label">{{ $t("Region") }}<span style="color: red;"><sup>*</sup></span></label>
<select id="opsgenie-region" v-model="$parent.notification.opsgenieRegion" class="form-select" required>
<option value="us">
US (Default)
</option>
<option value="eu">
EU
</option>
</select>
</div>
<div class="mb-3">
<label for="opsgenie-apikey" class="form-label">{{ $t("API Key") }}<span style="color: red;"><sup>*</sup></span></label>
<HiddenInput id="opsgenie-apikey" v-model="$parent.notification.opsgenieApiKey" required="true" autocomplete="false"></HiddenInput>
</div>
<div class="mb-3">
<label for="opsgenie-priority" class="form-label">{{ $t("Priority") }}</label>
<input id="opsgenie-priority" v-model="$parent.notification.opsgeniePriority" type="number" class="form-control" min="1" max="5" step="1">
</div>
<div class="form-text">
<span style="color: red;"><sup>*</sup></span>{{ $t("Required") }}
<i18n-t tag="p" keypath="aboutWebhooks" style="margin-top: 8px;">
<a href="https://docs.opsgenie.com/docs/alert-api" target="_blank">https://docs.opsgenie.com/docs/alert-api</a>
</i18n-t>
</div>
</template>
<script>
import HiddenInput from "../HiddenInput.vue";
export default {
components: {
HiddenInput,
},
};
</script>

View file

@ -0,0 +1,27 @@
<template>
<div class="mb-3">
<label for="twilio-account-sid" class="form-label">{{ $t("Account SID") }}</label>
<input id="twilio-account-sid" v-model="$parent.notification.twilioAccountSID" type="text" class="form-control" required>
</div>
<div class="mb-3">
<label for="twilio-auth-token" class="form-label">{{ $t("Auth Token") }}</label>
<input id="twilio-auth-token" v-model="$parent.notification.twilioAuthToken" type="text" class="form-control" required>
</div>
<div class="mb-3">
<label for="twilio-from-number" class="form-label">{{ $t("From Number") }}</label>
<input id="twilio-from-number" v-model="$parent.notification.twilioFromNumber" type="text" class="form-control" required>
</div>
<div class="mb-3">
<label for="twilio-to-number" class="form-label">{{ $t("To Number") }}</label>
<input id="twilio-to-number" v-model="$parent.notification.twilioToNumber" type="text" class="form-control" required>
</div>
<div class="mb-3">
<i18n-t tag="p" keypath="More info on:" style="margin-top: 8px;">
<a href="https://www.twilio.com/docs/sms" target="_blank">https://www.twilio.com/docs/sms</a>
</i18n-t>
</div>
</template>

View file

@ -21,6 +21,7 @@ import Mattermost from "./Mattermost.vue";
import Ntfy from "./Ntfy.vue"; import Ntfy from "./Ntfy.vue";
import Octopush from "./Octopush.vue"; import Octopush from "./Octopush.vue";
import OneBot from "./OneBot.vue"; import OneBot from "./OneBot.vue";
import Opsgenie from "./Opsgenie.vue";
import PagerDuty from "./PagerDuty.vue"; import PagerDuty from "./PagerDuty.vue";
import PagerTree from "./PagerTree.vue"; import PagerTree from "./PagerTree.vue";
import PromoSMS from "./PromoSMS.vue"; import PromoSMS from "./PromoSMS.vue";
@ -41,6 +42,7 @@ import STMP from "./SMTP.vue";
import Teams from "./Teams.vue"; import Teams from "./Teams.vue";
import TechulusPush from "./TechulusPush.vue"; import TechulusPush from "./TechulusPush.vue";
import Telegram from "./Telegram.vue"; import Telegram from "./Telegram.vue";
import Twilio from "./Twilio.vue";
import Webhook from "./Webhook.vue"; import Webhook from "./Webhook.vue";
import WeCom from "./WeCom.vue"; import WeCom from "./WeCom.vue";
import GoAlert from "./GoAlert.vue"; import GoAlert from "./GoAlert.vue";
@ -76,6 +78,7 @@ const NotificationFormList = {
"ntfy": Ntfy, "ntfy": Ntfy,
"octopush": Octopush, "octopush": Octopush,
"OneBot": OneBot, "OneBot": OneBot,
"Opsgenie": Opsgenie,
"PagerDuty": PagerDuty, "PagerDuty": PagerDuty,
"PagerTree": PagerTree, "PagerTree": PagerTree,
"promosms": PromoSMS, "promosms": PromoSMS,
@ -95,6 +98,7 @@ const NotificationFormList = {
"stackfield": Stackfield, "stackfield": Stackfield,
"teams": Teams, "teams": Teams,
"telegram": Telegram, "telegram": Telegram,
"twilio": Twilio,
"Splunk": Splunk, "Splunk": Splunk,
"webhook": Webhook, "webhook": Webhook,
"WeCom": WeCom, "WeCom": WeCom,

View file

@ -707,5 +707,9 @@
"wayToGetPagerTreeIntegrationURL": "After creating the Uptime Kuma integration in PagerTree, copy the Endpoint. See full details {0}", "wayToGetPagerTreeIntegrationURL": "After creating the Uptime Kuma integration in PagerTree, copy the Endpoint. See full details {0}",
"lunaseaTarget": "Target", "lunaseaTarget": "Target",
"lunaseaDeviceID": "Device ID", "lunaseaDeviceID": "Device ID",
"lunaseaUserID": "User ID" "lunaseaUserID": "User ID",
"twilioAccountSID": "Account SID",
"twilioAuthToken": "Auth Token",
"twilioFromNumber": "From Number",
"twilioToNumber": "To Number"
} }