1
1
from __future__ import annotations
2
2
3
3
import os
4
- from typing import Callable , TypeVar
4
+ from typing import TYPE_CHECKING , Callable , TypeVar
5
5
6
+ import discord
6
7
from discord import app_commands
7
8
from discord .ext import commands
8
9
9
- T = TypeVar ("T" )
10
+ # Although commands.HybridCommand (and it's group version) can be bound here for Type T,
11
+ # it doesn't make sense as they are just subclasses of commands.Command and co.
12
+ T = TypeVar ("T" , commands .Command , commands .Group )
13
+
14
+ if TYPE_CHECKING :
15
+ from libs .utils .context import RoboContext
10
16
11
17
12
- # For time's sake I might as well take these from RDanny
13
- # There is really no used of creating my own system when there is one out there already
14
18
async def check_guild_permissions (
15
- ctx : commands . Context , perms : dict [str , bool ], * , check = all
19
+ ctx : RoboContext , perms : dict [str , bool ], * , check = all
16
20
) -> bool :
17
21
is_owner = await ctx .bot .is_owner (ctx .author )
18
22
if is_owner :
@@ -27,9 +31,48 @@ async def check_guild_permissions(
27
31
)
28
32
29
33
30
- def hybrid_permissions_check (** perms : bool ) -> Callable [[T ], T ]:
31
- async def pred (ctx : commands .Context ):
32
- return await check_guild_permissions (ctx , perms )
34
+ async def check_bot_permissions (
35
+ ctx : RoboContext , perms : dict [str , bool ], * , check = all
36
+ ) -> bool :
37
+ is_owner = await ctx .bot .is_owner (ctx .author )
38
+ if is_owner :
39
+ return True
40
+
41
+ if ctx .guild is None :
42
+ return False
43
+
44
+ bot_resolved_perms = ctx .me .guild_permissions # type: ignore
45
+ return check (
46
+ getattr (bot_resolved_perms , name , None ) == value
47
+ for name , value in perms .items ()
48
+ )
49
+
50
+
51
+ def check_permissions (** perms : bool ) -> Callable [[T ], T ]:
52
+ async def pred (ctx : RoboContext ):
53
+ # Usually means this is in the context of a DM
54
+ if (
55
+ isinstance (ctx .me , discord .ClientUser )
56
+ or isinstance (ctx .author , discord .User )
57
+ or ctx .guild is None
58
+ ):
59
+ return False
60
+ guild_perms = await check_guild_permissions (ctx , perms )
61
+ can_run = ctx .me .top_role > ctx .author .top_role
62
+ return guild_perms and can_run
63
+
64
+ def decorator (func : T ) -> T :
65
+ func .extras ["permissions" ] = perms
66
+ commands .check (pred )(func )
67
+ app_commands .default_permissions (** perms )(func )
68
+ return func
69
+
70
+ return decorator
71
+
72
+
73
+ def bot_check_permissions (** perms : bool ) -> Callable [[T ], T ]:
74
+ async def pred (ctx : RoboContext ):
75
+ return await check_bot_permissions (ctx , perms )
33
76
34
77
def decorator (func : T ) -> T :
35
78
commands .check (pred )(func )
@@ -40,17 +83,17 @@ def decorator(func: T) -> T:
40
83
41
84
42
85
def is_manager ():
43
- return hybrid_permissions_check (manage_guild = True )
86
+ return check_permissions (manage_guild = True )
44
87
45
88
46
89
def is_mod ():
47
- return hybrid_permissions_check (
90
+ return check_permissions (
48
91
ban_members = True , manage_messages = True , kick_members = True , moderate_members = True
49
92
)
50
93
51
94
52
95
def is_admin ():
53
- return hybrid_permissions_check (administrator = True )
96
+ return check_permissions (administrator = True )
54
97
55
98
56
99
def is_docker () -> bool :
0 commit comments