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

bot.cogs.health.HealthCog.__init__()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
"""Cog the preforms health functions"""
2
from datetime import datetime
3
import logging
4
from discord.ext import commands
5
import discord
6
from bot import utils
7
8
log = logging.getLogger("bot")
9
10
11
async def managed_role_check(role: discord.Role):
12
    """managed_role_check
13
    ---
14
15
    Checks to see if the updated one was one that the bot cares about.
16
17
    Arguments:
18
        role {discord.Role} -- [description]
19
20
    Returns:
21
        bool -- returns True if the role was cared about or does not return.
22
    """
23
    for table in ["schools", "regions"]:
24
        if await utils.select(table, "id", "id", role.id):
25
            return True, table
26
    return False, "error"
27
28
29
class HealthCog(commands.Cog, name="Health"):
30
    """HealthCog
31
    ---
32
33
    Cog that holds the health commands and is responsible for updating the
34
    tables when roles change in discord.
35
36
    Commands:
37
    ---
38
        `check-health`: Makes sure that all the roles in the tables `schools` and `regions` map
39
             to roles in the discord server.
40
41
    Events:
42
    ---
43
        `on_guild_role_update`: Event that is triggered when a role is updated.
44
45
        `on_guild_role_delete`: Event that is triggered when a role is deleted.
46
47
    Arguments:
48
    ---
49
        bot {discord.commands.Bot} -- The bot
50
    """
51
52
    def __init__(self, bot):
53
        self.bot = bot
54
55
    async def cog_check(self, ctx: commands.Context):
56
        """cog_check
57
        ---
58
59
        cog_check is set for the whole cog. Which makes all the commands in health admin only.
60
61
        Arguments:
62
        ---
63
            ctx {discord.ext.commands.Context} -- Context of the command.
64
65
        Returns:
66
            bool -- True if the user in the bot admins
67
        """
68
        return await utils.check_admin(ctx)
69
70
    @commands.command(name="check-health", help="Checks health of roles for schools and regions")
71
    async def check_health(self, ctx: commands.Context):
72
        """check-health
73
        ---
74
75
        Checks health of roles for schools and regions. It pulls all the IDs for school and
76
        region roles. Then compares the names of the matching ids to see if they match. If
77
        they match then added to a list called success and if the check fails then then
78
        both names are added to a list called fail.
79
80
        Arguments:
81
        ---
82
            ctx {discord.ext.commands.Context} -- Context of the command.
83
84
        """
85
        async with ctx.typing():
86
            table_schools = await utils.fetch("schools", "school")
87
            regions = await utils.fetch("regions", "name")
88
            success, fail = [], []
89
            for roles in [table_schools, regions]:
90
                for role in roles:
91
                    try:
92
                        role_name = discord.utils.get(ctx.guild.roles, name=role)
93
                        if role_name.name == role:
94
                            success.append(role_name)
95
                        else:
96
                            fail.append((role_name, role))
97
                    except AttributeError:
98
                        log.error("Attribute error with role {}".format(role))
99
                        fail.append((role, None))
100
101
        message = "There were {} successes and {} failures".format(len(success), len(fail))
102
        await utils.make_embed(ctx, "28b463", title="Check Complete", description=message)
103
104
    @commands.command(
105
        name="get-status",
106
        help="Gets all errors or reports for the day.",
107
        description="Admin Only Feature",
108
    )
109
    async def get_status(self, ctx: commands.Context, which: str, ack: bool = False):
110
        """get-status
111
        ---
112
113
        Gets all the errors for the same day.
114
115
        Arguments:
116
        ---
117
            ctx {discord.ext.commands.Context} -- Context of the command.
118
            which {str} --- which item to get, reports or errors.
119
        """
120
        if which == "errors":
121
            columns = "id, message, command, error, ack"
122
        elif which == "reports":
123
            columns = "name, message"
124
        else:
125
            return await utils.error_message(ctx, "Please pick a valid option.")
126
        date = datetime.utcnow().strftime("%Y-%m-%d")
127
        results = await utils.select(which, columns, "date_trunc('day', time)", date)
128
        if not results:
129
            await utils.make_embed(
130
                ctx, "28b463", title="Success", description=f"No {which} for {date}"
131
            )
132
        else:
133
            results_string = []
134
            for result in results:
135
                if result[-1] == ack and which == "errors":
136
                    results_string.append(" ".join(map(str, result)))
137
            await utils.list_message(ctx, results_string, which)
138
139
    @commands.command(
140
        name="test-log",
141
        help="Tests to make sure that that logging feature works.",
142
        description="Admin Only Feature",
143
    )
144
    async def check_log(self, ctx: commands.Context):
145
        """test-log
146
        ---
147
148
        Tests to make sure that that logging feature works.
149
150
        Arguments:
151
        ---
152
            ctx {discord.ext.commands.Context} -- Context of the command.
153
        """
154
        await utils.admin_log(self.bot, "TESTING LOG: True", True)
155
        await utils.admin_log(self.bot, "TESTING LOG: False", False)
156
        await utils.make_embed(ctx, color="28b463", title="Test Complete")
157
158
    @commands.Cog.listener()
159
    async def on_guild_role_update(self, before: discord.Role, after: discord.Role):
160
        """on_guild_role_update
161
        ---
162
163
        Runs when a role is edited. Logs the old name and new name then updates the name in the
164
        table.
165
166
        Arguments:
167
        ---
168
            before {discord.Role} -- The discord role before it was edited.
169
            after {discord.Role} -- The discord role after it was edited.
170
        """
171
        managed, _ = await managed_role_check(before)
172
        log.debug("Role: {} Managed: {}".format(before.name, managed))
173
        if managed:
174
            await utils.update("schools", "school", before.name, after.name)
175
            log.warning('Role "{}" was updated. It is now {}'.format(before.name, after.name))
176
            await utils.admin_log(self.bot, "Old role {} now new role {}".format(before, after))
177
        else:
178
            log.info("Old role {} now new role {}".format(before, after))
179
180
    @commands.Cog.listener()
181
    async def on_guild_role_delete(self, role: discord.Role):
182
        """on_guild_role_delete
183
        ---
184
185
        Runs when a role is deleted. Will only delete an entry if it existed in the schools or
186
        regions table.
187
188
        Arguments:
189
        ---
190
            role {discord.Role} -- The role that was deleted.
191
        """
192
        managed, table = await managed_role_check(role)
193
        if managed:
194
            await utils.delete("schools", "id", role.id)
195
            log.warning('Role "{}" was deleted. It was in {}'.format(role.name, table))
196
        else:
197
            log.info('Role "{}" was deleted. It was not a managed role'.format(role.name))
198
199
        await utils.admin_log(self.bot, "Role: {} was deleted".format(role.name), True)
200
201
202
def setup(bot):
203
    """Needed for extension loading"""
204
    bot.add_cog(HealthCog(bot))
205