Skip to content

Commit 0d48282

Browse files
authored
Deprecate Guild::permissions_for_user, add Message::author_permissions
This deprecates `GuildChannel::permissions_for_user` as: - It is unnecessary API surface - Performs a cache lookup when most users will have `Guild` if they have `GuildChannel` It also adds `Message::author_permissions` to match `Interaction::permissions` and hopefully be a replacement for a lot of the usage of `GuildChannel::permissions_for_user`. This also takes advantage of the lesser known `Message::member` field to not require member intents for calculating the permissions from a message create event. For `Message::author_permissions`, this also adds `Permissions::dm_permissions`, which returns the permissions that are implicitly enabled in a DM.
1 parent 85df0b0 commit 0d48282

File tree

5 files changed

+51
-18
lines changed

5 files changed

+51
-18
lines changed

examples/testing/src/main.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,7 @@ async fn message(ctx: &Context, msg: Message) -> Result<(), serenity::Error> {
196196
channel.edit(ctx, EditChannel::new().category(None)).await?;
197197
channel.edit(ctx, EditChannel::new().category(Some(parent_id))).await?;
198198
} else if msg.content == "channelperms" {
199-
let guild = guild_id.to_guild_cached(ctx).unwrap().clone();
200-
let perms = guild.user_permissions_in(
201-
&channel_id.to_channel(ctx).await?.guild().unwrap(),
202-
&*guild.member(ctx, msg.author.id).await?,
203-
);
204-
channel_id.say(ctx, format!("{:?}", perms)).await?;
199+
channel_id.say(ctx, format!("{:?}", msg.author_permissions(ctx))).await?;
205200
} else if let Some(forum_channel_id) = msg.content.strip_prefix("createforumpostin ") {
206201
forum_channel_id
207202
.parse::<ChannelId>()

src/framework/standard/mod.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -857,13 +857,10 @@ pub(crate) fn has_correct_permissions(
857857
) -> bool {
858858
if options.required_permissions().is_empty() {
859859
true
860+
} else if let Some(permissions) = message.author_permissions(cache) {
861+
permissions.contains(*options.required_permissions())
860862
} else {
861-
message.guild(cache.as_ref()).is_some_and(|guild| {
862-
let Some(channel) = guild.channels.get(&message.channel_id) else { return false };
863-
let Some(member) = guild.members.get(&message.author.id) else { return false };
864-
865-
guild.user_permissions_in(channel, member).contains(*options.required_permissions())
866-
})
863+
false
867864
}
868865
}
869866

src/model/channel/guild_channel.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@ impl GuildChannel {
761761
/// [Attach Files]: Permissions::ATTACH_FILES
762762
/// [Send Messages]: Permissions::SEND_MESSAGES
763763
#[cfg(feature = "cache")]
764+
#[deprecated = "Use `Guild::user_permissions_in`"]
764765
#[inline]
765766
pub fn permissions_for_user(
766767
&self,
@@ -1022,13 +1023,11 @@ impl GuildChannel {
10221023
.collect()),
10231024
ChannelType::News | ChannelType::Text => Ok(guild
10241025
.members
1025-
.iter()
1026-
.filter(|e| {
1027-
self.permissions_for_user(cache, e.0)
1028-
.map(|p| p.contains(Permissions::VIEW_CHANNEL))
1029-
.unwrap_or(false)
1026+
.values()
1027+
.filter(|member| {
1028+
guild.user_permissions_in(self, member).contains(Permissions::VIEW_CHANNEL)
10301029
})
1031-
.map(|e| e.1.clone())
1030+
.cloned()
10321031
.collect::<Vec<Member>>()),
10331032
_ => Err(Error::from(ModelError::InvalidChannelType)),
10341033
}

src/model/channel/message.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,26 @@ impl Message {
216216
self.author.id == cache.as_ref().current_user().id
217217
}
218218

219+
/// Calculates the permissions of the message author in the current channel.
220+
///
221+
/// This may return `None` if:
222+
/// - The [`Cache`] does not have the current [`Guild`]
223+
/// - This message is not from [`MessageCreateEvent`] and the author's [`Member`] cannot be
224+
/// found in [`Guild#structfield.members`].
225+
#[cfg(feature = "cache")]
226+
pub fn author_permissions(&self, cache: impl AsRef<Cache>) -> Option<Permissions> {
227+
let Some(guild_id) = self.guild_id else {
228+
return Some(Permissions::dm_permissions());
229+
};
230+
231+
let guild = cache.as_ref().guild(guild_id)?;
232+
if let Some(member) = &self.member {
233+
Some(guild.partial_member_permissions(self.author.id, member))
234+
} else {
235+
Some(guild.member_permissions(guild.members.get(&self.author.id)?))
236+
}
237+
}
238+
219239
/// Deletes the message.
220240
///
221241
/// **Note**: The logged in user must either be the author of the message or have the [Manage

src/model/permissions.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,28 @@ generate_get_permission_names! {
420420
/// TODO: use a macro to shorten this entire file lol
421421
#[cfg(feature = "model")]
422422
impl Permissions {
423+
#[must_use]
424+
pub fn dm_permissions() -> Self {
425+
Self::ADD_REACTIONS
426+
| Self::STREAM
427+
| Self::VIEW_CHANNEL
428+
| Self::SEND_MESSAGES
429+
| Self::SEND_TTS_MESSAGES
430+
| Self::EMBED_LINKS
431+
| Self::ATTACH_FILES
432+
| Self::READ_MESSAGE_HISTORY
433+
| Self::MENTION_EVERYONE
434+
| Self::USE_EXTERNAL_EMOJIS
435+
| Self::CONNECT
436+
| Self::SPEAK
437+
| Self::USE_VAD
438+
| Self::USE_APPLICATION_COMMANDS
439+
| Self::USE_EXTERNAL_STICKERS
440+
| Self::SEND_VOICE_MESSAGES
441+
| Self::SEND_POLLS
442+
| Self::USE_EXTERNAL_APPS
443+
}
444+
423445
/// Shorthand for checking that the set of permissions contains the [Add Reactions] permission.
424446
///
425447
/// [Add Reactions]: Self::ADD_REACTIONS

0 commit comments

Comments
 (0)