/* * For Client Socket */ const { TimeLogger } = require("../src/util"); const { R } = require("redbean-node"); const { UptimeKumaServer } = require("./uptime-kuma-server"); const server = UptimeKumaServer.getInstance(); const io = server.io; const { setting } = require("./util-server"); const checkVersion = require("./check-version"); const Database = require("./database"); /** * Send list of notification providers to client * @param {Socket} socket Socket.io socket instance * @returns {Promise} List of notifications */ async function sendNotificationList(socket) { const timeLogger = new TimeLogger(); let result = []; let list = await R.find("notification", " user_id = ? ", [ socket.userID, ]); for (let bean of list) { let notificationObject = bean.export(); notificationObject.isDefault = (notificationObject.isDefault === 1); notificationObject.usePathAsName = (notificationObject.usePathAsName === 1); notificationObject.active = (notificationObject.active === 1); const configObject = JSON.parse(notificationObject.config); if ( !("usePathAsName" in configObject)) { configObject.usePathAsName = notificationObject.usePathAsName; notificationObject.config = JSON.stringify(configObject); } result.push(notificationObject); } io.to(socket.userID).emit("notificationList", result); timeLogger.print("Send Notification List"); return list; } /** * Send Heartbeat History list to socket * @param {Socket} socket Socket.io instance * @param {number} monitorID ID of monitor to send heartbeat history * @param {boolean} toUser True = send to all browsers with the same user id, False = send to the current browser only * @param {boolean} overwrite Overwrite client-side's heartbeat list * @returns {Promise} */ async function sendHeartbeatList(socket, monitorID, toUser = false, overwrite = false) { let list = await R.getAll(` SELECT * FROM heartbeat WHERE monitor_id = ? ORDER BY time DESC LIMIT 100 `, [ monitorID, ]); let result = list.reverse(); if (toUser) { io.to(socket.userID).emit("heartbeatList", monitorID, result, overwrite); } else { socket.emit("heartbeatList", monitorID, result, overwrite); } } /** * Important Heart beat list (aka event list) * @param {Socket} socket Socket.io instance * @param {number} monitorID ID of monitor to send heartbeat history * @param {boolean} toUser True = send to all browsers with the same user id, False = send to the current browser only * @param {boolean} overwrite Overwrite client-side's heartbeat list * @returns {Promise} */ async function sendImportantHeartbeatList(socket, monitorID, toUser = false, overwrite = false) { const timeLogger = new TimeLogger(); let list = await R.find("heartbeat", ` monitor_id = ? AND important = 1 ORDER BY time DESC LIMIT 500 `, [ monitorID, ]); timeLogger.print(`[Monitor: ${monitorID}] sendImportantHeartbeatList`); if (toUser) { io.to(socket.userID).emit("importantHeartbeatList", monitorID, list, overwrite); } else { socket.emit("importantHeartbeatList", monitorID, list, overwrite); } } /** * Emit proxy list to client * @param {Socket} socket Socket.io socket instance * @returns {Promise} List of proxies */ async function sendProxyList(socket) { const timeLogger = new TimeLogger(); const list = await R.find("proxy", " user_id = ? ", [ socket.userID ]); io.to(socket.userID).emit("proxyList", list.map(bean => bean.export())); timeLogger.print("Send Proxy List"); return list; } /** * Emit API key list to client * @param {Socket} socket Socket.io socket instance * @returns {Promise} */ async function sendAPIKeyList(socket) { const timeLogger = new TimeLogger(); let result = []; const list = await R.find( "api_key", "user_id=?", [ socket.userID ], ); for (let bean of list) { result.push(bean.toPublicJSON()); } io.to(socket.userID).emit("apiKeyList", result); timeLogger.print("Sent API Key List"); return list; } /** * Emits the version information to the client. * @param {Socket} socket Socket.io socket instance * @param {boolean} hideVersion Should we hide the version information in the response? * @returns {Promise} */ async function sendInfo(socket, hideVersion = false) { let version; let latestVersion; let isContainer; let dbType; if (!hideVersion) { version = checkVersion.version; latestVersion = checkVersion.latestVersion; isContainer = (process.env.UPTIME_KUMA_IS_CONTAINER === "1"); dbType = Database.dbConfig.type; } socket.emit("info", { version, latestVersion, isContainer, dbType, primaryBaseURL: await setting("primaryBaseURL"), serverTimezone: await server.getTimezone(), serverTimezoneOffset: server.getTimezoneOffset(), }); } /** * Send list of docker hosts to client * @param {Socket} socket Socket.io socket instance * @returns {Promise} List of docker hosts */ async function sendDockerHostList(socket) { const timeLogger = new TimeLogger(); let result = []; let list = await R.find("docker_host", " user_id = ? ", [ socket.userID, ]); for (let bean of list) { result.push(bean.toJSON()); } io.to(socket.userID).emit("dockerHostList", result); timeLogger.print("Send Docker Host List"); return list; } /** * Send list of docker hosts to client * @param {Socket} socket Socket.io socket instance * @returns {Promise} List of docker hosts */ async function sendRemoteBrowserList(socket) { const timeLogger = new TimeLogger(); let result = []; let list = await R.find("remote_browser", " user_id = ? ", [ socket.userID, ]); for (let bean of list) { result.push(bean.toJSON()); } io.to(socket.userID).emit("remoteBrowserList", result); timeLogger.print("Send Remote Browser List"); return list; } /** * Send list of monitor types to client * @param {Socket} socket Socket.io socket instance * @returns {Promise} */ async function sendMonitorTypeList(socket) { const result = Object.entries(UptimeKumaServer.monitorTypeList).map(([ key, type ]) => { return [ key, { supportsConditions: type.supportsConditions, conditionVariables: type.conditionVariables.map(v => { return { id: v.id, operators: v.operators.map(o => { return { id: o.id, caption: o.caption, }; }), }; }), }]; }); io.to(socket.userID).emit("monitorTypeList", Object.fromEntries(result)); } module.exports = { sendNotificationList, sendImportantHeartbeatList, sendHeartbeatList, sendProxyList, sendAPIKeyList, sendInfo, sendDockerHostList, sendRemoteBrowserList, sendMonitorTypeList, };