4
4
import re
5
5
import sys
6
6
import traceback
7
+ from typing import Pattern
7
8
8
9
import discord
9
10
from discord .ext import commands
12
13
13
14
from . import utils
14
15
from .cogs import _utils
16
+ from .context import DozerContext
15
17
16
18
DOZER_LOGGER = logging .getLogger ('dozer' )
17
19
DOZER_LOGGER .level = logging .INFO
@@ -36,19 +38,11 @@ class InvalidContext(commands.CheckFailure):
36
38
"""
37
39
38
40
39
- class DozerContext (commands .Context ):
40
- """Cleans all messages before sending"""
41
- async def send (self , content = None , ** kwargs ): # pylint: disable=arguments-differ
42
- if content is not None :
43
- content = utils .clean (self , content , mass = True , member = False , role = False , channel = False )
44
- return await super ().send (content , ** kwargs )
45
-
46
-
47
41
class Dozer (commands .Bot ):
48
42
"""Botty things that are critical to Dozer working"""
49
43
_global_cooldown = commands .Cooldown (1 , 1 , commands .BucketType .user ) # One command per second per user
50
44
51
- def __init__ (self , config , * args , ** kwargs ):
45
+ def __init__ (self , config : dict , * args , ** kwargs ):
52
46
self .dynamic_prefix = _utils .PrefixHandler (config ['prefix' ])
53
47
super ().__init__ (command_prefix = self .dynamic_prefix .handler , * args , ** kwargs )
54
48
self .slash = SlashCommand (self , sync_commands = True , override_type = True )
@@ -78,45 +72,52 @@ async def on_ready(self):
78
72
DOZER_LOGGER .warning ("You are running an older version of the discord.py rewrite (with breaking changes)! "
79
73
"To upgrade, run `pip install -r requirements.txt --upgrade`" )
80
74
81
- async def get_context (self , message , * , cls = DozerContext ):
75
+ async def get_context (self , message : discord . Message , * , cls = DozerContext ):
82
76
ctx = await super ().get_context (message , cls = cls )
83
77
return ctx
84
78
85
- async def on_command_error (self , context , exception ):
79
+ async def on_command_error (self , context : DozerContext , exception ):
86
80
if isinstance (exception , commands .NoPrivateMessage ):
87
81
await context .send ('{}, This command cannot be used in DMs.' .format (context .author .mention ))
88
82
elif isinstance (exception , commands .UserInputError ):
89
83
await context .send ('{}, {}' .format (context .author .mention , self .format_error (context , exception )))
90
84
elif isinstance (exception , commands .NotOwner ):
91
85
await context .send ('{}, {}' .format (context .author .mention , exception .args [0 ]))
92
86
elif isinstance (exception , commands .MissingPermissions ):
93
- permission_names = [name .replace ('guild' , 'server' ).replace ('_' , ' ' ).title () for name in exception .missing_perms ]
87
+ permission_names = [name .replace ('guild' , 'server' ).replace ('_' , ' ' ).title () for name in
88
+ exception .missing_perms ]
94
89
await context .send ('{}, you need {} permissions to run this command!' .format (
95
90
context .author .mention , utils .pretty_concat (permission_names )))
96
91
elif isinstance (exception , commands .BotMissingPermissions ):
97
- permission_names = [name .replace ('guild' , 'server' ).replace ('_' , ' ' ).title () for name in exception .missing_perms ]
92
+ permission_names = [name .replace ('guild' , 'server' ).replace ('_' , ' ' ).title () for name in
93
+ exception .missing_perms ]
98
94
await context .send ('{}, I need {} permissions to run this command!' .format (
99
95
context .author .mention , utils .pretty_concat (permission_names )))
100
96
elif isinstance (exception , commands .CommandOnCooldown ):
101
97
await context .send (
102
- '{}, That command is on cooldown! Try again in {:.2f}s!' .format (context .author .mention , exception .retry_after ))
98
+ '{}, That command is on cooldown! Try again in {:.2f}s!' .format (context .author .mention ,
99
+ exception .retry_after ))
103
100
elif isinstance (exception , commands .MaxConcurrencyReached ):
104
- types = {discord .ext .commands .BucketType .default : "`Global`" , discord .ext .commands .BucketType .guild : "`Guild`" ,
105
- discord .ext .commands .BucketType .channel : "`Channel`" , discord .ext .commands .BucketType .category : "`Category`" ,
101
+ types = {discord .ext .commands .BucketType .default : "`Global`" ,
102
+ discord .ext .commands .BucketType .guild : "`Guild`" ,
103
+ discord .ext .commands .BucketType .channel : "`Channel`" ,
104
+ discord .ext .commands .BucketType .category : "`Category`" ,
106
105
discord .ext .commands .BucketType .member : "`Member`" , discord .ext .commands .BucketType .user : "`User`" }
107
106
await context .send (
108
107
'{}, That command has exceeded the max {} concurrency limit of `{}` instance! Please try again later.' .format (
109
108
context .author .mention , types [exception .per ], exception .number ))
110
109
elif isinstance (exception , (commands .CommandNotFound , InvalidContext )):
111
110
pass # Silent ignore
112
111
else :
113
- await context .send ('```\n %s\n ```' % '' .join (traceback .format_exception_only (type (exception ), exception )).strip ())
112
+ await context .send (
113
+ '```\n %s\n ```' % '' .join (traceback .format_exception_only (type (exception ), exception )).strip ())
114
114
if isinstance (context .channel , discord .TextChannel ):
115
115
DOZER_LOGGER .error ('Error in command <%d> (%d.name!r(%d.id) %d(%d.id) %d(%d.id) %d)' ,
116
116
context .command , context .guild , context .guild , context .channel , context .channel ,
117
117
context .author , context .author , context .message .content )
118
118
else :
119
- DOZER_LOGGER .error ('Error in command <%d> (DM %d(%d.id) %d)' , context .command , context .channel .recipient ,
119
+ DOZER_LOGGER .error ('Error in command <%d> (DM %d(%d.id) %d)' , context .command ,
120
+ context .channel .recipient ,
120
121
context .channel .recipient , context .message .content )
121
122
DOZER_LOGGER .error ('' .join (traceback .format_exception (type (exception ), exception , exception .__traceback__ )))
122
123
@@ -126,12 +127,12 @@ async def on_error(self, event_method, *args, **kwargs):
126
127
traceback .print_exc ()
127
128
capture_exception ()
128
129
129
- async def on_slash_command_error (self , ctx , ex ):
130
+ async def on_slash_command_error (self , ctx : DozerContext , ex : Exception ):
130
131
"""Passes slash command errors to primary command handler"""
131
132
await self .on_command_error (ctx , ex )
132
133
133
134
@staticmethod
134
- def format_error (ctx , err , * , word_re = re .compile ('[A-Z][a-z]+' )):
135
+ def format_error (ctx : DozerContext , err : Exception , * , word_re : Pattern = re .compile ('[A-Z][a-z]+' )):
135
136
"""Turns an exception into a user-friendly (or -friendlier, at least) error message."""
136
137
type_words = word_re .findall (type (err ).__name__ )
137
138
type_msg = ' ' .join (map (str .lower , type_words ))
@@ -141,12 +142,12 @@ def format_error(ctx, err, *, word_re=re.compile('[A-Z][a-z]+')):
141
142
else :
142
143
return type_msg
143
144
144
- def global_checks (self , ctx ):
145
+ def global_checks (self , ctx : DozerContext ):
145
146
"""Checks that should be executed before passed to the command"""
146
147
if ctx .author .bot :
147
148
raise InvalidContext ('Bots cannot run commands!' )
148
149
retry_after = self ._global_cooldown .update_rate_limit ()
149
- if retry_after and not hasattr (ctx , "is_pseudo" ): # bypass ratelimit for su'ed commands
150
+ if retry_after and not hasattr (ctx , "is_pseudo" ): # bypass ratelimit for su'ed commands
150
151
raise InvalidContext ('Global rate-limit exceeded!' )
151
152
return True
152
153
@@ -155,7 +156,7 @@ def run(self, *args, **kwargs):
155
156
del self .config ['discord_token' ] # Prevent token dumping
156
157
super ().run (token )
157
158
158
- async def shutdown (self , restart = False ):
159
+ async def shutdown (self , restart : bool = False ):
159
160
"""Shuts down the bot"""
160
161
self ._restarting = restart
161
162
await self .logout ()
0 commit comments