I hereby decree that this document shall no longer contain the substring " == ", and hereafter shall be referred to as " === ". This amendment shall take effect immediately.

Signed-off-by: pineafan <pineapplefanyt@gmail.com>
diff --git a/src/Unfinished/all.ts b/src/Unfinished/all.ts
index 05eb603..5c482f1 100644
--- a/src/Unfinished/all.ts
+++ b/src/Unfinished/all.ts
@@ -1,3 +1,4 @@
+import { LoadingEmbed } from './../utils/defaultEmbeds.js';
 import Discord, { CommandInteraction, GuildMember, MessageActionRow, MessageButton, MessageSelectMenu } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
@@ -78,12 +79,7 @@
 }
 
 const callback = async (interaction: CommandInteraction) => {
-    await interaction.reply({embeds: [new EmojiEmbed()
-        .setTitle("Role all")
-        .setDescription("Loading...")
-        .setStatus("Danger")
-        .setEmoji("NUCLEUS.LOADING")
-    ], ephemeral: true, fetchReply: true})
+    await interaction.reply({embeds: LoadingEmbed, ephemeral: true, fetchReply: true})
     let filters: Filter[] = [
         filterList.member.has.role("959901346000154674"),
         filterList.member.nickname.startsWith("Pinea"),
@@ -112,7 +108,7 @@
             .setDescription((all ? "All of the following must be true:" : "Any of the following must be true") + "\n" +
                 filters.map((f) => {
                     count ++;
-                    return (count == 1 ? getEmojiByName("ICONS.FILTER") : (all ? "**and** " : "**or** ")) +
+                    return (count === 1 ? getEmojiByName("ICONS.FILTER") : (all ? "**and** " : "**or** ")) +
                         (f.inverted ? "**not** " : "") + `${f.name}`
                 }).join("\n") + "\n\n" + `This will affect ${addPlural(affected.length, "member")}`)
             .setEmoji("GUILD.ROLES.CREATE")
@@ -144,11 +140,11 @@
 const check = async (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
     let member = (interaction.member as GuildMember)
     let me = (interaction.guild.me as GuildMember)
-    if (!me.permissions.has("MANAGE_ROLES")) throw "I do not have the Manage roles permission";
+    if (!me.permissions.has("MANAGE_ROLES")) throw "I do not have the *Manage Roles* permission";
     // Allow the owner to role anyone
-    if (member.id == interaction.guild.ownerId) return true
+    if (member.id === interaction.guild.ownerId) return true
     // Check if the user has manage_roles permission
-    if (! member.permissions.has("MANAGE_ROLES")) throw "You do not have the Manage roles permission";
+    if (! member.permissions.has("MANAGE_ROLES")) throw "You do not have the *Manage Roles* permission";
     // Allow role
     return true;
 }
diff --git a/src/Unfinished/categorisationTest.ts b/src/Unfinished/categorisationTest.ts
new file mode 100644
index 0000000..c75d1bb
--- /dev/null
+++ b/src/Unfinished/categorisationTest.ts
@@ -0,0 +1,98 @@
+import { LoadingEmbed } from '../utils/defaultEmbeds.js';
+import { CommandInteraction, GuildChannel, MessageActionRow, MessageButton, MessageSelectMenu } from "discord.js";
+import { SlashCommandBuilder } from "@discordjs/builders";
+import { WrappedCheck } from "jshaiku";
+import EmojiEmbed from "../utils/generateEmojiEmbed.js";
+import client from "../utils/client.js"
+import addPlural from "../utils/plurals.js";
+import getEmojiByName from "../utils/getEmojiByName.js";
+
+const command = new SlashCommandBuilder()
+    .setName("categorise")
+    .setDescription("Categorises your servers channels")
+
+const callback = async (interaction: CommandInteraction): Promise<any> => {
+    let channels = interaction.guild.channels.cache.filter(c => c.type !== "GUILD_CATEGORY");
+    let categorised = {}
+    await interaction.reply({embeds: LoadingEmbed, ephemeral: true});
+    let predicted = {}
+    let types = {
+        general: ["general", "muted", "main", "topic", "discuss"],
+        commands: ["bot", "command", "music"],
+        images: ["pic", "selfies", "image"],
+        nsfw: ["porn", "nsfw", "sex"],
+        links: ["links"],
+        advertising: ["ads", "advert", "server", "partner"],
+        staff: ["staff", "mod", "admin"],
+        spam: ["spam"],
+        other: ["random"]
+    }
+    for (let c of channels.values()) {
+        for (let type in types) {
+            for (let word of types[type]) {
+                if (c.name.toLowerCase().includes(word)) {
+                    predicted[c.id] = predicted[c.id] ?? []
+                    predicted[c.id].push(type)
+                }
+            }
+        }
+    }
+    let m;
+    for (let c of channels) {
+        // convert channel to a channel if its a string
+        let channel: any
+        if (typeof c === "string") channel = interaction.guild.channels.cache.get(channel).id
+        else channel = (c[0] as unknown as GuildChannel).id
+        console.log(channel)
+        if (!predicted[channel]) predicted[channel] = []
+        m = await interaction.editReply({embeds: [new EmojiEmbed()
+            .setTitle("Categorise")
+            .setDescription(`Select all types that apply to <#${channel}>.\n\n` +
+            `${addPlural(predicted[channel].length, "Suggestion")}: ${predicted[channel].join(", ")}`)
+            .setEmoji("CHANNEL.CATEGORY.CREATE")
+            .setStatus("Success")
+        ], components: [
+            new MessageActionRow().addComponents([new MessageSelectMenu()
+                .setCustomId("selected")
+                .setMaxValues(Object.keys(types).length)
+                .setMinValues(1)
+                .setPlaceholder("Select all types that apply to this channel")
+                .setOptions(Object.keys(types).map(type => ({label: type, value: type})))
+            ]),
+            new MessageActionRow().addComponents([
+                new MessageButton().setLabel("Accept Suggestion").setCustomId("accept").setStyle("SUCCESS").setDisabled(predicted[channel].length === 0)
+                    .setEmoji(client.emojis.cache.get(getEmojiByName("ICONS.TICK", "id"))),
+                new MessageButton().setLabel("Use \"Other\"").setCustomId("reject").setStyle("SECONDARY")
+                    .setEmoji(client.emojis.cache.get(getEmojiByName("ICONS.CROSS", "id")))
+            ])
+        ]})
+        let i;
+        try {
+            i = await m.awaitMessageComponent({ time: 300000 });
+        } catch (e) {
+            return await interaction.editReply({embeds: [new EmojiEmbed()
+                .setTitle("Categorise")
+                .setEmoji("CHANNEL.CATEGORY.DELETE")
+                .setStatus("Danger")
+                .setDescription(`Select all types that apply to <#${channel}>.\n\n` +
+                `${addPlural(predicted[channel].length, "Suggestion")}: ${predicted[channel].join(", ")}`)
+                .setFooter({text: "Message timed out"})
+            ]})
+        }
+        i.deferUpdate()
+        let selected;
+        if (i.customId === "select") { selected = i.values; }
+        if (i.customId === "accept") { selected = predicted[channel]; }
+        if (i.customId === "reject") { selected = ["other"]; }
+        categorised[channel] = selected
+    }
+    console.log(categorised)
+}
+
+const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
+    return true;
+}
+
+export { command };
+export { callback };
+export { check };
\ No newline at end of file