1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
import discord
import config
def istrue(value, key):
return hasattr(value, key) and getattr(value, key)
class Context:
def __init__(self, msg, args):
self.msg = msg
self.args = args
async def answer(self, value):
await self.msg.channel.send(f'{self.msg.author.mention} {value}')
class CommandClientMeta(type):
def __new__(cls, name, bases, dct):
commands = []
for item in dct.copy().values():
if callable(item) and istrue(item, 'command'):
if istrue(item, 'help_command'):
dct['help_command'] = item
commands.append(item)
dct['commands'] = commands
return super().__new__(cls, name, bases, dct)
class CommandClient(discord.Client, metaclass=CommandClientMeta):
def get_commands(self):
return type(self).commands.copy()
async def run_help(self, ctx):
return await type(self).help_command(self, ctx)
async def on_message(self, msg):
text = msg.content.strip()
if not text.startswith(config.COMMAND_PREFIX):
return
try:
cmd, *args = [v for v in text[len(config.COMMAND_PREFIX):].split(' ') if v]
except ValueError:
return await self.run_help(Context(msg, []))
ctx = Context(msg, args)
for command in self.get_commands():
if cmd in command.names:
return await command(self, ctx)
return await self.run_help(ctx)
class Command:
@classmethod
def names(cls, *names):
def meta(f):
f.command = True
f.names = names
return f
return meta
@classmethod
def description(cls, *names):
def meta(f):
f.command = True
f.names = names
return f
return meta
@classmethod
def help_command(cls, f):
f.help_command = True
return f
|