aboutsummaryrefslogtreecommitdiff
path: root/174bg/discord-bot/source/commands
diff options
context:
space:
mode:
authorAlex Pooley (@zuedev) <zuedev@gmail.com>2026-07-22 15:32:57 +0100
committerAlex Pooley (@zuedev) <zuedev@gmail.com>2026-07-22 15:32:57 +0100
commit72487019b3f255cece40a8073bbad8bc9968a3b7 (patch)
treeb6590e63039cdc8b1820bd345cdfe83f28ff839b /174bg/discord-bot/source/commands
parentda0509c91376f56f133872eddd2e4282d76f215e (diff)
downloadunnamed-group-72487019b3f255cece40a8073bbad8bc9968a3b7.tar
unnamed-group-72487019b3f255cece40a8073bbad8bc9968a3b7.tar.gz
unnamed-group-72487019b3f255cece40a8073bbad8bc9968a3b7.tar.bz2
unnamed-group-72487019b3f255cece40a8073bbad8bc9968a3b7.tar.xz
unnamed-group-72487019b3f255cece40a8073bbad8bc9968a3b7.zip
major code refactor, add uex lookup
Diffstat (limited to '174bg/discord-bot/source/commands')
-rw-r--r--174bg/discord-bot/source/commands/_index.js8
-rw-r--r--174bg/discord-bot/source/commands/close-ticket.js55
-rw-r--r--174bg/discord-bot/source/commands/oncall-check.js51
-rw-r--r--174bg/discord-bot/source/commands/requisition.js42
-rw-r--r--174bg/discord-bot/source/commands/uex.js81
5 files changed, 237 insertions, 0 deletions
diff --git a/174bg/discord-bot/source/commands/_index.js b/174bg/discord-bot/source/commands/_index.js
new file mode 100644
index 0000000..5fea200
--- /dev/null
+++ b/174bg/discord-bot/source/commands/_index.js
@@ -0,0 +1,8 @@
+import requisition from "./requisition.js";
+import closeTicket from "./close-ticket.js";
+import oncallCheck from "./oncall-check.js";
+import uex from "./uex.js";
+
+export { requisition, closeTicket, oncallCheck, uex };
+
+export default [requisition, closeTicket, oncallCheck, uex];
diff --git a/174bg/discord-bot/source/commands/close-ticket.js b/174bg/discord-bot/source/commands/close-ticket.js
new file mode 100644
index 0000000..ca3040e
--- /dev/null
+++ b/174bg/discord-bot/source/commands/close-ticket.js
@@ -0,0 +1,55 @@
+import { SlashCommandBuilder, PermissionFlagsBits } from "discord.js";
+
+export default {
+ data: new SlashCommandBuilder()
+ .setName("close-ticket")
+ .setDescription(
+ "Closes the current ticket by logging the contents and deleting the channel.",
+ )
+ .setDefaultMemberPermissions(PermissionFlagsBits.Administrator),
+ execute: async (interaction) => {
+ const channel = interaction.channel;
+
+ if (!channel || !channel.name.startsWith("ticket-")) {
+ return await interaction.reply({
+ content: "This command can only be used in a ticket channel.",
+ ephemeral: true,
+ });
+ }
+
+ // log the contents of the ticket and send to the logs channel if it exists
+ const messages = await channel.messages.fetch({ limit: 100 });
+ const log = messages
+ .map((message) => `${message.author.tag}: ${message.content}`)
+ .reverse()
+ .join("\n");
+
+ console.log(`Ticket log for ${channel.name}:\n${log}`);
+
+ const logsChannel = interaction.guild.channels.cache.find(
+ (ch) => ch.name === "logs" && ch.isTextBased(),
+ );
+
+ if (logsChannel)
+ await logsChannel.send({
+ content: `# Ticket log for ${channel.name}`,
+ files: [
+ {
+ name: `${channel.name}.txt`,
+ attachment: Buffer.from(
+ messages
+ .map(
+ (message) =>
+ `${message.author.tag}/${message.author.id}: ${message.content}`,
+ )
+ .reverse()
+ .join("\n"),
+ ),
+ },
+ ],
+ });
+
+ // delete the channel
+ await channel.delete();
+ },
+};
diff --git a/174bg/discord-bot/source/commands/oncall-check.js b/174bg/discord-bot/source/commands/oncall-check.js
new file mode 100644
index 0000000..7a3886d
--- /dev/null
+++ b/174bg/discord-bot/source/commands/oncall-check.js
@@ -0,0 +1,51 @@
+import { SlashCommandBuilder, PermissionFlagsBits } from "discord.js";
+import { login } from "../controllers/pocketbase.js";
+
+export default {
+ data: new SlashCommandBuilder()
+ .setName("oncall-check")
+ .setDescription("Returns a list of members who are currently on call.")
+ .setDefaultMemberPermissions(PermissionFlagsBits.Administrator),
+ execute: async (interaction) => {
+ const date = new Date();
+ const dateUTCHours = date.getUTCHours();
+ const dateUTCMinutes = date.getUTCMinutes();
+ const dateUTCDay = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][date.getUTCDay()];
+
+ const pb = await login();
+
+ const members = await pb.collection("members").getFullList();
+
+ let membersOnCall = [];
+
+ for (const member of members) {
+ try {
+ if (member.onCallSchedule) {
+ const available = member.onCallSchedule[dateUTCDay]?.available || false;
+
+ if (available) {
+ const start = member.onCallSchedule[dateUTCDay].start;
+ const startHours = start.split(":")[0];
+ const startMinutes = start.split(":")[1];
+ const end = member.onCallSchedule[dateUTCDay].end;
+ const endHours = end.split(":")[0];
+ const endMinutes = end.split(":")[1];
+
+ console.log(`Checking on-call schedule for member ${member.name}: ${start} - ${end} (UTC)`);
+
+ if ((dateUTCHours > startHours || (dateUTCHours === startHours && dateUTCMinutes >= startMinutes)) && (dateUTCHours < endHours || (dateUTCHours === endHours && dateUTCMinutes <= endMinutes))) {
+ membersOnCall.push(member);
+ }
+ }
+ }
+ } catch (error) {
+ console.error(`Error checking on-call schedule for member ${member.name}:`, error);
+ }
+ }
+
+ await interaction.reply({
+ content: `${membersOnCall.map((member) => `- <@${member.discordId}>`).join("\n") || "No members are currently on call."}`,
+ ephemeral: true,
+ });
+ },
+};
diff --git a/174bg/discord-bot/source/commands/requisition.js b/174bg/discord-bot/source/commands/requisition.js
new file mode 100644
index 0000000..02c7699
--- /dev/null
+++ b/174bg/discord-bot/source/commands/requisition.js
@@ -0,0 +1,42 @@
+import { SlashCommandBuilder } from "discord.js";
+import createTicket from "../utilities/createTicket.js";
+import notifyRoleByName from "../utilities/notifyRoleByName.js";
+
+export default {
+ data: new SlashCommandBuilder()
+ .setName("requisition")
+ .setDescription(
+ "Request items from the quartermaster. A new requisition ticket will be created.",
+ )
+ .addStringOption((option) =>
+ option
+ .setName("contents")
+ .setDescription("What are you requesting? Be as specific as possible.")
+ .setRequired(true),
+ ),
+ execute: async (interaction) => {
+ const contents = interaction.options.getString("contents");
+
+ const ticket = await createTicket(interaction, {
+ roleNamesWithAccess: ["quartermaster"],
+ ticketNamePrefix: "req-",
+ });
+
+ await ticket.send({
+ content: `**New requisition request from <@${interaction.user.id}>**: ${contents}`,
+ });
+
+ // reply to the user
+ await interaction.reply({
+ content: `Your requisition ticket has been created: <#${ticket.id}>`,
+ ephemeral: true,
+ });
+
+ // notify quartermasters
+ await notifyRoleByName(
+ interaction.guild,
+ "quartermaster",
+ `New requisition request from <@${interaction.user.id}>: ${contents}`,
+ );
+ },
+};
diff --git a/174bg/discord-bot/source/commands/uex.js b/174bg/discord-bot/source/commands/uex.js
new file mode 100644
index 0000000..f2f654f
--- /dev/null
+++ b/174bg/discord-bot/source/commands/uex.js
@@ -0,0 +1,81 @@
+import { SlashCommandBuilder, MessageFlags } from "discord.js";
+import { items } from "../controllers/uex.js";
+
+export default {
+ data: new SlashCommandBuilder()
+ .setName("uex")
+ .setDescription(
+ "Commands for interacting with UEX.",
+ )
+ .addSubcommandGroup((subcommandGroup) =>
+ subcommandGroup
+ .setName("lookup")
+ .setDescription("Lookup UEX information.")
+ .addSubcommand((subcommand) =>
+ subcommand
+ .setName("items")
+ .setDescription("Perform UEX lookup for Star Citizen items, including ship components, weapons, and more.")
+ .addStringOption((option) =>
+ option
+ .setName("query")
+ .setDescription(
+ "The item name or partial name to search for.",
+ )
+ .setRequired(true),
+ ),
+ )
+ ),
+ execute: async (interaction) => {
+ const subcommandGroup = interaction.options.getSubcommandGroup();
+ const subcommand = interaction.options.getSubcommand();
+
+ switch (subcommandGroup) {
+ case "lookup":
+ switch (subcommand) {
+ case "items":
+ await uex_lookup_items(interaction);
+ break;
+ default:
+ await interaction.reply({
+ content: "Unknown subcommand.",
+ ephemeral: true,
+ });
+ break;
+ }
+ break;
+ default:
+ await interaction.reply({
+ content: "Unknown subcommand group.",
+ ephemeral: true,
+ });
+ break;
+ }
+ },
+};
+
+async function uex_lookup_items(interaction) {
+ const query = interaction.options.getString("query");
+
+ await interaction.deferReply({ flags: MessageFlags.Ephemeral });
+
+ const allItems = await items();
+
+ const matchingItems = allItems.filter((item) =>
+ item.name.toLowerCase().includes(query.toLowerCase()),
+ );
+
+ if (matchingItems.length === 0) {
+ await interaction.editReply({
+ content: `No items found matching "${query}".`,
+ });
+ return;
+ }
+
+ const itemList = matchingItems
+ .map((item) => `- ${item.name} (ID: ${item.id})`)
+ .join("\n");
+
+ await interaction.editReply({
+ content: `Found ${matchingItems.length} item(s) matching "${query}":\n${itemList}`,
+ });
+} \ No newline at end of file