Repository: TheOdinProject/odin-bot-v2
Pull request #425 (2023-09-25 07:49:52)

Bump @discordjs/rest from 1.7.1 to 2.0.1
Bumps [@discordjs/rest](https://github.com/discordjs/discord.js/tree/HEAD/packages/rest) from 1.7.1 to 2.0.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/discordjs/discord.js/releases"><code>@​discordjs/rest</code>'s releases</a>.</em></p>
<blockquote>
<h2><code>@​discordjs/rest</code><a href="https://github.com/2"><code>@​2</code></a>.0.0</h2>
<h2>Features</h2>
<ul>
<li>No-de-no-de, now with extra buns (<a href="https://github.com/discordjs/discord.js/tree/HEAD/packages/rest/issues/9683">#9683</a>) (<a href="https://github.com/discordjs/discord.js/commit/386f206caf74a04c426799af9796ca96dcb37056">386f206</a>)
<ul>
<li><strong>BREAKING CHANGE:</strong> The REST and RequestManager classes now extend AsyncEventEmitter
from <code>@vladfrangu/async_event_emitter</code>, which aids in cross-compatibility
between Node, Deno, Bun, CF Workers, Vercel Functions, etc.</li>
<li><strong>BREAKING CHANGE:</strong> DefaultUserAgentAppendix has been adapted to support multiple
different platforms (previously mentioned Deno, Bun, CF Workers, etc)</li>
<li><strong>BREAKING CHANGE:</strong> the entry point for <code>@discordjs/rest</code> will now differ
in non-node-like environments (CF Workers, etc.)</li>
</ul>
</li>
<li>User avatar decorations (<a href="https://github.com/discordjs/discord.js/tree/HEAD/packages/rest/issues/8914">#8914</a>) (<a href="https://github.com/discordjs/discord.js/commit/8d9701745840e23854e8f0b057d21cb10e7d1d54">8d97017</a>)</li>
<li>Support new username system (<a href="https://github.com/discordjs/discord.js/tree/HEAD/packages/rest/issues/9512">#9512</a>) (<a href="https://github.com/discordjs/discord.js/commit/1ab60f9da4d6b7ea144fa05b97b029a4bfaeede2">1ab60f9</a>)</li>
</ul>
<h2>Refactor</h2>
<ul>
<li><strong>REST:</strong> Remove double classing (<a href="https://github.com/discordjs/discord.js/tree/HEAD/packages/rest/issues/9722">#9722</a>) (<a href="https://github.com/discordjs/discord.js/commit/8f4256db8a52ac08359d0b3436f41b641ac4e382">8f4256d</a>)
<ul>
<li><strong>BREAKING CHANGE:</strong> <code>REST</code> and <code>RequestManager</code> have been combined, most of the properties, methods, and events from both classes can now be found on <code>REST</code></li>
<li><strong>BREAKING CHANGE:</strong> <code>REST#raw</code> has been removed in favor of <code>REST#queueRequest</code></li>
<li><strong>BREAKING CHANGE:</strong> <code>REST#getAgent</code> has been removed in favor of <code>REST#agent</code></li>
</ul>
</li>
</ul>
<ul>
<li>chore: update for /rest changes</li>
</ul>
<ul>
<li><strong>rest:</strong> Switch api to fetch-like and provide strategies (<a href="https://github.com/discordjs/discord.js/tree/HEAD/packages/rest/issues/9416">#9416</a>) (<a href="https://github.com/discordjs/discord.js/commit/cdaa0a36f586459f1e5ede868c4250c7da90455c">cdaa0a3</a>)
<ul>
<li><strong>BREAKING CHANGE:</strong> NodeJS v18+ is required when using node due to the use of global <code>fetch</code></li>
<li><strong>BREAKING CHANGE:</strong> The raw method of REST now returns a web compatible <code>Respone</code> object.</li>
<li><strong>BREAKING CHANGE:</strong> The <code>parseResponse</code> utility method has been updated to operate on a web compatible <code>Response</code> object.</li>
<li><strong>BREAKING CHANGE:</strong> Many underlying internals have changed, some of which were exported.</li>
<li><strong>BREAKING CHANGE:</strong> <code>DefaultRestOptions</code> used to contain a default <code>agent</code>, which is now set to <code>null</code> instead.</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/discordjs/discord.js/blob/main/packages/rest/CHANGELOG.md"><code>@​discordjs/rest</code>'s changelog</a>.</em></p>
<blockquote>
<h1><a href="https://github.com/discordjs/discord.js/compare/@discordjs/rest@2.0.0...@discordjs/rest@2.0.1"><code>@​discordjs/rest</code><code>@​2.0.1</code></a> - (2023-08-17)</h1>
<h2>Documentation</h2>
<ul>
<li>Update Node.js requirement to 16.11.0 (<a href="https://github.com/discordjs/discord.js/tree/HEAD/packages/rest/issues/9764">#9764</a>) (<a href="https://github.com/discordjs/discord.js/commit/188877c50af70f0d5cffb246620fa277435c6ce6">188877c</a>)</li>
</ul>
<h1><a href="https://github.com/discordjs/discord.js/compare/@discordjs/rest@1.7.1...@discordjs/rest@2.0.0"><code>@​discordjs/rest</code><code>@​2.0.0</code></a> - (2023-07-31)</h1>
<h2>Features</h2>
<ul>
<li>No-de-no-de, now with extra buns (<a href="https://github.com/discordjs/discord.js/tree/HEAD/packages/rest/issues/9683">#9683</a>) (<a href="https://github.com/discordjs/discord.js/commit/386f206caf74a04c426799af9796ca96dcb37056">386f206</a>)
<ul>
<li><strong>BREAKING CHANGE:</strong> The REST and RequestManager classes now extend AsyncEventEmitter
from <code>@vladfrangu/async_event_emitter</code>, which aids in cross-compatibility
between Node, Deno, Bun, CF Workers, Vercel Functions, etc.</li>
<li><strong>BREAKING CHANGE:</strong> DefaultUserAgentAppendix has been adapted to support multiple
different platforms (previously mentioned Deno, Bun, CF Workers, etc)</li>
<li><strong>BREAKING CHANGE:</strong> the entry point for <code>@discordjs/rest</code> will now differ
in non-node-like environments (CF Workers, etc.)</li>
<li><strong>Co-authored-by:</strong> Suneet Tipirneni <a href="mailto:77477100+suneettipirneni@users.noreply.github.com">77477100+suneettipirneni@users.noreply.github.com</a></li>
<li><strong>Co-authored-by:</strong> Jiralite <a href="mailto:33201955+Jiralite@users.noreply.github.com">33201955+Jiralite@users.noreply.github.com</a></li>
<li><strong>Co-authored-by:</strong> suneettipirneni <a href="mailto:suneettipirneni@icloud.com">suneettipirneni@icloud.com</a></li>
</ul>
</li>
<li>User avatar decorations (<a href="https://github.com/discordjs/discord.js/tree/HEAD/packages/rest/issues/8914">#8914</a>) (<a href="https://github.com/discordjs/discord.js/commit/8d9701745840e23854e8f0b057d21cb10e7d1d54">8d97017</a>)</li>
<li>Support new username system (<a href="https://github.com/discordjs/discord.js/tree/HEAD/packages/rest/issues/9512">#9512</a>) (<a href="https://github.com/discordjs/discord.js/commit/1ab60f9da4d6b7ea144fa05b97b029a4bfaeede2">1ab60f9</a>)</li>
</ul>
<h2>Refactor</h2>
<ul>
<li><strong>REST:</strong> Remove double classing (<a href="https://github.com/discordjs/discord.js/tree/HEAD/packages/rest/issues/9722">#9722</a>) (<a href="https://github.com/discordjs/discord.js/commit/8f4256db8a52ac08359d0b3436f41b641ac4e382">8f4256d</a>)
<ul>
<li><strong>BREAKING CHANGE:</strong> <code>REST</code> and <code>RequestManager</code> have been combined, most of the properties, methods, and events from both classes can now be found on <code>REST</code></li>
<li><strong>BREAKING CHANGE:</strong> <code>REST#raw</code> has been removed in favor of <code>REST#queueRequest</code></li>
<li><strong>BREAKING CHANGE:</strong> <code>REST#getAgent</code> has been removed in favor of <code>REST#agent</code></li>
</ul>
</li>
</ul>
<ul>
<li>chore: update for /rest changes</li>
</ul>
<ul>
<li><strong>rest:</strong> Switch api to fetch-like and provide strategies (<a href="https://github.com/discordjs/discord.js/tree/HEAD/packages/rest/issues/9416">#9416</a>) (<a href="https://github.com/discordjs/discord.js/commit/cdaa0a36f586459f1e5ede868c4250c7da90455c">cdaa0a3</a>)
<ul>
<li><strong>BREAKING CHANGE:</strong> NodeJS v18+ is required when using node due to the use of global <code>fetch</code></li>
<li><strong>BREAKING CHANGE:</strong> The raw method of REST now returns a web compatible <code>Respone</code> object.</li>
<li><strong>BREAKING CHANGE:</strong> The <code>parseResponse</code> utility method has been updated to operate on a web compatible <code>Response</code> object.</li>
<li><strong>BREAKING CHANGE:</strong> Many underlying internals have changed, some of which were exported.</li>
<li><strong>BREAKING CHANGE:</strong> <code>DefaultRestOptions</code> used to contain a default <code>agent</code>, which is now set to <code>null</code> instead.</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/discordjs/discord.js/commit/84ead6e5540b519d2fcdeb4628be0a7346983d3c"><code>84ead6e</code></a> chore(rest): release <code>@​discordjs/rest</code><a href="https://github.com/2"><code>@​2</code></a>.0.1</li>
<li><a href="https://github.com/discordjs/discord.js/commit/7fa9ea3f0f8e91cb21a6359857af492bf9418321"><code>7fa9ea3</code></a> chore: pin discord-api-deps, revert undici</li>
<li><a href="https://github.com/discordjs/discord.js/commit/99cadfd82bcc9884c7dfe3bda64a368b91af430c"><code>99cadfd</code></a> chore: deps</li>
<li><a href="https://github.com/discordjs/discord.js/commit/188877c50af70f0d5cffb246620fa277435c6ce6"><code>188877c</code></a> docs: Update Node.js requirement to 16.11.0 (<a href="https://github.com/discordjs/discord.js/tree/HEAD/packages/rest/issues/9764">#9764</a>)</li>
<li><a href="https://github.com/discordjs/discord.js/commit/a1605b3a5e8b614ab768c431b24c5d3b0295e9fd"><code>a1605b3</code></a> build: Update vite and other related dependencies (<a href="https://github.com/discordjs/discord.js/tree/HEAD/packages/rest/issues/9772">#9772</a>)</li>
<li><a href="https://github.com/discordjs/discord.js/commit/d04987f09be7b4b8a075620afe186f1ccce63ede"><code>d04987f</code></a> chore(rest): release <code>@​discordjs/rest</code><a href="https://github.com/2"><code>@​2</code></a>.0.0</li>
<li><a href="https://github.com/discordjs/discord.js/commit/fd8197fe5b52bdd219e434268f5ed7a8f67870c6"><code>fd8197f</code></a> chore: deps</li>
<li><a href="https://github.com/discordjs/discord.js/commit/8f4256db8a52ac08359d0b3436f41b641ac4e382"><code>8f4256d</code></a> refactor(REST): remove double classing (<a href="https://github.com/discordjs/discord.js/tree/HEAD/packages/rest/issues/9722">#9722</a>)</li>
<li><a href="https://github.com/discordjs/discord.js/commit/d26e022afcc84448bb91deb4dd621aea20df6617"><code>d26e022</code></a> chore: deps</li>
<li><a href="https://github.com/discordjs/discord.js/commit/afa98793cdb5b5aa5a600070c3c29ffa1f80265f"><code>afa9879</code></a> chore: deps</li>
<li>Additional commits viewable in <a href="https://github.com/discordjs/discord.js/commits/@discordjs/rest@2.0.1/packages/rest">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@discordjs/rest&package-manager=npm_and_yarn&previous-version=1.7.1&new-version=2.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/bin/deploy-commands.js b/bin/deploy-commands.js
index f698a9d..cdce16e 100644
--- a/bin/deploy-commands.js
+++ b/bin/deploy-commands.js
@@ -1,6 +1,7 @@
 // SCRIPT TO REGISTER THE NEW DISCORD COMMANDS
 // Commands can be deployed directly from terminal with: node bin/deploy-commands.js
 
+/* eslint import/no-unresolved: 2 */
 const { REST } = require('@discordjs/rest');
 const { Routes } = require('discord.js');
 const { clientId, guildId, token } = require('../config');
diff --git a/botCommands/google-legacy.js b/botCommands/google-legacy.js
new file mode 100644
index 0000000..12e7936
--- /dev/null
+++ b/botCommands/google-legacy.js
@@ -0,0 +1,18 @@
+const { EmbedBuilder } = require('discord.js');
+const { registerBotCommand } = require('../botEngine');
+
+const command = {
+  regex: /\B!google\s+.+/,
+  cb: ({ content }) => {
+    const prompt = content.match(/\B!google\s+(.+)/)[1];
+    const searchUrl = `https://www.google.com/search?q=${prompt.replaceAll(' ', '+')}`;
+    const googleEmbed = new EmbedBuilder()
+      .setColor('#cc9543')
+      .setTitle('Search Google')
+      .setDescription(`This [Google query for "${prompt}"](${searchUrl}) might help you find what you're looking for.`);
+    return { embeds: [googleEmbed]};
+  }
+};
+registerBotCommand(command.regex, command.cb);
+
+module.exports = command;
\ No newline at end of file
diff --git a/botCommands/searchtop-legacy.js b/botCommands/searchtop-legacy.js
new file mode 100644
index 0000000..77672ea
--- /dev/null
+++ b/botCommands/searchtop-legacy.js
@@ -0,0 +1,18 @@
+const { EmbedBuilder } = require('discord.js');
+const { registerBotCommand } = require('../botEngine');
+
+const command = {
+  regex: /\B!searchtop\s+.+/,
+  cb: ({ content }) => {
+    const prompt = content.match(/\B!searchtop\s+(.+)/)[1];
+    const searchUrl = `https://www.google.com/search?q=site:theodinproject.com+${prompt.replaceAll(' ', '+')}`;
+    const topEmbed = new EmbedBuilder()
+      .setColor('#cc9543')
+      .setTitle('Search TOP')
+      .setDescription(`Here are the [Google results for TOP lessons containing "${prompt}"](${searchUrl})`);
+    return { embeds: [topEmbed]};
+  }
+};
+registerBotCommand(command.regex, command.cb);
+
+module.exports = command;
diff --git a/botCommands/simpleCommands.js b/botCommands/simpleCommands.js
deleted file mode 100644
index 23ced09..0000000
--- a/botCommands/simpleCommands.js
+++ /dev/null
@@ -1,104 +0,0 @@
-const Discord = require('discord.js');
-const { registerBotCommand } = require('../botEngine');
-
-const hug = {
-  regex: /(?<!\S)!hug(?!\S)/,
-  cb: () => '⊂(´・ω・｀⊂)',
-};
-registerBotCommand(hug.regex, hug.cb);
-
-const smart = {
-  regex: /(?<!\S)!smart(?!\S)/,
-  cb: () => String.raw`f(ಠ‿↼)z`,
-};
-registerBotCommand(smart.regex, smart.cb);
-
-const lenny = {
-  regex: /(?<!\S)!lenny(?!\S)/,
-  cb: () => String.raw`( ͡° ͜ʖ ͡°)`,
-};
-registerBotCommand(lenny.regex, lenny.cb);
-
-const fu = {
-  regex: /(?<!\S)!fu(?!\S)/,
-  cb: async (message) => {
-    await message.reply('http://media.riffsy.com/images/636a97aa416ad674eb2b72d4a6e9ad6c/tenor.gif');
-    return null;
-  },
-};
-registerBotCommand(fu.regex, fu.cb);
-
-const data = {
-  regex: /(?<!\S)!data(?!\S)/,
-  cb: () => {
-    const dataEmbed = new Discord.EmbedBuilder()
-      .setTitle('Don’t ask to ask!')
-      .setColor('#cc9543')
-      .setURL('https://www.dontasktoask.com/')
-      // this weird formating is needed because of some indentation on mobile
-      .setDescription(`
-Instead of asking if anyone can help you, ask your question outright with as much information as possible so people will know if they can help you.
-
-**Bad**: "Hey, anyone around that is really good with CSS?"
-
-**Good**:
-"Hey, I'm having trouble setting CSS styles via Javascript."
-
-**Project/Exercise:**
-**Lesson link:**
-**Code:** [code sandbox like replit or codepen]
-**Issue/Problem:** [screenshots if applicable]
-**What I expected:** 
-**What I've tried:** 
-
-**https://www.dontasktoask.com/**
-        `);
-
-    return { embeds: [dataEmbed] };
-  },
-};
-registerBotCommand(data.regex, data.cb);
-
-const google = {
-  regex: /\B!google\s+.+/,
-  cb: ({ content }) => {
-    const transform = (transformContent) => {
-      const query = transformContent.split(' ').map(encodeURIComponent).join('+');
-      return `**This query might help you find what you're looking for >** <https://google.com/search?q=${query}>`;
-    };
-
-    const query = content.match(/\B!google\s+(.+)/)[1];
-    return `${transform(query)}`;
-  },
-};
-registerBotCommand(google.regex, google.cb);
-
-const dab = {
-  regex: /(?<!\S)!dab(?!\S)/,
-  cb: () => 'https://tenor.com/view/bettywhite-dab-gif-5044603',
-};
-registerBotCommand(dab.regex, dab.cb);
-
-const motivate = {
-  regex: /(?<!\S)!motivate(?!\S)/,
-  cb: () => 'Don\'t give up! https://www.youtube.com/watch?v=KxGRhd_iWuE',
-};
-registerBotCommand(motivate.regex, motivate.cb);
-
-const justDoIt = {
-  regex: /(?<!\S)!justdoit(?!\S)/,
-  cb: () => 'What are you waiting for?! https://www.youtube.com/watch?v=ZXsQAXx_ao0',
-};
-registerBotCommand(justDoIt.regex, justDoIt.cb);
-
-module.exports = {
-  hug,
-  smart,
-  lenny,
-  fu,
-  data,
-  google,
-  dab,
-  motivate,
-  justDoIt,
-};
diff --git a/new-era-commands/slash/bootcamps.js b/new-era-commands/slash/bootcamps.js
new file mode 100644
index 0000000..2f940ec
--- /dev/null
+++ b/new-era-commands/slash/bootcamps.js
@@ -0,0 +1,25 @@
+const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
+
+module.exports = {
+  data: new SlashCommandBuilder()
+    .setName('bootcamps')
+    .setDescription('Info about bootcamps, which we think you should read')
+    .addUserOption((option) => option.setName('user').setDescription('user to ping')),
+  execute: async (interaction) => {
+    const userId = interaction.options.getUser('user');
+
+    const bootcampEmbed = new EmbedBuilder()
+      .setColor('#cc9543')
+      .setTitle('Bootcamps, be informed!')
+      .setDescription(`
+Friends don't let friends commit to bootcamps without being informed.
+
+Give this [web archive twitter thread about bootcamps](https://web.archive.org/web/20220410160426/https://twitter.com/lzsthw/status/1212284566431576069) a read to learn more about things to consider and watch out for.
+      `);
+
+    await interaction.reply({
+      content: userId ? `${userId}` : '',
+      embeds: [bootcampEmbed],
+    });
+  },
+};
diff --git a/new-era-commands/slash/callbacks.js b/new-era-commands/slash/callbacks.js
new file mode 100644
index 0000000..e10930e
--- /dev/null
+++ b/new-era-commands/slash/callbacks.js
@@ -0,0 +1,23 @@
+const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
+
+module.exports = {
+  data: new SlashCommandBuilder()
+    .setName('callbacks')
+    .setDescription('Article about callbacks')
+    .addUserOption((option) => option.setName('user').setDescription('user to ping')),
+  execute: async (interaction) => {
+    const userId = interaction.options.getUser('user');
+
+    const cbEmbed = new EmbedBuilder()
+      .setColor('#cc9543')
+      .setTitle('Did someone say CALLBACKS?!')
+      .setDescription(`
+[This article about callbacks](https://briggs.dev/blog/understanding-callbacks) has helped many people already. We suggest you give it a read!
+      `);
+
+    await interaction.reply({
+      content: userId ? `${userId}` : '',
+      embeds: [cbEmbed],
+    });
+  },
+};
diff --git a/new-era-commands/slash/faq.js b/new-era-commands/slash/faq.js
new file mode 100644
index 0000000..4e4085f
--- /dev/null
+++ b/new-era-commands/slash/faq.js
@@ -0,0 +1,25 @@
+const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
+
+module.exports = {
+  data: new SlashCommandBuilder()
+    .setName('faq')
+    .setDescription('Provides a link to our FAQ channel')
+    .addUserOption((option) => option.setName('user').setDescription('user to ping')),
+  execute: async (interaction) => {
+    const userId = interaction.options.getUser('user');
+
+    const faqEmbed = new EmbedBuilder()
+      .setColor('#cc9543')
+      .setTitle('Our TOP Discord FAQ')
+      .setDescription(`
+*"The definition of insanity is answering the same question over and over again"*
+
+We have a [channel with frequently asked questions](https://discord.com/channels/505093832157691914/823266307293839401/823266549912829992)!
+Help us stay sane by giving it a read.
+      `);
+    await interaction.reply({
+      content: userId ? `${userId}` : '',
+      embeds: [faqEmbed],
+    });
+  },
+};
diff --git a/new-era-commands/slash/microverse.js b/new-era-commands/slash/microverse.js
new file mode 100644
index 0000000..53447c3
--- /dev/null
+++ b/new-era-commands/slash/microverse.js
@@ -0,0 +1,21 @@
+const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
+
+module.exports = {
+  data: new SlashCommandBuilder()
+    .setName('microverse')
+    .setDescription('Information about Microverse using The Odin Project\'s content without permission')
+    .addUserOption((option) => option.setName('user').setDescription('user to ping')),
+  execute: async (interaction) => {
+    const userId = interaction.options.getUser('user');
+    const mvEmbed = new EmbedBuilder()
+      .setColor('#cc9543')
+      .setTitle('TOP is not affiliated with Microverse')
+      .setDescription(`
+Microverse is using The Odin Project's licensed content without permission. Please read [this statement we have made about that on Discord](https://discord.com/channels/505093832157691914/505093832157691916/781170792095809547)
+      `);
+    await interaction.reply({
+      content: userId ? `${userId}` : '',
+      embeds: [mvEmbed],
+    });
+  },
+};
diff --git a/new-era-commands/slash/research.js b/new-era-commands/slash/research.js
new file mode 100644
index 0000000..9e71036
--- /dev/null
+++ b/new-era-commands/slash/research.js
@@ -0,0 +1,35 @@
+const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
+
+module.exports = {
+  data: new SlashCommandBuilder()
+    .setName('research')
+    .setDescription("Our stance on doing your own research and asking questions")
+    .addUserOption((option) => option.setName('user').setDescription('user to ping')),
+  execute: async (interaction) => {
+    const userId = interaction.options.getUser('user');
+
+    const researchEmbed = new EmbedBuilder()
+      .setTitle('Asking questions in the TOP Discord')
+      .setColor('#cc9543')
+      .setDescription(`
+"Here's my take on asking questions here:
+
+Naturally, we welcome them. But we will hold you accountable when you ask a question that is easily researched. Not because we think you're a jerk. But because independent research is so critical to your continued learning.
+
+Imagine you are on your first job and you went to your lead dev for questions every few minutes. I'm sure they'd be happy to help but a better situation is if you do some initial research on your own then take what you've found to your lead if you still have questions.
+
+That's a very different conversation from: *"Hey, I have no idea about this. Please tell me everything."*
+
+vs
+
+*"So I did some research. This is what I understand. And this is what I don't understand. Can you help clarify this last bit?"*
+
+So yeah, feel free to continue to ask. But make sure you are doing your part by doing the research. This helps all of us grow.",
+       `)
+
+    await interaction.reply({
+      content: userId ? `${userId}` : '',
+      embeds: [researchEmbed],
+    });
+  },
+};
diff --git a/package-lock.json b/package-lock.json
index 970554b..c2a2ebc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,14 +9,14 @@
       "version": "1.0.0",
       "license": "ISC",
       "dependencies": {
-        "@discordjs/rest": "^1.7.1",
+        "@discordjs/rest": "^2.0.1",
         "axios": "^1.5.0",
         "discord-api-types": "^0.37.56",
         "discord.js": "^14.13.0",
         "dotenv": "^16.3.1",
         "glob": "^10.3.3",
         "ioredis": "^5.3.2",
-        "prettier": "^3.0.2"
+        "prettier": "^3.0.3"
       },
       "devDependencies": {
         "@babel/eslint-parser": "^7.22.9",
@@ -2002,14 +2002,6 @@
         "node": ">=16.11.0"
       }
     },
-    "node_modules/@discordjs/builders/node_modules/@discordjs/util": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.1.tgz",
-      "integrity": "sha512-d0N2yCxB8r4bn00/hvFZwM7goDcUhtViC5un4hPj73Ba4yrChLSJD8fy7Ps5jpTLg1fE9n4K0xBLc1y9WGwSsA==",
-      "engines": {
-        "node": ">=16.11.0"
-      }
-    },
     "node_modules/@discordjs/builders/node_modules/discord-api-types": {
       "version": "0.37.50",
       "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.50.tgz",
@@ -2040,29 +2032,35 @@
       "integrity": "sha512-X4CDiMnDbA3s3RaUXWXmgAIbY1uxab3fqe3qwzg5XutR3wjqi7M3IkgQbsIBzpqBN2YWr/Qdv7JrFRqSgb4TFg=="
     },
     "node_modules/@discordjs/rest": {
-      "version": "1.7.1",
-      "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.7.1.tgz",
-      "integrity": "sha512-Ofa9UqT0U45G/eX86cURQnX7gzOJLG2oC28VhIk/G6IliYgQF7jFByBJEykPSHE4MxPhqCleYvmsrtfKh1nYmQ==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.0.1.tgz",
+      "integrity": "sha512-/eWAdDRvwX/rIE2tuQUmKaxmWeHmGealttIzGzlYfI4+a7y9b6ZoMp8BG/jaohs8D8iEnCNYaZiOFLVFLQb8Zg==",
       "dependencies": {
-        "@discordjs/collection": "^1.5.1",
-        "@discordjs/util": "^0.3.0",
+        "@discordjs/collection": "^1.5.3",
+        "@discordjs/util": "^1.0.1",
         "@sapphire/async-queue": "^1.5.0",
-        "@sapphire/snowflake": "^3.4.2",
-        "discord-api-types": "^0.37.41",
-        "file-type": "^18.3.0",
-        "tslib": "^2.5.0",
-        "undici": "^5.22.0"
+        "@sapphire/snowflake": "^3.5.1",
+        "@vladfrangu/async_event_emitter": "^2.2.2",
+        "discord-api-types": "0.37.50",
+        "magic-bytes.js": "^1.0.15",
+        "tslib": "^2.6.1",
+        "undici": "5.22.1"
       },
       "engines": {
-        "node": ">=16.9.0"
+        "node": ">=16.11.0"
       }
     },
+    "node_modules/@discordjs/rest/node_modules/discord-api-types": {
+      "version": "0.37.50",
+      "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.50.tgz",
+      "integrity": "sha512-X4CDiMnDbA3s3RaUXWXmgAIbY1uxab3fqe3qwzg5XutR3wjqi7M3IkgQbsIBzpqBN2YWr/Qdv7JrFRqSgb4TFg=="
+    },
     "node_modules/@discordjs/util": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.3.1.tgz",
-      "integrity": "sha512-HxXKYKg7vohx2/OupUN/4Sd02Ev3PBJ5q0gtjdcvXb0ErCva8jNHWfe/v5sU3UKjIB/uxOhc+TDOnhqffj9pRA==",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.1.tgz",
+      "integrity": "sha512-d0N2yCxB8r4bn00/hvFZwM7goDcUhtViC5un4hPj73Ba4yrChLSJD8fy7Ps5jpTLg1fE9n4K0xBLc1y9WGwSsA==",
       "engines": {
-        "node": ">=16.9.0"
+        "node": ">=16.11.0"
       }
     },
     "node_modules/@discordjs/ws": {
@@ -2084,33 +2082,6 @@
         "node": ">=16.11.0"
       }
     },
-    "node_modules/@discordjs/ws/node_modules/@discordjs/rest": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.0.1.tgz",
-      "integrity": "sha512-/eWAdDRvwX/rIE2tuQUmKaxmWeHmGealttIzGzlYfI4+a7y9b6ZoMp8BG/jaohs8D8iEnCNYaZiOFLVFLQb8Zg==",
-      "dependencies": {
-        "@discordjs/collection": "^1.5.3",
-        "@discordjs/util": "^1.0.1",
-        "@sapphire/async-queue": "^1.5.0",
-        "@sapphire/snowflake": "^3.5.1",
-        "@vladfrangu/async_event_emitter": "^2.2.2",
-        "discord-api-types": "0.37.50",
-        "magic-bytes.js": "^1.0.15",
-        "tslib": "^2.6.1",
-        "undici": "5.22.1"
-      },
-      "engines": {
-        "node": ">=16.11.0"
-      }
-    },
-    "node_modules/@discordjs/ws/node_modules/@discordjs/util": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.1.tgz",
-      "integrity": "sha512-d0N2yCxB8r4bn00/hvFZwM7goDcUhtViC5un4hPj73Ba4yrChLSJD8fy7Ps5jpTLg1fE9n4K0xBLc1y9WGwSsA==",
-      "engines": {
-        "node": ">=16.11.0"
-      }
-    },
     "node_modules/@discordjs/ws/node_modules/discord-api-types": {
       "version": "0.37.50",
       "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.50.tgz",
@@ -2823,11 +2794,6 @@
         "@sinonjs/commons": "^3.0.0"
       }
     },
-    "node_modules/@tokenizer/token": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
-      "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="
-    },
     "node_modules/@types/babel__core": {
       "version": "7.20.1",
       "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz",
@@ -3899,33 +3865,6 @@
         "node": ">=16.11.0"
       }
     },
-    "node_modules/discord.js/node_modules/@discordjs/rest": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.0.1.tgz",
-      "integrity": "sha512-/eWAdDRvwX/rIE2tuQUmKaxmWeHmGealttIzGzlYfI4+a7y9b6ZoMp8BG/jaohs8D8iEnCNYaZiOFLVFLQb8Zg==",
-      "dependencies": {
-        "@discordjs/collection": "^1.5.3",
-        "@discordjs/util": "^1.0.1",
-        "@sapphire/async-queue": "^1.5.0",
-        "@sapphire/snowflake": "^3.5.1",
-        "@vladfrangu/async_event_emitter": "^2.2.2",
-        "discord-api-types": "0.37.50",
-        "magic-bytes.js": "^1.0.15",
-        "tslib": "^2.6.1",
-        "undici": "5.22.1"
-      },
-      "engines": {
-        "node": ">=16.11.0"
-      }
-    },
-    "node_modules/discord.js/node_modules/@discordjs/util": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.1.tgz",
-      "integrity": "sha512-d0N2yCxB8r4bn00/hvFZwM7goDcUhtViC5un4hPj73Ba4yrChLSJD8fy7Ps5jpTLg1fE9n4K0xBLc1y9WGwSsA==",
-      "engines": {
-        "node": ">=16.11.0"
-      }
-    },
     "node_modules/discord.js/node_modules/discord-api-types": {
       "version": "0.37.50",
       "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.50.tgz",
@@ -4732,22 +4671,6 @@
         "node": "^10.12.0 || >=12.0.0"
       }
     },
-    "node_modules/file-type": {
-      "version": "18.3.0",
-      "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.3.0.tgz",
-      "integrity": "sha512-pkPZ5OGIq0TYb37b8bHDLNeQSe1H2KlaQ2ySGpJkkr2KZdaWsO4QhPzHA0mQcsUW2cSqJk+4gM/UyLz/UFbXdQ==",
-      "dependencies": {
-        "readable-web-to-node-stream": "^3.0.2",
-        "strtok3": "^7.0.0",
-        "token-types": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=14.16"
-      },
-      "funding": {
-        "url": "https://github.com/sindresorhus/file-type?sponsor=1"
-      }
-    },
     "node_modules/fill-range": {
       "version": "7.0.1",
       "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -5189,25 +5112,6 @@
         "url": "https://github.com/sponsors/typicode"
       }
     },
-    "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/ignore": {
       "version": "5.2.4",
       "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
@@ -5280,7 +5184,8 @@
     "node_modules/inherits": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true
     },
     "node_modules/internal-slot": {
       "version": "1.0.5",
@@ -7261,18 +7166,6 @@
         "node": "14 || >=16.14"
       }
     },
-    "node_modules/peek-readable": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz",
-      "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==",
-      "engines": {
-        "node": ">=14.16"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/Borewit"
-      }
-    },
     "node_modules/picocolors": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
