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

cogs.schools.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
"""Schools commands for bot"""
2
import asyncio
3
import random
4
import logging
5
import discord
6
from discord.ext import commands
7
import utils
8
9
10
class SchoolCog(commands.Cog, name="Schools"):
11
    """SchoolCog
12
    ---
13
14
    Cog that deal with the school commands as well as the searching commands.
15
16
    Commands:
17
    ---
18
        `list-schools`: List all the available school roles that are joinable.
19
        `import-school`: Allows admin to import current roles into schools. *WIP*
20
        `join-school`: Allows users to join any available school role.
21
        `add-school`: Command that allows users to create their own school.
22
23
    Arguments:
24
    ---
25
        bot {discord.commands.Bot} -- The bot
26
27
    Raises:
28
    ---
29
        utils.FailedReactionCheck: Custom exception if the reaction check fails.
30
    """
31
    def __init__(self, bot):
32
        self.bot = bot
33
        self.log = logging.getLogger("bot")
34
35
    @commands.command(name="list-schools",
36
                      help="Gets list of current schools")
37
    async def list_schools(self, ctx):
38
        """list-schools
39
        ---
40
41
        Lists current schools in the database. Message is a embed that has a random color with the
42
        list of all schools.
43
44
        Arguments:
45
        ---
46
            ctx {discord.ext.commands.Context} -- Context of the command.
47
        """
48
        fetched = sorted(await utils.fetch("schools", "school"), key=str.lower)
49
        if len(fetched) == 0:
50
            return await utils.make_embed(ctx, color="FF0000",
51
                                          title="There are no schools to join.")
52
        schools = ""
53
        embed = await utils.make_embed(ctx, title="Available schools to join:", send=False,
54
                                       description="Use `$join-school` to join")
55
        for item in fetched:
56
            schools += "- {} \n".format(item)
57
        embed.add_field(name="Schools", value=schools, inline=False)
58
        embed.set_footer(text="If your school is not in the list, use `$help add-school`")
59
        await ctx.send(embed=embed)
60
61
    @commands.command(name="import-school",
62
                      help="Admin Only Feature")
63
    @commands.check(utils.check_admin)
64
    async def import_school(self, ctx, *, school_name: str):
65
        """import-school
66
        ---
67
68
        Allows admins to import existing roles as schools.
69
70
        Arguments:
71
        ---
72
            ctx {discord.ext.commands.Context} -- Context of the command.
73
            school_name {str} -- Name of the school role to import.
74
        """
75
        srole = discord.utils.get(ctx.guild.roles, name=school_name)
76
        if srole.name in await utils.fetch("schools", "school"):
77
            await utils.make_embed(ctx, "FF0000", title="That school already exists.")
78
        else:
79
            await ctx.send("Please enter the region for the school.")
80
            try:
81
                region = self.bot.wait_for('message', timeout=60.0)
82
            except asyncio.TimeoutError:
83
                return await utils.make_embed(ctx, "FF0000", title="Timed out")
84
            new_school = [school_name, region.content, srole.color,  # pylint: disable=no-member
85
                          "Imported", "Imported"]
86
            status = await utils.insert("schools", new_school)
87
            if status == "error":
88
                utils.make_embed(ctx, color="FF0000",
89
                                 title="There was an error importing the school.")
90
            else:
91
                utils.make_embed(ctx, color="28b463",
92
                                 title="Region has been created")
93
94
    @commands.command(name="join-school",
95
                      help="Joins a schools.")
96
    @commands.has_role("new")
97
    async def join_school(self, ctx, *, school_name: str):
98
        """join-school
99
        ---
100
101
        Enables users to join a school role. school_name arguments is not to be quote seperated.
102
        Users are required to have the role "new". Users will be assigned the school role, region
103
        role and "verified" role. They will lose their "new" role.
104
105
106
        Arguments:
107
        ---
108
            ctx {discord.ext.commands.Context} -- Context of the command.
109
            school_name {str} -- Name of the school the user wants to join.
110
        """
111
        user = ctx.message.author
112
        db_entry = await utils.fetch("schools", "school, region")
113
        try:
114
            entries = [x for x in db_entry if x[0] == school_name][0]
115
        except IndexError:
116
            return await utils.make_embed(
117
                ctx, "FF0000", title="Error:", description="School could not be found.")
118
119
        else:
120
            to_add = []
