mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-06-03 12:02:33 +02:00

Reformatted code across multiple modules, standardizing string quotes, indentation, and spacing. Improved readability by restructuring blocks and aligning object properties consistently. These changes ensure better code maintainability and follow standard conventions. Signed-off-by: Toby Liddicoat <toby@codesure.co.uk>
250 lines
7.6 KiB
JavaScript
250 lines
7.6 KiB
JavaScript
let express = require("express");
|
|
const apicache = require("../modules/apicache");
|
|
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
|
const StatusPage = require("../model/status_page");
|
|
const {
|
|
allowDevAllOrigin,
|
|
sendHttpError,
|
|
} = require("../util-server");
|
|
const { R } = require("redbean-node");
|
|
const { badgeConstants } = require("../../src/util");
|
|
const { makeBadge } = require("badge-maker");
|
|
const { UptimeCalculator } = require("../uptime-calculator");
|
|
|
|
let router = express.Router();
|
|
|
|
let cache = apicache.middleware;
|
|
const server = UptimeKumaServer.getInstance();
|
|
|
|
router.get("/status/:slug", cache("5 minutes"), async (request, response) => {
|
|
let slug = request.params.slug;
|
|
slug = slug.toLowerCase();
|
|
await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);
|
|
});
|
|
|
|
router.get("/status/:slug/rss", cache("5 minutes"), async (request, response) => {
|
|
let slug = request.params.slug;
|
|
slug = slug.toLowerCase();
|
|
await StatusPage.handleStatusPageRSSResponse(response, slug);
|
|
});
|
|
|
|
router.get("/status", cache("5 minutes"), async (request, response) => {
|
|
let slug = "default";
|
|
await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);
|
|
});
|
|
|
|
router.get("/status-page", cache("5 minutes"), async (request, response) => {
|
|
let slug = "default";
|
|
await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);
|
|
});
|
|
|
|
// Status page config, incident, monitor list
|
|
router.get("/api/status-page/:slug", cache("5 minutes"), async (request, response) => {
|
|
allowDevAllOrigin(response);
|
|
let slug = request.params.slug;
|
|
slug = slug.toLowerCase();
|
|
|
|
try {
|
|
// Get Status Page
|
|
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
|
slug,
|
|
]);
|
|
|
|
if (!statusPage) {
|
|
sendHttpError(response, "Status Page Not Found");
|
|
return null;
|
|
}
|
|
|
|
let statusPageData = await StatusPage.getStatusPageData(statusPage);
|
|
|
|
// Response
|
|
response.json(statusPageData);
|
|
|
|
} catch (error) {
|
|
sendHttpError(response, error.message);
|
|
}
|
|
});
|
|
|
|
// Status Page Polling Data
|
|
// Can fetch only if published
|
|
router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (request, response) => {
|
|
allowDevAllOrigin(response);
|
|
|
|
try {
|
|
let heartbeatList = {};
|
|
let uptimeList = {};
|
|
|
|
let slug = request.params.slug;
|
|
slug = slug.toLowerCase();
|
|
let statusPageID = await StatusPage.slugToID(slug);
|
|
|
|
let monitorIDList = await R.getCol(`
|
|
SELECT monitor_group.monitor_id FROM monitor_group, \`group\`
|
|
WHERE monitor_group.group_id = \`group\`.id
|
|
AND public = 1
|
|
AND \`group\`.status_page_id = ?
|
|
`, [
|
|
statusPageID,
|
|
]);
|
|
|
|
for (let monitorID of monitorIDList) {
|
|
let list = await R.getAll(`
|
|
SELECT * FROM heartbeat
|
|
WHERE monitor_id = ?
|
|
ORDER BY time DESC
|
|
LIMIT 50
|
|
`, [
|
|
monitorID,
|
|
]);
|
|
|
|
list = R.convertToBeans("heartbeat", list);
|
|
heartbeatList[monitorID] = list.reverse().map(row => row.toPublicJSON());
|
|
|
|
const uptimeCalculator = await UptimeCalculator.getUptimeCalculator(monitorID);
|
|
uptimeList[`${monitorID}_24`] = uptimeCalculator.get24Hour().uptime;
|
|
}
|
|
|
|
response.json({
|
|
heartbeatList,
|
|
uptimeList,
|
|
});
|
|
|
|
} catch (error) {
|
|
sendHttpError(response, error.message);
|
|
}
|
|
});
|
|
|
|
// Status page's manifest.json
|
|
router.get("/api/status-page/:slug/manifest.json", cache("1440 minutes"), async (request, response) => {
|
|
allowDevAllOrigin(response);
|
|
let slug = request.params.slug;
|
|
slug = slug.toLowerCase();
|
|
|
|
try {
|
|
// Get Status Page
|
|
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
|
slug,
|
|
]);
|
|
|
|
if (!statusPage) {
|
|
sendHttpError(response, "Not Found");
|
|
return;
|
|
}
|
|
|
|
// Response
|
|
response.json({
|
|
"name": statusPage.title,
|
|
"start_url": "/status/" + statusPage.slug,
|
|
"display": "standalone",
|
|
"icons": [
|
|
{
|
|
"src": statusPage.icon,
|
|
"sizes": "128x128",
|
|
"type": "image/png",
|
|
},
|
|
],
|
|
});
|
|
|
|
} catch (error) {
|
|
sendHttpError(response, error.message);
|
|
}
|
|
});
|
|
|
|
// overall status-page status badge
|
|
router.get("/api/status-page/:slug/badge", cache("5 minutes"), async (request, response) => {
|
|
allowDevAllOrigin(response);
|
|
let slug = request.params.slug;
|
|
slug = slug.toLowerCase();
|
|
const statusPageID = await StatusPage.slugToID(slug);
|
|
const {
|
|
label,
|
|
upColor = badgeConstants.defaultUpColor,
|
|
downColor = badgeConstants.defaultDownColor,
|
|
partialColor = "#F6BE00",
|
|
maintenanceColor = "#808080",
|
|
style = badgeConstants.defaultStyle,
|
|
} = request.query;
|
|
|
|
try {
|
|
let monitorIDList = await R.getCol(`
|
|
SELECT monitor_group.monitor_id FROM monitor_group, \`group\`
|
|
WHERE monitor_group.group_id = \`group\`.id
|
|
AND public = 1
|
|
AND \`group\`.status_page_id = ?
|
|
`, [
|
|
statusPageID,
|
|
]);
|
|
|
|
let hasUp = false;
|
|
let hasDown = false;
|
|
let hasMaintenance = false;
|
|
|
|
for (let monitorID of monitorIDList) {
|
|
// retrieve the latest heartbeat
|
|
let beat = await R.getAll(`
|
|
SELECT * FROM heartbeat
|
|
WHERE monitor_id = ?
|
|
ORDER BY time DESC
|
|
LIMIT 1
|
|
`, [
|
|
monitorID,
|
|
]);
|
|
|
|
// to be sure, when corresponding monitor not found
|
|
if (beat.length === 0) {
|
|
continue;
|
|
}
|
|
// handle status of beat
|
|
if (beat[0].status === 3) {
|
|
hasMaintenance = true;
|
|
} else if (beat[0].status === 2) {
|
|
// ignored
|
|
} else if (beat[0].status === 1) {
|
|
hasUp = true;
|
|
} else {
|
|
hasDown = true;
|
|
}
|
|
|
|
}
|
|
|
|
const badgeValues = { style };
|
|
|
|
if (!hasUp && !hasDown && !hasMaintenance) {
|
|
// return a "N/A" badge in naColor (grey), if monitor is not public / not available / non exsitant
|
|
|
|
badgeValues.message = "N/A";
|
|
badgeValues.color = badgeConstants.naColor;
|
|
|
|
} else {
|
|
if (hasMaintenance) {
|
|
badgeValues.label = label ? label : "";
|
|
badgeValues.color = maintenanceColor;
|
|
badgeValues.message = "Maintenance";
|
|
} else if (hasUp && !hasDown) {
|
|
badgeValues.label = label ? label : "";
|
|
badgeValues.color = upColor;
|
|
badgeValues.message = "Up";
|
|
} else if (hasUp && hasDown) {
|
|
badgeValues.label = label ? label : "";
|
|
badgeValues.color = partialColor;
|
|
badgeValues.message = "Degraded";
|
|
} else {
|
|
badgeValues.label = label ? label : "";
|
|
badgeValues.color = downColor;
|
|
badgeValues.message = "Down";
|
|
}
|
|
|
|
}
|
|
|
|
// build the svg based on given values
|
|
const svg = makeBadge(badgeValues);
|
|
|
|
response.type("image/svg+xml");
|
|
response.send(svg);
|
|
|
|
} catch (error) {
|
|
sendHttpError(response, error.message);
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|