-
-
Notifications
You must be signed in to change notification settings - Fork 192
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Some refactor of defaultVoiceStateHandler
- Loading branch information
1 parent
ee9ccfe
commit 2b8e24c
Showing
1 changed file
with
69 additions
and
83 deletions.
There are no files selected for viewing
152 changes: 69 additions & 83 deletions
152
packages/discord-player/src/DefaultVoiceStateHandler.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}`); | ||
} | ||
} |