diff --git a/src/commands/coach/queue/list.ts b/src/commands/coach/queue/list.ts index 49b4403..8a121de 100644 --- a/src/commands/coach/queue/list.ts +++ b/src/commands/coach/queue/list.ts @@ -1,4 +1,4 @@ -import { ApplicationCommandOptionType, EmbedField, Message } from "discord.js"; +import { ApplicationCommandOptionType, EmbedField, GuildMember, Message } from "discord.js"; import { Command } from "../../../../typings"; import { GuildModel } from "../../../models/guilds"; import { UserModel } from "../../../models/users"; @@ -54,9 +54,14 @@ const command: Command = { const position = queueData.getPosition(e.discord_id) + 1; const joined_at = ``; const intent = e.intent; - const member = await g.members.fetch(e.discord_id); + let member: GuildMember | null; + try { + member = await g.members.fetch(e.discord_id); + } catch (error) { + member = null; + } fields.push({ - name: member.displayName, value: + name: member?.displayName ?? "unknown", value: `-Position: ${position}` + `\n-joined at: ${joined_at}` + (intent ? `\n-intent: ${intent}` : ""), diff --git a/src/commands/coach/queue/next.ts b/src/commands/coach/queue/next.ts index 694c26d..6d16cbc 100644 --- a/src/commands/coach/queue/next.ts +++ b/src/commands/coach/queue/next.ts @@ -57,6 +57,11 @@ const command: Command = { if (!queueData) { return await client.utils.embeds.SimpleEmbed(interaction, { title: "Coaching System", text: "Queue Could not be Found.", empheral: true }); } + const members = await g.members.fetch(); + + // check if user is still on the server + await queueData.kickNonServerMembers(g, members); + if (queueData.isEmpty()) { return await client.utils.embeds.SimpleEmbed(interaction, { title: "Coaching System", text: "The Queue is Empty", empheral: true }); } @@ -66,6 +71,7 @@ const command: Command = { return await client.utils.embeds.SimpleEmbed(interaction, { title: "Coaching System Error", text: `There are less participants in the queue than requested.\n\\> Requested: ${interaction.options.getInteger("amount") ?? 1}\n\\> Available: ${entries.length}`, empheral: true }); } + // Get Room Spawner let spawner: VoiceChannelSpawner | undefined = queueData.room_spawner?.toObject(); @@ -106,7 +112,7 @@ const command: Command = { }, ); } else { - spawner.name = spawner.name ?? `${member.displayName}${member.displayName.endsWith("s")?"'":"s'"} ${queueData.name} Room ${coachingSession.getRoomAmount() + 1}`; + spawner.name = spawner.name ?? `${member.displayName}${member.displayName.endsWith("s") ? "'" : "s'"} ${queueData.name} Room ${coachingSession.getRoomAmount() + 1}`; } spawner.permission_overwrites = new mongoose.Types.DocumentArray( entries.map(x => { @@ -172,7 +178,7 @@ const command: Command = { // Try to move try { const member = g.members.resolve(user)!; - roomData.events.push({ emitted_by: "me", type: eventType.move_member, timestamp: Date.now().toString(), reason: `Queue System: '${queueData.name}' Queue automated member Move: ${member.id}`, target:member.id } as EVT); + roomData.events.push({ emitted_by: "me", type: eventType.move_member, timestamp: Date.now().toString(), reason: `Queue System: '${queueData.name}' Queue automated member Move: ${member.id}`, target: member.id } as EVT); await member.voice.setChannel(room); } catch (error) { // Ignore Errors @@ -188,7 +194,7 @@ const command: Command = { // Try to move Coach try { await member.voice.setChannel(room); - roomData.events.push({ emitted_by: "me", type: eventType.move_member, timestamp: Date.now().toString(), reason: `Queue System: '${queueData.name}' Queue automated member Move: ${member.id} (coach)`, target:member.id } as EVT); + roomData.events.push({ emitted_by: "me", type: eventType.move_member, timestamp: Date.now().toString(), reason: `Queue System: '${queueData.name}' Queue automated member Move: ${member.id} (coach)`, target: member.id } as EVT); } catch (error) { // Ignore Errors } diff --git a/src/commands/coach/queue/pick.ts b/src/commands/coach/queue/pick.ts index fd48522..6614480 100644 --- a/src/commands/coach/queue/pick.ts +++ b/src/commands/coach/queue/pick.ts @@ -66,6 +66,8 @@ const command: Command = { if (!queueData) { return await client.utils.embeds.SimpleEmbed(interaction, { title: "Coaching System", text: "Queue Could not be Found.", empheral: true }); } + + await queueData.kickNonServerMembers(g); if (queueData.isEmpty()) { return await client.utils.embeds.SimpleEmbed(interaction, { title: "Coaching System", text: "The Queue is Empty", empheral: true }); } diff --git a/src/models/queues.ts b/src/models/queues.ts index e6ac5eb..f2260f6 100644 --- a/src/models/queues.ts +++ b/src/models/queues.ts @@ -7,6 +7,7 @@ import * as moment from "moment"; import { QueueSpan } from "./queue_span"; import { Guild } from "./guilds"; import { VoiceChannelSpawner } from "./voice_channel_spawner"; +import * as djs from "discord.js"; /** * A Queue from the Database @@ -213,7 +214,8 @@ export class Queue { "member_id": entry.discord_id, "user": `<@${entry.discord_id}>`, "pos": this.getPosition(entry.discord_id) + 1, - "time_spent": moment.duration(Date.now() - (+entry.joinedAt)).format("d[d ]h[h ]m[m ]s.S[s]"), + "time_spent": (moment.duration(Date.now() - (+entry.joinedAt)) as unknown as { format: (arg0: string) => string; }) + .format("d[d ]h[h ]m[m ]s.S[s]"), }; for (const [key, value] of Object.entries(entryReplacements)) { replacements[key] = value; @@ -344,6 +346,26 @@ export class Queue { public getWaitingRooms(this: DocumentType, guild: Guild): DocumentType[] { return guild.voice_channels?.filter(x => x.queue?._id.equals(this._id!)) ?? []; } + + /** + * Kicks all queue entries that are not in the server the queue is in + * @param this the Queue instance + * @param guild (optionally) the corresponding guild + */ + public async kickNonServerMembers(this: DocumentType, guild: djs.Guild, members?: Map) { + if (!members) { + members = await guild.members.fetch(); + } + const entries = this.entries.filter(x => !members!.has(x.discord_id)); + if (!entries.length) { + return []; + } + console.log(`Missing: ${entries.map(x => x.discord_id).join(", ")} queue entries on Guild. Removing from Queue.`); + for (const entry of entries) { + await this.leave(entry.discord_id); + } + return entries; + } } export const QueueModel = getModelForClass(Queue, {