feat: Add incidents to RSS (#7420)

Co-authored-by: Frank Elsinga <frank@elsinga.de>
This commit is contained in:
DJ
2026-05-25 16:59:41 +02:00
committed by GitHub
parent efa194a6df
commit b829329e0a
2 changed files with 30 additions and 15 deletions
+20 -15
View File
@@ -77,7 +77,7 @@ class StatusPage extends BeanModel {
* @returns {Promise<string>} The rendered RSS XML
*/
static async renderRSS(statusPage, feedUrl) {
const { heartbeats, statusDescription } = await StatusPage.getRSSPageData(statusPage);
const { incidents, heartbeats, statusDescription } = await StatusPage.getRSSPageData(statusPage);
// Use custom RSS title if set, otherwise fall back to status page title
let feedTitle = "Uptime Kuma RSS Feed";
@@ -95,6 +95,17 @@ class StatusPage extends BeanModel {
updated: new Date(), // optional, default = today
});
incidents.forEach((incident) => {
let lastUpdatedDate = incident.lastUpdatedDate || incident.createdDate;
feed.addItem({
title: incident.title,
description: incident.content,
id: `i${incident.id}-${lastUpdatedDate}`,
link: feedUrl,
date: dayjs.utc(lastUpdatedDate).toDate(),
});
});
heartbeats.forEach((heartbeat) => {
feed.addItem({
title: `${heartbeat.name} is down`,
@@ -264,18 +275,11 @@ class StatusPage extends BeanModel {
* @returns {object} Status page data
*/
static async getRSSPageData(statusPage) {
// get all heartbeats that correspond to this statusPage
const config = await statusPage.toPublicJSON();
// Public Group List
const showTags = !!statusPage.show_tags;
const list = await R.find("group", " public = 1 AND status_page_id = ? ORDER BY weight ", [statusPage.id]);
const { incidents, publicGroupList } = await StatusPage.getStatusPageData(statusPage);
let heartbeats = [];
for (let groupBean of list) {
let monitorGroup = await groupBean.toPublicJSON(showTags, config?.showCertificateExpiry);
for (let monitorGroup of publicGroupList) {
for (const monitor of monitorGroup.monitorList) {
const heartbeat = await R.findOne("heartbeat", "monitor_id = ? ORDER BY time DESC", [monitor.id]);
if (heartbeat) {
@@ -288,14 +292,15 @@ class StatusPage extends BeanModel {
}
}
// keep only DOWN heartbeats in the RSS feed
heartbeats = heartbeats.filter((heartbeat) => heartbeat.status === DOWN);
// calculate RSS feed description
let status = StatusPage.overallStatus(heartbeats);
let statusDescription = StatusPage.getStatusDescription(status);
// keep only DOWN heartbeats in the RSS feed
heartbeats = heartbeats.filter((heartbeat) => heartbeat.status === DOWN);
return {
incidents,
heartbeats,
statusDescription,
};
@@ -312,7 +317,7 @@ class StatusPage extends BeanModel {
// All active incidents
let incidents = await R.find(
"incident",
" pin = 1 AND active = 1 AND status_page_id = ? ORDER BY created_date DESC",
"pin = 1 AND active = 1 AND status_page_id = ? ORDER BY created_date DESC",
[statusPage.id]
);
incidents = incidents.map((i) => i.toPublicJSON());
@@ -323,7 +328,7 @@ class StatusPage extends BeanModel {
const publicGroupList = [];
const showTags = !!statusPage.show_tags;
const list = await R.find("group", " public = 1 AND status_page_id = ? ORDER BY weight ", [statusPage.id]);
const list = await R.find("group", "public = 1 AND status_page_id = ? ORDER BY weight", [statusPage.id]);
for (let groupBean of list) {
let monitorGroup = await groupBean.toPublicJSON(showTags, config?.showCertificateExpiry);