forked from ddnet/ddnet-discordbot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbot.py
126 lines (100 loc) · 4.23 KB
/
bot.py
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import logging
import traceback
from datetime import datetime
from typing import Optional
import aiohttp
import discord
from discord.ext import commands
log = logging.getLogger(__name__)
initial_extensions = (
'cogs.admin',
'cogs.github',
'cogs.guild_log',
'cogs.map_testing',
'cogs.meme',
'cogs.misc',
'cogs.moderator',
'cogs.profile',
'cogs.records',
'cogs.status',
'cogs.votes',
)
def get_traceback(error: Exception) -> str:
return ''.join(traceback.format_exception(type(error), error, error.__traceback__))
class DDNet(commands.Bot):
def __init__(self, **kwargs):
intents = discord.Intents(guilds=True, members=True, emojis=True, messages=True, reactions=True)
super().__init__(command_prefix='$', fetch_offline_members=True, help_command=commands.MinimalHelpCommand(), intents=intents)
self.config = kwargs.pop('config')
self.pool = kwargs.pop('pool')
self.session = kwargs.pop('session')
for extension in initial_extensions:
try:
self.load_extension(extension)
except Exception:
log.exception('Failed to load extension %r', extension)
else:
log.info('Successfully loaded extension %r', extension)
self.start_time = datetime.utcnow()
self.add_check(self.global_check)
async def on_ready(self):
log.info('Logged in as %s (ID: %d)', self.user, self.user.id)
async def on_resumed(self):
log.info('Resumed')
async def close(self):
log.info('Closing')
await super().close()
await self.pool.close()
await self.session.close()
async def on_message(self, message: discord.Message):
await self.wait_until_ready()
await self.process_commands(message)
def global_check(self, ctx: commands.Context) -> bool:
return ctx.guild is None or ctx.channel.permissions_for(ctx.guild.me).send_messages
async def on_command(self, ctx: commands.Context):
if ctx.guild is None:
destination = 'Private Message'
guild_id = None
else:
destination = f'#{ctx.channel} ({ctx.guild})'
guild_id = ctx.guild.id
log.info('%s used command in %s: %s', ctx.author, destination, ctx.message.content)
query = """INSERT INTO stats_commands (guild_id, channel_id, author_id, timestamp, command)
VALUES ($1, $2, $3, $4, $5);
"""
values = (
guild_id,
ctx.channel.id,
ctx.author.id,
ctx.message.created_at,
ctx.command.qualified_name
)
await self.pool.execute(query, *values)
async def on_command_error(self, ctx: commands.Context, error: commands.CommandError):
command = ctx.command
msg = None
if isinstance(error, commands.MissingRequiredArgument):
msg = f'{self.command_prefix}{command.qualified_name} {command.signature}'
elif isinstance(error, commands.CommandInvokeError):
if isinstance(error.original, discord.Forbidden):
msg = 'I do not have proper permission'
elif isinstance(error.original, discord.HTTPException) and error.original.code == 40005:
msg = 'File is too large to upload'
else:
trace = get_traceback(error.original)
log.error('Command %r caused an exception\n%s', command.qualified_name, trace)
if isinstance(error.original, aiohttp.ClientConnectorError):
msg = 'Could not fetch/send data'
else:
msg = 'An internal error occurred'
if msg is not None:
try:
await ctx.send(msg)
except discord.Forbidden:
pass
async def on_error(self, event: str, *args, **kwargs):
log.exception('Event %r caused an exception', event)
def get_message(self, message_id: int) -> Optional[discord.Message]:
return discord.utils.get(self.cached_messages, id=message_id)