From b8876188b1f9cdce41420fbbee78f6c55f6bda4e Mon Sep 17 00:00:00 2001
From: SileNce5k <ozzynexus@gmail.com>
Date: Sat, 3 May 2025 07:23:22 +0200
Subject: [PATCH] Add whitelist for users as well

---
 commands/admin/whitelist.js           | 137 ++++++++++++++++++--------
 server.js                             |   6 +-
 server/createAndLoadWhitelistTable.js |  77 ++++++++++++---
 server/message.js                     |  11 ++-
 4 files changed, 167 insertions(+), 64 deletions(-)

diff --git a/commands/admin/whitelist.js b/commands/admin/whitelist.js
index b5659bf..4597e0a 100644
--- a/commands/admin/whitelist.js
+++ b/commands/admin/whitelist.js
@@ -2,55 +2,106 @@ const sqlite3 = require('sqlite3').verbose();
 
 module.exports = {
     name: 'whitelist',
-    description: 'Whitelist a command in a specific server.',
+    description: 'Whitelist a command in a specific server, or for a user.',
     admin: true,
     async execute({message, args, prefix, client}) {
-        if(args.length < 2){
-            message.channel.send(`You need to supply the command and channel that you want to whitelist\n\`${prefix}whitelist <command> <server_id>\``);
+        if(args.length < 3){
+            message.channel.send(`You need to supply the command and guild that you want to whitelist\n\`${prefix}whitelist <user|guild> <command> <user_id|guild_id>\``);
             return;
         } 
-        let command = args[0];
-        let guild = args[1];
-        if(guild === "this") guild = message.guild.id;
-        // TODO: Add ability to remove server from whitelist.
-        const whitelistedCommands = client.whitelist.get(guild);
-        if(whitelistedCommands && whitelistedCommands.includes(command)){
-            message.channel.send("Command is already whitelisted in that server.")
+        let option = args[0];
+        let command = args[1];
+        let guildOrUser = args[2];
+
+        if(option === "guild" || option === "server"){
+            if(guildOrUser === "this") guildOrUser = message.guild.id;
+            const whitelistedCommands = client.whitelist.guild.get(guildOrUser);
+            if(whitelistedCommands && whitelistedCommands.includes(command)){
+                message.channel.send("Command is already whitelisted in that server.")
+                return;
+            }
+            // TODO: First check if the bot has access to that guild before whitelisting.
+            const databasePath = 'data/database.db'
+            const db = new sqlite3.Database(databasePath)
+            let err = false;
+            await new Promise((resolve, reject)=>{
+                db.run(`INSERT INTO whitelist (
+                    serverId, 
+                    command,
+                    dateAdded
+                    ) VALUES (?, ?, ?)`, 
+                    [
+                        guildOrUser,
+                        command,
+                       new Date().getTime()
+                    ], function (error) {
+                    if (error) {
+                        console.error(error);
+                        err = true;
+                        resolve();
+                    }else{
+                        resolve();
+                    }
+                });
+            })
+            db.close();
+            if(!err){
+                if(whitelistedCommands){
+                    whitelistedCommands.push(command);
+                    client.whitelist.guild.set(guildOrUser, whitelistedCommands);
+                }else {
+                    client.whitelist.guild.set(guildOrUser, command);
+                }
+                message.channel.send(`"${command}" has been whitelisted in that server.`)
+    
+            } else message.channel.send("Could not whitelist the server with that command. Check the logs.")
+            return;
+        }else if (option === "user"){
+            const whitelistedCommands = client.whitelist.user.get(guildOrUser);
+            if(whitelistedCommands && whitelistedCommands.includes(command)){
+                message.channel.send("Command is already whitelisted for that user.")
+                return;
+            }
+            const databasePath = 'data/database.db'
+            const db = new sqlite3.Database(databasePath)
+            let err = false;
+            await new Promise((resolve, reject)=>{
+                db.run(`INSERT INTO user_whitelist (
+                    userId, 
+                    command,
+                    dateAdded
+                    ) VALUES (?, ?, ?)`, 
+                    [
+                        guildOrUser,
+                        command,
+                       new Date().getTime()
+                    ], function (error) {
+                    if (error) {
+                        console.error(error);
+                        err = true;
+                        resolve();
+                    }else{
+                        resolve();
+                    }
+                });
+            })
+            db.close();
+            if(!err){
+                if(whitelistedCommands){
+                    whitelistedCommands.push(command);
+                    client.whitelist.user.set(guildOrUser, whitelistedCommands);
+                }else {
+                    client.whitelist.user.set(guildOrUser, command);
+                }
+                message.channel.send(`"${command}" has been whitelisted for ${guildOrUser}.`)
+    
+            } else message.channel.send("Could not whitelist the server with that command. Check the logs.")
             return;
         }
-        // TODO: First check if the bot has access to that guild before whitelisting.
-        const databasePath = 'data/database.db'
-        const db = new sqlite3.Database(databasePath)
-        let err = false;
-        await new Promise((resolve, reject)=>{
-            db.run(`INSERT INTO whitelist (
-                serverId, 
-                command,
-                dateAdded
-                ) VALUES (?, ?, ?)`, 
-                [
-                    guild,
-                    command,
-                   new Date().getTime()
-                ], function (error) {
-                if (error) {
-                    console.error(error);
-                    err = true;
-                    resolve();
-                }else{
-                    resolve();
-                }
-            });
-        })
-        if(!err){
-            if(whitelistedCommands){
-                whitelistedCommands.push(command);
-			    client.whitelist.set(guild, whitelistedCommands);
-            }else {
-                client.whitelist.set(guild, command);
-            }
-            message.channel.send("Command has been whitelisted in that server.")
 
-        } else message.channel.send("Could not whitelist the server with that command. Check the logs.")
+        
+
+        // TODO: Add ability to remove server from whitelist.
     }
+
 };
\ No newline at end of file
diff --git a/server.js b/server.js
index 7b53ab9..b38abe4 100644
--- a/server.js
+++ b/server.js
@@ -44,8 +44,10 @@ const {
 client.settings = new Collection();
 client.commands = new Collection();
 client.serverPrefixes = new Collection();
-client.whitelist = new Collection();
-
+client.whitelist = {
+	guild: new Collection(),
+	user: new Collection()
+}
 
 createAndLoadWhitelistTable(client.whitelist);
 
diff --git a/server/createAndLoadWhitelistTable.js b/server/createAndLoadWhitelistTable.js
index d230db1..a304045 100644
--- a/server/createAndLoadWhitelistTable.js
+++ b/server/createAndLoadWhitelistTable.js
@@ -1,34 +1,61 @@
 const sqlite3 = require('sqlite3').verbose();
 module.exports = async function (clientWhitelist) { 
     const db = new sqlite3.Database('data/database.db');
+    await createGuildWhitelist(db);
+    await createUserWhitelist(db);
+    db.close();
+    loadWhitelist(clientWhitelist);
+}
+
+async function createGuildWhitelist(db) {
     await new Promise ((resolve, reject)=>{
         db.run(
-            `CREATE TABLE IF NOT EXISTS whitelist (
+            `CREATE TABLE IF NOT EXISTS guild_whitelist (
                         Id INTEGER PRIMARY KEY AUTOINCREMENT, 
-                        serverId TEXT, 
+                        guildId TEXT, 
                         command TEXT,
                         dateAdded INTEGER)`,
             (err) => {
                 if (err) {
-                    console.error(`Error while creating table 'whitelist': ${err}`);
+                    db.close();
+                    console.error(`Error while creating table 'guild_whitelist': ${err}`);
                     reject(err);
                 } else {
-                    console.log("Table 'whitelist' created successfully.");
+                    console.log("Table 'guild_whitelist' created successfully.");
                     resolve();
                 }
-                db.close();
             }
         );
-    })
-    loadWhitelist(clientWhitelist);
+    });
+}
+async function createUserWhitelist(db) {
+    await new Promise ((resolve, reject)=>{
+        db.run(
+            `CREATE TABLE IF NOT EXISTS user_whitelist (
+                        Id INTEGER PRIMARY KEY AUTOINCREMENT, 
+                        userId TEXT, 
+                        command TEXT,
+                        dateAdded INTEGER)`,
+            (err) => {
+                if (err) {
+                    db.close();
+                    console.error(`Error while creating table 'user_whitelist': ${err}`);
+                    reject(err);
+                } else {
+                    console.log("Table 'user_whitelist' created successfully.");
+                    resolve();
+                }
+            }
+        );
+    });
 }
 
 async function loadWhitelist(clientWhitelist) {
 	const db = new sqlite3.Database('data/database.db');
-	let rows = await new Promise((resolve) => {
-		db.all(`SELECT * FROM whitelist`, function (error, rows){
+	let guildRows = await new Promise((resolve) => {
+		db.all(`SELECT * FROM guild_whitelist`, function (error, rows){
 			if(error){
-				console.error("Failed to read whitelist table")
+				console.error("Failed to read guild_whitelist table")
 				console.error(error);
 				resolve([]);
 			}else{
@@ -36,13 +63,33 @@ async function loadWhitelist(clientWhitelist) {
 			}
 		});
 	});
-	rows.forEach(row => {
-		if(clientWhitelist.has(row.serverId)){
-			let oldEntry = clientWhitelist.get(row.serverId);
+    let userRows = await new Promise((resolve) => {
+        db.all(`SELECT * FROM user_whitelist`, function (error, rows){
+            if(error){
+                console.error("Failed to read user_whitelist table")
+                console.error(error);
+                resolve([]);
+            }
+        })
+    })
+	guildRows.forEach(row => {
+		if(clientWhitelist.guild.has(row.guildId)){
+			let oldEntry = clientWhitelist.guild.get(row.guildId);
 			oldEntry.push(row.command)
-			clientWhitelist.set(row.serverId, oldEntry)
+			clientWhitelist.guild.set(row.guildId, oldEntry)
 		}else {
-			clientWhitelist.set(row.serverId, [row.command])
+			clientWhitelist.guild.set(row.guildId, [row.command])
 		}
 	});
+    userRows.forEach(row => {
+		if(clientWhitelist.user.has(row.userId)){
+			let oldEntry = clientWhitelist.user.get(row.userId);
+			oldEntry.push(row.command)
+			clientWhitelist.user.set(row.userId, oldEntry)
+		}else {
+			clientWhitelist.user.set(row.userId, [row.command])
+		}
+	});
+
+    db.close();
 }
\ No newline at end of file
diff --git a/server/message.js b/server/message.js
index a7f9244..75f21b1 100644
--- a/server/message.js
+++ b/server/message.js
@@ -21,10 +21,13 @@ module.exports = function(client, owners, message, globalPrefix){
 	const command = client.commands.get(commandName);
 	if(!command) return;
 	if(command.needsWhitelist){
-		let isWhitelisted = client.whitelist.get(message.guild.id)?.includes(command.name);
-		if(!isWhitelisted){
-			message.channel.send(`\`${command.name}\` is not whitelisted in this server. The bot admin needs to whitelist the command in this server for it to work`)
-			return;
+		let isGuildWhitelisted = client.whitelist.get(message.guild.id)?.includes(command.name);
+		if(!isGuildWhitelisted){
+			let isUserWhitelisted = client.whitelist.user.get(message.author.id)?.includes(command.name);
+			if(!isUserWhitelisted){
+				message.channel.send(`\`${command.name}\` is not whitelisted in this server. The bot admin needs to whitelist the command in this server for it to work`)
+				return;
+			}
 		}
 	}
 	if (command.admin && owners.indexOf(message.author.id.toString()) == -1) return;