Skip to content

fix: voice lobby now handles multiple guilds #77

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/core/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ interface Cache<Entries extends Record<string, any>> {
}

interface CacheEntries {
lobbyId: string;
lobbyIds: string[];
channels: string[];
quoiFeurChannels: string[];
recurringMessages: { id: string; channelId: string; frequency: Frequency; message: string }[];
Expand Down
6 changes: 1 addition & 5 deletions src/modules/voiceOnDemand/voiceOnDemand.helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<void> => {
if (state.channelId !== lobbyId) {
return;
}

export const handleJoin = async (state: CheckedVoiceState): Promise<void> => {
const channel = await createUserVoiceChannel(state.channel.parent, state.member);
await state.member.voice.setChannel(channel);
};
Expand Down
65 changes: 35 additions & 30 deletions src/modules/voiceOnDemand/voiceOnDemand.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,24 @@ export const voiceOnDemand: BotModule = {
.toJSON(),
handler: {
create: async (interaction): Promise<void> => {
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;
}

Expand All @@ -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.',
Expand All @@ -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;
}
Expand All @@ -63,34 +67,35 @@ export const voiceOnDemand: BotModule = {
}

if (isJoinState(newState)) {
await handleJoin(newState, lobbyId);
await handleJoin(newState);
}
},
channelDelete: async (channel) => {
if (channel.type !== ChannelType.GuildVoice) {
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'],
Expand Down