From a41670b437384f0095f0186709aecc0c9b72ca0e Mon Sep 17 00:00:00 2001 From: nex <53234499+EEKIM10@users.noreply.github.com> Date: Sun, 30 Oct 2022 16:31:38 +0000 Subject: [PATCH] Blackify code (formatting) --- cogs/assignments.py | 189 +++++++++++++++------------------------- cogs/events.py | 14 +-- cogs/mod.py | 12 +-- cogs/timetable.py | 82 ++++++++--------- cogs/verify.py | 4 +- main.py | 11 +-- tests/test_timetable.py | 5 +- utils/__init__.py | 6 +- utils/_email.py | 1 + utils/db.py | 16 +--- utils/views.py | 47 ++++------ 11 files changed, 144 insertions(+), 243 deletions(-) diff --git a/cogs/assignments.py b/cogs/assignments.py index a3a927c..01300be 100644 --- a/cogs/assignments.py +++ b/cogs/assignments.py @@ -8,16 +8,13 @@ from discord.ext import commands, tasks import config from utils import Assignments, Tutors, simple_embed_paginator, get_or_none, Student, hyperlink, console -BOOL_EMOJI = { - True: "\N{white heavy check mark}", - False: "\N{cross mark}" -} +BOOL_EMOJI = {True: "\N{white heavy check mark}", False: "\N{cross mark}"} TUTOR_OPTION = discord.Option( str, "The tutor who assigned the project", default=None, - choices=[x.title() for x in dir(Tutors) if not x.startswith("__") and x not in ("name", "value")] + choices=[x.title() for x in dir(Tutors) if not x.startswith("__") and x not in ("name", "value")], ) __MARK_AS_OPTION_OPTIONS = ("unfinished", "finished", "unsubmitted", "submitted") MARK_AS_OPTION = discord.Option( @@ -29,7 +26,7 @@ MARK_AS_OPTION = discord.Option( value=__MARK_AS_OPTION_OPTIONS.index(x), ) for x in __MARK_AS_OPTION_OPTIONS - ] + ], ) @@ -39,12 +36,8 @@ class TutorSelector(discord.ui.View): @discord.ui.select( placeholder="Select a tutor name", options=[ - discord.SelectOption( - label=x.title(), - value=x.upper() - ) - for x in [y.name for y in TUTOR_OPTION.choices] - ] + discord.SelectOption(label=x.title(), value=x.upper()) for x in [y.name for y in TUTOR_OPTION.choices] + ], ) async def select_tutor(self, select: discord.ui.Select, interaction2: discord.Interaction): await interaction2.response.defer(invisible=True) @@ -56,13 +49,10 @@ async def assignment_autocomplete(ctx: discord.AutocompleteContext) -> list[str] if not ctx.value: results: list[Assignments] = await Assignments.objects.order_by("-due_by").limit(7).all() else: - results: list[Assignments] = await Assignments.objects.filter( - title__icontains=ctx.value - ).limit(30).order_by("-entry_id").all() - return [ - textwrap.shorten(f"{x.entry_id}: {x.title}", 100, placeholder="...") - for x in results - ] + results: list[Assignments] = ( + await Assignments.objects.filter(title__icontains=ctx.value).limit(30).order_by("-entry_id").all() + ) + return [textwrap.shorten(f"{x.entry_id}: {x.title}", 100, placeholder="...") for x in results] # noinspection DuplicatedCode @@ -80,16 +70,10 @@ class AssignmentsCog(commands.Cog): await self.bot.wait_until_ready() try: view_command = "".format( - self.bot.get_application_command( - "assignments", - type=discord.SlashCommandGroup - ) + self.bot.get_application_command("assignments", type=discord.SlashCommandGroup) ) edit_command = "".format( - self.bot.get_application_command( - "assignments", - type=discord.SlashCommandGroup - ) + self.bot.get_application_command("assignments", type=discord.SlashCommandGroup) ) except AttributeError: view_command = "`/assignments view`" @@ -100,10 +84,12 @@ class AssignmentsCog(commands.Cog): if not general.can_send(): return - msg_format = "@everyone {reminder_name} reminder for project {project_title} for **{project_tutor}**!\n" \ - "Run '%s {project_title}' to view information on the assignment.\n" \ - "*You can mark this assignment as complete with '%s {project_title}', which will prevent" \ - " further reminders.*" % (view_command, edit_command) + msg_format = ( + "@everyone {reminder_name} reminder for project {project_title} for **{project_tutor}**!\n" + "Run '%s {project_title}' to view information on the assignment.\n" + "*You can mark this assignment as complete with '%s {project_title}', which will prevent" + " further reminders.*" % (view_command, edit_command) + ) now = datetime.datetime.now() assignments: list[Assignments] = await Assignments.objects.filter(submitted=False).all() @@ -126,9 +112,9 @@ class AssignmentsCog(commands.Cog): msg_format.format( reminder_name=reminder_name, project_title=textwrap.shorten(assignment.title, 100, placeholder="..."), - project_tutor=assignment.tutor.name.title() + project_tutor=assignment.tutor.name.title(), ), - allowed_mentions=allowed_mentions + allowed_mentions=allowed_mentions, ) except discord.HTTPException: pass @@ -142,9 +128,9 @@ class AssignmentsCog(commands.Cog): msg_format.format( reminder_name=reminder_name, project_title=textwrap.shorten(assignment.title, 100, placeholder="..."), - project_tutor=assignment.tutor.name.title() + project_tutor=assignment.tutor.name.title(), ), - allowed_mentions=allowed_mentions + allowed_mentions=allowed_mentions, ) except discord.HTTPException: pass @@ -156,7 +142,7 @@ class AssignmentsCog(commands.Cog): embed = discord.Embed( title=f"Assignment #{assignment.entry_id}", description=f"**Title:**\n>>> {assignment.title}", - colour=discord.Colour.random() + colour=discord.Colour.random(), ) if assignment.classroom: @@ -172,37 +158,29 @@ class AssignmentsCog(commands.Cog): embed.add_field(name="Classroom URL:", value=classroom, inline=False), embed.add_field(name="Shared Document URL:", value=shared_doc) embed.add_field(name="Tutor:", value=assignment.tutor.name.title(), inline=False) - user_id = getattr(assignment.created_by, 'user_id', assignment.entry_id) - embed.add_field( - name="Created:", - value=f" by <@{user_id}>", - inline=False - ) + user_id = getattr(assignment.created_by, "user_id", assignment.entry_id) + embed.add_field(name="Created:", value=f" by <@{user_id}>", inline=False) embed.add_field( name="Due:", value=f" " - f"(finished: {BOOL_EMOJI[assignment.finished]} | Submitted: {BOOL_EMOJI[assignment.submitted]})", - inline=False + f"(finished: {BOOL_EMOJI[assignment.finished]} | Submitted: {BOOL_EMOJI[assignment.submitted]})", + inline=False, ) if assignment.reminders: embed.set_footer(text="Reminders sent: " + ", ".join(assignment.reminders)) return embed - assignments_command = discord.SlashCommandGroup( - "assignments", - "Assignment/project management", - guild_only=True - ) + assignments_command = discord.SlashCommandGroup("assignments", "Assignment/project management", guild_only=True) @assignments_command.command(name="list") async def list_assignments( - self, - ctx: discord.ApplicationContext, - limit: int = 20, - upcoming_only: bool = True, - tutor_name: TUTOR_OPTION = None, - unfinished_only: bool = False, - unsubmitted_only: bool = False + self, + ctx: discord.ApplicationContext, + limit: int = 20, + upcoming_only: bool = True, + tutor_name: TUTOR_OPTION = None, + unfinished_only: bool = False, + unsubmitted_only: bool = False, ): """Lists assignments.""" tutor_name: Optional[str] @@ -231,13 +209,9 @@ class AssignmentsCog(commands.Cog): ) embeds = simple_embed_paginator(lines, assert_ten=True, colour=ctx.author.colour) - embeds = embeds or [ - discord.Embed(description="No projects match the provided criteria.") - ] + embeds = embeds or [discord.Embed(description="No projects match the provided criteria.")] - return await ctx.respond( - embeds=embeds - ) + return await ctx.respond(embeds=embeds) @assignments_command.command(name="add") async def create_assignment(self, ctx: discord.ApplicationContext): @@ -255,7 +229,7 @@ class AssignmentsCog(commands.Cog): "classroom": None, "shared_doc": None, "due_by": None, - "tutor": None + "tutor": None, } super().__init__( discord.ui.InputText( @@ -263,7 +237,7 @@ class AssignmentsCog(commands.Cog): label="Assignment Title", min_length=2, max_length=2000, - value=self.create_kwargs["title"] + value=self.create_kwargs["title"], ), discord.ui.InputText( custom_id="classroom", @@ -271,7 +245,7 @@ class AssignmentsCog(commands.Cog): max_length=4000, required=False, placeholder="Optional, can be added later.", - value=self.create_kwargs["classroom"] + value=self.create_kwargs["classroom"], ), discord.ui.InputText( custom_id="shared_doc", @@ -279,7 +253,7 @@ class AssignmentsCog(commands.Cog): max_length=4000, required=False, placeholder="Google docs, slides, powerpoint, etc. Optional.", - value=self.create_kwargs["shared_doc"] + value=self.create_kwargs["shared_doc"], ), discord.ui.InputText( custom_id="due_by", @@ -289,11 +263,12 @@ class AssignmentsCog(commands.Cog): placeholder="dd/mm/yy hh:mm".upper(), value=( self.create_kwargs["due_by"].strftime("%d/%m/%y %H:%M") - if self.create_kwargs["due_by"] else None - ) + if self.create_kwargs["due_by"] + else None + ), ), title="Add an assignment", - timeout=300 + timeout=300, ) async def callback(self, interaction: discord.Interaction): @@ -304,9 +279,10 @@ class AssignmentsCog(commands.Cog): try: self.create_kwargs["due_by"] = datetime.datetime.strptime( self.children[3].value, - "%d/%m/%y %H:%M" if len(self.children[3].value) == 14 else "%d/%m/%Y %H:%M" + "%d/%m/%y %H:%M" if len(self.children[3].value) == 14 else "%d/%m/%Y %H:%M", ) except ValueError: + class TryAgainView(discord.ui.View): def __init__(self, kw): self._mod = None @@ -327,10 +303,7 @@ class AssignmentsCog(commands.Cog): self.stop() v = TryAgainView(self.create_kwargs) - msg = await interaction.followup.send( - "\N{cross mark} Failed to parse date - try again?", - view=v - ) + msg = await interaction.followup.send("\N{cross mark} Failed to parse date - try again?", view=v) await v.wait() if v.modal: self.create_kwargs = v.modal.create_kwargs @@ -338,10 +311,7 @@ class AssignmentsCog(commands.Cog): return else: view = TutorSelector() - msg = await interaction.followup.send( - "Which tutor assigned this project?", - view=view - ) + msg = await interaction.followup.send("Which tutor assigned this project?", view=view) await view.wait() self.create_kwargs["tutor"] = view.value @@ -353,25 +323,18 @@ class AssignmentsCog(commands.Cog): await modal.wait() if not modal.msg: return - await modal.msg.edit( - content="Creating assignment...", - view=None - ) + await modal.msg.edit(content="Creating assignment...", view=None) try: modal.create_kwargs["due_by"] = modal.create_kwargs["due_by"].timestamp() await Assignments.objects.create(**modal.create_kwargs) except sqlite3.Error as e: return await modal.msg.edit(content="SQL Error: %s.\nAssignment not saved." % e) else: - return await modal.msg.edit( - content=f"\N{white heavy check mark} Created assignment!" - ) + return await modal.msg.edit(content=f"\N{white heavy check mark} Created assignment!") @assignments_command.command(name="view") async def get_assignment( - self, - ctx: discord.ApplicationContext, - title: discord.Option(str, autocomplete=assignment_autocomplete) + self, ctx: discord.ApplicationContext, title: discord.Option(str, autocomplete=assignment_autocomplete) ): """Views an assignment's details""" try: @@ -389,9 +352,7 @@ class AssignmentsCog(commands.Cog): @assignments_command.command(name="edit") async def edit_assignment( - self, - ctx: discord.ApplicationContext, - title: discord.Option(str, autocomplete=assignment_autocomplete) + self, ctx: discord.ApplicationContext, title: discord.Option(str, autocomplete=assignment_autocomplete) ): """Edits an assignment""" try: @@ -432,15 +393,14 @@ class AssignmentsCog(commands.Cog): min_length=2, max_length=4000, ), - title="Update assignment title" + title="Update assignment title", ) async def callback(self, _interaction: discord.Interaction): await _interaction.response.defer() await assignment.update(title=self.children[0].value) await _interaction.followup.send( - "\N{white heavy check mark} Changed assignment title!", - delete_after=5 + "\N{white heavy check mark} Changed assignment title!", delete_after=5 ) self.stop() @@ -460,7 +420,7 @@ class AssignmentsCog(commands.Cog): required=False, max_length=4000, ), - title="Update Classroom url" + title="Update Classroom url", ) async def callback(self, _interaction: discord.Interaction): @@ -468,8 +428,7 @@ class AssignmentsCog(commands.Cog): try: await assignment.update(classroom=self.children[0].value) await _interaction.followup.send( - "\N{white heavy check mark} Changed classroom URL!", - delete_after=5 + "\N{white heavy check mark} Changed classroom URL!", delete_after=5 ) except sqlite3.Error: await _interaction.followup.send( @@ -494,7 +453,7 @@ class AssignmentsCog(commands.Cog): required=False, max_length=4000, ), - title="Update shared document url" + title="Update shared document url", ) async def callback(self, _interaction: discord.Interaction): @@ -502,8 +461,7 @@ class AssignmentsCog(commands.Cog): try: await assignment.update(shared_doc=self.children[0].value) await _interaction.followup.send( - "\N{white heavy check mark} Changed shared doc URL!", - delete_after=5 + "\N{white heavy check mark} Changed shared doc URL!", delete_after=5 ) except sqlite3.Error: await _interaction.followup.send( @@ -521,14 +479,12 @@ class AssignmentsCog(commands.Cog): await interaction.response.defer() view = TutorSelector() msg: discord.WebhookMessage = await interaction.followup.send( - "Which tutor assigned this project?", - view=view + "Which tutor assigned this project?", view=view ) await view.wait() await assignment.update(tutor=view.value) await msg.edit( - content=f"\N{white heavy check mark} Changed tutor to {view.value.name.title()}", - view=None + content=f"\N{white heavy check mark} Changed tutor to {view.value.name.title()}", view=None ) await msg.delete(delay=5) await self.update_display(interaction) @@ -544,9 +500,9 @@ class AssignmentsCog(commands.Cog): placeholder=self.date.strftime("%d/%m/%y %H:%M"), value=self.date.strftime("%d/%m/%y %H:%M"), min_length=14, - max_length=16 + max_length=16, ), - title="Change due by date" + title="Change due by date", ) async def callback(self, _interaction: discord.Interaction): @@ -554,7 +510,7 @@ class AssignmentsCog(commands.Cog): try: new = datetime.datetime.strptime( self.children[1].value, - "%d/%m/%y %H:%M" if len(self.children[1].value) == 14 else "%d/%m/%Y %H:%M" + "%d/%m/%y %H:%M" if len(self.children[1].value) == 14 else "%d/%m/%Y %H:%M", ) except ValueError: await _interaction.followup.send( @@ -566,15 +522,13 @@ class AssignmentsCog(commands.Cog): try: await assignment.update(due_by=new.timestamp(), reminders=[]) await _interaction.followup.send( - "\N{white heavy check mark} Changed due by date & reset reminders.", - delete_after=5 + "\N{white heavy check mark} Changed due by date & reset reminders.", delete_after=5 ) except sqlite3.Error: - await _interaction.followup.send( - "\N{cross mark} Failed to apply changes." - ) + await _interaction.followup.send("\N{cross mark} Failed to apply changes.") finally: self.stop() + await interaction.response.send_modal(UpdateDateModal()) await self.update_display(interaction) @@ -599,7 +553,7 @@ class AssignmentsCog(commands.Cog): if assignment.finished is False and assignment.submitted is False: return await interaction.followup.send( "\N{cross mark} You cannot mark an assignment as submitted if it is not marked as complete!", - delete_after=10 + delete_after=10, ) await assignment.update(submitted=not assignment.submitted) await self.update_display(interaction) @@ -607,7 +561,7 @@ class AssignmentsCog(commands.Cog): "\N{white heavy check mark} Assignment is now marked as {}submitted.".format( "in" if assignment.submitted is False else "" ), - delete_after=5 + delete_after=5, ) @discord.ui.button(label="Save & Exit") @@ -621,8 +575,7 @@ class AssignmentsCog(commands.Cog): await interaction.response.defer(ephemeral=True) await assignment.created_by.load() await interaction.followup.send( - embed=AssignmentsCog.generate_assignment_embed(assignment), - ephemeral=True + embed=AssignmentsCog.generate_assignment_embed(assignment), ephemeral=True ) await self.update_display(interaction) @@ -630,9 +583,7 @@ class AssignmentsCog(commands.Cog): @assignments_command.command(name="remove") async def remove_assignment( - self, - ctx: discord.ApplicationContext, - title: discord.Option(str, autocomplete=assignment_autocomplete) + self, ctx: discord.ApplicationContext, title: discord.Option(str, autocomplete=assignment_autocomplete) ): """Edits an assignment""" try: diff --git a/cogs/events.py b/cogs/events.py index 42f0217..837ebf5 100644 --- a/cogs/events.py +++ b/cogs/events.py @@ -37,11 +37,7 @@ class Events(commands.Cog): if self.bot.activity.name == text: return await self.bot.change_presence( - activity=discord.Activity( - name=text, - type=discord.ActivityType.playing - ), - status=status + activity=discord.Activity(name=text, type=discord.ActivityType.playing), status=status ) else: await self.bot.change_presence() @@ -71,9 +67,7 @@ class Events(commands.Cog): channel: discord.TextChannel = discord.utils.get(member.guild.text_channels, name="general") if channel and channel.can_send(): - await channel.send( - f"{LTR} {member.mention} {f'({student.id})' if student else '(pending verification)'}" - ) + await channel.send(f"{LTR} {member.mention} {f'({student.id})' if student else '(pending verification)'}") @commands.Cog.listener() async def on_member_remove(self, member: discord.Member): @@ -83,9 +77,7 @@ class Events(commands.Cog): student: Optional[Student] = await get_or_none(Student, user_id=member.id) channel: discord.TextChannel = discord.utils.get(member.guild.text_channels, name="general") if channel and channel.can_send(): - await channel.send( - f"{RTL} {member.mention} {f'({student.id})' if student else '(pending verification)'}" - ) + await channel.send(f"{RTL} {member.mention} {f'({student.id})' if student else '(pending verification)'}") @commands.Cog.listener() async def on_message(self, message: discord.Message): diff --git a/cogs/mod.py b/cogs/mod.py index 6c85ded..ab745d4 100644 --- a/cogs/mod.py +++ b/cogs/mod.py @@ -26,8 +26,7 @@ class Mod(commands.Cog): await member.ban(reason=f"Banned ID {ban.student_id} by {ctx.author}") return await ctx.respond( - f"\N{white heavy check mark} Banned {ban.student_id} (and {member.mention})", - ephemeral=True + f"\N{white heavy check mark} Banned {ban.student_id} (and {member.mention})", ephemeral=True ) @commands.slash_command(name="unban-student-number") @@ -45,18 +44,13 @@ class Mod(commands.Cog): return await ctx.respond(f"\N{white heavy check mark} Unbanned {student_id}. No user to unban.") else: try: - await ctx.guild.unban( - discord.Object(user_id), - reason=f"Unbanned by {ctx.author}" - ) + await ctx.guild.unban(discord.Object(user_id), reason=f"Unbanned by {ctx.author}") except discord.HTTPException as e: return await ctx.respond( f"\N{white heavy check mark} Unbanned {student_id}. Failed to unban {user_id} - HTTP {e.status}." ) else: - return await ctx.respond( - f"\N{white heavy check mark} Unbanned {student_id}. Unbanned {user_id}." - ) + return await ctx.respond(f"\N{white heavy check mark} Unbanned {student_id}. Unbanned {user_id}.") def setup(bot): diff --git a/cogs/timetable.py b/cogs/timetable.py index 00ef37a..8d96760 100644 --- a/cogs/timetable.py +++ b/cogs/timetable.py @@ -32,11 +32,7 @@ class TimeTableCog(commands.Cog): start_date = datetime.strptime(dates["start"], "%d/%m/%Y") end_date = datetime.strptime(dates["end"], "%d/%m/%Y") if date.timestamp() <= end_date.timestamp() and date.timestamp() >= start_date.timestamp(): - return { - "name": name, - "start": start_date, - "end": end_date - } + return {"name": name, "start": start_date, "end": end_date} def cog_unload(self): self.update_status.stop() @@ -92,7 +88,9 @@ class TimeTableCog(commands.Cog): if lesson is None: # Loop until we find the next day when it isn't the weekend, and we aren't on break. next_available_date = date.replace(hour=0, minute=0, second=0) - while self.are_on_break(next_available_date) or not self.timetable.get(next_available_date.strftime("%A").lower()): + while self.are_on_break(next_available_date) or not self.timetable.get( + next_available_date.strftime("%A").lower() + ): next_available_date += timedelta(days=1) if next_available_date.year >= 2024: raise RuntimeError("Failed to fetch absolute next lesson") @@ -103,60 +101,60 @@ class TimeTableCog(commands.Cog): return lesson async def update_timetable_message( - self, - message: Union[discord.Message, discord.ApplicationContext], - date: datetime = None, - *, - no_prefix: bool = False, + self, + message: Union[discord.Message, discord.ApplicationContext], + date: datetime = None, + *, + no_prefix: bool = False, ): date = date or datetime.now() _break = self.are_on_break(date) if _break: next_lesson = self.next_lesson(_break["end"] + timedelta(days=1, hours=7)) - next_lesson = next_lesson or { - "name": "Unknown", - "tutor": "Unknown", - "room": "Unknown" - } - text = "[tt] On break {!r} from {} until {}. Break ends {}, and the first lesson back is " \ - "{lesson[name]!r} with {lesson[tutor]} in {lesson[room]}.".format( - _break["name"], - discord.utils.format_dt(_break["start"], "d"), - discord.utils.format_dt(_break["end"], "d"), - discord.utils.format_dt(_break["end"], "R"), - lesson=next_lesson + next_lesson = next_lesson or {"name": "Unknown", "tutor": "Unknown", "room": "Unknown"} + text = ( + "[tt] On break {!r} from {} until {}. Break ends {}, and the first lesson back is " + "{lesson[name]!r} with {lesson[tutor]} in {lesson[room]}.".format( + _break["name"], + discord.utils.format_dt(_break["start"], "d"), + discord.utils.format_dt(_break["end"], "d"), + discord.utils.format_dt(_break["end"], "R"), + lesson=next_lesson, + ) ) else: lesson = self.current_lesson(date) if not lesson: next_lesson = self.next_lesson(date) if not next_lesson: - next_lesson = await asyncio.to_thread( - self.absolute_next_lesson, - new_method=True - ) + next_lesson = await asyncio.to_thread(self.absolute_next_lesson, new_method=True) next_lesson = next_lesson or { "name": "unknown", "tutor": "unknown", "room": "unknown", - "start_datetime": datetime.max + "start_datetime": datetime.max, } - text = "[tt] No more lessons today!\n" \ - f"[tt] Next Lesson: {next_lesson['name']!r} with {next_lesson['tutor']} in " \ - f"{next_lesson['room']} - " \ - f"Starts {discord.utils.format_dt(next_lesson['start_datetime'], 'R')}" + text = ( + "[tt] No more lessons today!\n" + f"[tt] Next Lesson: {next_lesson['name']!r} with {next_lesson['tutor']} in " + f"{next_lesson['room']} - " + f"Starts {discord.utils.format_dt(next_lesson['start_datetime'], 'R')}" + ) else: - text = f"[tt] Next Lesson: {next_lesson['name']!r} with {next_lesson['tutor']} in " \ - f"{next_lesson['room']} - Starts {discord.utils.format_dt(next_lesson['start_datetime'], 'R')}" + text = ( + f"[tt] Next Lesson: {next_lesson['name']!r} with {next_lesson['tutor']} in " + f"{next_lesson['room']} - Starts {discord.utils.format_dt(next_lesson['start_datetime'], 'R')}" + ) else: - text = f"[tt] Current Lesson: {lesson['name']!r} with {lesson['tutor']} in {lesson['room']} - " \ - f"ends {discord.utils.format_dt(lesson['end_datetime'], 'R')}" + text = ( + f"[tt] Current Lesson: {lesson['name']!r} with {lesson['tutor']} in {lesson['room']} - " + f"ends {discord.utils.format_dt(lesson['end_datetime'], 'R')}" + ) next_lesson = self.next_lesson(date) if next_lesson: text += "\n[tt] Next lesson: {0[name]!r} with {0[tutor]} in {0[room]} - starts {1}".format( - next_lesson, - discord.utils.format_dt(next_lesson["start_datetime"], 'R') + next_lesson, discord.utils.format_dt(next_lesson["start_datetime"], "R") ) if no_prefix: @@ -215,9 +213,11 @@ class TimeTableCog(commands.Cog): for lesson in lessons: start_datetime = date.replace(hour=lesson["start"][0], minute=lesson["start"][1]) end_datetime = date.replace(hour=lesson["end"][0], minute=lesson["end"][1]) - text = f"{discord.utils.format_dt(start_datetime, 't')} to {discord.utils.format_dt(end_datetime, 't')}" \ - f":\n> Lesson Name: {lesson['name']!r}\n" \ - f"> Tutor: **{lesson['tutor']}**\n> Room: `{lesson['room']}`" + text = ( + f"{discord.utils.format_dt(start_datetime, 't')} to {discord.utils.format_dt(end_datetime, 't')}" + f":\n> Lesson Name: {lesson['name']!r}\n" + f"> Tutor: **{lesson['tutor']}**\n> Room: `{lesson['room']}`" + ) blocks.append(text) await ctx.respond("\n\n".join(blocks)) diff --git a/cogs/verify.py b/cogs/verify.py index 7585200..88c3521 100644 --- a/cogs/verify.py +++ b/cogs/verify.py @@ -63,13 +63,13 @@ class VerifyCog(commands.Cog): return await ctx.respond( f"{member.mention}'s B number is saved as {student.id!r}.", ephemeral=True, - allowed_mentions=discord.AllowedMentions.none() + allowed_mentions=discord.AllowedMentions.none(), ) except orm.NoMatch: return await ctx.respond( f"{member.mention} has no saved B number.", ephemeral=True, - allowed_mentions=discord.AllowedMentions.none() + allowed_mentions=discord.AllowedMentions.none(), ) @commands.command(name="rebind") diff --git a/main.py b/main.py index b0d9249..085daea 100644 --- a/main.py +++ b/main.py @@ -8,17 +8,10 @@ bot = commands.Bot( commands.when_mentioned_or("h!"), debug_guilds=config.guilds, allowed_mentions=discord.AllowedMentions.none(), - intents=discord.Intents.default() + discord.Intents.members + intents=discord.Intents.default() + discord.Intents.members, ) -extensions = [ - "jishaku", - "cogs.verify", - "cogs.mod", - "cogs.events", - "cogs.assignments", - "cogs.timetable" -] +extensions = ["jishaku", "cogs.verify", "cogs.mod", "cogs.events", "cogs.assignments", "cogs.timetable"] for ext in extensions: bot.load_extension(ext) console.log(f"Loaded extension [green]{ext}") diff --git a/tests/test_timetable.py b/tests/test_timetable.py index 730955a..cd1e49c 100644 --- a/tests/test_timetable.py +++ b/tests/test_timetable.py @@ -16,11 +16,10 @@ def is_sane_time(time: list[int, int]) -> Union[bool, AssertionError]: assert minute in range(0, 60), "Invalid minute range - must be between (inclusive) 0 & 59" if minute % 15 != 0: warnings.warn( - UserWarning( - "Time '%s:%s' is probably not a valid timetable time, as lessons are every 15 minutes." - ) + UserWarning("Time '%s:%s' is probably not a valid timetable time, as lessons are every 15 minutes.") ) return True + try: return inner() except AssertionError as e: diff --git a/utils/__init__.py b/utils/__init__.py index de3ac85..1526b8e 100644 --- a/utils/__init__.py +++ b/utils/__init__.py @@ -8,11 +8,7 @@ from .views import * def simple_embed_paginator( - lines: list[str], - *, - assert_ten: bool = False, - empty_is_none: bool = True, - **kwargs + lines: list[str], *, assert_ten: bool = False, empty_is_none: bool = True, **kwargs ) -> Optional[list[discord.Embed]]: """Paginates x lines into x embeds.""" if not lines and empty_is_none is True: diff --git a/utils/_email.py b/utils/_email.py index 7243e8c..4d10b25 100644 --- a/utils/_email.py +++ b/utils/_email.py @@ -19,6 +19,7 @@ class _FakeUser: def __str__(self): import random + return f"{random.choice(self.names)}#{str(random.randint(1, 9999)).zfill(4)}" diff --git a/utils/db.py b/utils/db.py index 45316db..46c2da9 100644 --- a/utils/db.py +++ b/utils/db.py @@ -21,17 +21,9 @@ class Tutors(IntEnum): os.chdir(Path(__file__).parent.parent) -__all__ = [ - "registry", - "get_or_none", - "VerifyCode", - "Student", - "BannedStudentID", - "Assignments", - "Tutors" -] +__all__ = ["registry", "get_or_none", "VerifyCode", "Student", "BannedStudentID", "Assignments", "Tutors"] -T = TypeVar('T') +T = TypeVar("T") T_co = TypeVar("T_co", covariant=True) @@ -83,7 +75,7 @@ class BannedStudentID(orm.Model): "entry_id": orm.UUID(primary_key=True, default=uuid.uuid4), "student_id": orm.String(min_length=7, max_length=7, unique=True), "associated_account": orm.BigInteger(default=None), - "banned_at_timestamp": orm.Float(default=lambda: datetime.datetime.utcnow().timestamp()) + "banned_at_timestamp": orm.Float(default=lambda: datetime.datetime.utcnow().timestamp()), } if TYPE_CHECKING: entry_id: uuid.UUID @@ -105,7 +97,7 @@ class Assignments(orm.Model): "tutor": orm.Enum(Tutors), "reminders": orm.JSON(default=[]), "finished": orm.Boolean(default=False), - "submitted": orm.Boolean(default=False) + "submitted": orm.Boolean(default=False), } if TYPE_CHECKING: entry_id: int diff --git a/utils/views.py b/utils/views.py index 31b6b12..9ce1705 100644 --- a/utils/views.py +++ b/utils/views.py @@ -12,11 +12,7 @@ class VerifyView(discord.ui.View): self.ctx = ctx super().__init__(timeout=300, disable_on_timeout=True) - @discord.ui.button( - label="I have a verification code!", - emoji="\U0001f4e7", - custom_id="have" - ) + @discord.ui.button(label="I have a verification code!", emoji="\U0001f4e7", custom_id="have") async def have(self, _, interaction1: discord.Interaction): class Modal(discord.ui.Modal): def __init__(self): @@ -25,8 +21,8 @@ class VerifyView(discord.ui.View): custom_id="code", label="Verification Code", placeholder="e.g: " + secrets.token_hex(TOKEN_LENGTH), - min_length=TOKEN_LENGTH*2, - max_length=TOKEN_LENGTH*2, + min_length=TOKEN_LENGTH * 2, + max_length=TOKEN_LENGTH * 2, ), title="Enter the verification code in your inbox", ) @@ -51,7 +47,7 @@ class VerifyView(discord.ui.View): self.stop() return await interaction.user.ban( reason=f"Attempted to verify with banned student ID {ban.student_id}" - f" (originally associated with account {ban.associated_account})" + f" (originally associated with account {ban.associated_account})" ) await Student.objects.create(id=existing.student_id, user_id=interaction.user.id) await existing.delete() @@ -62,8 +58,7 @@ class VerifyView(discord.ui.View): console.log(f"[green]{interaction.user} verified ({interaction.user.id}/{existing.student_id})") self.stop() return await interaction.followup.send( - "\N{white heavy check mark} Verification complete!", - ephemeral=True + "\N{white heavy check mark} Verification complete!", ephemeral=True ) await interaction1.response.send_modal(Modal()) @@ -71,10 +66,7 @@ class VerifyView(discord.ui.View): await interaction1.edit_original_response(view=self) await interaction1.delete_original_response(delay=1) - @discord.ui.button( - label="Send me a verification code.", - emoji="\U0001f4e5" - ) + @discord.ui.button(label="Send me a verification code.", emoji="\U0001f4e5") async def send(self, btn: discord.ui.Button, interaction1: discord.Interaction): class Modal(discord.ui.Modal): def __init__(self): @@ -87,7 +79,7 @@ class VerifyView(discord.ui.View): max_length=7, ), title="Enter your student ID number", - timeout=120 + timeout=120, ) async def callback(self, interaction: discord.Interaction): @@ -98,17 +90,13 @@ class VerifyView(discord.ui.View): if not re.match(r"^B\d{6}$", st): btn.disabled = False - return await interaction.followup.send( - "\N{cross mark} Invalid student ID.", - delete_after=60 - ) + return await interaction.followup.send("\N{cross mark} Invalid student ID.", delete_after=60) ex = await get_or_none(Student, id=st) if ex: btn.disabled = False return await interaction.followup.send( - "\N{cross mark} Student ID is already associated.", - delete_after=60 + "\N{cross mark} Student ID is already associated.", delete_after=60 ) try: @@ -117,8 +105,9 @@ class VerifyView(discord.ui.View): return await interaction.followup.send(f"\N{cross mark} Failed to send email - {e}. Try again?") console.log(f"Sending verification email to {interaction.user} ({interaction.user.id}/{st})...") __code = await VerifyCode.objects.create(code=_code, bind=interaction.id, student_id=st) - console.log(f"[green]Sent verification email to {interaction.user} ({interaction.user.id}/{st}): " - f"{_code!r}") + console.log( + f"[green]Sent verification email to {interaction.user} ({interaction.user.id}/{st}): " f"{_code!r}" + ) await interaction.followup.send( "\N{white heavy check mark} Verification email sent to your college email " f"({st}@my.leedscitycollege.ac.uk)\n" @@ -140,14 +129,9 @@ class VerifyView(discord.ui.View): await modal.wait() await interaction1.edit_original_response(view=self) - @discord.ui.button( - label="Why do I need a verification code?", - emoji="\U0001f616" - ) + @discord.ui.button(label="Why do I need a verification code?", emoji="\U0001f616") async def why(self, _, interaction: discord.Interaction): - await interaction.response.defer( - ephemeral=True - ) + await interaction.response.defer(ephemeral=True) await interaction.followup.send( "In order to access this server, you need to enter your student ID.\n" "We require this to make sure only **students** in our course can access the server.\n" @@ -155,6 +139,5 @@ class VerifyView(discord.ui.View): "This is not invading your privacy, your B number is publicly visible, as it is the start of your email," " plus can be found on google chat.", ephemeral=True, - delete_after=60 + delete_after=60, ) -