@@ -7334,9 +7227,9 @@
       }
     },
     "node_modules/prettier": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.2.tgz",
-      "integrity": "sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
+      "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
       "bin": {
         "prettier": "bin/prettier.cjs"
       },
@@ -7448,34 +7341,6 @@
       "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
       "dev": true
     },
-    "node_modules/readable-stream": {
-      "version": "3.6.2",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
-      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
-      "dependencies": {
-        "inherits": "^2.0.3",
-        "string_decoder": "^1.1.1",
-        "util-deprecate": "^1.0.1"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/readable-web-to-node-stream": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz",
-      "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==",
-      "dependencies": {
-        "readable-stream": "^3.6.0"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/Borewit"
-      }
-    },
     "node_modules/readdirp": {
       "version": "3.6.0",
       "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
@@ -7959,33 +7824,6 @@
         "node": ">=10.0.0"
       }
     },
-    "node_modules/string_decoder": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
-      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
-      "dependencies": {
-        "safe-buffer": "~5.2.0"
-      }
-    },
-    "node_modules/string_decoder/node_modules/safe-buffer": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-      "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/string-argv": {
       "version": "0.3.2",
       "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
@@ -8133,22 +7971,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/strtok3": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz",
-      "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==",
-      "dependencies": {
-        "@tokenizer/token": "^0.3.0",
-        "peek-readable": "^5.0.0"
-      },
-      "engines": {
-        "node": ">=14.16"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/Borewit"
-      }
-    },
     "node_modules/supports-color": {
       "version": "7.2.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -8240,22 +8062,6 @@
         "node": ">=8.0"
       }
     },
