Add support for different plugin sources; add support for installing plugins from npm
parent
e6bdc4cd8c
commit
d8c531cb4d
File diff suppressed because it is too large
Load Diff
|
@ -34,6 +34,7 @@
|
||||||
"moment": "^2.27.0",
|
"moment": "^2.27.0",
|
||||||
"mv": "^2.1.1",
|
"mv": "^2.1.1",
|
||||||
"mysql2": "^2.1.0",
|
"mysql2": "^2.1.0",
|
||||||
|
"pacote": "^11.1.11",
|
||||||
"public-ip": "^4.0.2",
|
"public-ip": "^4.0.2",
|
||||||
"sqlite3": "^5.0.0",
|
"sqlite3": "^5.0.0",
|
||||||
"tmp": "^0.1.0",
|
"tmp": "^0.1.0",
|
||||||
|
|
61
src/main.js
61
src/main.js
|
@ -7,29 +7,13 @@ const knex = require("./knex");
|
||||||
const {messageQueue} = require("./queue");
|
const {messageQueue} = require("./queue");
|
||||||
const utils = require("./utils");
|
const utils = require("./utils");
|
||||||
const { createCommandManager } = require("./commands");
|
const { createCommandManager } = require("./commands");
|
||||||
const { getPluginAPI, loadPlugin } = require("./plugins");
|
const { getPluginAPI, installPlugins, loadPlugins } = require("./plugins");
|
||||||
const { callBeforeNewThreadHooks } = require("./hooks/beforeNewThread");
|
const { callBeforeNewThreadHooks } = require("./hooks/beforeNewThread");
|
||||||
|
|
||||||
const blocked = require("./data/blocked");
|
const blocked = require("./data/blocked");
|
||||||
const threads = require("./data/threads");
|
const threads = require("./data/threads");
|
||||||
const updates = require("./data/updates");
|
const updates = require("./data/updates");
|
||||||
|
|
||||||
const reply = require("./modules/reply");
|
|
||||||
const close = require("./modules/close");
|
|
||||||
const snippets = require("./modules/snippets");
|
|
||||||
const logs = require("./modules/logs");
|
|
||||||
const move = require("./modules/move");
|
|
||||||
const block = require("./modules/block");
|
|
||||||
const suspend = require("./modules/suspend");
|
|
||||||
const { plugin: webserver } = require("./modules/webserver");
|
|
||||||
const greeting = require("./modules/greeting");
|
|
||||||
const typingProxy = require("./modules/typingProxy");
|
|
||||||
const version = require("./modules/version");
|
|
||||||
const newthread = require("./modules/newthread");
|
|
||||||
const idModule = require("./modules/id");
|
|
||||||
const alert = require("./modules/alert");
|
|
||||||
const joinLeaveNotification = require("./modules/joinLeaveNotification");
|
|
||||||
|
|
||||||
const {ACCIDENTAL_THREAD_MESSAGES} = require("./data/constants");
|
const {ACCIDENTAL_THREAD_MESSAGES} = require("./data/constants");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -301,36 +285,29 @@ async function initPlugins() {
|
||||||
|
|
||||||
// Load plugins
|
// Load plugins
|
||||||
const builtInPlugins = [
|
const builtInPlugins = [
|
||||||
reply,
|
"file:./src/modules/reply",
|
||||||
close,
|
"file:./src/modules/close",
|
||||||
logs,
|
"file:./src/modules/logs",
|
||||||
block,
|
"file:./src/modules/block",
|
||||||
move,
|
"file:./src/modules/move",
|
||||||
snippets,
|
"file:./src/modules/snippets",
|
||||||
suspend,
|
"file:./src/modules/suspend",
|
||||||
greeting,
|
"file:./src/modules/greeting",
|
||||||
webserver,
|
"file:./src/modules/webserverPlugin",
|
||||||
typingProxy,
|
"file:./src/modules/typingProxy",
|
||||||
version,
|
"file:./src/modules/version",
|
||||||
newthread,
|
"file:./src/modules/newthread",
|
||||||
idModule,
|
"file:./src/modules/id",
|
||||||
alert,
|
"file:./src/modules/alert",
|
||||||
joinLeaveNotification
|
"file:./src/modules/joinLeaveNotification",
|
||||||
];
|
];
|
||||||
|
|
||||||
const plugins = [...builtInPlugins];
|
const plugins = [...builtInPlugins, ...config.plugins];
|
||||||
|
|
||||||
if (config.plugins && config.plugins.length) {
|
await installPlugins(plugins);
|
||||||
for (const plugin of config.plugins) {
|
|
||||||
const pluginFn = require(`../${plugin}`);
|
|
||||||
plugins.push(pluginFn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const pluginApi = getPluginAPI({ bot, knex, config, commands });
|
const pluginApi = getPluginAPI({ bot, knex, config, commands });
|
||||||
for (const plugin of plugins) {
|
await loadPlugins(plugins, pluginApi);
|
||||||
await loadPlugin(plugin, pluginApi);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.updateNotifications) {
|
if (config.updateNotifications) {
|
||||||
updates.startVersionRefreshLoop();
|
updates.startVersionRefreshLoop();
|
||||||
|
|
|
@ -64,9 +64,4 @@ server.on("error", err => {
|
||||||
console.log("[WARN] Web server error:", err.message);
|
console.log("[WARN] Web server error:", err.message);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = {
|
module.exports = server;
|
||||||
server,
|
|
||||||
plugin() {
|
|
||||||
server.listen(config.port);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
const server = require("./webserver");
|
||||||
|
|
||||||
|
module.exports = ({ config }) => {
|
||||||
|
server.listen(config.port);
|
||||||
|
};
|
|
@ -4,8 +4,94 @@ const { beforeNewThread } = require("./hooks/beforeNewThread");
|
||||||
const { afterThreadClose } = require("./hooks/afterThreadClose");
|
const { afterThreadClose } = require("./hooks/afterThreadClose");
|
||||||
const formats = require("./formatters");
|
const formats = require("./formatters");
|
||||||
const { server: webserver } = require("./modules/webserver");
|
const { server: webserver } = require("./modules/webserver");
|
||||||
|
const childProcess = require("child_process");
|
||||||
|
const pacote = require("pacote");
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
const pluginSources = {
|
||||||
|
npm: {
|
||||||
|
install(plugins) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
console.log(`Installing ${plugins.length} plugins from NPM...`);
|
||||||
|
|
||||||
|
let stderr = "";
|
||||||
|
const npmProcess = childProcess.spawn("npm", ["install", "--no-save", ...plugins], { cwd: process.cwd() });
|
||||||
|
npmProcess.stderr.on("data", data => { stderr += String(data) });
|
||||||
|
npmProcess.on("close", code => {
|
||||||
|
if (code !== 0) {
|
||||||
|
return reject(new Error(stderr));
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async load(plugin, pluginApi) {
|
||||||
|
const manifest = await pacote.manifest(plugin);
|
||||||
|
const packageName = manifest.name;
|
||||||
|
const pluginFn = require(packageName);
|
||||||
|
if (typeof pluginFn !== "function") {
|
||||||
|
throw new Error(`Plugin '${plugin}' is not a valid plugin`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pluginFn(pluginApi);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
file: {
|
||||||
|
install(plugins) {},
|
||||||
|
load(plugin, pluginApi) {
|
||||||
|
const requirePath = path.join(__dirname, "..", plugin);
|
||||||
|
const pluginFn = require(requirePath);
|
||||||
|
if (typeof pluginFn !== "function") {
|
||||||
|
throw new Error(`Plugin '${plugin}' is not a valid plugin`);
|
||||||
|
}
|
||||||
|
return pluginFn(pluginApi);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultPluginSource = "file";
|
||||||
|
|
||||||
|
function splitPluginSource(pluginName) {
|
||||||
|
for (const pluginSource of Object.keys(pluginSources)) {
|
||||||
|
if (pluginName.startsWith(`${pluginSource}:`)) {
|
||||||
|
return {
|
||||||
|
source: pluginSource,
|
||||||
|
plugin: pluginName.slice(pluginSource.length + 1),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
source: defaultPluginSource,
|
||||||
|
plugin: pluginName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
async installPlugins(plugins) {
|
||||||
|
const pluginsBySource = {};
|
||||||
|
|
||||||
|
for (const pluginName of plugins) {
|
||||||
|
const { source, plugin } = splitPluginSource(pluginName);
|
||||||
|
pluginsBySource[source] = pluginsBySource[source] || [];
|
||||||
|
pluginsBySource[source].push(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [source, sourcePlugins] of Object.entries(pluginsBySource)) {
|
||||||
|
await pluginSources[source].install(sourcePlugins);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async loadPlugins(plugins, pluginApi) {
|
||||||
|
for (const pluginName of plugins) {
|
||||||
|
const { source, plugin } = splitPluginSource(pluginName);
|
||||||
|
await pluginSources[source].load(plugin, pluginApi);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bot
|
* @param bot
|
||||||
* @param knex
|
* @param knex
|
||||||
|
@ -44,8 +130,4 @@ module.exports = {
|
||||||
webserver,
|
webserver,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
async loadPlugin(plugin, api) {
|
|
||||||
await plugin(api);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue