381 lines
13 KiB
HTML
381 lines
13 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>JSDoc: Source: commandPreprocessor.js</title>
|
||
|
||
<script src="scripts/prettify/prettify.js"> </script>
|
||
<script src="scripts/prettify/lang-css.js"> </script>
|
||
<!--[if lt IE 9]>
|
||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||
<![endif]-->
|
||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||
</head>
|
||
|
||
<body>
|
||
|
||
<div id="main">
|
||
|
||
<h1 class="page-title">Source: commandPreprocessor.js</h1>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<section>
|
||
<article>
|
||
<pre class="prettyprint source linenums"><code>/*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/>.*/
|
||
|
||
/**
|
||
* Class containing chat and command pre-processing logic
|
||
*/
|
||
class commandPreprocessor{
|
||
/**
|
||
* Instantiates a new commandPreprocessor object
|
||
* @param {channel} client - Parent client Management Object
|
||
*/
|
||
constructor(client){
|
||
/**
|
||
* Parent Client Management object
|
||
*/
|
||
this.client = client;
|
||
|
||
/**
|
||
* Child Command Processor object
|
||
*/
|
||
this.commandProcessor = new commandProcessor(client);
|
||
|
||
/**
|
||
* Set of arrays containing site-wide, channel-wide, and user-specific emotes
|
||
*/
|
||
this.emotes = {
|
||
site: [],
|
||
chan: [],
|
||
personal: []
|
||
}
|
||
|
||
//define listeners
|
||
this.defineListeners();
|
||
}
|
||
|
||
/**
|
||
* Defines Network-Related Listeners
|
||
*/
|
||
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));
|
||
this.client.socket.on("usedTokes", this.setUsedTokes.bind(this));
|
||
}
|
||
|
||
/**
|
||
* Pre-Processes a single chat/command before sending it off to the server
|
||
* @param {String} command - Chat/Command to pre-process
|
||
*/
|
||
preprocess(command){
|
||
//Set command and sendFlag
|
||
this.command = command;
|
||
this.sendFlag = true;
|
||
|
||
//Attempt to process as local command
|
||
this.processLocalCommand();
|
||
|
||
//If we made it through the local command processor
|
||
if(this.sendFlag){
|
||
//Set the message to the command
|
||
this.message = command;
|
||
//Process message emotes into links
|
||
this.processEmotes();
|
||
//Process unmarked links into marked links
|
||
this.processLinks();
|
||
//Send command off to server
|
||
this.sendRemoteCommand();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Processes local commands, starting with '/'
|
||
*/
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Processes emotes refrences in loaded message into links to be further processed by processLinks()
|
||
*/
|
||
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, pad with invisible whitespace to keep link from getting mushed
|
||
this.message = this.message.replaceAll(`[${emote.name}]`, `ㅤ${emote.link}ㅤ`);
|
||
});
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Processes links into numbered file seperators, putting links into a dedicated array.
|
||
*/
|
||
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('');
|
||
}
|
||
|
||
/**
|
||
* Transmits message/command off to server
|
||
*/
|
||
sendRemoteCommand(){
|
||
this.client.socket.emit("chatMessage",{msg: this.message, links: this.links});
|
||
}
|
||
|
||
/**
|
||
* Sets site emotes
|
||
* @param {Object} data - Emote data from server
|
||
*/
|
||
setSiteEmotes(data){
|
||
this.emotes.site = data;
|
||
}
|
||
|
||
/**
|
||
* Sets channel emotes
|
||
* @param {Object} data - Emote data from server
|
||
*/
|
||
setChanEmotes(data){
|
||
this.emotes.chan = data;
|
||
}
|
||
|
||
/**
|
||
* Sets personal emotes
|
||
* @param {Object} data - Emote data from server
|
||
*/
|
||
setPersonalEmotes(data){
|
||
this.emotes.personal = data;
|
||
}
|
||
|
||
/**
|
||
* Sets used tokes
|
||
* @param {Object} data - Used toke data from server
|
||
*/
|
||
setUsedTokes(data){
|
||
this.usedTokes = data.tokes;
|
||
}
|
||
|
||
/**
|
||
* Fetches emote by link
|
||
* @param {String} link - Link to fetch emote with
|
||
* @returns {Object} found emote
|
||
*/
|
||
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;
|
||
}
|
||
|
||
/**
|
||
* Generates flat list of emote names
|
||
* @returns {Array} List of strings containing emote names
|
||
*/
|
||
getEmoteNames(){
|
||
//Create an empty array to hold names
|
||
let names = [];
|
||
|
||
//For every set of emotes
|
||
for(let set of Object.keys(this.emotes)){
|
||
//for every emote in the current set of emotes
|
||
for(let emote of this.emotes[set]){
|
||
//push the name of the emote to the name list
|
||
names.push(emote.name);
|
||
}
|
||
}
|
||
|
||
//return our list of names
|
||
return names;
|
||
}
|
||
|
||
/**
|
||
* Generates auto-complete dictionary from pre-written commands, emotes, and used tokes from servers for use with autocomplete
|
||
* @returns {Object} Generated Dictionary object
|
||
*/
|
||
buildAutocompleteDictionary(){
|
||
let dictionary = {
|
||
tokes: {
|
||
prefix: '!',
|
||
postfix: '',
|
||
cmds: [
|
||
['toke', true]
|
||
].concat(injectPerms(this.usedTokes))
|
||
},
|
||
//Make sure to add spaces at the end for commands that take arguments
|
||
//Not necissary but definitely nice to have
|
||
serverCMD: {
|
||
prefix: '!',
|
||
postfix: '',
|
||
cmds: [
|
||
["whisper ", true],
|
||
["announce ", client.user.permMap.chan.get('announce')],
|
||
["serverannounce ", client.user.permMap.site.get('announce')],
|
||
["clear ", client.user.permMap.chan.get('clearChat')],
|
||
["kick ", client.user.permMap.chan.get('kickUser')],
|
||
]
|
||
},
|
||
localCMD:{
|
||
prefix: '/',
|
||
postfix: '',
|
||
cmds: [
|
||
["high ", true]
|
||
]
|
||
},
|
||
usernames:{
|
||
prefix: '',
|
||
postfix: '',
|
||
cmds: injectPerms(Array.from(client.userList.colorMap.keys()))
|
||
},
|
||
emotes:{
|
||
prefix:'[',
|
||
postfix:']',
|
||
cmds: injectPerms(this.getEmoteNames())
|
||
}
|
||
};
|
||
|
||
//return our dictionary object
|
||
return dictionary;
|
||
|
||
function injectPerms(cmds, perm = true){
|
||
//Create empty array to hold cmds
|
||
let cmdSet = [];
|
||
|
||
//For each cmd
|
||
for(let cmd of cmds){
|
||
//Add the cmd with its perm to the cmdset
|
||
cmdSet.push([cmd, perm]);
|
||
}
|
||
|
||
//return the cmd set
|
||
return cmdSet;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
/**
|
||
* Class which contains logic for client-side commands
|
||
*/
|
||
class commandProcessor{
|
||
/**
|
||
* Instantiates a new Command Processor object
|
||
* @param {channel} client - Parent client mgmt object
|
||
*/
|
||
constructor(client){
|
||
/**
|
||
* Parent Client Management object
|
||
*/
|
||
this.client = client
|
||
}
|
||
|
||
/**
|
||
* Method handling /high client command
|
||
* @param {Array} argumentArray - Array of arguments passed down from Command Pre-Processor
|
||
*/
|
||
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]});
|
||
}
|
||
}
|
||
}</code></pre>
|
||
</article>
|
||
</section>
|
||
|
||
|
||
|
||
|
||
</div>
|
||
|
||
<nav>
|
||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="addURLPopup.html">addURLPopup</a></li><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="clearPopup.html">clearPopup</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="defaultTitlesPopup.html">defaultTitlesPopup</a></li><li><a href="emotePanel.html">emotePanel</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="newPlaylistPopup.html">newPlaylistPopup</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="playlistManager.html">playlistManager</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="queuePanel.html">queuePanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="renamePopup.html">renamePopup</a></li><li><a href="reschedulePopup.html">reschedulePopup</a></li><li><a href="schedulePopup.html">schedulePopup</a></li><li><a href="settingsPanel.html">settingsPanel</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||
</nav>
|
||
|
||
<br class="clear">
|
||
|
||
<footer>
|
||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Sat Sep 06 2025 10:33:49 GMT-0400 (Eastern Daylight Time)
|
||
</footer>
|
||
|
||
<script> prettyPrint(); </script>
|
||
<script src="scripts/linenumber.js"> </script>
|
||
</body>
|
||
</html>
|