feat: add Flowtriq DDoS detection notification provider (#7546)

Co-authored-by: Jacob <jacob@humera.io>
This commit is contained in:
Jacob Masse
2026-06-28 05:08:26 -04:00
committed by GitHub
parent 584fc0761c
commit b4ce00530e
6 changed files with 128 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { DOWN, UP } = require("../../src/util");
class Flowtriq extends NotificationProvider {
name = "Flowtriq";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
const okMsg = "Sent Successfully.";
try {
let status = "info";
let monitorName = monitorJSON?.name || "Unknown";
if (heartbeatJSON != null) {
if (heartbeatJSON.status === DOWN) {
status = "down";
} else if (heartbeatJSON.status === UP) {
status = "up";
}
}
let data = {
source: "uptime-kuma",
status: status,
monitor: monitorName,
msg: msg,
};
if (heartbeatJSON) {
data.heartbeat = {
status: heartbeatJSON.status,
time: heartbeatJSON.time,
ping: heartbeatJSON.ping,
msg: heartbeatJSON.msg,
timezone: heartbeatJSON.timezone,
};
}
if (monitorJSON) {
data.monitorInfo = {
id: monitorJSON.id,
name: monitorJSON.name,
type: monitorJSON.type,
url: monitorJSON.url,
hostname: monitorJSON.hostname,
port: monitorJSON.port,
};
}
let headers = {
"Content-Type": "application/json",
};
if (notification.flowtriqApiKey) {
headers["X-API-Key"] = notification.flowtriqApiKey;
}
let config = this.getAxiosConfigWithProxy({
headers: headers,
});
let result = await axios.post(notification.flowtriqWebhookUrl, data, config);
if (result.status < 200 || result.status >= 300) {
throw new Error("Flowtriq notification failed with status code " + result.status);
}
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
}
module.exports = Flowtriq;
+2
View File
@@ -42,6 +42,7 @@ const JiraServiceManagement = require("./notification-providers/jira-service-man
const PagerDuty = require("./notification-providers/pagerduty"); const PagerDuty = require("./notification-providers/pagerduty");
const Pumble = require("./notification-providers/pumble"); const Pumble = require("./notification-providers/pumble");
const FlashDuty = require("./notification-providers/flashduty"); const FlashDuty = require("./notification-providers/flashduty");
const Flowtriq = require("./notification-providers/flowtriq");
const PagerTree = require("./notification-providers/pagertree"); const PagerTree = require("./notification-providers/pagertree");
const PromoSMS = require("./notification-providers/promosms"); const PromoSMS = require("./notification-providers/promosms");
const Pushbullet = require("./notification-providers/pushbullet"); const Pushbullet = require("./notification-providers/pushbullet");
@@ -152,6 +153,7 @@ class Notification {
new JiraServiceManagement(), new JiraServiceManagement(),
new PagerDuty(), new PagerDuty(),
new FlashDuty(), new FlashDuty(),
new Flowtriq(),
new PagerTree(), new PagerTree(),
new PromoSMS(), new PromoSMS(),
new Pumble(), new Pumble(),
+1
View File
@@ -292,6 +292,7 @@ export default {
let incidentManagement = { let incidentManagement = {
alerta: "Alerta", alerta: "Alerta",
AlertNow: "AlertNow", AlertNow: "AlertNow",
Flowtriq: "Flowtriq",
GoAlert: "GoAlert", GoAlert: "GoAlert",
GrafanaOncall: "Grafana Oncall", GrafanaOncall: "Grafana Oncall",
HeiiOnCall: "Heii On-Call", HeiiOnCall: "Heii On-Call",
+41
View File
@@ -0,0 +1,41 @@
<template>
<div class="mb-3">
<label for="flowtriq-webhook-url" class="form-label">
{{ $t("Flowtriq Webhook URL") }}
<span style="color: red"><sup>*</sup></span>
</label>
<input
id="flowtriq-webhook-url"
v-model="$parent.notification.flowtriqWebhookUrl"
type="url"
class="form-control"
required
autocomplete="false"
placeholder="https://app.flowtriq.com/api/webhooks/..."
/>
</div>
<div class="mb-3">
<label for="flowtriq-api-key" class="form-label">
{{ $t("Flowtriq API Key") }}
</label>
<HiddenInput
id="flowtriq-api-key"
v-model="$parent.notification.flowtriqApiKey"
autocomplete="false"
:placeholder="$t('Optional')"
/>
<div class="form-text">
{{ $t("flowtriqApiKeyDescription") }}
</div>
</div>
</template>
<script>
import HiddenInput from "../HiddenInput.vue";
export default {
components: {
HiddenInput,
},
mounted() {},
};
</script>
+2
View File
@@ -41,6 +41,7 @@ import Opsgenie from "./Opsgenie.vue";
import JiraServiceManagement from "./JiraServiceManagement.vue"; import JiraServiceManagement from "./JiraServiceManagement.vue";
import PagerDuty from "./PagerDuty.vue"; import PagerDuty from "./PagerDuty.vue";
import FlashDuty from "./FlashDuty.vue"; import FlashDuty from "./FlashDuty.vue";
import Flowtriq from "./Flowtriq.vue";
import PagerTree from "./PagerTree.vue"; import PagerTree from "./PagerTree.vue";
import PromoSMS from "./PromoSMS.vue"; import PromoSMS from "./PromoSMS.vue";
import Pumble from "./Pumble.vue"; import Pumble from "./Pumble.vue";
@@ -140,6 +141,7 @@ const NotificationFormList = {
JiraServiceManagement: JiraServiceManagement, JiraServiceManagement: JiraServiceManagement,
PagerDuty: PagerDuty, PagerDuty: PagerDuty,
FlashDuty: FlashDuty, FlashDuty: FlashDuty,
Flowtriq: Flowtriq,
PagerTree: PagerTree, PagerTree: PagerTree,
promosms: PromoSMS, promosms: PromoSMS,
pumble: Pumble, pumble: Pumble,
+3
View File
@@ -1103,6 +1103,9 @@
"FlashDuty Severity": "Severity", "FlashDuty Severity": "Severity",
"FlashDuty Push URL": "Push URL", "FlashDuty Push URL": "Push URL",
"FlashDuty Push URL Placeholder": "Copy from the alerting integration page", "FlashDuty Push URL Placeholder": "Copy from the alerting integration page",
"Flowtriq Webhook URL": "Webhook URL",
"Flowtriq API Key": "API Key",
"flowtriqApiKeyDescription": "Optional API key for authenticating webhook requests to your Flowtriq instance.",
"nostrRelays": "Nostr relays", "nostrRelays": "Nostr relays",
"nostrRelaysHelp": "One relay URL per line", "nostrRelaysHelp": "One relay URL per line",
"nostrSender": "Sender Private Key (nsec)", "nostrSender": "Sender Private Key (nsec)",