437 lines
12 KiB
JavaScript
437 lines
12 KiB
JavaScript
const { ModalBuilder, UserSelectMenuBuilder, TextInputBuilder, EmbedBuilder, TimestampStyles, time, StringSelectMenuBuilder } = require("@discordjs/builders");
|
|
const { SlashCommandBuilder, LabelBuilder, TextInputStyle, MessageFlags } = require("discord.js");
|
|
const { mClient } = require("../../..");
|
|
require('dotenv').config()
|
|
|
|
function getRemaining(timer) {
|
|
if (timer.state !== 'running') {
|
|
return timer.timeRemaining;
|
|
}
|
|
|
|
return Math.max(
|
|
0,
|
|
timer.timeRemaining - (Date.now() - timer.startedAt)
|
|
);
|
|
}
|
|
|
|
function ordinal(n) {
|
|
const s = ["th", "st", "nd", "rd"];
|
|
const v = n % 100;
|
|
|
|
return n + (s[(v - 20) % 10] || s[v] || s[0]);
|
|
}
|
|
|
|
async function wgeStatus(interaction) {
|
|
const db = mClient.db('neo-db')
|
|
const wgeColl = db.collection('timer_wge')
|
|
const historyColl = db.collection('history_wge');
|
|
|
|
const results = await wgeColl.findOne({
|
|
$and: [
|
|
{ debug: false },
|
|
{ state: 'running' }
|
|
]
|
|
})
|
|
if (!results) {
|
|
return interaction.editReply({
|
|
content: 'No WGE Session currently running!',
|
|
flags: MessageFlags.Ephemeral
|
|
})
|
|
}
|
|
|
|
const historyCount = await historyColl.countDocuments();
|
|
const iteration = historyCount + 1;
|
|
|
|
const createdAt = new Date(results.createdAt)
|
|
const expiresAt = new Date(createdAt.getTime() + Number(results.timeRemaining))
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setTitle(`✨ [${ordinal(iteration)}] World's Greatest Expert ✨`)
|
|
.setDescription(
|
|
`<@${results.assignedUser}> is currently the **World's Greatest Expert** in **${results.topic}**.\n\n` +
|
|
`They must submit their entry <t:${Math.floor(expiresAt.getTime() / 1000)}:R>.\n\n` +
|
|
`Thank you, <@${results.assigningUser}>, for the nomination!`
|
|
)
|
|
|
|
return interaction.editReply({
|
|
embeds: [embed]
|
|
})
|
|
}
|
|
|
|
async function wgeStart(interaction) {
|
|
const defaultUsers = []
|
|
defaultUsers.push(process.env.D_ID)
|
|
|
|
const db = mClient.db('neo-db')
|
|
const participantColl = db.collection('items_wge')
|
|
const participants = await participantColl.find({
|
|
status: true
|
|
}).toArray()
|
|
|
|
|
|
const wgeBaseModal = new ModalBuilder()
|
|
.setCustomId('wgeBaseModal')
|
|
.setTitle("World's Greatest Expert")
|
|
|
|
const options = [
|
|
{
|
|
label: 'RANDOM',
|
|
value: process.env.D_ID
|
|
}
|
|
];
|
|
|
|
const participantOptions = await Promise.all(
|
|
participants.map(async (participant) => {
|
|
try {
|
|
const member = await interaction.guild.members.fetch(participant.userID);
|
|
return {
|
|
label: `${member.displayName} (${member.user.username})`,
|
|
value: participant.userID
|
|
};
|
|
} catch {
|
|
return null;
|
|
}
|
|
})
|
|
);
|
|
|
|
options.push(
|
|
...participantOptions.filter(option => option !== null)
|
|
);
|
|
|
|
// Using StringSelectMenuBuilder because UserSelectMenuBuilder cannot be filtered for now
|
|
const wgeUserCustInput = new StringSelectMenuBuilder()
|
|
.setCustomId('wgeCustUserInput')
|
|
.setMaxValues(1)
|
|
.setMinValues(1)
|
|
.setRequired(true)
|
|
.addOptions(options)
|
|
|
|
const wgeTopicInput = new TextInputBuilder()
|
|
.setCustomId('wgeTopicInput')
|
|
.setStyle(TextInputStyle.Short)
|
|
.setRequired(true)
|
|
|
|
const wgeTopicLabel = new LabelBuilder()
|
|
.setLabel("And WHAT are they an expert in?")
|
|
.setDescription('Tell me!')
|
|
.setTextInputComponent(wgeTopicInput)
|
|
|
|
const wgeCustUserLabel = new LabelBuilder()
|
|
.setLabel('WHO is your greatest expert?')
|
|
.setDescription('Select them')
|
|
.setStringSelectMenuComponent(wgeUserCustInput)
|
|
|
|
wgeBaseModal
|
|
.addLabelComponents(wgeCustUserLabel, wgeTopicLabel)
|
|
|
|
await interaction.showModal(wgeBaseModal)
|
|
}
|
|
|
|
async function wgeStop(interaction) {
|
|
const db = mClient.db('neo-db');
|
|
const wgeColl = db.collection('timer_wge');
|
|
|
|
const timer = await wgeColl.findOne({
|
|
debug: false
|
|
});
|
|
|
|
if (!timer) {
|
|
return interaction.reply({
|
|
content: 'Timer not found.',
|
|
flags: MessageFlags.Ephemeral
|
|
});
|
|
}
|
|
|
|
// freeze remaining time
|
|
const remaining = getRemaining(timer);
|
|
|
|
await wgeColl.updateOne(
|
|
{ _id: timer._id },
|
|
{
|
|
$set: {
|
|
timeRemaining: remaining,
|
|
startedAt: null,
|
|
state: 'stopped'
|
|
}
|
|
}
|
|
);
|
|
|
|
await interaction.reply({
|
|
content: `🛑 Timer stopped for **${timer.topic}**`
|
|
});
|
|
}
|
|
|
|
async function wgeResume(interaction) {
|
|
const db = mClient.db('neo-db');
|
|
const wgeColl = db.collection('timer_wge');
|
|
|
|
const timer = await wgeColl.findOne({
|
|
debug: false
|
|
});
|
|
|
|
if (!timer) {
|
|
return interaction.reply({
|
|
content: 'Timer not found.',
|
|
ephemeral: true
|
|
});
|
|
}
|
|
|
|
// freeze remaining time
|
|
const remaining = getRemaining(timer);
|
|
|
|
await wgeColl.updateOne(
|
|
{ _id: timer._id },
|
|
{
|
|
$set: {
|
|
timeRemaining: remaining,
|
|
startedAt: Date.now(),
|
|
state: 'running'
|
|
}
|
|
}
|
|
);
|
|
|
|
await interaction.reply({
|
|
content: `🟢 Timer resumed for **${timer.topic}**`
|
|
});
|
|
}
|
|
|
|
async function wgeForfeit(interaction) {
|
|
// Reset Timer, Reassign Randomly
|
|
const db = mClient.db('neo-db')
|
|
const wgeColl = db.collection('timer_wge')
|
|
|
|
// Randomizer Function
|
|
const participateColl = db.collection('items_wge')
|
|
const randomParticipant = await participateColl.aggregate([
|
|
{ $match: { status: true } },
|
|
{ $sample: { size: 1 } }
|
|
]).toArray()
|
|
|
|
if (!randomParticipant.length) { return interaction.reply({ content: 'No one else is participating!' }) }
|
|
|
|
random = await interaction.guild.members.fetch(randomParticipant[0].userID)
|
|
wgeAssignedUser = random.user
|
|
|
|
const wge = await wgeColl.findOne({
|
|
$and: [
|
|
{ debug: false },
|
|
{ state: 'running' }
|
|
]
|
|
})
|
|
|
|
await wgeColl.deleteOne({
|
|
_id: wge._id
|
|
})
|
|
|
|
const wgeDefaultAssignedTime = 7 * 24 * 60 * 60 * 1000; // 7 days in ms
|
|
|
|
interaction.reply({
|
|
content: `${interaction.user} has forfeited! <@${wgeAssignedUser.id}> is the next expert! Their topic is **${wge.topic}**`
|
|
})
|
|
|
|
await wgeColl.insertOne({
|
|
assignedUser: wgeAssignedUser.id,
|
|
assigningUser: wge.assigningUser,
|
|
|
|
startedAt: Date.now(),
|
|
timeRemaining: wgeDefaultAssignedTime,
|
|
|
|
state: 'running',
|
|
|
|
notifications: {
|
|
half: false,
|
|
day24: false,
|
|
complete: false
|
|
},
|
|
|
|
topic: wge.topic,
|
|
debug: false,
|
|
|
|
createdAt: new Date()
|
|
});
|
|
}
|
|
|
|
async function wgeHistory(interaction) {
|
|
//FIXME!
|
|
}
|
|
|
|
async function wgeParticipate(interaction) {
|
|
const status = interaction.options.getBoolean('status')
|
|
const user = interaction.user
|
|
const db = mClient.db('neo-db')
|
|
const coll = db.collection('items_wge')
|
|
|
|
// Choice was false, ergo not participating
|
|
await coll.findOneAndUpdate({
|
|
userID: user.id
|
|
}, {
|
|
$set: {
|
|
userID: user.id,
|
|
status: status
|
|
}
|
|
}, {
|
|
upsert: true
|
|
})
|
|
|
|
interaction.reply({
|
|
content: `You are ${status ? '' : 'no longer '}participating!`,
|
|
flags: MessageFlags.Ephemeral
|
|
})
|
|
}
|
|
|
|
async function wgeList(interaction) {
|
|
const thing = interaction.options.getString('thing');
|
|
|
|
switch (thing) {
|
|
case 'participants': {
|
|
const db = mClient.db('neo-db');
|
|
const participantColl = db.collection('items_wge');
|
|
const participants = await participantColl.find({}).toArray();
|
|
|
|
const participating = participants
|
|
.filter(p => p.status)
|
|
.map(p => `<@${p.userID}>`);
|
|
|
|
const notParticipating = participants
|
|
.filter(p => !p.status)
|
|
.map(p => `<@${p.userID}>`);
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setTitle('WGE Participation')
|
|
.setColor(0x5865F2)
|
|
.addFields(
|
|
{
|
|
name: `Participating (${participating.length})`,
|
|
value: participating.join('\n') || 'No participants found.',
|
|
inline: true
|
|
},
|
|
{
|
|
name: `Not Participating (${notParticipating.length})`,
|
|
value: notParticipating.join('\n') || 'No entries found.',
|
|
inline: true
|
|
}
|
|
)
|
|
.setFooter({
|
|
text: `Total entries: ${participants.length}`
|
|
})
|
|
|
|
await interaction.reply({
|
|
embeds: [embed],
|
|
flags: MessageFlags.Ephemeral
|
|
});
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
data: new SlashCommandBuilder()
|
|
.setName('wge')
|
|
.setDescription('welcome to worlds greatest experts')
|
|
// Show Status of Current Running WGE Session
|
|
.addSubcommand(s =>
|
|
s
|
|
.setName('status')
|
|
.setDescription('display current wge session')
|
|
)
|
|
|
|
// Assign Someone to be the next Expert
|
|
.addSubcommand(s =>
|
|
s
|
|
.setName('start')
|
|
.setDescription('start a new wge session')
|
|
)
|
|
|
|
// Stop the current Session Timer
|
|
.addSubcommand(s =>
|
|
s
|
|
.setName('stop')
|
|
.setDescription('stop the current wge session')
|
|
)
|
|
|
|
// Resume the current Session Timer
|
|
.addSubcommand(s =>
|
|
s
|
|
.setName('resume')
|
|
.setDescription('resume the current wge session timer')
|
|
)
|
|
|
|
// Forfeit your current expert topic and assign someone else
|
|
.addSubcommand(s =>
|
|
s
|
|
.setName('forfeit')
|
|
.setDescription('forfeit your current topic')
|
|
)
|
|
|
|
// List the previous WGE Sessions
|
|
.addSubcommand(s =>
|
|
s
|
|
.setName('history')
|
|
.setDescription('display the previous wge sessions')
|
|
)
|
|
|
|
// List the previous WGE Sessions
|
|
.addSubcommand(s =>
|
|
s
|
|
.setName('participate')
|
|
.setDescription('do you want to play a game?')
|
|
.addBooleanOption(o =>
|
|
o.setName('status')
|
|
.setDescription('choose')
|
|
.setRequired(true)
|
|
)
|
|
)
|
|
|
|
// List the previous WGE Sessions
|
|
.addSubcommand(s =>
|
|
s
|
|
.setName('list')
|
|
.setDescription('list things')
|
|
.addStringOption(o =>
|
|
o.setName('thing')
|
|
.setDescription('what would you like to be listed')
|
|
.addChoices(
|
|
{ name: 'participants', value: 'participants' },
|
|
{ name: 'history', value: 'history' }
|
|
)
|
|
)
|
|
)
|
|
,
|
|
async execute(interaction) {
|
|
switch (interaction.options._subcommand) {
|
|
case 'status':
|
|
await interaction.deferReply()
|
|
wgeStatus(interaction)
|
|
break;
|
|
case 'start':
|
|
wgeStart(interaction)
|
|
break;
|
|
case 'stop':
|
|
wgeStop(interaction)
|
|
break;
|
|
case 'pause':
|
|
wgePause(interaction)
|
|
break;
|
|
case 'resume':
|
|
wgeResume(interaction)
|
|
break;
|
|
case 'forfeit':
|
|
wgeForfeit(interaction)
|
|
break;
|
|
case 'history':
|
|
wgeHistory(interaction)
|
|
break;
|
|
case 'participate':
|
|
wgeParticipate(interaction)
|
|
break;
|
|
case 'list':
|
|
wgeList(interaction)
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
} |