From 309349eb3cdd2fcbf57e7b36da1911323fac3c8c Mon Sep 17 00:00:00 2001 From: niklhut <49069026+niklhut@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:09:19 +0100 Subject: [PATCH 01/12] Move create queue to config --- src/commands/{ => config/queue}/create-queue.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename src/commands/{ => config/queue}/create-queue.ts (93%) diff --git a/src/commands/create-queue.ts b/src/commands/config/queue/create-queue.ts similarity index 93% rename from src/commands/create-queue.ts rename to src/commands/config/queue/create-queue.ts index 306d763..b76dbe8 100644 --- a/src/commands/create-queue.ts +++ b/src/commands/config/queue/create-queue.ts @@ -1,13 +1,13 @@ import { ApplicationCommandOptionType, Message } from "discord.js"; -import { Command } from "../../typings"; -import { GuildModel } from "../models/guilds"; -import { Queue } from "../models/queues"; +import { Command } from "../../../../typings"; +import { GuildModel } from "../../../models/guilds"; +import { Queue } from "../../../models/queues"; import { mongoose } from "@typegoose/typegoose"; import { FilterOutFunctionKeys } from "@typegoose/typegoose/lib/types"; const command: Command = { - name: "create-queue", - description: "creates a queue", + name: "create", + description: "Creates a queue", aliases: ["cq"], usage: "[channel resolvable]", cooldown: 5, From cf7e535e98ccf6ed938aa833a24564333b1da9fb Mon Sep 17 00:00:00 2001 From: niklhut <49069026+niklhut@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:09:43 +0100 Subject: [PATCH 02/12] Change description parameter to be required --- src/commands/config/queue/create-queue.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/config/queue/create-queue.ts b/src/commands/config/queue/create-queue.ts index b76dbe8..5f76005 100644 --- a/src/commands/config/queue/create-queue.ts +++ b/src/commands/config/queue/create-queue.ts @@ -23,7 +23,7 @@ const command: Command = { name: "description", description: "The Queue Description", type: ApplicationCommandOptionType.String, - required: false, + required: true, }, ], guildOnly: true, From ecfc64804e7ad82916cf68fd6ee56e80c20ca525 Mon Sep 17 00:00:00 2001 From: niklhut <49069026+niklhut@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:11:30 +0100 Subject: [PATCH 03/12] Adjust setup documentation --- Setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Setup.md b/Setup.md index 8d02ec4..c451245 100644 --- a/Setup.md +++ b/Setup.md @@ -16,7 +16,7 @@ 5. Call the command `/admin genverifyroles` to generate the roles in the database. 6. Create a new category, call it for example `Tutoring` and make it private but allow the `Tutor` role to see it. 7. Create one voice channel in the category, for example `tutoring-waiting` and allow the `Verified` role to see it. The `Tutor` role should be able to see it already because it is in the same category. -8. Call the command `/create-queue` and pass it the name for the queue and a description, for example `tutoring`. This will create a new queue in the database. +8. Call the command `/config queue create` and pass it the name for the queue and a description, for example `tutoring` and `the queue used to wait for tutoring`. This will create a new queue in the database. 9. Call the command `/setqueue` and pass it the name of the waiting channel, for example `tutoring-waiting` and the name of the queue, for example `tutoring` as well as the supervisor role, for example `Tutor`. This will set the waiting channel for the queue and the supervisor role. 10. Optionally rename the `coach` commands on the server to `tutor` by calling the command `/config commands rename` and passing it the old and new name of the command. From 33c941e7bf38e958ac2788ca1ca81afdeb35b1f7 Mon Sep 17 00:00:00 2001 From: niklhut <49069026+niklhut@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:13:24 +0100 Subject: [PATCH 04/12] Rename command file --- src/commands/config/queue/{create-queue.ts => create.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/commands/config/queue/{create-queue.ts => create.ts} (100%) diff --git a/src/commands/config/queue/create-queue.ts b/src/commands/config/queue/create.ts similarity index 100% rename from src/commands/config/queue/create-queue.ts rename to src/commands/config/queue/create.ts From dd8d5547f97b780d0b715ee46ae2bb8f6323a0b8 Mon Sep 17 00:00:00 2001 From: niklhut <49069026+niklhut@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:48:47 +0100 Subject: [PATCH 05/12] Move set queue to config --- .../queue/set_waiting_room.ts} | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) rename src/commands/{setqueue.ts => config/queue/set_waiting_room.ts} (91%) diff --git a/src/commands/setqueue.ts b/src/commands/config/queue/set_waiting_room.ts similarity index 91% rename from src/commands/setqueue.ts rename to src/commands/config/queue/set_waiting_room.ts index 43e8b24..653d47c 100644 --- a/src/commands/setqueue.ts +++ b/src/commands/config/queue/set_waiting_room.ts @@ -1,14 +1,14 @@ -import { VoiceChannelModel } from "./../models/voice_channels"; +import { VoiceChannelModel } from "../../../models/voice_channels"; import { ApplicationCommandOptionType, GuildChannel, Message } from "discord.js"; -import { Command } from "../../typings"; -import { GuildModel } from "../models/guilds"; -import { VoiceChannel } from "../models/voice_channels"; +import { Command } from "../../../../typings"; +import { GuildModel } from "../../../models/guilds"; +import { VoiceChannel } from "../../../models/voice_channels"; import { mongoose } from "@typegoose/typegoose"; import { FilterOutFunctionKeys } from "@typegoose/typegoose/lib/types"; const command: Command = { - name: "setqueue", - description: "sets the given channel as join to create", + name: "set_waiting_room", + description: "Sets the given channel as join to create", aliases: ["setwaitingroom", "swr", "setwr", "setqueue", "sq"], usage: "[channel resolvable]", cooldown: 5, From 4c3c27adce6aca97fb4ad0b183d6c9911643c766 Mon Sep 17 00:00:00 2001 From: niklhut <49069026+niklhut@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:49:17 +0100 Subject: [PATCH 06/12] Adjust setup documentation --- Setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Setup.md b/Setup.md index c451245..6201719 100644 --- a/Setup.md +++ b/Setup.md @@ -17,7 +17,7 @@ 6. Create a new category, call it for example `Tutoring` and make it private but allow the `Tutor` role to see it. 7. Create one voice channel in the category, for example `tutoring-waiting` and allow the `Verified` role to see it. The `Tutor` role should be able to see it already because it is in the same category. 8. Call the command `/config queue create` and pass it the name for the queue and a description, for example `tutoring` and `the queue used to wait for tutoring`. This will create a new queue in the database. -9. Call the command `/setqueue` and pass it the name of the waiting channel, for example `tutoring-waiting` and the name of the queue, for example `tutoring` as well as the supervisor role, for example `Tutor`. This will set the waiting channel for the queue and the supervisor role. +9. Call the command `/config queue set_waiting_room` and pass it the name of the waiting channel, for example `tutoring-waiting` and the name of the queue, for example `tutoring` as well as the supervisor role, for example `Tutor`. This will set the waiting channel for the queue and the supervisor role. 10. Optionally rename the `coach` commands on the server to `tutor` by calling the command `/config commands rename` and passing it the old and new name of the command. ## Testing the Bot From a1042c0e72ce6394cbcbc77e9cc1eb1f318087e9 Mon Sep 17 00:00:00 2001 From: niklhut <49069026+niklhut@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:59:39 +0100 Subject: [PATCH 07/12] Move set join to create to config --- src/commands/{ => config}/setjointocreate.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename src/commands/{ => config}/setjointocreate.ts (96%) diff --git a/src/commands/setjointocreate.ts b/src/commands/config/setjointocreate.ts similarity index 96% rename from src/commands/setjointocreate.ts rename to src/commands/config/setjointocreate.ts index 83f06b2..345d908 100644 --- a/src/commands/setjointocreate.ts +++ b/src/commands/config/setjointocreate.ts @@ -1,7 +1,7 @@ import { ApplicationCommandOptionType, CategoryChannel, GuildChannel, Message, VoiceChannel as dvc } from "discord.js"; -import { Command } from "../../typings"; -import { GuildModel } from "../models/guilds"; -import { VoiceChannel } from "../models/voice_channels"; +import { Command } from "../../../typings"; +import { GuildModel } from "../../models/guilds"; +import { VoiceChannel } from "../../models/voice_channels"; import { FilterOutFunctionKeys } from "@typegoose/typegoose/lib/types"; import { mongoose } from "@typegoose/typegoose"; From ca6388d9a109ddff50bb9bffa4a8e96ff9549f6c Mon Sep 17 00:00:00 2001 From: Rdeisenroth Date: Mon, 4 Dec 2023 22:32:21 +0100 Subject: [PATCH 08/12] pass --fix to npm run lint script --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e1cae2f..e6f8067 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "start": "tsc --build --clean tsconfig.json; tsc --build tsconfig.json; node dist/index.js", "nodemon": "nodemon --watch 'src/**/*.ts' src/index.ts", "build": "tsc --build --clean tsconfig.json; tsc --build tsconfig.json", - "lint": "eslint --ext .ts src/", + "lint": "eslint --ext .ts src/ --fix", "watch": "tsc -p tsconfig.json -w", "test": "jest --detectOpenHandles" }, From c97f6c24bd4a778d30b13454114d4d1bd05aa2c8 Mon Sep 17 00:00:00 2001 From: Rdeisenroth Date: Mon, 4 Dec 2023 22:34:41 +0100 Subject: [PATCH 09/12] fix channel creation bug in /tutor queue next --- src/commands/coach/queue/next.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/coach/queue/next.ts b/src/commands/coach/queue/next.ts index 76b96cf..e24e274 100644 --- a/src/commands/coach/queue/next.ts +++ b/src/commands/coach/queue/next.ts @@ -69,7 +69,7 @@ const command: Command = { // Get Room Spawner let spawner: VoiceChannelSpawner | undefined = queueData.room_spawner?.toObject(); - const queue_channel_data = guildData.voice_channels.find(x => x.queue && x.queue == queue); + const queue_channel_data = guildData.voice_channels.find(x => x.queue && x.queue._id.equals(queue)); const queue_channel = g.channels.cache.get(queue_channel_data?._id ?? ""); const member = client.utils.general.getMember(interaction)!; if (!spawner) { From d8f2bd8c59681482131bd516483beaa4ea21d5a0 Mon Sep 17 00:00:00 2001 From: Rdeisenroth Date: Wed, 6 Dec 2023 21:17:08 +0100 Subject: [PATCH 10/12] fix #11 --- src/commands/coach/queue/next.ts | 2 +- src/commands/coach/queue/pick.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/coach/queue/next.ts b/src/commands/coach/queue/next.ts index e24e274..694c26d 100644 --- a/src/commands/coach/queue/next.ts +++ b/src/commands/coach/queue/next.ts @@ -106,7 +106,7 @@ const command: Command = { }, ); } else { - spawner.name = spawner.name ?? `${member.displayName}' ${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 => { diff --git a/src/commands/coach/queue/pick.ts b/src/commands/coach/queue/pick.ts index cc51955..fd48522 100644 --- a/src/commands/coach/queue/pick.ts +++ b/src/commands/coach/queue/pick.ts @@ -121,7 +121,7 @@ const command: Command = { }, ); } else { - spawner.name = spawner.name ?? `${member.displayName}' ${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([ { From e3ad0f7df81a29f6c891c40cbce14629723daa17 Mon Sep 17 00:00:00 2001 From: Rdeisenroth Date: Wed, 6 Dec 2023 22:09:26 +0100 Subject: [PATCH 11/12] lint --- src/commands/coach/session/quit.ts | 4 ++-- src/commands/coach/session/start.ts | 4 ++-- src/models/queues.ts | 28 ++++++++++++++-------------- src/utils/general.ts | 6 +++--- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/commands/coach/session/quit.ts b/src/commands/coach/session/quit.ts index 941db49..14b8813 100644 --- a/src/commands/coach/session/quit.ts +++ b/src/commands/coach/session/quit.ts @@ -3,7 +3,7 @@ import { Command } from "../../../../typings"; import { GuildModel } from "../../../models/guilds"; import { UserModel } from "../../../models/users"; import moment from "moment"; -import {removeRoleFromUser} from "../../../utils/general"; +import { removeRoleFromUser } from "../../../utils/general"; const command: Command = { name: "quit", @@ -34,7 +34,7 @@ const command: Command = { return await client.utils.embeds.SimpleEmbed(interaction, { title: "Coaching System", text: "You Have no Active Coaching Session.", empheral: true }); } - await removeRoleFromUser(g, user, 'active_session') + await removeRoleFromUser(g, user, "active_session"); //TODO: Terminate Rooms diff --git a/src/commands/coach/session/start.ts b/src/commands/coach/session/start.ts index 49aa152..5698c25 100644 --- a/src/commands/coach/session/start.ts +++ b/src/commands/coach/session/start.ts @@ -5,7 +5,7 @@ import { UserModel } from "../../../models/users"; import { SessionModel, sessionRole } from "../../../models/sessions"; import { Queue } from "../../../models/queues"; import { DocumentType } from "@typegoose/typegoose"; -import {assignRoleToUser} from "../../../utils/general"; +import { assignRoleToUser } from "../../../utils/general"; const command: Command = { name: "start", @@ -60,7 +60,7 @@ const command: Command = { userEntry.sessions.push(session._id); await userEntry.save(); - await assignRoleToUser(g, user, 'active_session') + await assignRoleToUser(g, user, "active_session"); client.utils.embeds.SimpleEmbed(interaction, { title: "Coaching System", text: "The Session was started.", empheral: true }); }, diff --git a/src/models/queues.ts b/src/models/queues.ts index 8c3fdfe..e6ac5eb 100644 --- a/src/models/queues.ts +++ b/src/models/queues.ts @@ -107,7 +107,7 @@ export class Queue { * Put an Entry into the Queue * @param entry The Queue Entry */ - public async join(this: DocumentType, entry: QueueEntry): Promise{ + public async join(this: DocumentType, entry: QueueEntry): Promise { if (this.entries.find(x => x.discord_id === entry.discord_id)) { throw new Error("Dublicate Entry"); } @@ -120,7 +120,7 @@ export class Queue { * Leaves the queue * @param discord_id The Discord ID of the entry */ - public async leave(this: DocumentType, discord_id: string): Promise{ + public async leave(this: DocumentType, discord_id: string): Promise { const entry = this.entries.find(x => x.discord_id === discord_id); if (!entry) { throw new Error("Not Found"); @@ -133,7 +133,7 @@ export class Queue { * Gets the Sorted Entries with the First ones being the ones with the highest Importance * @param limit How many entries should we get at most? */ - public getSortedEntries(this: DocumentType, limit?: number | undefined): DocumentType[]{ + public getSortedEntries(this: DocumentType, limit?: number | undefined): DocumentType[] { const entries = this.entries.sort((x, y) => { const x_importance = (Date.now() - (+x.joinedAt)) * (x.importance || 1); const y_importance = (Date.now() - (+y.joinedAt)) * (y.importance || 1); @@ -145,7 +145,7 @@ export class Queue { * Returns true if the ID is contained in the queue * @param discord_id the Discord ID to check if it's contained */ - public contains(this:DocumentType, discord_id: string): boolean { + public contains(this: DocumentType, discord_id: string): boolean { return this.entries.some(x => x.discord_id === discord_id); } /** @@ -159,7 +159,7 @@ export class Queue { * Gets the Position in the Current Queue * @param discord_id the Discord ID of the entry */ - public getPosition(this: DocumentType, discord_id: string): number{ + public getPosition(this: DocumentType, discord_id: string): number { return this.getSortedEntries().findIndex(x => x.discord_id === discord_id); } /** @@ -190,7 +190,7 @@ export class Queue { * @param string The String to Interpolate * @param entry_resolvable The Entry Resolvable */ - public interpolateQueueString(this: DocumentType, string:string, entry_resolvable?: string | QueueEntry | undefined): string | null{ + public interpolateQueueString(this: DocumentType, string: string, entry_resolvable?: string | QueueEntry | undefined): string | null { try { const replacements: StringReplacements = { "limit": this.limit, @@ -245,7 +245,7 @@ export class Queue { * Gets the leave Message of the Queue * @param entry_resolvable The Entry Resolvable */ - public getLeaveMessage(this: DocumentType, entry_resolvable?: string | QueueEntry | undefined): string{ + public getLeaveMessage(this: DocumentType, entry_resolvable?: string | QueueEntry | undefined): string { const default_leave_message = "You left the Queue."; if (this.leave_message) { const leave_msg = this.interpolateQueueString(this.leave_message!, entry_resolvable); @@ -273,7 +273,7 @@ export class Queue { * Gets the leave Room Message of the Queue * @param entry_resolvable The Entry Resolvable */ - public getLeaveRoomMessage(this: DocumentType, entry_resolvable?: string | QueueEntry | undefined): string{ + public getLeaveRoomMessage(this: DocumentType, entry_resolvable?: string | QueueEntry | undefined): string { const default_leave_message = `You left the Room. Please confirm your stay or you will be removed from the queue after the Timeout of ${(this.disconnect_timeout ?? 0) / 1000}s.`; if (this.leave_room_message) { const leave_msg = this.interpolateQueueString(this.leave_room_message, entry_resolvable); @@ -301,7 +301,7 @@ export class Queue { * Gets the leave Message of the Queue * @param entry_resolvable The Entry Resolvable */ - public getJoinMessage(this: DocumentType, entry_resolvable?: string | QueueEntry | undefined): string{ + public getJoinMessage(this: DocumentType, entry_resolvable?: string | QueueEntry | undefined): string { const default_join_message = "You left the Queue."; if (this.join_message) { const join_msg = this.interpolateQueueString(this.join_message, entry_resolvable); @@ -314,34 +314,34 @@ export class Queue { /** * Returns `true` if the Queue is Empty */ - public isEmpty(this: DocumentType): boolean{ + public isEmpty(this: DocumentType): boolean { return this.entries.length < 1; } /** * Locks the queue. This removes the voice Channel Permissions and disallows the queue from the /queue join command */ - public async lock(this: DocumentType): Promise{ + public async lock(this: DocumentType): Promise { this.locked = true; await this.$parent()?.save(); } /** * Unlocks the queue. This restores the voice Channel Permissions and allows the queue from the /queue join command */ - public async unlock(this: DocumentType): Promise{ + public async unlock(this: DocumentType): Promise { this.locked = false; await this.$parent()?.save(); } /** * Locks or Unlocks the queue (opposite State). */ - public async toggleLock(this: DocumentType): Promise{ + public async toggleLock(this: DocumentType): Promise { this.locked = !this.locked; await this.$parent()?.save(); } /** * Resolves all Waiting rooms for the current Queue */ - public getWaitingRooms(this: DocumentType, guild: Guild): DocumentType[]{ + public getWaitingRooms(this: DocumentType, guild: Guild): DocumentType[] { return guild.voice_channels?.filter(x => x.queue?._id.equals(this._id!)) ?? []; } } diff --git a/src/utils/general.ts b/src/utils/general.ts index 7b19ff6..190d89d 100644 --- a/src/utils/general.ts +++ b/src/utils/general.ts @@ -10,7 +10,7 @@ import ChannelType, { Message, RoleResolvable, User, - UserResolvable + UserResolvable, } from "discord.js"; import moment from "moment"; import { Command, StringReplacements } from "../../typings"; @@ -408,7 +408,7 @@ export async function assignRoleToUser(g: Guild, user: User, roleName: string) { if (role && member && !member.roles.cache.has(role.id)) { await member.roles.add(role); } else { - console.error(`Could not assign role: ${roleName} to ${user.username} on guild: ${g.name}`) + console.error(`Could not assign role: ${roleName} to ${user.username} on guild: ${g.name}`); } } @@ -425,6 +425,6 @@ export async function removeRoleFromUser(g: Guild, user: User, roleName: string) if (role && member && member.roles.cache.has(role.id)) { await member.roles.remove(role); } else { - console.error(`Could not remove role: ${roleName} from ${user.username} on guild: ${g.name}`) + console.error(`Could not remove role: ${roleName} from ${user.username} on guild: ${g.name}`); } } \ No newline at end of file From 63194d321684659b5571c9c3213ce1545498f2fe Mon Sep 17 00:00:00 2001 From: Rdeisenroth <53945743+Rdeisenroth@users.noreply.github.com> Date: Wed, 6 Dec 2023 22:16:12 +0100 Subject: [PATCH 12/12] Fix: Queue Channel could not be created (#44) * First attempt at #43 * lint --- src/commands/coach/queue/list.ts | 11 ++++++++--- src/commands/coach/queue/next.ts | 12 +++++++++--- src/commands/coach/queue/pick.ts | 2 ++ src/models/queues.ts | 24 +++++++++++++++++++++++- 4 files changed, 42 insertions(+), 7 deletions(-) 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, {