diff --git a/db/knex_init_db.js b/db/knex_init_db.js index e838345a..fbf8d2b9 100644 --- a/db/knex_init_db.js +++ b/db/knex_init_db.js @@ -31,6 +31,7 @@ async function createTables() { table.boolean("public").notNullable().defaultTo(false); table.boolean("active").notNullable().defaultTo(true); table.integer("weight").notNullable().defaultTo(1000); + table.integer("status_page_id").unsigned(); }); // proxy diff --git a/server/database.js b/server/database.js index dbf5a6d6..98536ca4 100644 --- a/server/database.js +++ b/server/database.js @@ -683,6 +683,15 @@ class Database { static async shrink() { await R.exec("VACUUM"); } + + static sqlHourOffset() { + if (this.dbConfig.client === "sqlite3") { + return "DATETIME('now', ? || ' hours')"; + } else { + return "DATE_ADD(NOW(), INTERVAL ? HOUR)"; + } + } + } module.exports = Database; diff --git a/server/jobs/clear-old-data.js b/server/jobs/clear-old-data.js index ed80b0f7..516add2c 100644 --- a/server/jobs/clear-old-data.js +++ b/server/jobs/clear-old-data.js @@ -1,6 +1,7 @@ const { log, exit, connectDb } = require("./util-worker"); const { R } = require("redbean-node"); const { setSetting, setting } = require("../util-server"); +const Database = require("../database"); const DEFAULT_KEEP_PERIOD = 180; @@ -31,10 +32,12 @@ const DEFAULT_KEEP_PERIOD = 180; log(`Clearing Data older than ${parsedPeriod} days...`); + const sqlHourOffset = Database.sqlHourOffset(); + try { await R.exec( - "DELETE FROM heartbeat WHERE time < DATETIME('now', '-' || ? || ' days') ", - [ parsedPeriod ] + "DELETE FROM heartbeat WHERE time < " + sqlHourOffset, + [ parsedPeriod * -24 ] ); } catch (e) { log(`Failed to clear old data: ${e.message}`); diff --git a/server/model/monitor.js b/server/model/monitor.js index 4cbb56e1..6a73091c 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -19,6 +19,7 @@ const { DockerHost } = require("../docker"); const Maintenance = require("./maintenance"); const { UptimeCacheList } = require("../uptime-cache-list"); const Gamedig = require("gamedig"); +const Database = require("../database"); /** * status: @@ -935,11 +936,12 @@ class Monitor extends BeanModel { */ static async sendAvgPing(duration, io, monitorID, userID) { const timeLogger = new TimeLogger(); + const sqlHourOffset = Database.sqlHourOffset(); let avgPing = parseInt(await R.getCell(` SELECT AVG(ping) FROM heartbeat - WHERE time > DATETIME('now', ? || ' hours') + WHERE time > ${sqlHourOffset} AND ping IS NOT NULL AND monitor_id = ? `, [ -duration, diff --git a/server/routers/api-router.js b/server/routers/api-router.js index 665163ae..7dafaa3a 100644 --- a/server/routers/api-router.js +++ b/server/routers/api-router.js @@ -9,6 +9,7 @@ const StatusPage = require("../model/status_page"); const { UptimeKumaServer } = require("../uptime-kuma-server"); const { makeBadge } = require("badge-maker"); const { badgeConstants } = require("../config"); +const Database = require("../database"); let router = express.Router(); @@ -268,10 +269,12 @@ router.get("/api/badge/:id/ping/:duration?", cache("5 minutes"), async (request, const requestedDuration = Math.min(request.params.duration ? parseInt(request.params.duration, 10) : 24, 720); const overrideValue = value && parseFloat(value); + const sqlHourOffset = Database.sqlHourOffset(); + const publicAvgPing = parseInt(await R.getCell(` SELECT AVG(ping) FROM monitor_group, \`group\`, heartbeat WHERE monitor_group.group_id = \`group\`.id - AND heartbeat.time > DATETIME('now', ? || ' hours') + AND heartbeat.time > ${sqlHourOffset} AND heartbeat.ping IS NOT NULL AND public = 1 AND heartbeat.monitor_id = ? @@ -334,10 +337,12 @@ router.get("/api/badge/:id/avg-response/:duration?", cache("5 minutes"), async ( ); const overrideValue = value && parseFloat(value); + const sqlHourOffset = Database.sqlHourOffset(); + const publicAvgPing = parseInt(await R.getCell(` SELECT AVG(ping) FROM monitor_group, \`group\`, heartbeat WHERE monitor_group.group_id = \`group\`.id - AND heartbeat.time > DATETIME('now', ? || ' hours') + AND heartbeat.time > ${sqlHourOffset} AND heartbeat.ping IS NOT NULL AND public = 1 AND heartbeat.monitor_id = ? diff --git a/server/server.js b/server/server.js index 613b98f5..e93245de 100644 --- a/server/server.js +++ b/server/server.js @@ -831,15 +831,17 @@ let needSetup = false; throw new Error("Invalid period."); } + const sqlHourOffset = Database.sqlHourOffset(); + let list = await R.getAll(` SELECT * FROM heartbeat WHERE monitor_id = ? - AND time > DATETIME('now', '-' || ? || ' hours') + AND time > ${sqlHourOffset} ORDER BY time ASC `, [ monitorID, - period, + -period, ]); callback({ diff --git a/server/util-server.js b/server/util-server.js index 615edcbc..198ada51 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -27,6 +27,9 @@ const { }, } = require("node-radius-utils"); const dayjs = require("dayjs"); +const readline = require("readline"); +const rl = readline.createInterface({ input: process.stdin, + output: process.stdout }); const isWindows = process.platform === /^win/.test(process.platform); @@ -859,3 +862,5 @@ module.exports.grpcQuery = async (options) => { }); }; + +module.exports.prompt = (query) => new Promise((resolve) => rl.question(query, resolve));