Make permissions checking not depend on the cache

This commit is contained in:
2025-08-21 19:19:02 -03:00
parent 408f0223a2
commit e28f11d9bb
3 changed files with 48 additions and 21 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ twilight-cache-inmemory = { version = "0.16.0", features = ["permission-calculat
twilight-gateway = "0.16.0" twilight-gateway = "0.16.0"
twilight-http = { version = "0.16.0", features = ["simd-json"] } twilight-http = { version = "0.16.0", features = ["simd-json"] }
twilight-model = "0.16.0" twilight-model = "0.16.0"
twilight-util = { version = "0.16.0", features = ["builder"] } twilight-util = { version = "0.16.0", features = ["builder", "permission-calculator"] }
twilight-validate = "0.16.0" twilight-validate = "0.16.0"
unicode-segmentation = "1.12.0" unicode-segmentation = "1.12.0"
unidecode = "0.3.0" unidecode = "0.3.0"
+47 -19
View File
@@ -1,5 +1,9 @@
use async_trait::async_trait; use async_trait::async_trait;
use twilight_model::guild::Permissions; use twilight_model::{
guild::Permissions,
id::{Id, marker::RoleMarker},
};
use twilight_util::permission_calculator::PermissionCalculator;
use crate::{ use crate::{
framework::commands::{CommandError, context::CommandContext, permissions::Permission}, framework::commands::{CommandError, context::CommandContext, permissions::Permission},
@@ -31,28 +35,52 @@ pub struct ServerModeratorPermission;
impl Permission<State> for ServerModeratorPermission { impl Permission<State> for ServerModeratorPermission {
async fn check(&self, ctx: &CommandContext<State>) -> Result<bool, CommandError> { async fn check(&self, ctx: &CommandContext<State>) -> Result<bool, CommandError> {
if let Some(guild_id) = ctx.event.guild_id { if let Some(guild_id) = ctx.event.guild_id {
let permissions = ctx let Some(guild) = ctx.rt.cache.guild(guild_id) else {
log::warn!("Could not get guild for ID {guild_id}!");
return Ok(false);
};
let member = ctx
.rt .rt
.cache .http
.permissions() .guild_member(guild_id, ctx.event.author.id)
.root(ctx.event.author.id, guild_id); .await
.map_err(CommandError::DiscordAPIFailed)?
.model()
.await
.map_err(CommandError::DiscordDeserializationFailed)?;
if let Ok(permissions) = permissions { let Some(everyone_role) = ctx.rt.cache.role(guild_id.cast()) else {
let guild = ctx log::warn!("Could not get @everyone role for guild ID {guild_id}!");
.rt
.cache
.guild(guild_id)
.ok_or(CommandError::CacheStateInconsistent)?;
Ok(permissions return Ok(false);
.contains(Permissions::MANAGE_CHANNELS | Permissions::MANAGE_MESSAGES) };
|| guild.owner_id() == ctx.event.author.id)
} else { let member_roles: Vec<(Id<RoleMarker>, Permissions)> = member
Err(CommandError::CacheStateInconsistent) .roles
} .into_iter()
} else { .filter_map(|role_id| {
Ok(true) ctx.rt
.cache
.role(role_id)
.map(|role| (role.id, role.permissions))
})
.collect();
let calculator = PermissionCalculator::new(
guild_id,
ctx.event.author.id,
everyone_role.permissions,
&member_roles,
)
.owner_id(guild.owner_id());
return Ok(calculator.root().contains(Permissions::MANAGE_CHANNELS | Permissions::MANAGE_MESSAGES));
} }
// DMs channel, the user has all permissions.
Ok(true)
} }
async fn on_handle_denied(&self, ctx: &CommandContext<State>) -> Result<(), CommandError> { async fn on_handle_denied(&self, ctx: &CommandContext<State>) -> Result<(), CommandError> {
-1
View File
@@ -244,7 +244,6 @@ async fn start(
.shard(shard) .shard(shard)
.intent(Intents::GUILDS) .intent(Intents::GUILDS)
.intent(Intents::GUILD_MESSAGES) .intent(Intents::GUILD_MESSAGES)
.intent(Intents::GUILD_MEMBERS)
.intent(Intents::MESSAGE_CONTENT) .intent(Intents::MESSAGE_CONTENT)
.command(HelpCommand) .command(HelpCommand)
.command(CallCommand::new()) .command(CallCommand::new())