From a48830165536fa7181b2e9df211300141661d9d4 Mon Sep 17 00:00:00 2001 From: marzavec Date: Thu, 21 Feb 2019 00:43:25 -0800 Subject: Core hook upgrade, misc fixes (See ChangeLog.md tbh) --- server/package-lock.json | 138 ++++++++++++---------------- server/package.json | 14 +-- server/src/commands/admin/reload.js | 5 +- server/src/commands/core/changenick.js | 4 +- server/src/commands/core/chat.js | 36 +++----- server/src/commands/core/emote.js | 96 +++++++++++++++++++ server/src/commands/core/help.js | 4 +- server/src/commands/core/morestats.js | 2 +- server/src/commands/core/whisper.js | 2 +- server/src/commands/internal/legacylayer.js | 20 ++++ server/src/commands/mod/dumb.js | 4 +- server/src/core/server.js | 68 +++++++++++--- server/src/managers/config.js | 5 +- 13 files changed, 264 insertions(+), 134 deletions(-) create mode 100644 server/src/commands/core/emote.js create mode 100644 server/src/commands/internal/legacylayer.js (limited to 'server') diff --git a/server/package-lock.json b/server/package-lock.json index ef02881..b23f7f6 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -22,15 +22,6 @@ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -51,9 +42,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -61,11 +52,11 @@ } }, "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "requires": { - "color-name": "^1.1.1" + "color-name": "1.1.3" } }, "color-name": { @@ -74,28 +65,20 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "colors": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz", - "integrity": "sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==" + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" }, "common-tags": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.7.2.tgz", - "integrity": "sha512-joj9ZlUOjCrwdbmiLqafeUSgkUM74NqhLsZtSqDmhKudaIY197zTrb8JMl31fMnCUuxwFT23eC/oWvrZzDLRJQ==", - "requires": { - "babel-runtime": "^6.26.0" - } + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==" }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, - "core-js": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.6.tgz", - "integrity": "sha512-lQUVfQi0aLix2xpyjrrJEvfuYCqPc/HwmTKsC/VNf8q0zsjX7SQZtp4+oRONN5Tsur9GDETPjj+Ub2iDiGZfSQ==" - }, "cycle": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", @@ -107,12 +90,12 @@ "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" }, "deasync": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.13.tgz", - "integrity": "sha512-/6ngYM7AapueqLtvOzjv9+11N2fHDSrkxeMF1YPE20WIfaaawiBg+HZH1E5lHrcJxlKR42t6XPOEmMmqcAsU1g==", + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.14.tgz", + "integrity": "sha512-wN8sIuEqIwyQh72AG7oY6YQODCxIp1eXzEZlZznBuwDF8Q03Tdy9QNp1BNZXeadXoklNrw+Ip1fch+KXo/+ASw==", "requires": { "bindings": "~1.2.1", - "nan": "^2.0.7" + "node-addon-api": "^1.6.0" } }, "deep-equal": { @@ -121,12 +104,13 @@ "integrity": "sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0=" }, "didyoumean2": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/didyoumean2/-/didyoumean2-1.3.0.tgz", - "integrity": "sha1-bjT0AUM1HJIGlulyO7oB/8C5ZAI=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/didyoumean2/-/didyoumean2-2.0.2.tgz", + "integrity": "sha512-YEpkuyJ4lN8fSuuQy1UgfzGTAPi92rehUIcNmO+dcPhka0j2jWWniAy8tWEyJ2WJJQ3DLVI0C1Kjy31MJgFseA==", "requires": { "leven": "^2.0.0", - "lodash": "^4.17.2" + "lodash.deburr": "^4.1.0", + "ramda": "^0.26.1" } }, "escape-string-regexp": { @@ -140,9 +124,9 @@ "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" }, "fs-extra": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", - "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "requires": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -155,9 +139,9 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -168,9 +152,9 @@ } }, "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" }, "has-flag": { "version": "3.0.0", @@ -214,10 +198,10 @@ "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" }, - "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + "lodash.deburr": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.deburr/-/lodash.deburr-4.1.0.tgz", + "integrity": "sha1-3bG7s+8HRYwBd7oH3hRCLLAz/5s=" }, "minimatch": { "version": "3.0.4", @@ -241,20 +225,20 @@ } }, "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" - }, - "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, "ncp": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz", "integrity": "sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY=" }, + "node-addon-api": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.6.2.tgz", + "integrity": "sha512-479Bjw9nTE5DdBSZZWprFryHGjUaQC31y1wHo19We/k0BZlrmhqQitWoUL0cD8+scljCbIUL+E58oRDEakdGGA==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -286,6 +270,11 @@ "winston": "2.1.x" } }, + "ramda": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", + "integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==" + }, "read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", @@ -299,22 +288,17 @@ "resolved": "https://registry.npmjs.org/readdir-recursive/-/readdir-recursive-0.0.4.tgz", "integrity": "sha1-mvQ1q6nFi9gNvclIi025up8SMB8=" }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" - }, "revalidator": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=" }, "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "requires": { - "glob": "^7.0.5" + "glob": "^7.1.3" } }, "stack-trace": { @@ -323,17 +307,17 @@ "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "requires": { "has-flag": "^3.0.0" } }, "universalify": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", - "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" }, "utile": { "version": "0.3.0", @@ -385,9 +369,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.1.1.tgz", - "integrity": "sha512-bOusvpCb09TOBLbpMKszd45WKC2KPtxiyiHanv+H2DE3Az+1db5a/L7sVJZVDPUC1Br8f0SKRr1KjLpD1U/IAw==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", "requires": { "async-limiter": "~1.0.0" } diff --git a/server/package.json b/server/package.json index 7973595..8595033 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "hack.chat-v2", - "version": "2.1.0", + "version": "2.1.9", "description": "a minimal distraction free chat application", "main": "main.js", "repository": { @@ -18,14 +18,14 @@ "author": "Marzavec", "license": "WTFPL", "dependencies": { - "chalk": "^2.3.2", - "common-tags": "^1.7.2", + "chalk": "^2.4.2", + "common-tags": "^1.8.0", "dateformat": "^3.0.3", - "deasync": "^0.1.12", - "didyoumean2": "^1.3.0", - "fs-extra": "^5.0.0", + "deasync": "^0.1.14", + "didyoumean2": "^2.0.2", + "fs-extra": "^7.0.1", "prompt": "^1.0.0", "readdir-recursive": "0.0.4", - "ws": "^5.0.0" + "ws": "^6.1.4" } } diff --git a/server/src/commands/admin/reload.js b/server/src/commands/admin/reload.js index f40d0b2..947f9d9 100644 --- a/server/src/commands/admin/reload.js +++ b/server/src/commands/admin/reload.js @@ -9,13 +9,12 @@ exports.run = async (core, server, socket, data) => { return server._police.frisk(socket.remoteAddress, 20); } - // do command reloads and store results + // do command reload and store results let loadResult = core.managers.dynamicImports.reloadDirCache('src/commands'); loadResult += core.commands.loadCommands(); // clear and rebuild all module hooks - server.clearHooks(); - core.commands.initCommandHooks(server); + server.loadHooks(); // build reply based on reload results if (loadResult == '') { diff --git a/server/src/commands/core/changenick.js b/server/src/commands/core/changenick.js index 28d8de3..ae057b3 100644 --- a/server/src/commands/core/changenick.js +++ b/server/src/commands/core/changenick.js @@ -85,10 +85,10 @@ exports.run = async (core, server, socket, data) => { // module hook functions exports.initHooks = (server) => { - server.registerHook('in', 'chat', this.nickCheck); + server.registerHook('in', 'chat', this.nickCheck, 29); }; -// hooks chat commands checking for /whisper +// hooks chat commands checking for /nick exports.nickCheck = (core, server, socket, payload) => { if (typeof payload.text !== 'string') { return false; diff --git a/server/src/commands/core/chat.js b/server/src/commands/core/chat.js index 6f5c6a0..3455453 100644 --- a/server/src/commands/core/chat.js +++ b/server/src/commands/core/chat.js @@ -62,8 +62,8 @@ exports.run = async (core, server, socket, data) => { // module hook functions exports.initHooks = (server) => { - server.registerHook('in', 'chat', this.commandCheckIn); - server.registerHook('out', 'chat', this.commandCheckOut); + server.registerHook('in', 'chat', this.commandCheckIn, 20); + server.registerHook('in', 'chat', this.finalCmdCheck, 254); }; // checks for miscellaneous '/' based commands @@ -84,31 +84,26 @@ exports.commandCheckIn = (core, server, socket, payload) => { return payload; }; -// checks for miscellaneous '/' based commands -exports.commandCheckOut = (core, server, socket, payload) => { +exports.finalCmdCheck = (core, server, socket, payload) => { + if (typeof payload.text !== 'string') { + return false; + } + if (!payload.text.startsWith('/')) { return payload; } - // TODO: make emotes their own module/event #lazydev - if (payload.text.startsWith('//me ')) { - payload.text = payload.text.substr(1, payload.text.length); + if (payload.text.startsWith('//')) { + payload.text = payload.text.substr(1); return payload; - } else if (payload.text.startsWith('/me ')) { - let emote = payload.text.substr(4); - if (emote.trim() === '') { - emote = 'fails at life'; - } - - let newPayload = { - cmd: 'info', - type: 'emote', - nick: payload.nick, - text: `@${payload.nick} ${emote}` - }; + } else { + server.reply({ + cmd: 'warn', + text: `Unknown command: ${payload.text}` + }, socket); - return newPayload; + return false; } return payload; @@ -123,6 +118,5 @@ exports.info = { API: { cmd: 'chat', text: '' } Text: Uuuuhm. Just kind type in that little box at the bottom and hit enter.\n Bonus super secret hidden commands: - /me /myhash` }; diff --git a/server/src/commands/core/emote.js b/server/src/commands/core/emote.js new file mode 100644 index 0000000..40fcff2 --- /dev/null +++ b/server/src/commands/core/emote.js @@ -0,0 +1,96 @@ +/* + Description: Broadcasts an emote to the current channel +*/ + +// module support functions +const parseText = (text) => { + // verifies user input is text + if (typeof text !== 'string') { + return false; + } + + // strip newlines from beginning and end + text = text.replace(/^\s*\n|^\s+$|\n\s*$/g, ''); + // replace 3+ newlines with just 2 newlines + text = text.replace(/\n{3,}/g, "\n\n"); + + return text; +}; + +// module main +exports.run = async (core, server, socket, payload) => { + // check user input + let text = parseText(payload.text); + + if (!text) { + // lets not send objects or empty text, yea? + return server._police.frisk(socket.remoteAddress, 8); + } + + // check for spam + let score = text.length / 83 / 4; + if (server._police.frisk(socket.remoteAddress, score)) { + return server.reply({ + cmd: 'warn', + text: 'You are sending too much text. Wait a moment and try again.\nPress the up arrow key to restore your last message.' + }, socket); + } + + let newPayload = { + cmd: 'info', + type: 'emote', + nick: socket.nick, + text: `@${socket.nick} ${text}` + }; + + // broadcast to channel peers + server.broadcast( newPayload, { channel: socket.channel}); +}; + +// module hook functions +exports.initHooks = (server) => { + server.registerHook('in', 'chat', this.emoteCheck, 30); +}; + +// hooks chat commands checking for /me +exports.emoteCheck = (core, server, socket, payload) => { + if (typeof payload.text !== 'string') { + return false; + } + + if (payload.text.startsWith('/me ')) { + let input = payload.text.split(' '); + + // If there is no emote target parameter + if (input[1] === undefined) { + server.reply({ + cmd: 'warn', + text: 'Refer to `/help emote` for instructions on how to use this command.' + }, socket); + + return false; + } + + input.splice(0, 1); + let actionText = input.join(' '); + + this.run(core, server, socket, { + cmd: 'emote', + text: actionText + }); + + return false; + } + + return payload; +}; + +// module meta +exports.requiredData = ['text']; +exports.info = { + name: 'emote', + description: 'Typical emote / action text', + usage: ` + API: { cmd: 'emote', text: '' } + Text: /me ` +}; diff --git a/server/src/commands/core/help.js b/server/src/commands/core/help.js index 60a7280..51f6d87 100644 --- a/server/src/commands/core/help.js +++ b/server/src/commands/core/help.js @@ -57,7 +57,7 @@ exports.run = async (core, server, socket, payload) => { // module hook functions exports.initHooks = (server) => { - server.registerHook('in', 'chat', this.helpCheck); + server.registerHook('in', 'chat', this.helpCheck, 28); }; // hooks chat commands checking for /whisper @@ -67,7 +67,7 @@ exports.helpCheck = (core, server, socket, payload) => { } if (payload.text.startsWith('/help')) { - let input = payload.text.substr(1, payload.text.length).split(' ', 2); + let input = payload.text.substr(1).split(' ', 2); this.run(core, server, socket, { cmd: input[0], diff --git a/server/src/commands/core/morestats.js b/server/src/commands/core/morestats.js index e8eed05..69740a9 100644 --- a/server/src/commands/core/morestats.js +++ b/server/src/commands/core/morestats.js @@ -58,7 +58,7 @@ exports.run = async (core, server, socket, data) => { // module hook functions exports.initHooks = (server) => { - server.registerHook('in', 'chat', this.statsCheck); + server.registerHook('in', 'chat', this.statsCheck, 26); }; // hooks chat commands checking for /stats diff --git a/server/src/commands/core/whisper.js b/server/src/commands/core/whisper.js index 672db93..c515d43 100644 --- a/server/src/commands/core/whisper.js +++ b/server/src/commands/core/whisper.js @@ -74,7 +74,7 @@ exports.run = async (core, server, socket, payload) => { // module hook functions exports.initHooks = (server) => { - server.registerHook('in', 'chat', this.whisperCheck); + server.registerHook('in', 'chat', this.whisperCheck, 20); }; // hooks chat commands checking for /whisper diff --git a/server/src/commands/internal/legacylayer.js b/server/src/commands/internal/legacylayer.js new file mode 100644 index 0000000..50f5fd7 --- /dev/null +++ b/server/src/commands/internal/legacylayer.js @@ -0,0 +1,20 @@ +/* + Description: This module adjusts outgoing data, making it compatible with legacy clients +*/ + +// module main +exports.run = async (core, server, socket, data) => { + return; +}; + +// module hook functions +exports.initHooks = (server) => { + // module is only a placeholder + //server.registerHook('out', '', this.); +}; + +// module meta +exports.info = { + name: 'legacylayer', + description: 'This module adjusts outgoing data, making it compatible with legacy clients' +}; diff --git a/server/src/commands/mod/dumb.js b/server/src/commands/mod/dumb.js index ecb4e0d..d64c746 100644 --- a/server/src/commands/mod/dumb.js +++ b/server/src/commands/mod/dumb.js @@ -61,8 +61,8 @@ exports.run = async (core, server, socket, data) => { // module hook functions exports.initHooks = (server) => { - server.registerHook('in', 'chat', this.chatCheck); - server.registerHook('in', 'invite', this.inviteCheck); + server.registerHook('in', 'chat', this.chatCheck, 25); + server.registerHook('in', 'invite', this.inviteCheck, 25); // TODO: add whisper hook, need hook priorities todo finished first }; diff --git a/server/src/core/server.js b/server/src/core/server.js index 08ddad7..4132b55 100644 --- a/server/src/core/server.js +++ b/server/src/core/server.js @@ -30,9 +30,7 @@ class server extends wsServer { this._cmdBlacklist = {}; this._cmdKey = internalCmdKey; - this._heartBeat = setInterval(((data) => { - this.beatHeart(); - }).bind(this), pulseSpeed); + this._heartBeat = setInterval(() => this.beatHeart(), pulseSpeed); this.on('error', (err) => { this.handleError('server', err); @@ -42,7 +40,7 @@ class server extends wsServer { this.newConnection(socket, request); }); - this._core.commands.initCommandHooks(this); + this.loadHooks(); } /** @@ -74,17 +72,17 @@ class server extends wsServer { newConnection (socket, request) { socket.remoteAddress = request.headers['x-forwarded-for'] || request.connection.remoteAddress; - socket.on('message', ((data) => { + socket.on('message', (data) => { this.handleData(socket, data); - }).bind(this)); + }); - socket.on('close', (() => { + socket.on('close', () => { this.handleClose(socket); - }).bind(this)); + }); - socket.on('error', ((err) => { + socket.on('error', (err) => { this.handleError(socket, err); - }).bind(this)); + }); } /** @@ -325,6 +323,39 @@ class server extends wsServer { return sha.digest('base64').substr(0, 15); } + /** + * (Re)loads all command module hooks, then sorts their order of operation by + * priority, ascending (0 being highest priority) + * + */ + loadHooks () { + // clear current hooks (if any) + this.clearHooks(); + // notify each module to register their hooks (if any) + this._core.commands.initCommandHooks(this); + + if (typeof this._hooks['in'] !== 'undefined') { + // start sorting, with incoming first + let curHooks = [ ...this._hooks['in'].keys() ]; + let hookObj = []; + for (let i = 0, j = curHooks.length; i < j; i++) { + hookObj = this._hooks['in'].get(curHooks[i]); + hookObj.sort( (h1, h2) => h1.priority - h2.priority ); + this._hooks['in'].set(hookObj); + } + } + + if (typeof this._hooks['out'] !== 'undefined') { + // then outgoing + curHooks = [ ...this._hooks['out'].keys() ]; + for (let i = 0, j = curHooks.length; i < j; i++) { + hookObj = this._hooks['out'].get(curHooks[i]); + hookObj.sort( (h1, h2) => h1.priority - h2.priority ); + this._hooks['out'].set(hookObj); + } + } + } + /** * Adds a target function to an array of hooks. Hooks are executed either before * processing user input (`in`) or before sending data back to the client (`out`) @@ -333,9 +364,13 @@ class server extends wsServer { * @param {String} type The type of event, typically `in` (incoming) or `out` (outgoing) * @param {String} command Should match the desired `cmd` attrib of the payload * @param {Function} hookFunction Target function to execute, should accept `server`, `socket` and `payload` as parameters + * @param {Number} priority Execution priority, hooks with priority 1 will be executed before hooks with priority 200 for example */ - // TODO: add hook priority levels - registerHook (type, command, hookFunction) { + registerHook (type, command, hookFunction, priority) { + if (typeof priority === 'undefined') { + priority = 25; + } + if (typeof this._hooks[type] === 'undefined') { this._hooks[type] = new Map(); } @@ -344,7 +379,10 @@ class server extends wsServer { this._hooks[type].set(command, []); } - this._hooks[type].get(command).push(hookFunction); + this._hooks[type].get(command).push({ + run: hookFunction, + priority: priority + }); } /** @@ -367,14 +405,14 @@ class server extends wsServer { for (let i = 0, j = hooks.length; i < j; i++) { try { - payload = hooks[i](this._core, this, socket, payload); + payload = hooks[i].run(this._core, this, socket, payload); } catch (err) { let errText = `Hook failure, '${type}', '${command}': ${err}`; console.log(errText); return errText; } - // A payload may choose to return false to prevent all further processing + // A hook function may choose to return false to prevent all further processing if (payload === false) { return false; } diff --git a/server/src/managers/config.js b/server/src/managers/config.js index 97961ce..7b49aa8 100644 --- a/server/src/managers/config.js +++ b/server/src/managers/config.js @@ -116,7 +116,6 @@ class ConfigManager { conf = this.load(); // websocketport is the last core config question, wait until it's been populated - // TODO: update this to work with new plugin support while(conf === null || typeof conf.websocketPort === 'undefined') { deSync.sleep(100); } @@ -138,8 +137,8 @@ class ConfigManager { ${chalk.gray('--------------(') + chalk.white(' HackChat Setup Wizard v1.0 ') + chalk.gray(')--------------')} ${chalk.magenta('°º¤ø,¸¸,ø¤º°`°º¤ø,¸,ø¤°º¤ø,¸¸,ø¤º°`°º¤ø,¸°º¤ø,¸¸,ø¤º°`°º¤ø')} - For advanced setup, see the HackChat wiki at: - ${chalk.green('https://github.com/')} + For advanced setup, see the documentation at: + ${chalk.green('https://github.com/hack-chat/main/tree/master/documentation')} ${chalk.white('Note:')} ${chalk.green('npm/yarn run config')} will re-run this utility. -- cgit v1.2.1