Files
2026-08-15 00:32:27 +02:00

329 lines
6.2 KiB
JavaScript

const {
SlashCommandBuilder,
ModalBuilder,
TextInputBuilder,
TextInputStyle,
ActionRowBuilder,
MessageFlags
} = require("discord.js");
const { ObjectId } = require("mongodb");
const { mClient } = require("../..");
const DATABASE = "neo-db";
const DUTY_COLLECTION = "items_duties";
const RAID_TYPES = [
"Trial",
"Raid",
"AllianceRaid"
];
const RAID_DIFFICULTIES = [
"Extreme",
"Unreal",
"Savage",
"Ultimate",
"Chaotic"
];
module.exports = {
data: new SlashCommandBuilder()
.setName("raid")
.setDescription("Raid planning commands.")
.addSubcommand(subcommand =>
subcommand
.setName("plan")
.setDescription("Create a new raid event.")
.addStringOption(option =>
option
.setName("duty")
.setDescription(
"Select the duty you want to run."
)
.setRequired(true)
.setAutocomplete(true)
)
),
async execute(interaction) {
switch (
interaction.options.getSubcommand()
) {
case "plan":
return planRaid(interaction);
}
},
async autocomplete(interaction) {
return autocompleteDuty(interaction);
}
};
/*
* AUTOCOMPLETE
*/
async function autocompleteDuty(interaction) {
const focused =
interaction.options.getFocused();
const collection = mClient
.db(DATABASE)
.collection(DUTY_COLLECTION);
const query = {
Type: {
$in: RAID_TYPES
},
Difficulty: {
$in: RAID_DIFFICULTIES
}
};
if (focused) {
query.Name = {
$regex: escapeRegex(focused),
$options: "i"
};
}
const duties = await collection
.find(query)
.sort({
Name: 1
})
.limit(25)
.toArray();
return interaction.respond(
duties.map(duty => ({
name: buildAutocompleteName(duty),
value: duty._id.toString()
}))
);
}
/*
* /raid plan
*/
async function planRaid(interaction) {
if (!interaction.guild) {
return interaction.reply({
content:
"Raid planning can only be used inside a server.",
flags:
MessageFlags.Ephemeral
});
}
const dutyId =
interaction.options.getString(
"duty",
true
);
if (!ObjectId.isValid(dutyId)) {
return interaction.reply({
content:
"Please select a duty from the autocomplete results.",
flags:
MessageFlags.Ephemeral
});
}
const collection = mClient
.db(DATABASE)
.collection(DUTY_COLLECTION);
const duty =
await collection.findOne({
_id:
new ObjectId(dutyId),
Type: {
$in: RAID_TYPES
},
Difficulty: {
$in: RAID_DIFFICULTIES
}
});
if (!duty) {
return interaction.reply({
content:
"That duty could not be found or is not eligible for raid planning.",
flags:
MessageFlags.Ephemeral
});
}
const modal =
buildRaidModal(duty);
return interaction.showModal(
modal
);
}
/*
* MODAL
*/
function buildRaidModal(duty) {
const modal =
new ModalBuilder()
.setCustomId(
`raidPlan:${duty._id}`
)
.setTitle(
"Shaiwase Raid Planner"
);
const nameInput =
new TextInputBuilder()
.setCustomId("raid-name")
.setLabel("Name")
.setPlaceholder(
"Friday Savage Prog"
)
.setStyle(
TextInputStyle.Short
)
.setMinLength(1)
.setMaxLength(100)
.setRequired(true);
const descriptionInput =
new TextInputBuilder()
.setCustomId(
"raid-description"
)
.setLabel("Description")
.setPlaceholder(
"What are we doing? Any requirements?"
)
.setStyle(
TextInputStyle.Paragraph
)
.setMaxLength(1000)
.setRequired(true);
const dateInput =
new TextInputBuilder()
.setCustomId("raid-date")
.setLabel("Date")
.setPlaceholder(
"DD-MM-YYYY"
)
.setStyle(
TextInputStyle.Short
)
.setMinLength(10)
.setMaxLength(10)
.setRequired(true);
const timeInput =
new TextInputBuilder()
.setCustomId("raid-time")
.setLabel(
"Start - End (24h clock)"
)
.setPlaceholder(
"20:00 - 23:00"
)
.setStyle(
TextInputStyle.Short
)
.setRequired(true);
modal.addComponents(
new ActionRowBuilder()
.addComponents(
nameInput
),
new ActionRowBuilder()
.addComponents(
descriptionInput
),
new ActionRowBuilder()
.addComponents(
dateInput
),
new ActionRowBuilder()
.addComponents(
timeInput
)
);
return modal;
}
/*
* HELPERS
*/
function buildAutocompleteName(duty) {
const label =
`${duty.Name} — ${formatDutyType(duty.Type)} / ${duty.Difficulty}`;
return label.slice(
0,
100
);
}
function formatDutyType(type) {
switch (type) {
case "AllianceRaid":
return "Alliance Raid";
default:
return type;
}
}
function escapeRegex(value) {
return value.replace(
/[.*+?^${}()|[\]\\]/g,
"\\$&"
);
}