Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
8d98bcb
Update dependencies
CarrotManMatt Jul 12, 2024
a609157
Improve selected linting rules
CarrotManMatt Jul 12, 2024
50d33ee
Improve `GetTokenAuthorisationCommandCog` name
CarrotManMatt Jul 12, 2024
1a8a41b
Improve `MessageSavingSenderComponent` name
CarrotManMatt Jul 12, 2024
fb360b4
Ensure command descriptions end with punctuation
CarrotManMatt Jul 12, 2024
6840280
Make all custom exceptions inherit from `BaseTeXBotError`
CarrotManMatt Jul 12, 2024
26907c9
Fix references of "the bot" into "TeX-Bot"
CarrotManMatt Jul 12, 2024
0d95015
Ensure all loggers annotated as `Final`
CarrotManMatt Jul 12, 2024
650e8ff
Use improved set type annotation in autocomplete functions
CarrotManMatt Jul 13, 2024
732bef9
Use improved formatting of channel & role names
CarrotManMatt Jul 13, 2024
347106c
Make command names hyphenated
CarrotManMatt Jul 13, 2024
77afbe6
Use `re.fullmatch()`, rather than ~`re.match`~
CarrotManMatt Jul 13, 2024
4908ba7
Fix missed references of "the bot" to "TeX-Bot"
CarrotManMatt Jul 13, 2024
53f3de8
Add subclass `@override` decorator for overridden methods
CarrotManMatt Jul 13, 2024
53ea6e1
Fix missed references of "the bot" to "TeX-Bot"
CarrotManMatt Jul 13, 2024
5e8c78d
Use relative imports inside local packages to fix cyclical import errors
CarrotManMatt Jul 13, 2024
a6f1611
Fix missing import & class export
CarrotManMatt Jul 13, 2024
3262c7b
Fix spelling & grammar mistakes
CarrotManMatt Jul 13, 2024
788a136
Change calls to functions to use keyword arguments to be more explicit
CarrotManMatt Jul 13, 2024
5afc748
Fix incorrect usage of whitespace and newlines
CarrotManMatt Jul 13, 2024
9a00a06
Improve ordering of Dockerfile directory copying
CarrotManMatt Jul 13, 2024
2a445ce
Fix grammar error
CarrotManMatt Jul 13, 2024
e937704
Use the term "main guild" rather than just "guild" & improve shortcut…
CarrotManMatt Jul 14, 2024
f4c3d39
Improve f-string formatting
CarrotManMatt Jul 14, 2024
c8a7bb8
Improve values embedded within strings
CarrotManMatt Jul 14, 2024
127fb20
Improve usage of `Final` constants & capitalisation
CarrotManMatt Jul 14, 2024
2590973
Fix missed `Final` constant usage
CarrotManMatt Jul 14, 2024
03b9e0f
Improve ping command response message
CarrotManMatt Jul 14, 2024
ff47669
Improve source command response message
CarrotManMatt Jul 14, 2024
0a56269
Improve autocomplete exception handling
CarrotManMatt Jul 14, 2024
475d2a5
Improve function names
CarrotManMatt Jul 14, 2024
49e8e3c
Fix missing linting error changes
CarrotManMatt Jul 14, 2024
c0bcd5f
Fix more uses of the term "guild" rather than "main guild"
CarrotManMatt Jul 14, 2024
44d2104
Fix incorrect punctuation
CarrotManMatt Jul 14, 2024
befbc15
Fix more incorrect linting ignores & whitespace
CarrotManMatt Jul 14, 2024
541661c
Improve guard-clause function returns
CarrotManMatt Jul 14, 2024
b832389
Improve settings names
CarrotManMatt Jul 14, 2024
d8c77b4
Fix command description
CarrotManMatt Jul 14, 2024
9bcddd4
Improve type annotations for messages iterable
CarrotManMatt Jul 14, 2024
f3296a4
Fix missed use of the term "guild" rather than "main guild"
CarrotManMatt Jul 14, 2024
828fc0f
Improve running in `main.py`
CarrotManMatt Jul 14, 2024
c4b826e
Fix missed unhyphenated command name
CarrotManMatt Jul 14, 2024
884e90a
Improve string handling
CarrotManMatt Jul 14, 2024
eafa980
Annotate that `discord.Bot.close()` function will not return
CarrotManMatt Jul 14, 2024
510317f
Improve error handling with `TeXBot.close()` function
CarrotManMatt Jul 14, 2024
2a97bd3
Fix typing & linting errors
CarrotManMatt Jul 14, 2024
4e9acec
Fix missed spelling mistakes
CarrotManMatt Jul 14, 2024
04227bf
Fix linting error
CarrotManMatt Jul 14, 2024
9831bca
Fix missing spaces in `#noqa` comments
CarrotManMatt Jul 15, 2024
97faec4
Merge branch 'main' into small-fixes
CarrotManMatt Jul 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
python-version: 3.12

