Skip to content

fix: remove audio channel when last member leaves #79

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 5 commits into from
Sep 13, 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 @@ -22,7 +22,7 @@ interface Cache<Entries extends Record<string, any>> {

interface CacheEntries {
lobbyIds: string[];
channels: string[];
onDemandChannels: string[];
quoiFeurChannels: string[];
recurringMessages: { id: string; channelId: string; frequency: Frequency; message: string }[];
}
Expand Down
16 changes: 8 additions & 8 deletions src/modules/voiceOnDemand/voiceOnDemand.helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ type CheckedVoiceState = SetNonNullable<VoiceState, 'channel' | 'channelId' | 'm
export const isJoinState = (newState: VoiceState): newState is CheckedVoiceState =>
newState.channel !== null && newState.channelId !== null && newState.member !== null;

export const isLeaveState = (oldDate: VoiceState): oldDate is CheckedVoiceState =>
oldDate.channel !== null && oldDate.channelId !== null && oldDate.member !== null;
export const isLeaveState = (oldState: VoiceState): oldState is CheckedVoiceState =>
oldState.channel !== null && oldState.channelId !== null && oldState.member !== null;

export const handleJoin = async (state: CheckedVoiceState): Promise<void> => {
export const handleJoinLobby = async (state: CheckedVoiceState): Promise<void> => {
const channel = await createUserVoiceChannel(state.channel.parent, state.member);
await state.member.voice.setChannel(channel);
};

export const handleLeave = async (state: CheckedVoiceState): Promise<void> => {
const channels = await cache.get('channels', []);
export const handleLeaveOnDemand = async (state: CheckedVoiceState): Promise<void> => {
const channels = await cache.get('onDemandChannels', []);

const { channel } = state;
const { id, members, guild } = channel;
Expand All @@ -34,7 +34,7 @@ export const handleLeave = async (state: CheckedVoiceState): Promise<void> => {
guild.channels.cache.delete(id);

const filtered = channels.filter((channelId) => channelId !== id);
await cache.set('channels', filtered);
await cache.set('onDemandChannels', filtered);
}
};

Expand All @@ -56,9 +56,9 @@ export const createUserVoiceChannel = async (

const channel = await guild.channels.create(parent === null ? options : { ...options, parent });

const channels = await cache.get('channels', []);
const channels = await cache.get('onDemandChannels', []);

await cache.set('channels', [...channels, channel.id]);
await cache.set('onDemandChannels', [...channels, channel.id]);

return channel.id;
};
45 changes: 28 additions & 17 deletions src/modules/voiceOnDemand/voiceOnDemand.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import { ChannelType, Guild, SlashCommandBuilder } from 'discord.js';

import { cache } from '../../core/cache';
import type { BotModule } from '../../types/bot';
import { handleJoin, handleLeave, isJoinState, isLeaveState } from './voiceOnDemand.helpers';
import {
handleJoinLobby,
handleLeaveOnDemand,
isJoinState,
isLeaveState,
} from './voiceOnDemand.helpers';

export const voiceOnDemand: BotModule = {
slashCommands: [
Expand Down Expand Up @@ -56,18 +61,21 @@ export const voiceOnDemand: BotModule = {
eventHandlers: {
voiceStateUpdate: async (oldState, newState) => {
const lobbyIds = await cache.get('lobbyIds', []);
const lobbyId = lobbyIds.find((lobbyId) => newState.channelId === lobbyId);
const onDemandChannels = await cache.get('onDemandChannels', []);

if (lobbyId === undefined) {
const isLobbyChannel = lobbyIds.includes(newState.channelId ?? '');
const isOnDemandChannel = onDemandChannels.includes(newState.channelId ?? '');

if (!isOnDemandChannel && !isLobbyChannel) {
return;
}

if (isLeaveState(oldState)) {
await handleLeave(oldState);
if (isOnDemandChannel && isLeaveState(oldState)) {
await handleLeaveOnDemand(oldState);
}

if (isJoinState(newState)) {
await handleJoin(newState);
if (isLobbyChannel && isJoinState(newState)) {
await handleJoinLobby(newState);
}
},
channelDelete: async (channel) => {
Expand All @@ -76,23 +84,26 @@ export const voiceOnDemand: BotModule = {
}

const lobbyIds = await cache.get('lobbyIds', []);
const { guild, id } = channel;
const onDemandChannels = await cache.get('onDemandChannels', []);

if (lobbyIds.includes(id)) return;
const isLobbyChannel = lobbyIds.includes(channel.id);
const isOnDemandChannel = onDemandChannels.includes(channel.id);

if (!isOnDemandChannel && !isLobbyChannel) {
return;
}

await cache.set(
'lobbyIds',
lobbyIds.filter((lobbyId) => lobbyId !== id),
lobbyIds.filter((lobbyId) => lobbyId !== channel.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);
onDemandChannels.map(async (id) => {
const updatedChannel = await channel.guild.channels.fetch(id).catch(() => null);
if (updatedChannel !== null) {
await channel.guild.channels.delete(id);
channel.guild.channels.cache.delete(id);
}
}),
);
Expand Down