From 3892debb02e11bb1e75e56537c839db911c8c79d Mon Sep 17 00:00:00 2001 From: Joey Hines Date: Fri, 16 Aug 2019 10:21:58 -0500 Subject: [PATCH] Added mod commands back into Geoffrey + This a bit of a hack, will be redone with the command model refactor --- GeoffreyBot/geoffrey.py | 45 +++++++++---- GeoffreyBot/geoffrey_mod_cmds.py | 107 +++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 12 deletions(-) create mode 100644 GeoffreyBot/geoffrey_mod_cmds.py diff --git a/GeoffreyBot/geoffrey.py b/GeoffreyBot/geoffrey.py index 1019ad4..3f6b3c6 100644 --- a/GeoffreyBot/geoffrey.py +++ b/GeoffreyBot/geoffrey.py @@ -7,7 +7,7 @@ import logging import time import traceback import sys -from GeoffreyBot.geoffrey_api import HandledError +from GeoffreyBot.util import HandledError from GeoffreyBot.geoffrey_formatter import format_message logger = logging.getLogger('GeoffreyBot') @@ -34,23 +34,30 @@ class GeoffreyBot(commands.Bot): command_list_url = base_url + '/GeoffreyApp/api/command/commands' logger.info("Connecting to the Geoffrey API... ") + + fail_count = 0 while True: try: 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() break except Exception: + if fail_count > 20: + print("Failed to connect to Geoffrey API!") + quit(-1) time.sleep(1) + fail_count += 1 self.prefix = setting['BOT_PREFIX'] self.error_users = setting['ERROR_USERS'] - self.admin_users = setting['MOD_RANKS'] + self.mod_ranks = setting['MOD_RANKS'] self.special_users = [] self.default_status = setting['STATUS'] super().__init__(command_prefix=self.prefix, description=description, case_insensitive=True, help_command=None) self.load_extension('GeoffreyBot.geoffrey_api') + self.load_extension('GeoffreyBot.geoffrey_mod_cmds') self.help_page = self.build_help_page() self.help_dict = self.build_help_dict() @@ -74,17 +81,17 @@ class GeoffreyBot(commands.Bot): async def on_command_error(self, ctx, error): error_str = "" - if hasattr(error, "original") and isinstance(error.original, HandledError): + 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): return elif isinstance(error, commands.errors.CommandNotFound): return - elif isinstance(error, commands.errors.BadArgument) or isinstance(error, - commands.errors.MissingRequiredArgument) or ( + elif isinstance(error, commands.errors.BadArgument) or isinstance(error, commands.MissingRequiredArgument) or ( 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:" - for line in self.help_dict[ctx.command.name]: - error_str += line + error_str = self.build_help_str(ctx.command.name, error_str) 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..." @@ -95,15 +102,19 @@ class GeoffreyBot(commands.Bot): if e == "TypeError": error_str = "Well bud, you got this far. Good job! But you still h*cked up the syntax:" - for line in self.help_dict[ctx.command.name]: - error_str += line + error_str = self.build_help_str(ctx.command.name, error_str) if error_str is '': + command_args = '' + if len(ctx.args) > 0: + if len(ctx.args[1].args) > 1: + command_args = ctx.args[1].args[2:] + else: + command_args = '' + await self.send_error_message( 'Geoffrey encountered unhandled exception: {} Command: **{}** Context: {}' - .format(error, - ctx.invoked_with, - ctx.args[1].args[2:])) + .format(error, ctx.invoked_with, command_args)) error_message = ["```python"] for tb in traceback.format_tb(error.original.__traceback__): @@ -119,6 +130,16 @@ class GeoffreyBot(commands.Bot): await ctx.message.channel.send('{} **Error Running Command:** {}'.format( ctx.message.author.mention, error_str)) + 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 + async def send_error_message(self, msg): for user_id in self.error_users: user = self.get_user(user_id) diff --git a/GeoffreyBot/geoffrey_mod_cmds.py b/GeoffreyBot/geoffrey_mod_cmds.py new file mode 100644 index 0000000..e81a932 --- /dev/null +++ b/GeoffreyBot/geoffrey_mod_cmds.py @@ -0,0 +1,107 @@ +from discord.ext import commands +from GeoffreyBot.DiscordHelperFunctions import * +from GeoffreyBot.util import run_command, HandledError + + +class GeoffreyModCommands(commands.Cog): + def __init__(self, bot): + self.bot = bot + self.base_url = bot.base_url + self.api_token = bot.api_token + + # Check if the user has permission to use mod commands + async def cog_check(self, ctx): + + if not hasattr(ctx.author, "roles"): + return False + + mod_ranks = self.bot.mod_ranks + + for role in ctx.author.roles: + for mod_rank in mod_ranks: + if role.id == mod_rank: + return True + + return False + + @commands.command(pass_context=True) + async def mod_delete(self, ctx, discord_uuid, *args): + """ + {}mod_delete + """ + name = get_name(args) + + errors = { + "LocationLookUpError": "That user does not have a location by the name **{}**.".format(name) + } + + location = await run_command(ctx, self.base_url, self.api_token, "POST", "delete", errors=errors, name=name, + discord_uuid=discord_uuid) + + await ctx.send("{}, **{}** has been deleted from Geoffrey".format(ctx.message.author.mention, location)) + + @commands.command(pass_context=True) + async def mod_delete_item(self, ctx, discord_uuid, item_name: str, *args): + """ + {}mod_delete_item + The Shop Name parameter is optional if you only have one location. + """ + + shop_name = get_name(args) + + errors = { + "LocationLookUpError": "no shop can be found by that name for the user.", + "EntryNameNotUniqueError": "Please specify the location name".format(item_name) + } + + shop = await run_command(ctx, self.base_url, self.api_token, "POST", "delete_item", errors=errors, + item=item_name, + shop_name=shop_name, discord_uuid=discord_uuid) + + await ctx.send("{}, **{}** has been deleted from {}.".format( + ctx.message.author.mention, item_name, shop["name"])) + + @commands.command(pass_conext=True) + async def mod_edit_name(self, ctx, discord_uuid, new_name: str, old_name: str): + """ + {}mod_edit_name + If the name has spaces in it, it must be wrapped in quotes. eg "Cool Shop 123" + """ + + errors = { + "EntryNameNotUniqueError": "a location is already called **{}**".format(old_name), + "LocationLookUpError": "That location can not be found**{}**".format( + old_name) + } + + location = await run_command(ctx, self.base_url, self.api_token, "POST", "edit_name", errors=errors, + loc_name=old_name, + new_name=new_name, discord_uuid=discord_uuid) + + await ctx.send("{}, **{}** has been renamed to **{}**.".format(ctx.message.author.mention, old_name, + location["name"])) + + @commands.command(pass_context=True) + async def mod_remove_resident(self, ctx, discord_uuid, resident_name, *args): + """ + {}remove_resident + The Town Name is optional if you only have one town. + """ + + town_name = get_name(args) + + errors = { + "ResidentNotFoundError": "{} is not in that town".format(resident_name), + "LocationLookUpError": "Town not found.".format(town_name) + } + + location = await run_command(ctx, self.base_url, self.api_token, "POST", "remove_resident", errors=errors, + resident_name=resident_name, + town_name=town_name, discord_uuid=discord_uuid) + + await ctx.send('{}, **{}** has been remove as a resident of **{}**'.format( + ctx.message.author.mention, resident_name, location["name"])) + + +def setup(bot): + bot.add_cog(GeoffreyModCommands(bot))