aboutsummaryrefslogtreecommitdiffstats
path: root/bot/seasons/evergreen
diff options
context:
space:
mode:
Diffstat (limited to 'bot/seasons/evergreen')
-rw-r--r--bot/seasons/evergreen/error_handler.py104
-rw-r--r--bot/seasons/evergreen/fun.py4
-rw-r--r--bot/seasons/evergreen/magic_8ball.py36
-rw-r--r--bot/seasons/evergreen/snakes/__init__.py2
-rw-r--r--bot/seasons/evergreen/snakes/snakes_cog.py9
-rw-r--r--bot/seasons/evergreen/snakes/utils.py2
-rw-r--r--bot/seasons/evergreen/uptime.py4
7 files changed, 92 insertions, 69 deletions
diff --git a/bot/seasons/evergreen/error_handler.py b/bot/seasons/evergreen/error_handler.py
index 47e18a31..7774f06e 100644
--- a/bot/seasons/evergreen/error_handler.py
+++ b/bot/seasons/evergreen/error_handler.py
@@ -8,105 +8,97 @@ from discord.ext import commands
log = logging.getLogger(__name__)
-class CommandErrorHandler:
+class CommandErrorHandler(commands.Cog):
"""A error handler for the PythonDiscord server!"""
def __init__(self, bot):
self.bot = bot
+ @staticmethod
+ def revert_cooldown_counter(command, message):
+ """Undoes the last cooldown counter for user-error cases."""
+ if command._buckets.valid:
+ bucket = command._buckets.get_bucket(message)
+ bucket._tokens = min(bucket.rate, bucket._tokens + 1)
+ logging.debug(
+ "Cooldown counter reverted as the command was not used correctly."
+ )
+
+ @commands.Cog.listener()
async def on_command_error(self, ctx, error):
"""Activates when a command opens an error"""
if hasattr(ctx.command, 'on_error'):
return logging.debug(
- "A command error occured but "
- "the command had it's own error handler"
+ "A command error occured but the command had it's own error handler."
)
+
error = getattr(error, 'original', error)
+
if isinstance(error, commands.CommandNotFound):
return logging.debug(
- f"{ctx.author} called '{ctx.message.content}' "
- "but no command was found"
+ f"{ctx.author} called '{ctx.message.content}' but no command was found."
)
+
if isinstance(error, commands.UserInputError):
logging.debug(
- f"{ctx.author} called the command '{ctx.command}' "
- "but entered invalid input!"
+ f"{ctx.author} called the command '{ctx.command}' but entered invalid input!"
)
+
+ self.revert_cooldown_counter(ctx.command, ctx.message)
+
return await ctx.send(
- ":no_entry: The command you specified failed to run."
+ ":no_entry: The command you specified failed to run. "
"This is because the arguments you provided were invalid."
)
+
if isinstance(error, commands.CommandOnCooldown):
logging.debug(
- f"{ctx.author} called the command '{ctx.command}' "
- "but they were on cooldown!"
+ f"{ctx.author} called the command '{ctx.command}' but they were on cooldown!"
)
- seconds = error.retry_after
- remaining_minutes, remaining_seconds = divmod(seconds, 60)
- time_remaining = f'{int(remaining_minutes)} minutes {math.ceil(remaining_seconds)} seconds'
+ remaining_minutes, remaining_seconds = divmod(error.retry_after, 60)
+
return await ctx.send(
- "This command is on cooldown,"
- f" please retry in {time_remaining}."
+ "This command is on cooldown, please retry in "
+ f"{int(remaining_minutes)} minutes {math.ceil(remaining_seconds)} seconds."
)
+
if isinstance(error, commands.DisabledCommand):
logging.debug(
- f"{ctx.author} called the command '{ctx.command}' "
- "but the command was disabled!"
- )
- return await ctx.send(
- ":no_entry: This command has been disabled."
+ f"{ctx.author} called the command '{ctx.command}' but the command was disabled!"
)
+ return await ctx.send(":no_entry: This command has been disabled.")
+
if isinstance(error, commands.NoPrivateMessage):
logging.debug(
f"{ctx.author} called the command '{ctx.command}' "
"in a private message however the command was guild only!"
)
- return await ctx.author.send(
- ":no_entry: This command can only be used inside a server."
- )
+ return await ctx.author.send(":no_entry: This command can only be used in the server.")
+
if isinstance(error, commands.BadArgument):
- if ctx.command.qualified_name == 'tag list':
- logging.debug(
- f"{ctx.author} called the command '{ctx.command}' "
- "but entered an invalid user!"
- )
- return await ctx.send(
- "I could not find that member. Please try again."
- )
- else:
- logging.debug(
- f"{ctx.author} called the command '{ctx.command}' "
- "but entered a bad argument!"
- )
- return await ctx.send(
- "The argument you provided was invalid."
- )
- if isinstance(error, commands.CheckFailure):
+ self.revert_cooldown_counter(ctx.command, ctx.message)
+
logging.debug(
- f"{ctx.author} called the command '{ctx.command}' "
- "but the checks failed!"
- )
- return await ctx.send(
- ":no_entry: You are not authorized to use this command."
+ f"{ctx.author} called the command '{ctx.command}' but entered a bad argument!"
)
- print(
- f"Ignoring exception in command {ctx.command}:",
- file=sys.stderr
- )
+ return await ctx.send("The argument you provided was invalid.")
+
+ if isinstance(error, commands.CheckFailure):
+ logging.debug(f"{ctx.author} called the command '{ctx.command}' but the checks failed!")
+ return await ctx.send(":no_entry: You are not authorized to use this command.")
+
+ print(f"Ignoring exception in command {ctx.command}:", file=sys.stderr)
+
logging.warning(
f"{ctx.author} called the command '{ctx.command}' "
"however the command failed to run with the error:"
f"-------------\n{error}"
)
- traceback.print_exception(
- type(error),
- error,
- error.__traceback__,
- file=sys.stderr
- )
+
+ traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr)
def setup(bot):
bot.add_cog(CommandErrorHandler(bot))
- log.debug("CommandErrorHandler cog loaded")
+ log.info("CommandErrorHandler cog loaded")
diff --git a/bot/seasons/evergreen/fun.py b/bot/seasons/evergreen/fun.py
index 4da01dd1..9ef47331 100644
--- a/bot/seasons/evergreen/fun.py
+++ b/bot/seasons/evergreen/fun.py
@@ -8,7 +8,7 @@ from bot.constants import Emojis
log = logging.getLogger(__name__)
-class Fun:
+class Fun(commands.Cog):
"""
A collection of general commands for fun.
"""
@@ -35,4 +35,4 @@ class Fun:
# Required in order to load the cog, use the class name in the add_cog function.
def setup(bot):
bot.add_cog(Fun(bot))
- log.debug("Fun cog loaded")
+ log.info("Fun cog loaded")
diff --git a/bot/seasons/evergreen/magic_8ball.py b/bot/seasons/evergreen/magic_8ball.py
new file mode 100644
index 00000000..88c9fd26
--- /dev/null
+++ b/bot/seasons/evergreen/magic_8ball.py
@@ -0,0 +1,36 @@
+import json
+import logging
+import random
+from pathlib import Path
+
+from discord.ext import commands
+
+log = logging.getLogger(__name__)
+
+
+class Magic8ball:
+ """
+ A Magic 8ball command to respond to a users question.
+ """
+
+ def __init__(self, bot):
+ self.bot = bot
+ with open(Path("bot", "resources", "evergreen", "magic8ball.json"), "r") as file:
+ self.answers = json.load(file)
+
+ @commands.command(name="8ball")
+ async def output_answer(self, ctx, *, question):
+ """
+ Return a magic 8 ball answer from answers list.
+ """
+ if len(question.split()) >= 3:
+ answer = random.choice(self.answers)
+ await ctx.send(answer)
+ else:
+ await ctx.send("Usage: .8ball <question> (minimum length of 3 eg: `will I win?`)")
+
+
+# Required in order to load the cog, use the class name in the add_cog function.
+def setup(bot):
+ bot.add_cog(Magic8ball(bot))
+ log.info("Magic 8ball cog loaded")
diff --git a/bot/seasons/evergreen/snakes/__init__.py b/bot/seasons/evergreen/snakes/__init__.py
index 367aea4d..6fb1f673 100644
--- a/bot/seasons/evergreen/snakes/__init__.py
+++ b/bot/seasons/evergreen/snakes/__init__.py
@@ -7,4 +7,4 @@ log = logging.getLogger(__name__)
def setup(bot):
bot.add_cog(Snakes(bot))
- log.info("Cog loaded: Snakes")
+ log.info("Snakes cog loaded")
diff --git a/bot/seasons/evergreen/snakes/snakes_cog.py b/bot/seasons/evergreen/snakes/snakes_cog.py
index 57eb7a52..74d2ab4f 100644
--- a/bot/seasons/evergreen/snakes/snakes_cog.py
+++ b/bot/seasons/evergreen/snakes/snakes_cog.py
@@ -15,7 +15,7 @@ import aiohttp
import async_timeout
from PIL import Image, ImageDraw, ImageFont
from discord import Colour, Embed, File, Member, Message, Reaction
-from discord.ext.commands import BadArgument, Bot, Context, bot_has_permissions, group
+from discord.ext.commands import BadArgument, Bot, Cog, Context, bot_has_permissions, group
from bot.constants import ERROR_REPLIES, Tokens
from bot.decorators import locked
@@ -132,7 +132,7 @@ CARD = {
# endregion
-class Snakes:
+class Snakes(Cog):
"""
Commands related to snakes. These were created by our
community during the first code jam.
@@ -1187,8 +1187,3 @@ class Snakes:
await ctx.send(embed=embed)
# endregion
-
-
-def setup(bot):
- bot.add_cog(Snakes(bot))
- log.info("Cog loaded: Snakes")
diff --git a/bot/seasons/evergreen/snakes/utils.py b/bot/seasons/evergreen/snakes/utils.py
index 605c7ef3..ec280223 100644
--- a/bot/seasons/evergreen/snakes/utils.py
+++ b/bot/seasons/evergreen/snakes/utils.py
@@ -117,7 +117,7 @@ ANGLE_RANGE = math.pi * 2
def get_resource(file: str) -> List[dict]:
- with (SNAKE_RESOURCES / f"{file}.json").open() as snakefile:
+ with (SNAKE_RESOURCES / f"{file}.json").open(encoding="utf-8") as snakefile:
return json.load(snakefile)
diff --git a/bot/seasons/evergreen/uptime.py b/bot/seasons/evergreen/uptime.py
index 1321da19..3d2c7d03 100644
--- a/bot/seasons/evergreen/uptime.py
+++ b/bot/seasons/evergreen/uptime.py
@@ -9,7 +9,7 @@ from bot import start_time
log = logging.getLogger(__name__)
-class Uptime:
+class Uptime(commands.Cog):
"""
A cog for posting the bots uptime.
"""
@@ -35,4 +35,4 @@ class Uptime:
# Required in order to load the cog, use the class name in the add_cog function.
def setup(bot):
bot.add_cog(Uptime(bot))
- log.debug("Uptime cog loaded")
+ log.info("Uptime cog loaded")