diff --git a/techsupport_bot/commands/animal.py b/techsupport_bot/commands/animal.py index ec2fb2a47..f03ab8d10 100644 --- a/techsupport_bot/commands/animal.py +++ b/techsupport_bot/commands/animal.py @@ -1,11 +1,22 @@ """Module for the animal extension for the discord bot.""" +from __future__ import annotations + +from typing import TYPE_CHECKING + from core import auxiliary, cogs from discord.ext import commands +if TYPE_CHECKING: + import bot + + +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the animals plugin into the bot -async def setup(bot) -> None: - """Loading the animal plugin""" + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + """ await bot.add_cog(Animals(bot=bot)) diff --git a/techsupport_bot/commands/bot.py b/techsupport_bot/commands/bot.py index e72661300..edf2e48dd 100644 --- a/techsupport_bot/commands/bot.py +++ b/techsupport_bot/commands/bot.py @@ -7,16 +7,26 @@ .bot """ +from __future__ import annotations + import re +from typing import TYPE_CHECKING import discord import git from core import auxiliary, cogs from discord.ext import commands +if TYPE_CHECKING: + import bot + -async def setup(bot) -> None: - """Registers the BotInfo Cog""" +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the BotInfo plugin into the bot + + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + """ await bot.add_cog(BotInfo(bot=bot)) diff --git a/techsupport_bot/commands/burn.py b/techsupport_bot/commands/burn.py index fc1b97674..476101300 100644 --- a/techsupport_bot/commands/burn.py +++ b/techsupport_bot/commands/burn.py @@ -4,15 +4,25 @@ This modules requires no config, no databases, and no APIs """ +from __future__ import annotations + import random +from typing import TYPE_CHECKING, Self import discord from core import auxiliary, cogs from discord.ext import commands +if TYPE_CHECKING: + import bot + + +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the Burn plugin into the bot -async def setup(bot) -> None: - """Method to add burn command to config.""" + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + """ await bot.add_cog(Burn(bot=bot)) @@ -29,7 +39,10 @@ class Burn(cogs.BaseCog): ] async def handle_burn( - self, ctx: commands.Context, user: discord.Member, message: discord.Message + self: Self, + ctx: commands.Context, + user: discord.Member, + message: discord.Message, ) -> None: """The core logic to handle the burn command diff --git a/techsupport_bot/commands/chatgpt.py b/techsupport_bot/commands/chatgpt.py index a48d0e323..4a22e7d18 100644 --- a/techsupport_bot/commands/chatgpt.py +++ b/techsupport_bot/commands/chatgpt.py @@ -10,6 +10,10 @@ Defines: None """ +from __future__ import annotations + +from typing import TYPE_CHECKING + import discord import expiringdict import ui @@ -17,9 +21,19 @@ from core import auxiliary, cogs from discord.ext import commands +if TYPE_CHECKING: + import bot + + +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the ChatGPT plugin into the bot + + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to -async def setup(bot) -> None: - """Registers the extension""" + Raises: + AttributeError: Raised if an API key is missing to prevent unusable commands from loading + """ # Don't load without the API key try: diff --git a/techsupport_bot/commands/commandcontrol.py b/techsupport_bot/commands/commandcontrol.py index 26f40d52d..02ec9c402 100644 --- a/techsupport_bot/commands/commandcontrol.py +++ b/techsupport_bot/commands/commandcontrol.py @@ -8,12 +8,23 @@ .command enable """ +from __future__ import annotations + +from typing import TYPE_CHECKING + from core import auxiliary, cogs from discord.ext import commands +if TYPE_CHECKING: + import bot + -async def setup(bot) -> None: - """Registers the CommandControl Cog""" +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the Command Control plugin into the bot + + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + """ await bot.add_cog(CommandControl(bot=bot)) diff --git a/techsupport_bot/commands/conch.py b/techsupport_bot/commands/conch.py index f4fbb0989..3ff84b2b2 100644 --- a/techsupport_bot/commands/conch.py +++ b/techsupport_bot/commands/conch.py @@ -4,15 +4,25 @@ This modules requires no config, no databases, and no APIs """ +from __future__ import annotations + import random +from typing import TYPE_CHECKING import discord from core import auxiliary, cogs from discord.ext import commands +if TYPE_CHECKING: + import bot + + +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the Magic Conch plugin into the bot -async def setup(bot) -> None: - """Method to add conch to the config in discord bot.""" + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + """ await bot.add_cog(MagicConch(bot=bot)) @@ -87,5 +97,11 @@ async def conch_command(self, ctx: commands.Context, question: str = "") -> None usage="[question]", ) async def ask_question(self, ctx: commands.Context, *, question: str = "") -> None: - """Method for how the conch command works for the bot.""" + """Method for how the conch command works for the bot. + This is a command and should be run via discord + + Args: + ctx (commands.Context): The context in which the command was run + question (str, optional): The question to ask the magic conch. Defaults to "". + """ await self.conch_command(ctx, question) diff --git a/techsupport_bot/commands/config.py b/techsupport_bot/commands/config.py index a4a3687dd..d6ebd9c4f 100644 --- a/techsupport_bot/commands/config.py +++ b/techsupport_bot/commands/config.py @@ -1,17 +1,27 @@ """Module for config commands.""" +from __future__ import annotations + import datetime import io import json +from typing import TYPE_CHECKING import discord import ui from core import auxiliary, cogs from discord.ext import commands +if TYPE_CHECKING: + import bot + + +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the Guild Config plugin into the bot -async def setup(bot) -> None: - """Method to add burn command to config.""" + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + """ await bot.add_cog(ConfigControl(bot=bot)) diff --git a/techsupport_bot/commands/correct.py b/techsupport_bot/commands/correct.py index dd2fa7e02..ecd3edf5d 100644 --- a/techsupport_bot/commands/correct.py +++ b/techsupport_bot/commands/correct.py @@ -4,13 +4,24 @@ This modules requires no config, no databases, and no APIs """ +from __future__ import annotations + +from typing import TYPE_CHECKING + import discord from core import auxiliary, cogs from discord.ext import commands +if TYPE_CHECKING: + import bot + + +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the Correct plugin into the bot -async def setup(bot) -> None: - """Method to add correct to the config.""" + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + """ await bot.add_cog(Corrector(bot=bot)) @@ -80,5 +91,11 @@ def prepare_message( async def correct( self, ctx: commands.Context, to_replace: str, replacement: str ) -> None: - """Method for the correct command for the discord bot.""" + """Discord entry point into the correct command + + Args: + ctx (commands.Context): The context in which the command was run + to_replace (str): What is being searched for to replace + replacement (str): What to replace to_replace with + """ await self.correct_command(ctx, to_replace, replacement) diff --git a/techsupport_bot/commands/duck.py b/techsupport_bot/commands/duck.py index aa481f308..b080c2623 100644 --- a/techsupport_bot/commands/duck.py +++ b/techsupport_bot/commands/duck.py @@ -7,7 +7,7 @@ import functools import random from datetime import timedelta -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Self import discord import munch @@ -21,8 +21,12 @@ import bot -async def setup(bot) -> None: - """Method to add duck into the config file""" +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the Duck plugin into the bot + + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + """ config = extensionconfig.ExtensionConfig() config.add( @@ -98,12 +102,17 @@ class DuckHunt(cogs.LoopCog): ON_START = False CHANNELS_KEY = "hunt_channels" - async def loop_preconfig(self) -> None: + async def loop_preconfig(self: Self) -> None: """Preconfig for cooldowns""" self.cooldowns = {} - async def wait(self, config, _) -> None: - """Method for the duck loop""" + async def wait(self: Self, config: munch.Munch, _: discord.Guild) -> None: + """Waits a random amount of time before sending another duck + This function shouldn't be manually called + + Args: + config (munch.Munch): The guild config to use to determine the min and max wait times + """ await asyncio.sleep( random.randint( config.extensions.duck.min_wait.value * 3600, @@ -112,9 +121,22 @@ async def wait(self, config, _) -> None: ) async def execute( - self, config, guild, channel, banned_user: discord.User = None + self: Self, + config: munch.Munch, + guild: discord.Guild, + channel: discord.abc.Messageable, + banned_user: discord.User = None, ) -> None: - """Method for sending the duck""" + """Sends a duck in the given channel + Can be manually called, and will be called automatically after wait() + + Args: + config (munch.Munch): The config of the guild where the duck is going + guild (discord.Guild): The guild where the duck is going + channel (discord.abc.Messageable): The channel to spawn the duck in + banned_user (discord.User, optional): A user that is not allowed to claim the duck. + Defaults to None. + """ if not channel: config = self.bot.guild_configs[str(guild.id)] log_channel = config.get("logging_channel") @@ -174,8 +196,12 @@ async def execute( else: await self.got_away(channel) - async def got_away(self, channel) -> None: - """Sends a "got away!" embed when timeout passes""" + async def got_away(self: Self, channel: discord.TextChannel) -> None: + """Sends a message telling everyone the duck got away + + Args: + channel (discord.TextChannel): The channel that the duck was previously in + """ embed = discord.Embed( title="A duck got away!", description="Then he waddled away, waddle waddle, 'til the very next day", @@ -271,14 +297,25 @@ def pick_quote(self) -> str: return random_line.strip() def message_check( - self, + self: Self, config: munch.Munch, channel: discord.abc.GuildChannel, duck_message: discord.Message, banned_user: discord.User, message: discord.Message, ) -> bool: - """Method to check if 'bef' or 'bang' was typed""" + """Checks if a message after the duck is a valid call to own the duck + + Args: + config (munch.Munch): The config of the guild where the duck is + channel (discord.abc.GuildChannel): The channel that the duck is in + duck_message (discord.Message): The message object of the duck embed + banned_user (discord.User): A user who is banned from claiming the duck + message (discord.Message): The raw message that was sent + + Returns: + bool: Whether the user should claim the duck or not + """ # ignore other channels if message.channel.id != channel.id: return False @@ -343,8 +380,20 @@ def message_check( return choice_ - async def get_duck_user(self, user_id, guild_id) -> bot.models.DuckUser: - """Method to get the duck winner""" + async def get_duck_user( + self: Self, user_id: int, guild_id: int + ) -> bot.models.DuckUser | None: + """If it exists, will return the duck winner database entry + + Args: + self (Self): _description_ + user_id (int): The integer ID of the user + guild_id (int): The guild ID of where the user belongs to + + Returns: + bot.models.DuckUser | None: The DuckUser database entry of the user/guild combo. + Or None if it doesn't exist + """ duck_user = ( await self.bot.models.DuckUser.query.where( self.bot.models.DuckUser.author_id == str(user_id) @@ -355,13 +404,16 @@ async def get_duck_user(self, user_id, guild_id) -> bot.models.DuckUser: return duck_user - async def get_global_record(self, guild_id) -> float: - """ - This is a function to get the current global speed record in a given guild + async def get_global_record(self: Self, guild_id: int) -> float: + """This is a function to get the current global speed record in a given guild + + Args: + guild_id (int): The ID of the guild in question - Parametrs: - guild_id -> The ID of the guild in question + Returns: + float: The exact decimal representation for the fastest speed record """ + query = await self.bot.models.DuckUser.query.where( self.bot.models.DuckUser.guild_id == str(guild_id) ).gino.all() @@ -377,8 +429,12 @@ async def get_global_record(self, guild_id) -> float: brief="Executes a duck command", description="Executes a duck command", ) - async def duck(self, ctx: commands.Context) -> None: - """Method to make the initial duck command""" + async def duck(self: Self, ctx: commands.Context) -> None: + """The bare .duck command. This does nothing but generate the help message + + Args: + ctx (commands.Context): The context in which the command was run in + """ # Executed if there are no/invalid args supplied await auxiliary.extension_help(self, ctx, self.__module__[9:]) @@ -391,9 +447,16 @@ async def duck(self, ctx: commands.Context) -> None: usage="@user (defaults to yourself)", ) async def stats( - self, ctx: commands.Context, *, user: discord.Member = None + self: Self, ctx: commands.Context, *, user: discord.Member = None ) -> None: - """Method for viewing duck stats""" + """Discord command for getting duck stats for a given user + + Args: + self (Self): _description_ + ctx (commands.Context): The context in which the command was run + user (discord.Member, optional): The member to lookup stats for. + Defaults to ctx.message.author. + """ if not user: user = ctx.message.author @@ -430,8 +493,12 @@ async def stats( brief="Get duck friendship scores", description="Gets duck friendship scores for all users", ) - async def friends(self, ctx: commands.Context) -> None: - """Method for viewing top friend counts""" + async def friends(self: Self, ctx: commands.Context) -> None: + """Discord commands to view high scores for befriended ducks + + Args: + ctx (commands.Context): The context in which the command was run + """ duck_users = ( await self.bot.models.DuckUser.query.order_by( -self.bot.models.DuckUser.befriend_count @@ -485,12 +552,14 @@ async def friends(self, ctx: commands.Context) -> None: brief="Get the record holder", description="Gets the current speed record holder, and their time", ) - async def record(self, ctx: commands.Context) -> None: - """ + async def record(self: Self, ctx: commands.Context) -> None: + """This outputs an embed shows the current speed record holder and their time This is a command and should be run via discord - This outputs an embed shows the current speed record holder and their time + Args: + ctx (commands.Context): The context in which the command was run """ + record_time = await self.get_global_record(ctx.guild.id) if record_time is None: await auxiliary.send_deny_embed( @@ -520,8 +589,12 @@ async def record(self, ctx: commands.Context) -> None: brief="Get duck kill scores", description="Gets duck kill scores for all users", ) - async def killers(self, ctx: commands.Context) -> None: - """Method for viewing top killer counts""" + async def killers(self: Self, ctx: commands.Context) -> None: + """Discord command to view high scores for killed ducks + + Args: + ctx (commands.Context): The context in which the command was run + """ duck_users = ( await self.bot.models.DuckUser.query.order_by( -self.bot.models.DuckUser.kill_count @@ -568,8 +641,15 @@ async def killers(self, ctx: commands.Context) -> None: await ui.PaginateView().send(ctx.channel, ctx.author, embeds) - def get_user_text(self, duck_user) -> str: - """Method to get the user for the top commands""" + def get_user_text(self: Self, duck_user: bot.models.DuckUser) -> str: + """Gets the name of a user formatted to be displayed across the extension + + Args: + duck_user (bot.models.DuckUser): The database entry of the user to format + + Returns: + str: The username in a pretty string format, ready to print + """ user = self.bot.get_user(int(duck_user.author_id)) if user: user_text = f"{user.display_name}" @@ -585,8 +665,13 @@ def get_user_text(self, duck_user) -> str: brief="Releases a duck into the wild", description="Returns a befriended duck to its natural habitat", ) - async def release(self, ctx: commands.Context) -> None: - """Method for releasing a duck""" + async def release(self: Self, ctx: commands.Context) -> None: + """Releases a duck into the wild, a duck will spawn in the channel this command is run from + This is a discord command + + Args: + ctx (commands.Context): The context in which the command was run + """ config = self.bot.guild_configs[str(ctx.guild.id)] if not config.extensions.duck.allow_manipulation.value: await auxiliary.send_deny_embed( @@ -625,8 +710,14 @@ async def release(self, ctx: commands.Context) -> None: "Adds a duck to your kill count. Why would you even want to do that?!" ), ) - async def kill(self, ctx: commands.Context) -> None: - """Method for killing ducks""" + async def kill(self: Self, ctx: commands.Context) -> None: + """Kills a friended duck and adds it to your kills. + Has a chance of failure + This is a discord command + + Args: + ctx (commands.Context): The context in which the command was run + """ config = self.bot.guild_configs[str(ctx.guild.id)] if not config.extensions.duck.allow_manipulation.value: await auxiliary.send_deny_embed( @@ -678,8 +769,16 @@ async def kill(self, ctx: commands.Context) -> None: description="Gives someone the gift of a live duck", usage="[user]", ) - async def donate(self, ctx: commands.Context, user: discord.Member) -> None: - """Method for donating ducks""" + async def donate(self: Self, ctx: commands.Context, user: discord.Member) -> None: + """Donates a befriended duck to a given user. Duck count will be subtracted from invoker + This has a chance of failure + This is a discord command + + Args: + self (Self): _description_ + ctx (commands.Context): The context in which the command was run + user (discord.Member): The user to donate a duck to + """ config = self.bot.guild_configs[str(ctx.guild.id)] if not config.extensions.duck.allow_manipulation.value: await auxiliary.send_deny_embed( @@ -750,8 +849,15 @@ async def donate(self, ctx: commands.Context, user: discord.Member) -> None: description="Deletes the database entry of the target", usage="[user]", ) - async def reset(self, ctx: commands.Context, user: discord.Member) -> None: - """Method for resetting duck counts""" + async def reset(self: Self, ctx: commands.Context, user: discord.Member) -> None: + """Admin only command to delete a database entry of a given user + This is a discord command + + Args: + self (Self): _description_ + ctx (commands.Context): The context in which the command was run + user (discord.Member): The user to reset + """ if user.bot: await auxiliary.send_deny_embed( message="You leave my ducks alone!", channel=ctx.channel diff --git a/techsupport_bot/commands/dumpdbg.py b/techsupport_bot/commands/dumpdbg.py index 3e2aa4797..1aa4173fd 100644 --- a/techsupport_bot/commands/dumpdbg.py +++ b/techsupport_bot/commands/dumpdbg.py @@ -1,15 +1,28 @@ """Module for the dumpdbg command on discord bot.""" +from __future__ import annotations + import json +from typing import TYPE_CHECKING, Self import discord from botlogging import LogContext, LogLevel from core import auxiliary, cogs, extensionconfig from discord.ext import commands +if TYPE_CHECKING: + import bot + + +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the DumpDBG plugin into the bot -async def setup(bot) -> None: - """Method to add the dumpdbg command to config.""" + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + + Raises: + AttributeError: Raised if an API key is missing to prevent unusable commands from loading + """ # Don't load without the API key try: @@ -46,8 +59,12 @@ class Dumpdbg(cogs.BaseCog): ), usage="|attached-dump-files|", ) - async def debug_dump(self, ctx: commands.Context) -> None: - """Method for the actual debugging""" + async def debug_dump(self: Self, ctx: commands.Context) -> None: + """The entry point and main logic for the dump debug command + + Args: + ctx (commands.Context): The context in which the command was run + """ config = self.bot.guild_configs[str(ctx.guild.id)] api_endpoint = self.bot.file_config.api.api_url.dumpdbg @@ -156,14 +173,14 @@ async def debug_dump(self, ctx: commands.Context) -> None: ) ) - async def get_files(self, ctx: commands.Context) -> list[str]: + async def get_files(self: Self, ctx: commands.Context) -> list[str]: """Gets files from passed message and checks if they are valid .dmp files - Params: - -> ctx (discord.Context) = The message to check + Args: + ctx (commands.Context): The message to check Returns: - -> Valid_URLs (list) = The list of valid .dmp CDN links + list[str]: The list of valid .dmp CDN links """ # Checks if attachments were supplied diff --git a/techsupport_bot/commands/echo.py b/techsupport_bot/commands/echo.py index ed8176c79..f262d31ad 100644 --- a/techsupport_bot/commands/echo.py +++ b/techsupport_bot/commands/echo.py @@ -8,12 +8,23 @@ .echo channel """ +from __future__ import annotations + +from typing import TYPE_CHECKING, Self + from core import auxiliary, cogs from discord.ext import commands +if TYPE_CHECKING: + import bot + -async def setup(bot) -> None: - """Registers the MessageEcho Cog""" +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the Echo plugin into the bot + + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + """ await bot.add_cog(MessageEcho(bot=bot)) @@ -26,7 +37,7 @@ class MessageEcho(cogs.BaseCog): @commands.group( brief="Executes an echo bot command", description="Executes an echo bot command" ) - async def echo(self, ctx: commands.Context) -> None: + async def echo(self: Self, ctx: commands.Context) -> None: """The bare .echo command. This does nothing but generate the help message Args: diff --git a/techsupport_bot/commands/embed.py b/techsupport_bot/commands/embed.py index f095a29a2..8a35eba89 100644 --- a/techsupport_bot/commands/embed.py +++ b/techsupport_bot/commands/embed.py @@ -10,14 +10,25 @@ Defines: has_embed_role """ +from __future__ import annotations + +from typing import TYPE_CHECKING + import discord import munch from core import auxiliary, cogs, extensionconfig from discord.ext import commands +if TYPE_CHECKING: + import bot + -async def setup(bot) -> None: - """Registers the extension and its config""" +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the Embed plugin into the bot + + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + """ config = extensionconfig.ExtensionConfig() config.add( key="embed_roles", diff --git a/techsupport_bot/commands/emoji.py b/techsupport_bot/commands/emoji.py index 7a0436ae9..d32a98f52 100644 --- a/techsupport_bot/commands/emoji.py +++ b/techsupport_bot/commands/emoji.py @@ -4,6 +4,9 @@ This modules requires no config, no databases, and no APIs """ +from __future__ import annotations + +from typing import TYPE_CHECKING, Self from unicodedata import lookup import discord @@ -12,9 +15,16 @@ from core import auxiliary, cogs from discord.ext import commands +if TYPE_CHECKING: + import bot + -async def setup(bot) -> None: - """Method to add emoji commands to config.""" +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the Emoji plugin into the bot + + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + """ await bot.add_cog(Emojis(bot=bot)) @@ -152,8 +162,12 @@ async def emoji_commands( brief="Executes an emoji command", description="Executes a emoji command", ) - async def emoji(self, ctx: commands.Context) -> None: - """Executed if there are no/invalid args supplied""" + async def emoji(self: Self, ctx: commands.Context) -> None: + """The bare .emoji command. This does nothing but generate the help message + + Args: + ctx (commands.Context): The context in which the command was run in + """ await auxiliary.extension_help(self, ctx, self.__module__[9:]) @auxiliary.with_typing @@ -163,9 +177,13 @@ async def emoji(self, ctx: commands.Context) -> None: description="Creates an emoji message", usage="[message]", ) - async def message(self, ctx: commands.Context, *, message: str) -> None: - """This is a command and should be run via discord - This is for generating a message of emojis""" + async def message(self: Self, ctx: commands.Context, *, message: str) -> None: + """Entry point for the message generation emoji command + + Args: + ctx (commands.Context): The context in which the command was run + message (str): The string to turn into emojis + """ await self.emoji_commands(ctx, message, False) @commands.has_permissions(add_reactions=True) @@ -178,7 +196,11 @@ async def message(self, ctx: commands.Context, *, message: str) -> None: async def reaction( self, ctx: commands.Context, message: str, react_user: discord.Member ) -> None: - """This is a command and should be run via discord - This is for reacting to a message with emojis - The message must be unique in this command""" + """Entry point for the reaction emoji command + + Args: + ctx (commands.Context): The context in which the command was run + message (str): The string to add as reactions + react_user (discord.Member): The member whose message is to be reacted to + """ await self.emoji_commands(ctx, message, True, react_user) diff --git a/techsupport_bot/commands/extension.py b/techsupport_bot/commands/extension.py index cb4e244e5..b43ffa54f 100644 --- a/techsupport_bot/commands/extension.py +++ b/techsupport_bot/commands/extension.py @@ -10,14 +10,25 @@ .extension register """ +from __future__ import annotations + +from typing import TYPE_CHECKING, Self + import discord import ui from core import auxiliary, cogs from discord.ext import commands +if TYPE_CHECKING: + import bot + -async def setup(bot) -> None: - """Registers the ExtensionControl Cog""" +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the Extension Control plugin into the bot + + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + """ await bot.add_cog(ExtensionControl(bot=bot)) @@ -32,7 +43,7 @@ class ExtensionControl(cogs.BaseCog): brief="Executes an extension bot command", description="Executes an extension bot command", ) - async def extension_group(self, ctx: commands.Context) -> None: + async def extension_group(self: Self, ctx: commands.Context) -> None: """The bare .extension command. This does nothing but generate the help message Args: diff --git a/techsupport_bot/commands/factoids.py b/techsupport_bot/commands/factoids.py index 1c443d4d1..b0a50a563 100644 --- a/techsupport_bot/commands/factoids.py +++ b/techsupport_bot/commands/factoids.py @@ -39,8 +39,10 @@ async def setup(bot: bot.TechSupportBot) -> None: - """ - Define database tables, registers configs, registers extension + """Loading the Factoid plugin into the bot + + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to """ # Sets up the config @@ -999,7 +1001,11 @@ async def cronjob( description="Executes a factoid command", ) async def factoid(self: Self, ctx: commands.Context) -> None: - """Method to create the factoid command group.""" + """The bare .factoid command. This does nothing but generate the help message + + Args: + ctx (commands.Context): The context in which the command was run in + """ # Executed if there are no/invalid args supplied await auxiliary.extension_help(self, ctx, self.__module__[9:]) diff --git a/techsupport_bot/commands/gate.py b/techsupport_bot/commands/gate.py index b35f8a645..f9cbf0248 100644 --- a/techsupport_bot/commands/gate.py +++ b/techsupport_bot/commands/gate.py @@ -1,13 +1,25 @@ """Module for defining the gate extension for the bot.""" +from __future__ import annotations + +from typing import TYPE_CHECKING, Self + import discord +import munch from botlogging import LogContext, LogLevel from core import auxiliary, cogs, extensionconfig from discord.ext import commands +if TYPE_CHECKING: + import bot + -async def setup(bot): - """Setup to add the gate config to the config file.""" +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the Gate plugin into the bot + + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + """ config = extensionconfig.ExtensionConfig() config.add( key="channel", @@ -67,15 +79,34 @@ async def setup(bot): class ServerGate(cogs.MatchCog): """Class to get the server gate from config.""" - async def match(self, config, ctx, _): - """Method to match the gate channel.""" + async def match( + self: Self, config: munch.Munch, ctx: commands.Context, _: str + ) -> bool: + """Matches any message and checks if it is in the gate channel + + Args: + config (munch.Munch): The config for the guild where the message was sent + ctx (commands.Context): The context of the original message + + Returns: + bool: Whether the message should be subject to the gate policy or not + """ if not config.extensions.gate.channel.value: return False return ctx.channel.id == int(config.extensions.gate.channel.value) - async def response(self, config, ctx: commands.Context, content, _): - """Method for a response from the gate extension.""" + async def response( + self: Self, config: munch.Munch, ctx: commands.Context, content: str, _: bool + ) -> None: + """Prepares a response to the gate policy, + deleting the message and assigning roles if needed + + Args: + config (munch.Munch): The config of the guild with the gate + ctx (commands.Context): The context of the message that triggered the gate + content (str): The string contents of the message from the gate channel + """ is_admin = await self.bot.is_bot_admin(ctx.author) if is_admin: @@ -117,8 +148,20 @@ async def response(self, config, ctx: commands.Context, content, _): delete_after=float(delete_wait), ) - async def get_roles(self, config, ctx): - """Method to get a role from the author.""" + async def get_roles( + self: Self, config: munch.Munch, ctx: commands.Context + ) -> list[discord.Role]: + """Builds a list of roles that the user in ctx doesn't have, + but are listed in the gate config roles to be applied + + Args: + self (Self): _description_ + config (munch.Munch): The config of the guild + ctx (commands.Context): The context of the message that triggered the gate + + Returns: + list[discord.Role]: A list of all the roles that should be given to the user + """ roles = [] for role_name in config.extensions.gate.roles.value: role = discord.utils.get(ctx.guild.roles, name=role_name) @@ -136,8 +179,12 @@ async def get_roles(self, config, ctx): brief="Executes a gate command", description="Executes a gate command", ) - async def gate_command(self, ctx): - """Method to create the command for gate extension.""" + async def gate_command(self: Self, ctx: commands.Context) -> None: + """The bare .gate command. This does nothing but generate the help message + + Args: + ctx (commands.Context): The context in which the command was run in + """ # Executed if there are no/invalid args supplied await auxiliary.extension_help(self, ctx, self.__module__[9:]) @@ -149,8 +196,13 @@ async def gate_command(self, ctx): brief="Generates a gate intro message", description="Generates the configured gate intro message", ) - async def intro_message(self, ctx): - """Method to add a message to the gate channel.""" + async def intro_message(self: Self, ctx: commands.Context) -> None: + """Admin only, generates a simple message that tells people how to use the gate channel + It will print the intro_message config value + + Args: + ctx (commands.Context): The context in which the command occured + """ config = self.bot.guild_configs[str(ctx.guild.id)] if ctx.channel.id != int(config.extensions.gate.channel.value): diff --git a/techsupport_bot/commands/giphy.py b/techsupport_bot/commands/giphy.py index a3c092d2f..50dff62f9 100644 --- a/techsupport_bot/commands/giphy.py +++ b/techsupport_bot/commands/giphy.py @@ -1,12 +1,26 @@ """Module for giphy extension in the bot.""" +from __future__ import annotations + +from typing import TYPE_CHECKING, Self + import ui from core import auxiliary, cogs from discord.ext import commands +if TYPE_CHECKING: + import bot + + +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the Giphy plugin into the bot -async def setup(bot): - """Method to add giphy to the config.""" + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + + Raises: + AttributeError: Raised if an API key is missing to prevent unusable commands from loading + """ # Don't load without the API key try: @@ -26,7 +40,14 @@ class Giphy(cogs.BaseCog): @staticmethod def parse_url(url: str) -> str: - """Method to parse the url.""" + """Parses the raw API url into a useable gif link + + Args: + url (str): The raw URL from Giphy + + Returns: + str: The direct link to the gif, if it exists + """ index = url.find("?cid=") return url[:index] @@ -38,8 +59,13 @@ def parse_url(url: str) -> str: description="Grabs a random Giphy image based on your search", usage="[query]", ) - async def giphy(self, ctx, *, query: str): - """Method to send giphy to discord.""" + async def giphy(self: Self, ctx: commands.Context, *, query: str) -> None: + """The main entry point and logic for the giphy command + + Args: + ctx (commands.Context): The context in which the command was run + query (str): The string to query the giphy API for + """ response = await self.bot.http_functions.http_call( "get", self.GIPHY_URL.format( diff --git a/techsupport_bot/commands/github.py b/techsupport_bot/commands/github.py index 537429853..950978d94 100644 --- a/techsupport_bot/commands/github.py +++ b/techsupport_bot/commands/github.py @@ -10,15 +10,28 @@ .issue """ +from __future__ import annotations + import json +from typing import TYPE_CHECKING, Self import discord from core import auxiliary, cogs from discord.ext import commands +if TYPE_CHECKING: + import bot + + +async def setup(bot: bot.TechSupportBot) -> None: + """Loading the Github plugin into the bot -async def setup(bot): - """Registers the IssueCreator Cog""" + Args: + bot (bot.TechSupportBot): The bot object to register the cogs to + + Raises: + AttributeError: Raised if an API key is missing to prevent unusable commands from loading + """ try: if not bot.file_config.api.github.api_key: raise AttributeError("IssueCreator was not loaded due to missing API key") @@ -48,7 +61,7 @@ class IssueCreator(cogs.BaseCog): description="Creates a Github issue on the configured bot repo", usage="[title] [description]", ) - async def issue(self, ctx, title: str, description: str): + async def issue(self: Self, ctx, title: str, description: str): """Creates an issue in the bot's Github Repo This is a command and should be accessed via Discord.