Compare commits

...

2 commits

6 changed files with 255 additions and 1 deletions

View file

@ -17,6 +17,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
//Local Imports
const permissionModel = require('../../schemas/permissionSchema');
const channelModel = require('../../schemas/channel/channelSchema');
const {userModel} = require('../../schemas/user/userSchema');
/**
* Class representing global server-side chat/command processing logic
@ -113,6 +114,62 @@ class commandProcessor{
return true
}
async ignore(commandObj){
//If we wherent given a user to ignore
if(commandObj.argumentArray[1] == null){
//Silently return
return;
}
//Attempt to find user DB doc object
const userDB = await userModel.findOne({user: commandObj.socket.user.user});
//Prevent missing users
if(userDB == null){
throw loggerUtils.exceptionSmith("Called from invalid user", "validation");
}
//ignore user
await userDB.ignoreByUser(commandObj.argumentArray[1]);
//Update all users sockets on every channel
this.server.crawlConnections(commandObj.socket.user.user, (user)=>{
//syncrhonously fire and forget ignored user list
user.sendIgnoredList(userDB);
});
//disable send flag
return false;
}
async unignore(commandObj){
//If we wherent given a user to ignore
if(commandObj.argumentArray[1] == null){
//Silently return
return;
}
//Attempt to find user DB doc object
const userDB = await userModel.findOne({user: commandObj.socket.user.user});
//Prevent missing users
if(userDB == null){
throw loggerUtils.exceptionSmith("Called from invalid user", "validation");
}
//ignore user
await userDB.unignoreByUser(commandObj.argumentArray[1]);
//Update all users sockets on every channel
this.server.crawlConnections(commandObj.socket.user.user, (user)=>{
//syncrhonously fire and forget ignored user list
user.sendIgnoredList(userDB);
});
//disable send flag
return false;
}
/**
* Command Processor method to handle the '!announce' command
* @param {Object} commandObj - Object representing a single given command/chat request

View file

@ -216,6 +216,7 @@ class connectedUser{
chan: Array.from(this.permMap.chan),
},
flair: this.flair,
ignored: (await userDB.getIgnoredUsers()).user
}
//For each flair listed in the Database
@ -332,6 +333,21 @@ class connectedUser{
this.channel.broadcastUserList();
this.sendClientMetadata();
}
/**
* Sends updated ignored list to a client
* @param {Mongoose.Document} userDB - Users DB Document
*/
async sendIgnoredList(userDB){
//if we wherent handed a user document
if(userDB == null){
//Pull it based on user name
userDB = await userModel.findOne({user: this.user});
}
//Retrieve and send updated ignored users list to clients socket
this.emit("ignore", (await userDB.getIgnoredUsers()).user);
}
}
module.exports = connectedUser;

View file