- name: Run Ruff
run: poetry run ruff check . --no-fix --extend-select TD002,TD003
run: poetry run ruff check . --no-fix

poetry-check:
runs-on: ubuntu-latest
Expand Down
8 changes: 4 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ We recommend also reading the following if you're unsure or not confident:
* [How To Make A Pull Request](https://makeapullrequest.com)
* [Contributing To An Open Source Project For The First Time](https://firsttimersonly.com)

This bot is written in [Python](https://python.org) using [Pycord](https://pycord.dev) and uses Discord's [slash-commands](https://support.discord.com/hc/articles/1500000368501-Slash-Commands-FAQ) & [user-commands](https://guide.pycord.dev/interactions/application-commands/context-menus).
TeX-Bot is written in [Python](https://python.org) using [Pycord](https://pycord.dev) and uses Discord's [slash-commands](https://support.discord.com/hc/articles/1500000368501-Slash-Commands-FAQ) & [user-commands](https://guide.pycord.dev/interactions/application-commands/context-menus).
We would recommend being somewhat familiar with the [Pycord library](https://docs.pycord.dev), [Python language](https://docs.python.org/3/reference/index) & [project terminology](README.md#terminology) before contributing.

## Using the Issue Tracker

We use [GitHub issues](https://docs.github.com/issues) to track bugs and feature requests.
If you find an issue with the bot, the best place to report it is through the issue tracker.
If you find an issue with TeX-Bot, the best place to report it is through the issue tracker.
If you are looking for issues to contribute code to, it's a good idea to look at the [issues labelled "good-first-issue"](https://github.com/CSSUoB/TeX-Bot-Py-V2/issues?q=label%3A%22good+first+issue%22)!

When submitting an issue, please be as descriptive as possible.
Expand Down Expand Up @@ -79,7 +79,7 @@ There are separate cog files for each activity, and one [`__init__.py`](cogs/__i

* [`cogs/delete_all.py`](cogs/delete_all.py): cogs for deleting all permanent data stored in a specific object's table in the database

* [`cogs/edit_message.py`](cogs/edit_message.py): cogs for editing messages that were previously sent by the bot
* [`cogs/edit_message.py`](cogs/edit_message.py): cogs for editing messages that were previously sent by TeX-Bot

* [`cogs/induct.py`](cogs/induct.py): cogs for inducting people into your group's Discord guild

Expand All @@ -89,7 +89,7 @@ There are separate cog files for each activity, and one [`__init__.py`](cogs/__i

* [`cogs/ping.py`](cogs/ping.py): cog to request a [ping](https://wikipedia.org/wiki/Ping-pong_scheme#Internet) response

* [`cogs/remind_me.py`](cogs/remind_me.py): cogs to ask the bot to send a reminder message at a later date
* [`cogs/remind_me.py`](cogs/remind_me.py): cogs to ask TeX-Bot to send a reminder message at a later date

* [`cogs/send_get_roles_reminders.py`](cogs/send_get_roles_reminders.py): cogs relating to sending reminders, to Discord members, about opt-in roles.
(See [Repeated Tasks Conditions](README.md#repeated-tasks-conditions) for which conditions are required to be met, to execute this task)
Expand Down
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ WORKDIR /app
COPY LICENSE .en[v] config.py main.py messages.json ./
RUN chmod +x main.py

COPY cogs/ ./cogs/
COPY db/ ./db/
COPY utils/ ./utils/
COPY exceptions/ ./exceptions/
COPY utils/ ./utils/
COPY db/ ./db/
COPY cogs/ ./cogs/

ENTRYPOINT ["python", "-m", "main"]
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ The meaning of each error code is given here:
* `E1023` - Your [Discord guild](https://discord.com/developers/docs/resources/guild) does not contain a [role](https://discord.com/developers/docs/topics/permissions#role-object) with the name "@**Member**".
(This [role](https://discord.com/developers/docs/topics/permissions#role-object) is required for the `/makemember` & `/ensure-members-inducted` [commands](https://discord.com/developers/docs/interactions/application-commands))

* `E1024` - Your [Discord guild](https://discord.com/developers/docs/resources/guild) does not contain a [role](https://discord.com/developers/docs/topics/permissions#role-object) with the name "**@Archivist**".
* `E1024` - Your [Discord guild](https://discord.com/developers/docs/resources/guild) does not contain a [role](https://discord.com/developers/docs/topics/permissions#role-object) with the name "@**Archivist**".
(This [role](https://discord.com/developers/docs/topics/permissions#role-object) is required for the `/archive` [command](https://discord.com/developers/docs/interactions/application-commands))

* `E1025` - Your [Discord guild](https://discord.com/developers/docs/resources/guild) does not contain a [role](https://discord.com/developers/docs/topics/permissions#role-object) with the name "**@Applicant**". (This [role](https://discord.com/developers/docs/topics/permissions#role-object) is required for the `/make-applicant` [command](https://discord.com/developers/docs/interactions/application-commands) and respective user and message commands)
* `E1025` - Your [Discord guild](https://discord.com/developers/docs/resources/guild) does not contain a [role](https://discord.com/developers/docs/topics/permissions#role-object) with the name "@**Applicant**". (This [role](https://discord.com/developers/docs/topics/permissions#role-object) is required for the `/make-applicant` [command](https://discord.com/developers/docs/interactions/application-commands) and respective user and message commands)

* `E1026` - Your [Discord guild](https://discord.com/developers/docs/resources/guild) does not contain a [role](https://discord.com/developers/docs/topics/permissions#role-objec) with the name "@**Committee-Elect**".
(This [role](https://discord.com/developers/docs/topics/permissions#role-object) is required for the `/handover` [command](https://discord.com/developers/docs/interactions/application-commands))
Expand Down
6 changes: 3 additions & 3 deletions cogs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

__all__: Sequence[str] = (
"ArchiveCommandCog",
"GetTokenAuthorisationCommand",
"GetTokenAuthorisationCommandCog",
"CommandErrorCog",
"DeleteAllCommandsCog",
"EditMessageCommandCog",
Expand Down Expand Up @@ -49,7 +49,7 @@
from cogs.command_error import CommandErrorCog
from cogs.delete_all import DeleteAllCommandsCog
from cogs.edit_message import EditMessageCommandCog
from cogs.get_token_authorisation import GetTokenAuthorisationCommand
from cogs.get_token_authorisation import GetTokenAuthorisationCommandCog
from cogs.induct import (
EnsureMembersInductedCommandCog,
InductContextCommandsCog,
Expand Down Expand Up @@ -80,7 +80,7 @@ def setup(bot: TeXBot) -> None:
"""Add all the cogs to the bot, at bot startup."""
cogs: Iterable[type[TeXBotBaseCog]] = (
ArchiveCommandCog,
GetTokenAuthorisationCommand,
GetTokenAuthorisationCommandCog,
CommandErrorCog,
DeleteAllCommandsCog,
EditMessageCommandCog,
Expand Down
14 changes: 7 additions & 7 deletions cogs/annual_handover_and_reset.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class CommitteeHandoverCommandCog(TeXBotBaseCog):

@discord.slash_command( # type: ignore[no-untyped-call, misc]
name="committee-handover",
description="Initiates the annual Discord handover procedure for new committee",
description="Initiates the annual Discord handover procedure for new committee.",
)
@CommandChecks.check_interaction_user_has_committee_role
@CommandChecks.check_interaction_user_in_main_guild
Expand All @@ -40,9 +40,9 @@ async def committee_handover(self, ctx: TeXBotApplicationContext) -> None:
To do this, TeX-Bot will need to hold a role above that of the "Committee" role.
"""
# NOTE: Shortcut accessors are placed at the top of the function, so that the exceptions they raise are displayed before any further errors may be sent
main_guild: discord.Guild = self.bot.main_guild
committee_role: discord.Role = await self.bot.committee_role
committee_elect_role: discord.Role = await self.bot.committee_elect_role
main_guild: discord.Guild = self.tex_bot.main_guild
committee_role: discord.Role = await self.tex_bot.committee_role
committee_elect_role: discord.Role = await self.tex_bot.committee_elect_role

initial_response: discord.Interaction | discord.WebhookMessage = await ctx.respond(
content=":hourglass: Running handover procedures... :hourglass:",
Expand Down Expand Up @@ -163,7 +163,7 @@ class AnnualRolesResetCommandCog(TeXBotBaseCog):

@discord.slash_command( # type: ignore[no-untyped-call, misc]
name="annual-roles-reset",
description="Removes the @Member role and academic year roles from all users",
description="Removes the @Member role and academic year roles from all users.",
)
@CommandChecks.check_interaction_user_has_committee_role
@CommandChecks.check_interaction_user_in_main_guild
Expand All @@ -176,8 +176,8 @@ async def annual_roles_reset(self, ctx: TeXBotApplicationContext) -> None:
the GroupMadeMember database model.
"""
# NOTE: Shortcut accessors are placed at the top of the function, so that the exceptions they raise are displayed before any further errors may be sent
main_guild: discord.Guild = self.bot.main_guild
member_role: discord.Role = await self.bot.member_role
main_guild: discord.Guild = self.tex_bot.main_guild
member_role: discord.Role = await self.tex_bot.member_role

logger.debug("Reset roles command called.")
initial_response: discord.Interaction | discord.WebhookMessage = await ctx.respond(
Expand Down
56 changes: 30 additions & 26 deletions cogs/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

import logging
import re
from collections.abc import Set
from logging import Logger
from typing import Final

import discord

Expand All @@ -21,34 +23,34 @@
TeXBotBaseCog,
)

logger: Logger = logging.getLogger("TeX-Bot")
logger: Final[Logger] = logging.getLogger("TeX-Bot")


class ArchiveCommandCog(TeXBotBaseCog):
"""Cog class that defines the "/archive" command and its call-back method."""

@staticmethod
async def autocomplete_get_categories(ctx: TeXBotAutocompleteContext) -> set[discord.OptionChoice]: # noqa: E501
async def autocomplete_get_categories(ctx: TeXBotAutocompleteContext) -> Set[discord.OptionChoice] | Set[str]: # noqa: E501
"""
Autocomplete callable that generates the set of available selectable categories.

The list of available selectable categories is unique to each member, and is used in
The list of available selectable categories is unique to each member and is used in
any of the "archive" slash-command options that have a category input-type.
"""
if not ctx.interaction.user:
return set()

try:
main_guild: discord.Guild = ctx.bot.main_guild
interaction_user: discord.Member = await ctx.bot.get_main_guild_member(
if not await ctx.tex_bot.check_user_has_committee_role(ctx.interaction.user):
return set()

main_guild: discord.Guild = ctx.tex_bot.main_guild
interaction_user: discord.Member = await ctx.tex_bot.get_main_guild_member(
ctx.interaction.user,
)
except (BaseDoesNotExistError, DiscordMemberNotInMainGuildError):
return set()

if not await ctx.bot.check_user_has_committee_role(interaction_user):
return set()

return {
discord.OptionChoice(name=category.name, value=str(category.id))
for category
Expand Down Expand Up @@ -80,15 +82,15 @@ async def archive(self, ctx: TeXBotApplicationContext, str_category_id: str) ->
have the "Archivist" role.
"""
# NOTE: Shortcut accessors are placed at the top of the function, so that the exceptions they raise are displayed before any further errors may be sent
main_guild: discord.Guild = self.bot.main_guild
interaction_member: discord.Member = await self.bot.get_main_guild_member(ctx.user)
committee_role: discord.Role = await self.bot.committee_role
guest_role: discord.Role = await self.bot.guest_role
member_role: discord.Role = await self.bot.member_role
archivist_role: discord.Role = await self.bot.archivist_role
everyone_role: discord.Role = await self.bot.get_everyone_role()

if not re.match(r"\A\d{17,20}\Z", str_category_id):
main_guild: discord.Guild = self.tex_bot.main_guild
interaction_member: discord.Member = await self.tex_bot.get_main_guild_member(ctx.user)
committee_role: discord.Role = await self.tex_bot.committee_role
guest_role: discord.Role = await self.tex_bot.guest_role
member_role: discord.Role = await self.tex_bot.member_role
archivist_role: discord.Role = await self.tex_bot.archivist_role
everyone_role: discord.Role = await self.tex_bot.get_everyone_role()

if not re.fullmatch(r"\A\d{17,20}\Z", str_category_id):
await self.command_send_error(
ctx,
message=f"{str_category_id!r} is not a valid category ID.",
Expand Down Expand Up @@ -121,19 +123,19 @@ async def archive(self, ctx: TeXBotApplicationContext, str_category_id: str) ->
channel: AllChannelTypes
for channel in category.channels:
try:
channel_needs_committee_archiving: bool = (
CHANNEL_NEEDS_COMMITTEE_ARCHIVING: bool = (
channel.permissions_for(committee_role).is_superset(
discord.Permissions(view_channel=True),
) and not channel.permissions_for(guest_role).is_superset(
discord.Permissions(view_channel=True),
)
)
channel_needs_normal_archiving: bool = channel.permissions_for(
guest_role,
).is_superset(
discord.Permissions(view_channel=True),
CHANNEL_NEEDS_NORMAL_ARCHIVING: bool = (
channel.permissions_for(guest_role).is_superset(
discord.Permissions(view_channel=True),
)
)
if channel_needs_committee_archiving:
if CHANNEL_NEEDS_COMMITTEE_ARCHIVING:
await channel.set_permissions(
everyone_role,
reason=f"{interaction_member.display_name} used \"/archive\".",
Expand All @@ -155,7 +157,7 @@ async def archive(self, ctx: TeXBotApplicationContext, str_category_id: str) ->
reason=f"{interaction_member.display_name} used \"/archive\".",
)

elif channel_needs_normal_archiving:
elif CHANNEL_NEEDS_NORMAL_ARCHIVING:
await channel.set_permissions(
everyone_role,
reason=f"{interaction_member.display_name} used \"/archive\".",
Expand Down Expand Up @@ -197,12 +199,14 @@ async def archive(self, ctx: TeXBotApplicationContext, str_category_id: str) ->
await self.command_send_error(
ctx,
message=(
"Bot does not have access to the channels in the selected category."
"TeX-Bot does not have access to "
"the channels in the selected category."
),
)
logger.error( # noqa: TRY400
(
"Bot did not have access to the channels in the selected category: "
"TeX-Bot did not have access to "
"the channels in the selected category: "
"%s."
),
category.name,
Expand Down
10 changes: 6 additions & 4 deletions cogs/command_error.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import contextlib
import logging
from logging import Logger
from typing import Final

import discord
from discord import Forbidden
Expand All @@ -20,7 +21,7 @@
from exceptions.base import BaseErrorWithErrorCode
from utils import CommandChecks, TeXBotApplicationContext, TeXBotBaseCog

logger: Logger = logging.getLogger("TeX-Bot")
logger: Final[Logger] = logging.getLogger("TeX-Bot")


class CommandErrorCog(TeXBotBaseCog):
Expand Down Expand Up @@ -48,15 +49,16 @@ async def on_application_command_error(self, ctx: TeXBotApplicationContext, erro
elif isinstance(error, CheckAnyFailure):
if CommandChecks.is_interaction_user_in_main_guild_failure(error.checks[0]):
message = (
f"You must be a member of the {self.bot.group_short_name} Discord server "
"You must be a member of "
f"the {self.tex_bot.group_short_name} Discord server "
"to use this command."
)

elif CommandChecks.is_interaction_user_has_committee_role_failure(error.checks[0]):
# noinspection PyUnusedLocal
committee_role_mention: str = "@Committee"
with contextlib.suppress(CommitteeRoleDoesNotExistError):
committee_role_mention = (await self.bot.committee_role).mention
committee_role_mention = (await self.tex_bot.committee_role).mention
message = f"Only {committee_role_mention} members can run this command."

await self.command_send_error(
Expand Down Expand Up @@ -85,4 +87,4 @@ async def on_application_command_error(self, ctx: TeXBotApplicationContext, erro
if message_part
),
)
await self.bot.close()
await self.tex_bot.close()
6 changes: 4 additions & 2 deletions cogs/delete_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ class DeleteAllCommandsCog(TeXBotBaseCog):
"""Cog class that defines the "/delete-all" command group and command call-back methods."""

delete_all: discord.SlashCommandGroup = discord.SlashCommandGroup(
"delete-all",
"Delete all instances of the selected object type from the backend database",
name="delete-all",
description=(
"Delete all instances of the selected object type from the backend database"
),
)

@staticmethod
Expand Down
Loading