const { mClient } = require(".."); async function getMember(client, userId) { const guild = client.guilds.cache.get(process.env.D_GuildID); if (!guild) { return null; } // Cache first let member = guild.members.cache.get(userId); // Fallback to API fetch if (!member) { member = await guild.members.fetch(userId).catch(() => null); } return member; } module.exports = { name: 'timerComplete', async execute(timer, client) { const db = mClient.db('neo-db'); const wgeColl = db.collection('timer_wge'); const participateColl = db.collection('items_wge'); const channelColl = db.collection('config_channels'); const guild = client.guilds.cache.get(process.env.D_GuildID); if (!guild) { console.error('timerComplete: Guild not found.'); return; } // Notify previous assignee via DM const previousMember = await getMember(client, timer.assignedUser); if (previousMember) { await previousMember.send( `❌ Timer ran out: **${timer.topic}** ...Re-assigning randomly...` ).catch(() => {}); } // Find the configured WGE channel const wgeChannelConfig = await channelColl.findOne({ purpose: 'wge', guildID: process.env.D_GuildID }); if (!wgeChannelConfig) { console.error('timerComplete: WGE channel configuration not found.'); return; } const channel = client.channels.cache.get(wgeChannelConfig.channelID); if (!channel) { console.error('timerComplete: WGE channel not found.'); return; } // Pick a random participant, excluding the previous assignee const randomParticipant = await participateColl.aggregate([ { $match: { status: true, userID: { $ne: timer.assignedUser } } }, { $sample: { size: 1 } } ]).toArray(); // Nobody else is available if (!randomParticipant.length) { await channel.send({ content: `The timer for <@${timer.assignedUser}> has run out, ` + `but there are currently no other participating users available for reassignment.` }); return; } const newMember = await guild.members .fetch(randomParticipant[0].userID) .catch(() => null); if (!newMember) { console.error( `timerComplete: Could not fetch selected user ${randomParticipant[0].userID}.` ); return; } const newAssignedUser = newMember.user; const wgeDefaultAssignedTime = 7 * 24 * 60 * 60 * 1000; // 7 days // Remove the expired timer specifically await wgeColl.deleteOne({ _id: timer._id }); // Create the new timer await wgeColl.insertOne({ assignedUser: newAssignedUser.id, assigningUser: timer.assigningUser, startedAt: Date.now(), timeRemaining: wgeDefaultAssignedTime, state: 'running', notifications: { half: false, day24: false, complete: false }, topic: timer.topic, debug: false, createdAt: new Date() }); // Announce reassignment await channel.send({ content: `The timer for <@${timer.assignedUser}> has run out! Assigning randomly...\n` + `<@${newAssignedUser.id}> is the next expert! Their topic is still **${timer.topic}**` }); } };