Passed
Push — master ( 95e0ba...ca4927 )
by Cyb3r
01:11
created

errors.ErrorsCog.ack_all()   A

Complexity

Conditions 3

Size

Total Lines 34
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

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