216 lines
7.3 KiB
JavaScript
216 lines
7.3 KiB
JavaScript
/*Canopy - The next generation of stoner streaming software
|
|
Copyright (C) 2024-2025 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')
|
|
|
|
//local imports
|
|
const commandPreprocessor = require('./commandPreprocessor');
|
|
const loggerUtils = require('../../utils/loggerUtils');
|
|
const linkUtils = require('../../utils/linkUtils');
|
|
const emoteValidator = require('../../validators/emoteValidator');
|
|
const chat = require('./chat');
|
|
const {userModel} = require('../../schemas/user/userSchema');
|
|
|
|
module.exports = class{
|
|
constructor(server){
|
|
//Set server
|
|
this.server = server;
|
|
//Initialize command preprocessor
|
|
this.commandPreprocessor = new commandPreprocessor(server, this)
|
|
//Max chat buffer size
|
|
this.chatBufferSize = 50;
|
|
}
|
|
|
|
defineListeners(socket){
|
|
socket.on("chatMessage", (data) => {this.handleChat(socket, data)});
|
|
socket.on("setFlair", (data) => {this.setFlair(socket, data)});
|
|
socket.on("setHighLevel", (data) => {this.setHighLevel(socket, data)});
|
|
socket.on("addPersonalEmote", (data) => {this.addPersonalEmote(socket, data)});
|
|
socket.on("deletePersonalEmote", (data) => {this.deletePersonalEmote(socket, data)});
|
|
}
|
|
|
|
handleChat(socket, data){
|
|
this.commandPreprocessor.preprocess(socket, data);
|
|
}
|
|
|
|
async setFlair(socket, data){
|
|
var userDB = await userModel.findOne({user: socket.user.user});
|
|
|
|
if(userDB){
|
|
try{
|
|
//We can take this data raw since our schema checks it against existing flairs, and mongoose sanatizes queries
|
|
const flairDB = await userDB.setFlair(data.flair);
|
|
|
|
//Crawl through users active connections
|
|
this.server.crawlConnections(socket.user.user, (conn)=>{
|
|
//Update flair
|
|
conn.updateFlair(flairDB.name);
|
|
});
|
|
}catch(err){
|
|
return loggerUtils.socketExceptionHandler(socket, err);
|
|
}
|
|
}
|
|
}
|
|
|
|
async setHighLevel(socket, data){
|
|
var userDB = await userModel.findOne({user: socket.user.user});
|
|
|
|
if(userDB){
|
|
try{
|
|
//Floor input to an integer and set high level
|
|
userDB.highLevel = Math.floor(data.highLevel);
|
|
//Save user DB Document
|
|
await userDB.save();
|
|
|
|
//GetConnects across all channels
|
|
const connections = this.server.getConnections(socket.user.user);
|
|
|
|
//For each connection
|
|
connections.forEach((conn) => {
|
|
conn.updateHighLevel(userDB.highLevel);
|
|
});
|
|
}catch(err){
|
|
return loggerUtils.socketExceptionHandler(socket, err);
|
|
}
|
|
}
|
|
}
|
|
|
|
async addPersonalEmote(socket, data){
|
|
//Sanatize and Validate input
|
|
const name = emoteValidator.manualName(data.name);
|
|
const link = emoteValidator.manualLink(data.link);
|
|
|
|
//If we received good input
|
|
if(link && name){
|
|
//Generate marked link object
|
|
var emote = await linkUtils.markLink(link);
|
|
|
|
//If the link we have is an image or video
|
|
if(emote.type == 'image' || emote.type == 'video'){
|
|
//Get user document from DB
|
|
const userDB = await userModel.findOne({user: socket.user.user})
|
|
|
|
//if we have a user in the DB
|
|
if(userDB != null){
|
|
//Convert marked link into emote object with 1 ez step for only $19.95
|
|
emote.name = name;
|
|
|
|
//add emote to user document emotes list
|
|
userDB.emotes.push(emote);
|
|
|
|
//Save user doc
|
|
await userDB.save();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async deletePersonalEmote(socket, data){
|
|
//Get user doc from DB based on socket
|
|
const userDB = await userModel.findOne({user: socket.user.user});
|
|
|
|
//if we found a user
|
|
if(userDB != null){
|
|
await userDB.deleteEmote(data.name);
|
|
}
|
|
}
|
|
|
|
//Base chat functions
|
|
relayChat(user, flair, highLevel, msg, type = 'chat', chan, links){
|
|
this.relayChatObject(chan, new chat(user, flair, highLevel, msg, type, links));
|
|
}
|
|
|
|
relayChatObject(chan, chat){
|
|
//Send out chat
|
|
this.server.io.in(chan).emit("chatMessage", chat);
|
|
|
|
const channel = this.server.activeChannels.get(chan);
|
|
|
|
//If chat buffer length is over mandated size
|
|
if(channel.chatBuffer.buffer.length >= this.chatBufferSize){
|
|
//Take out oldest chat
|
|
channel.chatBuffer.shift();
|
|
}
|
|
|
|
//Add buffer to chat
|
|
channel.chatBuffer.push(chat);
|
|
}
|
|
|
|
relayPrivateChat(socket, user, flair, highLevel, msg, type, links){
|
|
this.relayPrivateChatObject(socket , new chat(user, flair, highLevel, msg, type, links));
|
|
}
|
|
|
|
relayPrivateChatObject(socket, chat){
|
|
socket.emit("chatMessage", chat);
|
|
}
|
|
|
|
relayGlobalChat(user, flair, highLevel, msg, type = 'chat', links){
|
|
this.relayGlobalChatObject(new chat(user, flair, highLevel, msg, type, links));
|
|
}
|
|
|
|
relayGlobalChatObject(chat){
|
|
this.server.io.emit("chatMessage", chat);
|
|
}
|
|
|
|
//User Chat Functions
|
|
relayUserChat(socket, msg, type, links){
|
|
const user = this.server.getSocketInfo(socket);
|
|
this.relayChat(user.user, user.flair, user.highLevel, msg, type, socket.chan, links);
|
|
}
|
|
|
|
//Toke Chat Functions
|
|
relayTokeCallout(msg, links){
|
|
this.relayGlobalChat("Tokebot", "", '∞', msg, "toke", links);
|
|
}
|
|
|
|
relayTokeWhisper(socket, msg, links){
|
|
this.relayPrivateChat(socket, "Tokebot", "", '∞', msg, "tokewhisper", links);
|
|
}
|
|
|
|
relayGlobalTokeWhisper(msg, links){
|
|
this.relayGlobalChat("Tokebot", "", '∞', msg, "tokewhisper", links);
|
|
}
|
|
|
|
//Announcement Functions
|
|
relayServerAnnouncement(msg, links){
|
|
this.relayGlobalChat("Server", "", '∞', msg, "announcement", links);
|
|
}
|
|
|
|
relayChannelAnnouncement(chan, msg, links){
|
|
const activeChan = this.server.activeChannels.get(chan);
|
|
|
|
//If channel isn't null
|
|
if(activeChan != null){
|
|
this.relayChat("Channel", "", '∞', msg, "announcement", chan, links);
|
|
}
|
|
}
|
|
|
|
//Misc Functions
|
|
clearChat(chan, user){
|
|
const activeChan = this.server.activeChannels.get(chan);
|
|
|
|
//If channel isn't null
|
|
if(activeChan != null){
|
|
const target = activeChan.userList.get(user);
|
|
|
|
//If no user was entered OR the user was found
|
|
if(user == null || target != null){
|
|
this.server.io.in(chan).emit("clearChat", {user});
|
|
}
|
|
}
|
|
}
|
|
} |