diff --git a/src/command/leave.rs b/src/command/leave.rs index c6991b1..791b0e6 100644 --- a/src/command/leave.rs +++ b/src/command/leave.rs @@ -39,6 +39,9 @@ pub enum GetGuildAndVoiceChannelIdError { /// the bot is not in a voice chat in this guild BotNotInVC, + + /// the user is not in a voice chat with the bot in this guild + UserNotInVCWithBot, } #[tracing::instrument] @@ -46,22 +49,32 @@ pub fn get_user_and_guild_and_voice_channel_id( bot_user_id: Id, interaction: &Interaction, vcs: &VCs, -) -> Result<(Id, Id, Id), GetGuildAndVoiceChannelIdError> { +) -> Result<(Id, Id), GetGuildAndVoiceChannelIdError> { + let guild_id = interaction.guild_id.context(NotInGuildSnafu)?; + let user_id = interaction .member .as_ref() .and_then(|member| member.user.as_ref().map(|user| user.id)) .context(NoUserSnafu)?; - let guild_id = interaction.guild_id.context(NotInGuildSnafu)?; - - let &voice_channel_id = vcs + let &bot_voice_channel_id = vcs .get(&guild_id) .context(BotNotInVCSnafu)? .get_left_for(&bot_user_id) .context(BotNotInVCSnafu)?; - Ok((user_id, guild_id, voice_channel_id)) + let &user_voice_channel_id = vcs + .get(&guild_id) + .context(UserNotInVCWithBotSnafu)? + .get_left_for(&user_id) + .context(UserNotInVCWithBotSnafu)?; + + if user_voice_channel_id != bot_voice_channel_id { + return Err(GetGuildAndVoiceChannelIdError::UserNotInVCWithBot); + } + + Ok((guild_id, bot_voice_channel_id)) } fn get_guild_and_vc_error_to_embed(error: GetGuildAndVoiceChannelIdError) -> Embed { @@ -75,20 +88,23 @@ fn get_guild_and_vc_error_to_embed(error: GetGuildAndVoiceChannelIdError) -> Emb GetGuildAndVoiceChannelIdError::BotNotInVC => { EmbedBuilder::new().title("Not in a VC").description("This bot can't leave VC if it isn't in one in this server.").validate().unwrap().build() }, + GetGuildAndVoiceChannelIdError::UserNotInVCWithBot => { + EmbedBuilder::new().title("Not in a VC with the Bot").description("You have to be in the VC with the bot to make it leave (to prevent griefing and abuse).").validate().unwrap().build() + }, } } #[tracing::instrument] pub async fn handle(state: State, interaction: Interaction) { - let user_and_guild_and_voice_channel_id_res = { + let guild_and_voice_channel_id_result = { get_user_and_guild_and_voice_channel_id( state.discord_user_id, &interaction, &state.vcs_sender.borrow(), ) }; - let (user_id, guild_id, voice_channel_id) = match user_and_guild_and_voice_channel_id_res { - Ok((user_id, guild_id, voice_channel_id)) => (user_id, guild_id, voice_channel_id), + let (guild_id, voice_channel_id) = match guild_and_voice_channel_id_result { + Ok((guild_id, voice_channel_id)) => (guild_id, voice_channel_id), Err(error) => { state .discord_client @@ -113,31 +129,6 @@ pub async fn handle(state: State, interaction: Interaction) { } }; - if user_id != state.discord_bot_owner_user_id { - state - .discord_client - .interaction(state.discord_application_id) - .create_response( - interaction.id, - &interaction.token, - &InteractionResponse { - kind: InteractionResponseType::ChannelMessageWithSource, - data: Some( - InteractionResponseDataBuilder::new() - .embeds([ - EmbedBuilder::new().title("No permission to make this bot leave").description("Only the owner of this bot is allowed to make the bot leave RIGHT NOW. You might be looking for the opt out command.").validate().unwrap().build() - ]) - .flags(MessageFlags::EPHEMERAL) - .build(), - ), - }, - ) - .await - .expect("TODO"); - - return; - } - state.songbird.leave(guild_id).await.expect("TODO"); tracing::error!("TODO: successfully left the call"); @@ -154,13 +145,13 @@ pub async fn handle(state: State, interaction: Interaction) { InteractionResponseDataBuilder::new() .embeds([ EmbedBuilder::new() - .title("Left VC") - .description(format!( - "This bot left {channel_mention} (and is thereby unable to record anymore)." - )) - .validate() - .unwrap() - .build() + .title("Left VC") + .description(format!( + "This bot left {channel_mention} (and is thereby unable to record anymore)." + )) + .validate() + .unwrap() + .build() ]) .flags(MessageFlags::EPHEMERAL) .build(),