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",
|
||||
"mv": "^2.1.1",
|
||||
"mysql2": "^2.1.0",
|
||||
"pacote": "^11.1.11",
|
||||
"public-ip": "^4.0.2",
|
||||
"sqlite3": "^5.0.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 utils = require("./utils");
|
||||
const { createCommandManager } = require("./commands");
|
||||
const { getPluginAPI, loadPlugin } = require("./plugins");
|
||||
const { getPluginAPI, installPlugins, loadPlugins } = require("./plugins");
|
||||
const { callBeforeNewThreadHooks } = require("./hooks/beforeNewThread");
|
||||
|
||||
const blocked = require("./data/blocked");
|
||||
const threads = require("./data/threads");
|
||||
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");
|
||||
|
||||
module.exports = {
|
||||
|
@ -301,36 +285,29 @@ async function initPlugins() {
|
|||
|
||||
// Load plugins
|
||||
const builtInPlugins = [
|
||||
reply,
|
||||
close,
|
||||
logs,
|
||||
block,
|
||||
move,
|
||||
snippets,
|
||||
suspend,
|
||||
greeting,
|
||||
webserver,
|
||||
typingProxy,
|
||||
version,
|
||||
newthread,
|
||||
idModule,
|
||||
alert,
|
||||
joinLeaveNotification
|
||||
"file:./src/modules/reply",
|
||||
"file:./src/modules/close",
|
||||
"file:./src/modules/logs",
|
||||
"file:./src/modules/block",
|
||||
"file:./src/modules/move",
|
||||
"file:./src/modules/snippets",
|
||||
"file:./src/modules/suspend",
|
||||
"file:./src/modules/greeting",
|
||||
"file:./src/modules/webserverPlugin",
|
||||
"file:./src/modules/typingProxy",
|
||||
"file:./src/modules/version",
|
||||
"file:./src/modules/newthread",
|
||||
"file:./src/modules/id",
|
||||
"file:./src/modules/alert",
|
||||
"file:./src/modules/joinLeaveNotification",
|
||||
];
|
||||
|
||||
const plugins = [...builtInPlugins];
|
||||
const plugins = [...builtInPlugins, ...config.plugins];
|
||||
|
||||
if (config.plugins && config.plugins.length) {
|
||||
for (const plugin of config.plugins) {
|
||||
const pluginFn = require(`../${plugin}`);
|
||||
plugins.push(pluginFn);
|
||||
}
|
||||
}
|
||||
await installPlugins(plugins);
|
||||
|
||||
const pluginApi = getPluginAPI({ bot, knex, config, commands });
|
||||
for (const plugin of plugins) {
|
||||
await loadPlugin(plugin, pluginApi);
|
||||
}
|
||||
await loadPlugins(plugins, pluginApi);
|
||||
|
||||
if (config.updateNotifications) {
|
||||
updates.startVersionRefreshLoop();
|
||||
|
|
|
@ -64,9 +64,4 @@ server.on("error", err => {
|
|||
console.log("[WARN] Web server error:", err.message);
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
server,
|
||||
plugin() {
|
||||
server.listen(config.port);
|
||||
},
|
||||
};
|
||||
module.exports = server;
|
||||
|
|
|
@ -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 formats = require("./formatters");
|
||||
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 = {
|
||||
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 knex
|
||||
|
@ -44,8 +130,4 @@ module.exports = {
|
|||
webserver,
|
||||
};
|
||||
},
|
||||
|
||||
async loadPlugin(plugin, api) {
|
||||
await plugin(api);
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue