added proper modal handler and raidplan
This commit is contained in:
@@ -0,0 +1,300 @@
|
||||
const {
|
||||
SlashCommandBuilder,
|
||||
ModalBuilder,
|
||||
TextInputBuilder,
|
||||
TextInputStyle,
|
||||
ActionRowBuilder
|
||||
} = 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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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()
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
async function planRaid(interaction) {
|
||||
const dutyId =
|
||||
interaction.options.getString(
|
||||
"duty",
|
||||
true
|
||||
);
|
||||
|
||||
|
||||
if (!ObjectId.isValid(dutyId)) {
|
||||
return interaction.reply({
|
||||
content:
|
||||
"Please select a duty from the autocomplete results.",
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
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.",
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The duty ObjectId is embedded in the modal customId.
|
||||
*
|
||||
* The modal handler can then retrieve the selected duty
|
||||
* without trusting editable modal input.
|
||||
*/
|
||||
const modal =
|
||||
buildRaidModal(duty);
|
||||
|
||||
|
||||
return interaction.showModal(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);
|
||||
|
||||
|
||||
/*
|
||||
* Display only.
|
||||
*
|
||||
* We don't use this field to identify the duty.
|
||||
* The ObjectId in the modal customId is authoritative.
|
||||
*/
|
||||
const dutyInput =
|
||||
new TextInputBuilder()
|
||||
.setCustomId("raid-duty")
|
||||
.setLabel("Duty")
|
||||
.setValue(duty.Name)
|
||||
.setStyle(
|
||||
TextInputStyle.Short
|
||||
)
|
||||
.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)
|
||||
.setMinLength(13)
|
||||
.setMaxLength(13)
|
||||
.setRequired(true);
|
||||
|
||||
|
||||
modal.addComponents(
|
||||
new ActionRowBuilder()
|
||||
.addComponents(nameInput),
|
||||
|
||||
new ActionRowBuilder()
|
||||
.addComponents(descriptionInput),
|
||||
|
||||
new ActionRowBuilder()
|
||||
.addComponents(dutyInput),
|
||||
|
||||
new ActionRowBuilder()
|
||||
.addComponents(dateInput),
|
||||
|
||||
new ActionRowBuilder()
|
||||
.addComponents(timeInput)
|
||||
);
|
||||
|
||||
|
||||
return modal;
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
"\\$&"
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user