From f2ad0e561105ee1899e9c98c9ecd6ca7f1d5f5a4 Mon Sep 17 00:00:00 2001
From: MinusGix <MinusGix@gmail.com>
Date: Fri, 6 Mar 2020 17:12:19 -0600
Subject: Extract invite code into utility functions for greater re-use and
 access

---
 server/src/commands/core/invite.js | 107 ++++++++++++++++++++++++++++---------
 1 file changed, 82 insertions(+), 25 deletions(-)

(limited to 'server/src/commands')

diff --git a/server/src/commands/core/invite.js b/server/src/commands/core/invite.js
index b98115b..00584b3 100644
--- a/server/src/commands/core/invite.js
+++ b/server/src/commands/core/invite.js
@@ -4,6 +4,79 @@
 
 import * as UAC from '../utility/UAC/_info';
 
+// module support functions
+/**
+  * Returns a message for if it's a valid nickname to invite. Returns null if there was no error.
+  * @param {any} nick
+  * @return {(string|null)}
+  */
+export function checkNickname (nick, inviterNick) {
+  if (typeof nick !== 'string' || !UAC.verifyNickname(nick)) {
+    return "Nickname was invalid.";
+  } else if (nick === inviterNick) {
+    return "Why would you invite yourself?";
+  }
+
+  return null;
+}
+
+/**
+  * Returns the channel that should be invited to.
+  * @param {any} channel
+  * @return {string}
+  */
+export function getChannel (channel=undefined) {
+  if (typeof channel === 'string') {
+    return channel;
+  } else {
+    return Math.random().toString(36).substr(2, 8);
+  }
+}
+
+/**
+  * Creates the payload that a user who is being invited would receive.
+  * @param {string} inviter The user who is inviting them.
+  * @param {string} channel The channel they are being invited to.
+  * @return {Object}
+  */
+export function createRecipientPayload (inviter, channel) {
+  return {
+    cmd: 'info',
+    type: 'invite',
+    from: inviter,
+    text: `${inviter} invited you to ?${channel}`,
+  };
+}
+
+/**
+  * Creates the payload that a user who invited users (and succeeded) would receive.
+  * @param {string} nick The user who was invited.
+  * @param {string} channel The channel they were invited to.
+  */
+export function createSuccessPayload (nick, channel) {
+  return {
+    cmd: 'info',
+    type: 'invite',
+    invite: channel,
+    text: `You invited ${nick} to ?${channel}`,
+  };
+}
+
+/**
+  * Sends the invites to the recipients.
+  * @param {MainServer} server The server. Required to broadcast the messages.
+  * @param {string} recipientNick The user who is being invited.
+  * @param {string} inviterNick The user who is doing the inviting.
+  * @param {string} originalChannel The channel they have in common, and where the invite is sent in.
+  * @param {string} inviteChannel The channel they are being invited to.
+  */
+export function sendInvite (server, recipientNick, inviterNick, originalChannel, inviteChannel) {
+  return server.broadcast(createRecipientPayload(inviterNick, inviteChannel), {
+    channel: originalChannel,
+    nick: recipientNick,
+  });
+}
+
 // module main
 export async function run(core, server, socket, data) {
   // check for spam
@@ -15,30 +88,19 @@ export async function run(core, server, socket, data) {
   }
 
   // verify user input
-  if (typeof data.nick !== 'string' || !UAC.verifyNickname(data.nick)) {
-    return true;
-  }
-
-  // why would you invite yourself?
-  if (data.nick === socket.nick) {
+  const nickValid = checkNickname(data.nick, socket.nick);
+  if (nickValid !== null) {
+    server.reply({
+      cmd: 'warn',
+      text: nickValid,
+    }, socket);
     return true;
   }
 
-  let channel;
-  if (typeof data.to === 'string') {
-    channel = data.to;
-  } else {
-    channel = Math.random().toString(36).substr(2, 8);
-  }
+  const channel = getChannel(data.to);
 
   // build and send invite
-  const payload = {
-    cmd: 'info',
-    type: 'invite',
-    from: socket.nick,
-    invite: channel,
-    text: `${socket.nick} invited you to ?${channel}`,
-  };
+  const payload = createRecipientPayload(socket.nick, channel);
 
   const inviteSent = server.broadcast(payload, {
     channel: socket.channel,
@@ -54,12 +116,7 @@ export async function run(core, server, socket, data) {
   }
 
   // reply with common channel
-  server.reply({
-    cmd: 'info',
-    type: 'invite',
-    invite: channel,
-    text: `You invited ${data.nick} to ?${channel}`,
-  }, socket);
+  server.reply(createSuccessPayload(data.nick, channel), socket);
 
   // stats are fun
   core.stats.increment('invites-sent');
-- 
cgit v1.2.1


From 1d01376ba5e395fd81c95d36951604b10d1432c7 Mon Sep 17 00:00:00 2001
From: MinusGix <MinusGix@gmail.com>
Date: Fri, 6 Mar 2020 17:13:03 -0600
Subject: Make dumb use abstracted invite functions rather than duplicating
 code

---
 server/src/commands/mod/dumb.js | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

(limited to 'server/src/commands')

diff --git a/server/src/commands/mod/dumb.js b/server/src/commands/mod/dumb.js
index 488ed9e..51fc745 100644
--- a/server/src/commands/mod/dumb.js
+++ b/server/src/commands/mod/dumb.js
@@ -4,6 +4,7 @@
  */
 
 import * as UAC from '../utility/UAC/_info';
+import * as Invite from '../core/invite';
 
 // module constructor
 export function init(core) {
@@ -117,19 +118,21 @@ export function chatCheck(core, server, socket, payload) {
 
 // shadow-prevent all invites from muzzled users
 export function inviteCheck(core, server, socket, payload) {
-  if (typeof payload.nick !== 'string') {
-    return false;
-  }
-
   if (core.muzzledHashes[socket.hash]) {
+    const nickValid = Invite.checkNickname(payload.nick);
+    if (nickValid !== null) {
+      server.reply({
+        cmd: 'warn',
+        text: nickValid,
+      }, socket);
+      return false;
+    }
+
     // generate common channel
-    const channel = Math.random().toString(36).substr(2, 8);
+    const channel = Invite.getChannel();
 
     // send fake reply
-    server.reply({
-      cmd: 'info',
-      text: `You invited ${payload.nick} to ?${channel}`,
-    }, socket);
+    server.reply(Invite.createSuccessPayload(payload.nick, channel), socket);
 
     return false;
   }
-- 
cgit v1.2.1