Server now seperates links and media. Client now embeds links, but not media.
This commit is contained in:
parent
a83dbdcb7f
commit
23df4f88f9
|
|
@ -79,45 +79,45 @@ module.exports = class{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
relayUserChat(socket, msg, type){
|
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)
|
this.relayChat(user.user, user.flair, user.highLevel, msg, type, socket.chan, links)
|
||||||
}
|
}
|
||||||
|
|
||||||
relayChat(user, flair, highLevel, msg, type = 'chat', chan){
|
relayChat(user, flair, highLevel, msg, type = 'chat', chan, links){
|
||||||
this.server.io.in(chan).emit("chatMessage", {user, flair, highLevel, msg, type});
|
this.server.io.in(chan).emit("chatMessage", {user, flair, highLevel, msg, type, links});
|
||||||
}
|
}
|
||||||
|
|
||||||
relayServerWisper(socket, user, flair, highLevel, msg, type){
|
relayServerWisper(socket, user, flair, highLevel, msg, type, links){
|
||||||
socket.emit("chatMessage", {user, flair, highLevel, msg, type});
|
socket.emit("chatMessage", {user, flair, highLevel, msg, type, links});
|
||||||
}
|
}
|
||||||
|
|
||||||
relayGlobalChat(user, flair, highLevel, msg, type = 'chat'){
|
relayGlobalChat(user, flair, highLevel, msg, type = 'chat', links){
|
||||||
this.server.io.emit("chatMessage", {user, flair, highLevel, msg, type});
|
this.server.io.emit("chatMessage", {user, flair, highLevel, msg, type, links});
|
||||||
}
|
}
|
||||||
|
|
||||||
relayTokeCallout(msg){
|
relayTokeCallout(msg, links){
|
||||||
this.relayGlobalChat("Tokebot", "", '∞', msg, "toke");
|
this.relayGlobalChat("Tokebot", "", '∞', msg, "toke", links);
|
||||||
}
|
}
|
||||||
|
|
||||||
relayTokeWhisper(socket, msg){
|
relayTokeWhisper(socket, msg, links){
|
||||||
this.relayServerWisper(socket, "Tokebot", "", '∞', msg, "tokewhisper");
|
this.relayServerWisper(socket, "Tokebot", "", '∞', msg, "tokewhisper", links);
|
||||||
}
|
}
|
||||||
|
|
||||||
relayGlobalTokeWhisper(msg){
|
relayGlobalTokeWhisper(msg, links){
|
||||||
this.relayGlobalChat("Tokebot", "", '∞', msg, "tokewhisper");
|
this.relayGlobalChat("Tokebot", "", '∞', msg, "tokewhisper", links);
|
||||||
}
|
}
|
||||||
|
|
||||||
relayServerAnnouncement(msg){
|
relayServerAnnouncement(msg, links){
|
||||||
this.relayGlobalChat("Server", "", '∞', msg, "announcement");
|
this.relayGlobalChat("Server", "", '∞', msg, "announcement", links);
|
||||||
}
|
}
|
||||||
|
|
||||||
relayChannelAnnouncement(chan, msg){
|
relayChannelAnnouncement(chan, msg, links){
|
||||||
const activeChan = this.server.activeChannels.get(chan);
|
const activeChan = this.server.activeChannels.get(chan);
|
||||||
|
|
||||||
//If channel isn't null
|
//If channel isn't null
|
||||||
if(activeChan != null){
|
if(activeChan != null){
|
||||||
this.relayChat("Channel", "", '∞', msg, "announcement", chan);
|
this.relayChat("Channel", "", '∞', msg, "announcement", chan, links);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ module.exports = class commandPreprocessor{
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
this.sendFlag = true;
|
this.sendFlag = true;
|
||||||
this.rawData = data;
|
this.rawData = data;
|
||||||
|
this.chatType = 'chat';
|
||||||
|
|
||||||
//If we don't pass sanatization/validation turn this car around
|
//If we don't pass sanatization/validation turn this car around
|
||||||
if(!this.sanatizeCommand()){
|
if(!this.sanatizeCommand()){
|
||||||
|
|
@ -45,8 +46,18 @@ module.exports = class commandPreprocessor{
|
||||||
this.splitCommand();
|
this.splitCommand();
|
||||||
//Process the command
|
//Process the command
|
||||||
await this.processServerCommand();
|
await this.processServerCommand();
|
||||||
//Send it as chat (assuming the flag isn't false)
|
|
||||||
this.sendChat();
|
//If we're going to relay this command as a message, continue on to chat processing
|
||||||
|
if(this.sendFlag){
|
||||||
|
//Create message from commandArray
|
||||||
|
this.message = this.commandArray.join('').trimStart();
|
||||||
|
|
||||||
|
//Validate links and mark them by embed type
|
||||||
|
await this.markLinks();
|
||||||
|
|
||||||
|
//Send the chat
|
||||||
|
this.sendChat();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sanatizeCommand(){
|
sanatizeCommand(){
|
||||||
|
|
@ -66,35 +77,72 @@ module.exports = class commandPreprocessor{
|
||||||
async processServerCommand(){
|
async processServerCommand(){
|
||||||
//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(this.rawData.msg[0] == '!'){
|
if(this.rawData.msg[0] == '!'){
|
||||||
//Create hash table to hold information about current command
|
|
||||||
const commandObj = {
|
|
||||||
socket: this.socket,
|
|
||||||
commandArray: this.commandArray,
|
|
||||||
argumentArray: this.argumentArray,
|
|
||||||
rawData: this.rawData
|
|
||||||
}
|
|
||||||
|
|
||||||
//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(this.argumentArray != null){
|
if(this.argumentArray != null){
|
||||||
if(this.commandProcessor[this.argumentArray[0].toLowerCase()] != null){
|
if(this.commandProcessor[this.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)
|
||||||
this.sendFlag = await this.commandProcessor[this.argumentArray[0].toLowerCase()](commandObj);
|
this.sendFlag = await this.commandProcessor[this.argumentArray[0].toLowerCase()](this);
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
//Process as toke command if we didnt get a match from the standard server-side command processor
|
//Process as toke command if we didnt get a match from the standard server-side command processor
|
||||||
this.sendFlag = await this.tokebot.tokeProcessor(commandObj);
|
this.sendFlag = await this.tokebot.tokeProcessor(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sendChat(){
|
async markLinks(){
|
||||||
//If the send flag is true
|
const maxSize = 4000000;
|
||||||
if(this.sendFlag){
|
//Empty out the links array
|
||||||
//FUCKIN' SEND IT!
|
this.links = [];
|
||||||
this.chatHandler.relayUserChat(this.socket, this.commandArray.join('').trimStart());
|
|
||||||
|
//For each link sent from the client
|
||||||
|
//this.rawData.links.forEach((link) => {
|
||||||
|
for (const link of this.rawData.links){
|
||||||
|
//Set standard link type
|
||||||
|
var linkType = 'link';
|
||||||
|
|
||||||
|
//Pull content type
|
||||||
|
var response = await fetch(link,{
|
||||||
|
method: "HEAD",
|
||||||
|
});
|
||||||
|
|
||||||
|
//Get file type from header
|
||||||
|
const fileType = response.headers.get('content-type');
|
||||||
|
const fileSize = response.headers.get('content-length');
|
||||||
|
|
||||||
|
|
||||||
|
//If they're reporting file types
|
||||||
|
if(fileType != null){
|
||||||
|
//If we have an image
|
||||||
|
if(fileType.match('image/')){
|
||||||
|
//If the file size is unreported OR it's smaller than 4MB (not all servers report this and images that big are pretty rare)
|
||||||
|
if(fileSize == null || fileSize <= maxSize){
|
||||||
|
//Mark link as an image
|
||||||
|
linkType = 'image';
|
||||||
|
}
|
||||||
|
//If it's a video
|
||||||
|
}else if(fileType.match('video/mp4' || 'video/webm')){
|
||||||
|
//If the server is reporting file-size and it's reporting under 4MB (Reject unreported sizes to be on the safe side is video is huge)
|
||||||
|
if(fileSize != null && fileSize <= maxSize){
|
||||||
|
//mark link as a video
|
||||||
|
linkType = 'video';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add a marked link object to our links array
|
||||||
|
this.links.push({
|
||||||
|
link,
|
||||||
|
linkType
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendChat(){
|
||||||
|
//FUCKIN' SEND IT!
|
||||||
|
this.chatHandler.relayUserChat(this.socket, this.message, this.chatType, this.links);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class commandProcessor{
|
class commandProcessor{
|
||||||
|
|
@ -104,27 +152,27 @@ class commandProcessor{
|
||||||
}
|
}
|
||||||
|
|
||||||
//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
|
||||||
whisper(commandObj){
|
whisper(preprocessor){
|
||||||
//splice out our whisper
|
//splice out our whisper
|
||||||
commandObj.commandArray.splice(0,2);
|
preprocessor.commandArray.splice(0,2);
|
||||||
|
|
||||||
//send it
|
//Mark out the current message as a whisper
|
||||||
this.chatHandler.relayUserChat(commandObj.socket, commandObj.commandArray.join(''), 'whisper');
|
preprocessor.chatType = 'whisper';
|
||||||
|
|
||||||
//Make sure to throw the send flag
|
//Make sure to throw the send flag
|
||||||
return false;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
async announce(commandObj){
|
async announce(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: preprocessor.socket.chan});
|
||||||
|
|
||||||
//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(chanDB != null && await chanDB.permCheck(commandObj.socket.user, 'announce')){
|
if(chanDB != null && await chanDB.permCheck(preprocessor.socket.user, 'announce')){
|
||||||
//splice out our whisper
|
//splice out our whisper
|
||||||
commandObj.commandArray.splice(0,2);
|
preprocessor.commandArray.splice(0,2);
|
||||||
//send it
|
//send it
|
||||||
this.chatHandler.relayChannelAnnouncement(commandObj.socket.chan, commandObj.commandArray.join(''));
|
this.chatHandler.relayChannelAnnouncement(preprocessor.socket.chan, preprocessor.commandArray.join(''));
|
||||||
//throw send flag
|
//throw send flag
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -133,13 +181,13 @@ class commandProcessor{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async serverannounce(commandObj){
|
async serverannounce(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(preprocessor.socket.user, 'announce')){
|
||||||
//splice out our whisper
|
//splice out our whisper
|
||||||
commandObj.commandArray.splice(0,2);
|
preprocessor.commandArray.splice(0,2);
|
||||||
//send it
|
//send it
|
||||||
this.chatHandler.relayServerAnnouncement(commandObj.commandArray.join(''));
|
this.chatHandler.relayServerAnnouncement(preprocessor.commandArray.join(''));
|
||||||
//throw send flag
|
//throw send flag
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -148,14 +196,14 @@ class commandProcessor{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async clear(commandObj){
|
async clear(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: preprocessor.socket.chan});
|
||||||
|
|
||||||
//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 chanDB.permCheck(commandObj.socket.user, 'clearChat')){
|
if(await chanDB.permCheck(preprocessor.socket.user, 'clearChat')){
|
||||||
//Send off the command
|
//Send off the command
|
||||||
this.chatHandler.clearChat(commandObj.socket.chan, commandObj.argumentArray[1]);
|
this.chatHandler.clearChat(preprocessor.socket.chan, preprocessor.argumentArray[1]);
|
||||||
//throw send flag
|
//throw send flag
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -295,6 +295,10 @@ select.panel-head-element{
|
||||||
color: var(--accent1);
|
color: var(--accent1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-link{
|
||||||
|
color: var(--focus0);
|
||||||
|
}
|
||||||
|
|
||||||
/* popup */
|
/* popup */
|
||||||
|
|
||||||
.popup-backer{
|
.popup-backer{
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@ class chatPostprocessor{
|
||||||
//We could pass this through arguments but these functions wont be very interoperable anyways since they expect a purpose-made hashtable
|
//We could pass this through arguments but these functions wont be very interoperable anyways since they expect a purpose-made hashtable
|
||||||
this.splitBody();
|
this.splitBody();
|
||||||
|
|
||||||
|
//Inject links into un-processed placeholders
|
||||||
|
this.processLinks();
|
||||||
|
|
||||||
//Inject whitespace into un-processed words
|
//Inject whitespace into un-processed words
|
||||||
this.addWhitespace();
|
this.addWhitespace();
|
||||||
|
|
||||||
|
|
@ -26,8 +29,8 @@ class chatPostprocessor{
|
||||||
splitBody(){
|
splitBody(){
|
||||||
//Create an empty array to hold the body
|
//Create an empty array to hold the body
|
||||||
this.bodyArray = [];
|
this.bodyArray = [];
|
||||||
//Split string by words
|
//Split string by words (except for file seperator to keep link placeholders in-tact)
|
||||||
const splitString = this.chatBody.innerHTML.split(/\b/g); //Group words together
|
const splitString = this.chatBody.innerHTML.split(/(?<!␜)\b(?!␜)/g); //Group words together
|
||||||
|
|
||||||
//for each word in the splitstring
|
//for each word in the splitstring
|
||||||
splitString.forEach((string) => {
|
splitString.forEach((string) => {
|
||||||
|
|
@ -48,7 +51,18 @@ class chatPostprocessor{
|
||||||
|
|
||||||
//Extract strings into the empty array
|
//Extract strings into the empty array
|
||||||
this.bodyArray.forEach((wordObj) => {
|
this.bodyArray.forEach((wordObj) => {
|
||||||
stringArray.push(wordObj.string);
|
if(wordObj.type == 'word'){
|
||||||
|
stringArray.push(wordObj.string);
|
||||||
|
}else if(wordObj.type == 'link'){
|
||||||
|
//Create a link node from our link
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.classList.add('chat-link');
|
||||||
|
link.href = wordObj.link;
|
||||||
|
link.innerHTML = wordObj.link;
|
||||||
|
|
||||||
|
//Inject it into the original string, and add it to string array
|
||||||
|
stringArray.push(wordObj.string.replace('␜',link.outerHTML));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//Join the strings to fill the chat entry
|
//Join the strings to fill the chat entry
|
||||||
|
|
@ -62,7 +76,6 @@ class chatPostprocessor{
|
||||||
if(wordObj.type == "word"){
|
if(wordObj.type == "word"){
|
||||||
var wordArray = [];
|
var wordArray = [];
|
||||||
//Add invisible whitespace in-between characters to keep it from breaking page layout
|
//Add invisible whitespace in-between characters to keep it from breaking page layout
|
||||||
//this.bodyArray[index].string = wordObj.string.split("").join("ㅤ");
|
|
||||||
this.bodyArray[wordIndex].string.split("").forEach((char, charIndex) => {
|
this.bodyArray[wordIndex].string.split("").forEach((char, charIndex) => {
|
||||||
wordArray.push(char);
|
wordArray.push(char);
|
||||||
//After eight characters
|
//After eight characters
|
||||||
|
|
@ -78,6 +91,24 @@ class chatPostprocessor{
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processLinks(){
|
||||||
|
this.rawData.links.forEach((link, linkIndex) => {
|
||||||
|
this.bodyArray.forEach((wordObj, wordIndex) => {
|
||||||
|
//Check current wordobj for link (placeholder may contain whitespace with it)
|
||||||
|
if(wordObj.string.match(`␜${linkIndex}␜`)){
|
||||||
|
//Set current word object in the body array to the new link object
|
||||||
|
this.bodyArray[wordIndex] = {
|
||||||
|
//Don't want to use a numbered placeholder to make this easier during body injection
|
||||||
|
//but we also don't want to clobber any surrounding whitespace
|
||||||
|
string: wordObj.string.replace(`␜${linkIndex}␜`, '␜'),
|
||||||
|
link: link.link,
|
||||||
|
type: "link"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
handleChatType(){
|
handleChatType(){
|
||||||
if(this.rawData.type == "whisper"){
|
if(this.rawData.type == "whisper"){
|
||||||
//add whisper class
|
//add whisper class
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue