Geoffrey-Django/api/discord_bot/bot.py

168 lines
6.7 KiB
Python

import asyncio
import logging
from discord import Game
from discord.ext import commands
from discord.utils import oauth_url
import logging.handlers as handlers
from sys import stdout
from os import path
from GeoffreyApp.api.discord_bot.BotErrors import *
from GeoffreyApp.api.commands import *
from django.conf import settings
logger = logging.getLogger(__name__)
description = '''
Geoffrey (pronounced JOFF-ree) started his life as an inside joke none of you will understand.
At some point, she was to become an airhorn discord_bot. Now, they know where your stuff is.
Please respect Geoffrey, the discord_bot is very sensitive.
All commands must be prefaced with '?'
If have a suggestion or if something is borked, you can PM my ding dong of a creator BirbHD.
*You must use ?register before adding things to Geoffrey*
For a better a explanation on how this discord_bot works go the following link:
https://github.com/joeyahines/Geoffrey/blob/master/README.md
'''
bad_error_message = 'OOPSIE WOOPSIE!! Uwu We made a fucky wucky!! A wittle fucko boingo! The admins at our ' \
'headquarters are working VEWY HAWD to fix this! (Error in command {})'
extensions = []
'''
extensions = ['GeoffreyApp.cogs.Add_Commands',
'GeoffreyApp.cogs.Delete_Commands',
'GeoffreyApp.cogs.Edit_Commands',
'GeoffreyApp.cogs.Search_Commands',
'GeoffreyApp.cogs.Admin_Commands']
'''
class GeoffreyBot(commands.Bot):
def __init__(self):
super().__init__(command_prefix=getattr(settings, 'BOT_PREFIX', '?'), description=description, pm_help=True, case_insensitive=True)
self.error_users = getattr(settings, 'ERROR_USERS', [])
self.admin_users = getattr(settings, 'MOD_RANK', [])
self.special_users = getattr(settings, 'SPECIAL_USERS', [])
self.default_status = getattr(settings, 'DEFAULT_STATUS', 'sed')
for extension in extensions:
try:
self.load_extension(extension)
except Exception as e:
logger.info('Failed to load extension {}'.format(extension))
raise e
async def on_ready(self):
logger.info("%s Online, ID: %s", self.user.name, self.user.id)
info = await self.application_info()
url = oauth_url(info.id)
logger.info("Bot url: %s", url)
await self.change_presence(activity=Game(self.default_status))
async def on_command(self, ctx):
if ctx.invoked_subcommand is None:
subcommand = ""
else:
subcommand = ":" + ctx.invoked_subcommand.__str__()
logger.info("User %s, used command %s%s with context: %s", ctx.message.author, ctx.command.name, subcommand,
ctx.args)
if ctx.invoked_with.lower() == 'help' and ctx.message.guild is not None:
await ctx.send("{}, I sent you some help in the DMs.".format(ctx.message.author.mention))
async def on_command_error(self, ctx, error):
error_str = ''
if hasattr(ctx, 'cog'):
if "Admin_Commands" in ctx.cog.__str__():
return
if hasattr(error, 'original'):
if isinstance(error.original, NoPermissionError):
error_str = 'You don\'t have permission for that cool command.'
elif isinstance(error.original, UsernameLookupFailed):
error_str = 'Your user name was not found, either Mojang is having a fucky wucky ' \
'or your nickname is not set correctly. *stares at the Mods*'
elif isinstance(error.original, PlayerNotFound):
error_str = 'Make sure to use ?register first you ding dong.'
elif isinstance(error.original, EntryNameNotUniqueError):
error_str = 'An entry in the database already has that name you ding dong.'
elif isinstance(error.original, DatabaseValueError):
error_str = 'Use a shorter name or a smaller value, dong ding.'
elif isinstance(error.original, NotOnServerError):
error_str = 'Command needs to be run on 24CC. Run this command there whoever you are.'.format()
elif isinstance(error.original, EmptryString):
error_str = 'Do not not pass empty string to Geoffrey. Ding dong.'
elif isinstance(error, commands.CommandOnCooldown):
return
elif isinstance(error, commands.UserInputError):
error_str = 'Invalid syntax for **{}** you ding dong:' \
.format(ctx.invoked_with, ctx.invoked_with)
pages = await self.formatter.format_help_for(ctx, ctx.command)
for page in pages:
error_str = error_str + '\n' + page
elif isinstance(error, commands.CommandNotFound):
return
if error_str is '':
await self.send_error_message(
'Geoffrey encountered unhandled exception: {} Command: **{}** Context: {}'.format(error,
ctx.command.name,
ctx.args))
error_str = bad_error_message.format(ctx.invoked_with)
logger.error("Geoffrey encountered exception: %s", error)
await ctx.message.channel.send('{} **Error Running Command:** {}'.format(
ctx.message.author.mention, error_str))
async def send_error_message(self, msg):
for user_id in self.error_users:
user = await self.get_user_info(user_id)
await user.send(msg)
def setup_logging():
discord_logger = logging.getLogger('discord')
discord_logger.setLevel(logging.INFO)
bot_info_logger = logging.getLogger('GeoffreyApp.api.discord_bot.discord_bot')
bot_info_logger.setLevel(logging.INFO)
console = logging.StreamHandler(stdout)
console.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(name)s: %(message)s'))
bot_info_logger.addHandler(console)
def start_bot():
asyncio.set_event_loop(asyncio.new_event_loop())
bot = None
try:
bot = GeoffreyBot()
@bot.command(pass_context=True)
async def test(ctx):
"""
Checks if the discord_bot is alive.
"""
await ctx.send('I\'m here you ding dong')
setup_logging()
bot.run(getattr(settings, 'DISCORD_TOKEN'))
except KeyboardInterrupt:
logger.info("Bot received keyboard interrupt")
except Exception as e:
print(e)
logger.info('Bot encountered the following unhandled exception %s', e)
finally:
if bot is not None:
bot.loop.stop()
logger.info("Bot shutting down...")