Make permissions checking not depend on the cache
This commit is contained in:
+1
-1
@@ -33,7 +33,7 @@ twilight-cache-inmemory = { version = "0.16.0", features = ["permission-calculat
|
||||
twilight-gateway = "0.16.0"
|
||||
twilight-http = { version = "0.16.0", features = ["simd-json"] }
|
||||
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"
|
||||
unicode-segmentation = "1.12.0"
|
||||
unidecode = "0.3.0"
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
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::{
|
||||
framework::commands::{CommandError, context::CommandContext, permissions::Permission},
|
||||
@@ -31,29 +35,53 @@ pub struct ServerModeratorPermission;
|
||||
impl Permission<State> for ServerModeratorPermission {
|
||||
async fn check(&self, ctx: &CommandContext<State>) -> Result<bool, CommandError> {
|
||||
if let Some(guild_id) = ctx.event.guild_id {
|
||||
let permissions = ctx
|
||||
.rt
|
||||
.cache
|
||||
.permissions()
|
||||
.root(ctx.event.author.id, guild_id);
|
||||
let Some(guild) = ctx.rt.cache.guild(guild_id) else {
|
||||
log::warn!("Could not get guild for ID {guild_id}!");
|
||||
|
||||
if let Ok(permissions) = permissions {
|
||||
let guild = ctx
|
||||
.rt
|
||||
.cache
|
||||
.guild(guild_id)
|
||||
.ok_or(CommandError::CacheStateInconsistent)?;
|
||||
return Ok(false);
|
||||
};
|
||||
|
||||
Ok(permissions
|
||||
.contains(Permissions::MANAGE_CHANNELS | Permissions::MANAGE_MESSAGES)
|
||||
|| guild.owner_id() == ctx.event.author.id)
|
||||
} else {
|
||||
Err(CommandError::CacheStateInconsistent)
|
||||
let member = ctx
|
||||
.rt
|
||||
.http
|
||||
.guild_member(guild_id, ctx.event.author.id)
|
||||
.await
|
||||
.map_err(CommandError::DiscordAPIFailed)?
|
||||
.model()
|
||||
.await
|
||||
.map_err(CommandError::DiscordDeserializationFailed)?;
|
||||
|
||||
let Some(everyone_role) = ctx.rt.cache.role(guild_id.cast()) else {
|
||||
log::warn!("Could not get @everyone role for guild ID {guild_id}!");
|
||||
|
||||
return Ok(false);
|
||||
};
|
||||
|
||||
let member_roles: Vec<(Id<RoleMarker>, Permissions)> = member
|
||||
.roles
|
||||
.into_iter()
|
||||
.filter_map(|role_id| {
|
||||
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));
|
||||
}
|
||||
} else {
|
||||
|
||||
// DMs channel, the user has all permissions.
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
async fn on_handle_denied(&self, ctx: &CommandContext<State>) -> Result<(), CommandError> {
|
||||
ctx.send()
|
||||
|
||||
@@ -244,7 +244,6 @@ async fn start(
|
||||
.shard(shard)
|
||||
.intent(Intents::GUILDS)
|
||||
.intent(Intents::GUILD_MESSAGES)
|
||||
.intent(Intents::GUILD_MEMBERS)
|
||||
.intent(Intents::MESSAGE_CONTENT)
|
||||
.command(HelpCommand)
|
||||
.command(CallCommand::new())
|
||||
|
||||
Reference in New Issue
Block a user