add !whisper command for tiny chats

This commit is contained in:
rainbow napkin 2024-12-08 13:05:09 -05:00
parent 4c1f0f10a7
commit 0182c6927e
6 changed files with 92 additions and 37 deletions

View file

@ -14,9 +14,6 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.*/ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
//NPM Imports
const validator = require('validator');//No express here, so regular validator it is!
//local imports //local imports
const commandPreprocessor = require('./commandPreprocessor'); const commandPreprocessor = require('./commandPreprocessor');
const loggerUtils = require('../../utils/loggerUtils'); const loggerUtils = require('../../utils/loggerUtils');
@ -38,19 +35,6 @@ module.exports = class{
this.commandPreprocessor.preprocess(socket, data); this.commandPreprocessor.preprocess(socket, data);
} }
relayChat(socket, data){
//Trim and Sanatize for XSS
const msg = validator.trim(validator.escape(data));
const user = this.server.getSocketInfo(socket);
//nuke the message if its empty or huge
if(!validator.isLength(msg, {min: 1, max: 255})){
return;
}
this.server.io.in(socket.chan).emit("chatMessage", {user: user.user, flair: user.flair, highLevel: user.highLevel, msg});
}
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});
@ -94,4 +78,9 @@ module.exports = class{
} }
} }
} }
relayChat(socket, msg, type = 'chat'){
const user = this.server.getSocketInfo(socket);
this.server.io.in(socket.chan).emit("chatMessage", {user: user.user, flair: user.flair, highLevel: user.highLevel, msg, type});
}
} }

View file

