Passed
Push — master ( e17e00...ecdb37 )
by Cyb3r
01:27
created

cogs.health.HealthCog.managed_role_check()   A

Complexity

Conditions 3

Size

Total Lines 16
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nop 2
dl 0
loc 16
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
import utils
7
8
9
async def managed_role_check(role: discord.Role):
10
    """managed_role_check
11
    ---
12
13
    Checks to see if the updated one was one that the bot cares about.
14
15
    Arguments:
16
        role {discord.Role} -- [description]
17
18
    Returns:
19
        bool -- returns True if the role was cared about or does not return.
20
    """
21
    for table in ["schools", "regions"]:
22
        if await utils.select(table, "id", "id", role.id):
23
            return True, table
24
    return False, "error"
25
26
27
class HealthCog(commands.Cog, name="Health"):
28
    """HealthCog
29
    ---
30
31
    Cog that holds the health commands and is responsible for updating the
32
    tables when roles change in discord.
33
34
    Commands:
35
    ---
36
        `check-health`: Makes sure that all the roles in the tables `schools` and `regions` map
37
             to roles in the discord server.
38
39
    Events:
40
    ---
41
        `on_guild_role_update`: Event that is triggered when a role is updated.
42
43
        `on_guild_role_delete`: Event that is triggered when a role is deleted.
44
45
    Arguments:
46
    ---
47
        bot {discord.commands.Bot} -- The bot
48
    """
49
50
    def __init__(self, bot):
51
        self.bot = bot
52
        self.log = logging.getLogger("bot")
53
54
    async def cog_check(self, ctx: commands.Context):
55
        """cog_check
56
        ---
57
58
        cog_check is set for the whole cog. Which makes all the commands in health admin only.
59
60
        Arguments:
61
        ---
62
            ctx {discord.ext.commands.Context} -- Context of the command.
63
64
        Returns:
65
            bool -- True if the user in the bot admins
66
        """
67
        return await utils.check_admin(ctx)
68
69
    @commands.command(name="check-health", help="Checks health of roles for schools and regions")
70
    async def check_health(self, ctx: commands.Context):
71
        """check-health
72
        ---
73
74
        Checks health of roles for schools and regions. It pulls all the IDs for school and
75
        region roles. Then compares the names of the matching ids to see if they match. If
76
        they match then added to a list called success and if the check fails then then
77
        both names are added to a list called fail.
78
79
        Arguments:
80
        ---
81
            ctx {discord.ext.commands.Context} -- Context of the command.
82
83
        """
84
        async with ctx.typing():
85
            table_schools = await utils.fetch("schools", "school")
86
            regions = await utils.fetch("regions", "name")
87
            success, fail = [], []
88
            for roles in [table_schools, regions]:
89
                for role in roles:
90
                    try:
91
                        role_name = discord.utils.get(ctx.guild.roles, name=role)
92
                        if role_name.name == role:
93
                            success.append(role_name)
94
                        else:
95
                            fail.append((role_name, role))
96
                    except AttributeError:
97
                        self.log.error("Attribute error with role {}".format(role))
98
                        fail.append((role, None))
99
100
        message = "There were {} successes and {} failures".format(len(success), len(fail))
101
        await utils.make_embed(ctx, "28b463", title="Check Complete", description=message)
102
103
    @commands.command(
104
        name="get-status",
105
        help="Gets all errors or reports for the day.",
106
        description="Admin Only Feature",
107
    )
108
    async def get_status(self, ctx: commands.Context, which: str):
109
        """get-status
110
        ---
111
112
        Gets all the errors for the same day.
113
114
        Arguments:
115
        ---
116
            ctx {discord.ext.commands.Context} -- Context of the command.
117
            which {str} --- which item to get, reports or errors.
118
        """
119
        if which == "errors":
120
            columns = "id, message, command, error"
121
        elif which == "reports":
122
            columns = "name, message"
123
        else:
124
            return await utils.make_embed(
125
                ctx, "FF0000", title="Error", description="Please pick a valid option."
126
            )
127
        date = datetime.utcnow().strftime("%Y-%m-%d")
128
        results = await utils.select(which, columns, "date_trunc('day', time)", date)
129
        if not results:
130
            await utils.make_embed(
131
                ctx, "28b463", title="Success", description="No {} for {}".format(which, date),
132
            )
133
        else:
134
            results_string = []
135
            for result in results:
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
        self.log.debug("Role: {} Managed: {}".format(before.name, managed))
173
        if managed:
174
            await utils.update("schools", "school", before.name, after.name)
175
            self.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
            self.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
            self.log.warning('Role "{}" was deleted. It was in {}'.format(role.name, table))
196
        else:
197
            self.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