|
2 | 2 |
|
3 | 3 | use crate::serenity_prelude as serenity; |
4 | 4 |
|
5 | | -/// Retrieves user permissions in the given channel. If unknown, returns None. If in DMs, returns |
6 | | -/// `Permissions::all()`. |
7 | | -async fn user_permissions( |
8 | | - ctx: &serenity::Context, |
9 | | - guild_id: Option<serenity::GuildId>, |
10 | | - channel_id: serenity::ChannelId, |
11 | | - user_id: serenity::UserId, |
12 | | -) -> Option<serenity::Permissions> { |
13 | | - let guild_id = match guild_id { |
14 | | - Some(x) => x, |
15 | | - None => return Some(serenity::Permissions::all()), // no permission checks in DMs |
16 | | - }; |
17 | | - |
18 | | - let guild = guild_id.to_partial_guild(ctx).await.ok()?; |
19 | | - |
20 | | - // Use to_channel so that it can fallback on HTTP for threads (which aren't in cache usually) |
21 | | - let channel = match channel_id.to_channel(ctx).await { |
22 | | - Ok(serenity::Channel::Guild(channel)) => channel, |
23 | | - Ok(_other_channel) => { |
24 | | - tracing::warn!( |
25 | | - "guild message was supposedly sent in a non-guild channel. Denying invocation" |
26 | | - ); |
27 | | - return None; |
28 | | - } |
29 | | - Err(_) => return None, |
30 | | - }; |
31 | | - |
32 | | - let member = guild.member(ctx, user_id).await.ok()?; |
33 | | - |
34 | | - Some(guild.user_permissions_in(&channel, &member)) |
35 | | -} |
36 | | - |
37 | | -/// Retrieves the set of permissions that are lacking, relative to the given required permission set |
38 | | -/// |
39 | | -/// Returns None if permissions couldn't be retrieved |
40 | | -async fn missing_permissions<U, E>( |
41 | | - ctx: crate::Context<'_, U, E>, |
42 | | - user: serenity::UserId, |
43 | | - required_permissions: serenity::Permissions, |
44 | | -) -> Option<serenity::Permissions> { |
45 | | - if required_permissions.is_empty() { |
46 | | - return Some(serenity::Permissions::empty()); |
47 | | - } |
48 | | - |
49 | | - let permissions = user_permissions( |
50 | | - ctx.serenity_context(), |
51 | | - ctx.guild_id(), |
52 | | - ctx.channel_id(), |
53 | | - user, |
54 | | - ) |
55 | | - .await; |
56 | | - Some(required_permissions - permissions?) |
57 | | -} |
58 | | - |
59 | 5 | /// See [`check_permissions_and_cooldown`]. Runs the check only for a single command. The caller |
60 | 6 | /// should call this multiple time for each parent command to achieve the check inheritance logic. |
61 | 7 | async fn check_permissions_and_cooldown_single<'a, U, E>( |
@@ -111,35 +57,29 @@ async fn check_permissions_and_cooldown_single<'a, U, E>( |
111 | 57 | } |
112 | 58 |
|
113 | 59 | // Make sure that user has required permissions |
114 | | - match missing_permissions(ctx, ctx.author().id, cmd.required_permissions).await { |
115 | | - Some(missing_permissions) if missing_permissions.is_empty() => {} |
116 | | - Some(missing_permissions) => { |
117 | | - return Err(crate::FrameworkError::MissingUserPermissions { |
118 | | - ctx, |
119 | | - missing_permissions: Some(missing_permissions), |
120 | | - }) |
121 | | - } |
122 | | - // Better safe than sorry: when perms are unknown, restrict access |
123 | | - None => { |
| 60 | + if let Some((user_missing_permissions, bot_missing_permissions)) = |
| 61 | + super::permissions::calculate_missing( |
| 62 | + ctx, |
| 63 | + cmd.required_permissions, |
| 64 | + cmd.required_bot_permissions, |
| 65 | + ) |
| 66 | + .await |
| 67 | + { |
| 68 | + if !user_missing_permissions.is_empty() { |
124 | 69 | return Err(crate::FrameworkError::MissingUserPermissions { |
125 | 70 | ctx, |
126 | | - missing_permissions: None, |
127 | | - }) |
| 71 | + missing_permissions: Some(user_missing_permissions), |
| 72 | + }); |
128 | 73 | } |
129 | | - } |
130 | 74 |
|
131 | | - // Before running any pre-command checks, make sure the bot has the permissions it needs |
132 | | - match missing_permissions(ctx, ctx.framework().bot_id(), cmd.required_bot_permissions).await { |
133 | | - Some(missing_permissions) if missing_permissions.is_empty() => {} |
134 | | - Some(missing_permissions) => { |
| 75 | + if !bot_missing_permissions.is_empty() { |
135 | 76 | return Err(crate::FrameworkError::MissingBotPermissions { |
136 | 77 | ctx, |
137 | | - missing_permissions, |
138 | | - }) |
| 78 | + missing_permissions: bot_missing_permissions, |
| 79 | + }); |
139 | 80 | } |
140 | | - // When in doubt, just let it run. Not getting fancy missing permissions errors is better |
141 | | - // than the command not executing at all |
142 | | - None => {} |
| 81 | + } else { |
| 82 | + return Err(crate::FrameworkError::PermissionFetchFailed { ctx }); |
143 | 83 | } |
144 | 84 |
|
145 | 85 | // Only continue if command checks returns true |
|
0 commit comments