Passed
Push — master ( 58f506...9afc6c )
by Cyb3r
01:28 queued 11s
created

cogs.health.setup()   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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