diff --git a/.gitignore b/.gitignore index d5e4f15..2358922 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ -**/__pycache__ \ No newline at end of file +**/__pycache__ +.vscode +.env +node_modules +unused-commands +d.py/ \ No newline at end of file diff --git a/README.md b/README.md index b2716e5..059fd17 100644 --- a/README.md +++ b/README.md @@ -2,35 +2,20 @@ ## Table of Contents -1. [Prerequisites](#prerequisites) -2. [Setting up the bot](#setting-up-the-bot) -3. [Project structure](#project-structure) -4. [Features](#features) -5. [Resources](#resources) +1. [WARNING](#warning) +2. [Prerequisites](#prerequisites) +3. [Setting up the bot](#setting-up-the-bot) +4. [Project structure](#project-structure) +5. [Features](#features) +6. [Resources](#resources) -## Prerequisites +## warning -**Python 3.8 or later is required to run this bot.** To check your python version, open a terminal and run: -```bash -$ python --version -``` -You can also try: -```bash -$ python2 --version -``` -and -```bash -$ python3 --version -``` -Out of those three, use the interpreter of a version that is equal or higher than the one mentioned above. If you do not have the correct version, [you can download it here.](https://www.python.org/downloads/release/python-3105/) +This branch is **NOT** ready for production use. Do not use it. No support is provided at this time. -**Once that's done, [download Discord.py here](https://discordpy.readthedocs.io/en/stable/intro.html).** Make sure you get the most recent **stable** version, which is v.1.7.4. The available versions can be viewed by clicking a dropdown in the lower right corner of the webpage. +## Prerequisites -Next, clone the project to a folder on your machine: -```bash -git clone https://github.com/llisaeva/CSSC-Bot.git -``` -If you don't have git, you can either download the project as a zip file **(Code > Download ZIP)**, or [download git](https://git-scm.com/downloads). +TBD - This branch is a complete rewrite of the existing codebase so no prerequisites are provided yet. **You will need a server to test the bot on. Create your own 'private' Discord server.** @@ -60,120 +45,39 @@ On your new bots page, select **Reset Token**. Once the new token appears, copy ![Step #6](/demo/6.jpg) -In the project folder, open the **tkn.py** file. Paste the token between the quotes next to the TOKEN variable. - -```python -TOKEN="<paste your token here>" -``` +In the project folder, create a file called **.env**. +Fill it out using the template in **.env.template**. **Why you should keep your bot token a secret**: a bot token is used to attach a script to your bot. If someone has your bot token, they can control your bot with any script they attach to it. If you want your own remote branch in this project, **please do not commit changes to this file.** -The **MAKER** variable in **tkn.py** is used to associate the bot with an author - you can replace the ID with your own (but do not commit the change). This bot has a command that will DM your ID, check the [Features](#features) section. - After that is done, generate a URL for your bot. Select **OAuth2** from the left menu, and click **URL Generator**. Choose the **bot** checkbox, and select the **Administrator** checkbox in the section that appears. Copy the URL at the bottom of the page. ![Step #7](/demo/7.jpg) Follow this link in a browser, and choose the private server you created to add your bot to. Go to the project folder, and run -```py -python rolebot.py -``` -(replace *python* with the interpreter that has the correct version from the first step) - -The bot should become responsive. You can check for errors in **logs/bot.txt**. - - -## Project Structure - -All python files are located in the **modules** folder, the only exception is **rolebot.py** - it is the interface of the bot. - -**modules/logger.py** - code for logging errors for this project. There are 3 log files: **logs/bot.txt**, **logs/discord.txt**, and **logs/server.txt**. bot.txt is used for errors caused by the bot, discord.txt is used for errors that are sent from your Discord server, and server.txt is used for errors logged by the machine the bot is running on. Nothing in the project links to the last file, it's just a place that I use to dump errors from the physical server. - -**modules/persistance.py** - used for creating json files that need to be persisted. Currently, it keeps track of the IDs of the messages that the bot creates. This makes those messages accessable by the bot after it reboots. The message ID JSON file is stored at **json/msg_ids.json**. - -**modules/role_poll.py** - module for the role reaction polls. There are two, one for selecting a college year, and another for choosing an occupation at UWM. The role reaction poll options are represented by objects that extend `ReactionPoll`. `ReactionPoll` is a custom base class, its purpose is to keep all reaction polls in the same format. The existing classes that extend it are `CollegeYearPoll` and `CollegeStaffPoll`. You can add a new reaction poll by creating a key, extending the `ReactionPoll` class, and editing the `polls` variable, like so: - -```python - -MY_NEW_POLL_KEY = "new_poll_key" - -class MyNewPoll(ReactionPoll): - pass - -polls = { - - ..., - - MY_NEW_POLL_KEY: - { - TITLE: "New Poll", - DESCRIPTION: "This is your description:", - OPTIONS: - [ - MyNewPoll("#1", 0xaaa, "🙂", "yay"), - MyNewPoll("#2", 0xccc, "😐", "meh"), - MyNewPoll("#3", 0xeee, "🙁", "boo"), - ] - } -} - +```bash +npm install +npm install -g typescript ts-node +ts-node index.ts ``` -This will assign the roles `#1`, `#2` or `#3` to the user that selects the corresponding reaction. Their colors will be `0xaaa`, `0xccc` and `0xeee`. If those roles do not exist on the server, they will be created (when checking for an existing role, only the name is matched - color is used during role creation by the bot). The last parameter needs to be unique among all polls, it is used to assign a role to a user with a command. +Alternately a Docker image will be provided soon for more reliable operation. -The base `ReactionPoll` class has one function `assign()` that can be overridden. It assigns the role that it represents to the argument **member** from the argument **server** (Guild). The `CollegeYearPoll` overrides this to make sure that the member only has one college year. +The bot should become responsive. You can check for errors in the console. -**modules/utils.py** - this file is for utility functions. Currently, it has one, it is used to find the argument `roleName` in the argument `guild` (server). If it is not found, then a role named by the argument `roleName` of the argument `roleColor` color will be created in the argument `guild`. The new or retrieved role is returned. -**tkn.py** - contains the bot token and the authors ID. - -**txt/cmds.txt** - the content that is displayed when the user wants to find out what commands can be used with the bot. The **txt** folder should contain all of the project's text files that are used for displaying content. - -**img** - contains project images. - -**demo** - contains content for the README.md file. +## Project Structure -**json** - folder that contains persisted JSON files. **json/msg_ids.json** has the IDs of all of the messages that this bot posts, this makes those messages accessible by the bot after it reboots. **modules/persistance.py** should be used to create the JSON files. +TBD - This branch is a complete rewrite of the existing codebase so no structure is provided yet. ## Features -The commands work on Discord servers and in private messages sent to the bot. However, it cannot assign roles inside of DMs. To assign roles, the command for role assignment must be sent in a Discord server where the roles can be created (this is possible to change). - -**$cmds** - list the commands that can be used with this bot - -**$poll collegeYear** - post a college year reaction poll. All active polls made by this bot work, you can use this to summon a poll anywhere for newcomers. - -![College Year Poll](demo/college-year-poll.png) - -**$poll collegeStaff** - post a college occupation reaction poll. - -![College Staff Poll](demo/college-staff-poll.png) - -The bot only resonds to the event when a reaction **is added**. Currently, nothing happens when a reaction is removed. - -**$assign role** - assign yourself a role, where **role** is: *prefrosh*, *freshman*, *sophomore*, *junior*, *senior*, *gradstudent*, *alumni*, *professor*, *tutor*, *ta*, *sileader* - -**$assign clear** - this will only clear the roles mentioned above, **not** any special roles, like *leet gamer* or *club mod* - -**$dm id** - make the bot DM your ID. This can be assigned to -the `MAKER` variable in **tkn.py**, which will make all of the -maker commands accessible only by you. This command is not a -maker command. - -### **Maker commands** -These can only be used by an account with an ID that matches `MAKER` in **tkn.py**. You can -change the `MAKER` ID to your own ID. - -**$dm botlogs** - DMs logs/bot.txt - -**$dm discordlogs** - DMs logs/discord.txt - -**$dm serverlogs** - DMs logs/server.txt -**$die** - shuts down the bot +TBD - This branch is a complete rewrite of the existing codebase so no feature explanations are provided yet. ## Resources - - [Discord.py Tutorial](https://discordpy.readthedocs.io/en/stable/ext/commands/commands.html) - - [Discord.py API](https://discordpy.readthedocs.io/en/stable/api.html) \ No newline at end of file + - [Discord.js Docs](https://discord.js.org/#/docs) + - [WOKcommands Docs](https://docs.wornoffkeys.com/) + - [AntaresBot Codebase](https://playantares.com/antaresbot) \ No newline at end of file diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..67b6117 --- /dev/null +++ b/TODO.md @@ -0,0 +1,9 @@ +**TODO** +- Add validation that roles exist in the server +- Add code to create roles that do not exist in the server if required +- Add error checking anytime roles are accessed +- Add error checking where necessary +- Add a few other misc features +- Remove lots of unoptimized and duplicate code. Refactor functions that can be refactored. +- When WOKCommands [updates to Discord.js v14](https://github.com/AlexzanderFlores/WOKCommands/issues/228), update WOKcommands +- Add logging for most functions \ No newline at end of file diff --git a/commands/owner/staffPoll.ts b/commands/owner/staffPoll.ts new file mode 100644 index 0000000..59cea14 --- /dev/null +++ b/commands/owner/staffPoll.ts @@ -0,0 +1,57 @@ +import { MessageEmbed, MessageActionRow, MessageSelectMenu } from "discord.js"; +import { ICommand } from "wokcommands"; + +export default { + name: "staffPoll", + category: "owner", + description: "Posts the College Staff Poll", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["SEND_MESSAGES"], + ownerOnly: true, + + callback: async ({ client, interaction: msgInt }) => { + // Define embeds used in this command + const infoEmbed = new MessageEmbed() + .setTitle("Choose a role") + .setColor("#0099ff") + .setDescription("Select the option with your current occupation at UWM.") + .setFooter({ + text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, + iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", + }); + + // Create row one of the buttons for the poll + const row = new MessageActionRow().addComponents( + new MessageSelectMenu() + .setCustomId("collegeStaffPoll") + .setPlaceholder("Select an option") + .addOptions( + { + label: "Tutor", + value: "tutor", + }, + { + label: "SI Leader", + value: "sileader", + }, + { + label: "TA", + value: "ta", + }, + { + label: "Professor", + value: "professor", + }, + { + label: "Student Employee", + value: "studentemployee", + } + ) + ); + + // Send the embed and message component rows + msgInt.reply({ embeds: [infoEmbed], components: [row] }); + }, +} as ICommand; diff --git a/commands/owner/yearPoll.ts b/commands/owner/yearPoll.ts new file mode 100644 index 0000000..ea88d7c --- /dev/null +++ b/commands/owner/yearPoll.ts @@ -0,0 +1,66 @@ +import { MessageEmbed, MessageActionRow, MessageSelectMenu } from "discord.js"; +import { ICommand } from "wokcommands"; + +export default { + name: "yearPoll", + category: "owner", + description: "Posts the College Year Poll", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["SEND_MESSAGES"], + ownerOnly: true, + + callback: async ({ client, interaction: msgInt }) => { + // Define embeds used in this command + const infoEmbed = new MessageEmbed() + .setTitle("Choose a role") + .setColor("#0099ff") + .setDescription("Select the button with your current college year.") + .setFooter({ + text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, + iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", + }); + + + // Create row one of the buttons for the poll + const row = new MessageActionRow().addComponents( + new MessageSelectMenu() + .setCustomId("collegeYearPoll") + .setPlaceholder("Select an option.") + .addOptions( + { + label: "Prefrosh", + value: "prefrosh", + }, + { + label: "Freshman", + value: "freshman", + }, + { + label: "Sophomore", + value: "sophomore", + }, + { + label: "Junior", + value: "junior", + }, + { + label: "Senior", + value: "senior", + }, + { + label: "Graduate Student", + value: "graduatestudent", + }, + { + label: "Alumni", + value: "alumni", + } + ) + ); + + // Send the embed and message component rows + msgInt.reply({ embeds: [infoEmbed], components: [row] }); + }, +} as ICommand; diff --git a/commands/user/clearRoles.ts b/commands/user/clearRoles.ts new file mode 100644 index 0000000..039adcf --- /dev/null +++ b/commands/user/clearRoles.ts @@ -0,0 +1,24 @@ +import { GuildMember } from "discord.js"; +import { ICommand } from "wokcommands"; +import { returnRoles as roleDictionary } from "../../definitions"; +import { removePrevRole } from "../../rolesOps"; + +export default { + name: "clear", + category: "user", + description: "removes all roles the bot has assigned to a user", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["SEND_MESSAGES"], + + callback: async ({ interaction }) => { + // Remove roles from user + if (!interaction.member) return; + const member = interaction.member as GuildMember; + removePrevRole(member, 0); + removePrevRole(member, 1); + // Reply to the user + interaction.reply({ content: "Cleared all roles that I have assigned to you.", ephemeral: true }); + }, +} as ICommand; diff --git a/commands/user/github.ts b/commands/user/github.ts new file mode 100644 index 0000000..577aac3 --- /dev/null +++ b/commands/user/github.ts @@ -0,0 +1,32 @@ +import { MessageEmbed, TextChannel } from "discord.js"; +import { ICommand } from "wokcommands"; + +export default { + name: "github", + category: "user", + description: "Sends an embed with a link to the github repo for the bot.", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["SEND_MESSAGES"], + + callback: async ({ client, interaction }) => { + // Embed values + const color = "#0099ff"; + const thumbnail = "https://playantares.com/resources/CSSC-bot/cssc-server-icon.png"; + const title = "Github"; + const description = "Click here to go to the CSSC-bot repo: \n https://github.com/llisaeva/CSSC-Bot"; + const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; + const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; + + // Embed construction + const Embed = new MessageEmbed() + .setColor(color) + .setTitle(title) + .setThumbnail(thumbnail) + .setDescription(description) + .setFooter({ text: footer, iconURL: footerIcon }); + + interaction.reply({ embeds: [Embed] }); + }, +} as ICommand; diff --git a/commands/user/help.ts b/commands/user/help.ts new file mode 100644 index 0000000..9e559f0 --- /dev/null +++ b/commands/user/help.ts @@ -0,0 +1,50 @@ +import { + MessageEmbed, + } from "discord.js"; + import { ICommand } from "wokcommands"; + + export default { + name: "help", + category: "user", + description: "Shows the help embed", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["SEND_MESSAGES"], + + callback: async ({ client, interaction }) => { + + const color = "#0099ff" ; + const thumbnail = "https://playantares.com/resources/CSSC-bot/cssc-server-icon.png"; + const title = "Github"; + const description = "Welcome to CSSC-Bot! My purpose in this server is to make sure you have the correct roles for this server. My purpose mey evolve over time. You can always use this command to see my latest features."; + const fields = [ + { + name: "Commands", + value: + "**/help** - Shows this help embed\n" + + "**/github** - Shows the official GitHub repository for this bot.\n" + + "**/view** - Shows a list of all roles that I have assigned to you\n" + + "**/clear** - Removes all roles that I have assigned to you\n", + }, + { + name: "Features", + value: + "**College Student Roles** - Assigns the correct role for your year in school.\n" + + "**College Employee Roles** - Assigns the correct role for your job title.", + } + ] + const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; + const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; + + const Embed = new MessageEmbed() + .setColor(color) + .setTitle(title) + .setThumbnail(thumbnail) + .setDescription(description) + .addFields(fields) + .setFooter({text: footer, iconURL: footerIcon}); + interaction.reply({embeds: [Embed]}); + // Post command usage + } + } as ICommand; \ No newline at end of file diff --git a/commands/user/status.ts b/commands/user/status.ts new file mode 100644 index 0000000..7521029 --- /dev/null +++ b/commands/user/status.ts @@ -0,0 +1,32 @@ +import { MessageEmbed, TextChannel } from "discord.js"; +import { ICommand } from "wokcommands"; + +export default { + name: "status", + category: "user", + description: "Sends an embed with a link to the status page for the bot.", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["SEND_MESSAGES"], + + callback: async ({ client, interaction }) => { + // Embed values + const color = "#0099ff"; + const thumbnail = "https://playantares.com/resources/CSSC-bot/cssc-server-icon.png"; + const title = "Status Page"; + const description = "CLick here to see the bot's status: \nhttps://status.playantares.com"; + const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; + const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; + + // Embed construction + const Embed = new MessageEmbed() + .setColor(color) + .setTitle(title) + .setThumbnail(thumbnail) + .setDescription(description) + .setFooter({ text: footer, iconURL: footerIcon }); + + interaction.reply({ embeds: [Embed] }); + }, +} as ICommand; diff --git a/commands/user/uptime.ts b/commands/user/uptime.ts new file mode 100644 index 0000000..27ece1f --- /dev/null +++ b/commands/user/uptime.ts @@ -0,0 +1,42 @@ +import { MessageEmbed, TextChannel } from "discord.js"; +import { ICommand } from "wokcommands"; + +export default { + name: "uptime", + category: "user", + description: "Checks how long the bot has been online.", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["SEND_MESSAGES"], + + callback: async ({ client, interaction }) => { + // Command information + const id = interaction.user.id; + const chan = interaction.channel as TextChannel; + + // Computed values + const time = client.uptime!; + const days = Math.floor(time / 86400000); + const hours = Math.floor(time / 3600000) % 24; + const minutes = Math.floor(time / 60000) % 60; + const seconds = Math.floor(time / 1000) % 60; + + // Embed values + const color = "#0099ff" + const title = "Bot Uptime" + const description = `I have been online for ${days}d ${hours}h ${minutes}m ${seconds}s` + const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; + const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; + + // Embed construction + const Embed = new MessageEmbed() + .setColor(color) + .setTitle(title) + .setDescription(description) + .setFooter({text: footer, iconURL: footerIcon}); + + // Return the embed + interaction.reply({embeds: [Embed]}); + }, +} as ICommand; \ No newline at end of file diff --git a/commands/user/viewRoles.ts b/commands/user/viewRoles.ts new file mode 100644 index 0000000..2aa97b6 --- /dev/null +++ b/commands/user/viewRoles.ts @@ -0,0 +1,41 @@ +import { GuildMember } from "discord.js"; +import { ICommand } from "wokcommands"; +import { returnRoles as roleDictionary } from "../../definitions"; + + +export default { + name: "view", + category: "user", + description: "Shows a list of all roles that I have assigned to you", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["SEND_MESSAGES"], + + callback: async ({ interaction }) => { + + // Remove roles from user + if (!interaction.member) return; + let list = ""; + const member = interaction.member as GuildMember; + for (const role of Object.values(roleDictionary()[0])) { + if (member.roles.cache.has(role)) { + list += `${member.guild.roles.cache.get(role)?.name}\n`; + } + } + for (const role of Object.values(roleDictionary()[1])) { + if (member.roles.cache.has(role)) { + list += `${member.guild.roles.cache.get(role)?.name}\n`; + } + } + + + // Reply to the user + if (list === "") { + interaction.reply({content: "You don't have any College roles assigned to you.", ephemeral: true}); + } else { + interaction.reply({content: "**Your roles:**\n" + list, ephemeral: true}); + } + + }, +} as ICommand; \ No newline at end of file diff --git a/definitions.ts b/definitions.ts new file mode 100644 index 0000000..03e595f --- /dev/null +++ b/definitions.ts @@ -0,0 +1,44 @@ +type dict = { + [key: string]: string; +}; + +function returnRoles(): dict[] { + let studentRoleDictionary = { + prefrosh: String(process.env.prefrosh), + freshman: String(process.env.freshman), + sophomore: String(process.env.sophomore), + junior: String(process.env.junior), + senior: String(process.env.senior), + graduatestudent: String(process.env.graduatestudent), + alumni: String(process.env.alumni), + }; + let staffRoleDictionary = { + tutor: String(process.env.tutor), + sileader: String(process.env.sileader), + ta: String(process.env.ta), + studentemployee: String(process.env.studentemployee) + } + if (process.env.debugMode === "true") { + + let studentRoleDictionary = { + prefrosh: "1003849993255403601", + freshman: "1003367383181824131", + sophomore: "1003367410679685262", + junior: "1003367473053171743", + senior: "1003850030920245409", + graduatestudent: "1003850131994583122", + alumni: "1003850162935975960" + }; + let staffRoleDictionary = { + tutor: "1003850195202744560", + sileader: "1003850241591742595", + ta: "1003850228643934260", + studentemployee: "1003850274840002620", + professor: "1003881218686865439" + } + return [studentRoleDictionary, staffRoleDictionary]; + }; + return [studentRoleDictionary, staffRoleDictionary]; +} + +export { returnRoles }; diff --git a/env.template b/env.template new file mode 100644 index 0000000..2345875 --- /dev/null +++ b/env.template @@ -0,0 +1,20 @@ +BOT_TOKEN= +MONGODB_URI= +BOT_DEFAULT_PREFIX= +VERSION= +UPTIME_KUMA_MONITOR_DOMAIN= +UPTIME_KUMA_MONITOR_ID= + + +# Fill out these values with the role id's of the roles you have in your server + +prefrosh= +freshman= +sophomore= +junior= +senior= +graduatestudent= +alumni=8 +sileader= +ta= +studentemployee= \ No newline at end of file diff --git a/features/interactionCreate.ts b/features/interactionCreate.ts new file mode 100644 index 0000000..c2f9401 --- /dev/null +++ b/features/interactionCreate.ts @@ -0,0 +1,66 @@ +import { Client, MessageEmbed, GuildMember } from "discord.js"; +import { returnRoles as roleDictionary } from "../definitions"; +import { removePrevRole } from "../rolesOps"; + +// Listen interactionCreate events from the client +export default (client: Client): void => { + client.on("interactionCreate", async (interaction) => { + // Make sure the interaction is from a select menu + if (!interaction.isSelectMenu()) return; + + // Constants for all interactions + const member = interaction.member as GuildMember; + + // Get the select menu by it's custom ID + if (interaction.customId === "collegeYearPoll") { + // Set the embed values + const title = "College Year Poll"; + const color = "#0099ff"; + const description = `You selected the ${interaction.values[0]} role.`; + const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; + const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; + + // Create and send the embed object + interaction.reply({ + embeds: [ + new MessageEmbed() + .setColor(color) + .setTitle(title) + .setDescription(description) + .setFooter({text: footer, iconURL: footerIcon}), + ], + ephemeral: true + }); + // Remove any previous roles in the dictionary from the user + removePrevRole(member, 0); + + // Assign the new role to the user + member.roles.add(roleDictionary()[0][interaction.values[0]]); + + } else if (interaction.customId === "collegeStaffPoll") { + // Set the embed values + const title = "College Staff Poll"; + const color = "#0099ff"; + const description = `You selected the ${interaction.values[0]} role.`; + const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; + const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; + + // Create and send the embed object + interaction.reply({ + embeds: [ + new MessageEmbed() + .setColor(color) + .setTitle(title) + .setDescription(description) + .setFooter({text: footer, iconURL: footerIcon}), + ], + ephemeral: true + }); + // Remove any previous roles in the dictionary from the user + removePrevRole(member, 1); + + // Assign the new role to the user + member.roles.add(roleDictionary()[1][interaction.values[0]]); + } + }); +} \ No newline at end of file diff --git a/features/status-changer.ts b/features/status-changer.ts new file mode 100644 index 0000000..d011993 --- /dev/null +++ b/features/status-changer.ts @@ -0,0 +1,39 @@ +import { Client } from "discord.js"; + + +export default async (client: Client) => { + + const statusOptions = [ + `/help | Ping: ${client.ws.ping}ms`, + `V.${process.env.VERSION}`, + `status.playantares.com`, + 'Go to #roles!', + 'Hello! I\'m CSSC-Bot', + + ]; + let counter = 0; + + const updateStatus = () => { + client.user?.setPresence({ + status: "online", + activities: [ + { + name: statusOptions[counter], + type: "PLAYING", + }, + ], + }); + + if (++counter >= statusOptions.length) { + counter = 0; + } + + setTimeout(updateStatus, 1000 * 60 * 5); + }; + updateStatus(); +}; + +export const config = { + dbName: "STATUS_CHANGER", + displayName: "Status Changer", +}; \ No newline at end of file diff --git a/features/statuspage.ts b/features/statuspage.ts new file mode 100644 index 0000000..58b611d --- /dev/null +++ b/features/statuspage.ts @@ -0,0 +1,19 @@ + +import axios from "axios"; +import { Client } from "discord.js"; + +export default (client: Client): void => { + const updateStatus = async () => { + // This function is called every 1 minutes and pings the network status page for uptime monitoring + axios.get(`https://${process.env.UPTIME_KUMA_MONITOR_DOMAIN}/api/push/${process.env.UPTIME_KUMA_MONITOR_ID}?msg=OK&ping=${client.ws.ping}`); + console.log(`Posted status to ${process.env.UPTIME_KUMA_MONITOR_DOMAIN}`); + setTimeout(updateStatus, 1000 * 60); + }; + updateStatus() + .catch(err => console.log(err)); +}; + +export const config = { + dbName: "STATUSPAGE_UPDATE", + displayName: "Status Page Update", +}; \ No newline at end of file diff --git a/img/botface.jpg b/img/botface.jpg deleted file mode 100644 index f1c854a..0000000 Binary files a/img/botface.jpg and /dev/null differ diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..9a9eb66 --- /dev/null +++ b/index.ts @@ -0,0 +1,68 @@ +// Import packages from NPM +import DiscordJs, { Intents } from "discord.js"; +import WOKCommands from "wokcommands"; +import path from "path"; +import chalk from "chalk"; +import dotenv from "dotenv"; + +// import all environment variables from .env file +dotenv.config(); + +// Create a new Discord client +const client = new DiscordJs.Client({ + intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.DIRECT_MESSAGE_REACTIONS, Intents.FLAGS.GUILD_EMOJIS_AND_STICKERS], +}); + +client.on("ready", () => { + if (client.user) { + console.log(chalk.green(`Logged in as ${client.user.tag}!`)); + if (process.env.debugMode === "true") { + console.log(chalk.red.bold("Debug mode is enabled!\nTesting Server roles are loaded!")); + } else if (process.env.debugMode === "false") { + console.log(chalk.red.bold("Debug mode is disabled!\nProduction Server roles are loaded!")); + } + } + + const dbOptions = { + // These are the default values + keepAlive: true, + useNewUrlParser: true, + useUnifiedTopology: true, + }; + + // Set up the WOKCommands instance + const wok = new WOKCommands(client, { + commandDir: path.join(__dirname, "commands"), + featureDir: path.join(__dirname, "features"), + dbOptions, + typeScript: true, + mongoUri: String(process.env.MONGODB_URI), + disabledDefaultCommands: ["help", "language"], + botOwners: ["603629606154666024", "680813135556378634"], + }).setDefaultPrefix(String(process.env.BOT_DEFAULT_PREFIX)); + + // Set up the connection to the database + wok.on("databaseConnected", async () => { + console.log(chalk.green("Connected to the database")); + }); +}); + +// Catch all errors that are not handled well and just dump to the console. THis will be changed later but for now it's fine. +client.on("error", console.error); +client.on("warn", (e) => console.warn(e)); +process.on("unhandledRejection", (promise, reason) => { + console.error("Unhandled promise rejection:", promise, "\nreason", reason); +}); + +// Login to Discord with the bot token and display an error if it fails. +client.login(process.env.BOT_TOKEN).catch((error) => { + console.log(chalk.red.bold(`There was an error connecting to the Discord API`)); + console.error(error); + process.exit(1); +}); + +// Exit gracefully and print the exit code. +process.on("exit", (code) => { + console.log("Now exiting..."); + console.log(`Exited with status code: ${code}`); +}); \ No newline at end of file diff --git a/json/msg_ids.json b/json/msg_ids.json deleted file mode 100644 index e69de29..0000000 diff --git a/logs/bot.txt b/logs/bot.txt deleted file mode 100644 index e69de29..0000000 diff --git a/logs/discord.txt b/logs/discord.txt deleted file mode 100644 index e69de29..0000000 diff --git a/logs/server.txt b/logs/server.txt deleted file mode 100644 index e69de29..0000000 diff --git a/modules/logger.py b/modules/logger.py deleted file mode 100644 index 32df7bd..0000000 --- a/modules/logger.py +++ /dev/null @@ -1,56 +0,0 @@ -# logger module - -import io -import logging -import sys - -# Logger setup ============================================= - -# custom logger, logs only when called from this project -# gets set up in setupLoggers() -log = None - -logFormat = "[%(levelname)s] %(asctime)s (%(name)s): %(message)s" - -# open log files in append mode -logMode = "a" - -# location of logs created by the discord.py framework -discordPyLogs = "logs/discord.txt" - -# location of logs created by project -botLogs = "logs/bot.txt" - -# setup a logger to receive framework log messages -# the level is set to WARN - this will only log -# error and warning messages -logging.basicConfig(filename=discordPyLogs, - filemode=logMode, - format=logFormat, - level=logging.WARN) - -# this will reroute stderr to the project log file -class ErrorStream(io.IOBase): - def write(self, s): - log.error(s) - -# create a logger -def createLogger(name: str, file: str, level=logging.DEBUG): - logger = logging.getLogger(name) - formatter = logging.Formatter(logFormat) - fileHandler = logging.FileHandler(file, logMode) - fileHandler.setFormatter(formatter) - streamHandler = logging.StreamHandler() - streamHandler.setFormatter(formatter) - logger.setLevel(level) - logger.addHandler(fileHandler) - logger.propagate = False - -# setup the project logger -def setupLoggers(): - botLoggerName = "Local" - createLogger(botLoggerName, botLogs) - global log - log = logging.getLogger(botLoggerName) - # reroute stderr to project log file - sys.stderr = ErrorStream() diff --git a/modules/persistance.py b/modules/persistance.py deleted file mode 100644 index 171ddd1..0000000 --- a/modules/persistance.py +++ /dev/null @@ -1,43 +0,0 @@ -# persistance.py module -# -# The purpose of this is to persist the IDs of messages -# that this bot creates. If the bot shuts down or crashes -# it will still have access to all of the messages -# that it posted in the past. -# ========================================================== - -import json - -# location of message IDs json file -fileName = 'json/msg_ids.json' - -# cache -items: dict = {} - -# tries opening and reading the JSON file into items -try: - with open(fileName, "r") as file: - items: dict = json.load(file) -except json.JSONDecodeError: - items: dict = {} - -# functions ================================================ - -# saves the ID under the specified key --------------------- -def save(key, value): - if key in items: - items[key].append(value) - else: - items[key] = [] - items[key].append(value) - - with open(fileName, "w") as file: - json.dump(items, file, indent=4) - -# checks if the ID is persisted. If it is ------------------ -# returns its key, if not, returns None -def has(value): - for key in items: - if value in items[key]: - return key - return None \ No newline at end of file diff --git a/modules/role_poll.py b/modules/role_poll.py deleted file mode 100644 index a50f4d1..0000000 --- a/modules/role_poll.py +++ /dev/null @@ -1,140 +0,0 @@ -import discord -from discord import Embed, Guild, Member -from discord.ext.commands import Context -import modules.logger as logger -import modules.utils as utils - -# 'Constants' ============================================== - -# key of the College Year poll IDs -COLLEGE_YEAR_POLL_KEY = "college_year_poll" -COLLEGE_STAFF_POLL_KEY = "college_staff_poll" - -TITLE = "title" -DESCRIPTION = "description" -OPTIONS = "options" - -# Classes ================================================== - -# role reaction poll 'interface' -class ReactionPoll: - def __init__(self, name: str, color: int, emoji: str, cmd: str): - self.name : str = name - self.color : int = color - self.emoji : str = emoji - self.cmd : str = cmd - - async def assign(self, guild: Guild, author: Member): - role = await utils.getRole(guild, self.name, self.color) - if role and not role in author.roles: - await author.add_roles(role) - -class CollegeYearPoll(ReactionPoll): - async def assign(self, guild: Guild, author: Member): - role = await utils.getRole(guild, self.name, self.color) - if role: - await clearRoles(COLLEGE_YEAR_POLL_KEY, author) - await author.add_roles(role) - -class CollegeStaffPoll(ReactionPoll): - pass - -# Reaction poll content ==================================== - -polls = { - # College Year Poll content ---------------------------- - COLLEGE_YEAR_POLL_KEY: - { - TITLE: "College Year", - DESCRIPTION: "React with your current college year:", - OPTIONS: - [ - CollegeYearPoll("Prefrosh", 0x3498db, "0️⃣", "prefrosh"), - CollegeYearPoll("Freshman", 0x2ecc71, "1️⃣", "freshman"), - CollegeYearPoll("Sophomore", 0xe67e22, "2️⃣", "sophomore"), - CollegeYearPoll("Junior", 0x9b59b6, "3️⃣", "junior"), - CollegeYearPoll("Senior", 0xe74c3c, "4️⃣", "senior"), - CollegeYearPoll("Grad Student", 0x4fe8f5, "5️⃣", "gradstudent"), - CollegeYearPoll("Alumni", 0xe9e740, "6️⃣", "alumni") - ], - }, - - # College Staff Poll content --------------------------- - COLLEGE_STAFF_POLL_KEY: - { - TITLE: "College Staff Member", - DESCRIPTION: "React with your occupation at UWM:", - OPTIONS: - [ - CollegeStaffPoll("Tutor", 0xcaad66, "🐶", "tutor"), - CollegeStaffPoll("SI Leader", 0xcaad66, "🐱", "sileader"), - CollegeStaffPoll("TA", 0xcaad66, "🦊", "ta"), - CollegeStaffPoll("Professor", 0xcaad66, "🐻", "professor") - ] - } -} - -# Utilities ================================================ - -# A map where two keys map to one value -------------------- -# Keys map to OPTIONS in the polls object -# An option can be found either by its command, or by its ID -# and emoji -roleMap = {} - -# creating the roleMap ------------------------------------- -def makeRoleMap(): - for key in polls: - for item in polls[key][OPTIONS]: - roleMap[(key, item.emoji)] = item - roleMap[item.cmd] = item - -makeRoleMap() - -# Module functions ========================================= - -# posts a reaction role poll, based on its ID -------------- -async def post(ctx: Context, key): - content = f"*{polls[key][DESCRIPTION]}*\n\n" - for item in polls[key][OPTIONS]: - content += f"{item.emoji} - **{item.name}**\n" - - embed = discord.Embed(title=polls[key][TITLE], description=content) - if embed == Embed.Empty: - logger.log.warn("In college_year.post() the created embed was empty") - else: - msg = await ctx.send(embed=embed) - - for item in polls[key][OPTIONS]: - await msg.add_reaction(item.emoji) - return msg - return None - -# assign a role to <author> in <guild> based --------------- -# on command <cmd> -async def cmd(cmd, guild, author): - if cmd in roleMap: - await roleMap[cmd].assign(guild, author) - -# assign a role to <author> in <guild> based --------------- -# on the reaction poll <key> and option <emoji> -async def reaction(key, emoji, guild, author): - if (key, emoji) in roleMap: - await roleMap[(key, emoji)].assign(guild, author) - -# clear roles that are in the poll with <key> from <author> -async def clearRoles(key, author: Member): - rolesToClear = [option.name for option in polls[key][OPTIONS]] - for role in author.roles: - if role.name in rolesToClear: - await author.remove_roles(role) - -# clear all roles from all polls in the polls -------------- -# object from <author> -async def clearAllRoles(author: Member): - rolesToClear = [] - for key in polls: - rolesToClear += [option.name for option in polls[key][OPTIONS]] - for role in author.roles: - if role.name in rolesToClear: - await author.remove_roles(role) \ No newline at end of file diff --git a/modules/utils.py b/modules/utils.py deleted file mode 100644 index 40801f9..0000000 --- a/modules/utils.py +++ /dev/null @@ -1,12 +0,0 @@ -import discord -from discord import Guild -from discord.utils import get - -# Checks if the server has the specified role -------------- -# and returns it, creates the role if it does -# not exist -async def getRole(guild: Guild, roleName: str, roleColor: int): - role = get(guild.roles, name=roleName) - if not role: - role = await guild.create_role(name=roleName, colour=discord.Colour(roleColor)) - return role \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..7608820 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1418 @@ +{ + "name": "cssc-bot", + "version": "2.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "cssc-bot", + "version": "2.0.0", + "license": "ISC", + "dependencies": { + "axios": "^0.27.2", + "chalk": "^4.1.2", + "discord.js": "^13.9.2", + "mongoose": "^6.2.2", + "path": "^0.12.7", + "ts-node": "^10.5.0", + "typescript": "^4.5.5", + "wokcommands": "^1.5.3" + }, + "engines": { + "node": "17.x" + } + }, + "node_modules/@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dependencies": { + "@cspotcode/source-map-consumer": "0.8.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@discordjs/builders": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.16.0.tgz", + "integrity": "sha512-9/NCiZrLivgRub2/kBc0Vm5pMBE5AUdYbdXsLu/yg9ANgvnaJ0bZKTY8yYnLbsEc/LYUP79lEIdC73qEYhWq7A==", + "deprecated": "no longer supported", + "dependencies": { + "@sapphire/shapeshift": "^3.5.1", + "discord-api-types": "^0.36.2", + "fast-deep-equal": "^3.1.3", + "ts-mixer": "^6.0.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/@discordjs/builders/node_modules/discord-api-types": { + "version": "0.36.3", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.36.3.tgz", + "integrity": "sha512-bz/NDyG0KBo/tY14vSkrwQ/n3HKPf87a0WFW/1M9+tXYK+vp5Z5EksawfCWo2zkAc6o7CClc0eff1Pjrqznlwg==" + }, + "node_modules/@discordjs/collection": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.7.0.tgz", + "integrity": "sha512-R5i8Wb8kIcBAFEPLLf7LVBQKBDYUL+ekb23sOgpkpyGT+V4P7V83wTxcsqmX+PbqHt4cEHn053uMWfRqh/Z/nA==", + "deprecated": "no longer supported", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/@sapphire/async-queue": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.3.2.tgz", + "integrity": "sha512-rUpMLATsoAMnlN3gecAcr9Ecnw1vG7zi5Xr+IX22YzRzi1k9PF9vKzoT8RuEJbiIszjcimu3rveqUnvwDopz8g==", + "engines": { + "node": ">=v14.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@sapphire/shapeshift": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.5.1.tgz", + "integrity": "sha512-7JFsW5IglyOIUQI1eE0g6h06D/Far6HqpcowRScgCiLSqTf3hhkPWCWotVTtVycnDCMYIwPeaw6IEPBomKC8pA==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "lodash.uniqwith": "^4.5.0" + }, + "engines": { + "node": ">=v14.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + }, + "node_modules/@types/node": { + "version": "18.6.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.3.tgz", + "integrity": "sha512-6qKpDtoaYLM+5+AFChLhHermMQxc3TOEFIDzrZLPRGHPrLEwqFkkT5Kx3ju05g6X7uDPazz3jHbKPX0KzCjntg==" + }, + "node_modules/@types/node-fetch": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", + "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "node_modules/@types/node-fetch/node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/webidl-conversions": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz", + "integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q==" + }, + "node_modules/@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "dependencies": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, + "node_modules/@types/ws": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", + "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bson": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.5.tgz", + "integrity": "sha512-uqrgcjyOaZsHfz7ea8zLRCLe1u+QGUSzMZmvXqO24CDW7DWoW1qiN9folSwa7hSneTSgM2ykDIzF5kcQQ8cwNw==", + "dependencies": { + "buffer": "^5.6.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/discord-api-types": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.33.5.tgz", + "integrity": "sha512-dvO5M52v7m7Dy96+XUnzXNsQ/0npsYpU6dL205kAtEDueswoz3aU3bh1UMoK4cQmcGtB1YRyLKqp+DXi05lzFg==" + }, + "node_modules/discord.js": { + "version": "13.9.2", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.9.2.tgz", + "integrity": "sha512-wShFlyAyxgQcWzINeufUoT1U0fmju+pPCRzPfJB7CaA0V1tQHc4e0PpO4NQif8sLfZvrQmEILBaIJ0G5I32OxQ==", + "dependencies": { + "@discordjs/builders": "^0.16.0", + "@discordjs/collection": "^0.7.0", + "@sapphire/async-queue": "^1.3.2", + "@types/node-fetch": "^2.6.2", + "@types/ws": "^8.5.3", + "discord-api-types": "^0.33.3", + "form-data": "^4.0.0", + "node-fetch": "^2.6.7", + "ws": "^8.8.1" + }, + "engines": { + "node": ">=16.6.0", + "npm": ">=7.0.0" + } + }, + "node_modules/dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "engines": { + "node": ">=10" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, + "node_modules/kareem": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.4.tgz", + "integrity": "sha512-Vcrt8lcpVl0s8ePx634BxwRqmFo+5DcOhlmNadehxreMTIQi/9hOL/B3hZQQbK5DgMS7Lem3xABXV7/S3jy+7g==" + }, + "node_modules/lodash.uniqwith": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniqwith/-/lodash.uniqwith-4.5.0.tgz", + "integrity": "sha512-7lYL8bLopMoy4CTICbxygAUq6CdRJ36vFc80DucPueUee+d5NBRxz3FdT9Pes/HEx5mPoT9jwnsEJWz1N7uq7Q==" + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mongodb": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.3.1.tgz", + "integrity": "sha512-sNa8APSIk+r4x31ZwctKjuPSaeKuvUeNb/fu/3B6dRM02HpEgig7hTHM8A/PJQTlxuC/KFWlDlQjhsk/S43tBg==", + "dependencies": { + "bson": "^4.6.1", + "denque": "^2.0.1", + "mongodb-connection-string-url": "^2.4.1", + "socks": "^2.6.1" + }, + "engines": { + "node": ">=12.9.0" + }, + "optionalDependencies": { + "saslprep": "^1.0.3" + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.3.tgz", + "integrity": "sha512-f+/WsED+xF4B74l3k9V/XkTVj5/fxFH2o5ToKXd8Iyi5UhM+sO9u0Ape17Mvl/GkZaFtM0HQnzAG5OTmhKw+tQ==", + "dependencies": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "node_modules/mongoose": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.2.2.tgz", + "integrity": "sha512-uiWCPydp83OdVQjp6rMCwB/CbITUbGlisGt1BdlYUDQJzPJVIxeojQXuors8coSeB2HnZrULHrLcm4FP106ehA==", + "dependencies": { + "bson": "^4.2.2", + "kareem": "2.3.4", + "mongodb": "4.3.1", + "mpath": "0.8.4", + "mquery": "4.0.2", + "ms": "2.1.2", + "sift": "13.5.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mpath": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz", + "integrity": "sha512-DTxNZomBcTWlrMW76jy1wvV37X/cNNxPW1y2Jzd4DZkAaC5ZGsm8bfGfNOthcDuRJujXLqiuS6o3Tpy0JEoh7g==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-4.0.2.tgz", + "integrity": "sha512-oAVF0Nil1mT3rxty6Zln4YiD6x6QsUWYz927jZzjMxOK2aqmhEz5JQ7xmrKK7xRFA2dwV+YaOpKU/S+vfNqKxA==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", + "dependencies": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/sift": { + "version": "13.5.2", + "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz", + "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==" + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz", + "integrity": "sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "optional": true, + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/ts-mixer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.1.tgz", + "integrity": "sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg==" + }, + "node_modules/ts-node": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.5.0.tgz", + "integrity": "sha512-6kEJKwVxAJ35W4akuiysfKwKmjkbYxwQMTBaAxo9KKAx/Yd26mPUyhGz3ji+EsJoAgrLqVsYHNuuYwQe22lbtw==", + "dependencies": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.0", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/typescript": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/wokcommands": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/wokcommands/-/wokcommands-1.5.3.tgz", + "integrity": "sha512-oBb7ujov8zJ1DYSLz3G7OW9DJK+0l35t/ds5j/2nJ+4DwfzLU7w4i2yXGZOidSHkkygSegiNuaWKfZTP2okJOw==", + "dependencies": { + "discord.js": "^13.1.0", + "dotenv": "^8.2.0", + "mongoose": "^6.0.10" + } + }, + "node_modules/ws": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", + "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } + } + }, + "dependencies": { + "@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==" + }, + "@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "requires": { + "@cspotcode/source-map-consumer": "0.8.0" + } + }, + "@discordjs/builders": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.16.0.tgz", + "integrity": "sha512-9/NCiZrLivgRub2/kBc0Vm5pMBE5AUdYbdXsLu/yg9ANgvnaJ0bZKTY8yYnLbsEc/LYUP79lEIdC73qEYhWq7A==", + "requires": { + "@sapphire/shapeshift": "^3.5.1", + "discord-api-types": "^0.36.2", + "fast-deep-equal": "^3.1.3", + "ts-mixer": "^6.0.1", + "tslib": "^2.4.0" + }, + "dependencies": { + "discord-api-types": { + "version": "0.36.3", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.36.3.tgz", + "integrity": "sha512-bz/NDyG0KBo/tY14vSkrwQ/n3HKPf87a0WFW/1M9+tXYK+vp5Z5EksawfCWo2zkAc6o7CClc0eff1Pjrqznlwg==" + } + } + }, + "@discordjs/collection": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.7.0.tgz", + "integrity": "sha512-R5i8Wb8kIcBAFEPLLf7LVBQKBDYUL+ekb23sOgpkpyGT+V4P7V83wTxcsqmX+PbqHt4cEHn053uMWfRqh/Z/nA==" + }, + "@sapphire/async-queue": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.3.2.tgz", + "integrity": "sha512-rUpMLATsoAMnlN3gecAcr9Ecnw1vG7zi5Xr+IX22YzRzi1k9PF9vKzoT8RuEJbiIszjcimu3rveqUnvwDopz8g==" + }, + "@sapphire/shapeshift": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.5.1.tgz", + "integrity": "sha512-7JFsW5IglyOIUQI1eE0g6h06D/Far6HqpcowRScgCiLSqTf3hhkPWCWotVTtVycnDCMYIwPeaw6IEPBomKC8pA==", + "requires": { + "fast-deep-equal": "^3.1.3", + "lodash.uniqwith": "^4.5.0" + } + }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + }, + "@types/node": { + "version": "18.6.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.3.tgz", + "integrity": "sha512-6qKpDtoaYLM+5+AFChLhHermMQxc3TOEFIDzrZLPRGHPrLEwqFkkT5Kx3ju05g6X7uDPazz3jHbKPX0KzCjntg==" + }, + "@types/node-fetch": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", + "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, + "@types/webidl-conversions": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz", + "integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q==" + }, + "@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "requires": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, + "@types/ws": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", + "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==" + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "requires": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bson": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.5.tgz", + "integrity": "sha512-uqrgcjyOaZsHfz7ea8zLRCLe1u+QGUSzMZmvXqO24CDW7DWoW1qiN9folSwa7hSneTSgM2ykDIzF5kcQQ8cwNw==", + "requires": { + "buffer": "^5.6.0" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + }, + "discord-api-types": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.33.5.tgz", + "integrity": "sha512-dvO5M52v7m7Dy96+XUnzXNsQ/0npsYpU6dL205kAtEDueswoz3aU3bh1UMoK4cQmcGtB1YRyLKqp+DXi05lzFg==" + }, + "discord.js": { + "version": "13.9.2", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.9.2.tgz", + "integrity": "sha512-wShFlyAyxgQcWzINeufUoT1U0fmju+pPCRzPfJB7CaA0V1tQHc4e0PpO4NQif8sLfZvrQmEILBaIJ0G5I32OxQ==", + "requires": { + "@discordjs/builders": "^0.16.0", + "@discordjs/collection": "^0.7.0", + "@sapphire/async-queue": "^1.3.2", + "@types/node-fetch": "^2.6.2", + "@types/ws": "^8.5.3", + "discord-api-types": "^0.33.3", + "form-data": "^4.0.0", + "node-fetch": "^2.6.7", + "ws": "^8.8.1" + } + }, + "dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, + "kareem": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.4.tgz", + "integrity": "sha512-Vcrt8lcpVl0s8ePx634BxwRqmFo+5DcOhlmNadehxreMTIQi/9hOL/B3hZQQbK5DgMS7Lem3xABXV7/S3jy+7g==" + }, + "lodash.uniqwith": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniqwith/-/lodash.uniqwith-4.5.0.tgz", + "integrity": "sha512-7lYL8bLopMoy4CTICbxygAUq6CdRJ36vFc80DucPueUee+d5NBRxz3FdT9Pes/HEx5mPoT9jwnsEJWz1N7uq7Q==" + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "mongodb": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.3.1.tgz", + "integrity": "sha512-sNa8APSIk+r4x31ZwctKjuPSaeKuvUeNb/fu/3B6dRM02HpEgig7hTHM8A/PJQTlxuC/KFWlDlQjhsk/S43tBg==", + "requires": { + "bson": "^4.6.1", + "denque": "^2.0.1", + "mongodb-connection-string-url": "^2.4.1", + "saslprep": "^1.0.3", + "socks": "^2.6.1" + } + }, + "mongodb-connection-string-url": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.3.tgz", + "integrity": "sha512-f+/WsED+xF4B74l3k9V/XkTVj5/fxFH2o5ToKXd8Iyi5UhM+sO9u0Ape17Mvl/GkZaFtM0HQnzAG5OTmhKw+tQ==", + "requires": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "mongoose": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.2.2.tgz", + "integrity": "sha512-uiWCPydp83OdVQjp6rMCwB/CbITUbGlisGt1BdlYUDQJzPJVIxeojQXuors8coSeB2HnZrULHrLcm4FP106ehA==", + "requires": { + "bson": "^4.2.2", + "kareem": "2.3.4", + "mongodb": "4.3.1", + "mpath": "0.8.4", + "mquery": "4.0.2", + "ms": "2.1.2", + "sift": "13.5.2" + } + }, + "mpath": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz", + "integrity": "sha512-DTxNZomBcTWlrMW76jy1wvV37X/cNNxPW1y2Jzd4DZkAaC5ZGsm8bfGfNOthcDuRJujXLqiuS6o3Tpy0JEoh7g==" + }, + "mquery": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-4.0.2.tgz", + "integrity": "sha512-oAVF0Nil1mT3rxty6Zln4YiD6x6QsUWYz927jZzjMxOK2aqmhEz5JQ7xmrKK7xRFA2dwV+YaOpKU/S+vfNqKxA==", + "requires": { + "debug": "4.x" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, + "path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", + "requires": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, + "sift": { + "version": "13.5.2", + "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz", + "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==" + }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" + }, + "socks": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz", + "integrity": "sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==", + "requires": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + } + }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "optional": true, + "requires": { + "memory-pager": "^1.0.2" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "requires": { + "punycode": "^2.1.1" + } + }, + "ts-mixer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.1.tgz", + "integrity": "sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg==" + }, + "ts-node": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.5.0.tgz", + "integrity": "sha512-6kEJKwVxAJ35W4akuiysfKwKmjkbYxwQMTBaAxo9KKAx/Yd26mPUyhGz3ji+EsJoAgrLqVsYHNuuYwQe22lbtw==", + "requires": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.0", + "yn": "3.1.1" + } + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "typescript": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==" + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "requires": { + "inherits": "2.0.3" + } + }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "requires": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + } + }, + "wokcommands": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/wokcommands/-/wokcommands-1.5.3.tgz", + "integrity": "sha512-oBb7ujov8zJ1DYSLz3G7OW9DJK+0l35t/ds5j/2nJ+4DwfzLU7w4i2yXGZOidSHkkygSegiNuaWKfZTP2okJOw==", + "requires": { + "discord.js": "^13.1.0", + "dotenv": "^8.2.0", + "mongoose": "^6.0.10" + } + }, + "ws": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", + "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", + "requires": {} + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..ba5c577 --- /dev/null +++ b/package.json @@ -0,0 +1,32 @@ +{ + "name": "cssc-bot", + "version": "2.0.0", + "engines": { + "node": "17.x" + }, + "description": "", + "main": "index.ts", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/llisaeva/CSSC-Bot.git" + }, + "author": "llisaeva, nathen418", + "license": "ISC", + "bugs": { + "url": "https://github.com/llisaeva/CSSC-Bot/issues" + }, + "homepage": "https://github.com/llisaeva/CSSC-Bot#readme", + "dependencies": { + "axios": "^0.27.2", + "chalk": "^4.1.2", + "discord.js": "^13.9.2", + "mongoose": "^6.2.2", + "path": "^0.12.7", + "ts-node": "^10.5.0", + "typescript": "^4.5.5", + "wokcommands": "^1.5.3" + } +} diff --git a/rolebot.py b/rolebot.py deleted file mode 100644 index f656297..0000000 --- a/rolebot.py +++ /dev/null @@ -1,121 +0,0 @@ -# rolebot module -import discord -from discord import Message, RawReactionActionEvent -from discord.ext import commands -from discord.ext.commands import Context -from discord.utils import get -import modules.logger as logger -import modules.persistance as persistance -import modules.role_poll as role_poll -from tkn import MAKER, TOKEN - -# 'Constants' ============================================== - -CMD_TEXT = "txt/cmds.txt" -CMD_PREFIX = "$" -intents = discord.Intents.default() -bot = commands.Bot(command_prefix=CMD_PREFIX, owner_id=MAKER, intents=intents) - -# Commands ================================================= - -# post a reaction poll -@bot.command(pass_context=True) -async def poll(ctx: Context, arg=None): - if arg == "collegeYear": - await rolePoll(ctx, role_poll.COLLEGE_YEAR_POLL_KEY) - elif arg == "collegeStaff": - await rolePoll(ctx, role_poll.COLLEGE_STAFF_POLL_KEY) - -# assign a role using a command ---------------------------- -@bot.command(pass_context=True) -async def assign(ctx: Context, arg=None): - if arg and ctx.author: - if arg == "clear": - await role_poll.clearAllRoles(ctx.author) - - elif ctx.guild: - await role_poll.cmd(arg, ctx.guild, ctx.author) - -# post a message that lists all of the commands ------------ -@bot.command(pass_context=True) -async def cmds(ctx: Context): - content = "" - with open(CMD_TEXT, "r") as file: - content = file.read() - - if content: - embed = discord.Embed(title="Command List", description=content) - await ctx.send(embed=embed) - -# Maker Commands =========================================== - -# DMs caller's ID (all users can call this command) --------- -# DMs bot logs, discord logs, or server logs (only -# owner can use this command) -@bot.command() -async def dm(ctx: Context, arg=None): - if arg: - dm = await ctx.author.create_dm() - fileName = None - if arg == "id": - await dm.send(str(ctx.author.id)) - elif arg == "botlogs": - fileName = r'./logs/bot.txt' - elif arg == "discordlogs": - fileName = r'./logs/discord.txt' - elif arg == "serverlogs": - fileName = r'./logs/server.txt' - if fileName: - if ctx.author.id == MAKER: - file = file=discord.File(fileName) - await dm.send(file=file) - else: - await dm.send("You are not my maker") - -# shuts down the bot -@bot.command() -async def die(ctx): - dm = await ctx.author.create_dm() - if ctx.author.id == MAKER: - await dm.send("goodbye") - await ctx.bot.close() - else: - await dm.send("You are not my maker") - -# Events =================================================== - -# boot message --------------------------------------------- -@bot.event -async def on_ready(): - logger.setupLoggers() - logger.log.info("BOOT") - print('{0.user} is running'.format(bot)) - -# event is called when a reaction is added on the server --- -@bot.event -async def on_raw_reaction_add(payload: RawReactionActionEvent): - # reaction was not created by bot and the - # author of the message is the bot - if (payload and - payload.member and - payload.member != bot.user and - payload.message_id): - - key = persistance.has(payload.message_id) - guild = bot.get_guild(payload.guild_id) - - if key and guild: - await role_poll.reaction(key, str(payload.emoji), guild, payload.member) - -# Utilities & Helpers ====================================== - -# post a role reaction poll for ---------------------------- -# the specified key -async def rolePoll(ctx: Context, key): - msg: Message = await role_poll.post(ctx, key) - persistance.save(key, msg.id) - -# Run Rolebot ============================================== - -bot.run(TOKEN) -logger.log.info("SHUTDOWN") \ No newline at end of file diff --git a/rolesOps.ts b/rolesOps.ts new file mode 100644 index 0000000..653534a --- /dev/null +++ b/rolesOps.ts @@ -0,0 +1,22 @@ +import { GuildMember, Guild } from "discord.js"; +import { returnRoles as roleDictionary } from "./definitions"; + +async function removePrevRole(member: GuildMember, listID: number) { + for (const role of Object.values(roleDictionary()[listID])) { + if (member.roles.cache.has(role)) { + await member.roles.remove(role); + } + } +} + +// write a function that will create all necessary roles when the bot joins a guild, if they don't exist already +//! this does not work yet. DO NOT USE +export async function createRoles(guild: Guild, listID: number): Promise<void> { + for (const role of Object.values(roleDictionary()[listID])) { + if (!guild.roles.cache.has(role)) { + await guild.roles.create({ name: role }); + } + } +} + +export { removePrevRole }; diff --git a/tkn.py b/tkn.py deleted file mode 100644 index daa2af7..0000000 --- a/tkn.py +++ /dev/null @@ -1,2 +0,0 @@ -TOKEN="" -MAKER=680813135556378634 \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..8fa4c31 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,100 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es5" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } + } \ No newline at end of file diff --git a/txt/cmds.txt b/txt/cmds.txt deleted file mode 100644 index 621a128..0000000 --- a/txt/cmds.txt +++ /dev/null @@ -1,9 +0,0 @@ -**$cmds** - list the commands that can be used with this bot. - -**$poll collegeYear** - post a college year reaction poll. All active polls made by this bot work, you can use this to summon a poll anywhere for newcomers. - -**$poll collegeStaff** - post a college occupation reaction poll. - -**$assign role** - assign yourself a role, where **role** is: *prefrosh*, *freshman*, *sophomore*, *junior*, *senior*, *gradstudent*, *alumni*, *professor*, *tutor*, *ta*, *sileader*. - -**$assign clear** - this will only clear the roles mentioned above, **not** any special roles, like *leet gamer* or *club mod*. \ No newline at end of file