From d490285a447c4401e9986f6dbed3995454042fb5 Mon Sep 17 00:00:00 2001
From: yumeiyin <155420652+yumeiyin@users.noreply.github.com>
Date: Mon, 14 Jul 2025 16:08:53 +0800
Subject: [PATCH 1/3] chore: fix some minor issues in comments (#5984)
Signed-off-by: yumeiyin
---
server/model/monitor.js | 2 +-
server/notification-providers/promosms.js | 2 +-
server/socket-handlers/api-key-socket-handler.js | 2 +-
server/uptime-calculator.js | 4 ++--
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/server/model/monitor.js b/server/model/monitor.js
index 3be8267c9..0ddfa924c 100644
--- a/server/model/monitor.js
+++ b/server/model/monitor.js
@@ -1314,7 +1314,7 @@ class Monitor extends BeanModel {
/**
* Send a notification about a monitor
* @param {boolean} isFirstBeat Is this beat the first of this monitor?
- * @param {Monitor} monitor The monitor to send a notificaton about
+ * @param {Monitor} monitor The monitor to send a notification about
* @param {Bean} bean Status information about monitor
* @returns {void}
*/
diff --git a/server/notification-providers/promosms.js b/server/notification-providers/promosms.js
index 05334e902..36b7ecb33 100644
--- a/server/notification-providers/promosms.js
+++ b/server/notification-providers/promosms.js
@@ -15,7 +15,7 @@ class PromoSMS extends NotificationProvider {
notification.promosmsAllowLongSMS = false;
}
- //TODO: Add option for enabling special characters. It will decrese message max length from 160 to 70 chars.
+ //TODO: Add option for enabling special characters. It will decrease message max length from 160 to 70 chars.
//Lets remove non ascii char
let cleanMsg = msg.replace(/[^\x00-\x7F]/g, "");
diff --git a/server/socket-handlers/api-key-socket-handler.js b/server/socket-handlers/api-key-socket-handler.js
index d88151294..d49ac086b 100644
--- a/server/socket-handlers/api-key-socket-handler.js
+++ b/server/socket-handlers/api-key-socket-handler.js
@@ -27,7 +27,7 @@ module.exports.apiKeySocketHandler = (socket) => {
log.debug("apikeys", "Added API Key");
log.debug("apikeys", key);
- // Append key ID and prefix to start of key seperated by _, used to get
+ // Append key ID and prefix to start of key separated by _, used to get
// correct hash when validating key.
let formattedKey = "uk" + bean.id + "_" + clearKey;
await sendAPIKeyList(socket);
diff --git a/server/uptime-calculator.js b/server/uptime-calculator.js
index 71d1d458c..48f7d80ae 100644
--- a/server/uptime-calculator.js
+++ b/server/uptime-calculator.js
@@ -582,7 +582,7 @@ class UptimeCalculator {
let totalPing = 0;
let endTimestamp;
- // Get the eariest timestamp of the required period based on the type
+ // Get the earliest timestamp of the required period based on the type
switch (type) {
case "day":
endTimestamp = key - 86400 * (num - 1);
@@ -710,7 +710,7 @@ class UptimeCalculator {
let endTimestamp;
- // Get the eariest timestamp of the required period based on the type
+ // Get the earliest timestamp of the required period based on the type
switch (type) {
case "day":
endTimestamp = key - 86400 * (num - 1);
From 7c88a38df3815130263721394afb58e8fd32524e Mon Sep 17 00:00:00 2001
From: Ionys <9364594+Ionys320@users.noreply.github.com>
Date: Wed, 16 Jul 2025 17:28:29 +0200
Subject: [PATCH 2/3] Fixing recurring maintenance start (again) (#5914)
Co-authored-by: Frank Elsinga
---
...5-06-13-0000-maintenance-add-last-start.js | 34 ++++++++++++++++++
server/model/maintenance.js | 36 +++++++++++++++----
2 files changed, 64 insertions(+), 6 deletions(-)
create mode 100644 db/knex_migrations/2025-06-13-0000-maintenance-add-last-start.js
diff --git a/db/knex_migrations/2025-06-13-0000-maintenance-add-last-start.js b/db/knex_migrations/2025-06-13-0000-maintenance-add-last-start.js
new file mode 100644
index 000000000..3cb28d968
--- /dev/null
+++ b/db/knex_migrations/2025-06-13-0000-maintenance-add-last-start.js
@@ -0,0 +1,34 @@
+// Add column last_start_date to maintenance table
+exports.up = async function (knex) {
+ await knex.schema
+ .alterTable("maintenance", function (table) {
+ table.datetime("last_start_date");
+ });
+
+ // Perform migration for recurring-interval strategy
+ const recurringMaintenances = await knex("maintenance").where({
+ strategy: "recurring-interval",
+ cron: "* * * * *"
+ }).select("id", "start_time");
+
+ // eslint-disable-next-line camelcase
+ const maintenanceUpdates = recurringMaintenances.map(async ({ start_time, id }) => {
+ // eslint-disable-next-line camelcase
+ const [ hourStr, minuteStr ] = start_time.split(":");
+ const hour = parseInt(hourStr, 10);
+ const minute = parseInt(minuteStr, 10);
+
+ const cron = `${minute} ${hour} * * *`;
+
+ await knex("maintenance")
+ .where({ id })
+ .update({ cron });
+ });
+ await Promise.all(maintenanceUpdates);
+};
+
+exports.down = function (knex) {
+ return knex.schema.alterTable("maintenance", function (table) {
+ table.dropColumn("last_start_date");
+ });
+};
diff --git a/server/model/maintenance.js b/server/model/maintenance.js
index 0a70063ff..aa1fa0c14 100644
--- a/server/model/maintenance.js
+++ b/server/model/maintenance.js
@@ -202,7 +202,7 @@ class Maintenance extends BeanModel {
* @returns {void}
*/
static validateCron(cron) {
- let job = new Cron(cron, () => {});
+ let job = new Cron(cron, () => { });
job.stop();
}
@@ -239,6 +239,8 @@ class Maintenance extends BeanModel {
apicache.clear();
});
} else if (this.cron != null) {
+ let current = dayjs();
+
// Here should be cron or recurring
try {
this.beanMeta.status = "scheduled";
@@ -258,6 +260,10 @@ class Maintenance extends BeanModel {
this.beanMeta.status = "scheduled";
UptimeKumaServer.getInstance().sendMaintenanceListByUserID(this.user_id);
}, duration);
+
+ // Set last start date to current time
+ this.last_start_date = current.toISOString();
+ R.store(this);
};
// Create Cron
@@ -268,9 +274,25 @@ class Maintenance extends BeanModel {
const startDateTime = startDate.hour(hour).minute(minute);
this.beanMeta.job = new Cron(this.cron, {
timezone: await this.getTimezone(),
- interval: this.interval_day * 24 * 60 * 60,
startAt: startDateTime.toISOString(),
- }, startEvent);
+ }, () => {
+ if (!this.lastStartDate || this.interval_day === 1) {
+ return startEvent();
+ }
+
+ // If last start date is set, it means the maintenance has been started before
+ let lastStartDate = dayjs(this.lastStartDate)
+ .subtract(1.1, "hour"); // Subtract 1.1 hour to avoid issues with timezone differences
+
+ // Check if the interval is enough
+ if (current.diff(lastStartDate, "day") < this.interval_day) {
+ log.debug("maintenance", "Maintenance id: " + this.id + " is still in the window, skipping start event");
+ return;
+ }
+
+ log.debug("maintenance", "Maintenance id: " + this.id + " is not in the window, starting event");
+ return startEvent();
+ });
} else {
this.beanMeta.job = new Cron(this.cron, {
timezone: await this.getTimezone(),
@@ -279,7 +301,6 @@ class Maintenance extends BeanModel {
// Continue if the maintenance is still in the window
let runningTimeslot = this.getRunningTimeslot();
- let current = dayjs();
if (runningTimeslot) {
let duration = dayjs(runningTimeslot.endDate).diff(current, "second") * 1000;
@@ -423,8 +444,11 @@ class Maintenance extends BeanModel {
} else if (!this.strategy.startsWith("recurring-")) {
this.cron = "";
} else if (this.strategy === "recurring-interval") {
- // For intervals, the pattern is calculated in the run function as the interval-option is set
- this.cron = "* * * * *";
+ // For intervals, the pattern is used to check if the execution should be started
+ let array = this.start_time.split(":");
+ let hour = parseInt(array[0]);
+ let minute = parseInt(array[1]);
+ this.cron = `${minute} ${hour} * * *`;
this.duration = this.calcDuration();
log.debug("maintenance", "Cron: " + this.cron);
log.debug("maintenance", "Duration: " + this.duration);
From 2fd4e1cc72a7522df87310efdd2ff75c613f5159 Mon Sep 17 00:00:00 2001
From: "Otto Richter (fnetX)"
Date: Thu, 17 Jul 2025 08:47:51 +0200
Subject: [PATCH 3/3] Matrix token command hint should send JSON (#5990)
Co-authored-by: Otto Richter
---
src/components/notifications/Matrix.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/notifications/Matrix.vue b/src/components/notifications/Matrix.vue
index 60d43cf17..49c51f9e4 100644
--- a/src/components/notifications/Matrix.vue
+++ b/src/components/notifications/Matrix.vue
@@ -18,7 +18,7 @@
{{ $t("matrixDesc1") }}
- curl -XPOST -d '{"type": "m.login.password", "identifier": {"user": "botusername", "type": "m.id.user"}, "password": "passwordforuser"}' "https://home.server/_matrix/client/v3/login"
.
+ curl -XPOST --json '{"type": "m.login.password", "identifier": {"user": "botusername", "type": "m.id.user"}, "password": "passwordforuser"}' "https://home.server/_matrix/client/v3/login"
.