Merge pull request #3281 from thelounge/mcinkay/input-refactor

Refactor command API for plugins
This commit is contained in:
Pavel Djundik 2019-07-05 17:26:06 +03:00 committed by GitHub
commit 807856dbef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 68 additions and 21 deletions

View file

@ -12,6 +12,7 @@ const UAParser = require("ua-parser-js");
const uuidv4 = require("uuid/v4"); const uuidv4 = require("uuid/v4");
const escapeRegExp = require("lodash/escapeRegExp"); const escapeRegExp = require("lodash/escapeRegExp");
const inputs = require("./plugins/inputs"); const inputs = require("./plugins/inputs");
const PublicClient = require("./plugins/packages/publicClient");
const MessageStorage = require("./plugins/messageStorage/sqlite"); const MessageStorage = require("./plugins/messageStorage/sqlite");
const TextFileMessageStorage = require("./plugins/messageStorage/text"); const TextFileMessageStorage = require("./plugins/messageStorage/text");
@ -336,20 +337,19 @@ Client.prototype.inputLine = function(data) {
const irc = target.network.irc; const irc = target.network.irc;
let connected = irc && irc.connection && irc.connection.connected; let connected = irc && irc.connection && irc.connection.connected;
if (Object.prototype.hasOwnProperty.call(inputs.userInputs, cmd) && typeof inputs.userInputs[cmd].input === "function") { if (inputs.userInputs.has(cmd)) {
const plugin = inputs.userInputs[cmd]; const plugin = inputs.userInputs.get(cmd);
if (connected || plugin.allowDisconnected) { if (typeof plugin.input === "function" && (connected || plugin.allowDisconnected)) {
connected = true; connected = true;
plugin.input.apply(client, plugin.input.apply(client, [target.network, target.chan, cmd, args]);
[ }
target.network, } else if (inputs.pluginCommands.has(cmd)) {
target.chan, const plugin = inputs.pluginCommands.get(cmd);
cmd,
args, if (typeof plugin.input === "function" && (connected || plugin.allowDisconnected)) {
(command) => this.inputLine({target: data.target, text: command}), connected = true;
] plugin.input(new PublicClient(client), {network: target.network, chan: target.chan}, cmd, args);
);
} }
} else if (connected) { } else if (connected) {
irc.raw(text); irc.raw(text);

View file

@ -37,18 +37,25 @@ const userInputs = [
"whois", "whois",
].reduce(function(plugins, name) { ].reduce(function(plugins, name) {
const plugin = require(`./${name}`); const plugin = require(`./${name}`);
plugin.commands.forEach((command) => (plugins[command] = plugin)); plugin.commands.forEach((command) => plugins.set(command, plugin));
return plugins; return plugins;
}, {}); }, new Map());
const pluginCommands = new Map();
const getCommands = () => const getCommands = () =>
Object.keys(userInputs) Array.from(userInputs.keys())
.concat(Array.from(pluginCommands.keys()))
.map((command) => `/${command}`) .map((command) => `/${command}`)
.concat(clientSideCommands) .concat(clientSideCommands)
.concat(passThroughCommands) .concat(passThroughCommands)
.sort(); .sort();
const addPluginCommand = (command, func) => pluginCommands.set(command, func);
module.exports = { module.exports = {
addPluginCommand,
getCommands, getCommands,
pluginCommands,
userInputs, userInputs,
}; };

View file

@ -16,14 +16,14 @@ module.exports = {
loadPackages, loadPackages,
}; };
const packageApis = function(clientManager, packageName) { const packageApis = function(packageName) {
return { return {
Stylesheets: { Stylesheets: {
addFile: addStylesheet.bind(this, packageName), addFile: addStylesheet.bind(this, packageName),
}, },
Commands: { Commands: {
add: (command, func) => inputs.userInputs[command] = func, add: inputs.addPluginCommand,
runAsUser: (line, userName, target) => clientManager.findClient(userName).inputLine({target, text: line}), runAsUser: (command, targetId, client) => client.inputLine({target: targetId, text: command}),
}, },
Config: { Config: {
getConfig: () => Helper.config, getConfig: () => Helper.config,
@ -43,7 +43,7 @@ function getPackage(name) {
return packageMap.get(name); return packageMap.get(name);
} }
function loadPackages(clientManager) { function loadPackages() {
const packageJson = path.join(Helper.getPackagesPath(), "package.json"); const packageJson = path.join(Helper.getPackagesPath(), "package.json");
let packages; let packages;
let anyPlugins = false; let anyPlugins = false;
@ -83,7 +83,7 @@ function loadPackages(clientManager) {
} }
if (packageFile.onServerStart) { if (packageFile.onServerStart) {
packageFile.onServerStart(packageApis(clientManager, packageName)); packageFile.onServerStart(packageApis(packageName));
} }
log.info(`Package ${colors.bold(packageName)} loaded`); log.info(`Package ${colors.bold(packageName)} loaded`);

View file

@ -0,0 +1,40 @@
module.exports = class PublicClient {
constructor(client) {
this.client = client;
}
/**
*
* @param {String} command - IRC command to run, this is in the same format that a client would send to the server (eg: JOIN #test)
* @param {String} targetId - The id of the channel to simulate the command coming from. Replies will go to this channel if appropriate
*/
runAsUser(command, targetId) {
this.client.inputLine({target: targetId, text: command});
}
/**
*
* @param {Object} attributes
*/
createChannel(attributes) {
return this.client.createChannel(attributes);
}
/**
* Emits an `event` to the browser client, with `data` in the body of the event.
*
* @param {String} event - Name of the event, must be something the browser will recognise
* @param {Object} data - Body of the event, can be anything, but will need to be properly interpreted by the client
*/
sendToBrowser(event, data) {
this.client.emit(event, data);
}
/**
*
* @param {Number} chanId
*/
getChannel(chanId) {
return this.client.find(chanId);
}
};

View file

@ -173,7 +173,7 @@ module.exports = function() {
}); });
manager = new ClientManager(); manager = new ClientManager();
packages.loadPackages(manager); packages.loadPackages();
new Identification((identHandler) => { new Identification((identHandler) => {
manager.init(identHandler, sockets); manager.init(identHandler, sockets);