2019-01-14 20:20:16 +00:00
|
|
|
from discord import Game
|
|
|
|
from discord.ext import commands
|
2019-01-31 19:56:50 +00:00
|
|
|
from requests import exceptions as request_exception
|
2019-01-14 20:20:16 +00:00
|
|
|
from discord.utils import oauth_url
|
|
|
|
import requests
|
|
|
|
import logging
|
|
|
|
import time
|
|
|
|
import traceback
|
|
|
|
import sys
|
2019-08-16 15:21:58 +00:00
|
|
|
from GeoffreyBot.util import HandledError
|
2019-07-26 23:17:46 +00:00
|
|
|
from GeoffreyBot.geoffrey_formatter import format_message
|
2019-01-14 20:20:16 +00:00
|
|
|
|
|
|
|
logger = logging.getLogger('GeoffreyBot')
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
If have a suggestion or if something is borked, you can PM my ding dong of a creator ZeroHD.
|
|
|
|
|
|
|
|
*You must use ?register before adding things to Geoffrey*
|
|
|
|
'''
|
|
|
|
|
|
|
|
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 {})'
|
|
|
|
|
|
|
|
|
|
|
|
class GeoffreyBot(commands.Bot):
|
|
|
|
def __init__(self, base_url, api_token):
|
|
|
|
self.base_url = base_url
|
|
|
|
self.api_token = api_token
|
|
|
|
|
2019-05-11 16:45:55 +00:00
|
|
|
settings_url = base_url + '/GeoffreyApp/api/settings/'
|
|
|
|
command_list_url = base_url + '/GeoffreyApp/api/command/commands'
|
2019-01-14 20:20:16 +00:00
|
|
|
|
|
|
|
logger.info("Connecting to the Geoffrey API... ")
|
2019-08-16 15:21:58 +00:00
|
|
|
|
|
|
|
fail_count = 0
|
2019-01-14 20:20:16 +00:00
|
|
|
while True:
|
|
|
|
try:
|
2019-01-28 02:35:17 +00:00
|
|
|
setting = requests.get(url=settings_url, params={"api": self.api_token}).json()
|
|
|
|
self.command_list = requests.get(url=command_list_url, params={"api": self.api_token}).json()
|
2019-01-14 20:20:16 +00:00
|
|
|
break
|
|
|
|
except Exception:
|
2019-08-16 15:21:58 +00:00
|
|
|
if fail_count > 20:
|
|
|
|
print("Failed to connect to Geoffrey API!")
|
|
|
|
quit(-1)
|
2019-01-14 20:20:16 +00:00
|
|
|
time.sleep(1)
|
2019-08-16 15:21:58 +00:00
|
|
|
fail_count += 1
|
2019-01-14 20:20:16 +00:00
|
|
|
|
|
|
|
self.prefix = setting['BOT_PREFIX']
|
|
|
|
self.error_users = setting['ERROR_USERS']
|
2019-08-16 15:21:58 +00:00
|
|
|
self.mod_ranks = setting['MOD_RANKS']
|
2019-01-14 20:20:16 +00:00
|
|
|
self.special_users = []
|
|
|
|
self.default_status = setting['STATUS']
|
|
|
|
|
2019-04-10 19:08:39 +00:00
|
|
|
super().__init__(command_prefix=self.prefix, description=description, case_insensitive=True, help_command=None)
|
2019-01-14 20:20:16 +00:00
|
|
|
|
|
|
|
self.load_extension('GeoffreyBot.geoffrey_api')
|
2019-08-16 15:21:58 +00:00
|
|
|
self.load_extension('GeoffreyBot.geoffrey_mod_cmds')
|
2019-01-14 20:20:16 +00:00
|
|
|
|
2019-01-28 02:35:17 +00:00
|
|
|
self.help_page = self.build_help_page()
|
|
|
|
self.help_dict = self.build_help_dict()
|
|
|
|
|
2019-01-14 20:20:16 +00:00
|
|
|
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__()
|
|
|
|
|
2019-01-31 19:56:50 +00:00
|
|
|
logger.info("User %s, used command '%s%s' with arguments: %s", ctx.message.author, ctx.command.name, subcommand,
|
|
|
|
ctx.args[2:])
|
2019-01-14 20:20:16 +00:00
|
|
|
|
|
|
|
async def on_command_error(self, ctx, error):
|
|
|
|
error_str = ""
|
2019-05-10 21:22:10 +00:00
|
|
|
|
2019-08-16 15:21:58 +00:00
|
|
|
if isinstance(error, commands.CheckFailure):
|
|
|
|
error_str = "You do not have permission to run that whacky command dog."
|
|
|
|
elif hasattr(error, "original") and isinstance(error.original, HandledError):
|
2019-05-10 21:22:10 +00:00
|
|
|
return
|
|
|
|
elif isinstance(error, commands.errors.CommandNotFound):
|
2019-01-14 20:20:16 +00:00
|
|
|
return
|
2019-08-16 15:21:58 +00:00
|
|
|
elif isinstance(error, commands.errors.BadArgument) or isinstance(error, commands.MissingRequiredArgument) or (
|
2019-05-10 21:22:10 +00:00
|
|
|
hasattr(error, "original") and isinstance(error.original, ValueError)):
|
|
|
|
error_str = "Well bud, you got this far. Good job! But you still h*cked up the syntax:"
|
|
|
|
|
2019-08-16 15:21:58 +00:00
|
|
|
error_str = self.build_help_str(ctx.command.name, error_str)
|
2019-05-10 21:22:10 +00:00
|
|
|
|
2019-01-31 19:56:50 +00:00
|
|
|
elif hasattr(error, "original") and isinstance(error.original, request_exception.ConnectionError):
|
|
|
|
error_str = "Unable to connect to the database. Hopefully someone is working on this..."
|
2019-05-10 21:22:10 +00:00
|
|
|
await self.send_error_message("Can't connect to the GeoffreyAPI, is it offline?")
|
2019-05-14 13:02:14 +00:00
|
|
|
elif hasattr(error, "original"):
|
|
|
|
e = error.original.args[0]
|
|
|
|
|
|
|
|
if e == "TypeError":
|
|
|
|
error_str = "Well bud, you got this far. Good job! But you still h*cked up the syntax:"
|
|
|
|
|
2019-08-16 15:21:58 +00:00
|
|
|
error_str = self.build_help_str(ctx.command.name, error_str)
|
2019-01-14 20:20:16 +00:00
|
|
|
|
|
|
|
if error_str is '':
|
2019-08-16 15:21:58 +00:00
|
|
|
command_args = ''
|
|
|
|
if len(ctx.args) > 0:
|
|
|
|
if len(ctx.args[1].args) > 1:
|
|
|
|
command_args = ctx.args[1].args[2:]
|
|
|
|
else:
|
|
|
|
command_args = ''
|
|
|
|
|
2019-01-14 20:20:16 +00:00
|
|
|
await self.send_error_message(
|
2019-01-31 19:56:50 +00:00
|
|
|
'Geoffrey encountered unhandled exception: {} Command: **{}** Context: {}'
|
2019-08-16 15:21:58 +00:00
|
|
|
.format(error, ctx.invoked_with, command_args))
|
2019-01-31 19:56:50 +00:00
|
|
|
|
2019-02-17 03:21:29 +00:00
|
|
|
error_message = ["```python"]
|
2019-01-31 19:56:50 +00:00
|
|
|
for tb in traceback.format_tb(error.original.__traceback__):
|
2019-02-17 03:21:29 +00:00
|
|
|
error_message.append(tb)
|
|
|
|
|
|
|
|
error_message.append("```")
|
2019-01-31 19:56:50 +00:00
|
|
|
|
2019-01-14 20:20:16 +00:00
|
|
|
error_str = bad_error_message.format(ctx.invoked_with)
|
|
|
|
|
|
|
|
logger.error("Geoffrey encountered exception: %s", error)
|
|
|
|
traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr)
|
|
|
|
|
|
|
|
await ctx.message.channel.send('{} **Error Running Command:** {}'.format(
|
|
|
|
ctx.message.author.mention, error_str))
|
|
|
|
|
2019-08-16 15:21:58 +00:00
|
|
|
def build_help_str(self, command_name, help_str=""):
|
|
|
|
|
|
|
|
if "mod_" in command_name:
|
|
|
|
return help_str
|
|
|
|
|
|
|
|
for line in self.help_dict[command_name]:
|
|
|
|
help_str += line
|
|
|
|
|
|
|
|
return help_str
|
|
|
|
|
2019-01-14 20:20:16 +00:00
|
|
|
async def send_error_message(self, msg):
|
|
|
|
for user_id in self.error_users:
|
2019-04-10 19:08:39 +00:00
|
|
|
user = self.get_user(user_id)
|
2019-02-17 03:21:29 +00:00
|
|
|
|
2019-05-13 14:52:15 +00:00
|
|
|
if user is None:
|
|
|
|
continue
|
|
|
|
|
2019-02-17 03:21:29 +00:00
|
|
|
if msg is list:
|
|
|
|
await self.send_list(user, msg)
|
|
|
|
else:
|
|
|
|
await user.send(msg)
|
2019-01-14 20:20:16 +00:00
|
|
|
|
|
|
|
def run_command(self, command, **kwargs):
|
2019-04-10 19:08:39 +00:00
|
|
|
url = self.base_url + '/api/command/{}'
|
2019-01-14 20:20:16 +00:00
|
|
|
|
2019-04-10 19:08:39 +00:00
|
|
|
return requests.get(url=url.format(command), params=kwargs).json()
|
2019-01-14 20:20:16 +00:00
|
|
|
|
2019-05-15 13:14:50 +00:00
|
|
|
@staticmethod
|
|
|
|
async def send_formatted_message(ctx, msg_format, *args, ping_user=False):
|
|
|
|
if ping_user:
|
|
|
|
msg_format = "%s %s" % (ctx.message.author, msg_format)
|
|
|
|
|
|
|
|
msg = format_message(msg_format, *args)
|
|
|
|
|
|
|
|
ctx.send(msg)
|
|
|
|
|
2019-04-10 19:08:39 +00:00
|
|
|
@staticmethod
|
|
|
|
async def send_list(ctx, send_list):
|
2019-01-14 20:20:16 +00:00
|
|
|
msg = ""
|
|
|
|
|
|
|
|
for s in send_list:
|
2019-05-14 02:05:37 +00:00
|
|
|
if (len(msg) + len(s)) > 2000:
|
2019-01-14 20:20:16 +00:00
|
|
|
await ctx.send(msg)
|
|
|
|
msg = s
|
|
|
|
else:
|
|
|
|
msg = msg + '\n' + s
|
|
|
|
|
|
|
|
if len(msg) > 0:
|
|
|
|
await ctx.send(msg)
|
2019-01-28 02:35:17 +00:00
|
|
|
|
|
|
|
def build_help_page(self):
|
2019-05-11 16:57:44 +00:00
|
|
|
help_list = []
|
2019-01-28 02:35:17 +00:00
|
|
|
largest_command_size = 0
|
|
|
|
for command in self.command_list:
|
|
|
|
if largest_command_size < len(command["command"]):
|
|
|
|
largest_command_size = len(command["command"])
|
|
|
|
|
|
|
|
for line in self.description.split("\n"):
|
|
|
|
help_list.append(line)
|
|
|
|
|
|
|
|
help_list.append("\nCommands:")
|
|
|
|
for command in self.command_list:
|
|
|
|
name = command["command"].ljust(largest_command_size + 2)
|
|
|
|
help_list.append(" {}{}{}".format(self.prefix, name, command["help"]))
|
|
|
|
|
2019-04-10 19:08:39 +00:00
|
|
|
help_list.append("\nDo ?help <command name> to get more info on any of the commands above")
|
2019-05-11 16:57:44 +00:00
|
|
|
|
2019-01-28 02:35:17 +00:00
|
|
|
|
|
|
|
return help_list
|
|
|
|
|
|
|
|
def build_help_dict(self):
|
|
|
|
help_dict = {}
|
|
|
|
for command in self.command_list:
|
|
|
|
command_name = command["command"]
|
|
|
|
|
2019-04-10 19:08:39 +00:00
|
|
|
help_list = ['```', command["help"] + "\n"]
|
2019-01-28 02:35:17 +00:00
|
|
|
|
2019-02-17 03:21:29 +00:00
|
|
|
c = self.get_command(command_name)
|
|
|
|
|
|
|
|
if c is not None:
|
|
|
|
help_msg = c.help
|
|
|
|
help_list.append(help_msg.format(self.prefix))
|
2019-01-28 02:35:17 +00:00
|
|
|
|
|
|
|
help_list.append('```')
|
|
|
|
|
|
|
|
help_dict[command_name] = help_list
|
|
|
|
|
|
|
|
return help_dict
|