From 23e7c98b867ee29e5657fed632643140bdb58459 Mon Sep 17 00:00:00 2001 From: Manu Date: Wed, 13 Sep 2023 00:06:07 +0200 Subject: [PATCH] fix: voice lobby now handles multiple guilds (#77) --- src/core/cache.ts | 2 +- .../voiceOnDemand/voiceOnDemand.helpers.ts | 6 +- .../voiceOnDemand/voiceOnDemand.module.ts | 65 ++++++++++--------- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/core/cache.ts b/src/core/cache.ts index 7bf69ab9..b26c97ab 100644 --- a/src/core/cache.ts +++ b/src/core/cache.ts @@ -21,7 +21,7 @@ interface Cache> { } interface CacheEntries { - lobbyId: string; + lobbyIds: string[]; channels: string[]; quoiFeurChannels: string[]; recurringMessages: { id: string; channelId: string; frequency: Frequency; message: string }[]; diff --git a/src/modules/voiceOnDemand/voiceOnDemand.helpers.ts b/src/modules/voiceOnDemand/voiceOnDemand.helpers.ts index 45001523..ad0a7efe 100644 --- a/src/modules/voiceOnDemand/voiceOnDemand.helpers.ts +++ b/src/modules/voiceOnDemand/voiceOnDemand.helpers.ts @@ -18,11 +18,7 @@ export const isJoinState = (newState: VoiceState): newState is CheckedVoiceState export const isLeaveState = (oldDate: VoiceState): oldDate is CheckedVoiceState => oldDate.channel !== null && oldDate.channelId !== null && oldDate.member !== null; -export const handleJoin = async (state: CheckedVoiceState, lobbyId: string): Promise => { - if (state.channelId !== lobbyId) { - return; - } - +export const handleJoin = async (state: CheckedVoiceState): Promise => { const channel = await createUserVoiceChannel(state.channel.parent, state.member); await state.member.voice.setChannel(channel); }; diff --git a/src/modules/voiceOnDemand/voiceOnDemand.module.ts b/src/modules/voiceOnDemand/voiceOnDemand.module.ts index df5d4e46..6d490f54 100644 --- a/src/modules/voiceOnDemand/voiceOnDemand.module.ts +++ b/src/modules/voiceOnDemand/voiceOnDemand.module.ts @@ -16,23 +16,24 @@ export const voiceOnDemand: BotModule = { .toJSON(), handler: { create: async (interaction): Promise => { - const guild = interaction.guild as Guild; + const { guild } = interaction; - const lobbyId = await cache.get('lobbyId'); + if (!(guild instanceof Guild)) { + await interaction.reply({ + content: 'This command is only available in guilds', + ephemeral: true, + }); - if (lobbyId !== undefined && guild.channels.cache.has(lobbyId)) { - guild.channels.cache.delete(lobbyId); + return; } + const lobbyIds = await cache.get('lobbyIds', []); + const lobbyId = lobbyIds.find((lobbyId) => guild.channels.cache.has(lobbyId)); - const channel = - lobbyId === undefined ? null : await guild.channels.fetch(lobbyId).catch(() => null); - - if (channel !== null) { + if (lobbyId !== undefined) { await interaction.reply({ content: 'Voice on demand voice lobby already exists.', ephemeral: true, }); - return; } @@ -41,7 +42,8 @@ export const voiceOnDemand: BotModule = { type: ChannelType.GuildVoice, }); - await cache.set('lobbyId', id); + //NOTES: this is a potential race condition. + await cache.set('lobbyIds', [...lobbyIds, id]); await interaction.reply({ content: 'Created voice on demand voice channel.', @@ -53,7 +55,9 @@ export const voiceOnDemand: BotModule = { ], eventHandlers: { voiceStateUpdate: async (oldState, newState) => { - const lobbyId = await cache.get('lobbyId'); + const lobbyIds = await cache.get('lobbyIds', []); + const lobbyId = lobbyIds.find((lobbyId) => newState.channelId === lobbyId); + if (lobbyId === undefined) { return; } @@ -63,7 +67,7 @@ export const voiceOnDemand: BotModule = { } if (isJoinState(newState)) { - await handleJoin(newState, lobbyId); + await handleJoin(newState); } }, channelDelete: async (channel) => { @@ -71,26 +75,27 @@ export const voiceOnDemand: BotModule = { return; } - const lobbyId = await cache.get('lobbyId'); - + const lobbyIds = await cache.get('lobbyIds', []); const { guild, id } = channel; - if (id === lobbyId) { - await cache.delete('lobbyId'); - guild.channels.cache.delete(lobbyId); - - const channels = await cache.get('channels', []); - - await Promise.all( - channels.map(async (id) => { - const channel = await guild.channels.fetch(id).catch(() => null); - if (channel !== null) { - await guild.channels.delete(id); - guild.channels.cache.delete(id); - } - }), - ); - } + if (lobbyIds.includes(id)) return; + + await cache.set( + 'lobbyIds', + lobbyIds.filter((lobbyId) => lobbyId !== id), + ); + + const channels = await cache.get('channels', []); + + await Promise.all( + channels.map(async (id) => { + const channel = await guild.channels.fetch(id).catch(() => null); + if (channel !== null) { + await guild.channels.delete(id); + guild.channels.cache.delete(id); + } + }), + ); }, }, intents: ['GuildVoiceStates', 'GuildMembers'],