Note on permissions

There are 3 ways to check if an user / member has permissions to do something in a channel / server.

Let's say we want to implement a ban command:

Manually checking permissions

#![allow(unused)] fn main() { use robespierre::framework::standard::{FwContext, CommandResult, macros::command}; use robespierre::framework::standard::extractors::{Args, AuthorMember, RawArgs, Rest}; use robespierre::model::MessageExt; use robespierre_models::channels::Message; use robespierre_models::servers::ServerPermissions; use robespierre_models::users::User; #[derive(thiserror::Error, Debug)] #[error("missing perms")] struct MissingPerms; #[command] async fn ban( ctx: &FwContext, msg: &Message, Args((user, Rest(reason))): Args<(User, Rest<Option<String>>)>, AuthorMember(member): AuthorMember, ) -> CommandResult { let server = msg.server(ctx).await?.unwrap(); let result = robespierre_models::permissions_utils::member_has_permissions( &member, ServerPermissions::BAN_MEMBERS, &server, ); if !result { return Err(MissingPerms.into()); } // ban Ok(()) } }

If you need to check if an user has permissions in a given channel use member_has_permissions_in_channel, and pass the ChannelPermissions you want to check + a reference to the channel you want to check for permissions in.

Extractor version

#![allow(unused)] fn main() { use robespierre::framework::standard::{FwContext, CommandResult, macros::command}; use robespierre::framework::standard::extractors::{Args, AuthorMember, RawArgs, Rest, RequiredPermissions}; use robespierre::model::MessageExt; use robespierre_models::channels::Message; use robespierre_models::channels::ChannelPermissions; use robespierre_models::servers::ServerPermissions; use robespierre_models::users::User; #[command] async fn ban( ctx: &FwContext, msg: &Message, Args((user, Rest(reason))): Args<(User, Rest<Option<String>>)>, _: RequiredPermissions< { ServerPermissions::bits(&ServerPermissions::BAN_MEMBERS) }, { ChannelPermissions::bits(&ChannelPermissions::empty()) }, >, ) -> CommandResult { // ban Ok(()) } }

If one of them is T::bits(&T::empty()), it can be rewritten with the RequiredServerPermissions and RequiredChannelPermissions utils. In our example:

#![allow(unused)] fn main() { use robespierre::framework::standard::{FwContext, CommandResult, macros::command}; use robespierre::framework::standard::extractors::{Args, AuthorMember, RawArgs, Rest}; use robespierre::model::MessageExt; use robespierre_models::channels::Message; use robespierre_models::servers::ServerPermissions; use robespierre_models::users::User; use robespierre::framework::standard::extractors::RequiredServerPermissions; #[command] async fn ban( ctx: &FwContext, msg: &Message, Args((user, Rest(reason))): Args<(User, Rest<Option<String>>)>, _: RequiredServerPermissions<{ ServerPermissions::bits(&ServerPermissions::BAN_MEMBERS) }>, ) -> CommandResult { // --snip-- // ban Ok(()) } }

Adding required permissions to the command when creating the framework

use robespierre::CacheWrap; use robespierre::EventHandlerWrap; use robespierre::Context; use robespierre::Authentication; use robespierre::model::MessageExt; use robespierre::framework::standard::{FwContext, CommandResult, macros::command}; use robespierre::framework::standard::{StandardFramework, Command, CommandCodeFn}; use robespierre::framework::standard::extractors::{Args, Rest}; use robespierre::FrameworkWrap; use robespierre_cache::CacheConfig; use robespierre_events::Connection; use robespierre_http::Http; use robespierre_models::channels::Message; use robespierre_models::servers::ServerPermissions; use robespierre_models::users::User; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // --snip-- tracing_subscriber::fmt::init(); let token = std::env::var("TOKEN") .expect("Cannot get token; set environment variable TOKEN=... and run again"); let auth = Authentication::bot(token); let http = Http::new(&auth).await?; let connection = Connection::connect(&auth).await?; let context = Context::new(http, robespierre::typemap::ShareMap::custom()).with_cache(CacheConfig::default()); let fw = StandardFramework::default() .configure(|c| c.prefix("!")) .group(|g| { g.name("General") .command(|| Command::new("ban", ban as CommandCodeFn).required_server_permissions(ServerPermissions::BAN_MEMBERS)) }); // --snip-- let handler = FrameworkWrap::new(fw, Handler); let handler = CacheWrap::new(EventHandlerWrap::new(handler)); connection.run(context, handler).await?; Ok(()) } #[command] async fn ban( ctx: &FwContext, msg: &Message, Args((user, Rest(reason))): Args<(User, Rest<Option<String>>)>, ) -> CommandResult { // ban Ok(()) } #[derive(Clone)] struct Handler; #[robespierre::async_trait] impl robespierre::EventHandler for Handler {}