From a48830165536fa7181b2e9df211300141661d9d4 Mon Sep 17 00:00:00 2001
From: marzavec <admin@marzavec.com>
Date: Thu, 21 Feb 2019 00:43:25 -0800
Subject: Core hook upgrade, misc fixes

(See ChangeLog.md tbh)
---
 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 +-
 9 files changed, 141 insertions(+), 32 deletions(-)
 create mode 100644 server/src/commands/core/emote.js
 create mode 100644 server/src/commands/internal/legacylayer.js

(limited to 'server/src/commands')

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 to send>' }
     Text: Uuuuhm. Just kind type in that little box at the bottom and hit enter.\n
     Bonus super secret hidden commands:
-    /me <emote>
     /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: '<emote/action text>' }
+    Text: /me <emote/action text>`
+};
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
 };
 
-- 
cgit v1.2.1