-    "node_modules/token-types": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz",
-      "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==",
-      "dependencies": {
-        "@tokenizer/token": "^0.3.0",
-        "ieee754": "^1.2.1"
-      },
-      "engines": {
-        "node": ">=14.16"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/Borewit"
-      }
-    },
     "node_modules/touch": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
@@ -8520,11 +8326,6 @@
         "punycode": "^2.1.0"
       }
     },
-    "node_modules/util-deprecate": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
-    },
     "node_modules/v8-to-istanbul": {
       "version": "9.1.0",
       "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz",
@@ -10131,11 +9932,6 @@
         "tslib": "^2.6.1"
       },
       "dependencies": {
-        "@discordjs/util": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.1.tgz",
-          "integrity": "sha512-d0N2yCxB8r4bn00/hvFZwM7goDcUhtViC5un4hPj73Ba4yrChLSJD8fy7Ps5jpTLg1fE9n4K0xBLc1y9WGwSsA=="
-        },
         "discord-api-types": {
           "version": "0.37.50",
           "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.50.tgz",
@@ -10164,24 +9960,32 @@
       }
     },
     "@discordjs/rest": {
-      "version": "1.7.1",
-      "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.7.1.tgz",
-      "integrity": "sha512-Ofa9UqT0U45G/eX86cURQnX7gzOJLG2oC28VhIk/G6IliYgQF7jFByBJEykPSHE4MxPhqCleYvmsrtfKh1nYmQ==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.0.1.tgz",
+      "integrity": "sha512-/eWAdDRvwX/rIE2tuQUmKaxmWeHmGealttIzGzlYfI4+a7y9b6ZoMp8BG/jaohs8D8iEnCNYaZiOFLVFLQb8Zg==",
       "requires": {
-        "@discordjs/collection": "^1.5.1",
-        "@discordjs/util": "^0.3.0",
+        "@discordjs/collection": "^1.5.3",
+        "@discordjs/util": "^1.0.1",
         "@sapphire/async-queue": "^1.5.0",
-        "@sapphire/snowflake": "^3.4.2",
-        "discord-api-types": "^0.37.41",
-        "file-type": "^18.3.0",
-        "tslib": "^2.5.0",
-        "undici": "^5.22.0"
+        "@sapphire/snowflake": "^3.5.1",
+        "@vladfrangu/async_event_emitter": "^2.2.2",
+        "discord-api-types": "0.37.50",
+        "magic-bytes.js": "^1.0.15",
+        "tslib": "^2.6.1",
+        "undici": "5.22.1"
+      },
+      "dependencies": {
+        "discord-api-types": {
+          "version": "0.37.50",
+          "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.50.tgz",
+          "integrity": "sha512-X4CDiMnDbA3s3RaUXWXmgAIbY1uxab3fqe3qwzg5XutR3wjqi7M3IkgQbsIBzpqBN2YWr/Qdv7JrFRqSgb4TFg=="
+        }
       }
     },
     "@discordjs/util": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.3.1.tgz",
-      "integrity": "sha512-HxXKYKg7vohx2/OupUN/4Sd02Ev3PBJ5q0gtjdcvXb0ErCva8jNHWfe/v5sU3UKjIB/uxOhc+TDOnhqffj9pRA=="
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.1.tgz",
+      "integrity": "sha512-d0N2yCxB8r4bn00/hvFZwM7goDcUhtViC5un4hPj73Ba4yrChLSJD8fy7Ps5jpTLg1fE9n4K0xBLc1y9WGwSsA=="
     },
     "@discordjs/ws": {
       "version": "1.0.1",
@@ -10199,27 +10003,6 @@
         "ws": "^8.13.0"
       },
       "dependencies": {
-        "@discordjs/rest": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.0.1.tgz",
-          "integrity": "sha512-/eWAdDRvwX/rIE2tuQUmKaxmWeHmGealttIzGzlYfI4+a7y9b6ZoMp8BG/jaohs8D8iEnCNYaZiOFLVFLQb8Zg==",
-          "requires": {
-            "@discordjs/collection": "^1.5.3",
-            "@discordjs/util": "^1.0.1",
-            "@sapphire/async-queue": "^1.5.0",
-            "@sapphire/snowflake": "^3.5.1",
-            "@vladfrangu/async_event_emitter": "^2.2.2",
-            "discord-api-types": "0.37.50",
-            "magic-bytes.js": "^1.0.15",
-            "tslib": "^2.6.1",
-            "undici": "5.22.1"
-          }
-        },
-        "@discordjs/util": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.1.tgz",
-          "integrity": "sha512-d0N2yCxB8r4bn00/hvFZwM7goDcUhtViC5un4hPj73Ba4yrChLSJD8fy7Ps5jpTLg1fE9n4K0xBLc1y9WGwSsA=="
-        },
         "discord-api-types": {
           "version": "0.37.50",
           "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.50.tgz",
@@ -10770,11 +10553,6 @@
         "@sinonjs/commons": "^3.0.0"
       }
     },
