feat: allow anyone in a VC being recorded to make the bot leave

This commit is contained in:
2026-05-24 13:27:53 -04:00
parent b598adb498
commit 56ec8aaf8c

View File

@@ -39,6 +39,9 @@ pub enum GetGuildAndVoiceChannelIdError {
/// the bot is not in a voice chat in this guild /// the bot is not in a voice chat in this guild
BotNotInVC, BotNotInVC,
/// the user is not in a voice chat with the bot in this guild
UserNotInVCWithBot,
} }
#[tracing::instrument] #[tracing::instrument]
@@ -46,22 +49,32 @@ pub fn get_user_and_guild_and_voice_channel_id(
bot_user_id: Id<UserMarker>, bot_user_id: Id<UserMarker>,
interaction: &Interaction, interaction: &Interaction,
vcs: &VCs, vcs: &VCs,
) -> Result<(Id<UserMarker>, Id<GuildMarker>, Id<ChannelMarker>), GetGuildAndVoiceChannelIdError> { ) -> Result<(Id<GuildMarker>, Id<ChannelMarker>), GetGuildAndVoiceChannelIdError> {
let guild_id = interaction.guild_id.context(NotInGuildSnafu)?;
let user_id = interaction let user_id = interaction
.member .member
.as_ref() .as_ref()
.and_then(|member| member.user.as_ref().map(|user| user.id)) .and_then(|member| member.user.as_ref().map(|user| user.id))
.context(NoUserSnafu)?; .context(NoUserSnafu)?;
let guild_id = interaction.guild_id.context(NotInGuildSnafu)?; let &bot_voice_channel_id = vcs
let &voice_channel_id = vcs
.get(&guild_id) .get(&guild_id)
.context(BotNotInVCSnafu)? .context(BotNotInVCSnafu)?
.get_left_for(&bot_user_id) .get_left_for(&bot_user_id)
.context(BotNotInVCSnafu)?; .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 { 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 => { 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() 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] #[tracing::instrument]
pub async fn handle(state: State, interaction: Interaction) { 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( get_user_and_guild_and_voice_channel_id(
state.discord_user_id, state.discord_user_id,
&interaction, &interaction,
&state.vcs_sender.borrow(), &state.vcs_sender.borrow(),
) )
}; };
let (user_id, guild_id, voice_channel_id) = match user_and_guild_and_voice_channel_id_res { let (guild_id, voice_channel_id) = match guild_and_voice_channel_id_result {
Ok((user_id, guild_id, voice_channel_id)) => (user_id, guild_id, voice_channel_id), Ok((guild_id, voice_channel_id)) => (guild_id, voice_channel_id),
Err(error) => { Err(error) => {
state state
.discord_client .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"); state.songbird.leave(guild_id).await.expect("TODO");
tracing::error!("TODO: successfully left the call"); tracing::error!("TODO: successfully left the call");
@@ -154,13 +145,13 @@ pub async fn handle(state: State, interaction: Interaction) {
InteractionResponseDataBuilder::new() InteractionResponseDataBuilder::new()
.embeds([ .embeds([
EmbedBuilder::new() EmbedBuilder::new()
.title("Left VC") .title("Left VC")
.description(format!( .description(format!(
"This bot left {channel_mention} (and is thereby unable to record anymore)." "This bot left {channel_mention} (and is thereby unable to record anymore)."
)) ))
.validate() .validate()
.unwrap() .unwrap()
.build() .build()
]) ])
.flags(MessageFlags::EPHEMERAL) .flags(MessageFlags::EPHEMERAL)
.build(), .build(),