diff --git a/techsupport_bot/bot.py b/techsupport_bot/bot.py index d7de2663d..97e608277 100644 --- a/techsupport_bot/bot.py +++ b/techsupport_bot/bot.py @@ -402,7 +402,7 @@ async def get_log_channel_from_guild( # File config loading functions - def load_file_config(self, validate: bool = True): + def load_file_config(self, validate: bool = True) -> None: """Loads the config yaml file into a bot object. Args: @@ -423,7 +423,7 @@ def load_file_config(self, validate: bool = True): for subsection in ["required"]: self.validate_bot_config_subsection("bot_config", subsection) - def validate_bot_config_subsection(self, section: str, subsection: str): + def validate_bot_config_subsection(self, section: str, subsection: str) -> None: """Loops through a config subsection to check for missing values. Args: @@ -969,7 +969,7 @@ async def can_run(self, ctx: commands.Context, *, call_once=False) -> bool: # IRC Stuff - async def start_irc(self): + async def start_irc(self) -> None: """Starts the IRC connection in a seperate thread""" irc_config = getattr(self.file_config.api, "irc") main_loop = asyncio.get_running_loop() diff --git a/techsupport_bot/botlogging/delayed.py b/techsupport_bot/botlogging/delayed.py index 8312828b5..7529d738d 100644 --- a/techsupport_bot/botlogging/delayed.py +++ b/techsupport_bot/botlogging/delayed.py @@ -23,7 +23,7 @@ def __init__(self, *args, **kwargs): self.__send_queue = None super().__init__(*args, **kwargs) - async def send_log(self, *args, **kwargs): + async def send_log(self, *args, **kwargs) -> None: """Adds a log to the queue Does nothing different than the Logger send_log function() Will disregard debug logs if debug is off @@ -36,11 +36,11 @@ async def send_log(self, *args, **kwargs): await self.__send_queue.put(super().send_log(*args, **kwargs)) - def register_queue(self): + def register_queue(self) -> None: """Registers the asyncio.Queue object to make delayed logging possible""" self.__send_queue = asyncio.Queue(maxsize=self.queue_size) - async def run(self): + async def run(self) -> None: """A forever loop that pulls from the queue and then waits based on the config""" while True: try: diff --git a/techsupport_bot/commands/animal.py b/techsupport_bot/commands/animal.py index 333477f8b..ec2fb2a47 100644 --- a/techsupport_bot/commands/animal.py +++ b/techsupport_bot/commands/animal.py @@ -4,7 +4,7 @@ from discord.ext import commands -async def setup(bot): +async def setup(bot) -> None: """Loading the animal plugin""" await bot.add_cog(Animals(bot=bot)) diff --git a/techsupport_bot/commands/application.py b/techsupport_bot/commands/application.py index 9da402503..8c42dce97 100644 --- a/techsupport_bot/commands/application.py +++ b/techsupport_bot/commands/application.py @@ -753,7 +753,7 @@ async def notify_for_application_change( interaction: discord.Interaction, application: bot.models.Applications, member: discord.Member, - ): + ) -> None: """Notifies: - The invoker - The user diff --git a/techsupport_bot/commands/bot.py b/techsupport_bot/commands/bot.py index a5121f4bc..e72661300 100644 --- a/techsupport_bot/commands/bot.py +++ b/techsupport_bot/commands/bot.py @@ -15,7 +15,7 @@ from discord.ext import commands -async def setup(bot): +async def setup(bot) -> None: """Registers the BotInfo Cog""" await bot.add_cog(BotInfo(bot=bot)) @@ -27,7 +27,7 @@ class BotInfo(cogs.BaseCog): @commands.check(auxiliary.bot_admin_check_context) @commands.command(name="bot", description="Provides bot info") - async def get_bot_data(self, ctx): + async def get_bot_data(self, ctx) -> None: """Gets various data about the bot. This is a command and should be accessed via Discord. diff --git a/techsupport_bot/commands/burn.py b/techsupport_bot/commands/burn.py index 2916b1b34..fc1b97674 100644 --- a/techsupport_bot/commands/burn.py +++ b/techsupport_bot/commands/burn.py @@ -11,7 +11,7 @@ from discord.ext import commands -async def setup(bot): +async def setup(bot) -> None: """Method to add burn command to config.""" await bot.add_cog(Burn(bot=bot)) @@ -80,7 +80,7 @@ async def burn_command( description="Declares the user's last message as a BURN!", usage="@user", ) - async def burn(self, ctx: commands.Context, user_to_match: discord.Member): + async def burn(self, ctx: commands.Context, user_to_match: discord.Member) -> None: """The only purpose of this function is to accept input from discord Args: diff --git a/techsupport_bot/commands/chatgpt.py b/techsupport_bot/commands/chatgpt.py index 0efdc68bf..a48d0e323 100644 --- a/techsupport_bot/commands/chatgpt.py +++ b/techsupport_bot/commands/chatgpt.py @@ -18,7 +18,7 @@ from discord.ext import commands -async def setup(bot): +async def setup(bot) -> None: """Registers the extension""" # Don't load without the API key @@ -36,7 +36,7 @@ class ChatGPT(cogs.BaseCog): API_URL = "https://api.openai.com/v1/chat/completions" - async def preconfig(self): + async def preconfig(self) -> None: """Sets up the dict""" self.history = expiringdict.ExpiringDict( max_len=1000, @@ -93,7 +93,7 @@ async def call_api(self, ctx: commands.Context, api_key: str, prompt: str) -> st description="Issues a prompt to the ChatGPT API", usage="[prompt]", ) - async def gpt(self, ctx: commands.Context, *, prompt: str): + async def gpt(self, ctx: commands.Context, *, prompt: str) -> None: """Pushes a prompt to the OpenAI API for ChatGPT Args: @@ -160,7 +160,7 @@ async def gpt(self, ctx: commands.Context, *, prompt: str): brief="Executes a ChatGPT utility command", description="Executes a ChatGPT utility command", ) - async def gptutil(self, ctx: commands.Context): + async def gptutil(self, ctx: commands.Context) -> None: """Defines the Gptutil command group for history management Args: @@ -176,7 +176,7 @@ async def gptutil(self, ctx: commands.Context): brief="Clears history", description="Clears your ChatGPT conversation history", ) - async def clear_history(self, ctx: commands.Context): + async def clear_history(self, ctx: commands.Context) -> None: """Command to clear the invokers result history Args: @@ -219,7 +219,7 @@ async def clear_history(self, ctx: commands.Context): brief="Gets history", description="Gets your ChatGPT conversation history", ) - async def get_history(self, ctx: commands.Context): + async def get_history(self, ctx: commands.Context) -> None: """Command to get the history of the invoker Args: diff --git a/techsupport_bot/commands/commandcontrol.py b/techsupport_bot/commands/commandcontrol.py index 22b5918e3..26f40d52d 100644 --- a/techsupport_bot/commands/commandcontrol.py +++ b/techsupport_bot/commands/commandcontrol.py @@ -12,7 +12,7 @@ from discord.ext import commands -async def setup(bot): +async def setup(bot) -> None: """Registers the CommandControl Cog""" await bot.add_cog(CommandControl(bot=bot)) @@ -28,7 +28,7 @@ class CommandControl(cogs.BaseCog): brief="Executes a commands bot command", description="Executes a commands bot command", ) - async def command_group(self, ctx: commands.Context): + async def command_group(self, ctx: commands.Context) -> None: """The bare .command command. This does nothing but generate the help message Args: @@ -42,7 +42,7 @@ async def command_group(self, ctx: commands.Context): @command_group.command( name="enable", description="Enables a command by name", usage="[command-name]" ) - async def enable_command(self, ctx, *, command_name: str): + async def enable_command(self, ctx, *, command_name: str) -> None: """Enables a command by name. This is a command and should be accessed via Discord. @@ -75,7 +75,7 @@ async def enable_command(self, ctx, *, command_name: str): @command_group.command( name="disable", description="Disables a command by name", usage="[command-name]" ) - async def disable_command(self, ctx, *, command_name: str): + async def disable_command(self, ctx, *, command_name: str) -> None: """Disables a command by name. This is a command and should be accessed via Discord. diff --git a/techsupport_bot/commands/conch.py b/techsupport_bot/commands/conch.py index 51887c2eb..f4fbb0989 100644 --- a/techsupport_bot/commands/conch.py +++ b/techsupport_bot/commands/conch.py @@ -11,7 +11,7 @@ from discord.ext import commands -async def setup(bot): +async def setup(bot) -> None: """Method to add conch to the config in discord bot.""" await bot.add_cog(MagicConch(bot=bot)) @@ -86,6 +86,6 @@ async def conch_command(self, ctx: commands.Context, question: str = "") -> None description="Asks the Magic Conch (8ball) a question", usage="[question]", ) - async def ask_question(self, ctx: commands.Context, *, question: str = ""): + async def ask_question(self, ctx: commands.Context, *, question: str = "") -> None: """Method for how the conch command works for the bot.""" await self.conch_command(ctx, question) diff --git a/techsupport_bot/commands/config.py b/techsupport_bot/commands/config.py index 0c8662dc0..a4a3687dd 100644 --- a/techsupport_bot/commands/config.py +++ b/techsupport_bot/commands/config.py @@ -10,7 +10,7 @@ from discord.ext import commands -async def setup(bot): +async def setup(bot) -> None: """Method to add burn command to config.""" await bot.add_cog(ConfigControl(bot=bot)) @@ -23,7 +23,7 @@ class ConfigControl(cogs.BaseCog): brief="Issues a config command", description="Issues a config command", ) - async def config_command(self, ctx): + async def config_command(self, ctx) -> None: """The parent config command. This is a command and should be accessed via Discord. @@ -43,13 +43,13 @@ async def config_command(self, ctx): description="Edits guild config by uploading JSON", usage="|uploaded-json|", ) - async def patch_config(self, ctx): + async def patch_config(self, ctx: commands.Context) -> None: """Displays the current config to the user. This is a command and should be accessed via Discord. parameters: - ctx (discord.ext.Context): the context object for the message + ctx (commands.Context): the context object for the message """ config = self.bot.guild_configs[str(ctx.guild.id)] @@ -112,13 +112,15 @@ async def patch_config(self, ctx): description="Enables an extension for the guild by name", usage="[extension-name]", ) - async def enable_extension(self, ctx, extension_name: str): + async def enable_extension( + self, ctx: commands.Context, extension_name: str + ) -> None: """Enables an extension for the guild. This is a command and should be accessed via Discord. parameters: - ctx (discord.ext.Context): the context object for the message + ctx (commands.Context): the context object for the message extension_name (str): the extension subname to enable """ if not ( @@ -160,13 +162,15 @@ async def enable_extension(self, ctx, extension_name: str): description="Disables an extension for the guild by name", usage="[extension-name]", ) - async def disable_extension(self, ctx, extension_name: str): + async def disable_extension( + self, ctx: commands.Context, extension_name: str + ) -> None: """Disables an extension for the guild. This is a command and should be accessed via Discord. parameters: - ctx (discord.ext.Context): the context object for the message + ctx (commands.Context): the context object for the message extension_name (str): the extension subname to disable """ if not ( @@ -210,7 +214,7 @@ async def disable_extension(self, ctx, extension_name: str): brief="Resets current guild config", description="Resets config to default for the current guild", ) - async def reset_config(self, ctx: commands.Context): + async def reset_config(self, ctx: commands.Context) -> None: """A function to reset the current guild config to stock Args: diff --git a/techsupport_bot/commands/correct.py b/techsupport_bot/commands/correct.py index 34cbf1631..dd2fa7e02 100644 --- a/techsupport_bot/commands/correct.py +++ b/techsupport_bot/commands/correct.py @@ -9,7 +9,7 @@ from discord.ext import commands -async def setup(bot): +async def setup(bot) -> None: """Method to add correct to the config.""" await bot.add_cog(Corrector(bot=bot)) @@ -77,6 +77,8 @@ def prepare_message( description="Replaces the most recent text with your text", usage="[to_replace] [replacement]", ) - async def correct(self, ctx, to_replace: str, replacement: str): + async def correct( + self, ctx: commands.Context, to_replace: str, replacement: str + ) -> None: """Method for the correct command for the discord bot.""" await self.correct_command(ctx, to_replace, replacement) diff --git a/techsupport_bot/commands/duck.py b/techsupport_bot/commands/duck.py index bc2869fc3..aa481f308 100644 --- a/techsupport_bot/commands/duck.py +++ b/techsupport_bot/commands/duck.py @@ -1,10 +1,13 @@ """Module for the duck extension""" +from __future__ import annotations + import asyncio import datetime import functools import random from datetime import timedelta +from typing import TYPE_CHECKING import discord import munch @@ -14,8 +17,11 @@ from discord import Color as embed_colors from discord.ext import commands +if TYPE_CHECKING: + import bot + -async def setup(bot): +async def setup(bot) -> None: """Method to add duck into the config file""" config = extensionconfig.ExtensionConfig() @@ -92,11 +98,11 @@ class DuckHunt(cogs.LoopCog): ON_START = False CHANNELS_KEY = "hunt_channels" - async def loop_preconfig(self): + async def loop_preconfig(self) -> None: """Preconfig for cooldowns""" self.cooldowns = {} - async def wait(self, config, _): + async def wait(self, config, _) -> None: """Method for the duck loop""" await asyncio.sleep( random.randint( @@ -105,7 +111,9 @@ async def wait(self, config, _): ) ) - async def execute(self, config, guild, channel, banned_user: discord.User = None): + async def execute( + self, config, guild, channel, banned_user: discord.User = None + ) -> None: """Method for sending the duck""" if not channel: config = self.bot.guild_configs[str(guild.id)] @@ -166,7 +174,7 @@ async def execute(self, config, guild, channel, banned_user: discord.User = None else: await self.got_away(channel) - async def got_away(self, channel): + async def got_away(self, channel) -> None: """Sends a "got away!" embed when timeout passes""" embed = discord.Embed( title="A duck got away!", @@ -176,7 +184,14 @@ async def got_away(self, channel): await channel.send(embed=embed) - async def handle_winner(self, winner, guild, action, raw_duration, channel): + async def handle_winner( + self, + winner: discord.Member, + guild: discord.Guild, + action: str, + raw_duration: datetime.datetime, + channel: discord.abc.Messageable, + ) -> None: """ This is a function to update the database based on a winner @@ -262,7 +277,7 @@ def message_check( duck_message: discord.Message, banned_user: discord.User, message: discord.Message, - ): + ) -> bool: """Method to check if 'bef' or 'bang' was typed""" # ignore other channels if message.channel.id != channel.id: @@ -328,7 +343,7 @@ def message_check( return choice_ - async def get_duck_user(self, user_id, guild_id): + async def get_duck_user(self, user_id, guild_id) -> bot.models.DuckUser: """Method to get the duck winner""" duck_user = ( await self.bot.models.DuckUser.query.where( @@ -340,7 +355,7 @@ async def get_duck_user(self, user_id, guild_id): return duck_user - async def get_global_record(self, guild_id): + async def get_global_record(self, guild_id) -> float: """ This is a function to get the current global speed record in a given guild @@ -362,7 +377,7 @@ async def get_global_record(self, guild_id): brief="Executes a duck command", description="Executes a duck command", ) - async def duck(self, ctx): + async def duck(self, ctx: commands.Context) -> None: """Method to make the initial duck command""" # Executed if there are no/invalid args supplied @@ -375,7 +390,9 @@ async def duck(self, ctx): description="Gets duck friendships and kills for yourself or another user", usage="@user (defaults to yourself)", ) - async def stats(self, ctx, *, user: discord.Member = None): + async def stats( + self, ctx: commands.Context, *, user: discord.Member = None + ) -> None: """Method for viewing duck stats""" if not user: user = ctx.message.author @@ -413,7 +430,7 @@ async def stats(self, ctx, *, user: discord.Member = None): brief="Get duck friendship scores", description="Gets duck friendship scores for all users", ) - async def friends(self, ctx): + async def friends(self, ctx: commands.Context) -> None: """Method for viewing top friend counts""" duck_users = ( await self.bot.models.DuckUser.query.order_by( @@ -468,7 +485,7 @@ async def friends(self, ctx): brief="Get the record holder", description="Gets the current speed record holder, and their time", ) - async def record(self, ctx): + async def record(self, ctx: commands.Context) -> None: """ This is a command and should be run via discord @@ -503,7 +520,7 @@ async def record(self, ctx): brief="Get duck kill scores", description="Gets duck kill scores for all users", ) - async def killers(self, ctx): + async def killers(self, ctx: commands.Context) -> None: """Method for viewing top killer counts""" duck_users = ( await self.bot.models.DuckUser.query.order_by( @@ -551,7 +568,7 @@ async def killers(self, ctx): await ui.PaginateView().send(ctx.channel, ctx.author, embeds) - def get_user_text(self, duck_user): + def get_user_text(self, duck_user) -> str: """Method to get the user for the top commands""" user = self.bot.get_user(int(duck_user.author_id)) if user: @@ -608,7 +625,7 @@ 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): + async def kill(self, ctx: commands.Context) -> None: """Method for killing ducks""" config = self.bot.guild_configs[str(ctx.guild.id)] if not config.extensions.duck.allow_manipulation.value: @@ -661,7 +678,7 @@ async def kill(self, ctx): description="Gives someone the gift of a live duck", usage="[user]", ) - async def donate(self, ctx: commands.Context, user: discord.Member): + async def donate(self, ctx: commands.Context, user: discord.Member) -> None: """Method for donating ducks""" config = self.bot.guild_configs[str(ctx.guild.id)] if not config.extensions.duck.allow_manipulation.value: @@ -733,7 +750,7 @@ async def donate(self, ctx: commands.Context, user: discord.Member): description="Deletes the database entry of the target", usage="[user]", ) - async def reset(self, ctx, user: discord.Member): + async def reset(self, ctx: commands.Context, user: discord.Member) -> None: """Method for resetting duck counts""" if user.bot: await auxiliary.send_deny_embed( diff --git a/techsupport_bot/commands/dumpdbg.py b/techsupport_bot/commands/dumpdbg.py index 18af50f4a..608674f55 100644 --- a/techsupport_bot/commands/dumpdbg.py +++ b/techsupport_bot/commands/dumpdbg.py @@ -8,7 +8,7 @@ from discord.ext import commands -async def setup(bot): +async def setup(bot) -> None: """Method to add the dumpdbg command to config.""" # Don't load without the API key @@ -54,7 +54,7 @@ class Dumpdbg(cogs.BaseCog): ), usage="|attached-dump-files|", ) - async def debug_dump(self, ctx): + async def debug_dump(self, ctx: commands.Context) -> None: """Method for the actual debugging""" config = self.bot.guild_configs[str(ctx.guild.id)] @@ -162,7 +162,7 @@ async def debug_dump(self, ctx): ) ) - async def get_files(self, ctx): + async def get_files(self, ctx: commands.Context) -> list[str]: """Gets files from passed message and checks if they are valid .dmp files Params: diff --git a/techsupport_bot/commands/echo.py b/techsupport_bot/commands/echo.py index f92c45696..ed8176c79 100644 --- a/techsupport_bot/commands/echo.py +++ b/techsupport_bot/commands/echo.py @@ -12,7 +12,7 @@ from discord.ext import commands -async def setup(bot): +async def setup(bot) -> None: """Registers the MessageEcho Cog""" await bot.add_cog(MessageEcho(bot=bot)) @@ -26,7 +26,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): + async def echo(self, ctx: commands.Context) -> None: """The bare .echo command. This does nothing but generate the help message Args: @@ -42,7 +42,9 @@ async def echo(self, ctx: commands.Context): description="Echos a message to a channel", usage="[channel-id] [message]", ) - async def echo_channel(self, ctx, channel_id: int, *, message: str): + async def echo_channel( + self, ctx: commands.Context, channel_id: int, *, message: str + ) -> None: """Sends a message to a specified channel. This is a command and should be accessed via Discord. @@ -69,13 +71,15 @@ async def echo_channel(self, ctx, channel_id: int, *, message: str): description="Echos a message to a user", usage="[user-id] [message]", ) - async def echo_user(self, ctx, user_id: int, *, message: str): + async def echo_user( + self, ctx: commands.Context, user_id: int, *, message: str + ) -> None: """Sends a message to a specified user. This is a command and should be accessed via Discord. parameters: - ctx (discord.ext.Context): the context object for the calling message + ctx (commands.Context): the context object for the calling message user_id (int): the ID of the user to send the echoed message message (str): the message to echo """ diff --git a/techsupport_bot/commands/embed.py b/techsupport_bot/commands/embed.py index 5fa4bc25a..f095a29a2 100644 --- a/techsupport_bot/commands/embed.py +++ b/techsupport_bot/commands/embed.py @@ -16,7 +16,7 @@ from discord.ext import commands -async def setup(bot): +async def setup(bot) -> None: """Registers the extension and its config""" config = extensionconfig.ExtensionConfig() config.add( @@ -79,7 +79,7 @@ class Embedder(cogs.BaseCog): + "(see: https://discord.com/developers/docs/resources/channel#embed-object)", usage="[keep-succesful-if-one-fails] |embed-list-json-upload|", ) - async def embed(self, ctx: commands.Context, *, keep_option: str = None): + async def embed(self, ctx: commands.Context, *, keep_option: str = None) -> None: """Command to convert an attached .json to an embed Args: diff --git a/techsupport_bot/commands/emoji.py b/techsupport_bot/commands/emoji.py index d713750a0..7a0436ae9 100644 --- a/techsupport_bot/commands/emoji.py +++ b/techsupport_bot/commands/emoji.py @@ -13,7 +13,7 @@ from discord.ext import commands -async def setup(bot): +async def setup(bot) -> None: """Method to add emoji commands to config.""" await bot.add_cog(Emojis(bot=bot)) @@ -43,7 +43,7 @@ def emoji_from_char(cls, char: str): return emoji.emojize(f":{cls.KEY_MAP[char]}:", language="alias") return None - def check_if_all_unique(self, string: str): + def check_if_all_unique(self, string: str) -> bool: """Checks, using the set function, if a string has duplicates or not Args: @@ -86,7 +86,7 @@ async def emoji_commands( message: str, add_reactions: bool, react_user: discord.Member = None, - ): + ) -> None: """A method to handle the core of both emoji message and reaction Args: @@ -152,7 +152,7 @@ async def emoji_commands( brief="Executes an emoji command", description="Executes a emoji command", ) - async def emoji(self, ctx): + async def emoji(self, ctx: commands.Context) -> None: """Executed if there are no/invalid args supplied""" await auxiliary.extension_help(self, ctx, self.__module__[9:]) @@ -163,7 +163,7 @@ async def emoji(self, ctx): description="Creates an emoji message", usage="[message]", ) - async def message(self, ctx, *, message: str): + 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""" await self.emoji_commands(ctx, message, False) @@ -175,7 +175,9 @@ async def message(self, ctx, *, message: str): description="Creates an emoji reaction for a user's most recent message", usage="[message] @user", ) - async def reaction(self, ctx, message: str, react_user: discord.Member): + 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""" diff --git a/techsupport_bot/commands/extension.py b/techsupport_bot/commands/extension.py index da741d659..cb4e244e5 100644 --- a/techsupport_bot/commands/extension.py +++ b/techsupport_bot/commands/extension.py @@ -16,7 +16,7 @@ from discord.ext import commands -async def setup(bot): +async def setup(bot) -> None: """Registers the ExtensionControl Cog""" await bot.add_cog(ExtensionControl(bot=bot)) @@ -32,7 +32,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): + async def extension_group(self, ctx: commands.Context) -> None: """The bare .extension command. This does nothing but generate the help message Args: @@ -48,13 +48,15 @@ async def extension_group(self, ctx: commands.Context): description="Gets the status of an extension by name", usage="[extension-name]", ) - async def extension_status(self, ctx, *, extension_name: str): + async def extension_status( + self, ctx: commands.Context, *, extension_name: str + ) -> None: """Gets the status of an extension. This is a command and should be accessed via Discord. parameters: - ctx (discord.ext.Context): the context object for the message + ctx (commands.Context): the context object for the message extension_name (str): the name of the extension """ extensions_status = ( @@ -85,13 +87,15 @@ async def extension_status(self, ctx, *, extension_name: str): @extension_group.command( name="load", description="Loads an extension by name", usage="[extension-name]" ) - async def load_extension(self, ctx, *, extension_name: str): + async def load_extension( + self, ctx: commands.Context, *, extension_name: str + ) -> None: """Loads an extension by filename. This is a command and should be accessed via Discord. parameters: - ctx (discord.ext.Context): the context object for the message + ctx (commands.Context): the context object for the message extension_name (str): the name of the extension """ try: @@ -108,13 +112,15 @@ async def load_extension(self, ctx, *, extension_name: str): description="Unloads an extension by name", usage="[extension-name]", ) - async def unload_extension(self, ctx, *, extension_name: str): + async def unload_extension( + self, ctx: commands.Context, *, extension_name: str + ) -> None: """Unloads an extension by filename. This is a command and should be accessed via Discord. parameters: - ctx (discord.ext.Context): the context object for the message + ctx (commands.Context): the context object for the message extension_name (str): the name of the extension """ try: @@ -131,13 +137,15 @@ async def unload_extension(self, ctx, *, extension_name: str): description="Uploads an extension from Discord to be saved on the bot", usage="[extension-name] |python-file-upload|", ) - async def register_extension(self, ctx, extension_name: str): + async def register_extension( + self, ctx: commands.Context, extension_name: str + ) -> None: """Unloads an extension by filename. This is a command and should be accessed via Discord. parameters: - ctx (discord.ext.Context): the context object for the message + ctx (commands.Context): the context object for the message extension_name (str): the name of the extension """ if not ctx.message.attachments: diff --git a/techsupport_bot/commands/factoids.py b/techsupport_bot/commands/factoids.py index a9a416913..b844ef3a7 100644 --- a/techsupport_bot/commands/factoids.py +++ b/techsupport_bot/commands/factoids.py @@ -20,11 +20,12 @@ import re from dataclasses import dataclass from socket import gaierror -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Self import aiocron import discord import expiringdict +import munch import ui import yaml from aiohttp.client_exceptions import InvalidURL @@ -37,7 +38,7 @@ import bot -async def setup(bot): +async def setup(bot: bot.TechSupportBot) -> None: """ Define database tables, registers configs, registers extension """ @@ -171,7 +172,7 @@ class FactoidManager(cogs.MatchCog): + r")|\*\/[1-9])$" ) - async def preconfig(self): + async def preconfig(self: Self) -> None: """Preconfig for factoid jobs""" self.factoid_cache = expiringdict.ExpiringDict( max_len=100, max_age_seconds=1200 @@ -189,7 +190,9 @@ async def preconfig(self): await self.kickoff_jobs() # -- DB calls -- - async def delete_factoid_call(self, factoid: bot.models.Factoid, guild: str): + async def delete_factoid_call( + self: Self, factoid: bot.models.Factoid, guild: str + ) -> None: """Calls the db to delete a factoid Args: @@ -220,13 +223,13 @@ async def delete_factoid_call(self, factoid: bot.models.Factoid, guild: str): await factoid.delete() async def create_factoid_call( - self, + self: Self, factoid_name: str, guild: str, message: str, embed_config: str, alias: str = None, - ): + ) -> None: """Calls the DB to create a factoid Args: @@ -258,13 +261,13 @@ async def create_factoid_call( await factoid.create() async def modify_factoid_call( - self, - factoid, - ): + self: Self, + factoid: bot.models.Factoid, + ) -> None: """Makes a DB call to modify a factoid Args: - factoid (Factoid): Factoid to modify. + factoid (bot.models.Factoid): Factoid to modify. Raises: custom_errors.TooLongFactoidMessageError: @@ -362,8 +365,8 @@ async def check_valid_factoid_contents( return None async def handle_parent_change( - self, ctx: commands.Context, aliases: list, new_name: str - ): + self: Self, ctx: commands.Context, aliases: list, new_name: str + ) -> None: """Changes the list of aliases to point to a new name Args: @@ -445,7 +448,7 @@ def get_embed_from_factoid(self, factoid: bot.models.Factoid) -> discord.Embed: return discord.Embed.from_dict(embed_config) # -- Cache functions -- - async def handle_cache(self, guild: str, factoid_name: str): + async def handle_cache(self: Self, guild: str, factoid_name: str) -> None: """Deletes factoid from the factoid cache Args: @@ -511,7 +514,9 @@ async def get_all_factoids( return factoids - async def get_raw_factoid_entry(self, factoid_name: str, guild: str): + async def get_raw_factoid_entry( + self: Self, factoid_name: str, guild: str + ) -> bot.models.Factoid: """Searches the db for a factoid by its name, does NOT follow aliases Args: @@ -519,7 +524,7 @@ async def get_raw_factoid_entry(self, factoid_name: str, guild: str): guild (str): The id of the guild for the factoid Returns: - Factoid: The factoid + bot.models.Factoid: The factoid """ cache_key = self.get_cache_key(guild, factoid_name.lower()) factoid = self.factoid_cache.get(cache_key) @@ -542,7 +547,9 @@ async def get_raw_factoid_entry(self, factoid_name: str, guild: str): return factoid - async def get_factoid(self, factoid_name: str, guild: str): + async def get_factoid( + self: Self, factoid_name: str, guild: str + ) -> bot.models.Factoid: """Gets the factoid from the DB, follows aliases Args: @@ -553,7 +560,7 @@ async def get_factoid(self, factoid_name: str, guild: str): custom_errors.FactoidNotFoundError: If the factoid wasn't found Returns: - Factoid: The factoid + bot.models.Factoid: The factoid """ factoid = await self.get_raw_factoid_entry(factoid_name, guild) @@ -570,14 +577,14 @@ async def get_factoid(self, factoid_name: str, guild: str): # -- Adding and removing factoids -- async def add_factoid( - self, + self: Self, ctx: commands.Context, factoid_name: str, guild: str, message: str, embed_config: str, alias: str = None, - ): + ) -> None: """Adds a factoid with confirmation, modifies it if it already exists Args: @@ -708,14 +715,19 @@ async def match(self, config, _: commands.Context, message_contents: str) -> boo """ return message_contents.startswith(config.extensions.factoids.prefix.value) - async def response(self, config, ctx: commands.Context, message_content: str, _): + async def response( + self: Self, + config: munch.Munch, + ctx: commands.Context, + message_content: str, + _: bool, + ) -> None: """Responds to a factoid call Args: - config (Config): The server config + config (munch.Munch): The server config ctx (commands.Context): Context of the call message_content (str): Content of the call - _ (bool): Result, unused Raises: custom_errors.FactoidNotFoundError: Raised if a broken alias is present in the DB @@ -827,7 +839,7 @@ async def send_to_irc( ) # -- Factoid job related functions -- - async def kickoff_jobs(self): + async def kickoff_jobs(self: Self) -> None: """Gets a list of cron jobs and starts them""" jobs = await self.bot.models.FactoidJob.query.gino.all() for job in jobs: @@ -838,7 +850,9 @@ async def kickoff_jobs(self): task = asyncio.create_task(self.cronjob(job)) task = self.running_jobs[job_id]["task"] = task - async def cronjob(self, job: bot.models.FactoidJob, ctx: commands.Context = None): + async def cronjob( + self: Self, job: bot.models.FactoidJob, ctx: commands.Context = None + ) -> None: """Run a cron job for a factoid Args: @@ -985,7 +999,7 @@ async def cronjob(self, job: bot.models.FactoidJob, ctx: commands.Context = None brief="Executes a factoid command", description="Executes a factoid command", ) - async def factoid(self, ctx): + async def factoid(self: Self, ctx: commands.Context) -> None: """Method to create the factoid command group.""" # Executed if there are no/invalid args supplied @@ -1001,8 +1015,8 @@ async def factoid(self, ctx): usage="[factoid-name] [factoid-output] |optional-embed-json-upload|", ) async def remember( - self, ctx: commands.Context, factoid_name: str, *, message: str = "" - ): + self: Self, ctx: commands.Context, factoid_name: str, *, message: str = "" + ) -> None: """Command to add a factoid Args: @@ -1049,7 +1063,7 @@ async def remember( description="Deletes a factoid permanently, including its aliases", usage="[factoid-name]", ) - async def forget(self, ctx: commands.Context, factoid_name: str): + async def forget(self: Self, ctx: commands.Context, factoid_name: str) -> None: """Command to remove a factoid Args: @@ -1093,13 +1107,13 @@ async def forget(self, ctx: commands.Context, factoid_name: str): usage="[factoid-name] [channel] [cron-config]", ) async def loop( - self, + self: Self, ctx: commands.Context, factoid_name: str, channel: discord.TextChannel, *, cron_config: str, - ): + ) -> None: """Command to loop a factoid in a channel Args: @@ -1190,8 +1204,11 @@ async def loop( usage="[factoid-name] [channel]", ) async def deloop( - self, ctx: commands.Context, factoid_name: str, channel: discord.TextChannel - ): + self: Self, + ctx: commands.Context, + factoid_name: str, + channel: discord.TextChannel, + ) -> None: """Command to remove a factoid loop Args: @@ -1242,8 +1259,11 @@ async def deloop( usage="[factoid-name] [channel]", ) async def job( - self, ctx: commands.Context, factoid_name: str, channel: discord.TextChannel - ): + self: Self, + ctx: commands.Context, + factoid_name: str, + channel: discord.TextChannel, + ) -> None: """Command to list info about a loop Args: @@ -1288,7 +1308,7 @@ async def job( brief="Lists loop jobs", description="Lists all the currently registered loop jobs", ) - async def jobs(self, ctx: commands.Context): + async def jobs(self: Self, ctx: commands.Context) -> None: """Command ot list all factoid loop jobs Args: @@ -1372,10 +1392,10 @@ async def _json(self, ctx: commands.Context, factoid_name: str) -> None: usage="[factoid-name]", ) async def info( - self, + self: Self, ctx: commands.Context, query: str, - ): + ) -> None: """Command to list info about a factoid Args: @@ -1449,7 +1469,7 @@ async def info( description="Sends a list of all factoids, can take a file and hidden flag.", usage="[optional-flag]", ) - async def all_(self, ctx: commands.Context, *, flag: str = ""): + async def all_(self: Self, ctx: commands.Context, *, flag: str = "") -> None: """Command to list all factoids Args: @@ -1643,7 +1663,7 @@ async def send_factoids_as_file( aliases: dict, list_only_hidden: bool, flag: str, - ): + ) -> None: """Method to send the factoid list as a file instead of a paste Args: @@ -1707,7 +1727,7 @@ async def send_factoids_as_file( description="Searches a factoid by name and contents", usage="[optional-flag]", ) - async def search(self, ctx: commands.Context, *, query: str): + async def search(self: Self, ctx: commands.Context, *, query: str) -> None: """Commands to search a factoid Args: @@ -1783,11 +1803,11 @@ async def search(self, ctx: commands.Context, *, query: str): usage="[new-alias-name] [original-factoid-name]", ) async def alias( - self, + self: Self, ctx: commands.Context, alias_name: str, factoid_name: str, - ): + ) -> None: """Command to add an alternate way of calling a factoid Args: @@ -1906,8 +1926,11 @@ async def alias( usage="[factoid-name] [optional-new-parent]", ) async def dealias( - self, ctx: commands.Context, factoid_name: str, replacement_name: str = None - ): + self: Self, + ctx: commands.Context, + factoid_name: str, + replacement_name: str = None, + ) -> None: """Command to remove an alias from the group, but never delete the parent Args: @@ -2034,7 +2057,7 @@ async def dealias( brief="Flushes all factoid caches", description="Flushes all factoid caches", ) - async def flush(self, ctx: commands.Context): + async def flush(self: Self, ctx: commands.Context) -> None: """Command to flush all factoid caches Args: @@ -2061,10 +2084,10 @@ async def flush(self, ctx: commands.Context): usage="[factoid-name]", ) async def hide( - self, + self: Self, ctx: commands.Context, factoid_name: str, - ): + ) -> None: """Command to hide a factoid from the .factoid all command Args: @@ -2103,10 +2126,10 @@ async def hide( usage="[factoid-name]", ) async def unhide( - self, + self: Self, ctx: commands.Context, factoid_name: str, - ): + ) -> None: """Command to unhide a factoid from the .factoid all list Args: