Repository: TheOdinProject/odin-bot-v2
Pull request #416 (2023-09-15 11:28:10)

WSL: Add WSL command
**DO NOT MERGE:** Depends on TheOdinProject/curriculum/pull/25402

## Because
- We're moving to support WSL2

## This PR
- Adds a new command to direct users to the wsl channel for support

## Pull Request Requirements
<!-- Replace the whitespace between the square brackets with an 'x', e.g. [x]. After you create the PR, they will become checkboxes that you can click on. -->
-   [x] I have thoroughly read and understand [The Odin Project Contributing Guide](https://github.com/TheOdinProject/.github/blob/main/CONTRIBUTING.md)
-   [x] The title of this PR follows the `location of change: brief description of change` format, e.g. `Callbacks command: Update verbiage`
-   [x] The `Because` section summarizes the reason for this PR
-   [x] The `This PR` section has a bullet point list describing the changes in this PR
-   [x] If applicable, I have ensured all tests related to any command files included in this PR pass, and/or all snapshots are up to date


KevinMulhern: Ignore the closing and reopens - trying to retrigger CI using this PR

Patch:
diff --git a/botCommands/club_40_gifs.json b/botCommands/club_40_gifs.json
index b3ba2f7..5e62fe0 100644
--- a/botCommands/club_40_gifs.json
+++ b/botCommands/club_40_gifs.json
@@ -66,9 +66,5 @@
   {
     "gif": "https://media.tenor.com/VRYCq0ZeasQAAAAC/dundie-award.gif",
     "author": "Unknown"
-  },
-  {
-    "gif": "https://i.imgur.com/EhZCIzv.gif",
-    "author": "Mao"
   }
-]
\ No newline at end of file
+]
diff --git a/botCommands/wsl.js b/botCommands/wsl.js
new file mode 100644
index 0000000..db983a2
--- /dev/null
+++ b/botCommands/wsl.js
@@ -0,0 +1,20 @@
+const Discord = require("discord.js");
+const { registerBotCommand } = require("../botEngine");
+
+const command = {
+  regex: /(?<!\S)!wsl(?!\S)/,
+  cb: () => {
+    const wslEmbed = new Discord.EmbedBuilder()
+      .setColor("#cc9543")
+      .setTitle("WSL")
+      .setDescription(
+        "For help with using WSL please use the WSL channel: <#1077759838785904640>"
+      );
+
+    return { embeds: [wslEmbed] };
+  },
+};
+
+registerBotCommand(command.regex, command.cb);
+
+module.exports = command;
diff --git a/new-era-commands/slash/wsl.js b/new-era-commands/slash/wsl.js
new file mode 100644
index 0000000..13149e8
--- /dev/null
+++ b/new-era-commands/slash/wsl.js
@@ -0,0 +1,21 @@
+const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
+
+module.exports = {
+  data: new SlashCommandBuilder()
+    .setName('wsl')
+    .setDescription('Help with using WSL')
+    .addUserOption((option) => option.setName('user').setDescription('user to ping')),
+  execute: async (interaction) => {
+    const userId = interaction.options.getUser('user')?.id;
+
+    const wslEmbed = new EmbedBuilder()
+      .setColor('#cc9543')
+      .setTitle('WSL')
+      .setDescription('For help with using WSL please use the WSL channel: <#1077759838785904640>')
+
+    await interaction.reply({
+      content: userId ? `<@${userId}>` : '',
+      embeds: [wslEmbed],
+    });
+  },
+};


Test patch:
diff --git a/botCommands/__snapshots__/wsl.test.js.snap b/botCommands/__snapshots__/wsl.test.js.snap
new file mode 100644
index 0000000..6cb0317
--- /dev/null
+++ b/botCommands/__snapshots__/wsl.test.js.snap
@@ -0,0 +1,13 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`!wsl callback returns correct output 1`] = `
+{
+  "embeds": [
+    {
+      "color": 13407555,
+      "description": "For help with using WSL please use the WSL channel: <#1077759838785904640>",
+      "title": "WSL",
+    },
+  ],
+}
+`;
diff --git a/botCommands/wsl.test.js b/botCommands/wsl.test.js
new file mode 100644
index 0000000..002f162
--- /dev/null
+++ b/botCommands/wsl.test.js
@@ -0,0 +1,52 @@
+const command = require('./wsl');
+
+describe('!wsl', () => {
+  describe('regex', () => {
+    it.each([
+      ['!wsl'],
+      [' !wsl'],
+      ['!wsl @odin-bot'],
+      ['@odin-bot !wsl'],
+    ])('correct strings trigger the callback', (string) => {
+      expect(command.regex.test(string)).toBeTruthy();
+    });
+
+    it.each([
+      ['wndows'],
+      ['wsl'],
+      ['window'],
+      ['!wndows'],
+      ['!window'],
+      ['! wsl'],
+      ['!awsl'],
+    ])("'%s' does not trigger the callback", (string) => {
+      expect(command.regex.test(string)).toBeFalsy();
+    });
+
+    it.each([
+      ['Check this out! !wsl'],
+      ['Don\'t worry about !wsl'],
+      ['Hey @odin-bot, !wsl'],
+      ['!@odin-bot ^ !me !wsl !tests$*'],
+    ])("'%s' - command can be anywhere in the string", (string) => {
+      expect(command.regex.test(string)).toBeTruthy();
+    });
+
+    it.each([
+      ['@user!wsl'],
+      ['it\'s about!wsl'],
+      ['!wslanillusion'],
+      ['!wsl!'],
+      ['!wsl*'],
+      ['!wsl...'],
+    ])("'%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()).toMatchSnapshot();
+    });
+  });
+});