forgot to add files
diff --git a/src/actions/roleMenu.ts b/src/actions/roleMenu.ts
new file mode 100644
index 0000000..a4397a3
--- /dev/null
+++ b/src/actions/roleMenu.ts
@@ -0,0 +1,157 @@
+import { Message, MessageButton } from "discord.js";
+import EmojiEmbed from '../utils/generateEmojiEmbed.js'
+import { MessageActionRow, MessageSelectMenu } from 'discord.js';
+import getEmojiByName from "../utils/getEmojiByName.js";
+import client from "../utils/client.js";
+
+export async function callback(interaction) {
+    let config = await client.database.guilds.read(interaction.guild.id);
+    if (!config.roleMenu.enabled) return await interaction.reply({embeds: [new EmojiEmbed()
+        .setTitle("Roles")
+        .setDescription("Self roles are currently disabled. Please contact a staff member or try again later.")
+        .setStatus("Danger")
+        .setEmoji("CONTROL.BLOCKCROSS")
+    ], ephemeral: true})
+    if (config.roleMenu.options.length === 0) return await interaction.reply({embeds: [new EmojiEmbed()
+        .setTitle("Roles")
+        .setDescription("There are no roles available. Please contact a staff member or try again later.")
+        .setStatus("Danger")
+        .setEmoji("CONTROL.BLOCKCROSS")
+    ], ephemeral: true})
+    await interaction.reply({embeds: [new EmojiEmbed()
+        .setTitle("Roles")
+        .setDescription("Loading...")
+        .setStatus("Success")
+        .setEmoji("NUCLEUS.LOADING")
+    ], ephemeral: true})
+    let m;
+    if (config.roleMenu.allowWebUI) {
+        let code = ""
+        let length = 5
+        let itt = 0
+        const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+        while (true) {
+            itt += 1
+            code = ""
+            for (let i = 0; i < length; i++) { code += chars.charAt(Math.floor(Math.random() * chars.length)); }
+            if (code in client.roleMenu) continue;
+            if (itt > 1000) {
+                itt = 0
+                length += 1
+                continue;
+            }
+            break;
+        }
+        client.roleMenu[code] = {
+            guild: interaction.guild.id,
+            guildName: interaction.guild.name,
+            guildIcon: interaction.guild.iconURL({format: "png"}),
+            user: interaction.member.user.id,
+            username: interaction.member.user.username,
+            data: config.roleMenu.options,
+            interaction: interaction
+        };
+        let up = true
+        try {
+            let status = await fetch(client.config.baseUrl).then(res => res.status);
+            if (status != 200) up = false
+        } catch { up = false }
+        m = await interaction.editReply({
+            embeds: [new EmojiEmbed()
+                .setTitle("Roles")
+                .setDescription("Select how to choose your roles")
+                .setStatus("Success")
+                .setEmoji("GUILD.GREEN")
+            ], components: [new MessageActionRow().addComponents([
+                new MessageButton()
+                    .setLabel("Online")
+                    .setStyle("LINK")
+                    .setDisabled(!up)
+                    .setURL(`${client.config.baseUrl}/nucleus/rolemenu?code=${code}`),
+                new MessageButton()
+                    .setLabel("Manual")
+                    .setStyle("PRIMARY")
+                    .setCustomId("manual")
+            ])]
+        })
+    }
+    let component;
+    try { component = await (m as Message).awaitMessageComponent({time: 300000});
+    } catch (e) { return }
+    component.deferUpdate()
+    let rolesToAdd = []
+    for (let i = 0; i < config.roleMenu.options.length; i++) {
+        let object = config.roleMenu.options[i];
+        let m = await interaction.editReply({
+            embeds: [
+                new EmojiEmbed()
+                    .setTitle("Roles")
+                    .setEmoji("GUILD.GREEN")
+                    .setDescription(`**${object.name}**` + (object.description ? `\n${object.description}` : ``) +
+                        `\n\nSelect ${object.min}` + (object.min != object.max ? ` to ${object.max}` : ``) + ` role${object.max == 1 ? '' : 's'} to add.`)
+                    .setStatus("Success")
+                    .setFooter({text: `Step ${i + 1}/${config.roleMenu.options.length}`})
+            ],
+            components: [
+                new MessageActionRow().addComponents([
+                    new MessageButton()
+                        .setLabel("Cancel")
+                        .setStyle("DANGER")
+                        .setCustomId("cancel")
+                        .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
+                    ].concat(object.min == 0 ? [
+                        new MessageButton()
+                            .setLabel("Skip")
+                            .setStyle("SECONDARY")
+                            .setCustomId("skip")
+                            .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
+                        ] : []))
+            ].concat([new MessageActionRow().addComponents([new MessageSelectMenu()
+                .setPlaceholder(`${object.name}`)
+                .setCustomId("rolemenu")
+                .setMinValues(object.min)
+                .setMaxValues(object.max)
+                .setOptions(object.options.map(o => { return {label: o.name, description: o.description, value: o.role} }))
+            ])])
+        });
+        let component;
+        try {
+            component = await (m as Message).awaitMessageComponent({time: 300000});
+        } catch (e) {
+            return
+        }
+        component.deferUpdate()
+        if (component.customId == "rolemenu") {
+            rolesToAdd = rolesToAdd.concat(component.values)
+        } else if (component.customId == "cancel") {
+            return await interaction.editReply({embeds: [new EmojiEmbed()
+                .setTitle("Roles")
+                .setDescription("Cancelled. No changes were made.")
+                .setStatus("Danger")
+                .setEmoji("GUILD.RED")
+            ], components: []})
+        }
+    }
+    let rolesToRemove = config.roleMenu.options.map(o => o.options.map(o => o.role)).flat()
+    let memberRoles = interaction.member.roles.cache.map(r => r.id)
+    rolesToRemove = rolesToRemove.filter(r => memberRoles.includes(r)).filter(r => !rolesToAdd.includes(r))
+    rolesToAdd = rolesToAdd.filter(r => !memberRoles.includes(r))
+    try {
+        await interaction.member.roles.remove(rolesToRemove)
+        await interaction.member.roles.add(rolesToAdd)
+    } catch (e) {
+        return await interaction.reply({embeds: [new EmojiEmbed()
+            .setTitle("Roles")
+            .setDescription("Something went wrong and your roles were not added. Please contact a staff member or try again later.")
+            .setStatus("Danger")
+            .setEmoji("GUILD.RED")
+        ], components: []})
+    }
+    await interaction.editReply({embeds: [new EmojiEmbed()
+        .setTitle("Roles")
+        .setDescription("Roles have been added. You may close this message.")
+        .setStatus("Success")
+        .setEmoji("GUILD.GREEN")
+    ], components: []})
+    return
+}