Repository: TheOdinProject/odin-bot-v2
Pull request #417 (2023-09-15 11:36:12)

OS: Add generic OS command
**DO NOT MERGE:** Depends on TheOdinProject/curriculum/pull/25402

## Because
- Once we've moved to support WSL, its easier to disclaim that every OS not mentioned isn't supported, rather than trying to account for every possible edgecase (But what about TempleOS???)


## This PR
- Adds a generic `!os` command which makes it clear that everything not mentioned as supported is unsupported


## 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 this PR addresses an open issue, it is linked in the `Issue` section
-   [x] If this PR adds new features or functionality, I have added new tests
-   [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



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/os.js b/botCommands/os.js
new file mode 100644
index 0000000..b80f99a
--- /dev/null
+++ b/botCommands/os.js
@@ -0,0 +1,23 @@
+const Discord = require("discord.js");
+const { registerBotCommand } = require("../botEngine");
+
+const command = {
+  regex: /(?<!\S)!os(?!\S)/,
+  cb: () => {
+    const osEmbed = new Discord.EmbedBuilder()
+      .setColor("#cc9543")
+      .setTitle("Windows")
+      .setDescription(
+        "**The Odin Project does not support Windows or any other OS outside of our recommendations**. We are happy to assist with any questions about installing a VM, using WSL, or dual booting Linux. <https://www.theodinproject.com/paths/foundations/courses/foundations/lessons/installation-overview#os-options>"
+      )
+      .setURL(
+        "https://www.theodinproject.com/paths/foundations/courses/foundations/lessons/installation-overview#os-options"
+      );
+
+    return { embeds: [osEmbed] };
+  },
+};
+
+registerBotCommand(command.regex, command.cb);
+
+module.exports = command;
diff --git a/new-era-commands/slash/os.js b/new-era-commands/slash/os.js
new file mode 100644
index 0000000..f189511
--- /dev/null
+++ b/new-era-commands/slash/os.js
@@ -0,0 +1,22 @@
+const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
+
+module.exports = {
+  data: new SlashCommandBuilder()
+    .setName('os')
+    .setDescription('Using other OS\'s')
+    .addUserOption((option) => option.setName('user').setDescription('user to ping')),
+  execute: async (interaction) => {
+    const userId = interaction.options.getUser('user')?.id;
+
+    const osEmbed = new EmbedBuilder()
+      .setColor('#cc9543')
+      .setTitle('Windows')
+      .setDescription('**The Odin Project does not support Windows or any other OS outside of our recommendations**. We are happy to assist with any questions about installing a VM, using WSL, or dual booting Linux. <https://www.theodinproject.com/paths/foundations/courses/foundations/lessons/installation-overview#os-options>')
+      .setURL('https://www.theodinproject.com/paths/foundations/courses/foundations/lessons/installation-overview#os-options');
+
+    await interaction.reply({
+      content: userId ? `<@${userId}>` : '',
+      embeds: [osEmbed],
+    });
+  },
+};


Test patch:
diff --git a/botCommands/__snapshots__/os.test.js.snap b/botCommands/__snapshots__/os.test.js.snap
new file mode 100644
index 0000000..8cf5aa1
--- /dev/null
+++ b/botCommands/__snapshots__/os.test.js.snap
@@ -0,0 +1,14 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`!os callback returns correct output 1`] = `
+{
+  "embeds": [
+    {
+      "color": 13407555,
+      "description": "**The Odin Project does not support Windows or any other OS outside of our recommendations**. We are happy to assist with any questions about installing a VM, using WSL, or dual booting Linux. <https://www.theodinproject.com/paths/foundations/courses/foundations/lessons/installation-overview#os-options>",
+      "title": "Windows",
+      "url": "https://www.theodinproject.com/paths/foundations/courses/foundations/lessons/installation-overview#os-options",
+    },
+  ],
+}
+`;
diff --git a/botCommands/os.test.js b/botCommands/os.test.js
new file mode 100644
index 0000000..dc3d108
--- /dev/null
+++ b/botCommands/os.test.js
@@ -0,0 +1,50 @@
+const command = require('./os');
+
+describe('!os', () => {
+  describe('regex', () => {
+    it.each([
+      ['!os'],
+      [' !os'],
+      ['!os @odin-bot'],
+      ['@odin-bot !os'],
+    ])('correct strings trigger the callback', (string) => {
+      expect(command.regex.test(string)).toBeTruthy();
+    });
+
+    it.each([
+      ['so'],
+      ['os'],
+      ['!so'],
+      ['! os'],
+      ['!aos'],
+    ])("'%s' does not trigger the callback", (string) => {
+      expect(command.regex.test(string)).toBeFalsy();
+    });
+
+    it.each([
+      ['Check this out! !os'],
+      ['Don\'t worry about !os'],
+      ['Hey @odin-bot, !os'],
+      ['!@odin-bot ^ !me !os !tests$*'],
+    ])("'%s' - command can be anywhere in the string", (string) => {
+      expect(command.regex.test(string)).toBeTruthy();
+    });
+
+    it.each([
+      ['@user!os'],
+      ['it\'s about!os'],
+      ['!osanillusion'],
+      ['!os!'],
+      ['!os*'],
+      ['!os...'],
+    ])("'%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();
+    });
+  });
+});