Add support for command plugins (#2757)
This commit is contained in:
commit
1b38e6cc02
@ -19,62 +19,6 @@ const colorCodeMap = [
|
||||
["15", "Light Grey"],
|
||||
];
|
||||
|
||||
const commands = [
|
||||
"/as",
|
||||
"/away",
|
||||
"/back",
|
||||
"/ban",
|
||||
"/banlist",
|
||||
"/bs",
|
||||
"/close",
|
||||
"/collapse",
|
||||
"/connect",
|
||||
"/cs",
|
||||
"/ctcp",
|
||||
"/cycle",
|
||||
"/dehop",
|
||||
"/deop",
|
||||
"/devoice",
|
||||
"/disconnect",
|
||||
"/expand",
|
||||
"/ho",
|
||||
"/hop",
|
||||
"/hs",
|
||||
"/ignore",
|
||||
"/ignorelist",
|
||||
"/invite",
|
||||
"/invitelist",
|
||||
"/join",
|
||||
"/kick",
|
||||
"/leave",
|
||||
"/list",
|
||||
"/me",
|
||||
"/mode",
|
||||
"/ms",
|
||||
"/msg",
|
||||
"/nick",
|
||||
"/notice",
|
||||
"/ns",
|
||||
"/op",
|
||||
"/os",
|
||||
"/part",
|
||||
"/query",
|
||||
"/quote",
|
||||
"/quit",
|
||||
"/raw",
|
||||
"/rejoin",
|
||||
"/rs",
|
||||
"/say",
|
||||
"/send",
|
||||
"/server",
|
||||
"/slap",
|
||||
"/topic",
|
||||
"/unban",
|
||||
"/unignore",
|
||||
"/voice",
|
||||
"/whois",
|
||||
];
|
||||
|
||||
const condensedTypes = [
|
||||
"away",
|
||||
"back",
|
||||
@ -95,7 +39,7 @@ const timeFormats = {
|
||||
|
||||
module.exports = {
|
||||
colorCodeMap,
|
||||
commands,
|
||||
commands: [],
|
||||
condensedTypes,
|
||||
condensedTypesQuery,
|
||||
timeFormats,
|
||||
|
8
client/js/socket-events/commands.js
Normal file
8
client/js/socket-events/commands.js
Normal file
@ -0,0 +1,8 @@
|
||||
const constants = require("../constants");
|
||||
const socket = require("../socket");
|
||||
|
||||
socket.on("commands", function(commands) {
|
||||
if (commands) {
|
||||
constants.commands = commands;
|
||||
}
|
||||
});
|
@ -2,6 +2,7 @@
|
||||
|
||||
require("./auth");
|
||||
require("./change_password");
|
||||
require("./commands");
|
||||
require("./init");
|
||||
require("./join");
|
||||
require("./more");
|
||||
|
@ -11,6 +11,7 @@ const Helper = require("./helper");
|
||||
const UAParser = require("ua-parser-js");
|
||||
const uuidv4 = require("uuid/v4");
|
||||
const escapeRegExp = require("lodash/escapeRegExp");
|
||||
const inputs = require("./plugins/inputs");
|
||||
|
||||
const MessageStorage = require("./plugins/messageStorage/sqlite");
|
||||
const TextFileMessageStorage = require("./plugins/messageStorage/text");
|
||||
@ -40,33 +41,6 @@ const events = [
|
||||
"list",
|
||||
"whois",
|
||||
];
|
||||
const inputs = [
|
||||
"ban",
|
||||
"ctcp",
|
||||
"msg",
|
||||
"part",
|
||||
"rejoin",
|
||||
"action",
|
||||
"away",
|
||||
"connect",
|
||||
"disconnect",
|
||||
"ignore",
|
||||
"invite",
|
||||
"kick",
|
||||
"kill",
|
||||
"mode",
|
||||
"nick",
|
||||
"notice",
|
||||
"quit",
|
||||
"raw",
|
||||
"topic",
|
||||
"list",
|
||||
"whois",
|
||||
].reduce(function(plugins, name) {
|
||||
const plugin = require(`./plugins/inputs/${name}`);
|
||||
plugin.commands.forEach((command) => plugins[command] = plugin);
|
||||
return plugins;
|
||||
}, {});
|
||||
|
||||
function Client(manager, name, config = {}) {
|
||||
_.merge(this, {
|
||||
@ -362,12 +336,20 @@ Client.prototype.inputLine = function(data) {
|
||||
const irc = target.network.irc;
|
||||
let connected = irc && irc.connection && irc.connection.connected;
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(inputs, cmd) && typeof inputs[cmd].input === "function") {
|
||||
const plugin = inputs[cmd];
|
||||
if (Object.prototype.hasOwnProperty.call(inputs.userInputs, cmd) && typeof inputs.userInputs[cmd].input === "function") {
|
||||
const plugin = inputs.userInputs[cmd];
|
||||
|
||||
if (connected || plugin.allowDisconnected) {
|
||||
connected = true;
|
||||
plugin.input.apply(client, [target.network, target.chan, cmd, args]);
|
||||
plugin.input.apply(client,
|
||||
[
|
||||
target.network,
|
||||
target.chan,
|
||||
cmd,
|
||||
args,
|
||||
(command) => this.inputLine({target: data.target, text: command}),
|
||||
]
|
||||
);
|
||||
}
|
||||
} else if (connected) {
|
||||
irc.raw(text);
|
||||
|
54
src/plugins/inputs/index.js
Normal file
54
src/plugins/inputs/index.js
Normal file
@ -0,0 +1,54 @@
|
||||
const clientSideCommands = ["/collapse", "/expand"];
|
||||
|
||||
const passThroughCommands = [
|
||||
"/as",
|
||||
"/bs",
|
||||
"/cs",
|
||||
"/ho",
|
||||
"/hs",
|
||||
"/join",
|
||||
"/ms",
|
||||
"/ns",
|
||||
"/os",
|
||||
"/rs",
|
||||
];
|
||||
|
||||
const userInputs = [
|
||||
"action",
|
||||
"away",
|
||||
"ban",
|
||||
"connect",
|
||||
"ctcp",
|
||||
"disconnect",
|
||||
"ignore",
|
||||
"invite",
|
||||
"kick",
|
||||
"kill",
|
||||
"list",
|
||||
"mode",
|
||||
"msg",
|
||||
"nick",
|
||||
"notice",
|
||||
"part",
|
||||
"quit",
|
||||
"raw",
|
||||
"rejoin",
|
||||
"topic",
|
||||
"whois",
|
||||
].reduce(function(plugins, name) {
|
||||
const plugin = require(`./${name}`);
|
||||
plugin.commands.forEach((command) => (plugins[command] = plugin));
|
||||
return plugins;
|
||||
}, {});
|
||||
|
||||
const getCommands = () =>
|
||||
Object.keys(userInputs)
|
||||
.map((command) => `/${command}`)
|
||||
.concat(clientSideCommands)
|
||||
.concat(passThroughCommands)
|
||||
.sort();
|
||||
|
||||
module.exports = {
|
||||
getCommands,
|
||||
userInputs,
|
||||
};
|
@ -6,6 +6,7 @@ const path = require("path");
|
||||
const Helper = require("../../helper");
|
||||
const themes = require("./themes");
|
||||
const packageMap = new Map();
|
||||
const inputs = require("../inputs");
|
||||
|
||||
const stylesheets = [];
|
||||
|
||||
@ -15,11 +16,15 @@ module.exports = {
|
||||
loadPackages,
|
||||
};
|
||||
|
||||
const packageApis = function(packageName) {
|
||||
const packageApis = function(clientManager, packageName) {
|
||||
return {
|
||||
Stylesheets: {
|
||||
addFile: addStylesheet.bind(this, packageName),
|
||||
},
|
||||
Commands: {
|
||||
add: (command, func) => inputs.userInputs[command] = func,
|
||||
runAsUser: (line, userName, target) => clientManager.findClient(userName).inputLine({target, text: line}),
|
||||
},
|
||||
Config: {
|
||||
getConfig: () => Helper.config,
|
||||
},
|
||||
@ -38,7 +43,7 @@ function getPackage(name) {
|
||||
return packageMap.get(name);
|
||||
}
|
||||
|
||||
function loadPackages() {
|
||||
function loadPackages(clientManager) {
|
||||
const packageJson = path.join(Helper.getPackagesPath(), "package.json");
|
||||
let packages;
|
||||
|
||||
@ -75,7 +80,7 @@ function loadPackages() {
|
||||
}
|
||||
|
||||
if (packageFile.onServerStart) {
|
||||
packageFile.onServerStart(packageApis(packageName));
|
||||
packageFile.onServerStart(packageApis(clientManager, packageName));
|
||||
}
|
||||
|
||||
log.info(`Package ${colors.bold(packageName)} loaded`);
|
||||
|
@ -16,12 +16,12 @@ const colors = require("chalk");
|
||||
const net = require("net");
|
||||
const Identification = require("./identification");
|
||||
const changelog = require("./plugins/changelog");
|
||||
const inputs = require("./plugins/inputs");
|
||||
|
||||
const themes = require("./plugins/packages/themes");
|
||||
themes.loadLocalThemes();
|
||||
|
||||
const packages = require("./plugins/packages/index");
|
||||
packages.loadPackages();
|
||||
|
||||
// The order defined the priority: the first available plugin is used
|
||||
// ALways keep local auth in the end, which should always be enabled.
|
||||
@ -173,6 +173,7 @@ module.exports = function() {
|
||||
});
|
||||
|
||||
manager = new ClientManager();
|
||||
packages.loadPackages(manager);
|
||||
|
||||
new Identification((identHandler) => {
|
||||
manager.init(identHandler, sockets);
|
||||
@ -582,6 +583,7 @@ function initializeClient(socket, client, token, lastMessage) {
|
||||
networks: client.networks.map((network) => network.getFilteredClone(client.lastActiveChannel, lastMessage)),
|
||||
token: tokenToSend,
|
||||
});
|
||||
socket.emit("commands", inputs.getCommands());
|
||||
};
|
||||
|
||||
if (!Helper.config.public && token === null) {
|
||||
|
@ -17,19 +17,6 @@ describe("client-side constants", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe(".commands", function() {
|
||||
it("should be a non-empty array", function() {
|
||||
expect(constants.commands).to.be.an("array").that.is.not.empty;
|
||||
});
|
||||
|
||||
it("should only contain strings with no whitespaces and starting with /", function() {
|
||||
constants.commands.forEach((command) => {
|
||||
expect(command).to.be.a("string").that.does.not.match(/\s/);
|
||||
expect(command[0]).to.equal("/");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(".condensedTypes", function() {
|
||||
it("should be a non-empty array", function() {
|
||||
expect(constants.condensedTypes).to.be.an("array").that.is.not.empty;
|
||||
|
21
test/plugins/inputs/indexTest.js
Normal file
21
test/plugins/inputs/indexTest.js
Normal file
@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
|
||||
const expect = require("chai").expect;
|
||||
const inputs = require("../../../src/plugins/inputs");
|
||||
|
||||
describe("inputs", function() {
|
||||
describe(".getCommands", function() {
|
||||
it("should return a non-empty array", function() {
|
||||
expect(inputs.getCommands()).to.be.an("array").that.is.not.empty;
|
||||
});
|
||||
|
||||
it("should only return strings with no whitespaces and starting with /", function() {
|
||||
inputs.getCommands().forEach((command) => {
|
||||
expect(command)
|
||||
.to.be.a("string")
|
||||
.that.does.not.match(/\s/);
|
||||
expect(command[0]).to.equal("/");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user