feat: add google sheets notification provider
logs monitor events to google spreadsheet via apps script webhook
This commit is contained in:
parent
b638ae48ef
commit
491741be23
62
server/notification-providers/google-sheets.js
Normal file
62
server/notification-providers/google-sheets.js
Normal file
@ -0,0 +1,62 @@
|
||||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
const { DOWN, UP } = require("../../src/util");
|
||||
|
||||
class GoogleSheets extends NotificationProvider {
|
||||
name = "GoogleSheets";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
const okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
// Prepare the data to be logged
|
||||
const timestamp = new Date().toISOString();
|
||||
let status = "N/A";
|
||||
let monitorName = "N/A";
|
||||
let monitorUrl = "N/A";
|
||||
let responseTime = "N/A";
|
||||
let statusCode = "N/A";
|
||||
|
||||
if (monitorJSON) {
|
||||
monitorName = monitorJSON.name || "N/A";
|
||||
monitorUrl = this.extractAddress(monitorJSON) || "N/A";
|
||||
}
|
||||
|
||||
if (heartbeatJSON) {
|
||||
status = heartbeatJSON.status === DOWN ? "DOWN" : heartbeatJSON.status === UP ? "UP" : "UNKNOWN";
|
||||
responseTime = heartbeatJSON.ping || "N/A";
|
||||
statusCode = heartbeatJSON.status || "N/A";
|
||||
}
|
||||
|
||||
// Send data to Google Apps Script webhook
|
||||
const webhookUrl = notification.googleSheetsWebhookUrl;
|
||||
|
||||
const config = this.getAxiosConfigWithProxy({
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
|
||||
const data = {
|
||||
timestamp: timestamp,
|
||||
status: status,
|
||||
monitorName: monitorName,
|
||||
monitorUrl: monitorUrl,
|
||||
message: msg,
|
||||
responseTime: responseTime,
|
||||
statusCode: statusCode
|
||||
};
|
||||
|
||||
await axios.post(webhookUrl, data, config);
|
||||
|
||||
return okMsg;
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GoogleSheets;
|
||||
@ -17,6 +17,7 @@ const Feishu = require("./notification-providers/feishu");
|
||||
const Notifery = require("./notification-providers/notifery");
|
||||
const FreeMobile = require("./notification-providers/freemobile");
|
||||
const GoogleChat = require("./notification-providers/google-chat");
|
||||
const GoogleSheets = require("./notification-providers/google-sheets");
|
||||
const Gorush = require("./notification-providers/gorush");
|
||||
const Gotify = require("./notification-providers/gotify");
|
||||
const GrafanaOncall = require("./notification-providers/grafana-oncall");
|
||||
@ -117,6 +118,7 @@ class Notification {
|
||||
new Feishu(),
|
||||
new FreeMobile(),
|
||||
new GoogleChat(),
|
||||
new GoogleSheets(),
|
||||
new Gorush(),
|
||||
new Gotify(),
|
||||
new GrafanaOncall(),
|
||||
|
||||
@ -305,7 +305,9 @@ export default {
|
||||
};
|
||||
|
||||
// Other Integrations
|
||||
let other = {};
|
||||
let other = {
|
||||
GoogleSheets: "Google Sheets",
|
||||
};
|
||||
|
||||
// Regional - Not supported in most regions or documentation is not in English
|
||||
let regional = {
|
||||
|
||||
116
src/components/notifications/GoogleSheets.vue
Normal file
116
src/components/notifications/GoogleSheets.vue
Normal file
@ -0,0 +1,116 @@
|
||||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="google-sheets-webhook-url" class="form-label">{{ $t("Google Apps Script Webhook URL") }}</label>
|
||||
<input
|
||||
id="google-sheets-webhook-url"
|
||||
v-model="$parent.notification.googleSheetsWebhookUrl"
|
||||
type="text"
|
||||
class="form-control"
|
||||
required
|
||||
placeholder="https://script.google.com/macros/s/YOUR_SCRIPT_ID/exec"
|
||||
/>
|
||||
<div class="form-text">
|
||||
<p>{{ $t("Deploy a Google Apps Script as a web app and paste the URL here") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info" style="border-radius: 8px;">
|
||||
<h6 style="margin-bottom: 12px; font-weight: 600;">{{ $t("Quick Setup Guide") }}:</h6>
|
||||
<ol style="margin-bottom: 0; padding-left: 20px; line-height: 1.8;">
|
||||
<li>{{ $t("Open your Google Spreadsheet") }}</li>
|
||||
<li>{{ $t("Go to Extensions → Apps Script") }}</li>
|
||||
<li>{{ $t("Paste the script code (see below)") }}</li>
|
||||
<li>{{ $t("Click Deploy → New deployment → Web app") }}</li>
|
||||
<li>{{ $t("Set 'Execute as: Me' and 'Who has access: Anyone'") }}</li>
|
||||
<li>{{ $t("Copy the web app URL and paste it above") }}</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary btn-sm"
|
||||
@click="showScript = !showScript"
|
||||
>
|
||||
{{ showScript ? $t("Hide Script Code") : $t("Show Script Code") }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="showScript" class="mb-3">
|
||||
<label class="form-label">{{ $t("Google Apps Script Code") }}:</label>
|
||||
<textarea
|
||||
readonly
|
||||
class="form-control"
|
||||
rows="15"
|
||||
style="font-family: monospace; font-size: 12px;"
|
||||
>function doPost(e) {
|
||||
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
|
||||
var data = JSON.parse(e.postData.contents);
|
||||
|
||||
// Add header row if sheet is empty
|
||||
if (sheet.getLastRow() === 0) {
|
||||
sheet.appendRow(['Timestamp', 'Status', 'Monitor Name', 'URL', 'Message', 'Response Time', 'Status Code']);
|
||||
}
|
||||
|
||||
// Add data row
|
||||
sheet.appendRow([
|
||||
data.timestamp,
|
||||
data.status,
|
||||
data.monitorName,
|
||||
data.monitorUrl,
|
||||
data.message,
|
||||
data.responseTime,
|
||||
data.statusCode
|
||||
]);
|
||||
|
||||
return ContentService.createTextOutput(JSON.stringify({result: 'success'}))
|
||||
.setMimeType(ContentService.MimeType.JSON);
|
||||
}</textarea>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-secondary btn-sm mt-2"
|
||||
@click="copyScript"
|
||||
>
|
||||
{{ $t("Copy to Clipboard") }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
showScript: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
copyScript() {
|
||||
const scriptCode = `function doPost(e) {
|
||||
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
|
||||
var data = JSON.parse(e.postData.contents);
|
||||
|
||||
// Add header row if sheet is empty
|
||||
if (sheet.getLastRow() === 0) {
|
||||
sheet.appendRow(['Timestamp', 'Status', 'Monitor Name', 'URL', 'Message', 'Response Time', 'Status Code']);
|
||||
}
|
||||
|
||||
// Add data row
|
||||
sheet.appendRow([
|
||||
data.timestamp,
|
||||
data.status,
|
||||
data.monitorName,
|
||||
data.monitorUrl,
|
||||
data.message,
|
||||
data.responseTime,
|
||||
data.statusCode
|
||||
]);
|
||||
|
||||
return ContentService.createTextOutput(JSON.stringify({result: 'success'}))
|
||||
.setMimeType(ContentService.MimeType.JSON);
|
||||
}`;
|
||||
navigator.clipboard.writeText(scriptCode);
|
||||
alert(this.$t("Copied to clipboard!"));
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@ -15,6 +15,7 @@ import Elks from "./46elks.vue";
|
||||
import Feishu from "./Feishu.vue";
|
||||
import FreeMobile from "./FreeMobile.vue";
|
||||
import GoogleChat from "./GoogleChat.vue";
|
||||
import GoogleSheets from "./GoogleSheets.vue";
|
||||
import Gorush from "./Gorush.vue";
|
||||
import Gotify from "./Gotify.vue";
|
||||
import GrafanaOncall from "./GrafanaOncall.vue";
|
||||
@ -105,6 +106,7 @@ const NotificationFormList = {
|
||||
Feishu: Feishu,
|
||||
FreeMobile: FreeMobile,
|
||||
GoogleChat: GoogleChat,
|
||||
GoogleSheets: GoogleSheets,
|
||||
gorush: Gorush,
|
||||
gotify: Gotify,
|
||||
GrafanaOncall: GrafanaOncall,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user