Skip to content

Commit

Permalink
Some refactor of defaultVoiceStateHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
mariusbegby committed Aug 13, 2024
1 parent ee9ccfe commit 2b8e24c
Showing 1 changed file with 69 additions and 83 deletions.
152 changes: 69 additions & 83 deletions packages/discord-player/src/DefaultVoiceStateHandler.ts
Original file line number Diff line number Diff line change
@@ -1,119 +1,105 @@
import { GuildQueue, GuildQueueEvent } from './queue';
import { ChannelType, GatewayVoiceState } from 'discord-api-types/v10';
import { Channel } from './clientadapter/IClientAdapter';
import { Player } from './Player';
import { GuildQueue, GuildQueueEvent } from './queue';
import { Util } from './utils/Util';
import { GatewayVoiceState } from 'discord-api-types/v9';
import { VoiceBasedChannel } from './clientadapter/IClientAdapter';
import { ChannelType } from 'discord-api-types/v10';

export async function defaultVoiceStateHandler(player: Player, queue: GuildQueue, oldState: GatewayVoiceState, newState: GatewayVoiceState) {
if (!queue || !queue.connection || !queue.channel) return;

const clientUserId = player.clientAdapter.getClientUserId();

handleDisconnection(clientUserId, oldState, newState, queue, player);
handlePauseOnEmptyState(queue);
handleVoiceChannelUpdates(player, clientUserId, oldState, newState, queue);
handleChannelPopulationAndDeletion(oldState, newState, queue, player);
}

function handleDisconnection(clientUserId: string, oldState: GatewayVoiceState, newState: GatewayVoiceState, queue: GuildQueue, player: Player) {
if (oldState.channel_id && !newState.channel_id && newState.member?.user?.id === clientUserId) {
try {
queue.delete();
} catch {
Util.noop();
}
return void player.events.emit(GuildQueueEvent.disconnect, queue);
player.events.emit(GuildQueueEvent.disconnect, queue);
}
}

function handlePauseOnEmptyState(queue: GuildQueue) {
if (queue.options.pauseOnEmpty) {
const isEmpty = Util.isVoiceEmpty(queue.channel);
const isEmpty = Util.isVoiceEmpty(queue.channel!);
const isPausedOnEmpty = Reflect.get(queue, '__pausedOnEmpty');

if (isEmpty) {
queue.node.setPaused(true);
Reflect.set(queue, '__pausedOnEmpty', true);
if (queue.hasDebugger) {
queue.debug('Voice channel is empty and options#pauseOnEmpty is true, pausing...');
}
} else {
if (Reflect.get(queue, '__pausedOnEmpty')) {
queue.node.setPaused(false);
Reflect.set(queue, '__pausedOnEmpty', false);
if (queue.hasDebugger) {
queue.debug('Voice channel is not empty and options#pauseOnEmpty is true, resuming...');
}
}
debugLog(queue, 'pausing');
} else if (isPausedOnEmpty) {
queue.node.setPaused(false);
Reflect.set(queue, '__pausedOnEmpty', false);
debugLog(queue, 'resuming');
}
}
}

function handleVoiceChannelUpdates(player: Player, clientUserId: string, oldState: GatewayVoiceState, newState: GatewayVoiceState, queue: GuildQueue) {
const newStateChannel = player.clientAdapter.getChannel(newState.channel_id!);
if (!newStateChannel) return;

if (!oldState.channel_id && newState.channel_id && newState.member?.user?.id === clientUserId) {
if (newState.mute != null && oldState.mute !== newState.mute) {
queue.node.setPaused(newState.mute);
} else if (newStateChannel?.type === ChannelType.GuildStageVoice && newState.suppress != null && oldState.suppress !== newState.suppress) {
queue.node.setPaused(newState.suppress);
if (newState.suppress) {
newStateChannel.clientUser.requestToSpeak().catch(Util.noop);
}
handleMuteAndSuppressChanges(oldState, newState, queue, newStateChannel);
}
}

function handleMuteAndSuppressChanges(oldState: GatewayVoiceState, newState: GatewayVoiceState, queue: GuildQueue, newStateChannel: Channel) {
if (newState.mute != null && oldState.mute !== newState.mute) {
queue.node.setPaused(newState.mute);
} else if (newStateChannel?.type === ChannelType.GuildStageVoice && newState.suppress != null && oldState.suppress !== newState.suppress) {
queue.node.setPaused(newState.suppress);
if (newState.suppress) {
newStateChannel.clientUser.requestToSpeak().catch(Util.noop);
}
}
}

if (!newState.channel_id && oldState.channel_id === queue.channel.id) {
if (!Util.isVoiceEmpty(queue.channel)) return;
const timeout = setTimeout(() => {
if (!Util.isVoiceEmpty(queue.channel!)) return;
if (!player.nodes.has(queue.guild.id)) return;
if (queue.options.leaveOnEmpty) queue.delete();
player.events.emit(GuildQueueEvent.emptyChannel, queue);
}, queue.options.leaveOnEmptyCooldown || 0).unref();
queue.timeouts.set(`empty_${oldState.guild_id}`, timeout);
function handleChannelPopulationAndDeletion(oldState: GatewayVoiceState, newState: GatewayVoiceState, queue: GuildQueue, player: Player) {
manageTimeoutsOnChannelChange(oldState, newState, queue, player);
}

function manageTimeoutsOnChannelChange(oldState: GatewayVoiceState, newState: GatewayVoiceState, queue: GuildQueue, player: Player) {
const channelEmpty = Util.isVoiceEmpty(queue.channel!);

if (!newState.channel_id && oldState.channel_id === queue.channel!.id && channelEmpty) {
setEmptyTimeout(queue, oldState, player);
} else if (newState.channel_id && newState.channel_id === queue.channel!.id) {
clearEmptyTimeout(queue, oldState, player);
}
}

if (newState.channel_id && newState.channel_id === queue.channel.id) {
const emptyTimeout = queue.timeouts.get(`empty_${oldState.guild_id}`);
const channelEmpty = Util.isVoiceEmpty(queue.channel);
if (!channelEmpty && emptyTimeout) {
clearTimeout(emptyTimeout);
queue.timeouts.delete(`empty_${oldState.guild_id}`);
player.events.emit(GuildQueueEvent.channelPopulate, queue);
function setEmptyTimeout(queue: GuildQueue, oldState: GatewayVoiceState, player: Player) {
const timeout = setTimeout(() => {
if (Util.isVoiceEmpty(queue.channel!) && player.nodes.has(queue.guild.id) && queue.options.leaveOnEmpty) {
queue.delete();
player.events.emit(GuildQueueEvent.emptyChannel, queue);
}
}, queue.options.leaveOnEmptyCooldown || 0).unref();
const timeoutKey = `empty_${oldState.guild_id}`;
queue.timeouts.set(timeoutKey, timeout);
}

function clearEmptyTimeout(queue: GuildQueue, oldState: GatewayVoiceState, player: Player) {
const timeoutKey = `empty_${oldState.guild_id}`;
const emptyTimeout = queue.timeouts.get(timeoutKey);
if (emptyTimeout) {
clearTimeout(emptyTimeout);
queue.timeouts.delete(timeoutKey);
player.events.emit(GuildQueueEvent.channelPopulate, queue);
}
}

if (oldState.channel_id && newState.channel_id && oldState.channel_id !== newState.channel_id) {
if (newState.member?.user?.id === clientUserId) {
if (queue.connection && newState.member?.user?.id === clientUserId) {
const newQueueChannel = player.clientAdapter.getChannel(newState.channel_id);
queue.channel! = newQueueChannel as VoiceBasedChannel;
}
const emptyTimeout = queue.timeouts.get(`empty_${oldState.guild_id}`);
const channelEmpty = Util.isVoiceEmpty(queue.channel!);
if (!channelEmpty && emptyTimeout) {
clearTimeout(emptyTimeout);
queue.timeouts.delete(`empty_${oldState.guild_id}`);
player.events.emit(GuildQueueEvent.channelPopulate, queue);
} else {
const timeout = setTimeout(() => {
if (queue.connection && !Util.isVoiceEmpty(queue.channel!)) return;
if (!player.nodes.has(queue.guild.id)) return;
if (queue.options.leaveOnEmpty) queue.delete();
player.events.emit(GuildQueueEvent.emptyChannel, queue);
}, queue.options.leaveOnEmptyCooldown || 0).unref();
queue.timeouts.set(`empty_${oldState.guild_id}`, timeout);
}
} else {
if (newState.channel_id !== queue.channel.id) {
const channelEmpty = Util.isVoiceEmpty(queue.channel!);
if (!channelEmpty) return;
if (queue.timeouts.has(`empty_${oldState.guild_id}`)) return;
const timeout = setTimeout(() => {
if (!Util.isVoiceEmpty(queue.channel!)) return;
if (!player.nodes.has(queue.guild.id)) return;
if (queue.options.leaveOnEmpty) queue.delete();
player.events.emit(GuildQueueEvent.emptyChannel, queue);
}, queue.options.leaveOnEmptyCooldown || 0).unref();
queue.timeouts.set(`empty_${oldState.guild_id}`, timeout);
} else {
const emptyTimeout = queue.timeouts.get(`empty_${oldState.guild_id}`);
const channelEmpty = Util.isVoiceEmpty(queue.channel!);
if (!channelEmpty && emptyTimeout) {
clearTimeout(emptyTimeout);
queue.timeouts.delete(`empty_${oldState.guild_id}`);
player.events.emit(GuildQueueEvent.channelPopulate, queue);
}
}
}
function debugLog(queue: GuildQueue, message: string) {
if (queue.hasDebugger) {
queue.debug(`Voice channel state change: ${message}`);
}
}

0 comments on commit 2b8e24c

Please sign in to comment.