const { ModalBuilder, UserSelectMenuBuilder, TextInputBuilder, EmbedBuilder, TimestampStyles, time } = 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 .\n\n` + `Thank you, <@${results.assigningUser}>, for the nomination!` ) return interaction.editReply({ embeds: [embed] }) } async function wgeStart(interaction) { const wgeBaseModal = new ModalBuilder() .setCustomId('wgeBaseModal') .setTitle("World's Greatest Expert") const wgeUserInput = new UserSelectMenuBuilder() .setCustomId('wgeUserInput') .setMaxValues(1) .setRequired(true) .addDefaultUsers(process.env.D_ID) // DefaultUser is randomizer const wgeTopicInput = new TextInputBuilder() .setCustomId('wgeTopicInput') .setStyle(TextInputStyle.Short) .setRequired(true) const wgeUserLabel = new LabelBuilder() .setLabel("Who is YOUR World's Greatest Expert?") .setDescription('Select them!') .setUserSelectMenuComponent(wgeUserInput) const wgeTopicLabel = new LabelBuilder() .setLabel("And WHAT are they an expert in?") .setDescription('Tell me!') .setTextInputComponent(wgeTopicInput) wgeBaseModal .addLabelComponents(wgeUserLabel, 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(`You are ${status ? '' : 'no longer '}participating!`) } 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') ) ) , 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; default: break; } } }