diff --git a/server/database.js b/server/database.js index 2544f197..bc6c5cfc 100644 --- a/server/database.js +++ b/server/database.js @@ -4,6 +4,7 @@ const { setSetting, setting } = require("./util-server"); const { log, sleep } = require("../src/util"); const dayjs = require("dayjs"); const knex = require("knex"); +const { PluginsManager } = require("./plugins-manager"); /** * Database & App Data Folder @@ -83,6 +84,13 @@ class Database { static init(args) { // Data Directory (must be end with "/") Database.dataDir = process.env.DATA_DIR || args["data-dir"] || "./data/"; + + // Plugin feature is working only if the dataDir = "./data"; + if (Database.dataDir !== "./data/") { + log.warn("PLUGIN", "Warning: In order to enable plugin feature, you need to use the default data directory: ./data/"); + PluginsManager.disable = true; + } + Database.path = Database.dataDir + "kuma.db"; if (! fs.existsSync(Database.dataDir)) { fs.mkdirSync(Database.dataDir, { recursive: true }); diff --git a/server/model/monitor.js b/server/model/monitor.js index 9f8c8300..fbe44b76 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -617,6 +617,15 @@ class Monitor extends BeanModel { } } bean.ping = dayjs().valueOf() - startTime; + + } else if (this.type in UptimeKumaServer.monitorTypeList) { + let startTime = dayjs().valueOf(); + const monitorType = UptimeKumaServer.monitorTypeList[this.type]; + await monitorType.check(this, bean); + if (!bean.ping) { + bean.ping = dayjs().valueOf() - startTime; + } + } else { bean.msg = "Unknown Monitor Type"; bean.status = PENDING; diff --git a/server/monitor-types/monitor-type.js b/server/monitor-types/monitor-type.js index f3b4f709..f2c7cbee 100644 --- a/server/monitor-types/monitor-type.js +++ b/server/monitor-types/monitor-type.js @@ -1,5 +1,19 @@ class MonitorType { + name = undefined; + + /** + * + * @param {Monitor} monitor + * @param {Heartbeat} heartbeat + * @returns {Promise} + */ + async check(monitor, heartbeat) { + throw new Error("You need to override check()"); + } + } -module.exports = MonitorType; +module.exports = { + MonitorType, +}; diff --git a/server/plugin.js b/server/plugin.js new file mode 100644 index 00000000..77e09551 --- /dev/null +++ b/server/plugin.js @@ -0,0 +1,13 @@ +class Plugin { + async install() { + + } + + async uninstall() { + + } +} + +module.exports = { + Plugin, +}; diff --git a/server/plugins-manager.js b/server/plugins-manager.js index d0d9452c..837b7aae 100644 --- a/server/plugins-manager.js +++ b/server/plugins-manager.js @@ -4,9 +4,11 @@ const path = require("path"); class PluginsManager { + static disable = false; + /** * Plugin List - * @type {Plugin[]} + * @type {PluginWrapper[]} */ pluginList = []; @@ -20,28 +22,34 @@ class PluginsManager { * @param {UptimeKumaServer} server * @param {string} dir */ - constructor(server, dir) { - this.pluginsDir = dir; + constructor(server) { + if (!PluginsManager.disable) { + this.pluginsDir = "./data/plugins/"; - if (! fs.existsSync(this.pluginsDir)) { - fs.mkdirSync(this.pluginsDir, { recursive: true }); - } - - log.debug("plugin", "Scanning plugin directory"); - let list = fs.readdirSync(this.pluginsDir); - - this.pluginList = []; - for (let item of list) { - let plugin = new Plugin(server, this.pluginsDir + item); - - try { - plugin.load(); - this.pluginList.push(plugin); - } catch (e) { - log.error("plugin", "Failed to load plugin: " + this.pluginsDir + item); - log.error("plugin", "Reason: " + e.message); + if (! fs.existsSync(this.pluginsDir)) { + fs.mkdirSync(this.pluginsDir, { recursive: true }); } + + log.debug("plugin", "Scanning plugin directory"); + let list = fs.readdirSync(this.pluginsDir); + + this.pluginList = []; + for (let item of list) { + let plugin = new PluginWrapper(server, this.pluginsDir + item); + + try { + plugin.load(); + this.pluginList.push(plugin); + } catch (e) { + log.error("plugin", "Failed to load plugin: " + this.pluginsDir + item); + log.error("plugin", "Reason: " + e.message); + } + } + + } else { + log.warn("PLUGIN", "Skip scanning plugin directory"); } + } /** @@ -71,7 +79,7 @@ class PluginsManager { } } -class Plugin { +class PluginWrapper { server = undefined; pluginDir = undefined; @@ -129,5 +137,5 @@ class Plugin { module.exports = { PluginsManager, - Plugin + PluginWrapper }; diff --git a/server/server.js b/server/server.js index 2d81b1af..1bd2d0d4 100644 --- a/server/server.js +++ b/server/server.js @@ -167,7 +167,7 @@ let needSetup = false; Database.init(args); await initDatabase(testMode); await server.initAfterDatabaseReady(); - server.loadPlugins(Database.dataDir + "plugins/"); + server.loadPlugins(); server.entryPage = await Settings.get("entryPage"); await StatusPage.loadDomainMappingList(); diff --git a/server/uptime-kuma-server.js b/server/uptime-kuma-server.js index ebd4082c..892df2b1 100644 --- a/server/uptime-kuma-server.js +++ b/server/uptime-kuma-server.js @@ -55,6 +55,14 @@ class UptimeKumaServer { */ pluginsManager = null; + /** + * + * @type {{}} + */ + static monitorTypeList = { + + }; + static getInstance(args) { if (UptimeKumaServer.instance == null) { UptimeKumaServer.instance = new UptimeKumaServer(args); @@ -249,11 +257,34 @@ class UptimeKumaServer { } loadPlugins(dir) { - this.pluginsManager = new PluginsManager(this, dir); + this.pluginsManager = new PluginsManager(this); } + /** + * + * @param {MonitorType} monitorType + */ addMonitorType(monitorType) { - // TODO + if (monitorType instanceof MonitorType && monitorType.name) { + if (monitorType.name in UptimeKumaServer.monitorTypeList) { + log.error("", "Conflict Monitor Type name"); + } + UptimeKumaServer.monitorTypeList[monitorType.name] = monitorType; + } else { + log.error("", "Invalid Monitor Type: " + monitorType.name); + } + } + + /** + * + * @param {MonitorType} monitorType + */ + removeMonitorType(monitorType) { + if (UptimeKumaServer.monitorTypeList[monitorType.name] === monitorType) { + delete UptimeKumaServer.monitorTypeList[monitorType.name]; + } else { + log.error("", "Remove MonitorType failed: " + monitorType.name); + } } } @@ -264,3 +295,4 @@ module.exports = { // Must be at the end const MaintenanceTimeslot = require("./model/maintenance_timeslot"); +const { MonitorType } = require("./monitor-types/monitor-type"); diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 10293e0c..82a87392 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -64,7 +64,7 @@ @@ -77,7 +77,7 @@ -
+
@@ -99,10 +99,10 @@
-
+
-
+
{{ $t("keywordDescription") }}
diff --git a/src/util.js b/src/util.js index 09e6d0ee..44d29bd8 100644 Binary files a/src/util.js and b/src/util.js differ