rewrote cookiesgit add commands/applications/random.js
This commit is contained in:
@@ -0,0 +1,557 @@
|
||||
const {
|
||||
SlashCommandBuilder,
|
||||
EmbedBuilder,
|
||||
AttachmentBuilder
|
||||
} = require("discord.js");
|
||||
|
||||
const { mClient } = require("../..");
|
||||
const path = require("node:path");
|
||||
const jobIconDirectory = path.resolve(
|
||||
__dirname,
|
||||
"../../assets/jobs"
|
||||
);
|
||||
const expansions = [
|
||||
{ name: "A Realm Reborn", value: 2 },
|
||||
{ name: "Heavensward", value: 3 },
|
||||
{ name: "Stormblood", value: 4 },
|
||||
{ name: "Shadowbringers", value: 5 },
|
||||
{ name: "Endwalker", value: 6 },
|
||||
{ name: "Dawntrail", value: 7 }
|
||||
];
|
||||
|
||||
const dutyTypes = [
|
||||
{ name: "Dungeon", value: "Dungeon" },
|
||||
{ name: "Trial", value: "Trial" },
|
||||
{ name: "Raid", value: "Raid" },
|
||||
{ name: "Alliance Raid", value: "AllianceRaid" },
|
||||
{ name: "Guildhest", value: "Guildhest" },
|
||||
{ name: "Variant Dungeon", value: "VariantDungeon" },
|
||||
{ name: "Criterion", value: "Criterion" }
|
||||
];
|
||||
|
||||
const dutyDifficulties = [
|
||||
{ name: "Normal", value: "Normal" },
|
||||
{ name: "Hard", value: "Hard" },
|
||||
{ name: "Extreme", value: "Extreme" },
|
||||
{ name: "Unreal", value: "Unreal" },
|
||||
{ name: "Savage", value: "Savage" },
|
||||
{ name: "Ultimate", value: "Ultimate" },
|
||||
{ name: "Chaotic", value: "Chaotic" }
|
||||
];
|
||||
|
||||
const roulettes = [
|
||||
{ name: "Leveling", value: "Leveling" },
|
||||
{ name: "High-level Dungeons", value: "High-level Dungeons" },
|
||||
{ name: "Level Cap Dungeons", value: "Level Cap Dungeons" },
|
||||
{ name: "Trials", value: "Trials" },
|
||||
{ name: "Normal Raids", value: "Normal Raids" },
|
||||
{ name: "Alliance Raids", value: "Alliance Raids" },
|
||||
{ name: "Main Scenario", value: "Main Scenario" },
|
||||
{ name: "Guildhests", value: "Guildhests" },
|
||||
{ name: "Mentor", value: "Mentor" }
|
||||
];
|
||||
|
||||
const roles = [
|
||||
{ name: "Tank", value: "Tank" },
|
||||
{ name: "Healer", value: "Healer" },
|
||||
{ name: "DPS", value: "DPS" }
|
||||
];
|
||||
|
||||
const roleTypes = [
|
||||
{ name: "Tank", value: "Tank" },
|
||||
{ name: "Pure Healer", value: "Pure" },
|
||||
{ name: "Shield Healer", value: "Shield" },
|
||||
{ name: "Melee DPS", value: "Melee" },
|
||||
{ name: "Physical Ranged DPS", value: "PhysicalRanged" },
|
||||
{ name: "Magical Ranged DPS", value: "MagicalRanged" }
|
||||
];
|
||||
|
||||
const damageTypes = [
|
||||
{ name: "Physical", value: "Physical" },
|
||||
{ name: "Magical", value: "Magical" }
|
||||
];
|
||||
|
||||
function getJobIcon(job) {
|
||||
const fileName = `${job.Name.replace(/\s+/g, "")}.png`;
|
||||
|
||||
return path.join(
|
||||
jobIconDirectory,
|
||||
fileName
|
||||
);
|
||||
}
|
||||
|
||||
const dutyIcons = {
|
||||
Guildhest:
|
||||
"https://ffxiv.consolegameswiki.com/mediawiki/images/6/61/Guildhest.png",
|
||||
|
||||
Dungeon:
|
||||
"https://ffxiv.consolegameswiki.com/mediawiki/images/a/ab/Dungeon.png",
|
||||
|
||||
Trial:
|
||||
"https://ffxiv.consolegameswiki.com/mediawiki/images/0/0d/Trial.png",
|
||||
|
||||
Raid:
|
||||
"https://ffxiv.consolegameswiki.com/mediawiki/images/d/d6/Raid.png",
|
||||
|
||||
AllianceRaid:
|
||||
"https://ffxiv.consolegameswiki.com/mediawiki/images/d/d6/Raid.png",
|
||||
|
||||
VariantDungeon:
|
||||
"https://ffxiv.consolegameswiki.com/mediawiki/images/5/5e/Variant_and_criterion_dungeons_icon1.png",
|
||||
|
||||
Criterion:
|
||||
"https://ffxiv.consolegameswiki.com/mediawiki/images/5/5e/Variant_and_criterion_dungeons_icon1.png"
|
||||
};
|
||||
|
||||
const dutyDifficultyIcons = {
|
||||
Ultimate:
|
||||
"https://ffxiv.consolegameswiki.com/mediawiki/images/8/8a/Ultimate_Raid.png",
|
||||
|
||||
Chaotic:
|
||||
"https://ffxiv.consolegameswiki.com/mediawiki/images/a/a9/Chaotic_Alliance_Raid.png"
|
||||
};
|
||||
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("random")
|
||||
.setDescription("Randomly select FFXIV content.")
|
||||
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName("duty")
|
||||
.setDescription("Select a random duty to complete.")
|
||||
|
||||
.addIntegerOption(option =>
|
||||
option
|
||||
.setName("level")
|
||||
.setDescription("Your current level.")
|
||||
.setRequired(true)
|
||||
.setMinValue(10)
|
||||
.setMaxValue(100)
|
||||
)
|
||||
|
||||
.addStringOption(option =>
|
||||
option
|
||||
.setName("type")
|
||||
.setDescription("Only select a specific duty type.")
|
||||
.addChoices(...dutyTypes)
|
||||
)
|
||||
|
||||
.addStringOption(option =>
|
||||
option
|
||||
.setName("difficulty")
|
||||
.setDescription("Only select a specific difficulty.")
|
||||
.addChoices(...dutyDifficulties)
|
||||
)
|
||||
|
||||
.addIntegerOption(option =>
|
||||
option
|
||||
.setName("expansion")
|
||||
.setDescription("Only select duties from an expansion.")
|
||||
.addChoices(...expansions)
|
||||
)
|
||||
|
||||
.addStringOption(option =>
|
||||
option
|
||||
.setName("roulette")
|
||||
.setDescription("Only select duties belonging to a roulette.")
|
||||
.addChoices(...roulettes)
|
||||
)
|
||||
|
||||
.addIntegerOption(option =>
|
||||
option
|
||||
.setName("party-size")
|
||||
.setDescription("Only select duties with this party size.")
|
||||
.addChoices(
|
||||
{ name: "4 Players", value: 4 },
|
||||
{ name: "8 Players", value: 8 },
|
||||
{ name: "24 Players", value: 24 }
|
||||
)
|
||||
)
|
||||
|
||||
.addBooleanOption(option =>
|
||||
option
|
||||
.setName("duty-support")
|
||||
.setDescription("Filter by Duty Support availability.")
|
||||
)
|
||||
|
||||
.addBooleanOption(option =>
|
||||
option
|
||||
.setName("trusts")
|
||||
.setDescription("Filter by Trust availability.")
|
||||
)
|
||||
)
|
||||
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName("class")
|
||||
.setDescription("Select a random class or job.")
|
||||
|
||||
.addStringOption(option =>
|
||||
option
|
||||
.setName("role")
|
||||
.setDescription("Only select a specific role.")
|
||||
.addChoices(...roles)
|
||||
)
|
||||
|
||||
.addStringOption(option =>
|
||||
option
|
||||
.setName("role-type")
|
||||
.setDescription("Only select a specific role subtype.")
|
||||
.addChoices(...roleTypes)
|
||||
)
|
||||
|
||||
.addStringOption(option =>
|
||||
option
|
||||
.setName("damage-type")
|
||||
.setDescription("Filter by physical or magical damage.")
|
||||
.addChoices(...damageTypes)
|
||||
)
|
||||
|
||||
.addIntegerOption(option =>
|
||||
option
|
||||
.setName("expansion")
|
||||
.setDescription("Only select classes/jobs from an expansion.")
|
||||
.addChoices(...expansions)
|
||||
)
|
||||
|
||||
.addBooleanOption(option =>
|
||||
option
|
||||
.setName("jobstone")
|
||||
.setDescription("True for jobs, false for base classes.")
|
||||
)
|
||||
|
||||
.addBooleanOption(option =>
|
||||
option
|
||||
.setName("limited")
|
||||
.setDescription("Filter by limited-job status.")
|
||||
)
|
||||
|
||||
.addIntegerOption(option =>
|
||||
option
|
||||
.setName("max-starting-level")
|
||||
.setDescription("Maximum starting level of the class/job.")
|
||||
.setMinValue(1)
|
||||
.setMaxValue(100)
|
||||
)
|
||||
),
|
||||
|
||||
async execute(interaction) {
|
||||
switch (interaction.options.getSubcommand()) {
|
||||
case "duty":
|
||||
return randomDuty(interaction);
|
||||
|
||||
case "class":
|
||||
return randomClass(interaction);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
async function randomDuty(interaction) {
|
||||
const collection = mClient
|
||||
.db("neo-db")
|
||||
.collection("items_duties");
|
||||
|
||||
const level = interaction.options.getInteger("level");
|
||||
const type = interaction.options.getString("type");
|
||||
const difficulty = interaction.options.getString("difficulty");
|
||||
const expansion = interaction.options.getInteger("expansion");
|
||||
const roulette = interaction.options.getString("roulette");
|
||||
const partySize = interaction.options.getInteger("party-size");
|
||||
const dutySupport = interaction.options.getBoolean("duty-support");
|
||||
const trusts = interaction.options.getBoolean("trusts");
|
||||
|
||||
const query = {
|
||||
MinimumLevel: {
|
||||
$lte: level
|
||||
}
|
||||
};
|
||||
|
||||
if (type !== null)
|
||||
query.Type = type;
|
||||
|
||||
if (difficulty !== null)
|
||||
query.Difficulty = difficulty;
|
||||
|
||||
if (expansion !== null)
|
||||
query.Expansion = expansion;
|
||||
|
||||
if (roulette !== null)
|
||||
query.Roulettes = roulette;
|
||||
|
||||
if (partySize !== null)
|
||||
query["Party.Size"] = partySize;
|
||||
|
||||
if (dutySupport !== null)
|
||||
query["Party.CanUseDutySupport"] = dutySupport;
|
||||
|
||||
if (trusts !== null)
|
||||
query["Party.CanUseTrusts"] = trusts;
|
||||
|
||||
|
||||
const [duty] = await collection.aggregate([
|
||||
{
|
||||
$match: query
|
||||
},
|
||||
{
|
||||
$sample: {
|
||||
size: 1
|
||||
}
|
||||
}
|
||||
]).toArray();
|
||||
|
||||
|
||||
if (!duty) {
|
||||
return interaction.reply({
|
||||
content: "No duties matched those filters.",
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(duty.Name)
|
||||
.setThumbnail(getDutyIcon(duty))
|
||||
.setDescription(
|
||||
[
|
||||
`**${formatDutyType(duty.Type)}**`,
|
||||
`${duty.Difficulty} Difficulty`,
|
||||
`${getExpansionName(duty.Expansion)} • Patch ${formatPatch(duty)}`
|
||||
].join("\n")
|
||||
)
|
||||
.addFields(
|
||||
{
|
||||
name: "Level",
|
||||
value: `${duty.MinimumLevel}`,
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: "Level Sync",
|
||||
value: `${duty.LevelSync}`,
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: "Minimum Item Level",
|
||||
value: duty.MinimumItemLevel
|
||||
? `${duty.MinimumItemLevel}`
|
||||
: "None",
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: "Party",
|
||||
value: formatParty(duty.Party)
|
||||
},
|
||||
{
|
||||
name: "Roulettes",
|
||||
value: duty.Roulettes?.length
|
||||
? duty.Roulettes.join(", ")
|
||||
: "None"
|
||||
},
|
||||
{
|
||||
name: "NPC Support",
|
||||
value: [
|
||||
`Duty Support: ${duty.Party.CanUseDutySupport ? "Yes" : "No"}`,
|
||||
`Trusts: ${duty.Party.CanUseTrusts ? "Yes" : "No"}`
|
||||
].join("\n")
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
return interaction.reply({
|
||||
embeds: [embed]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
async function randomClass(interaction) {
|
||||
const collection = mClient
|
||||
.db("neo-db")
|
||||
.collection("items_classes");
|
||||
|
||||
const role = interaction.options.getString("role");
|
||||
const roleType = interaction.options.getString("role-type");
|
||||
const damageType = interaction.options.getString("damage-type");
|
||||
const expansion = interaction.options.getInteger("expansion");
|
||||
const hasJobStone = interaction.options.getBoolean("jobstone");
|
||||
const limited = interaction.options.getBoolean("limited");
|
||||
const maxStartingLevel =
|
||||
interaction.options.getInteger("max-starting-level");
|
||||
|
||||
const query = {};
|
||||
|
||||
if (role !== null)
|
||||
query.Role = role;
|
||||
|
||||
if (roleType !== null)
|
||||
query.RoleType = roleType;
|
||||
|
||||
if (damageType !== null)
|
||||
query.DamageType = damageType;
|
||||
|
||||
if (expansion !== null)
|
||||
query.Expansion = expansion;
|
||||
|
||||
if (hasJobStone !== null)
|
||||
query.HasJobStone = hasJobStone;
|
||||
|
||||
if (limited !== null)
|
||||
query.Limited = limited;
|
||||
|
||||
if (maxStartingLevel !== null) {
|
||||
query.StartingLevel = {
|
||||
$lte: maxStartingLevel
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const [job] = await collection.aggregate([
|
||||
{
|
||||
$match: query
|
||||
},
|
||||
{
|
||||
$sample: {
|
||||
size: 1
|
||||
}
|
||||
}
|
||||
]).toArray();
|
||||
|
||||
|
||||
if (!job) {
|
||||
return interaction.reply({
|
||||
content: "No classes or jobs matched those filters.",
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
|
||||
const icon = new AttachmentBuilder(
|
||||
getJobIcon(job),
|
||||
{
|
||||
name: `${job.Abbreviation}.png`
|
||||
}
|
||||
);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`${job.Name} (${job.Abbreviation})`)
|
||||
.setThumbnail(`attachment://${job.Abbreviation}.png`)
|
||||
.setDescription(
|
||||
[
|
||||
`**${job.Role} • ${formatRoleType(job.RoleType)}**`,
|
||||
`${job.DamageType} Damage`,
|
||||
`${getExpansionName(job.Expansion)} • Patch ${formatPatch(job)}`
|
||||
].join("\n")
|
||||
)
|
||||
.addFields(
|
||||
{
|
||||
name: "Starting Level",
|
||||
value: `${job.StartingLevel}`,
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: "Job Stone",
|
||||
value: job.HasJobStone ? "Yes" : "No",
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: "Limited Job",
|
||||
value: job.Limited ? "Yes" : "No",
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: "Base Class",
|
||||
value: job.Class ?? "None",
|
||||
inline: true
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
return interaction.reply({
|
||||
embeds: [embed],
|
||||
files: [icon]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function getDutyIcon(duty) {
|
||||
return dutyDifficultyIcons[duty.Difficulty]
|
||||
?? dutyIcons[duty.Type]
|
||||
?? null;
|
||||
}
|
||||
|
||||
|
||||
function getExpansionName(expansion) {
|
||||
return expansions.find(entry =>
|
||||
entry.value === expansion
|
||||
)?.name ?? `Expansion ${expansion}`;
|
||||
}
|
||||
|
||||
|
||||
function formatPatch(item) {
|
||||
if (item.MinorPatch) {
|
||||
return `${item.Expansion}.${item.MajorPatch}${item.MinorPatch}`;
|
||||
}
|
||||
|
||||
return `${item.Expansion}.${item.MajorPatch}`;
|
||||
}
|
||||
|
||||
|
||||
function formatDutyType(type) {
|
||||
switch (type) {
|
||||
case "AllianceRaid":
|
||||
return "Alliance Raid";
|
||||
|
||||
case "VariantDungeon":
|
||||
return "Variant Dungeon";
|
||||
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function formatRoleType(roleType) {
|
||||
switch (roleType) {
|
||||
case "PhysicalRanged":
|
||||
return "Physical Ranged";
|
||||
|
||||
case "MagicalRanged":
|
||||
return "Magical Ranged";
|
||||
|
||||
case "Pure":
|
||||
return "Pure Healer";
|
||||
|
||||
case "Shield":
|
||||
return "Shield Healer";
|
||||
|
||||
default:
|
||||
return roleType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function formatParty(party) {
|
||||
const roles = [];
|
||||
|
||||
if (party.Tanks > 0) {
|
||||
roles.push(
|
||||
`${party.Tanks} Tank${party.Tanks !== 1 ? "s" : ""}`
|
||||
);
|
||||
}
|
||||
|
||||
if (party.Healers > 0) {
|
||||
roles.push(
|
||||
`${party.Healers} Healer${party.Healers !== 1 ? "s" : ""}`
|
||||
);
|
||||
}
|
||||
|
||||
if (party.DPS > 0) {
|
||||
roles.push(`${party.DPS} DPS`);
|
||||
}
|
||||
|
||||
if (!roles.length) {
|
||||
return `${party.Size} Player${party.Size !== 1 ? "s" : ""}`;
|
||||
}
|
||||
|
||||
return `${party.Size} Players\n${roles.join(" • ")}`;
|
||||
}
|
||||
Reference in New Issue
Block a user