Javadoc for src/app complete
This commit is contained in:
parent
ad057916d8
commit
2303c89bcf
|
|
@ -25,7 +25,14 @@ const emoteValidator = require('../../validators/emoteValidator');
|
||||||
const chat = require('./chat');
|
const chat = require('./chat');
|
||||||
const {userModel} = require('../../schemas/user/userSchema');
|
const {userModel} = require('../../schemas/user/userSchema');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class containing global server-side chat relay logic
|
||||||
|
*/
|
||||||
module.exports = class{
|
module.exports = class{
|
||||||
|
/**
|
||||||
|
* Instantiates a chatHandler object
|
||||||
|
* @param {channelManager} server - Parent Server Object
|
||||||
|
*/
|
||||||
constructor(server){
|
constructor(server){
|
||||||
//Set server
|
//Set server
|
||||||
this.server = server;
|
this.server = server;
|
||||||
|
|
@ -35,6 +42,10 @@ module.exports = class{
|
||||||
this.chatBufferSize = 50;
|
this.chatBufferSize = 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines global server-side chat relay event listeners
|
||||||
|
* @param {Socket} socket - Requesting Socket
|
||||||
|
*/
|
||||||
defineListeners(socket){
|
defineListeners(socket){
|
||||||
socket.on("chatMessage", (data) => {this.handleChat(socket, data)});
|
socket.on("chatMessage", (data) => {this.handleChat(socket, data)});
|
||||||
socket.on("setFlair", (data) => {this.setFlair(socket, data)});
|
socket.on("setFlair", (data) => {this.setFlair(socket, data)});
|
||||||
|
|
@ -43,10 +54,20 @@ module.exports = class{
|
||||||
socket.on("deletePersonalEmote", (data) => {this.deletePersonalEmote(socket, data)});
|
socket.on("deletePersonalEmote", (data) => {this.deletePersonalEmote(socket, data)});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles incoming chat messages from client connections
|
||||||
|
* @param {Socket} socket - Socket we're receiving the request from
|
||||||
|
* @param {Object} data - Event payload
|
||||||
|
*/
|
||||||
handleChat(socket, data){
|
handleChat(socket, data){
|
||||||
this.commandPreprocessor.preprocess(socket, data);
|
this.commandPreprocessor.preprocess(socket, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles incoming client request to change flair
|
||||||
|
* @param {Socket} socket - Socket we're receiving the request from
|
||||||
|
* @param {Object} data - Event payload
|
||||||
|
*/
|
||||||
async setFlair(socket, data){
|
async setFlair(socket, data){
|
||||||
var userDB = await userModel.findOne({user: socket.user.user});
|
var userDB = await userModel.findOne({user: socket.user.user});
|
||||||
|
|
||||||
|
|
@ -66,6 +87,11 @@ module.exports = class{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles incoming client request to change high level
|
||||||
|
* @param {Socket} socket - Socket we're receiving the request from
|
||||||
|
* @param {Object} data - Event payload
|
||||||
|
*/
|
||||||
async setHighLevel(socket, data){
|
async setHighLevel(socket, data){
|
||||||
var userDB = await userModel.findOne({user: socket.user.user});
|
var userDB = await userModel.findOne({user: socket.user.user});
|
||||||
|
|
||||||
|
|
@ -89,6 +115,11 @@ module.exports = class{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles incoming client request to add a personal emote
|
||||||
|
* @param {Socket} socket - Socket we're receiving the request from
|
||||||
|
* @param {Object} data - Event payload
|
||||||
|
*/
|
||||||
async addPersonalEmote(socket, data){
|
async addPersonalEmote(socket, data){
|
||||||
//Sanatize and Validate input
|
//Sanatize and Validate input
|
||||||
const name = emoteValidator.manualName(data.name);
|
const name = emoteValidator.manualName(data.name);
|
||||||
|
|
@ -119,6 +150,11 @@ module.exports = class{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles incoming client request to delete a personal emote
|
||||||
|
* @param {Socket} socket - Socket we're receiving the request from
|
||||||
|
* @param {Object} data - Event payload
|
||||||
|
*/
|
||||||
async deletePersonalEmote(socket, data){
|
async deletePersonalEmote(socket, data){
|
||||||
//Get user doc from DB based on socket
|
//Get user doc from DB based on socket
|
||||||
const userDB = await userModel.findOne({user: socket.user.user});
|
const userDB = await userModel.findOne({user: socket.user.user});
|
||||||
|
|
@ -130,10 +166,25 @@ module.exports = class{
|
||||||
}
|
}
|
||||||
|
|
||||||
//Base chat functions
|
//Base chat functions
|
||||||
|
/**
|
||||||
|
* Creates a new chatObject and relays the resulting message to the given channel
|
||||||
|
* @param {String} user - Originating user
|
||||||
|
* @param {String} flair - Flair ID to mark chat with
|
||||||
|
* @param {Number} highLevel - High Level to mark chat with
|
||||||
|
* @param {String} msg - Message Text Content
|
||||||
|
* @param {String} type - Message Type, used for client-side chat post-processing.
|
||||||
|
* @param {String} chan - Channel to broadcast message within
|
||||||
|
* @param {Array} links - Array of URLs/Links to hand to the client-side chat post-processor to inject into the final message.
|
||||||
|
*/
|
||||||
relayChat(user, flair, highLevel, msg, type = 'chat', chan, links){
|
relayChat(user, flair, highLevel, msg, type = 'chat', chan, links){
|
||||||
this.relayChatObject(chan, new chat(user, flair, highLevel, msg, type, links));
|
this.relayChatObject(chan, new chat(user, flair, highLevel, msg, type, links));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relays an existing chat object to a channel
|
||||||
|
* @param {String} chan - Channel to broadcast message within
|
||||||
|
* @param {chat} chat - Chat Object representing the message to broadcast to the given channel
|
||||||
|
*/
|
||||||
relayChatObject(chan, chat){
|
relayChatObject(chan, chat){
|
||||||
//Send out chat
|
//Send out chat
|
||||||
this.server.io.in(chan).emit("chatMessage", chat);
|
this.server.io.in(chan).emit("chatMessage", chat);
|
||||||
|
|
@ -150,46 +201,107 @@ module.exports = class{
|
||||||
channel.chatBuffer.push(chat);
|
channel.chatBuffer.push(chat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new chatObject and relays the resulting message to the given socket
|
||||||
|
* @param {Socket} socket - Socket we're sending a message to (sounds menacing, huh?)
|
||||||
|
* @param {String} user - Originating user
|
||||||
|
* @param {String} flair - Flair ID to mark chat with
|
||||||
|
* @param {Number} highLevel - High Level to mark chat with
|
||||||
|
* @param {String} msg - Message Text Content
|
||||||
|
* @param {String} type - Message Type, used for client-side chat post-processing.
|
||||||
|
* @param {String} chan - Channel to broadcast message within
|
||||||
|
* @param {Array} links - Array of URLs/Links to hand to the client-side chat post-processor to inject into the final message.
|
||||||
|
*/
|
||||||
relayPrivateChat(socket, user, flair, highLevel, msg, type, links){
|
relayPrivateChat(socket, user, flair, highLevel, msg, type, links){
|
||||||
this.relayPrivateChatObject(socket , new chat(user, flair, highLevel, msg, type, links));
|
this.relayPrivateChatObject(socket , new chat(user, flair, highLevel, msg, type, links));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles incoming client request to delete a personal emote
|
||||||
|
* @param {Socket} socket - Socket we're receiving the request from
|
||||||
|
* @param {Object} data - Event payload
|
||||||
|
*/
|
||||||
relayPrivateChatObject(socket, chat){
|
relayPrivateChatObject(socket, chat){
|
||||||
socket.emit("chatMessage", chat);
|
socket.emit("chatMessage", chat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new chatObject and relays the resulting message to the entire server
|
||||||
|
* @param {String} user - Originating user
|
||||||
|
* @param {String} flair - Flair ID to mark chat with
|
||||||
|
* @param {Number} highLevel - High Level to mark chat with
|
||||||
|
* @param {String} msg - Message Text Content
|
||||||
|
* @param {String} type - Message Type, used for client-side chat post-processing.
|
||||||
|
* @param {Array} links - Array of URLs/Links to hand to the client-side chat post-processor to inject into the final message.
|
||||||
|
*/
|
||||||
relayGlobalChat(user, flair, highLevel, msg, type = 'chat', links){
|
relayGlobalChat(user, flair, highLevel, msg, type = 'chat', links){
|
||||||
this.relayGlobalChatObject(new chat(user, flair, highLevel, msg, type, links));
|
this.relayGlobalChatObject(new chat(user, flair, highLevel, msg, type, links));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relays an existing chat object to the entire server
|
||||||
|
* @param {chat} chat - Chat Object representing the message to broadcast throughout the server
|
||||||
|
*/
|
||||||
relayGlobalChatObject(chat){
|
relayGlobalChatObject(chat){
|
||||||
this.server.io.emit("chatMessage", chat);
|
this.server.io.emit("chatMessage", chat);
|
||||||
}
|
}
|
||||||
|
|
||||||
//User Chat Functions
|
//User Chat Functions
|
||||||
|
/**
|
||||||
|
* Relays a chat message from a user to the rest of the channel based on socket
|
||||||
|
* @param {Socket} socket - Socket we're receiving the request from
|
||||||
|
* @param {String} msg - Message Text Content
|
||||||
|
* @param {String} type - Message Type, used for client-side chat post-processing.
|
||||||
|
* @param {Array} links - Array of URLs/Links to hand to the client-side chat post-processor to inject into the final message.
|
||||||
|
*/
|
||||||
relayUserChat(socket, msg, type, links){
|
relayUserChat(socket, msg, type, links){
|
||||||
const user = this.server.getSocketInfo(socket);
|
const user = this.server.getSocketInfo(socket);
|
||||||
this.relayChat(user.user, user.flair, user.highLevel, msg, type, socket.chan, links);
|
this.relayChat(user.user, user.flair, user.highLevel, msg, type, socket.chan, links);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Toke Chat Functions
|
//Toke Chat Functions
|
||||||
|
/**
|
||||||
|
* Broadcasts toke callout to the server
|
||||||
|
* @param {String} msg - Message Text Content
|
||||||
|
* @param {Array} links - Array of URLs/Links to hand to the client-side chat post-processor to inject into the final message.
|
||||||
|
*/
|
||||||
relayTokeCallout(msg, links){
|
relayTokeCallout(msg, links){
|
||||||
this.relayGlobalChat("Tokebot", "", '∞', msg, "toke", links);
|
this.relayGlobalChat("Tokebot", "", '∞', msg, "toke", links);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Broadcasts toke callout to the server
|
||||||
|
* @param {Socket} socket - Socket we're sending the whisper to
|
||||||
|
* @param {String} msg - Message Text Content
|
||||||
|
* @param {Array} links - Array of URLs/Links to hand to the client-side chat post-processor to inject into the final message.
|
||||||
|
*/
|
||||||
relayTokeWhisper(socket, msg, links){
|
relayTokeWhisper(socket, msg, links){
|
||||||
this.relayPrivateChat(socket, "Tokebot", "", '∞', msg, "tokewhisper", links);
|
this.relayPrivateChat(socket, "Tokebot", "", '∞', msg, "tokewhisper", links);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Broadcasts toke whisper to the server
|
||||||
|
* @param {String} msg - Message Text Content
|
||||||
|
* @param {Array} links - Array of URLs/Links to hand to the client-side chat post-processor to inject into the final message.
|
||||||
|
*/
|
||||||
relayGlobalTokeWhisper(msg, links){
|
relayGlobalTokeWhisper(msg, links){
|
||||||
this.relayGlobalChat("Tokebot", "", '∞', msg, "tokewhisper", links);
|
this.relayGlobalChat("Tokebot", "", '∞', msg, "tokewhisper", links);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Announcement Functions
|
//Announcement Functions
|
||||||
|
/**
|
||||||
|
* Broadcasts announcement to the server
|
||||||
|
* @param {String} msg - Message Text Content
|
||||||
|
* @param {Array} links - Array of URLs/Links to hand to the client-side chat post-processor to inject into the final message.
|
||||||
|
*/
|
||||||
relayServerAnnouncement(msg, links){
|
relayServerAnnouncement(msg, links){
|
||||||
this.relayGlobalChat("Server", "", '∞', msg, "announcement", links);
|
this.relayGlobalChat("Server", "", '∞', msg, "announcement", links);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Broadcasts announcement to a given channel
|
||||||
|
* @param {String} msg - Message Text Content
|
||||||
|
* @param {Array} links - Array of URLs/Links to hand to the client-side chat post-processor to inject into the final message.
|
||||||
|
*/
|
||||||
relayChannelAnnouncement(chan, msg, links){
|
relayChannelAnnouncement(chan, msg, links){
|
||||||
const activeChan = this.server.activeChannels.get(chan);
|
const activeChan = this.server.activeChannels.get(chan);
|
||||||
|
|
||||||
|
|
@ -200,6 +312,11 @@ module.exports = class{
|
||||||
}
|
}
|
||||||
|
|
||||||
//Misc Functions
|
//Misc Functions
|
||||||
|
/**
|
||||||
|
* Clears chat for a given channel, targets specified user or entire channel if none found/specified.
|
||||||
|
* @param {String} user - User chats to clear
|
||||||
|
* @param {String} chan - Channel to broadcast message within
|
||||||
|
*/
|
||||||
clearChat(chan, user){
|
clearChat(chan, user){
|
||||||
const activeChan = this.server.activeChannels.get(chan);
|
const activeChan = this.server.activeChannels.get(chan);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,15 @@ const linkUtils = require('../../utils/linkUtils');
|
||||||
const permissionModel = require('../../schemas/permissionSchema');
|
const permissionModel = require('../../schemas/permissionSchema');
|
||||||
const channelModel = require('../../schemas/channel/channelSchema');
|
const channelModel = require('../../schemas/channel/channelSchema');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class containing global server-side chat/command pre-processing logic
|
||||||
|
*/
|
||||||
module.exports = class commandPreprocessor{
|
module.exports = class commandPreprocessor{
|
||||||
|
/**
|
||||||
|
* Instantiates a commandPreprocessor object
|
||||||
|
* @param {channelManager} server - Parent Server Object
|
||||||
|
* @param {chatHandler} chatHandler - Parent Chat Handler Object
|
||||||
|
*/
|
||||||
constructor(server, chatHandler){
|
constructor(server, chatHandler){
|
||||||
this.server = server;
|
this.server = server;
|
||||||
this.chatHandler = chatHandler;
|
this.chatHandler = chatHandler;
|
||||||
|
|
@ -31,6 +39,11 @@ module.exports = class commandPreprocessor{
|
||||||
this.tokebot = new tokebot(server, chatHandler);
|
this.tokebot = new tokebot(server, chatHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ingests a command/chat request from Chat Handler and pre-processes and processes it accordingly
|
||||||
|
* @param {Socket} socket - Socket we're receiving the request from
|
||||||
|
* @param {Object} data - Event payload
|
||||||
|
*/
|
||||||
async preprocess(socket, data){
|
async preprocess(socket, data){
|
||||||
//Set command object
|
//Set command object
|
||||||
const commandObj = {
|
const commandObj = {
|
||||||
|
|
@ -61,6 +74,11 @@ module.exports = class commandPreprocessor{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanatizes and Validates a single user chat message/command
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
* @returns {Boolean} false if Command/Message is too long to send
|
||||||
|
*/
|
||||||
sanatizeCommand(commandObj){
|
sanatizeCommand(commandObj){
|
||||||
//Trim and Sanatize for XSS
|
//Trim and Sanatize for XSS
|
||||||
commandObj.command = validator.trim(validator.escape(commandObj.rawData.msg));
|
commandObj.command = validator.trim(validator.escape(commandObj.rawData.msg));
|
||||||
|
|
@ -69,17 +87,27 @@ module.exports = class commandPreprocessor{
|
||||||
return (validator.isLength(commandObj.rawData.msg, {min: 1, max: 255}));
|
return (validator.isLength(commandObj.rawData.msg, {min: 1, max: 255}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits raw chat/command data into seperate arrays, one by word-borders and words surrounded by word-borders
|
||||||
|
* These arrays are used to handle further command/chat processing
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
*/
|
||||||
splitCommand(commandObj){
|
splitCommand(commandObj){
|
||||||
//Split string by words
|
//Split string by words
|
||||||
commandObj.commandArray = commandObj.command.split(/\b/g);//Split by word-borders
|
commandObj.commandArray = commandObj.command.split(/\b/g);//Split by word-borders
|
||||||
commandObj.argumentArray = commandObj.command.match(/\b\w+\b/g);//Match by words surrounded by borders
|
commandObj.argumentArray = commandObj.command.match(/\b\w+\b/g);//Match by words surrounded by borders
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the server's Command Processor object to process the chat/command request.
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
*/
|
||||||
async processServerCommand(commandObj){
|
async processServerCommand(commandObj){
|
||||||
//If the raw message starts with '!' (skip commands that start with whitespace so people can send example commands in chat)
|
//If the raw message starts with '!' (skip commands that start with whitespace so people can send example commands in chat)
|
||||||
if(commandObj.rawData.msg[0] == '!'){
|
if(commandObj.rawData.msg[0] == '!'){
|
||||||
//if it isn't just an exclimation point, and we have a real command
|
//if it isn't just an exclimation point, and we have a real command
|
||||||
if(commandObj.argumentArray != null){
|
if(commandObj.argumentArray != null){
|
||||||
|
//If the command processor knows what to do with whatever the fuck the user sent us
|
||||||
if(this.commandProcessor[commandObj.argumentArray[0].toLowerCase()] != null){
|
if(this.commandProcessor[commandObj.argumentArray[0].toLowerCase()] != null){
|
||||||
//Process the command and use the return value to set the sendflag (true if command valid)
|
//Process the command and use the return value to set the sendflag (true if command valid)
|
||||||
commandObj.sendFlag = await this.commandProcessor[commandObj.argumentArray[0].toLowerCase()](commandObj, this);
|
commandObj.sendFlag = await this.commandProcessor[commandObj.argumentArray[0].toLowerCase()](commandObj, this);
|
||||||
|
|
@ -91,6 +119,10 @@ module.exports = class commandPreprocessor{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates through links in message and marks them by link type for later use by client-side post-processing
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
*/
|
||||||
async markLinks(commandObj){
|
async markLinks(commandObj){
|
||||||
//Setup the links array
|
//Setup the links array
|
||||||
commandObj.links = [];
|
commandObj.links = [];
|
||||||
|
|
@ -103,6 +135,10 @@ module.exports = class commandPreprocessor{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-creates message string from processed Command Array
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
*/
|
||||||
async prepMessage(commandObj){
|
async prepMessage(commandObj){
|
||||||
//Create message from commandArray
|
//Create message from commandArray
|
||||||
commandObj.message = commandObj.commandArray.join('').trimStart();
|
commandObj.message = commandObj.commandArray.join('').trimStart();
|
||||||
|
|
@ -110,19 +146,36 @@ module.exports = class commandPreprocessor{
|
||||||
await this.markLinks(commandObj);
|
await this.markLinks(commandObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relays chat to channel via parent Chat Handler object
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
*/
|
||||||
sendChat(commandObj){
|
sendChat(commandObj){
|
||||||
//FUCKIN' SEND IT!
|
//FUCKIN' SEND IT!
|
||||||
this.chatHandler.relayUserChat(commandObj.socket, commandObj.message, commandObj.chatType, commandObj.links);
|
this.chatHandler.relayUserChat(commandObj.socket, commandObj.message, commandObj.chatType, commandObj.links);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class representing global server-side chat/command processing logic
|
||||||
|
*/
|
||||||
class commandProcessor{
|
class commandProcessor{
|
||||||
|
/**
|
||||||
|
* Instantiates a commandProcessor object
|
||||||
|
* @param {channelManager} server - Parent Server Object
|
||||||
|
* @param {chatHandler} chatHandler - Parent Chat Handler Object
|
||||||
|
*/
|
||||||
constructor(server, chatHandler){
|
constructor(server, chatHandler){
|
||||||
this.server = server;
|
this.server = server;
|
||||||
this.chatHandler = chatHandler;
|
this.chatHandler = chatHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Command keywords get run through .toLowerCase(), so we should use lowercase method names for command methods
|
//Command keywords get run through .toLowerCase(), so we should use lowercase method names for command methods
|
||||||
|
/**
|
||||||
|
* Command Processor method to handle the '!whisper' command
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
* @returns {Boolean} True to enable send flag
|
||||||
|
*/
|
||||||
whisper(commandObj){
|
whisper(commandObj){
|
||||||
//splice out our command
|
//splice out our command
|
||||||
commandObj.commandArray.splice(0,2);
|
commandObj.commandArray.splice(0,2);
|
||||||
|
|
@ -134,6 +187,11 @@ class commandProcessor{
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command Processor method to handle the '!spoiler' command
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
* @returns {Boolean} True to enable send flag
|
||||||
|
*/
|
||||||
spoiler(commandObj){
|
spoiler(commandObj){
|
||||||
//splice out our command
|
//splice out our command
|
||||||
commandObj.commandArray.splice(0,2);
|
commandObj.commandArray.splice(0,2);
|
||||||
|
|
@ -145,6 +203,11 @@ class commandProcessor{
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command Processor method to handle the '!strikethrough' command
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
* @returns {Boolean} True to enable send flag
|
||||||
|
*/
|
||||||
strikethrough(commandObj){
|
strikethrough(commandObj){
|
||||||
//splice out our command
|
//splice out our command
|
||||||
commandObj.commandArray.splice(0,2);
|
commandObj.commandArray.splice(0,2);
|
||||||
|
|
@ -156,6 +219,11 @@ class commandProcessor{
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command Processor method to handle the '!bold' command
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
* @returns {Boolean} True to enable send flag
|
||||||
|
*/
|
||||||
bold(commandObj){
|
bold(commandObj){
|
||||||
//splice out our command
|
//splice out our command
|
||||||
commandObj.commandArray.splice(0,2);
|
commandObj.commandArray.splice(0,2);
|
||||||
|
|
@ -167,6 +235,11 @@ class commandProcessor{
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command Processor method to handle the '!italics' command
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
* @returns {Boolean} True to enable send flag
|
||||||
|
*/
|
||||||
italics(commandObj){
|
italics(commandObj){
|
||||||
//splice out our command
|
//splice out our command
|
||||||
commandObj.commandArray.splice(0,2);
|
commandObj.commandArray.splice(0,2);
|
||||||
|
|
@ -178,6 +251,11 @@ class commandProcessor{
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command Processor method to handle the '!announce' command
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
* @returns {Boolean} True to enable send flag on un-authorized call to shame the user
|
||||||
|
*/
|
||||||
async announce(commandObj, preprocessor){
|
async announce(commandObj, preprocessor){
|
||||||
//Get the current channel from the database
|
//Get the current channel from the database
|
||||||
const chanDB = await channelModel.findOne({name: commandObj.socket.chan});
|
const chanDB = await channelModel.findOne({name: commandObj.socket.chan});
|
||||||
|
|
@ -201,6 +279,11 @@ class commandProcessor{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command Processor method to handle the '!serverannounce' command
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
* @returns {Boolean} True to enable send flag on un-authorized call to shame the user
|
||||||
|
*/
|
||||||
async serverannounce(commandObj, preprocessor){
|
async serverannounce(commandObj, preprocessor){
|
||||||
//Check if the user has permission, and publicly shame them if they don't (lmao)
|
//Check if the user has permission, and publicly shame them if they don't (lmao)
|
||||||
if(await permissionModel.permCheck(commandObj.socket.user, 'announce')){
|
if(await permissionModel.permCheck(commandObj.socket.user, 'announce')){
|
||||||
|
|
@ -221,6 +304,11 @@ class commandProcessor{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command Processor method to handle the '!resettoke' command
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
* @returns {Boolean} True to enable send flag on un-authorized call to shame the user
|
||||||
|
*/
|
||||||
async resettoke(commandObj, preprocessor){
|
async resettoke(commandObj, preprocessor){
|
||||||
//Check if the user has permission, and publicly shame them if they don't (lmao)
|
//Check if the user has permission, and publicly shame them if they don't (lmao)
|
||||||
if(await permissionModel.permCheck(commandObj.socket.user, 'resetToke')){
|
if(await permissionModel.permCheck(commandObj.socket.user, 'resetToke')){
|
||||||
|
|
@ -238,6 +326,11 @@ class commandProcessor{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command Processor method to handle the '!clear' command
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
* @returns {Boolean} True to enable send flag on un-authorized call to shame the user
|
||||||
|
*/
|
||||||
async clear(commandObj){
|
async clear(commandObj){
|
||||||
//Get the current channel from the database
|
//Get the current channel from the database
|
||||||
const chanDB = await channelModel.findOne({name: commandObj.socket.chan});
|
const chanDB = await channelModel.findOne({name: commandObj.socket.chan});
|
||||||
|
|
@ -254,6 +347,11 @@ class commandProcessor{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command Processor method to handle the '!kick' command
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request
|
||||||
|
* @returns {Boolean} True to enable send flag on un-authorized call to shame the user
|
||||||
|
*/
|
||||||
async kick(commandObj){
|
async kick(commandObj){
|
||||||
//Get the current channel from the database
|
//Get the current channel from the database
|
||||||
const chanDB = await channelModel.findOne({name: commandObj.socket.chan});
|
const chanDB = await channelModel.findOne({name: commandObj.socket.chan});
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,17 @@ const flairModel = require('../../schemas/flairSchema');
|
||||||
const emoteModel = require('../../schemas/emoteSchema');
|
const emoteModel = require('../../schemas/emoteSchema');
|
||||||
const { userModel } = require('../../schemas/user/userSchema');
|
const { userModel } = require('../../schemas/user/userSchema');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class representing a single user connected to a channel
|
||||||
|
*/
|
||||||
module.exports = class{
|
module.exports = class{
|
||||||
|
/**
|
||||||
|
* Instantiates a connectedUser object
|
||||||
|
* @param {Mongoose.Document} userDB - User document to re-hydrate user from
|
||||||
|
* @param {PemissionModel.chanRank} chanRank - Enum representing user channel rank
|
||||||
|
* @param {String} - Channel the user is connecting to
|
||||||
|
* @param {Socket} socket - Socket associated with the users connection
|
||||||
|
*/
|
||||||
constructor(userDB, chanRank, channel, socket){
|
constructor(userDB, chanRank, channel, socket){
|
||||||
this.id = userDB.id;
|
this.id = userDB.id;
|
||||||
this.user = userDB.user;
|
this.user = userDB.user;
|
||||||
|
|
@ -44,6 +54,12 @@ module.exports = class{
|
||||||
this.sockets = [socket.id];
|
this.sockets = [socket.id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles server-side initialization for new connections from a specific user
|
||||||
|
* @param {Mongoose.Document} userDB - User Document Passthrough to save on DB Access
|
||||||
|
* @param {Mongoose.Document} chanDB - Channnel Document Passthrough to save on DB Access
|
||||||
|
* @param {Socket} socket - Requesting Socket
|
||||||
|
*/
|
||||||
async handleConnection(userDB, chanDB, socket){
|
async handleConnection(userDB, chanDB, socket){
|
||||||
//send metadata to client
|
//send metadata to client
|
||||||
this.sendClientMetadata();
|
this.sendClientMetadata();
|
||||||
|
|
@ -69,6 +85,10 @@ module.exports = class{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates through all known connections for a given user, running them through a supplied callback function
|
||||||
|
* @param {Function} cb - Callback to call against found sockets for a given user
|
||||||
|
*/
|
||||||
socketCrawl(cb){
|
socketCrawl(cb){
|
||||||
//Crawl through user's sockets (lol)
|
//Crawl through user's sockets (lol)
|
||||||
this.sockets.forEach((sockid) => {
|
this.sockets.forEach((sockid) => {
|
||||||
|
|
@ -79,22 +99,33 @@ module.exports = class{
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//My brain keeps going back to using dynamic per-user namespaces for this
|
|
||||||
//but everytime i look into it I come to the conclusion that it's a bad idea, then I toy with making chans namespaces
|
/**
|
||||||
//and using per-user channels for this, but what of gold or mod-only features? or games?
|
* Emits an event to all known sockets for a given user
|
||||||
//No matter what it'd probably end up hacky, as namespaces where meant for splitting app logic not user comms (like rooms).
|
*
|
||||||
//at the end of the day there has to be some penance for decent multi-session handling on-top of a library that doesn't do it.
|
* My brain keeps going back to using dynamic per-user namespaces for this
|
||||||
//Having to crawl through these sockets is that. Because the other ways seem more gross somehow.
|
* but everytime i look into it I come to the conclusion that it's a bad idea, then I toy with making chans namespaces
|
||||||
emit(eventName, args){
|
* and using per-user channels for this, but what of gold or mod-only features? or games?
|
||||||
|
* No matter what it'd probably end up hacky, as namespaces where meant for splitting app logic not user comms (like rooms).
|
||||||
|
* at the end of the day there has to be some penance for decent multi-session handling on-top of a library that doesn't do it.
|
||||||
|
* Having to crawl through these sockets is that. Because the other ways seem more gross somehow.
|
||||||
|
* @param {String} eventName - Event name to emit to client sockets
|
||||||
|
* @param {Object} data - Data to emit to client sockets
|
||||||
|
*/
|
||||||
|
emit(eventName, data){
|
||||||
this.socketCrawl((socket)=>{
|
this.socketCrawl((socket)=>{
|
||||||
//Ensure our socket is initialized
|
//Ensure our socket is initialized
|
||||||
if(socket != null){
|
if(socket != null){
|
||||||
socket.emit(eventName, args);
|
socket.emit(eventName, data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//generic disconnect function, defaults to kick
|
/**
|
||||||
|
* Disconnects all sockets for a given user
|
||||||
|
* @param {String} reason - Reason for being disconnected
|
||||||
|
* @param {String} type - Disconnection Type
|
||||||
|
*/
|
||||||
disconnect(reason, type = "Disconnected"){
|
disconnect(reason, type = "Disconnected"){
|
||||||
this.emit("kick",{type, reason});
|
this.emit("kick",{type, reason});
|
||||||
this.socketCrawl((socket)=>{socket.disconnect()});
|
this.socketCrawl((socket)=>{socket.disconnect()});
|
||||||
|
|
@ -102,6 +133,11 @@ module.exports = class{
|
||||||
|
|
||||||
//This is the big first push upon connection
|
//This is the big first push upon connection
|
||||||
//It should only fire once, so things that only need to be sent once can be slapped into here
|
//It should only fire once, so things that only need to be sent once can be slapped into here
|
||||||
|
/**
|
||||||
|
* Sends glut of required initial metadata to the client upon a new connection
|
||||||
|
* @param {Mongoose.Document} userDB - User Document Passthrough to save on DB Access
|
||||||
|
* @param {Mongoose.Document} chanDB - Channnel Document Passthrough to save on DB Access
|
||||||
|
*/
|
||||||
async sendClientMetadata(userDB, chanDB){
|
async sendClientMetadata(userDB, chanDB){
|
||||||
//Get flairList from DB and setup flairList array
|
//Get flairList from DB and setup flairList array
|
||||||
const flairListDB = await flairModel.find({});
|
const flairListDB = await flairModel.find({});
|
||||||
|
|
@ -166,6 +202,9 @@ module.exports = class{
|
||||||
this.emit("clientMetadata", {user: userObj, flairList, queue, queueLock, chatBuffer});
|
this.emit("clientMetadata", {user: userObj, flairList, queue, queueLock, chatBuffer});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send copy of site emotes to the user
|
||||||
|
*/
|
||||||
async sendSiteEmotes(){
|
async sendSiteEmotes(){
|
||||||
//Get emote list from DB
|
//Get emote list from DB
|
||||||
const emoteList = await emoteModel.getEmotes();
|
const emoteList = await emoteModel.getEmotes();
|
||||||
|
|
@ -174,6 +213,10 @@ module.exports = class{
|
||||||
this.emit('siteEmotes', emoteList);
|
this.emit('siteEmotes', emoteList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send copy of channel emotes to the user
|
||||||
|
* @param {Mongoose.Document} chanDB - Channnel Document Passthrough to save on DB Access
|
||||||
|
*/
|
||||||
async sendChanEmotes(chanDB){
|
async sendChanEmotes(chanDB){
|
||||||
//if we wherent handed a channel document
|
//if we wherent handed a channel document
|
||||||
if(chanDB == null){
|
if(chanDB == null){
|
||||||
|
|
@ -188,6 +231,10 @@ module.exports = class{
|
||||||
this.emit('chanEmotes', emoteList);
|
this.emit('chanEmotes', emoteList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send copy of channel emotes to the user
|
||||||
|
* @param {Mongoose.Document} userDB - User Document Passthrough to save on DB Access
|
||||||
|
*/
|
||||||
async sendPersonalEmotes(userDB){
|
async sendPersonalEmotes(userDB){
|
||||||
//if we wherent handed a user document
|
//if we wherent handed a user document
|
||||||
if(userDB == null){
|
if(userDB == null){
|
||||||
|
|
@ -202,6 +249,10 @@ module.exports = class{
|
||||||
this.emit('personalEmotes', emoteList);
|
this.emit('personalEmotes', emoteList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send copy of channel emotes to the user
|
||||||
|
* @param {Mongoose.Document} userDB - User Document Passthrough to save on DB Access
|
||||||
|
*/
|
||||||
async sendUsedTokes(userDB){
|
async sendUsedTokes(userDB){
|
||||||
//if we wherent handed a user document
|
//if we wherent handed a user document
|
||||||
if(userDB == null){
|
if(userDB == null){
|
||||||
|
|
@ -215,6 +266,10 @@ module.exports = class{
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set flair for a given user and broadcast update to clients
|
||||||
|
* @param {String} flair - Flair string to update user's flair to
|
||||||
|
*/
|
||||||
updateFlair(flair){
|
updateFlair(flair){
|
||||||
this.flair = flair;
|
this.flair = flair;
|
||||||
|
|
||||||
|
|
@ -222,6 +277,10 @@ module.exports = class{
|
||||||
this.sendClientMetadata();
|
this.sendClientMetadata();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set high level for a given user and broadcast update to clients
|
||||||
|
* @param {Number} highLevel - Number to update user's high-level to
|
||||||
|
*/
|
||||||
updateHighLevel(highLevel){
|
updateHighLevel(highLevel){
|
||||||
this.highLevel = highLevel;
|
this.highLevel = highLevel;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
//Local Imports
|
//Local Imports
|
||||||
const tokeCommandModel = require('../../schemas/tokebot/tokeCommandSchema');
|
const tokeCommandModel = require('../../schemas/tokebot/tokeCommandSchema');
|
||||||
const {userModel} = require('../../schemas/user/userSchema');
|
const {userModel} = require('../../schemas/user/userSchema');
|
||||||
const statModel = require('../../schemas/statSchema');
|
|
||||||
const statSchema = require('../../schemas/statSchema');
|
const statSchema = require('../../schemas/statSchema');
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class containing global server-side tokebot logic
|
||||||
|
*/
|
||||||
module.exports = class tokebot{
|
module.exports = class tokebot{
|
||||||
|
/**
|
||||||
|
* Instantiates a tokebot object
|
||||||
|
* @param {channelManager} server - Parent Server Object
|
||||||
|
* @param {chatHandler} chatHandler - Parent Chat Handler Object
|
||||||
|
*/
|
||||||
constructor(server, chatHandler){
|
constructor(server, chatHandler){
|
||||||
//Set parents
|
//Set parents
|
||||||
this.server = server;
|
this.server = server;
|
||||||
|
|
@ -46,11 +53,19 @@ module.exports = class tokebot{
|
||||||
this.refreshCommands();
|
this.refreshCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads toke commands from DB into RAM-based toke command store
|
||||||
|
*/
|
||||||
async refreshCommands(){
|
async refreshCommands(){
|
||||||
//Pull Command Strings from DB
|
//Pull Command Strings from DB
|
||||||
this.tokeCommands = await tokeCommandModel.getCommandStrings();
|
this.tokeCommands = await tokeCommandModel.getCommandStrings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes toke commands from Command Pre-Processor
|
||||||
|
* @param {Object} commandObj - Object representing a single given command/chat request, passed down from the Command Pre-Processor
|
||||||
|
* @returns {Boolean} True if the toke is an invalid toke command (tells Command Pre-Processor to send command as chat)
|
||||||
|
*/
|
||||||
tokeProcessor(commandObj){
|
tokeProcessor(commandObj){
|
||||||
//Check for site-wide toke commands
|
//Check for site-wide toke commands
|
||||||
if(this.tokeCommands.indexOf(commandObj.argumentArray[0].toLowerCase()) != -1){
|
if(this.tokeCommands.indexOf(commandObj.argumentArray[0].toLowerCase()) != -1){
|
||||||
|
|
@ -127,6 +142,9 @@ module.exports = class tokebot{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called each second during the toke. Handles decrementing the timer variable, and countdown end logic.
|
||||||
|
*/
|
||||||
countdown(){
|
countdown(){
|
||||||
//If we're in the last three seconds
|
//If we're in the last three seconds
|
||||||
if(this.tokeCounter <= 3 && this.tokeCounter > 0){
|
if(this.tokeCounter <= 3 && this.tokeCounter > 0){
|
||||||
|
|
@ -169,6 +187,10 @@ module.exports = class tokebot{
|
||||||
this.tokeTimer = setTimeout(this.countdown.bind(this), 1000)
|
this.tokeTimer = setTimeout(this.countdown.bind(this), 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method seems to be a vestage from a bygone era. We should remove it after documenting shit.
|
||||||
|
* I would now, but I don't want to break shit in a comment-only commit.
|
||||||
|
*/
|
||||||
async asyncFinisher(){
|
async asyncFinisher(){
|
||||||
//Grab a copy of the tokers map before it gets cleared out
|
//Grab a copy of the tokers map before it gets cleared out
|
||||||
const tokers = this.tokers;
|
const tokers = this.tokers;
|
||||||
|
|
@ -177,6 +199,9 @@ module.exports = class tokebot{
|
||||||
await userModel.tattooToke(tokers);
|
await userModel.tattooToke(tokers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs every second for 60 seconds after a toke
|
||||||
|
*/
|
||||||
cooldown(){
|
cooldown(){
|
||||||
//If the cooldown timer isn't over
|
//If the cooldown timer isn't over
|
||||||
if(this.cooldownCounter > 0){
|
if(this.cooldownCounter > 0){
|
||||||
|
|
@ -191,6 +216,9 @@ module.exports = class tokebot{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets toke cooldowns early upon authorized request
|
||||||
|
*/
|
||||||
resetToke(){
|
resetToke(){
|
||||||
//Set cooldown to 0
|
//Set cooldown to 0
|
||||||
this.cooldownCounter = 0;
|
this.cooldownCounter = 0;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue