fix: bot stuck when forcefully disconnected without using command

This commit is contained in:
Ladislav Hano 2025-02-02 00:22:09 +01:00
parent f7d926bf2d
commit 44d798d1d2

View file

@ -31,59 +31,80 @@ async fn get_channel_info(ctx: &Context, voice_state: &VoiceState) -> Option<Gui
Some(voice_channel)
}
pub async fn handle_autodisconnect(ctx: Context, voice_state_old: VoiceState, voice_state: VoiceState) -> Option<()> {
// Logic is as follows:
// User connected -> voice_state_old is None (we handle this before this function)
// Bot was moved to different vc -> we check if the new voice_state has the bot's user id
// User moved to different VC or disconnected -> we check old channel instead (the bot could be still there)
let mut voice_channel: GuildChannel;
if voice_state.user_id == ctx.cache.current_user().id {
voice_channel = get_channel_info(&ctx, &voice_state).await?;
}
// Someone disconnected or moved channels
else {
voice_channel = get_channel_info(&ctx, &voice_state_old).await?;
}
let manager = songbird::get(&ctx)
.await
.expect("Songbird Voice client placed in at initialisation.")
.clone();
// bot is not connected to any channel via songbird, don't need to do anything
if manager.get(voice_channel.guild_id).is_none() {
return None;
}
// There is a problem with this implementation
// if bot is left alone and users joins and disconnects while this counts down
// this is not a big problem since we want to disconnect anyway
sleep(Duration::from_secs(120)).await;
if voice_state.user_id == ctx.cache.current_user().id {
voice_channel = get_channel_info(&ctx, &voice_state).await?;
}
else {
voice_channel = get_channel_info(&ctx, &voice_state_old).await?;
}
// bot is not connected to any channel via songbird, don't need to do anything
// ? could have been removed while sleeping if the song stopped playing
if manager.get(voice_channel.guild_id).is_none() {
return None;
}
match manager.remove(voice_channel.guild_id).await {
Ok(()) => {
let _ = voice_channel.send_message(ctx.http,
CreateMessage::new()
.content("Disconnected to save bandwidth")
).await;
}
Err(e) => {
let _ = send_error(ctx.http, e.to_string()).await;
}
}
None
}
pub async fn handle_voice_update(ctx: Context, voice_state_old: VoiceState, voice_state: VoiceState) -> Option<()> {
// Logic is as follows:
// User connected -> voice_state_old is None (we handle this before this function)
// Bot was moved to different vc -> we check if the new voice_state has the bot's user id
// User moved to different VC or disconnected -> we check old channel instead (the bot could be still there)
let mut voice_channel: GuildChannel;
if voice_state.user_id == ctx.cache.current_user().id {
voice_channel = get_channel_info(&ctx, &voice_state).await?;
}
// Someone disconnected or moved channels
else {
voice_channel = get_channel_info(&ctx, &voice_state_old).await?;
}
let manager = songbird::get(&ctx)
.await
.expect("Songbird Voice client placed in at initialisation.")
.clone();
// bot is not connected to any channel via songbird, don't need to do anything
if manager.get(voice_channel.guild_id).is_none() {
return None;
}
// There is a problem with this implementation
// if bot is left alone and users joins and disconnects while this counts down
// this is not a big problem since we want to disconnect anyway
sleep(Duration::from_secs(120)).await;
if voice_state.user_id == ctx.cache.current_user().id {
voice_channel = get_channel_info(&ctx, &voice_state).await?;
}
else {
voice_channel = get_channel_info(&ctx, &voice_state_old).await?;
}
// bot is not connected to any channel via songbird, don't need to do anything
// ? could have been removed while sleeping if the song stopped playing
if manager.get(voice_channel.guild_id).is_none() {
return None;
}
match manager.remove(voice_channel.guild_id).await {
Ok(()) => {
let _ = voice_channel.send_message(ctx.http,
CreateMessage::new()
.content("Disconnected to save bandwidth")
).await;
}
Err(e) => {
let _ = send_error(ctx.http, e.to_string()).await;
// if the user was disconnected remove Songbird manager so it won't get stuck
// Actually this is not really a bug since we can handle disconnect and therefore saving the song queue for example
if voice_state.channel_id.is_none() && voice_state.user_id == ctx.cache.current_user().id {
let manager = songbird::get(&ctx)
.await
.expect("Songbird Voice client placed in at initialisation.")
.clone();
let guild_id = voice_state_old.guild_id?;
// bot is not connected to any channel via songbird, don't need to do anything
if manager.get(guild_id).is_some() {
let _ = manager.remove(guild_id).await;
return None;
}
}
handle_autodisconnect(ctx, voice_state_old, voice_state).await?;
None
}