-    "@tokenizer/token": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
-      "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="
-    },
     "@types/babel__core": {
       "version": "7.20.1",
       "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz",
@@ -11570,27 +11348,6 @@
         "ws": "^8.13.0"
       },
       "dependencies": {
-        "@discordjs/rest": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.0.1.tgz",
-          "integrity": "sha512-/eWAdDRvwX/rIE2tuQUmKaxmWeHmGealttIzGzlYfI4+a7y9b6ZoMp8BG/jaohs8D8iEnCNYaZiOFLVFLQb8Zg==",
-          "requires": {
-            "@discordjs/collection": "^1.5.3",
-            "@discordjs/util": "^1.0.1",
-            "@sapphire/async-queue": "^1.5.0",
-            "@sapphire/snowflake": "^3.5.1",
-            "@vladfrangu/async_event_emitter": "^2.2.2",
-            "discord-api-types": "0.37.50",
-            "magic-bytes.js": "^1.0.15",
-            "tslib": "^2.6.1",
-            "undici": "5.22.1"
-          }
-        },
-        "@discordjs/util": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.1.tgz",
-          "integrity": "sha512-d0N2yCxB8r4bn00/hvFZwM7goDcUhtViC5un4hPj73Ba4yrChLSJD8fy7Ps5jpTLg1fE9n4K0xBLc1y9WGwSsA=="
-        },
         "discord-api-types": {
           "version": "0.37.50",
           "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.50.tgz",
@@ -12198,16 +11955,6 @@
         "flat-cache": "^3.0.4"
       }
     },
-    "file-type": {
-      "version": "18.3.0",
-      "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.3.0.tgz",
-      "integrity": "sha512-pkPZ5OGIq0TYb37b8bHDLNeQSe1H2KlaQ2ySGpJkkr2KZdaWsO4QhPzHA0mQcsUW2cSqJk+4gM/UyLz/UFbXdQ==",
-      "requires": {
-        "readable-web-to-node-stream": "^3.0.2",
-        "strtok3": "^7.0.0",
-        "token-types": "^5.0.1"
-      }
-    },
     "fill-range": {
       "version": "7.0.1",
       "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -12503,11 +12250,6 @@
       "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==",
       "dev": true
     },
-    "ieee754": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
-      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
-    },
     "ignore": {
       "version": "5.2.4",
       "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
@@ -12559,7 +12301,8 @@
     "inherits": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true
     },
     "internal-slot": {
       "version": "1.0.5",
@@ -14004,11 +13747,6 @@
         }
       }
     },
-    "peek-readable": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz",
-      "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A=="
-    },
     "picocolors": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
@@ -14049,9 +13787,9 @@
       "dev": true
     },
     "prettier": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.2.tgz",
-      "integrity": "sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ=="
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
+      "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg=="
     },
     "pretty-format": {
       "version": "29.6.1",
@@ -14117,24 +13855,6 @@
       "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
       "dev": true
     },
-    "readable-stream": {
-      "version": "3.6.2",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
-      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
-      "requires": {
-        "inherits": "^2.0.3",
-        "string_decoder": "^1.1.1",
-        "util-deprecate": "^1.0.1"
-      }
-    },
-    "readable-web-to-node-stream": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz",
-      "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==",
-      "requires": {
-        "readable-stream": "^3.6.0"
-      }
-    },
     "readdirp": {
       "version": "3.6.0",
       "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
@@ -14485,21 +14205,6 @@
       "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
       "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="
     },
-    "string_decoder": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
-      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
-      "requires": {
-        "safe-buffer": "~5.2.0"
-      },
-      "dependencies": {
-        "safe-buffer": {
-          "version": "5.2.1",
-          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-          "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
-        }
-      }
-    },
     "string-argv": {
       "version": "0.3.2",
       "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
@@ -14603,15 +14308,6 @@
       "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
       "dev": true
     },
-    "strtok3": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz",
-      "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==",
-      "requires": {
-        "@tokenizer/token": "^0.3.0",
-        "peek-readable": "^5.0.0"
-      }
-    },
     "supports-color": {
       "version": "7.2.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -14681,15 +14377,6 @@
         "is-number": "^7.0.0"
       }
     },
-    "token-types": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz",
-      "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==",
-      "requires": {
-        "@tokenizer/token": "^0.3.0",
-        "ieee754": "^1.2.1"
-      }
-    },
     "touch": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
@@ -14879,11 +14566,6 @@
         "punycode": "^2.1.0"
       }
     },