121
            for item in (*entries, "verified"):
122
                to_add.append(discord.utils.get(ctx.guild.roles, name=item))
123
            if None in to_add:
124
                title = "The school you select does not have valid role."
125
                await utils.make_embed(ctx, "FF0000",
126
                                       title=title)
127
                self.log.warning("{} tried to join {}. Only roles found: {}".format(
128
                    ctx.author.name, school_name, to_add))
129
            else:
130
                await user.add_roles(
131
                    *to_add,
132
                    reason="{u} joined {s}".format(u=user.name, s=entries[0])
133
                )
134
                await user.remove_roles(
135
                    discord.utils.get(ctx.guild.roles, name="new"),
136
                    reason="{u} joined {s}".format(u=user.name, s=entries[0])
137
                )
138
                await ctx.author.send(embed=await utils.make_embed(
139
                    ctx, "28b463", send=False,
140
                    title="School assigned: {}".format(entries[0])
141
                    )
142
                                     )
143
144
    @commands.command(name="add-school",
145
                      help="Adds a new school and makes a role for it .",
146
                      description="Creates a new school")
147
    @commands.has_role("new")
148
    async def add_school(self, ctx, *, school_name: str):  # noqa: E501 pylint: disable=too-many-branches,line-too-long
149
        """add_school
150
        ---
151
152
        Enables users to create a school role. They are required to have the role "new". Schools
153
        will automatically be assigned a region based on the schools.csv in utils.
154
155
        Arguments:
156
        ---
157
            ctx {discord.ext.commands.Context} -- Context of the command.
158
            school_name {str} -- Name of the school the user wants to join.
159
160
        Raises:
161
        ---
162
            utils.FailedReactionCheck: Expection is raised if the reaction check does not validate.
163
        """
164
        if not await utils.school_check(school_name):
165
            return await utils.make_embed(
166
                ctx, "FF0000", title="Error: School name not valid.")
167
168
        r_regions = await utils.fetch("regions", "name")
169
        region = await utils.region_select(school_name)
170
        if region not in r_regions:
171
            # No region map error
172
            self.log.error("There is no region map for {}, region: {}, {}".format(school_name,
173
                                                                                  region,
174
                                                                                  r_regions))
175
            return await utils.make_embed(
176
                ctx, "FF0000", title="Error: There is no region mapped")
177
178
        await utils.make_embed(
179
            ctx, title="You are about to create a new school: {}.".format(school_name),
180
            description="React  👍  to confirm.")
181
        # Gives the user 30 seconds to add the reaction '👍' to the message.
182
        try:
183
            reactions, user = await self.bot.wait_for("reaction_add", timeout=30)
184
            if not await utils.check_react(ctx, user, reactions, "👍"):
185
                raise utils.FailedReactionCheck
186
        except asyncio.TimeoutError:
187
            await utils.make_embed(ctx, "FF0000", title="Error:",
188
                                   description="Timed out.")
189
        except utils.FailedReactionCheck:
190
            await utils.make_embed(
191
                ctx, "FF0000", title="Error:",
192
                description="Most likely the wrong react was added or by the wrong user.")
193
        else:
194
            color = int("0x%06x" % random.randint(0, 0xFFFFFF), 16)  # nosec
195
            added_school = await ctx.guild.create_role(
196
                name=school_name,
197
                color=discord.Color(color),
198
                mentionable=True,
199
                hoist=False,
200
                reason="Added by {}".format(ctx.author.name))
201
            data = [school_name,
202
                    region,
203
                    color,
204
                    added_school.id,
205
                    (ctx.author.name+ctx.author.discriminator),
206
                    ctx.author.id]
207
            status = await utils.insert("schools", data)
208
            if status == "error":
209
                await utils.make_embed(
210
                    ctx, "FF0000", title="Error",
211
                    description="There was an error with creating the role.")
212
                rrole = discord.utils.get(ctx.guild.roles, name=school_name)
213
                await rrole.delete(reason="Error in creation")
214
                self.log.warning("due to error with School Role creation.")
215
            else:
216
                success_msg = ("School \"{}\" has been created in {} with color of 0x{}"
217
                               .format(school_name, region, color))
218
                await utils.make_embed(ctx, color=color, title="Success",
219
                                       description=success_msg)
220
221
222
def setup(bot):
223
    """Needed for extension loading"""
224
    bot.add_cog(SchoolCog(bot))
225