Passed
Pull Request — master (#50)
by Cyb3r
01:40
created

bot.cogs.errors   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 128
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 83
dl 0
loc 128
rs 10
c 0
b 0
f 0
wmc 15

4 Methods

Rating   Name   Duplication   Size   Complexity  
A ErrorsCog.__init__() 0 2 1
A ErrorsCog.ack_all() 0 27 3
B ErrorsCog.on_command_error() 0 45 8
A ErrorsCog.ack_error() 0 15 2

1 Function

Rating   Name   Duplication   Size   Complexity  
A setup() 0 3 1
1
"""Cogs that handles errors"""
2
import logging
3
import random
4
from datetime import datetime
5
6
import discord
7
from discord.ext import commands
8
from bot import utils
9
10
log = logging.getLogger("bot")
11
12
13
class ErrorsCog(commands.Cog, name="Errors"):
14
    """ErrorsCogs
15
    ---
16
17
    The cog that handles all errors.
18
19
    Commands:
20
    ---
21
    `ack-error`: Acknowledge an error by ID
22
23
    Arguments:
24
    ---
25
        bot {discord.commands.Bot} -- The bot
26
    """
27
28
    def __init__(self, bot):
29
        self.bot = bot
30
31
    @commands.command(name="ack-error", help="Acknowledge an error to stop it from appearing")
32
    @commands.check(utils.check_admin)
33
    async def ack_error(self, ctx: commands.Context, error_id: str):
34
        """Acknowledge an error to prevent it from appearing"""
35
        error = await utils.select("errors", "id", "id", error_id)
36
        if not error:
37
            return await ctx.send(f"Error {error_id} not found")
38
        await utils.update(
39
            table="errors",
40
            where_column="id",
41
            where_value=error_id,
42
            column="ack",
43
            new_value=True,
44
        )
45
        await ctx.send(f"Error {error_id} has been acknowledged")
46
47
    @commands.command(name="ack-all", help="Acknowledge all errors")
48
    @commands.check(utils.check_admin)
49
    async def ack_all(self, ctx: commands.Context):
50
        """Acknowledge all currently unacknowledged errors"""
51
        errors = await utils.select(
52
            table="errors", column="id", where_column="ack", where_value=False
53
        )
54
        if not errors:
55
            return await ctx.send("No errors need acknowledging")
56
        error_count = 0
57
        for error in errors:
58
            await utils.update(
59
                table="errors",
60
                where_column="id",
61
                where_value=error,
62
                column="ack",
63
                new_value=True,
64
            )
65
            log.debug(
66
                "Acknowledged error {} as part of bulk acknowledgement by {}".format(
67
                    error, ctx.author.display_name
68
                )
69
            )
70
            error_count += 1
71
        await ctx.send(
72
            (
73
                "All errors have been acknowledged."
74
                f"Total: {str(error_count)}\nError Numbers: {', '.join(map(str, errors))}"
75
            )
76
        )
77
78
    @commands.Cog.listener()
79
    async def on_command_error(self, ctx: commands.Context, error):
80
        """Report errors to users"""
81
82
        if isinstance(error, commands.DisabledCommand):
83
            await utils.error_message(ctx, message=f"{ctx.command} has been disabled.")
84
85
        elif isinstance(error, commands.NoPrivateMessage):
86
            try:
87
                await ctx.author.send(f"{ctx.command} can not be used in Private Messages.")
88
            except discord.HTTPException:
89
                pass
90
91
        if isinstance(error, (commands.errors.MissingRole, commands.errors.CheckFailure)):
92
            error_msg = "You do not have the correct role for this command."
93
        elif isinstance(error, commands.errors.CommandNotFound):
94
            return
95
        elif isinstance(error, commands.MissingRequiredArgument):
96
            error_msg = f"`{ctx.message.content}` has missing required arguments"
97
        else:
98
            errors = await utils.fetch("errors", "id")
99
            error_id = random.randint(1, 32767)  # nosec
100
            while error_id in errors:
101
                log.warning("Error ID had to be regenerated")
102
                error_id = random.randint(1, 32767)  # nosec
103
104
            log.error((error_id, error))
105
            log.exception(error, exc_info=True)
106
            error_msg = (
107
                "There was an unknown error.\n"
108
                "Please report it for investigation.\n"
109
                "Error #{}".format(error_id)
110
            )
111
            log.error("There was the following error: {}".format(error))
112
            error_info = [
113
                error_id,
114
                ctx.message.content,
115
                f"COG: {ctx.command.cog.qualified_name} COMMAND: {ctx.command.name}",
116
                str(error),
117
                datetime.utcnow(),
118
                False,
119
            ]
120
            await utils.insert("errors", error_info)
121
122
        await utils.make_embed(ctx, "FF0000", title="Error:", description=error_msg)
123
124
125
def setup(bot):
126
    """Needed for extension loading"""
127
    bot.add_cog(ErrorsCog(bot))
128