-    "util-deprecate": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
-    },
     "v8-to-istanbul": {
       "version": "9.1.0",
       "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz",
diff --git a/package.json b/package.json
index 94c571a..561ff38 100644
--- a/package.json
+++ b/package.json
@@ -12,14 +12,14 @@
   "author": "",
   "license": "ISC",
   "dependencies": {
-    "@discordjs/rest": "^1.7.1",
+    "@discordjs/rest": "^2.0.1",
     "axios": "^1.5.0",
     "discord-api-types": "^0.37.56",
     "discord.js": "^14.13.0",
     "dotenv": "^16.3.1",
     "glob": "^10.3.3",
     "ioredis": "^5.3.2",
-    "prettier": "^3.0.2"
+    "prettier": "^3.0.3"
   },
   "devDependencies": {
     "@babel/eslint-parser": "^7.22.9",


Test patch:
diff --git a/botCommands/__snapshots__/code.test.js.snap b/botCommands/__snapshots__/code-legacy.test.js.snap
similarity index 100%
rename from botCommands/__snapshots__/code.test.js.snap
rename to botCommands/__snapshots__/code-legacy.test.js.snap
diff --git a/botCommands/__snapshots__/google-legacy.test.js.snap b/botCommands/__snapshots__/google-legacy.test.js.snap
new file mode 100644
index 0000000..d2f767b
--- /dev/null
+++ b/botCommands/__snapshots__/google-legacy.test.js.snap
@@ -0,0 +1,13 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`!google callback returns correct output 1`] = `
+{
+  "embeds": [
+    {
+      "color": 13407555,
+      "description": "This [Google query for "The Odin Project"](https://www.google.com/search?q=The+Odin+Project) might help you find what you're looking for.",
+      "title": "Search Google",
+    },
+  ],
+}
+`;
diff --git a/botCommands/__snapshots__/searchtop-legacy.test.js.snap b/botCommands/__snapshots__/searchtop-legacy.test.js.snap
new file mode 100644
index 0000000..cb898e9
--- /dev/null
+++ b/botCommands/__snapshots__/searchtop-legacy.test.js.snap
@@ -0,0 +1,13 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`!searchtop callback returns correct output 1`] = `
+{
+  "embeds": [
+    {
+      "color": 13407555,
+      "description": "Here are the [Google results for TOP lessons containing "The Odin Project"](https://www.google.com/search?q=site:theodinproject.com+The+Odin+Project)",
+      "title": "Search TOP",
+    },
+  ],
+}
+`;
diff --git a/botCommands/__snapshots__/simpleCommands.test.js.snap b/botCommands/__snapshots__/simpleCommands.test.js.snap
deleted file mode 100644
index 0d52a83..0000000
--- a/botCommands/__snapshots__/simpleCommands.test.js.snap
+++ /dev/null
@@ -1,46 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`!dab callback returns correct output 1`] = `"https://tenor.com/view/bettywhite-dab-gif-5044603"`;
-
-exports[`!data callback returns correct output 1`] = `
-{
-  "embeds": [
-    {
-      "color": 13407555,
-      "description": "
-Instead of asking if anyone can help you, ask your question outright with as much information as possible so people will know if they can help you.
-
-**Bad**: "Hey, anyone around that is really good with CSS?"
-
-**Good**:
-"Hey, I'm having trouble setting CSS styles via Javascript."
-
-**Project/Exercise:**
-**Lesson link:**
-**Code:** [code sandbox like replit or codepen]
-**Issue/Problem:** [screenshots if applicable]
-**What I expected:** 
-**What I've tried:** 
-
-**https://www.dontasktoask.com/**
-        ",
-      "title": "Don’t ask to ask!",
-      "url": "https://www.dontasktoask.com/",
-    },
-  ],
-}
-`;
-
-exports[`!fu callback returns correct output 1`] = `"http:!!media.riffsy.com!images!636a97aa416ad674eb2b72d4a6e9ad6c!tenor.gif"`;
-
-exports[`!google callback returns correct output 1`] = `"**This query might help you find what you're looking for >** <https://google.com/search?q=The+Odin+Project>"`;
-
-exports[`!hug callback returns correct output 1`] = `"⊂(´・ω・｀⊂)"`;
-
-exports[`!justdoit callback returns correct output 1`] = `"What are you waiting for?! https://www.youtube.com/watch?v=ZXsQAXx_ao0"`;
-
-exports[`!lenny callback returns correct output 1`] = `"( ͡° ͜ʖ ͡°)"`;
-
-exports[`!motivate callback returns correct output 1`] = `"Don't give up! https://www.youtube.com/watch?v=KxGRhd_iWuE"`;
-
-exports[`!smart callback returns correct output 1`] = `"f(ಠ‿↼)z"`;
diff --git a/botCommands/__snapshots__/top.test.js.snap b/botCommands/__snapshots__/top-legacy.test.js.snap
similarity index 100%
rename from botCommands/__snapshots__/top.test.js.snap
rename to botCommands/__snapshots__/top-legacy.test.js.snap
diff --git a/botCommands/code.js b/botCommands/code-legacy.js
similarity index 100%
rename from botCommands/code.js
rename to botCommands/code-legacy.js
diff --git a/botCommands/code.test.js b/botCommands/code-legacy.test.js
similarity index 97%
rename from botCommands/code.test.js
rename to botCommands/code-legacy.test.js
index e7e670b..0a17632 100644
--- a/botCommands/code.test.js
+++ b/botCommands/code-legacy.test.js
@@ -1,4 +1,4 @@
-const commands = require('./code');
+const commands = require('./code-legacy');
 const { generateMentions } = require('./mockData');
 
 describe('!code', () => {
diff --git a/botCommands/google-legacy.test.js b/botCommands/google-legacy.test.js
new file mode 100644
index 0000000..50d4b2e
--- /dev/null
+++ b/botCommands/google-legacy.test.js
@@ -0,0 +1,65 @@
+const command = require('./google-legacy');
+
+describe('!google', () => {
+  describe('regex', () => {
+    it.each([
+      ['!google query'],
+      [' !google query'],
+      ['!google query @odin-bot'],
+      ['@odin-bot !google query'],
+    ])('correct strings trigger the callback', (string) => {
+      expect(command.regex.test(string)).toBeTruthy();
+    });
+
+    it.each([
+      ['!googl'],
+      ['google'],
+      ['!goog'],
+      ['!googless'],
+      ['```function("!google", () => {}```'],
+      ['!googles'],
+      [''],
+      [' '],
+      [' !'],
+      ['@odin-bot ! google'],
+      ['!goo&gle'],
+      ['!goo^gle'],
+      ['!google!'],
+      ['@odin-bot! google'],
+      ['https:!!google.com'],
+    ])("'%s' does not trigger the callback", (string) => {
+      expect(command.regex.test(string)).toBeFalsy();
+    });
+
+    it.each([
+      ['Check this out! !google query'],
+      ["Don't worry about !google query"],
+      ['Hey @odin-bot, !google query'],
+      ['!@odin-bot ^ !me !google !tests$*'],
+    ])("'%s' - command can be anywhere in the string", (string) => {
+      expect(command.regex.test(string)).toBeTruthy();
+    });
+
+    it.each([
+      ['@user!google'],
+      ["it's about!google"],
+      ['!googleisanillusion'],
+      ['!google!'],
+      ['!google*'],
+      ['!google...'],
+    ])(
+      "'%s' - command should be its own word!group - no leading or trailing characters",
+      (string) => {
+        expect(command.regex.test(string)).toBeFalsy();
+      },
+    );
+  });
+
+  describe('callback', () => {
+    it('returns correct output', () => {
+      expect(
+        command.cb({ content: '!google The Odin Project' }),
+      ).toMatchSnapshot();
+    });
+  });
+});
diff --git a/botCommands/searchtop-legacy.test.js b/botCommands/searchtop-legacy.test.js
new file mode 100644
index 0000000..609cd98
--- /dev/null
+++ b/botCommands/searchtop-legacy.test.js
@@ -0,0 +1,65 @@
+const command = require('./searchtop-legacy');
+
+describe('!searchtop', () => {
+  describe('regex', () => {
+    it.each([
+      ['!searchtop query'],
+      [' !searchtop query'],
+      ['!searchtop query @odin-bot'],
+      ['@odin-bot !searchtop query'],
+    ])('correct strings trigger the callback', (string) => {
+      expect(command.regex.test(string)).toBeTruthy();
+    });
+
+    it.each([
+      ['!searchto'],
+      ['searchtop'],
+      ['!searcht'],
+      ['!search top'],
+      ['```function("!searchtop", () => {}```'],
+      ['!searchingtop'],
+      [''],
+      [' '],
+      [' !'],
+      ['@odin-bot ! searchtop'],
+      ['!search-top'],
+      ['!searc^htop'],
+      ['!searchtop!'],
+      ['@odin-bot! searchtop'],
+      ['https:!!searchtop.com'],
+    ])("'%s' does not trigger the callback", (string) => {
+      expect(command.regex.test(string)).toBeFalsy();
+    });
+
+    it.each([
+      ['Check this out! !searchtop query'],
+      ["Don't worry about !searchtop query"],
+      ['Hey @odin-bot, !searchtop query'],
+      ['!@odin-bot ^ !me !searchtop !tests$*'],
+    ])("'%s' - command can be anywhere in the string", (string) => {
+      expect(command.regex.test(string)).toBeTruthy();
+    });
+
+    it.each([
+      ['@user!searchtop'],
+      ["it's about!searchtop"],
+      ['!searchtopnow'],
+      ['!searchtop!'],
+      ['!searchtop*'],
+      ['!searchtop...'],
+    ])(
+      "'%s' - command should be its own word!group - no leading or trailing characters",
+      (string) => {
+        expect(command.regex.test(string)).toBeFalsy();
+      },
+    );
+  });
+
+  describe('callback', () => {
+    it('returns correct output', () => {
+      expect(
+        command.cb({ content: '!searchtop The Odin Project' }),
+      ).toMatchSnapshot();
+    });
+  });
+});
diff --git a/botCommands/simpleCommands.test.js b/botCommands/simpleCommands.test.js
deleted file mode 100644
index c9f767c..0000000
--- a/botCommands/simpleCommands.test.js
+++ /dev/null
@@ -1,556 +0,0 @@
-const commands = require('./simpleCommands');
-
-describe('!hug', () => {
-  describe('regex', () => {
-    it.each([['!hug'], [' !hug'], ['!hug @odin-bot'], ['@odin-bot !hug']])(
-      'correct strings trigger the callback',
-      (string) => {
-        expect(commands.hug.regex.test(string)).toBeTruthy();
-      },
-    );
-
-    it.each([
-      ['!hg'],
-      ['hug'],
-      ['!hu'],
-      ['!hugs'],
-      ['```function("!hug", () => {}```'],
-      ['!Hug'],
-      [''],
-      [' '],
-      [' !'],
-      ['@odin-bot ! hug'],
-      ['!hu&g'],
-      ['!hu^g'],
-      ['!hug!'],
-      ['@odin-bot! hug'],
-      ['https:!!hug.com'],
-    ])("'%s' does not trigger the callback", (string) => {
-      expect(commands.hug.regex.test(string)).toBeFalsy();
-    });
-
-    it.each([
-      ['Check this out! !hug'],
-      ["Don't worry about !hug"],
-      ['Hey @odin-bot, !hug'],
-      ['!@odin-bot ^ !me !hug !tests$*'],
-    ])("'%s' - command can be anywhere in the string", (string) => {
-      expect(commands.hug.regex.test(string)).toBeTruthy();
-    });
-
-    it.each([
-      ['@user!hug'],
-      ["it's about!hug"],
-      ['!hugisanillusion'],
-      ['!hug!'],
-      ['!hug*'],
-      ['!hug...'],
-    ])(
-      "'%s' - command should be its own word!group - no leading or trailing characters",
-      (string) => {
-        expect(commands.hug.regex.test(string)).toBeFalsy();
-      },
-    );
-  });
-
-  describe('callback', () => {
-    it('returns correct output', () => {
-      expect(commands.hug.cb()).toMatchSnapshot();
-    });
-  });
-});
-
-describe('!smart', () => {
-  describe('regex', () => {
-    it.each([
-      ['!smart'],
-      [' !smart'],
-      ['!smart @odin-bot'],
-      ['@odin-bot !smart'],
-    ])('correct strings trigger the callback', (string) => {
-      expect(commands.smart.regex.test(string)).toBeTruthy();
-    });
-
-    it.each([
-      ['!smar'],
-      ['smart'],
-      ['!smrt'],
-      ['!smarts'],
-      ['```function("!smart", () => {}```'],
-      ['!smarta'],
-      [''],
-      [' '],
-      [' !'],
-      ['@odin-bot ! smart'],
-      ['!sma&rt'],
-      ['!sma^rt'],
-      ['!smart!'],
-      ['@odin-bot! smart'],
-      ['https:!!smart.com'],
-    ])("'%s' does not trigger the callback", (string) => {
-      expect(commands.smart.regex.test(string)).toBeFalsy();
-    });
-
-    it.each([
-      ['Check this out! !smart'],
-      ["Don't worry about !smart"],
-      ['Hey @odin-bot, !smart'],
-      ['!@odin-bot ^ !me !smart !tests$*'],
-    ])("'%s' - command can be anywhere in the string", (string) => {
-      expect(commands.smart.regex.test(string)).toBeTruthy();
-    });
-
-    it.each([
-      ['@user!smart'],
-      ["it's about!smart"],
-      ['!smartisanillusion'],
-      ['!smart!'],
-      ['!smart*'],
-      ['!smart...'],
-    ])(
-      "'%s' - command should be its own word!group - no leading or trailing characters",
-      (string) => {
-        expect(commands.smart.regex.test(string)).toBeFalsy();
-      },
-    );
-  });
-
-  describe('callback', () => {
-    it('returns correct output', () => {
-      expect(commands.smart.cb()).toMatchSnapshot();
-    });
-  });
-});
-
-describe('!lenny', () => {
-  describe('regex', () => {
-    it.each([
-      ['!lenny'],
-      [' !lenny'],
-      ['!lenny @odin-bot'],
-      ['@odin-bot !lenny'],
-    ])('correct strings trigger the callback', (string) => {
-      expect(commands.lenny.regex.test(string)).toBeTruthy();
-    });
-
-    it.each([
-      ['!hg'],
-      ['lenny'],
-      ['!hu'],
-      ['!lennys'],
-      ['```function("!lenny", () => {}```'],
-      ['!lennya'],
-      [''],
-      [' '],
-      [' !'],
-      ['@odin-bot ! lenny'],
-      ['!hu&g'],
-      ['!hu^g'],
-      ['!lenny!'],
-      ['@odin-bot! lenny'],
-      ['https:!!lenny.com'],
-    ])("'%s' does not trigger the callback", (string) => {
-      expect(commands.lenny.regex.test(string)).toBeFalsy();
-    });
-
-    it.each([
-      ['Check this out! !lenny'],
-      ["Don't worry about !lenny"],
-      ['Hey @odin-bot, !lenny'],
-      ['!@odin-bot ^ !me !lenny !tests$*'],
-    ])("'%s' - command can be anywhere in the string", (string) => {
-      expect(commands.lenny.regex.test(string)).toBeTruthy();
-    });
-
-    it.each([
-      ['@user!lenny'],
-      ["it's about!lenny"],
-      ['!lennyisanillusion'],
-      ['!lenny!'],
-      ['!lenny*'],
-      ['!lenny...'],
-    ])(
-      "'%s' - command should be its own word!group - no leading or trailing characters",
-      (string) => {
-        expect(commands.lenny.regex.test(string)).toBeFalsy();
-      },
-    );
-  });
-
-  describe('callback', () => {
-    it('returns correct output', () => {
-      expect(commands.lenny.cb()).toMatchSnapshot();
-    });
-  });
-});
-
-describe('!fu', () => {
-  describe('regex', () => {
-    it.each([['!fu'], [' !fu'], ['!fu @odin-bot'], ['@odin-bot !fu']])(
-      'correct strings trigger the callback',
-      (string) => {
-        expect(commands.fu.regex.test(string)).toBeTruthy();
-      },
-    );
-
-    it.each([
-      ['!f'],
-      ['fu'],
-      ['!fuu'],
-      ['!fus'],
-      ['```function("!fu", () => {}```'],
-      ['!fua'],
-      [''],
-      [' '],
-      [' !'],
-      ['@odin-bot ! fu'],
-      ['!f&u'],
-      ['!f^u'],
-      ['!fu!'],
-      ['@odin-bot! fu'],
-      ['https:!!fu.com'],
-    ])("'%s' does not trigger the callback", (string) => {
-      expect(commands.fu.regex.test(string)).toBeFalsy();
-    });
-
-    it.each([
-      ['Check this out! !fu'],
-      ["Don't worry about !fu"],
-      ['Hey @odin-bot, !fu'],
-      ['!@odin-bot ^ !me !fu !tests$*'],
-    ])("'%s' - command can be anywhere in the string", (string) => {
-      expect(commands.fu.regex.test(string)).toBeTruthy();
-    });
-
-    it.each([
-      ['@user!fu'],
-      ["it's about!fu"],
-      ['!fuisanillusion'],
-      ['!fu!'],
-      ['!fu*'],
-      ['!fu...'],
-    ])(
-      "'%s' - command should be its own word!group - no leading or trailing characters",
-      (string) => {
-        expect(commands.fu.regex.test(string)).toBeFalsy();
-      },
-    );
-  });
-
-  describe('callback', () => {
-    it('returns correct output', () => {
-      const fu = jest.fn(
-        () => 'http:!!media.riffsy.com!images!636a97aa416ad674eb2b72d4a6e9ad6c!tenor.gif',
-      );
-      expect(fu(':fu:')).toMatchSnapshot();
-    });
-  });
-});
-
-describe('!data', () => {
-  describe('regex', () => {
-    it.each([['!data'], [' !data'], ['!data @odin-bot'], ['@odin-bot !data']])(
-      'correct strings trigger the callback',
-      (string) => {
-        expect(commands.data.regex.test(string)).toBeTruthy();
-      },
-    );
-
-    it.each([
-      ['!dat'],
-      ['data'],
-      ['!daa'],
-      ['!datas'],
-      ['```function("!data", () => {}```'],
-      ['!dataa'],
-      [''],
-      [' '],
-      [' !'],
-      ['@odin-bot ! data'],
-      ['!da&ta'],
-      ['!da^ta'],
-      ['!data!'],
-      ['@odin-bot! data'],
-      ['https:!!data.com'],
-    ])("'%s' does not trigger the callback", (string) => {
-      expect(commands.data.regex.test(string)).toBeFalsy();
-    });
-
-    it.each([
-      ['Check this out! !data'],
-      ["Don't worry about !data"],
-      ['Hey @odin-bot, !data'],
-      ['!@odin-bot ^ !me !data !tests$*'],
-    ])("'%s' - command can be anywhere in the string", (string) => {
-      expect(commands.data.regex.test(string)).toBeTruthy();
-    });
-
-    it.each([
-      ['@user!data'],
-      ["it's about!data"],
-      ['!dataisanillusion'],
-      ['!data!'],
-      ['!data*'],
-      ['!data...'],
-    ])(
-      "'%s' - command should be its own word!group - no leading or trailing characters",
-      (string) => {
-        expect(commands.data.regex.test(string)).toBeFalsy();
-      },
-    );
-  });
-
-  describe('callback', () => {
-    it('returns correct output', () => {
-      expect(commands.data.cb()).toMatchSnapshot();
-    });
-  });
-});
-
-describe('!google', () => {
-  describe('regex', () => {
-    it.each([
-      ['!google query'],
-      [' !google query'],
-      ['!google query @odin-bot'],
-      ['@odin-bot !google query'],
-    ])('correct strings trigger the callback', (string) => {
-      expect(commands.google.regex.test(string)).toBeTruthy();
-    });
-
-    it.each([
-      ['!googl'],
-      ['google'],
-      ['!goog'],
-      ['!googless'],
-      ['```function("!google", () => {}```'],
-      ['!googles'],
-      [''],
-      [' '],
-      [' !'],
-      ['@odin-bot ! google'],
-      ['!goo&gle'],
-      ['!goo^gle'],
-      ['!google!'],
-      ['@odin-bot! google'],
-      ['https:!!google.com'],
-    ])("'%s' does not trigger the callback", (string) => {
-      expect(commands.google.regex.test(string)).toBeFalsy();
-    });
-
-    it.each([
-      ['Check this out! !google query'],
-      ["Don't worry about !google query"],
-      ['Hey @odin-bot, !google query'],
-      ['!@odin-bot ^ !me !google !tests$*'],
-    ])("'%s' - command can be anywhere in the string", (string) => {
-      expect(commands.google.regex.test(string)).toBeTruthy();
-    });
-
-    it.each([
-      ['@user!google'],
-      ["it's about!google"],
-      ['!googleisanillusion'],
-      ['!google!'],
-      ['!google*'],
-      ['!google...'],
-    ])(
-      "'%s' - command should be its own word!group - no leading or trailing characters",
-      (string) => {
-        expect(commands.google.regex.test(string)).toBeFalsy();
-      },
-    );
-  });
-
-  describe('callback', () => {
-    it('returns correct output', () => {
-      expect(
-        commands.google.cb({ content: '!google The Odin Project' }),
-      ).toMatchSnapshot();
-    });
-  });
-});
-
-describe('!dab', () => {
-  describe('regex', () => {
-    it.each([['!dab'], [' !dab'], ['!dab @odin-bot'], ['@odin-bot !dab']])(
-      'correct strings trigger the callback',
-      (string) => {
-        expect(commands.dab.regex.test(string)).toBeTruthy();
-      },
-    );
-
-    it.each([
-      ['!da'],
-      ['dab'],
-      ['!daa'],
-      ['!dabs'],
-      ['```function("!dab", () => {}```'],
-      ['!d'],
-      [''],
-      [' '],
-      [' !'],
-      ['@odin-bot ! dab'],
-      ['!da&b'],
-      ['!da^b'],
-      ['!dab!'],
-      ['@odin-bot! dab'],
-      ['https:!!dab.com'],
-    ])("'%s' does not trigger the callback", (string) => {
-      expect(commands.dab.regex.test(string)).toBeFalsy();
-    });
-
-    it.each([
-      ['Check this out! !dab'],
-      ["Don't worry about !dab"],
-      ['Hey @odin-bot, !dab'],
-      ['!@odin-bot ^ !me !dab !tests$*'],
-    ])("'%s' - command can be anywhere in the string", (string) => {
-      expect(commands.dab.regex.test(string)).toBeTruthy();
-    });
-
-    it.each([
-      ['@user!dab'],
-      ["it's about!dab"],
-      ['!dabisanillusion'],
-      ['!dab!'],
-      ['!dab*'],
-      ['!dab...'],
-    ])(
-      "'%s' - command should be its own word!group - no leading or trailing characters",
-      (string) => {
-        expect(commands.dab.regex.test(string)).toBeFalsy();
-      },
-    );
-  });
-
-  describe('callback', () => {
-    it('returns correct output', () => {
-      expect(commands.dab.cb()).toMatchSnapshot();
-    });
-  });
-});
-
-describe('!motivate', () => {
-  describe('regex', () => {
-    it.each([
-      ['!motivate'],
-      [' !motivate'],
-      ['!motivate @odin-bot'],
-      ['@odin-bot !motivate'],
-    ])('correct strings trigger the callback', (string) => {
-      expect(commands.motivate.regex.test(string)).toBeTruthy();
-    });
-
-    it.each([
-      ['!motivae'],
-      ['motivate'],
-      ['!motiv'],
-      ['!motivates'],
-      ['```function("!motivate", () => {}```'],
-      ['!motive'],
-      [''],
-      [' '],
-      [' !'],
-      ['@odin-bot ! motivate'],
-      ['!motiv&ate'],
-      ['!motiva^te'],
-      ['!motivate!'],
-      ['@odin-bot! motivate'],
-      ['https:!!motivate.com'],
-    ])("'%s' does not trigger the callback", (string) => {
-      expect(commands.motivate.regex.test(string)).toBeFalsy();
-    });
-
-    it.each([
-      ['Check this out! !motivate'],
-      ["Don't worry about !motivate"],
-      ['Hey @odin-bot, !motivate'],
-      ['!@odin-bot ^ !me !motivate !tests$*'],
-    ])("'%s' - command can be anywhere in the string", (string) => {
-      expect(commands.motivate.regex.test(string)).toBeTruthy();
-    });
-
-    it.each([
-      ['@user!motivate'],
-      ["it's about!motivate"],
-      ['!motivateisanillusion'],
-      ['!motivate!'],
-      ['!motivate*'],
-      ['!motivate...'],
-    ])(
-      "'%s' - command should be its own word!group - no leading or trailing characters",
-      (string) => {
-        expect(commands.motivate.regex.test(string)).toBeFalsy();
-      },
-    );
-  });
-
-  describe('callback', () => {
-    it('returns correct output', () => {
-      expect(commands.motivate.cb()).toMatchSnapshot();
-    });
-  });
-});
-
-describe('!justdoit', () => {
-  describe('regex', () => {
-    it.each([
-      ['!justdoit'],
-      [' !justdoit'],
-      ['!justdoit @odin-bot'],
-      ['@odin-bot !justdoit'],
-    ])('correct strings trigger the callback', (string) => {
-      expect(commands.justDoIt.regex.test(string)).toBeTruthy();
-    });
-
-    it.each([
-      ['!justdoi'],
-      ['justdoit'],
-      ['!justdo'],
-      ['!justdoits'],
-      ['```function("!justdoit", () => {}```'],
-      ['!d'],
-      [''],
-      [' '],
-      [' !'],
-      ['@odin-bot ! justdoit'],
-      ['!just&doit'],
-      ['!justdo^it'],
-      ['!justDoIt!'],
-      ['@odin-bot! justdoit'],
-      ['https:!!justdoit.com'],
-    ])("'%s' does not trigger the callback", (string) => {
-      expect(commands.justDoIt.regex.test(string)).toBeFalsy();
-    });
-
-    it.each([
-      ['Check this out! !justdoit'],
-      ["Don't worry about !justdoit"],
-      ['Hey @odin-bot, !justdoit'],
-      ['!@odin-bot ^ !me !justdoit !tests$*'],
-    ])("'%s' - command can be anywhere in the string", (string) => {
-      expect(commands.justDoIt.regex.test(string)).toBeTruthy();
-    });
-
-    it.each([
-      ['@user!justdoit'],
-      ["it's about!justdoit"],
-      ['!dabisanillusion'],
-      ['!justdoit!'],
-      ['!justdoit*'],
-      ['!justdoit...'],
-    ])(
-      "'%s' - command should be its own word!group - no leading or trailing characters",
-      (string) => {
-        expect(commands.justDoIt.regex.test(string)).toBeFalsy();
-      },
-    );
-  });
-
-  describe('callback', () => {
-    it('returns correct output', () => {
-      expect(commands.justDoIt.cb()).toMatchSnapshot();
-    });
-  });
-});
diff --git a/botCommands/top.js b/botCommands/top-legacy.js
similarity index 100%
rename from botCommands/top.js
rename to botCommands/top-legacy.js
diff --git a/botCommands/top.test.js b/botCommands/top-legacy.test.js
similarity index 96%
rename from botCommands/top.test.js
rename to botCommands/top-legacy.test.js
index 50e2507..1437cca 100644
--- a/botCommands/top.test.js
+++ b/botCommands/top-legacy.test.js
@@ -1,4 +1,4 @@
-const command = require('./top');
+const command = require('./top-legacy');
 
 describe('!top', () => {
   describe('regex', () => {