From b2c6c705c301d5883a073ccd9b019fa9dcd416d0 Mon Sep 17 00:00:00 2001
From: SileNce5k <ozzynexus@gmail.com>
Date: Sun, 4 May 2025 03:58:11 +0200
Subject: [PATCH] Add more types of whitelisting, plus support for subcommands

---
 commands/misc/fm.js         |  7 +++++++
 server/message.js           | 13 ++++---------
 tests/isWhitelisted.test.js | 30 ++++++++++++++++++++++++++++++
 util/isWhitelisted.js       | 22 ++++++++++++++++++++++
 4 files changed, 63 insertions(+), 9 deletions(-)
 create mode 100644 tests/isWhitelisted.test.js
 create mode 100644 util/isWhitelisted.js

diff --git a/commands/misc/fm.js b/commands/misc/fm.js
index c3a0089..8d07401 100644
--- a/commands/misc/fm.js
+++ b/commands/misc/fm.js
@@ -9,6 +9,7 @@ const getTopArtists = require("../../util/lastfm/getTopArtists");
 const getTopAlbums = require("../../util/lastfm/getTopAlbums");
 const {EmbedBuilder} = require('discord.js');
 const getNickname = require('../../util/getNickname');
+const isWhitelisted = require("../../util/isWhitelisted");
 module.exports = {
     name: 'fm',
     description: 'Last fm commands. See `<prefix>help fm` for more info.',
@@ -38,8 +39,14 @@ module.exports = {
                 sendText = await getCurrentCover(message.author.id, message.guild);
                 break;
             case "roast":
+                const commandName = "fmroast"
+                if(!isWhitelisted.isWhitelisted(commandName, client.whitelist, message.guild.id, message.author.id, isWhitelisted.whitelistTypes.EITHER)) {
+                    message.channel.send("fmroast has not been whitelisted for you or this server.")    
+                    return;
+                }
                 let topArtists = await getTopArtists(message.author.id, ["yearly"], message.guild, true);
                 let topAlbums = await getTopAlbums(message.author.id, ["yearly"], message.guild, true);
+                message.channel.sendTyping();
                 let result = await roast(topArtists, topAlbums);
 
                 let parse = parseMention(message.author.id, message.guild)
diff --git a/server/message.js b/server/message.js
index 75f21b1..08d860d 100644
--- a/server/message.js
+++ b/server/message.js
@@ -1,3 +1,4 @@
+const isWhitelisted = require('../util/isWhitelisted')
 module.exports = function(client, owners, message, globalPrefix){
 	let prefix = globalPrefix;
 	let serverPrefix = client.serverPrefixes.get(message.guild.id);
@@ -20,15 +21,9 @@ module.exports = function(client, owners, message, globalPrefix){
 	const commandName = args.shift().toLowerCase();
 	const command = client.commands.get(commandName);
 	if(!command) return;
-	if(command.needsWhitelist){
-		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.needsWhitelist && !isWhitelisted.isWhitelisted(command.name, client.whitelist, message.guild.id, message.author.id, isWhitelisted.whitelistTypes.EITHER)){
+		message.channel.send(`\`${command.name}\` is not whitelisted for you or this server. The bot admin needs to whitelist the command for you or this server.`)
+		return;
 	}
 	if (command.admin && owners.indexOf(message.author.id.toString()) == -1) return;
 	try {
diff --git a/tests/isWhitelisted.test.js b/tests/isWhitelisted.test.js
new file mode 100644
index 0000000..c955f4d
--- /dev/null
+++ b/tests/isWhitelisted.test.js
@@ -0,0 +1,30 @@
+const isWhitelisted = require('../util/isWhitelisted');
+
+const whitelist = {
+    guild: new Map(),
+    user: new Map()
+}
+whitelist.guild.set(20, ["test1", "test3"]);
+whitelist.guild.set(21, ["test2", "test4"]);
+whitelist.user.set(1001, ["test1", "test3"]);
+whitelist.user.set(1002, ["test2", "test4"]);
+
+test('Test isWhitelisted', () => {
+        expect(isWhitelisted.isWhitelisted("test1", whitelist, 20, 1001, isWhitelisted.whitelistTypes.BOTH)).toBe(true);
+        expect(isWhitelisted.isWhitelisted("test3", whitelist, 20, 1002, isWhitelisted.whitelistTypes.BOTH)).toBe(false);
+        expect(isWhitelisted.isWhitelisted("test3", whitelist, 21, 1001, isWhitelisted.whitelistTypes.BOTH)).toBe(false);
+
+        expect(isWhitelisted.isWhitelisted("test1", whitelist, 20, 1001, isWhitelisted.whitelistTypes.USER_ONLY)).toBe(true);
+        expect(isWhitelisted.isWhitelisted("test1", whitelist, 21, 1001, isWhitelisted.whitelistTypes.USER_ONLY)).toBe(true);
+        expect(isWhitelisted.isWhitelisted("test1", whitelist, 20, 1002, isWhitelisted.whitelistTypes.USER_ONLY)).toBe(false);
+
+        expect(isWhitelisted.isWhitelisted("test4", whitelist, 20, 1001, isWhitelisted.whitelistTypes.GUILD_ONLY)).toBe(false);
+        expect(isWhitelisted.isWhitelisted("test4", whitelist, 21, 1001, isWhitelisted.whitelistTypes.GUILD_ONLY)).toBe(true);
+        expect(isWhitelisted.isWhitelisted("test4", whitelist, 21, 1002, isWhitelisted.whitelistTypes.GUILD_ONLY)).toBe(true);
+
+        expect(isWhitelisted.isWhitelisted("test1", whitelist, 20, 1002, isWhitelisted.whitelistTypes.EITHER)).toBe(true);
+        expect(isWhitelisted.isWhitelisted("test2", whitelist, 20, 1002, isWhitelisted.whitelistTypes.EITHER)).toBe(true);
+        expect(isWhitelisted.isWhitelisted("test3", whitelist, 21, 1001, isWhitelisted.whitelistTypes.EITHER)).toBe(true);
+        expect(isWhitelisted.isWhitelisted("test4", whitelist, 20, 1001, isWhitelisted.whitelistTypes.EITHER)).toBe(false);
+        
+});
diff --git a/util/isWhitelisted.js b/util/isWhitelisted.js
new file mode 100644
index 0000000..8a99056
--- /dev/null
+++ b/util/isWhitelisted.js
@@ -0,0 +1,22 @@
+// type: 0 for both, 1 for guild, 2 for userId, 3 for either.
+function isWhitelisted(command, whitelist, guildId, userId, type=0){
+    const isGuildWhitelisted = Boolean(whitelist.guild.get(guildId)?.includes(command))
+    if(type === whitelistTypes.GUILD_ONLY) return isGuildWhitelisted;
+    if(type === whitelistTypes.BOTH && !isGuildWhitelisted) return false;
+    if(type === whitelistTypes.EITHER && isGuildWhitelisted) return true;
+    const isUserWhitelisted = Boolean(whitelist.user.get(userId)?.includes(command))
+    if(type === whitelistTypes.USER_ONLY) return isUserWhitelisted;
+    if(type === whitelistTypes.BOTH && isGuildWhitelisted && isUserWhitelisted) return true;
+    if(type === whitelistTypes.EITHER && (isGuildWhitelisted || isUserWhitelisted)) return true;
+    return false;
+}
+
+const whitelistTypes = {
+    BOTH: 0,
+    GUILD_ONLY: 1,
+    USER_ONLY: 2,
+    EITHER: 3
+}
+
+
+module.exports = {isWhitelisted, whitelistTypes}
\ No newline at end of file