class commandPreprocessor{ constructor(client){ this.client = client; this.commandProcessor = new commandProcessor(client); this.emotes = { site: [], chan: [], personal: [] } //define listeners this.defineListeners(); } defineListeners(){ //When we receive site-wide emote list this.client.socket.on("siteEmotes", this.setSiteEmotes.bind(this)); this.client.socket.on("chanEmotes", this.setChanEmotes.bind(this)); this.client.socket.on("personalEmotes", this.setPersonalEmotes.bind(this)); } preprocess(command){ //Set command and sendFlag this.command = command; this.sendFlag = true; this.processLocalCommand(); if(this.sendFlag){ this.message = command; this.processEmotes(); this.processLinks(); this.sendRemoteCommand(); } } processLocalCommand(){ //Create an empty array to hold the command this.commandArray = []; //Split string by words 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 //If this is a local command if(this.commandArray[0] == '/'){ //If the command exists if(this.argumentArray != null && this.commandProcessor[this.argumentArray[0].toLowerCase()] != null){ //Don't send it to the server this.sendFlag = false; //Call the command with the argument array this.commandProcessor[this.argumentArray[0].toLowerCase()](this.argumentArray, this.commandArray); } } } processEmotes(){ //inject invisible whitespace in-between emotes to prevent from mushing links together this.message = this.message.replaceAll('][',']ㅤ['); //For each list of emotes Object.keys(this.emotes).forEach((key) => { //For each emote in the current list this.emotes[key].forEach((emote) => { //Inject emote links into the message this.message = this.message.replaceAll(`[${emote.name}]`, emote.link); }); }); } processLinks(){ //Strip out file seperators in-case the user is being a smart-ass this.message = this.message.replaceAll('␜',''); //Split message by links var splitMessage = this.message.split(/(https?:\/\/[^\sㅤ]+)/g); //Create an empty array to hold links this.links = []; splitMessage.forEach((chunk, chunkIndex) => { //For each chunk that is a link if(chunk.match(/(https?:\/\/[^\sㅤ]+)/g)){ //I looked online for obscure characters that no one would use to prevent people from chatting embed placeholders //Then I found this fucker, turns out it's literally made for the job lmao (even if it was originally intended for paper/magnetic tape) //Replace link with indexed placeholder splitMessage[chunkIndex] = `␜${this.links.length}` //push current chunk as link this.links.push(chunk); } }); //Join the message back together this.message = splitMessage.join(''); } sendRemoteCommand(){ this.client.socket.emit("chatMessage",{msg: this.message, links: this.links}); } setSiteEmotes(data){ this.emotes.site = data; } setChanEmotes(data){ this.emotes.chan = data; } setPersonalEmotes(data){ this.emotes.personal = data; } getEmoteByLink(link){ //Create an empty variable to hold the found emote var foundEmote = null; //For each list of emotes Object.keys(this.emotes).forEach((key) => { //For each emote in the current list this.emotes[key].forEach((emote) => { //if we found a match if(emote.link == link){ //return the match foundEmote = emote; } }); }); return foundEmote; } } class commandProcessor{ constructor(client){ this.client = client } high(argumentArray){ //If we have an argument if(argumentArray[1]){ //Use it to set our high level //Technically this is less of a local command than it would be if it where telling the select to do this //but TTN used to treat this as a local command so fuck it this.client.socket.emit("setHighLevel", {highLevel: argumentArray[1]}); } } }