@ -153,6 +153,10 @@ const userSchema = new mongoose.Schema({
type: mongoose.SchemaTypes.ObjectID,
ref: "user"
}],
ignored:[{
type: mongoose.SchemaTypes.ObjectID,
ref: "user",
}],
playlists: [playlistSchema]
});
@ -662,6 +666,136 @@ userSchema.methods.deleteEmote = async function(name){
}
}
/**
* Ignores a given user by their username
* @param {Mongoose.Document} userDB - DB Document of user to ignore
*/
userSchema.methods.ignoreByUser = async function(user){
//Pull user doc from DB
const userDB = await this.constructor.findOne({user});
//Do a ignorem user by username
await this.ignoreByUserDoc(userDB);
}
/**
* Ignores a given user by their DB Document
* @param {Mongoose.Document} userDB - DB Document of user to ignore
*/
userSchema.methods.ignoreByUserDoc = async function(userDB){
//Prevent missing users
if(userDB == null){
throw loggerUtils.exceptionSmith("User not found", "validation");
}
//if someone is trying to self-ignore
if(userDB._id.equals(this._id)){
//Remind them of the brutal truth that is reality
throw loggerUtils.exceptionSmith("YOU CANNOT ESCAPE THE PRISON THAT IS YOUR MIND!!!", "validation");
}
if(this.ignored.includes(userDB._id)){
throw loggerUtils.exceptionSmith("User already ignored", "validation");
}
//Push user into ignored array
this.ignored.push(userDB._id);
//Save the DB document
await this.save();
console.log(await this.getIgnoredUsers());
}
/**
* un-ignores a given user by their username
* @param {Mongoose.Document} userDB - DB Document of user to ignore
*/
userSchema.methods.unignoreByUser = async function(user){
//Pull user doc from DB
const userDB = await this.constructor.findOne({user});
//Do an unignorem user by username
await this.unignoreByUserDoc(userDB);
}
/**
* un-ignores a given user by their DB Document
* @param {Mongoose.Document} userDB - DB Document of user to ignore
*/
userSchema.methods.unignoreByUserDoc = async function(userDB){
//Prevent missing users
if(userDB == null){
throw loggerUtils.exceptionSmith("User not found", "validation");
}
//prevent double un-ignoring
if(!this.ignored.includes(userDB._id)){
throw loggerUtils.exceptionSmith("User not ignored", "validation");
}
//Filter user out of ignored array
this.ignored = this.ignored.filter((id)=>{return !id.equals(userDB._id)});
//Save the DB document
await this.save();
console.log(await this.getIgnoredUsers());
}
userSchema.methods.getIgnoredUsers = async function(fetchAlts = true){
//Not me commiting ancient fucking sin
const _this = this;
//Populate all ignored users
await this.populate('ignored');
//If we're fetching alts
if(fetchAlts){
//Populate ignored users alts
await this.populate('ignored.alts');
}
//Create return object to hold list of DB ids and public user IDs/names
//Code using this method typically only need either/or, so seperating them from da get-go was the easiest option.
const ignored = {
_id: [],
user: []
}
//Iterate through all ignored users
for(const ignoredUser of this.ignored){
//Push user to ignored list
pushToList(ignoredUser);
//If we're fetching alts
if(fetchAlts){
//Iterate through ignored users alts
for(const ignoredAlt of ignoredUser.alts){
//Push alt to ignored list
pushToList(ignoredAlt);
}
}
}
//Return list of ignored users
return ignored;
function pushToList(ignoredUser){
//If we haven't already added this user, and it isn't us
//ignoring our own alts seem silly at first, but remember 1 IP =/= one user.
//VPNs, CGNAT, and even household disagreements all happen in da real world.
if(!ignored._id.includes(ignoredUser._id) && !ignoredUser._id.equals(_this._id)){
//Push DB _id into list for server-side use
ignored._id.push(ignoredUser._id);
//Push ignored username/outward id combo for client usage
ignored.user.push({
user: ignoredUser.user,
id: ignoredUser.id
});
}
}
}
/**
* Salts, Hashes and Tattoo's IP address to user document in a privacy respecting manner
* @param {String} ip - Plaintext IP Address to Salt, Hash and Tattoo

View file

@ -129,7 +129,9 @@ class channel{
this.socket.on("archive", (data) =>{
this.sortQueue(data.archive);
})
});
this.socket.on("ignore", this.handleIgnoredList.bind(this));
}
/**
@ -169,6 +171,21 @@ class channel{
this.streamType = data.streamType;
}
/**
* Updated ignore list
* @param {Array} data - Ignore list received from server
*/
handleIgnoredList(data){
//Update ignored users list
this.user.ignored = data;
//If we have the chatbox loaded in
if(this.chatBox != null){
//Re-render buffer
this.chatBox.rerenderBuffer();
}
}
/**
* Sorts queue, optionally adding new items along the way
* @param {object} queueData - Contains list of entries to add to the queue

View file

@ -229,6 +229,16 @@ class chatBox{
* @param {Object} data De-hydrated chat object from server
*/
displayChat(data){
//For every douchebag in the ignored users list
for(const douchebag of this.client.user.ignored){
//If this message is from the douchebag in question
if(data.user == douchebag.user){
//tell it to fuck off and die
return;
}
}
//Append the post-processed chat-body to the chat buffer
this.chatBuffer.appendChild(this.chatPostprocessor.postprocess(data));

View file

@ -196,6 +196,26 @@ class userList{
]);
if(user.user != "Tokebot" && user.user != this.client.user.user){
let ignored = false;
//For each douchebag in the ignored users list
for(const douchebag of this.client.user.ignored){
if(douchebag.user == user.user){
/* Normally I abhor making if statements to set booleans, but this only need to happen when its true
Plus I also needed to put the break statement somewhere
The fucked thing is the break statement isnt necissary with the if statement, but without it it becomes necissary
But it cant be used without the if statement, making the task of reducing linecount for this definition a fucking sisyphean nightmare */
ignored = true;
break;
}
}
if(ignored){
menuMap.set("Unignore", ()=>{this.client.chatBox.transmit(`!unignore ${user.user}`);});
}else{
menuMap.set("Ignore", ()=>{this.client.chatBox.transmit(`!ignore ${user.user}`);});
}
if(this.client.user.permMap.chan.get("kickUser")){
menuMap.set("Kick", ()=>{this.client.chatBox.transmit(`!kick ${user.user}`);});
}