diff --git a/src/app/channel/activeChannel.js b/src/app/channel/activeChannel.js
index be2121b..7abbc5b 100644
--- a/src/app/channel/activeChannel.js
+++ b/src/app/channel/activeChannel.js
@@ -55,6 +55,7 @@ module.exports = class{
//Make sure the client receives important client-info before userlist
//await this.sendClientMetadata(userDB, socket);
await userObj.sendClientMetadata();
+ await userObj.sendSiteEmotes();
//Send out the userlist
this.broadcastUserList(socket.chan);
diff --git a/src/app/channel/channelManager.js b/src/app/channel/channelManager.js
index d786e50..ebb886d 100644
--- a/src/app/channel/channelManager.js
+++ b/src/app/channel/channelManager.js
@@ -16,6 +16,7 @@ along with this program. If not, see .*/
//Local Imports
const channelModel = require('../../schemas/channel/channelSchema');
+const emoteModel = require('../../schemas/emoteSchema');
const {userModel} = require('../../schemas/userSchema');
const loggerUtils = require('../../utils/loggerUtils');
const activeChannel = require('./activeChannel');
@@ -181,4 +182,12 @@ module.exports = class{
//crawl through connections and kick user
this.crawlConnections(user,(foundUser)=>{foundUser.disconnect(reason)});
}
+
+ async broadcastSiteEmotes(){
+ //Get emote list from DB
+ const emoteList = await emoteModel.getEmotes();
+
+ //Broadcast that sumbitch
+ this.io.sockets.emit('siteEmotes', emoteList);
+ }
}
\ No newline at end of file
diff --git a/src/app/channel/connectedUser.js b/src/app/channel/connectedUser.js
index 3f444c0..6977e66 100644
--- a/src/app/channel/connectedUser.js
+++ b/src/app/channel/connectedUser.js
@@ -16,6 +16,7 @@ along with this program. If not, see .*/
//local imports
const flairModel = require('../../schemas/flairSchema');
+const emoteModel = require('../../schemas/emoteSchema');
const permissionModel = require('../../schemas/permissionSchema');
module.exports = class{
@@ -87,6 +88,14 @@ module.exports = class{
this.emit("clientMetadata", {user: userObj, flairList});
}
+ async sendSiteEmotes(){
+ //Get emote list from DB
+ const emoteList = await emoteModel.getEmotes();
+
+ //Send it off to the user
+ this.emit('siteEmotes', emoteList);
+ }
+
updateFlair(flair){
this.flair = flair;
diff --git a/src/app/channel/tokebot.js b/src/app/channel/tokebot.js
index a48b335..536d007 100644
--- a/src/app/channel/tokebot.js
+++ b/src/app/channel/tokebot.js
@@ -53,7 +53,7 @@ module.exports = class tokebot{
tokeProcessor(commandObj){
//Check for site-wide toke commands
- if(this.tokeCommands.indexOf(commandObj.argumentArray[0]) != -1){
+ if(this.tokeCommands.indexOf(commandObj.argumentArray[0].toLowerCase()) != -1){
//Seems lame to set a bool in an if statement but this would've made a really ugly turinary
var foundToke = true;
}else{
@@ -62,7 +62,7 @@ module.exports = class tokebot{
//Check if they're using a channel-only toke
//This should be safe to do without a null check but someone prove me wrong lmao
- var foundToke = (activeChan.tokeCommands.indexOf(commandObj.argumentArray[0]) != -1);
+ var foundToke = (activeChan.tokeCommands.indexOf(commandObj.argumentArray[0].toLowerCase()) != -1);
}
@@ -76,7 +76,7 @@ module.exports = class tokebot{
this.tokeCounter = this.tokeTime;
//Add the toking user to the tokers map
- this.tokers.set(commandObj.socket.user.user, commandObj.argumentArray[0]);
+ this.tokers.set(commandObj.socket.user.user, commandObj.argumentArray[0].toLowerCase());
//kick-off the count-down
this.tokeTimer = setTimeout(this.countdown.bind(this), 1000)
@@ -91,7 +91,7 @@ module.exports = class tokebot{
this.chatHandler.relayTokeCallout(`${commandObj.socket.user.user} has joined the toke from #${commandObj.socket.chan}! Post !${commandObj.argumentArray[0]} to take part!`);
//Add the toking user to the tokers map
- this.tokers.set(commandObj.socket.user.user, commandObj.argumentArray[0]);
+ this.tokers.set(commandObj.socket.user.user, commandObj.argumentArray[0].toLowerCase());
//If the user is already in the toke
}else{
//Tell them to fuck off
diff --git a/src/schemas/emoteSchema.js b/src/schemas/emoteSchema.js
index d3c5855..782aaca 100644
--- a/src/schemas/emoteSchema.js
+++ b/src/schemas/emoteSchema.js
@@ -19,6 +19,7 @@ const {mongoose} = require('mongoose');
//Local Imports
const defaultEmote = require("../../defaultEmotes.json");
+const server = require('../server');
const typeEnum = ["image", "video"];
@@ -39,6 +40,19 @@ const emoteSchema = new mongoose.Schema({
}
});
+//pre-save function
+emoteSchema.post('save', async function (next){
+ //broadcast updated emotes
+ server.channelManager.broadcastSiteEmotes();
+});
+
+//post-delete function (document not query)
+emoteSchema.post('deleteOne', {document: true}, async function (next){
+ //broadcast updated emotes
+ server.channelManager.broadcastSiteEmotes();
+});
+
+//statics
emoteSchema.statics.loadDefaults = async function(){
//Make sure registerEmote function is happy
const _this = this;
diff --git a/www/css/adminPanel.css b/www/css/adminPanel.css
index ab577d8..98fdd00 100644
--- a/www/css/adminPanel.css
+++ b/www/css/adminPanel.css
@@ -102,19 +102,14 @@ img.admin-list-entry-item{
width: 11em;
}
-#toke-command-list-div{
- /*Maybe I suck at CSS but I can't get relative percentage-based heights to play nice here.
- Either way sizing this by total viewheight isn't too big a deal. At least here...*/
- min-height: 9em;
- max-height: 20vh;
-}
-
div.toke-command-list{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(15em, 1fr));
text-align: center;
padding: 1em;
overflow-y: auto;
+ min-height: 0.8em;
+ max-height: 5.5em;
}
span.toke-command-list{
@@ -131,16 +126,13 @@ i.toke-command-list{
margin: 0.2em;
}
-#emote-list-div{
- height: 30vh;
-}
-
#emote-list{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(10em, 1fr));
padding: 1em;
overflow-y: auto;
justify-items: center;
+ max-height: 19.8em;
}
div.emote-list-emote{
diff --git a/www/css/channel.css b/www/css/channel.css
index 5ccbffb..d845251 100644
--- a/www/css/channel.css
+++ b/www/css/channel.css
@@ -269,11 +269,12 @@ span.user-entry{
.toke{
text-align: center;
margin: 0.2em auto;
- font-size: 9pt;
+ font-size: 9.5pt;
}
-.tokewhisper{
+.serverwhisper{
font-size: 9pt;
+ font-style: italic;
}
.chat-img, .chat-video{
diff --git a/www/css/theme/movie-night.css b/www/css/theme/movie-night.css
index 3642b77..7de2eca 100644
--- a/www/css/theme/movie-night.css
+++ b/www/css/theme/movie-night.css
@@ -26,8 +26,9 @@ along with this program. If not, see .*/
--bg2-alt0: rgb(200, 200, 200);
--bg2-alt1: rgb(180, 180, 180);
- --accent0: rgb(48, 47, 47);
+ --accent0: rgb(47, 47, 47);
--accent0-alt0: rgb(34, 34, 34);
+ --accent0-alt1: rgb(70, 70, 70);
--accent1: rgb(245, 245, 245);
--accent1-alt0: rgb(185, 185, 185);
--accent2: var(--accent0-alt0);
@@ -240,6 +241,10 @@ p.channel-guide-entry-item{
border-bottom: 1px solid var(--bg2-alt1);
}
+.serverwhisper{
+ color: var(--accent0-alt1)
+}
+
.userlist-color0{/*green0*/
color: var(--userlist-color0);
text-shadow: none;
diff --git a/www/js/channel/chat.js b/www/js/channel/chat.js
index fc1fb10..df8e38d 100644
--- a/www/js/channel/chat.js
+++ b/www/js/channel/chat.js
@@ -27,7 +27,7 @@ class chatBox{
//Preprocessor objects
this.commandPreprocessor = new commandPreprocessor(client);
- this.chatPostprocessor = new chatPostprocessor();
+ this.chatPostprocessor = new chatPostprocessor(client);
//Element Nodes
this.chatPanel = document.querySelector("#chat-panel-div");
diff --git a/www/js/channel/chatPostprocessor.js b/www/js/channel/chatPostprocessor.js
index bafec34..8000da7 100644
--- a/www/js/channel/chatPostprocessor.js
+++ b/www/js/channel/chatPostprocessor.js
@@ -1,5 +1,6 @@
class chatPostprocessor{
- constructor(){
+ constructor(client){
+ this.client = client;
}
preprocess(chatEntry, rawData){
@@ -91,6 +92,15 @@ class chatPostprocessor{
img.classList.add('chat-img');
img.src = wordObj.link;
+ //Look for an emote by link since emotes are tx'd as bare links
+ const emote = this.client.chatBox.commandPreprocessor.getEmoteByLink(wordObj.link);
+
+ //If this is a known emote
+ if(emote != null){
+ //Set the hover text to the emote's name
+ img.title = `[${emote.name}]`;
+ }
+
//Append node to chatBody
injectNode(wordObj, img);
}else if(wordObj.type == 'video'){
@@ -103,6 +113,15 @@ class chatPostprocessor{
vid.loop = true;
vid.muted = true;
+ //Look for an emote by link since emotes are tx'd as bare links
+ const emote = this.client.chatBox.commandPreprocessor.getEmoteByLink(wordObj.link);
+
+ //If this is a known emote
+ if(emote != null){
+ //Set the hover text to the emote's name
+ vid.title = `[${emote.name}]`;
+ }
+
injectNode(wordObj, vid);
}
});
@@ -216,7 +235,7 @@ class chatPostprocessor{
userNode.classList.add('announcement-title');
this.chatBody.classList.add('announcement-body');
this.chatEntry.classList.add('announcement');
- }else if(this.rawData.type == "toke" || this.rawData.type == "tokewhisper"){
+ }else if(this.rawData.type == "toke"){
//Squash the high-level
this.chatEntry.querySelector('.high-level').remove();
@@ -224,7 +243,16 @@ class chatPostprocessor{
this.chatEntry.querySelector('.chat-entry-username').remove();
//Add toke/tokewhisper class
- this.chatBody.classList.add(this.rawData.type);
+ this.chatBody.classList.add("toke");
+ }else if(this.rawData.type == "tokewhisper"){
+ //Squash the high-level
+ this.chatEntry.querySelector('.high-level').remove();
+
+ //remove the username
+ this.chatEntry.querySelector('.chat-entry-username').remove();
+
+ //Add toke/tokewhisper class
+ this.chatBody.classList.add("tokewhisper","serverwhisper");
}
}
}
\ No newline at end of file
diff --git a/www/js/channel/commandPreprocessor.js b/www/js/channel/commandPreprocessor.js
index 34e2410..b5e1ec9 100644
--- a/www/js/channel/commandPreprocessor.js
+++ b/www/js/channel/commandPreprocessor.js
@@ -2,6 +2,19 @@ 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));
}
preprocess(command){
@@ -13,6 +26,7 @@ class commandPreprocessor{
if(this.sendFlag){
this.message = command;
+ this.processEmotes();
this.processLinks();
this.sendRemoteCommand();
}
@@ -38,6 +52,14 @@ class commandPreprocessor{
}
}
+ processEmotes(){
+ //Does checking each word for an emote use more or less cycles than running replace against each emote?
+ //Not sure, but it's sure as fuck easier to write it that way lmao
+ this.emotes.site.forEach((emote) => {
+ 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('␜','');
@@ -66,6 +88,25 @@ class commandPreprocessor{
this.client.socket.emit("chatMessage",{msg: this.message, links: this.links});
}
+ setSiteEmotes(data){
+ this.emotes.site = data;
+ }
+
+ getEmoteByLink(link){
+ //Create an empty variable to hold the found emote
+ var foundEmote = null;
+
+ //For every site-wide emote
+ this.emotes.site.forEach((emote) => {
+ //if we found a match
+ if(emote.link == link){
+ //return the match
+ foundEmote = emote;
+ }
+ });
+
+ return foundEmote;
+ }
}