feat: check if the leave command was invoked by the bot owner before leaving
This commit is contained in:
@@ -66,7 +66,7 @@ fn get_guild_and_vc_error_to_embed(error: GetGuildAndVoiceChannelIdError) -> Emb
|
|||||||
match error {
|
match error {
|
||||||
GetGuildAndVoiceChannelIdError::NotInGuild => {
|
GetGuildAndVoiceChannelIdError::NotInGuild => {
|
||||||
EmbedBuilder::new().title("Use this in a server").description("This bot can't find a VC to join if the command is used outside of a server (you might've used it in a DM?).").validate().unwrap().build()
|
EmbedBuilder::new().title("Use this in a server").description("This bot can't find a VC to join if the command is used outside of a server (you might've used it in a DM?).").validate().unwrap().build()
|
||||||
}
|
},
|
||||||
GetGuildAndVoiceChannelIdError::NoUser => {
|
GetGuildAndVoiceChannelIdError::NoUser => {
|
||||||
EmbedBuilder::new().title("Not invoked by a user").description("This command works by joining the same VC as the user, but this bot didn't receive any user data. So did no user invoke it?! (This error should be impossible!)").validate().unwrap().build()
|
EmbedBuilder::new().title("Not invoked by a user").description("This command works by joining the same VC as the user, but this bot didn't receive any user data. So did no user invoke it?! (This error should be impossible!)").validate().unwrap().build()
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ pub enum GetGuildAndVoiceChannelIdError {
|
|||||||
/// this command was not used inside a guild (Discord server)
|
/// this command was not used inside a guild (Discord server)
|
||||||
NotInGuild,
|
NotInGuild,
|
||||||
|
|
||||||
|
/// there is no user who invoked this command
|
||||||
|
NoUser,
|
||||||
|
|
||||||
/// there are no voice chats in this guild
|
/// there are no voice chats in this guild
|
||||||
NoVCsInGuild,
|
NoVCsInGuild,
|
||||||
|
|
||||||
@@ -42,11 +45,17 @@ pub enum GetGuildAndVoiceChannelIdError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
pub fn get_guild_and_voice_channel_id(
|
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<GuildMarker>, Id<ChannelMarker>), GetGuildAndVoiceChannelIdError> {
|
) -> Result<(Id<UserMarker>, Id<GuildMarker>, Id<ChannelMarker>), GetGuildAndVoiceChannelIdError> {
|
||||||
|
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 guild_id = interaction.guild_id.context(NotInGuildSnafu)?;
|
||||||
|
|
||||||
let guild_vcs = vcs.get(&guild_id).context(NoVCsInGuildSnafu)?;
|
let guild_vcs = vcs.get(&guild_id).context(NoVCsInGuildSnafu)?;
|
||||||
@@ -55,14 +64,17 @@ pub fn get_guild_and_voice_channel_id(
|
|||||||
.get_left_for(&bot_user_id)
|
.get_left_for(&bot_user_id)
|
||||||
.context(BotNotInVCSnafu)?;
|
.context(BotNotInVCSnafu)?;
|
||||||
|
|
||||||
Ok((guild_id, voice_channel_id))
|
Ok((user_id, guild_id, 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 {
|
||||||
match error {
|
match error {
|
||||||
GetGuildAndVoiceChannelIdError::NotInGuild => {
|
GetGuildAndVoiceChannelIdError::NotInGuild => {
|
||||||
EmbedBuilder::new().title("Use this in a server").description("This bot can't tell which VC to leave if the command is used outside of a server (you might've used it in a DM?).").validate().unwrap().build()
|
EmbedBuilder::new().title("Use this in a server").description("This bot can't tell which VC to leave if the command is used outside of a server (you might've used it in a DM?).").validate().unwrap().build()
|
||||||
}
|
},
|
||||||
|
GetGuildAndVoiceChannelIdError::NoUser => {
|
||||||
|
EmbedBuilder::new().title("Not invoked by a user").description("This command works by joining the same VC as the user, but this bot didn't receive any user data. So did no user invoke it?! (This error should be impossible!)").validate().unwrap().build()
|
||||||
|
},
|
||||||
GetGuildAndVoiceChannelIdError::NoVCsInGuild => {
|
GetGuildAndVoiceChannelIdError::NoVCsInGuild => {
|
||||||
EmbedBuilder::new().title("No VCs in this server").description("This bot can't leave VC because there aren't any in this server right now (therefore the bot must not be in any).").validate().unwrap().build()
|
EmbedBuilder::new().title("No VCs in this server").description("This bot can't leave VC because there aren't any in this server right now (therefore the bot must not be in any).").validate().unwrap().build()
|
||||||
},
|
},
|
||||||
@@ -74,32 +86,60 @@ fn get_guild_and_vc_error_to_embed(error: GetGuildAndVoiceChannelIdError) -> Emb
|
|||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
pub async fn handle(state: State, interaction: Interaction) {
|
pub async fn handle(state: State, interaction: Interaction) {
|
||||||
let (guild_id, voice_channel_id) =
|
let (user_id, guild_id, voice_channel_id) = match get_user_and_guild_and_voice_channel_id(
|
||||||
match get_guild_and_voice_channel_id(state.discord_user_id, &interaction, &state.vcs) {
|
state.discord_user_id,
|
||||||
Ok((guild_id, voice_channel_id)) => (guild_id, voice_channel_id),
|
&interaction,
|
||||||
Err(error) => {
|
&state.vcs,
|
||||||
state
|
) {
|
||||||
.discord_client
|
Ok((user_id, guild_id, voice_channel_id)) => (user_id, guild_id, voice_channel_id),
|
||||||
.interaction(state.discord_application_id)
|
Err(error) => {
|
||||||
.create_response(
|
state
|
||||||
interaction.id,
|
.discord_client
|
||||||
&interaction.token,
|
.interaction(state.discord_application_id)
|
||||||
&InteractionResponse {
|
.create_response(
|
||||||
kind: InteractionResponseType::ChannelMessageWithSource,
|
interaction.id,
|
||||||
data: Some(
|
&interaction.token,
|
||||||
InteractionResponseDataBuilder::new()
|
&InteractionResponse {
|
||||||
.embeds([get_guild_and_vc_error_to_embed(error)])
|
kind: InteractionResponseType::ChannelMessageWithSource,
|
||||||
.flags(MessageFlags::EPHEMERAL)
|
data: Some(
|
||||||
.build(),
|
InteractionResponseDataBuilder::new()
|
||||||
),
|
.embeds([get_guild_and_vc_error_to_embed(error)])
|
||||||
},
|
.flags(MessageFlags::EPHEMERAL)
|
||||||
)
|
.build(),
|
||||||
.await
|
),
|
||||||
.expect("TODO");
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("TODO");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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 the 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");
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ use songbird::Songbird;
|
|||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
use twilight_model::{
|
use twilight_model::{
|
||||||
application::{command::Command, interaction::Interaction},
|
application::{command::Command, interaction::Interaction},
|
||||||
id::{Id, marker::{ApplicationMarker, UserMarker}},
|
id::{
|
||||||
|
Id,
|
||||||
|
marker::{ApplicationMarker, UserMarker},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::VCs;
|
use crate::VCs;
|
||||||
@@ -19,6 +22,7 @@ mod opt_out;
|
|||||||
pub struct State {
|
pub struct State {
|
||||||
pub cancellation_token: CancellationToken,
|
pub cancellation_token: CancellationToken,
|
||||||
pub discord_application_id: Id<ApplicationMarker>,
|
pub discord_application_id: Id<ApplicationMarker>,
|
||||||
|
pub discord_bot_owner_user_id: Id<UserMarker>,
|
||||||
pub discord_client: Arc<twilight_http::Client>,
|
pub discord_client: Arc<twilight_http::Client>,
|
||||||
pub discord_user_id: Id<UserMarker>,
|
pub discord_user_id: Id<UserMarker>,
|
||||||
pub songbird: Arc<Songbird>,
|
pub songbird: Arc<Songbird>,
|
||||||
|
|||||||
@@ -201,6 +201,7 @@ async fn main() -> Result<(), MainError> {
|
|||||||
let state = State {
|
let state = State {
|
||||||
cancellation_token: cancellation_token.clone(),
|
cancellation_token: cancellation_token.clone(),
|
||||||
discord_application_id,
|
discord_application_id,
|
||||||
|
discord_bot_owner_user_id: bot_owner,
|
||||||
discord_client,
|
discord_client,
|
||||||
discord_user_id,
|
discord_user_id,
|
||||||
songbird,
|
songbird,
|
||||||
|
|||||||
Reference in New Issue
Block a user