Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle SEND_MESSAGES_IN_THREADS in required_permissions calculations #326

Merged
merged 1 commit into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions src/dispatch/permissions/application.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
//! Application command permissions calculation
use crate::serenity_prelude as serenity;
use crate::{serenity::Permissions, serenity_prelude as serenity};

use super::PermissionsInfo;

/// Checks if a ChannelType is equal to a known thread type.
fn is_thread(kind: serenity::ChannelType) -> bool {
matches!(
kind,
serenity::ChannelType::NewsThread
| serenity::ChannelType::PrivateThread
| serenity::ChannelType::PublicThread
)
}

/// Gets the permissions of the ctx author and the bot.
pub(super) fn get_author_and_bot_permissions(
interaction: &serenity::CommandInteraction,
Expand All @@ -11,10 +21,22 @@ pub(super) fn get_author_and_bot_permissions(
let author_member = interaction.member.as_ref().expect(err);

let err = "should always be some as inside interaction";
let author_permissions = author_member.permissions.expect(err);
let mut author_permissions = author_member.permissions.expect(err);

let err = "should always be some according to discord docs";
let bot_permissions = interaction.app_permissions.expect(err);
let mut bot_permissions = interaction.app_permissions.expect(err);

let channel = interaction.channel.as_ref();
if channel.is_some_and(|c| is_thread(c.kind)) {
author_permissions.set(
Permissions::SEND_MESSAGES,
author_permissions.send_messages_in_threads(),
);
bot_permissions.set(
Permissions::SEND_MESSAGES,
bot_permissions.send_messages_in_threads(),
);
}

PermissionsInfo {
author_permissions: Some(author_permissions),
Expand Down
9 changes: 8 additions & 1 deletion src/dispatch/permissions/prefix/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,14 @@ fn get_bot_permissions(
let parent_channel_id = thread.parent_id.expect(err);

let parent_channel = guild.channels.get(&parent_channel_id)?;
Some(guild.user_permissions_in(parent_channel, bot_member))
let mut parent_permissions = guild.user_permissions_in(parent_channel, bot_member);

parent_permissions.set(
serenity::Permissions::SEND_MESSAGES,
parent_permissions.send_messages_in_threads(),
);

Some(parent_permissions)
} else {
// The message was either:
// - Sent in a guild with broken caching
Expand Down
14 changes: 10 additions & 4 deletions src/structs/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,21 @@ pub struct Command<U, E> {
///
/// Set to [`serenity::Permissions::empty()`] by default
pub default_member_permissions: serenity::Permissions,
/// Permissions which users must have to invoke this command. This is checked internally and
/// works for both prefix commands and slash commands.
/// Permissions which users must have to invoke this command.
///
/// This is checked internally and works for both prefix commands and slash commands.
///
/// This also handles the case a message is sent in a thread, in which `SEND_MESSAGES` is set to `SEND_MESSAGES_IN_THREADS`.
///
/// Set to [`serenity::Permissions::empty()`] by default
pub required_permissions: serenity::Permissions,
/// Permissions without which command execution will fail. You can set this to fail early and
/// give a descriptive error message in case the
/// Permissions without which command execution will fail.
///
/// You can set this to fail early and give a descriptive error message in case the
/// bot hasn't been assigned the minimum permissions by the guild admin.
///
/// This also handles the case a message is sent in a thread, in which `SEND_MESSAGES` is set to `SEND_MESSAGES_IN_THREADS`.
///
/// Set to [`serenity::Permissions::empty()`] by default
pub required_bot_permissions: serenity::Permissions,
/// If true, only users from the [owners list](crate::FrameworkOptions::owners) may use this
Expand Down
Loading