pikadick/checks/
admin.rs

1use pikadick_slash_framework::{
2    BoxFuture,
3    Command,
4    Reason as SlashReason,
5};
6use serenity::{
7    client::Context,
8    framework::standard::{
9        macros::check,
10        Args,
11        CommandOptions,
12        Reason,
13    },
14    model::{
15        application::CommandInteraction,
16        prelude::*,
17    },
18};
19use tracing::warn;
20
21#[check]
22#[name("Admin")]
23pub async fn admin_check(
24    ctx: &Context,
25    msg: &Message,
26    _args: &mut Args,
27    _opts: &CommandOptions,
28) -> Result<(), Reason> {
29    if let Some(guild_id) = msg.guild_id {
30        let member = match msg.member(ctx).await {
31            Ok(member) => member,
32            Err(e) => {
33                return Err(Reason::User(format!("failed to fetch member info: {}", e)));
34            }
35        };
36
37        if let Some(guild) = guild_id.to_guild_cached(&ctx.cache) {
38            let guild_channel = match guild.channels.get(&msg.channel_id) {
39                Some(channel) => channel,
40                None => return Err(Reason::Unknown),
41            };
42
43            let perms = guild.user_permissions_in(guild_channel, &member);
44
45            if perms.administrator() {
46                Ok(())
47            } else {
48                Err(Reason::User("not admin".to_string()))
49            }
50        } else {
51            Err(Reason::User("guild not in cache".to_string()))
52        }
53    } else {
54        // User is probably in a DM.
55        Ok(())
56    }
57}
58
59/// Ensure a user is admin
60pub fn create_slash_check<'a>(
61    _ctx: &'a Context,
62    interaction: &'a CommandInteraction,
63    _command: &'a Command,
64) -> BoxFuture<'a, Result<(), SlashReason>> {
65    Box::pin(async move {
66        match interaction.guild_id {
67            Some(id) => id,
68            None => {
69                // Let's not care about dms for now.
70                // They'll probably need special handling anyways.
71                // This will also probably only be useful in Group DMs,
72                // which I don't think bots can participate in anyways.
73                return Ok(());
74            }
75        };
76
77        match interaction
78            .member
79            .as_ref()
80            .and_then(|member| member.permissions)
81        {
82            Some(permissions) => {
83                if permissions.contains(Permissions::ADMINISTRATOR) {
84                    Ok(())
85                } else {
86                    Err(SlashReason::new_user("Not Admin.".to_string()))
87                }
88            }
89            None => {
90                // Failed to get member permissions.
91                // I don't think this matters since I think this is only absent in dms.
92                warn!("failed to get member permissions");
93                Err(SlashReason::new_unknown())
94            }
95        }
96    })
97}