@ -1,48 +1,100 @@
/*Canopy - The next generation of stoner streaming software
Copyright (C) 2024 Rainbownapkin and the TTN Community
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
//NPM Imports
const validator = require('validator');//No express here, so regular validator it is!
module.exports = class commandPreprocessor{ module.exports = class commandPreprocessor{
constructor(server){ constructor(server){
this.server = server; this.server = server;
this.commandProcessor = new commandProcessor(server); this.commandProcessor = new commandProcessor(server, this);
} }
preprocess(socket, data){ preprocess(socket, data){
//Set command, socket and sendFlag //Set socket, data, and sendFlag
this.command = data.msg;
this.socket = socket; this.socket = socket;
this.sendFlag = true; this.sendFlag = true;
this.rawData = data;
this.splitBody(); //If we don't pass sanatization/validation turn this car around
if(!this.sanatizeCommand()){
return;
}
//split the command
this.splitCommand();
//Process the command
this.processServerCommand(); this.processServerCommand();
//Send it as chat (assuming the flag isn't false)
this.sendChat(); this.sendChat();
} }
splitBody(){ sanatizeCommand(){
//Trim and Sanatize for XSS
this.command = validator.trim(validator.escape(this.rawData.msg));
//nuke the message if its empty or huge
if(!validator.isLength(this.command, {min: 1, max: 255})){
return false;
}
//return true to tell preprocess to continue on
return true;
}
splitCommand(){
//Split string by words //Split string by words
this.commandArray = this.command.split(/\b/g);//Split by word-borders this.commandArray = this.command.split(/\b/g);//Split by word-borders
this.argumentArray = this.command.match(/\b\w+\b/g);//Match by words surrounded by borders this.argumentArray = this.command.match(/\b\w+\b/g);//Match by words surrounded by borders
} }
processServerCommand(){ processServerCommand(){
//If the first word is '!'
if(this.commandArray[0] == '!'){ if(this.commandArray[0] == '!'){
//if it isn't just an exclimation point, and we have a real command
if(this.argumentArray != null && this.commandProcessor[this.argumentArray[0]] != null){ if(this.argumentArray != null && this.commandProcessor[this.argumentArray[0]] != null){
//disable chat
this.sendFlag = false; this.sendFlag = false;
this.commandProcessor[this.argumentArray[0]](this.socket, this.argumentArray); //Process the command
this.commandProcessor[this.argumentArray[0]]();
} }
} }
} }
sendChat(){ sendChat(){
//If the send flag is true
if(this.sendFlag){ if(this.sendFlag){
this.server.chatHandler.relayChat(this.socket, this.commandArray.join('')); //FUCKIN' SEND IT!
this.server.chatHandler.relayChat(this.socket, this.commandArray.join('').trimStart());
} }
} }
} }
class commandProcessor{ class commandProcessor{
constructor(server){ constructor(server, preprocessor){
this.server = server; this.server = server;
this.preprocessor = preprocessor
} }
whisper(socket, argumentArray){ whisper(){
console.log(argumentArray); //Ensure we don't double dip
this.sendFlag = false;
//splice out our whisper
this.preprocessor.commandArray.splice(0,2);
//send it
this.server.chatHandler.relayChat(this.preprocessor.socket, this.preprocessor.commandArray.join(''), 'whisper');
} }
} }

View file

@ -190,6 +190,10 @@ span.user-entry{
width: fit-content; width: fit-content;
} }
.whisper{
font-size: 0.7em;
}
#media-panel-aspect-lock-icon{ #media-panel-aspect-lock-icon{
display: none; display: none;
} }

View file

@ -76,31 +76,31 @@ class chatBox{
}); });
} }
displayChat(chat){ displayChat(data){
//Create chat-entry span //Create chat-entry span
var chatEntry = document.createElement('span'); var chatEntry = document.createElement('span');
chatEntry.classList.add("chat-panel-buffer","chat-entry",`chat-entry-${chat.user}`); chatEntry.classList.add("chat-panel-buffer","chat-entry",`chat-entry-${data.user}`);
//Create high-level label //Create high-level label
var highLevel = document.createElement('p'); var highLevel = document.createElement('p');
highLevel.classList.add("chat-panel-buffer","chat-entry-high-level","high-level"); highLevel.classList.add("chat-panel-buffer","chat-entry-high-level","high-level");
highLevel.innerHTML = `${chat.highLevel}`; highLevel.innerHTML = `${data.highLevel}`;
chatEntry.appendChild(highLevel); chatEntry.appendChild(highLevel);
//Create username label //Create username label
var userLabel = document.createElement('p'); var userLabel = document.createElement('p');
userLabel.classList.add("chat-panel-buffer","chat-entry-username"); userLabel.classList.add("chat-panel-buffer","chat-entry-username");
if(chat.flair != "classic"){ if(data.flair != "classic"){
var flair = `flair-${chat.flair}`; var flair = `flair-${data.flair}`;
}else{ }else{
var flair = this.client.userList.colorMap.get(chat.user); var flair = this.client.userList.colorMap.get(data.user);
} }
//Create color span //Create color span
var colorSpan = document.createElement('span'); var colorSpan = document.createElement('span');
colorSpan.classList.add("chat-entry-flair-span", flair); colorSpan.classList.add("chat-entry-flair-span", flair);
colorSpan.innerHTML = `${chat.user}`; colorSpan.innerHTML = `${data.user}`;
userLabel.innerHTML = `${colorSpan.outerHTML}: `; userLabel.innerHTML = `${colorSpan.outerHTML}: `;
chatEntry.appendChild(userLabel); chatEntry.appendChild(userLabel);
@ -108,11 +108,11 @@ class chatBox{
//Create chat body //Create chat body
var chatBody = document.createElement('p'); var chatBody = document.createElement('p');
chatBody.classList.add("chat-panel-buffer","chat-entry-body"); chatBody.classList.add("chat-panel-buffer","chat-entry-body");
chatBody.innerHTML = chat.msg; chatBody.innerHTML = data.msg;
chatEntry.appendChild(chatBody); chatEntry.appendChild(chatBody);
this.chatBuffer.appendChild(this.chatPreprocessor.preprocess(chatEntry)); this.chatBuffer.appendChild(this.chatPreprocessor.preprocess(chatEntry, data));
//Set size to aspect on launch //Set size to aspect on launch
this.resizeAspect(); this.resizeAspect();

View file

@ -2,7 +2,8 @@ class chatPreprocessor{
constructor(){ constructor(){
} }
preprocess(chatEntry){ preprocess(chatEntry, rawData){
this.rawData = rawData;
//Set current chat nodes //Set current chat nodes
this.chatEntry = chatEntry; this.chatEntry = chatEntry;
this.chatBody = this.chatEntry.querySelector(".chat-entry-body"); this.chatBody = this.chatEntry.querySelector(".chat-entry-body");
@ -13,6 +14,9 @@ class chatPreprocessor{
//Inject whitespace into un-processed words //Inject whitespace into un-processed words
this.addWhitespace(); this.addWhitespace();
//Sush chat if it's a whisper
this.handleChatType();
//Inject the pre-processed chat into the chatEntry node //Inject the pre-processed chat into the chatEntry node
this.injectBody(); this.injectBody();
//Return the pre-processed node //Return the pre-processed node
@ -73,4 +77,10 @@ class chatPreprocessor{
} }
}); });
} }
handleChatType(){
if(this.rawData.type == "whisper"){
this.chatBody.classList.add('whisper');
}
}
} }

View file

@ -31,7 +31,7 @@ class commandPreprocessor{
this.sendFlag = false; this.sendFlag = false;
//Call the command with the argument array //Call the command with the argument array
this.commandProcessor[this.argumentArray[0]](this.argumentArray); this.commandProcessor[this.argumentArray[0]](this.argumentArray, this.commandArray);
} }
} }
} }