diff options
Diffstat (limited to 'bot/exts')
53 files changed, 380 insertions, 389 deletions
| diff --git a/bot/exts/christmas/advent_of_code/_cog.py b/bot/exts/christmas/advent_of_code/_cog.py index 8376987d..da1cf28d 100644 --- a/bot/exts/christmas/advent_of_code/_cog.py +++ b/bot/exts/christmas/advent_of_code/_cog.py @@ -124,7 +124,7 @@ class AdventOfCode(commands.Cog):      @whitelist_override(channels=AOC_WHITELIST)      async def about_aoc(self, ctx: commands.Context) -> None:          """Respond with an explanation of all things Advent of Code.""" -        await ctx.send("", embed=self.cached_about_aoc) +        await ctx.send(embed=self.cached_about_aoc)      @adventofcode_group.command(name="join", aliases=("j",), brief="Learn how to join the leaderboard (via DM)")      @whitelist_override(channels=AOC_WHITELIST) @@ -135,7 +135,7 @@ class AdventOfCode(commands.Cog):              await ctx.send(f"The Python Discord leaderboard for {current_year} is not yet available!")              return -        author = ctx.message.author +        author = ctx.author          log.info(f"{author.name} ({author.id}) has requested a PyDis AoC leaderboard code")          if AocConfig.staff_leaderboard_id and any(r.id == Roles.helpers for r in author.roles): diff --git a/bot/exts/christmas/hanukkah_embed.py b/bot/exts/christmas/hanukkah_embed.py index 4f470a34..cd8a9192 100644 --- a/bot/exts/christmas/hanukkah_embed.py +++ b/bot/exts/christmas/hanukkah_embed.py @@ -5,6 +5,7 @@ from typing import List  from discord import Embed  from discord.ext import commands +from bot.bot import Bot  from bot.constants import Colours, Month  from bot.utils.decorators import in_month @@ -14,7 +15,7 @@ log = logging.getLogger(__name__)  class HanukkahEmbed(commands.Cog):      """A cog that returns information about Hanukkah festival.""" -    def __init__(self, bot: commands.Bot): +    def __init__(self, bot: Bot):          self.bot = bot          self.url = ("https://www.hebcal.com/hebcal/?v=1&cfg=json&maj=on&min=on&mod=on&nx=on&"                      "year=now&month=x&ss=on&mf=on&c=on&geo=geoname&geonameid=3448439&m=50&s=on") @@ -60,17 +61,18 @@ class HanukkahEmbed(commands.Cog):          if day in self.hanukkah_days and month in self.hanukkah_months and year in self.hanukkah_years:              if int(day) == hanukkah_start_day:                  now = datetime.datetime.utcnow() -                now = str(now) -                hours = int(now[11:13]) + 4  # using only hours +                hours = now.hour + 4  # using only hours                  hanukkah_start_hour = 18                  if hours < hanukkah_start_hour:                      embed.description = (f"Hanukkah hasnt started yet, "                                           f"it will start in about {hanukkah_start_hour-hours} hour/s.") -                    return await ctx.send(embed=embed) +                    await ctx.send(embed=embed) +                    return                  elif hours > hanukkah_start_hour:                      embed.description = (f'It is the starting day of Hanukkah ! '                                           f'Its been {hours-hanukkah_start_hour} hours hanukkah started !') -                    return await ctx.send(embed=embed) +                    await ctx.send(embed=embed) +                    return              festival_day = self.hanukkah_days.index(day)              number_suffixes = ['st', 'nd', 'rd', 'th']              suffix = '' @@ -108,6 +110,6 @@ class HanukkahEmbed(commands.Cog):              self.hanukkah_years.append(date[0:4]) -def setup(bot: commands.Bot) -> None: -    """Cog load.""" +def setup(bot: Bot) -> None: +    """Load the Hanukkah Embed Cog."""      bot.add_cog(HanukkahEmbed(bot)) diff --git a/bot/exts/evergreen/battleship.py b/bot/exts/evergreen/battleship.py index 1681434f..813f998e 100644 --- a/bot/exts/evergreen/battleship.py +++ b/bot/exts/evergreen/battleship.py @@ -9,6 +9,7 @@ from functools import partial  import discord  from discord.ext import commands +from bot.bot import Bot  from bot.constants import Colours  log = logging.getLogger(__name__) @@ -95,7 +96,7 @@ class Game:      def __init__(          self, -        bot: commands.Bot, +        bot: Bot,          channel: discord.TextChannel,          player1: discord.Member,          player2: discord.Member @@ -237,7 +238,7 @@ class Game:          square = None          turn_message = await self.turn.user.send(              "It's your turn! Type the square you want to fire at. Format it like this: A1\n" -            "Type `surrender` to give up" +            "Type `surrender` to give up."          )          await self.next.user.send("Their turn", delete_after=3.0)          while True: @@ -321,7 +322,7 @@ class Game:  class Battleship(commands.Cog):      """Play the classic game Battleship!""" -    def __init__(self, bot: commands.Bot) -> None: +    def __init__(self, bot: Bot) -> None:          self.bot = bot          self.games: typing.List[Game] = []          self.waiting: typing.List[discord.Member] = [] @@ -381,7 +382,7 @@ class Battleship(commands.Cog):              return await ctx.send("You're already playing a game!")          if ctx.author in self.waiting: -            return await ctx.send("You've already sent out a request for a player 2") +            return await ctx.send("You've already sent out a request for a player 2.")          announcement = await ctx.send(              "**Battleship**: A new game is about to start!\n" @@ -425,7 +426,7 @@ class Battleship(commands.Cog):              self.games.remove(game)          except Exception:              # End the game in the event of an unforseen error so the players aren't stuck in a game -            await ctx.send(f"{ctx.author.mention} {user.mention} An error occurred. Game failed") +            await ctx.send(f"{ctx.author.mention} {user.mention} An error occurred. Game failed.")              self.games.remove(game)              raise @@ -438,6 +439,6 @@ class Battleship(commands.Cog):          await ctx.send(embed=embed) -def setup(bot: commands.Bot) -> None: -    """Cog load.""" +def setup(bot: Bot) -> None: +    """Load the Battleship cog"""      bot.add_cog(Battleship(bot)) diff --git a/bot/exts/evergreen/bookmark.py b/bot/exts/evergreen/bookmark.py index 5fa05d2e..6a272784 100644 --- a/bot/exts/evergreen/bookmark.py +++ b/bot/exts/evergreen/bookmark.py @@ -4,6 +4,7 @@ import random  import discord  from discord.ext import commands +from bot.bot import Bot  from bot.constants import Colours, ERROR_REPLIES, Emojis, Icons  from bot.utils.converters import WrappedMessageConverter @@ -13,9 +14,6 @@ log = logging.getLogger(__name__)  class Bookmark(commands.Cog):      """Creates personal bookmarks by relaying a message link to the user's DMs.""" -    def __init__(self, bot: commands.Bot): -        self.bot = bot -      @commands.command(name="bookmark", aliases=("bm", "pin"))      async def bookmark(          self, @@ -28,7 +26,7 @@ class Bookmark(commands.Cog):          # Prevent users from bookmarking a message in a channel they don't have access to          permissions = ctx.author.permissions_in(target_message.channel)          if not permissions.read_messages: -            log.info(f"{ctx.author} tried to bookmark a message in #{target_message.channel} but has no permissions") +            log.info(f"{ctx.author} tried to bookmark a message in #{target_message.channel} but has no permissions.")              embed = discord.Embed(                  title=random.choice(ERROR_REPLIES),                  color=Colours.soft_red, @@ -51,7 +49,7 @@ class Bookmark(commands.Cog):          except discord.Forbidden:              error_embed = discord.Embed(                  title=random.choice(ERROR_REPLIES), -                description=f"{ctx.author.mention}, please enable your DMs to receive the bookmark", +                description=f"{ctx.author.mention}, please enable your DMs to receive the bookmark.",                  colour=Colours.soft_red              )              await ctx.send(embed=error_embed) @@ -60,6 +58,6 @@ class Bookmark(commands.Cog):              await ctx.message.add_reaction(Emojis.envelope) -def setup(bot: commands.Bot) -> None: +def setup(bot: Bot) -> None:      """Load the Bookmark cog."""      bot.add_cog(Bookmark(bot)) diff --git a/bot/exts/evergreen/cheatsheet.py b/bot/exts/evergreen/cheatsheet.py index 3fe709d5..57c6d0b0 100644 --- a/bot/exts/evergreen/cheatsheet.py +++ b/bot/exts/evergreen/cheatsheet.py @@ -8,6 +8,7 @@ from discord.ext import commands  from discord.ext.commands import BucketType, Context  from bot import constants +from bot.bot import Bot  from bot.constants import Categories, Channels, Colours, ERROR_REPLIES  from bot.utils.decorators import whitelist_override @@ -33,7 +34,7 @@ HEADERS = {'User-Agent': 'curl/7.68.0'}  class CheatSheet(commands.Cog):      """Commands that sends a result of a cht.sh search in code blocks.""" -    def __init__(self, bot: commands.Bot): +    def __init__(self, bot: Bot):          self.bot = bot      @staticmethod @@ -102,6 +103,6 @@ class CheatSheet(commands.Cog):                  await ctx.send(content=description) -def setup(bot: commands.Bot) -> None: +def setup(bot: Bot) -> None:      """Load the CheatSheet cog."""      bot.add_cog(CheatSheet(bot)) diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 7e3ec42b..df2a913a 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -8,6 +8,7 @@ import emojis  from discord.ext import commands  from discord.ext.commands import guild_only +from bot.bot import Bot  from bot.constants import Emojis  NUMBERS = list(Emojis.number_emojis.values()) @@ -22,7 +23,7 @@ class Game:      def __init__(              self, -            bot: commands.Bot, +            bot: Bot,              channel: discord.TextChannel,              player1: discord.Member,              player2: typing.Optional[discord.Member], @@ -180,7 +181,7 @@ class Game:  class AI:      """The Computer Player for Single-Player games.""" -    def __init__(self, bot: commands.Bot, game: Game) -> None: +    def __init__(self, bot: Bot, game: Game) -> None:          self.game = game          self.mention = bot.user.mention @@ -255,7 +256,7 @@ class AI:  class ConnectFour(commands.Cog):      """Connect Four. The Classic Vertical Four-in-a-row Game!""" -    def __init__(self, bot: commands.Bot) -> None: +    def __init__(self, bot: Bot) -> None:          self.bot = bot          self.games: typing.List[Game] = []          self.waiting: typing.List[discord.Member] = [] @@ -354,7 +355,7 @@ class ConnectFour(commands.Cog):              self.games.remove(game)          except Exception:              # End the game in the event of an unforeseen error so the players aren't stuck in a game -            await ctx.send(f"{ctx.author.mention} {user.mention if user else ''} An error occurred. Game failed") +            await ctx.send(f"{ctx.author.mention} {user.mention if user else ''} An error occurred. Game failed.")              if game in self.games:                  self.games.remove(game)              raise @@ -445,6 +446,6 @@ class ConnectFour(commands.Cog):          await self._play_game(ctx, None, board_size, str(emoji1), str(emoji2)) -def setup(bot: commands.Bot) -> None: +def setup(bot: Bot) -> None:      """Load ConnectFour Cog."""      bot.add_cog(ConnectFour(bot)) diff --git a/bot/exts/evergreen/conversationstarters.py b/bot/exts/evergreen/conversationstarters.py index e7058961..54fea0b3 100644 --- a/bot/exts/evergreen/conversationstarters.py +++ b/bot/exts/evergreen/conversationstarters.py @@ -4,6 +4,7 @@ import yaml  from discord import Color, Embed  from discord.ext import commands +from bot.bot import Bot  from bot.constants import WHITELISTED_CHANNELS  from bot.utils.decorators import whitelist_override  from bot.utils.randomization import RandomCycle @@ -34,9 +35,6 @@ TOPICS = {  class ConvoStarters(commands.Cog):      """Evergreen conversation topics.""" -    def __init__(self, bot: commands.Bot): -        self.bot = bot -      @commands.command()      @whitelist_override(channels=ALL_ALLOWED_CHANNELS)      async def topic(self, ctx: commands.Context) -> None: @@ -66,6 +64,6 @@ class ConvoStarters(commands.Cog):              await ctx.send(embed=embed) -def setup(bot: commands.Bot) -> None: -    """Conversation starters Cog load.""" +def setup(bot: Bot) -> None: +    """Load the ConvoStarters cog."""      bot.add_cog(ConvoStarters(bot)) diff --git a/bot/exts/evergreen/emoji.py b/bot/exts/evergreen/emoji.py index fa3044e3..8e540712 100644 --- a/bot/exts/evergreen/emoji.py +++ b/bot/exts/evergreen/emoji.py @@ -8,6 +8,7 @@ from typing import List, Optional, Tuple  from discord import Color, Embed, Emoji  from discord.ext import commands +from bot.bot import Bot  from bot.constants import Colours, ERROR_REPLIES  from bot.utils.extensions import invoke_help_command  from bot.utils.pagination import LinePaginator @@ -19,9 +20,6 @@ log = logging.getLogger(__name__)  class Emojis(commands.Cog):      """A collection of commands related to emojis in the server.""" -    def __init__(self, bot: commands.Bot): -        self.bot = bot -      @staticmethod      def embed_builder(emoji: dict) -> Tuple[Embed, List[str]]:          """Generates an embed with the emoji names and count.""" @@ -86,7 +84,7 @@ class Emojis(commands.Cog):          if not ctx.guild.emojis:              await ctx.send("No emojis found.")              return -        log.trace(f"Emoji Category {'' if category_query else 'not '}provided by the user") +        log.trace(f"Emoji Category {'' if category_query else 'not '}provided by the user.")          for emoji in ctx.guild.emojis:              emoji_category = emoji.name.split("_")[0] @@ -120,6 +118,6 @@ class Emojis(commands.Cog):          await ctx.send(embed=emoji_information) -def setup(bot: commands.Bot) -> None: -    """Add the Emojis cog into the bot.""" +def setup(bot: Bot) -> None: +    """Load the Emojis cog."""      bot.add_cog(Emojis(bot)) diff --git a/bot/exts/evergreen/error_handler.py b/bot/exts/evergreen/error_handler.py index 8db49748..dabd0ab5 100644 --- a/bot/exts/evergreen/error_handler.py +++ b/bot/exts/evergreen/error_handler.py @@ -7,6 +7,7 @@ from discord import Embed, Message  from discord.ext import commands  from sentry_sdk import push_scope +from bot.bot import Bot  from bot.constants import Channels, Colours, ERROR_REPLIES, NEGATIVE_REPLIES  from bot.utils.decorators import InChannelCheckFailure, InMonthCheckFailure  from bot.utils.exceptions import UserNotPlayingError @@ -17,9 +18,6 @@ log = logging.getLogger(__name__)  class CommandErrorHandler(commands.Cog):      """A error handler for the PythonDiscord server.""" -    def __init__(self, bot: commands.Bot): -        self.bot = bot -      @staticmethod      def revert_cooldown_counter(command: commands.Command, message: Message) -> None:          """Undoes the last cooldown counter for user-error cases.""" @@ -135,6 +133,6 @@ class CommandErrorHandler(commands.Cog):              log.exception(f"Unhandled command error: {str(error)}", exc_info=error) -def setup(bot: commands.Bot) -> None: -    """Error handler Cog load.""" +def setup(bot: Bot) -> None: +    """Load the ErrorHandler cog."""      bot.add_cog(CommandErrorHandler(bot)) diff --git a/bot/exts/evergreen/fun.py b/bot/exts/evergreen/fun.py index 7152d0cb..ed51358c 100644 --- a/bot/exts/evergreen/fun.py +++ b/bot/exts/evergreen/fun.py @@ -7,9 +7,10 @@ from typing import Callable, Iterable, Tuple, Union  from discord import Embed, Message  from discord.ext import commands -from discord.ext.commands import BadArgument, Bot, Cog, Context, MessageConverter, clean_content +from discord.ext.commands import BadArgument, Cog, Context, MessageConverter, clean_content  from bot import utils +from bot.bot import Bot  from bot.constants import Client, Colours, Emojis  from bot.utils import helpers @@ -242,6 +243,6 @@ class Fun(Cog):          return Embed.from_dict(embed_dict) -def setup(bot: commands.Bot) -> None: -    """Fun Cog load.""" +def setup(bot: Bot) -> None: +    """Load the Fun cog."""      bot.add_cog(Fun(bot)) diff --git a/bot/exts/evergreen/game.py b/bot/exts/evergreen/game.py index 068d3f68..24872e76 100644 --- a/bot/exts/evergreen/game.py +++ b/bot/exts/evergreen/game.py @@ -471,7 +471,7 @@ class Games(Cog):  def setup(bot: Bot) -> None: -    """Add/Load Games cog.""" +    """Load the Games cog."""      # Check does IGDB API key exist, if not, log warning and don't load cog      if not Tokens.igdb_client_id:          logger.warning("No IGDB client ID. Not loading Games cog.") diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index c8a6b3f7..fd100a7c 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -7,6 +7,7 @@ import discord  from discord.ext import commands  from discord.ext.commands.cooldowns import BucketType +from bot.bot import Bot  from bot.constants import Colours, NEGATIVE_REPLIES  from bot.exts.utils.extensions import invoke_help_command @@ -18,7 +19,7 @@ GITHUB_API_URL = "https://api.github.com"  class GithubInfo(commands.Cog):      """Fetches info from GitHub.""" -    def __init__(self, bot: commands.Bot): +    def __init__(self, bot: Bot):          self.bot = bot      async def fetch_data(self, url: str) -> dict: @@ -95,7 +96,7 @@ class GithubInfo(commands.Cog):                  embed.add_field(                      name=f"Organization{'s' if len(orgs)!=1 else ''}", -                    value=orgs_to_add if orgs else "No organizations" +                    value=orgs_to_add if orgs else "No organizations."                  )              embed.add_field(name="Website", value=blog) @@ -170,6 +171,6 @@ class GithubInfo(commands.Cog):          await ctx.send(embed=embed) -def setup(bot: commands.Bot) -> None: -    """Adding the cog to the bot.""" +def setup(bot: Bot) -> None: +    """Load the GithubInfo cog."""      bot.add_cog(GithubInfo(bot)) diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index a0316080..d7ee99c0 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -7,6 +7,7 @@ from dataclasses import dataclass  import discord  from discord.ext import commands +from bot.bot import Bot  from bot.constants import (      Categories,      Channels, @@ -91,7 +92,7 @@ class IssueState:  class Issues(commands.Cog):      """Cog that allows users to retrieve issues from GitHub.""" -    def __init__(self, bot: commands.Bot): +    def __init__(self, bot: Bot):          self.bot = bot          self.repos = [] @@ -269,6 +270,6 @@ class Issues(commands.Cog):          await message.channel.send(embed=resp) -def setup(bot: commands.Bot) -> None: -    """Cog Retrieves Issues From Github.""" +def setup(bot: Bot) -> None: +    """Load the Issues cog."""      bot.add_cog(Issues(bot)) diff --git a/bot/exts/evergreen/latex.py b/bot/exts/evergreen/latex.py index c4a8597c..3a93907a 100644 --- a/bot/exts/evergreen/latex.py +++ b/bot/exts/evergreen/latex.py @@ -9,6 +9,8 @@ import discord  import matplotlib.pyplot as plt  from discord.ext import commands +from bot.bot import Bot +  # configure fonts and colors for matplotlib  plt.rcParams.update(      { @@ -89,6 +91,6 @@ class Latex(commands.Cog):              await ctx.send(file=discord.File(image, "latex.png")) -def setup(bot: commands.Bot) -> None: +def setup(bot: Bot) -> None:      """Load the Latex Cog."""      bot.add_cog(Latex(bot)) diff --git a/bot/exts/evergreen/magic_8ball.py b/bot/exts/evergreen/magic_8ball.py index f974e487..708aa6d2 100644 --- a/bot/exts/evergreen/magic_8ball.py +++ b/bot/exts/evergreen/magic_8ball.py @@ -5,14 +5,15 @@ from pathlib import Path  from discord.ext import commands +from bot.bot import Bot +  log = logging.getLogger(__name__)  class Magic8ball(commands.Cog):      """A Magic 8ball command to respond to a user's question.""" -    def __init__(self, bot: commands.Bot): -        self.bot = bot +    def __init__(self, _bot: Bot):          with open(Path("bot/resources/evergreen/magic8ball.json"), "r", encoding="utf8") as file:              self.answers = json.load(file) @@ -26,6 +27,6 @@ class Magic8ball(commands.Cog):              await ctx.send("Usage: .8ball <question> (minimum length of 3 eg: `will I win?`)") -def setup(bot: commands.Bot) -> None: -    """Magic 8ball Cog load.""" +def setup(bot: Bot) -> None: +    """Load the Magic8Ball cog."""      bot.add_cog(Magic8ball(bot)) diff --git a/bot/exts/evergreen/minesweeper.py b/bot/exts/evergreen/minesweeper.py index 3031debc..d0cc28c5 100644 --- a/bot/exts/evergreen/minesweeper.py +++ b/bot/exts/evergreen/minesweeper.py @@ -6,6 +6,7 @@ from random import randint, random  import discord  from discord.ext import commands +from bot.bot import Bot  from bot.constants import Client  from bot.utils.exceptions import UserNotPlayingError  from bot.utils.extensions import invoke_help_command @@ -37,7 +38,7 @@ class CoordinateConverter(commands.Converter):      async def convert(self, ctx: commands.Context, coordinate: str) -> typing.Tuple[int, int]:          """Take in a coordinate string and turn it into an (x, y) tuple."""          if not 2 <= len(coordinate) <= 3: -            raise commands.BadArgument('Invalid co-ordinate provided') +            raise commands.BadArgument('Invalid co-ordinate provided.')          coordinate = coordinate.lower()          if coordinate[0].isalpha(): @@ -78,7 +79,7 @@ GamesDict = typing.Dict[int, Game]  class Minesweeper(commands.Cog):      """Play a game of Minesweeper.""" -    def __init__(self, bot: commands.Bot) -> None: +    def __init__(self, _bot: Bot) -> None:          self.games: GamesDict = {}  # Store the currently running games      @commands.group(name='minesweeper', aliases=('ms',), invoke_without_command=True) @@ -148,7 +149,7 @@ class Minesweeper(commands.Cog):                  f"Close the game with `{Client.prefix}ms end`\n"              )          except discord.errors.Forbidden: -            log.debug(f"{ctx.author.name} ({ctx.author.id}) has disabled DMs from server members") +            log.debug(f"{ctx.author.name} ({ctx.author.id}) has disabled DMs from server members.")              await ctx.send(f":x: {ctx.author.mention}, please enable DMs to play minesweeper.")              return @@ -158,7 +159,7 @@ class Minesweeper(commands.Cog):          dm_msg = await ctx.author.send(f"Here's your board!\n{self.format_for_discord(revealed_board)}")          if ctx.guild: -            await ctx.send(f"{ctx.author.mention} is playing Minesweeper") +            await ctx.send(f"{ctx.author.mention} is playing Minesweeper.")              chat_msg = await ctx.send(f"Here's their board!\n{self.format_for_discord(revealed_board)}")          else:              chat_msg = None @@ -247,7 +248,7 @@ class Minesweeper(commands.Cog):          """          Reveal one square. -        return is True if the game ended, breaking the loop in `reveal_command` and deleting the game +        return is True if the game ended, breaking the loop in `reveal_command` and deleting the game.          """          revealed[y][x] = board[y][x]          if board[y][x] == "bomb": @@ -285,13 +286,13 @@ class Minesweeper(commands.Cog):          game = self.games[ctx.author.id]          game.revealed = game.board          await self.update_boards(ctx) -        new_msg = f":no_entry: Game canceled :no_entry:\n{game.dm_msg.content}" +        new_msg = f":no_entry: Game canceled. :no_entry:\n{game.dm_msg.content}"          await game.dm_msg.edit(content=new_msg)          if game.activated_on_server:              await game.chat_msg.edit(content=new_msg)          del self.games[ctx.author.id] -def setup(bot: commands.Bot) -> None: +def setup(bot: Bot) -> None:      """Load the Minesweeper cog."""      bot.add_cog(Minesweeper(bot)) diff --git a/bot/exts/evergreen/movie.py b/bot/exts/evergreen/movie.py index b3bfe998..488e5142 100644 --- a/bot/exts/evergreen/movie.py +++ b/bot/exts/evergreen/movie.py @@ -6,8 +6,9 @@ from urllib.parse import urlencode  from aiohttp import ClientSession  from discord import Embed -from discord.ext.commands import Bot, Cog, Context, group +from discord.ext.commands import Cog, Context, group +from bot.bot import Bot  from bot.constants import Tokens  from bot.utils.extensions import invoke_help_command  from bot.utils.pagination import ImagePaginator @@ -50,7 +51,6 @@ class Movie(Cog):      """Movie Cog contains movies command that grab random movies from TMDB."""      def __init__(self, bot: Bot): -        self.bot = bot          self.http_session: ClientSession = bot.http_session      @group(name='movies', aliases=['movie'], invoke_without_command=True) @@ -198,5 +198,5 @@ class Movie(Cog):  def setup(bot: Bot) -> None: -    """Load Movie Cog.""" +    """Load the Movie Cog."""      bot.add_cog(Movie(bot)) diff --git a/bot/exts/evergreen/ping.py b/bot/exts/evergreen/ping.py index 97f8b34d..71152d15 100644 --- a/bot/exts/evergreen/ping.py +++ b/bot/exts/evergreen/ping.py @@ -1,13 +1,14 @@  from discord import Embed  from discord.ext import commands +from bot.bot import Bot  from bot.constants import Colours  class Ping(commands.Cog):      """Ping the bot to see its latency and state.""" -    def __init__(self, bot: commands.Bot): +    def __init__(self, bot: Bot):          self.bot = bot      @commands.command(name="ping") @@ -22,6 +23,6 @@ class Ping(commands.Cog):          await ctx.send(embed=embed) -def setup(bot: commands.Bot) -> None: -    """Cog load.""" +def setup(bot: Bot) -> None: +    """Load the Ping cog."""      bot.add_cog(Ping(bot)) diff --git a/bot/exts/evergreen/pythonfacts.py b/bot/exts/evergreen/pythonfacts.py index 457c2fd3..73234d55 100644 --- a/bot/exts/evergreen/pythonfacts.py +++ b/bot/exts/evergreen/pythonfacts.py @@ -3,6 +3,7 @@ import itertools  import discord  from discord.ext import commands +from bot.bot import Bot  from bot.constants import Colours  with open('bot/resources/evergreen/python_facts.txt') as file: @@ -14,9 +15,6 @@ COLORS = itertools.cycle([Colours.python_blue, Colours.python_yellow])  class PythonFacts(commands.Cog):      """Sends a random fun fact about Python.""" -    def __init__(self, bot: commands.Bot) -> None: -        self.bot = bot -      @commands.command(name='pythonfact', aliases=['pyfact'])      async def get_python_fact(self, ctx: commands.Context) -> None:          """Sends a Random fun fact about Python.""" @@ -28,6 +26,6 @@ class PythonFacts(commands.Cog):          await ctx.send(embed=embed) -def setup(bot: commands.Bot) -> None: -    """Load PythonFacts Cog.""" +def setup(bot: Bot) -> None: +    """Load the PythonFacts Cog."""      bot.add_cog(PythonFacts(bot)) diff --git a/bot/exts/evergreen/recommend_game.py b/bot/exts/evergreen/recommend_game.py index 5e262a5b..be329f44 100644 --- a/bot/exts/evergreen/recommend_game.py +++ b/bot/exts/evergreen/recommend_game.py @@ -6,6 +6,8 @@ from random import shuffle  import discord  from discord.ext import commands +from bot.bot import Bot +  log = logging.getLogger(__name__)  game_recs = [] @@ -20,7 +22,7 @@ shuffle(game_recs)  class RecommendGame(commands.Cog):      """Commands related to recommending games.""" -    def __init__(self, bot: commands.Bot) -> None: +    def __init__(self, bot: Bot) -> None:          self.bot = bot          self.index = 0 @@ -45,6 +47,6 @@ class RecommendGame(commands.Cog):          await ctx.send(embed=embed) -def setup(bot: commands.Bot) -> None: +def setup(bot: Bot) -> None:      """Loads the RecommendGame cog."""      bot.add_cog(RecommendGame(bot)) diff --git a/bot/exts/evergreen/reddit.py b/bot/exts/evergreen/reddit.py index 2be511c8..518ffeb7 100644 --- a/bot/exts/evergreen/reddit.py +++ b/bot/exts/evergreen/reddit.py @@ -5,6 +5,7 @@ import discord  from discord.ext import commands  from discord.ext.commands.cooldowns import BucketType +from bot.bot import Bot  from bot.utils.pagination import ImagePaginator  log = logging.getLogger(__name__) @@ -13,7 +14,7 @@ log = logging.getLogger(__name__)  class Reddit(commands.Cog):      """Fetches reddit posts.""" -    def __init__(self, bot: commands.Bot): +    def __init__(self, bot: Bot):          self.bot = bot      async def fetch(self, url: str) -> dict: @@ -123,6 +124,6 @@ class Reddit(commands.Cog):          await ImagePaginator.paginate(pages, ctx, embed) -def setup(bot: commands.Bot) -> None: -    """Load the Cog.""" +def setup(bot: Bot) -> None: +    """Load the Reddit cog."""      bot.add_cog(Reddit(bot)) diff --git a/bot/exts/evergreen/snakes/_snakes_cog.py b/bot/exts/evergreen/snakes/_snakes_cog.py index 3732b559..70093912 100644 --- a/bot/exts/evergreen/snakes/_snakes_cog.py +++ b/bot/exts/evergreen/snakes/_snakes_cog.py @@ -423,7 +423,7 @@ class Snakes(Cog):          try:              reaction, user = await ctx.bot.wait_for("reaction_add", timeout=45.0, check=predicate)          except asyncio.TimeoutError: -            await ctx.channel.send(f"You took too long. The correct answer was **{options[answer]}**.") +            await ctx.send(f"You took too long. The correct answer was **{options[answer]}**.")              await message.clear_reactions()              return @@ -720,7 +720,7 @@ class Snakes(Cog):          snake_image = utils.snakes[snake_name]          # Hatch the snake -        message = await ctx.channel.send(embed=Embed(description="Hatching your snake :snake:...")) +        message = await ctx.send(embed=Embed(description="Hatching your snake :snake:..."))          await asyncio.sleep(1)          for stage in utils.stages: @@ -737,7 +737,7 @@ class Snakes(Cog):              text=" Owner: {0}#{1}".format(ctx.message.author.name, ctx.message.author.discriminator)          ) -        await ctx.channel.send(embed=my_snake_embed) +        await ctx.send(embed=my_snake_embed)      @snakes_group.command(name='movie')      async def movie_command(self, ctx: Context) -> None: @@ -800,9 +800,9 @@ class Snakes(Cog):          embed.set_thumbnail(url="https://i.imgur.com/LtFtC8H.png")          try: -            await ctx.channel.send(embed=embed) +            await ctx.send(embed=embed)          except HTTPException as err: -            await ctx.channel.send("An error occurred while fetching a snake-related movie!") +            await ctx.send("An error occurred while fetching a snake-related movie!")              raise err from None      @snakes_group.command(name='quiz') @@ -828,7 +828,7 @@ class Snakes(Cog):              )          ) -        quiz = await ctx.channel.send("", embed=embed) +        quiz = await ctx.send("", embed=embed)          await self._validate_answer(ctx, quiz, answer, options)      @snakes_group.command(name='name', aliases=('name_gen',)) @@ -964,7 +964,7 @@ class Snakes(Cog):              )          ) -        await ctx.channel.send(embed=embed) +        await ctx.send(embed=embed)      @snakes_group.command(name='card')      async def card_command(self, ctx: Context, *, name: Snake = None) -> None: @@ -1018,7 +1018,7 @@ class Snakes(Cog):              color=SNAKE_COLOR,              description=question          ) -        await ctx.channel.send(embed=embed) +        await ctx.send(embed=embed)      @snakes_group.command(name='snakify')      async def snakify_command(self, ctx: Context, *, message: str = None) -> None: @@ -1059,7 +1059,7 @@ class Snakes(Cog):              )              embed.description = f"*{self._snakify(message)}*" -            await ctx.channel.send(embed=embed) +            await ctx.send(embed=embed)      @snakes_group.command(name='video', aliases=('get_video',))      async def video_command(self, ctx: Context, *, search: str = None) -> None: @@ -1095,7 +1095,7 @@ class Snakes(Cog):          if len(data) > 0:              num = random.randint(0, len(data) - 1)              youtube_base_url = 'https://www.youtube.com/watch?v=' -            await ctx.channel.send( +            await ctx.send(                  content=f"{youtube_base_url}{data[num]['id']['videoId']}"              )          else: @@ -1120,7 +1120,7 @@ class Snakes(Cog):          # Embed and send          embed.description = zen_quote -        await ctx.channel.send( +        await ctx.send(              embed=embed          )      # endregion diff --git a/bot/exts/evergreen/source.py b/bot/exts/evergreen/source.py index 45752bf9..14fd02f3 100644 --- a/bot/exts/evergreen/source.py +++ b/bot/exts/evergreen/source.py @@ -5,6 +5,7 @@ from typing import Optional, Tuple, Union  from discord import Embed  from discord.ext import commands +from bot.bot import Bot  from bot.constants import Source  SourceType = Union[commands.Command, commands.Cog, str, commands.ExtensionNotLoaded] @@ -31,9 +32,6 @@ class SourceConverter(commands.Converter):  class BotSource(commands.Cog):      """Displays information about the bot's source code.""" -    def __init__(self, bot: commands.Bot): -        self.bot = bot -      @commands.command(name="source", aliases=("src",))      async def source_command(self, ctx: commands.Context, *, source_item: SourceConverter = None) -> None:          """Display information and a GitHub link to the source code of a command, tag, or cog.""" @@ -104,6 +102,6 @@ class BotSource(commands.Cog):          return embed -def setup(bot: commands.Bot) -> None: +def setup(bot: Bot) -> None:      """Load the BotSource cog."""      bot.add_cog(BotSource(bot)) diff --git a/bot/exts/evergreen/space.py b/bot/exts/evergreen/space.py index 323ff659..ee9ad38c 100644 --- a/bot/exts/evergreen/space.py +++ b/bot/exts/evergreen/space.py @@ -39,7 +39,6 @@ class Space(Cog):      """Space Cog contains commands, that show images, facts or other information about space."""      def __init__(self, bot: Bot): -        self.bot = bot          self.http_session = bot.http_session          self.rovers = {} @@ -242,7 +241,7 @@ class Space(Cog):  def setup(bot: Bot) -> None: -    """Load Space Cog.""" +    """Load the Space cog."""      if not Tokens.nasa:          logger.warning("Can't find NASA API key. Not loading Space Cog.")          return diff --git a/bot/exts/evergreen/speedrun.py b/bot/exts/evergreen/speedrun.py index 21aad5aa..bf6f2117 100644 --- a/bot/exts/evergreen/speedrun.py +++ b/bot/exts/evergreen/speedrun.py @@ -5,6 +5,8 @@ from random import choice  from discord.ext import commands +from bot.bot import Bot +  log = logging.getLogger(__name__)  with Path('bot/resources/evergreen/speedrun_links.json').open(encoding="utf8") as file:      LINKS = json.load(file) @@ -13,15 +15,12 @@ with Path('bot/resources/evergreen/speedrun_links.json').open(encoding="utf8") a  class Speedrun(commands.Cog):      """Commands about the video game speedrunning community.""" -    def __init__(self, bot: commands.Bot): -        self.bot = bot -      @commands.command(name="speedrun")      async def get_speedrun(self, ctx: commands.Context) -> None:          """Sends a link to a video of a random speedrun."""          await ctx.send(choice(LINKS)) -def setup(bot: commands.Bot) -> None: +def setup(bot: Bot) -> None:      """Load the Speedrun cog."""      bot.add_cog(Speedrun(bot)) diff --git a/bot/exts/evergreen/status_codes.py b/bot/exts/evergreen/status_codes.py index 7c00fe20..635eef3d 100644 --- a/bot/exts/evergreen/status_codes.py +++ b/bot/exts/evergreen/status_codes.py @@ -3,6 +3,7 @@ from http import HTTPStatus  import discord  from discord.ext import commands +from bot.bot import Bot  from bot.utils.extensions import invoke_help_command  HTTP_DOG_URL = "https://httpstatusdogs.com/img/{code}.jpg" @@ -12,7 +13,7 @@ HTTP_CAT_URL = "https://http.cat/{code}.jpg"  class HTTPStatusCodes(commands.Cog):      """Commands that give HTTP statuses described and visualized by cats and dogs.""" -    def __init__(self, bot: commands.Bot): +    def __init__(self, bot: Bot):          self.bot = bot      @commands.group(name="http_status", aliases=("status", "httpstatus")) @@ -68,6 +69,6 @@ class HTTPStatusCodes(commands.Cog):              await ctx.send(embed=embed) -def setup(bot: commands.Bot) -> None: +def setup(bot: Bot) -> None:      """Load the HTTPStatusCodes cog."""      bot.add_cog(HTTPStatusCodes(bot)) diff --git a/bot/exts/evergreen/tic_tac_toe.py b/bot/exts/evergreen/tic_tac_toe.py index 6e21528e..1fef427a 100644 --- a/bot/exts/evergreen/tic_tac_toe.py +++ b/bot/exts/evergreen/tic_tac_toe.py @@ -246,8 +246,7 @@ def is_requester_free() -> t.Callable:  class TicTacToe(Cog):      """TicTacToe cog contains tic-tac-toe game commands.""" -    def __init__(self, bot: Bot): -        self.bot = bot +    def __init__(self, _bot: Bot):          self.games: t.List[Game] = []      @guild_only() @@ -323,5 +322,5 @@ class TicTacToe(Cog):  def setup(bot: Bot) -> None: -    """Load TicTacToe Cog.""" +    """Load the TicTacToe cog."""      bot.add_cog(TicTacToe(bot)) diff --git a/bot/exts/evergreen/timed.py b/bot/exts/evergreen/timed.py index 5f177fd6..42a77346 100644 --- a/bot/exts/evergreen/timed.py +++ b/bot/exts/evergreen/timed.py @@ -4,6 +4,8 @@ from time import perf_counter  from discord import Message  from discord.ext import commands +from bot.bot import Bot +  class TimedCommands(commands.Cog):      """Time the command execution of a command.""" @@ -41,6 +43,6 @@ class TimedCommands(commands.Cog):          await ctx.send(f"Command execution for `{new_ctx.command}` finished in {(t_end - t_start):.4f} seconds.") -def setup(bot: commands.Bot) -> None: -    """Cog load.""" +def setup(bot: Bot) -> None: +    """Load the Timed cog."""      bot.add_cog(TimedCommands(bot)) diff --git a/bot/exts/evergreen/trivia_quiz.py b/bot/exts/evergreen/trivia_quiz.py index fe692c2a..f40375a6 100644 --- a/bot/exts/evergreen/trivia_quiz.py +++ b/bot/exts/evergreen/trivia_quiz.py @@ -8,6 +8,7 @@ import discord  from discord.ext import commands  from fuzzywuzzy import fuzz +from bot.bot import Bot  from bot.constants import Roles @@ -23,7 +24,7 @@ WRONG_ANS_RESPONSE = [  class TriviaQuiz(commands.Cog):      """A cog for all quiz commands.""" -    def __init__(self, bot: commands.Bot) -> None: +    def __init__(self, bot: Bot) -> None:          self.bot = bot          self.questions = self.load_questions()          self.game_status = {}  # A variable to store the game status: either running or not running. @@ -299,6 +300,6 @@ class TriviaQuiz(commands.Cog):          await channel.send(embed=embed) -def setup(bot: commands.Bot) -> None: -    """Load the cog.""" +def setup(bot: Bot) -> None: +    """Load the TriviaQuiz cog."""      bot.add_cog(TriviaQuiz(bot)) diff --git a/bot/exts/evergreen/uptime.py b/bot/exts/evergreen/uptime.py index a9ad9dfb..d2509e6f 100644 --- a/bot/exts/evergreen/uptime.py +++ b/bot/exts/evergreen/uptime.py @@ -5,6 +5,7 @@ from dateutil.relativedelta import relativedelta  from discord.ext import commands  from bot import start_time +from bot.bot import Bot  log = logging.getLogger(__name__) @@ -12,9 +13,6 @@ log = logging.getLogger(__name__)  class Uptime(commands.Cog):      """A cog for posting the bot's uptime.""" -    def __init__(self, bot: commands.Bot): -        self.bot = bot -      @commands.command(name="uptime")      async def uptime(self, ctx: commands.Context) -> None:          """Responds with the uptime of the bot.""" @@ -28,6 +26,6 @@ class Uptime(commands.Cog):          await ctx.send(f"I started up {uptime_string}.") -def setup(bot: commands.Bot) -> None: -    """Uptime Cog load.""" +def setup(bot: Bot) -> None: +    """Load the Uptime cog."""      bot.add_cog(Uptime(bot)) diff --git a/bot/exts/evergreen/wikipedia.py b/bot/exts/evergreen/wikipedia.py index 068c4f43..e2172fc3 100644 --- a/bot/exts/evergreen/wikipedia.py +++ b/bot/exts/evergreen/wikipedia.py @@ -90,5 +90,5 @@ class WikipediaSearch(commands.Cog):  def setup(bot: Bot) -> None: -    """Wikipedia Cog load.""" +    """Load the WikipediaSearch cog."""      bot.add_cog(WikipediaSearch(bot)) diff --git a/bot/exts/evergreen/wolfram.py b/bot/exts/evergreen/wolfram.py index 14ec1041..c57a8d7a 100644 --- a/bot/exts/evergreen/wolfram.py +++ b/bot/exts/evergreen/wolfram.py @@ -9,6 +9,7 @@ from discord import Embed  from discord.ext import commands  from discord.ext.commands import BucketType, Cog, Context, check, group +from bot.bot import Bot  from bot.constants import Colours, STAFF_ROLES, Wolfram  from bot.utils.pagination import ImagePaginator @@ -55,7 +56,7 @@ def custom_cooldown(*ignore: List[int]) -> Callable:      """      Implement per-user and per-guild cooldowns for requests to the Wolfram API. -    A list of roles may be provided to ignore the per-user cooldown +    A list of roles may be provided to ignore the per-user cooldown.      """      async def predicate(ctx: Context) -> bool:          if ctx.invoked_with == 'help': @@ -102,7 +103,7 @@ def custom_cooldown(*ignore: List[int]) -> Callable:      return check(predicate) -async def get_pod_pages(ctx: Context, bot: commands.Bot, query: str) -> Optional[List[Tuple]]: +async def get_pod_pages(ctx: Context, bot: Bot, query: str) -> Optional[List[Tuple]]:      """Get the Wolfram API pod pages for the provided query."""      async with ctx.channel.typing():          url_str = parse.urlencode({ @@ -162,7 +163,7 @@ async def get_pod_pages(ctx: Context, bot: commands.Bot, query: str) -> Optional  class Wolfram(Cog):      """Commands for interacting with the Wolfram|Alpha API.""" -    def __init__(self, bot: commands.Bot): +    def __init__(self, bot: Bot):          self.bot = bot      @group(name="wolfram", aliases=("wolf", "wa"), invoke_without_command=True) @@ -188,11 +189,11 @@ class Wolfram(Cog):              image_url = "attachment://image.png"              if status == 501: -                message = "Failed to get response" +                message = "Failed to get response."                  footer = ""                  color = Colours.soft_red              elif status == 400: -                message = "No input found" +                message = "No input found."                  footer = ""                  color = Colours.soft_red              elif status == 403: @@ -268,12 +269,12 @@ class Wolfram(Cog):                  response_text = await response.text()              if status == 501: -                message = "Failed to get response" +                message = "Failed to get response."                  color = Colours.soft_red              elif status == 400: -                message = "No input found" +                message = "No input found."                  color = Colours.soft_red -            elif response_text == "Error 1: Invalid appid": +            elif response_text == "Error 1: Invalid appid.":                  message = "Wolfram API key is invalid or missing."                  color = Colours.soft_red              else: @@ -283,6 +284,6 @@ class Wolfram(Cog):              await send_embed(ctx, message, color) -def setup(bot: commands.Bot) -> None: +def setup(bot: Bot) -> None:      """Load the Wolfram cog."""      bot.add_cog(Wolfram(bot)) diff --git a/bot/exts/evergreen/wonder_twins.py b/bot/exts/evergreen/wonder_twins.py index afc5346e..9fa2d7f8 100644 --- a/bot/exts/evergreen/wonder_twins.py +++ b/bot/exts/evergreen/wonder_twins.py @@ -2,15 +2,15 @@ import random  from pathlib import Path  import yaml -from discord.ext.commands import Bot, Cog, Context, command +from discord.ext.commands import Cog, Context, command + +from bot.bot import Bot  class WonderTwins(Cog):      """Cog for a Wonder Twins inspired command.""" -    def __init__(self, bot: Bot): -        self.bot = bot - +    def __init__(self, _bot: Bot):          with open(Path.cwd() / "bot" / "resources" / "evergreen" / "wonder_twins.yaml", "r", encoding="utf-8") as f:              info = yaml.load(f, Loader=yaml.FullLoader)              self.water_types = info["water_types"] diff --git a/bot/exts/evergreen/xkcd.py b/bot/exts/evergreen/xkcd.py index 1ff98ca2..ba9e46e0 100644 --- a/bot/exts/evergreen/xkcd.py +++ b/bot/exts/evergreen/xkcd.py @@ -87,5 +87,5 @@ class XKCD(Cog):  def setup(bot: Bot) -> None: -    """Loading the XKCD cog.""" +    """Load the XKCD cog."""      bot.add_cog(XKCD(bot)) diff --git a/bot/exts/halloween/8ball.py b/bot/exts/halloween/8ball.py index 1df48fbf..59d4acc5 100644 --- a/bot/exts/halloween/8ball.py +++ b/bot/exts/halloween/8ball.py @@ -6,28 +6,27 @@ from pathlib import Path  from discord.ext import commands +from bot.bot import Bot +  log = logging.getLogger(__name__) -with open(Path("bot/resources/halloween/responses.json"), "r", encoding="utf8") as f: -    responses = json.load(f) +with Path("bot/resources/halloween/responses.json").open("r", encoding="utf8") as f: +    RESPONSES = json.load(f)  class SpookyEightBall(commands.Cog):      """Spooky Eightball answers.""" -    def __init__(self, bot: commands.Bot): -        self.bot = bot -      @commands.command(aliases=('spooky8ball',))      async def spookyeightball(self, ctx: commands.Context, *, question: str) -> None:          """Responds with a random response to a question.""" -        choice = random.choice(responses['responses']) +        choice = random.choice(RESPONSES["responses"])          msg = await ctx.send(choice[0])          if len(choice) > 1:              await asyncio.sleep(random.randint(2, 5))              await msg.edit(content=f"{choice[0]} \n{choice[1]}") -def setup(bot: commands.Bot) -> None: -    """Spooky Eight Ball Cog Load.""" -    bot.add_cog(SpookyEightBall(bot)) +def setup(bot: Bot) -> None: +    """Load the Spooky Eight Ball Cog.""" +    bot.add_cog(SpookyEightBall()) diff --git a/bot/exts/halloween/candy_collection.py b/bot/exts/halloween/candy_collection.py index 40e21f40..5441d8a5 100644 --- a/bot/exts/halloween/candy_collection.py +++ b/bot/exts/halloween/candy_collection.py @@ -6,6 +6,7 @@ import discord  from async_rediscache import RedisCache  from discord.ext import commands +from bot.bot import Bot  from bot.constants import Channels, Month  from bot.utils.decorators import in_month @@ -40,7 +41,7 @@ class CandyCollection(commands.Cog):      candy_messages = RedisCache()      skull_messages = RedisCache() -    def __init__(self, bot: commands.Bot): +    def __init__(self, bot: Bot):          self.bot = bot      @in_month(Month.OCTOBER) @@ -60,15 +61,15 @@ class CandyCollection(commands.Cog):          # do random check for skull first as it has the lower chance          if random.randint(1, ADD_SKULL_REACTION_CHANCE) == 1:              await self.skull_messages.set(message.id, "skull") -            return await message.add_reaction(EMOJIS['SKULL']) +            await message.add_reaction(EMOJIS["SKULL"])          # check for the candy chance next -        if random.randint(1, ADD_CANDY_REACTION_CHANCE) == 1: +        elif random.randint(1, ADD_CANDY_REACTION_CHANCE) == 1:              await self.candy_messages.set(message.id, "candy") -            return await message.add_reaction(EMOJIS['CANDY']) +            await message.add_reaction(EMOJIS["CANDY"])      @in_month(Month.OCTOBER)      @commands.Cog.listener() -    async def on_reaction_add(self, reaction: discord.Reaction, user: discord.Member) -> None: +    async def on_reaction_add(self, reaction: discord.Reaction, user: Union[discord.User, discord.Member]) -> None:          """Add/remove candies from a person if the reaction satisfies criteria."""          message = reaction.message          # check to ensure the reactor is human @@ -81,7 +82,7 @@ class CandyCollection(commands.Cog):          # if its not a candy or skull, and it is one of 10 most recent messages,          # proceed to add a skull/candy with higher chance -        if str(reaction.emoji) not in (EMOJIS['SKULL'], EMOJIS['CANDY']): +        if str(reaction.emoji) not in (EMOJIS["SKULL"], EMOJIS["CANDY"]):              recent_message_ids = map(                  lambda m: m.id,                  await self.hacktober_channel.history(limit=10).flatten() @@ -90,14 +91,14 @@ class CandyCollection(commands.Cog):                  await self.reacted_msg_chance(message)              return -        if await self.candy_messages.get(message.id) == "candy" and str(reaction.emoji) == EMOJIS['CANDY']: +        if await self.candy_messages.get(message.id) == "candy" and str(reaction.emoji) == EMOJIS["CANDY"]:              await self.candy_messages.delete(message.id)              if await self.candy_records.contains(user.id):                  await self.candy_records.increment(user.id)              else:                  await self.candy_records.set(user.id, 1) -        elif await self.skull_messages.get(message.id) == "skull" and str(reaction.emoji) == EMOJIS['SKULL']: +        elif await self.skull_messages.get(message.id) == "skull" and str(reaction.emoji) == EMOJIS["SKULL"]:              await self.skull_messages.delete(message.id)              if prev_record := await self.candy_records.get(user.id): @@ -124,11 +125,11 @@ class CandyCollection(commands.Cog):          """          if random.randint(1, ADD_SKULL_EXISTING_REACTION_CHANCE) == 1:              await self.skull_messages.set(message.id, "skull") -            return await message.add_reaction(EMOJIS['SKULL']) +            await message.add_reaction(EMOJIS['SKULL']) -        if random.randint(1, ADD_CANDY_EXISTING_REACTION_CHANCE) == 1: +        elif random.randint(1, ADD_CANDY_EXISTING_REACTION_CHANCE) == 1:              await self.candy_messages.set(message.id, "candy") -            return await message.add_reaction(EMOJIS['CANDY']) +            await message.add_reaction(EMOJIS["CANDY"])      @property      def hacktober_channel(self) -> discord.TextChannel: @@ -141,8 +142,10 @@ class CandyCollection(commands.Cog):      ) -> None:          """Send a spooky message."""          e = discord.Embed(colour=author.colour) -        e.set_author(name="Ghosts and Ghouls and Jack o' lanterns at night; " -                          f"I took {candies} candies and quickly took flight.") +        e.set_author( +            name="Ghosts and Ghouls and Jack o' lanterns at night; " +            f"I took {candies} candies and quickly took flight." +        )          await channel.send(embed=e)      @staticmethod @@ -173,7 +176,7 @@ class CandyCollection(commands.Cog):              return '\n'.join(                  f"{EMOJIS['MEDALS'][index]} <@{record[0]}>: {record[1]}"                  for index, record in enumerate(top_five) -            ) if top_five else 'No Candies' +            ) if top_five else "No Candies"          e = discord.Embed(colour=discord.Colour.blurple())          e.add_field( @@ -191,6 +194,6 @@ class CandyCollection(commands.Cog):          await ctx.send(embed=e) -def setup(bot: commands.Bot) -> None: -    """Candy Collection game Cog load.""" +def setup(bot: Bot) -> None: +    """Load the Candy Collection Cog."""      bot.add_cog(CandyCollection(bot)) diff --git a/bot/exts/halloween/hacktober-issue-finder.py b/bot/exts/halloween/hacktober-issue-finder.py index 9deadde9..c88e2b6f 100644 --- a/bot/exts/halloween/hacktober-issue-finder.py +++ b/bot/exts/halloween/hacktober-issue-finder.py @@ -3,10 +3,10 @@ import logging  import random  from typing import Dict, Optional -import aiohttp  import discord  from discord.ext import commands +from bot.bot import Bot  from bot.constants import Month, Tokens  from bot.utils.decorators import in_month @@ -25,7 +25,7 @@ if GITHUB_TOKEN := Tokens.github:  class HacktoberIssues(commands.Cog):      """Find a random hacktober python issue on GitHub.""" -    def __init__(self, bot: commands.Bot): +    def __init__(self, bot: Bot):          self.bot = bot          self.cache_normal = None          self.cache_timer_normal = datetime.datetime(1, 1, 1) @@ -41,7 +41,7 @@ class HacktoberIssues(commands.Cog):          If the command is run with beginner (`.hacktoberissues beginner`):          It will also narrow it down to the "first good issue" label.          """ -        with ctx.typing(): +        async with ctx.typing():              issues = await self.get_issues(ctx, option)              if issues is None:                  return @@ -59,40 +59,39 @@ class HacktoberIssues(commands.Cog):              log.debug("using cache")              return self.cache_normal -        async with aiohttp.ClientSession() as session: +        if option == "beginner": +            url = URL + '+label:"good first issue"' +            if self.cache_beginner is not None: +                page = random.randint(1, min(1000, self.cache_beginner["total_count"]) // 100) +                url += f"&page={page}" +        else: +            url = URL +            if self.cache_normal is not None: +                page = random.randint(1, min(1000, self.cache_normal["total_count"]) // 100) +                url += f"&page={page}" + +        log.debug(f"making api request to url: {url}") +        async with self.bot.http_session.get(url, headers=REQUEST_HEADERS) as response: +            if response.status != 200: +                log.error(f"expected 200 status (got {response.status}) from the GitHub api.") +                await ctx.send(f"ERROR: expected 200 status (got {response.status}) from the GitHub api.") +                await ctx.send(await response.text()) +                return None +            data = await response.json() + +            if len(data["items"]) == 0: +                log.error(f"no issues returned from GitHub api. with url: {response.url}") +                await ctx.send(f"ERROR: no issues returned from GitHub api. with url: {response.url}") +                return None +              if option == "beginner": -                url = URL + '+label:"good first issue"' -                if self.cache_beginner is not None: -                    page = random.randint(1, min(1000, self.cache_beginner["total_count"]) // 100) -                    url += f"&page={page}" +                self.cache_beginner = data +                self.cache_timer_beginner = ctx.message.created_at              else: -                url = URL -                if self.cache_normal is not None: -                    page = random.randint(1, min(1000, self.cache_normal["total_count"]) // 100) -                    url += f"&page={page}" - -            log.debug(f"making api request to url: {url}") -            async with session.get(url, headers=REQUEST_HEADERS) as response: -                if response.status != 200: -                    log.error(f"expected 200 status (got {response.status}) from the GitHub api.") -                    await ctx.send(f"ERROR: expected 200 status (got {response.status}) from the GitHub api.") -                    await ctx.send(await response.text()) -                    return None -                data = await response.json() - -                if len(data["items"]) == 0: -                    log.error(f"no issues returned from GitHub api. with url: {response.url}") -                    await ctx.send(f"ERROR: no issues returned from GitHub api. with url: {response.url}") -                    return None - -                if option == "beginner": -                    self.cache_beginner = data -                    self.cache_timer_beginner = ctx.message.created_at -                else: -                    self.cache_normal = data -                    self.cache_timer_normal = ctx.message.created_at - -                return data +                self.cache_normal = data +                self.cache_timer_normal = ctx.message.created_at + +            return data      @staticmethod      def format_embed(issue: Dict) -> discord.Embed: @@ -111,6 +110,6 @@ class HacktoberIssues(commands.Cog):          return embed -def setup(bot: commands.Bot) -> None: -    """Hacktober issue finder Cog Load.""" +def setup(bot: Bot) -> None: +    """Load the HacktoberIssue finder."""      bot.add_cog(HacktoberIssues(bot)) diff --git a/bot/exts/halloween/hacktoberstats.py b/bot/exts/halloween/hacktoberstats.py index d9fc0e8a..9695ba2a 100644 --- a/bot/exts/halloween/hacktoberstats.py +++ b/bot/exts/halloween/hacktoberstats.py @@ -5,11 +5,11 @@ from collections import Counter  from datetime import datetime, timedelta  from typing import List, Optional, Tuple, Union -import aiohttp  import discord  from async_rediscache import RedisCache  from discord.ext import commands +from bot.bot import Bot  from bot.constants import Channels, Month, NEGATIVE_REPLIES, Tokens, WHITELISTED_CHANNELS  from bot.utils.decorators import in_month, whitelist_override @@ -39,7 +39,7 @@ class HacktoberStats(commands.Cog):      # Stores mapping of user IDs and GitHub usernames      linked_accounts = RedisCache() -    def __init__(self, bot: commands.Bot): +    def __init__(self, bot: Bot):          self.bot = bot      @in_month(Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER) @@ -83,15 +83,15 @@ class HacktoberStats(commands.Cog):          if github_username:              if await self.linked_accounts.contains(author_id):                  old_username = await self.linked_accounts.get(author_id) -                logging.info(f"{author_id} has changed their github link from '{old_username}' to '{github_username}'") +                log.info(f"{author_id} has changed their github link from '{old_username}' to '{github_username}'")                  await ctx.send(f"{author_mention}, your GitHub username has been updated to: '{github_username}'")              else: -                logging.info(f"{author_id} has added a github link to '{github_username}'") +                log.info(f"{author_id} has added a github link to '{github_username}'")                  await ctx.send(f"{author_mention}, your GitHub username has been added")              await self.linked_accounts.set(author_id, github_username)          else: -            logging.info(f"{author_id} tried to link a GitHub account but didn't provide a username") +            log.info(f"{author_id} tried to link a GitHub account but didn't provide a username")              await ctx.send(f"{author_mention}, a GitHub username is required to link your account")      @in_month(Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER) @@ -157,7 +157,7 @@ class HacktoberStats(commands.Cog):          stats_embed = discord.Embed(              title=f"{github_username}'s Hacktoberfest", -            color=discord.Color(0x9c4af7), +            color=0x9c4af7,              description=(                  f"{github_username} has made {n} valid "                  f"{self._contributionator(n)} in " @@ -188,8 +188,7 @@ class HacktoberStats(commands.Cog):          logging.info(f"Hacktoberfest PR built for GitHub user '{github_username}'")          return stats_embed -    @staticmethod -    async def get_october_prs(github_username: str) -> Optional[List[dict]]: +    async def get_october_prs(self, github_username: str) -> Optional[List[dict]]:          """          Query GitHub's API for PRs created during the month of October by github_username. @@ -212,7 +211,7 @@ class HacktoberStats(commands.Cog):          Otherwise, return empty list.          None will be returned when the GitHub user was not found.          """ -        logging.info(f"Fetching Hacktoberfest Stats for GitHub user: '{github_username}'") +        log.info(f"Fetching Hacktoberfest Stats for GitHub user: '{github_username}'")          base_url = "https://api.github.com/search/issues?q="          action_type = "pr"          is_query = "public" @@ -228,24 +227,24 @@ class HacktoberStats(commands.Cog):              f"+created:{date_range}"              f"&per_page={per_page}"          ) -        logging.debug(f"GitHub query URL generated: {query_url}") +        log.logProcesses.debug(f"GitHub query URL generated: {query_url}") -        jsonresp = await HacktoberStats._fetch_url(query_url, REQUEST_HEADERS) -        if "message" in jsonresp.keys(): +        jsonresp = await self._fetch_url(query_url, REQUEST_HEADERS) +        if "message" in jsonresp:              # One of the parameters is invalid, short circuit for now              api_message = jsonresp["errors"][0]["message"]              # Ignore logging non-existent users or users we do not have permission to see              if api_message == GITHUB_NONEXISTENT_USER_MESSAGE: -                logging.debug(f"No GitHub user found named '{github_username}'") +                log.debug(f"No GitHub user found named '{github_username}'")                  return              else: -                logging.error(f"GitHub API request for '{github_username}' failed with message: {api_message}") +                log.error(f"GitHub API request for '{github_username}' failed with message: {api_message}")              return []  # No October PRs were found due to error          if jsonresp["total_count"] == 0:              # Short circuit if there aren't any PRs -            logging.info(f"No October PRs found for GitHub user: '{github_username}'") +            log.info(f"No October PRs found for GitHub user: '{github_username}'")              return []          logging.info(f"Found {len(jsonresp['items'])} Hacktoberfest PRs for GitHub user: '{github_username}'") @@ -253,20 +252,20 @@ class HacktoberStats(commands.Cog):          oct3 = datetime(int(CURRENT_YEAR), 10, 3, 23, 59, 59, tzinfo=None)          hackto_topics = {}  # cache whether each repo has the appropriate topic (bool values)          for item in jsonresp["items"]: -            shortname = HacktoberStats._get_shortname(item["repository_url"]) +            shortname = self._get_shortname(item["repository_url"])              itemdict = {                  "repo_url": f"https://www.github.com/{shortname}",                  "repo_shortname": shortname,                  "created_at": datetime.strptime( -                    item["created_at"], r"%Y-%m-%dT%H:%M:%SZ" +                    item["created_at"], "%Y-%m-%dT%H:%M:%SZ"                  ),                  "number": item["number"]              }              # If the PR has 'invalid' or 'spam' labels, the PR must be              # either merged or approved for it to be included -            if HacktoberStats._has_label(item, ["invalid", "spam"]): -                if not await HacktoberStats._is_accepted(itemdict): +            if self._has_label(item, ["invalid", "spam"]): +                if not await self._is_accepted(itemdict):                      continue              # PRs before oct 3 no need to check for topics @@ -277,21 +276,20 @@ class HacktoberStats(commands.Cog):                  continue              # Checking PR's labels for "hacktoberfest-accepted" -            if HacktoberStats._has_label(item, "hacktoberfest-accepted"): +            if self._has_label(item, "hacktoberfest-accepted"):                  outlist.append(itemdict)                  continue              # No need to query GitHub if repo topics are fetched before already -            if shortname in hackto_topics.keys(): -                if hackto_topics[shortname]: -                    outlist.append(itemdict) -                    continue +            if hackto_topics.get(shortname): +                outlist.append(itemdict) +                continue              # Fetch topics for the PR's repo              topics_query_url = f"https://api.github.com/repos/{shortname}/topics" -            logging.debug(f"Fetching repo topics for {shortname} with url: {topics_query_url}") -            jsonresp2 = await HacktoberStats._fetch_url(topics_query_url, GITHUB_TOPICS_ACCEPT_HEADER) +            log.debug(f"Fetching repo topics for {shortname} with url: {topics_query_url}") +            jsonresp2 = await self._fetch_url(topics_query_url, GITHUB_TOPICS_ACCEPT_HEADER)              if jsonresp2.get("names") is None: -                logging.error(f"Error fetching topics for {shortname}: {jsonresp2['message']}") +                log.error(f"Error fetching topics for {shortname}: {jsonresp2['message']}")                  continue  # Assume the repo doesn't have the `hacktoberfest` topic if API  request errored              # PRs after oct 3 that doesn't have 'hacktoberfest-accepted' label @@ -301,12 +299,10 @@ class HacktoberStats(commands.Cog):                  outlist.append(itemdict)          return outlist -    @staticmethod -    async def _fetch_url(url: str, headers: dict) -> dict: +    async def _fetch_url(self, url: str, headers: dict) -> dict:          """Retrieve API response from URL.""" -        async with aiohttp.ClientSession() as session: -            async with session.get(url, headers=headers) as resp: -                jsonresp = await resp.json() +        async with self.bot.http_session.get(url, headers=headers) as resp: +            jsonresp = await resp.json()          return jsonresp      @staticmethod @@ -319,40 +315,36 @@ class HacktoberStats(commands.Cog):          """          if not pr.get("labels"):  # if PR has no labels              return False -        if (isinstance(labels, str)) and (any(label["name"].casefold() == labels for label in pr["labels"])): +        if isinstance(labels, str) and any(label["name"].casefold() == labels for label in pr["labels"]):              return True          for item in labels:              if any(label["name"].casefold() == item for label in pr["labels"]):                  return True          return False -    @staticmethod -    async def _is_accepted(pr: dict) -> bool: +    async def _is_accepted(self, pr: dict) -> bool:          """Check if a PR is merged, approved, or labelled hacktoberfest-accepted."""          # checking for merge status -        query_url = f"https://api.github.com/repos/{pr['repo_shortname']}/pulls/" -        query_url += str(pr["number"]) -        jsonresp = await HacktoberStats._fetch_url(query_url, REQUEST_HEADERS) - -        if "message" in jsonresp.keys(): -            logging.error( -                f"Error fetching PR stats for #{pr['number']} in repo {pr['repo_shortname']}:\n" -                f"{jsonresp['message']}" -            ) +        query_url = f"https://api.github.com/repos/{pr['repo_shortname']}/pulls/{pr['number']}" +        jsonresp = await self._fetch_url(query_url, REQUEST_HEADERS) + +        if message := jsonresp.get("message"): +            log.error(f"Error fetching PR stats for #{pr['number']} in repo {pr['repo_shortname']}:\n{message}")              return False -        if ("merged" in jsonresp.keys()) and jsonresp["merged"]: + +        if jsonresp.get("merged"):              return True          # checking for the label, using `jsonresp` which has the label information -        if HacktoberStats._has_label(jsonresp, "hacktoberfest-accepted"): +        if self._has_label(jsonresp, "hacktoberfest-accepted"):              return True          # checking approval          query_url += "/reviews" -        jsonresp2 = await HacktoberStats._fetch_url(query_url, REQUEST_HEADERS) +        jsonresp2 = await self._fetch_url(query_url, REQUEST_HEADERS)          if isinstance(jsonresp2, dict):              # if API request is unsuccessful it will be a dict with the error in 'message' -            logging.error( +            log.error(                  f"Error fetching PR reviews for #{pr['number']} in repo {pr['repo_shortname']}:\n"                  f"{jsonresp2['message']}"              ) @@ -363,9 +355,8 @@ class HacktoberStats(commands.Cog):          # loop through reviews and check for approval          for item in jsonresp2: -            if "status" in item.keys(): -                if item['status'] == "APPROVED": -                    return True +            if item.get('status') == "APPROVED": +                return True          return False      @staticmethod @@ -381,8 +372,7 @@ class HacktoberStats(commands.Cog):          exp = r"https?:\/\/api.github.com\/repos\/([/\-\_\.\w]+)"          return re.findall(exp, in_url)[0] -    @staticmethod -    async def _categorize_prs(prs: List[dict]) -> tuple: +    async def _categorize_prs(self, prs: List[dict]) -> tuple:          """          Categorize PRs into 'in_review' and 'accepted' and returns as a tuple. @@ -399,7 +389,7 @@ class HacktoberStats(commands.Cog):          for pr in prs:              if (pr['created_at'] + timedelta(REVIEW_DAYS)) > now:                  in_review.append(pr) -            elif (pr['created_at'] <= oct3) or await HacktoberStats._is_accepted(pr): +            elif (pr['created_at'] <= oct3) or await self._is_accepted(pr):                  accepted.append(pr)          return in_review, accepted @@ -438,14 +428,14 @@ class HacktoberStats(commands.Cog):              return "contributions"      @staticmethod -    def _author_mention_from_context(ctx: commands.Context) -> Tuple: +    def _author_mention_from_context(ctx: commands.Context) -> Tuple[str, str]:          """Return stringified Message author ID and mentionable string from commands.Context.""" -        author_id = str(ctx.message.author.id) -        author_mention = ctx.message.author.mention +        author_id = str(ctx.author.id) +        author_mention = ctx.author.mention          return author_id, author_mention -def setup(bot: commands.Bot) -> None: -    """Hacktoberstats Cog load.""" +def setup(bot: Bot) -> None: +    """Load the Hacktober Stats Cog."""      bot.add_cog(HacktoberStats(bot)) diff --git a/bot/exts/halloween/halloween_facts.py b/bot/exts/halloween/halloween_facts.py index 7eb6d56f..139e0810 100644 --- a/bot/exts/halloween/halloween_facts.py +++ b/bot/exts/halloween/halloween_facts.py @@ -8,6 +8,8 @@ from typing import Tuple  import discord  from discord.ext import commands +from bot.bot import Bot +  log = logging.getLogger(__name__)  SPOOKY_EMOJIS = [ @@ -20,16 +22,15 @@ SPOOKY_EMOJIS = [      "\N{SKULL AND CROSSBONES}",      "\N{SPIDER WEB}",  ] -PUMPKIN_ORANGE = discord.Color(0xFF7518) +PUMPKIN_ORANGE = 0xFF7518  INTERVAL = timedelta(hours=6).total_seconds()  class HalloweenFacts(commands.Cog):      """A Cog for displaying interesting facts about Halloween.""" -    def __init__(self, bot: commands.Bot): -        self.bot = bot -        with open(Path("bot/resources/halloween/halloween_facts.json"), "r", encoding="utf8") as file: +    def __init__(self): +        with Path("bot/resources/halloween/halloween_facts.json").open("r", encoding="utf8") as file:              self.halloween_facts = json.load(file)          self.facts = list(enumerate(self.halloween_facts))          random.shuffle(self.facts) @@ -53,6 +54,6 @@ class HalloweenFacts(commands.Cog):          return discord.Embed(title=title, description=fact, color=PUMPKIN_ORANGE) -def setup(bot: commands.Bot) -> None: -    """Halloween facts Cog load.""" -    bot.add_cog(HalloweenFacts(bot)) +def setup(bot: Bot) -> None: +    """Load the Halloween Facts Cog.""" +    bot.add_cog(HalloweenFacts()) diff --git a/bot/exts/halloween/halloweenify.py b/bot/exts/halloween/halloweenify.py index 596c6682..5a8f4ecc 100644 --- a/bot/exts/halloween/halloweenify.py +++ b/bot/exts/halloween/halloweenify.py @@ -6,7 +6,9 @@ from random import choice  import discord  from discord.errors import Forbidden  from discord.ext import commands -from discord.ext.commands.cooldowns import BucketType +from discord.ext.commands import BucketType + +from bot.bot import Bot  log = logging.getLogger(__name__) @@ -14,9 +16,6 @@ log = logging.getLogger(__name__)  class Halloweenify(commands.Cog):      """A cog to change a invokers nickname to a spooky one!""" -    def __init__(self, bot: commands.Bot): -        self.bot = bot -      @commands.cooldown(1, 300, BucketType.user)      @commands.command()      async def halloweenify(self, ctx: commands.Context) -> None: @@ -61,6 +60,6 @@ class Halloweenify(commands.Cog):          await ctx.send(embed=embed) -def setup(bot: commands.Bot) -> None: -    """Halloweenify Cog load.""" -    bot.add_cog(Halloweenify(bot)) +def setup(bot: Bot) -> None: +    """Load the Halloweenify Cog.""" +    bot.add_cog(Halloweenify()) diff --git a/bot/exts/halloween/monsterbio.py b/bot/exts/halloween/monsterbio.py index 016a66d1..f484305d 100644 --- a/bot/exts/halloween/monsterbio.py +++ b/bot/exts/halloween/monsterbio.py @@ -6,6 +6,7 @@ from pathlib import Path  import discord  from discord.ext import commands +from bot.bot import Bot  from bot.constants import Colours  log = logging.getLogger(__name__) @@ -17,9 +18,6 @@ with open(Path("bot/resources/halloween/monster.json"), "r", encoding="utf8") as  class MonsterBio(commands.Cog):      """A cog that generates a spooky monster biography.""" -    def __init__(self, bot: commands.Bot): -        self.bot = bot -      def generate_name(self, seeded_random: random.Random) -> str:          """Generates a name (for either monster species or monster name)."""          n_candidate_strings = seeded_random.randint(2, len(TEXT_OPTIONS["monster_type"])) @@ -50,6 +48,6 @@ class MonsterBio(commands.Cog):          await ctx.send(embed=embed) -def setup(bot: commands.Bot) -> None: -    """Monster bio Cog load.""" -    bot.add_cog(MonsterBio(bot)) +def setup(bot: Bot) -> None: +    """Load the Monster Bio Cog.""" +    bot.add_cog(MonsterBio()) diff --git a/bot/exts/halloween/monstersurvey.py b/bot/exts/halloween/monstersurvey.py index 80196825..0610503d 100644 --- a/bot/exts/halloween/monstersurvey.py +++ b/bot/exts/halloween/monstersurvey.py @@ -23,9 +23,8 @@ class MonsterSurvey(Cog):      Users may change their vote, but only their current vote will be counted.      """ -    def __init__(self, bot: Bot): +    def __init__(self):          """Initializes values for the bot to use within the voting commands.""" -        self.bot = bot          self.registry_location = os.path.join(os.getcwd(), 'bot', 'resources', 'halloween', 'monstersurvey.json')          with open(self.registry_location, 'r', encoding="utf8") as jason:              self.voter_registry = json.load(jason) @@ -201,4 +200,5 @@ class MonsterSurvey(Cog):  def setup(bot: Bot) -> None: -    """Monster survey Cog load.""" +    """Load the Monster Survey Cog.""" +    bot.add_cog(MonsterSurvey()) diff --git a/bot/exts/halloween/scarymovie.py b/bot/exts/halloween/scarymovie.py index 0807eca6..48c9f53d 100644 --- a/bot/exts/halloween/scarymovie.py +++ b/bot/exts/halloween/scarymovie.py @@ -2,24 +2,25 @@ import logging  import random  from os import environ -import aiohttp  from discord import Embed  from discord.ext import commands +from bot.bot import Bot +  log = logging.getLogger(__name__) -TMDB_API_KEY = environ.get('TMDB_API_KEY') -TMDB_TOKEN = environ.get('TMDB_TOKEN') +TMDB_API_KEY = environ.get("TMDB_API_KEY") +TMDB_TOKEN = environ.get("TMDB_TOKEN")  class ScaryMovie(commands.Cog):      """Selects a random scary movie and embeds info into Discord chat.""" -    def __init__(self, bot: commands.Bot): +    def __init__(self, bot: Bot):          self.bot = bot -    @commands.command(name='scarymovie', alias=['smovie']) +    @commands.command(name="scarymovie", alias=["smovie"])      async def random_movie(self, ctx: commands.Context) -> None:          """Randomly select a scary movie and display information about it."""          async with ctx.typing(): @@ -28,36 +29,34 @@ class ScaryMovie(commands.Cog):          await ctx.send(embed=movie_details) -    @staticmethod -    async def select_movie() -> dict: +    async def select_movie(self) -> dict:          """Selects a random movie and returns a JSON of movie details from TMDb.""" -        url = 'https://api.themoviedb.org/4/discover/movie' +        url = "https://api.themoviedb.org/4/discover/movie"          params = { -            'with_genres': '27', -            'vote_count.gte': '5' +            "with_genres": "27", +            "vote_count.gte": "5"          }          headers = { -            'Authorization': 'Bearer ' + TMDB_TOKEN, -            'Content-Type': 'application/json;charset=utf-8' +            "Authorization": "Bearer " + TMDB_TOKEN, +            "Content-Type": "application/json;charset=utf-8"          }          # Get total page count of horror movies -        async with aiohttp.ClientSession() as session: -            response = await session.get(url=url, params=params, headers=headers) -            total_pages = await response.json() -            total_pages = total_pages.get('total_pages') - -            # Get movie details from one random result on a random page -            params['page'] = random.randint(1, total_pages) -            response = await session.get(url=url, params=params, headers=headers) -            response = await response.json() -            selection_id = random.choice(response.get('results')).get('id') - -            # Get full details and credits -            selection = await session.get( -                url='https://api.themoviedb.org/3/movie/' + str(selection_id), -                params={'api_key': TMDB_API_KEY, 'append_to_response': 'credits'} -            ) +        async with self.bot.http_session.get(url=url, params=params, headers=headers) as response: +            data = await response.json() +            total_pages = data.get("total_pages") + +        # Get movie details from one random result on a random page +        params['page'] = random.randint(1, total_pages) +        async with self.bot.http_session.get(url=url, params=params, headers=headers) as response: +            data = await response.json() +            selection_id = random.choice(data.get("results")).get("id") + +        # Get full details and credits +        async with self.bot.http_session.get( +            url=f"https://api.themoviedb.org/3/movie/{selection_id}", +            params={"api_key": TMDB_API_KEY, "append_to_response": "credits"} +        ) as selection:              return await selection.json() @@ -67,8 +66,8 @@ class ScaryMovie(commands.Cog):          # Build the relevant URLs.          movie_id = movie.get("id")          poster_path = movie.get("poster_path") -        tmdb_url = f'https://www.themoviedb.org/movie/{movie_id}' if movie_id else None -        poster = f'https://image.tmdb.org/t/p/original{poster_path}' if poster_path else None +        tmdb_url = f"https://www.themoviedb.org/movie/{movie_id}" if movie_id else None +        poster = f"https://image.tmdb.org/t/p/original{poster_path}" if poster_path else None          # Get cast names          cast = [] @@ -82,10 +81,7 @@ class ScaryMovie(commands.Cog):          # Determine the spookiness rating          rating = '' -        rating_count = movie.get('vote_average', 0) - -        if rating_count: -            rating_count /= 2 +        rating_count = movie.get('vote_average', 0) / 2          for _ in range(int(rating_count)):              rating += ':skull:' @@ -100,7 +96,7 @@ class ScaryMovie(commands.Cog):          # Not all these attributes will always be present          movie_attributes = {              "Directed by": director, -            "Starring": ', '.join(cast), +            "Starring": ", ".join(cast),              "Running time": runtime,              "Release year": year,              "Spookiness rating": rating, @@ -108,9 +104,9 @@ class ScaryMovie(commands.Cog):          embed = Embed(              colour=0x01d277, -            title='**' + movie.get('title') + '**', +            title=f"**{movie.get('title')}**",              url=tmdb_url, -            description=movie.get('overview') +            description=movie.get("overview")          )          if poster: @@ -127,6 +123,6 @@ class ScaryMovie(commands.Cog):          return embed -def setup(bot: commands.Bot) -> None: -    """Scary movie Cog load.""" +def setup(bot: Bot) -> None: +    """Load the Scary Movie Cog."""      bot.add_cog(ScaryMovie(bot)) diff --git a/bot/exts/halloween/spookygif.py b/bot/exts/halloween/spookygif.py index f402437f..bfdf2128 100644 --- a/bot/exts/halloween/spookygif.py +++ b/bot/exts/halloween/spookygif.py @@ -1,9 +1,9 @@  import logging -import aiohttp  import discord  from discord.ext import commands +from bot.bot import Bot  from bot.constants import Tokens  log = logging.getLogger(__name__) @@ -12,27 +12,26 @@ log = logging.getLogger(__name__)  class SpookyGif(commands.Cog):      """A cog to fetch a random spooky gif from the web!""" -    def __init__(self, bot: commands.Bot): +    def __init__(self, bot: Bot):          self.bot = bot      @commands.command(name="spookygif", aliases=("sgif", "scarygif"))      async def spookygif(self, ctx: commands.Context) -> None:          """Fetches a random gif from the GIPHY API and responds with it."""          async with ctx.typing(): -            async with aiohttp.ClientSession() as session: -                params = {'api_key': Tokens.giphy, 'tag': 'halloween', 'rating': 'g'} -                # Make a GET request to the Giphy API to get a random halloween gif. -                async with session.get('http://api.giphy.com/v1/gifs/random', params=params) as resp: -                    data = await resp.json() -                url = data['data']['image_url'] +            params = {'api_key': Tokens.giphy, 'tag': 'halloween', 'rating': 'g'} +            # Make a GET request to the Giphy API to get a random halloween gif. +            async with self.bot.http_session.get('http://api.giphy.com/v1/gifs/random', params=params) as resp: +                data = await resp.json() +            url = data['data']['image_url'] -                embed = discord.Embed(colour=0x9b59b6) -                embed.title = "A spooooky gif!" -                embed.set_image(url=url) +            embed = discord.Embed(colour=0x9b59b6) +            embed.title = "A spooooky gif!" +            embed.set_image(url=url)          await ctx.send(embed=embed) -def setup(bot: commands.Bot) -> None: +def setup(bot: Bot) -> None:      """Spooky GIF Cog load."""      bot.add_cog(SpookyGif(bot)) diff --git a/bot/exts/halloween/spookynamerate.py b/bot/exts/halloween/spookynamerate.py index e2950343..9191f5f6 100644 --- a/bot/exts/halloween/spookynamerate.py +++ b/bot/exts/halloween/spookynamerate.py @@ -12,8 +12,9 @@ from async_rediscache import RedisCache  from discord import Embed, Reaction, TextChannel, User  from discord.colour import Colour  from discord.ext import tasks -from discord.ext.commands import Bot, Cog, Context, group +from discord.ext.commands import Cog, Context, group +from bot.bot import Bot  from bot.constants import Channels, Client, Colours, Month  from bot.utils.decorators import InMonthCheckFailure @@ -34,7 +35,7 @@ ADDED_MESSAGES = [  ]  PING = "<@{id}>" -EMOJI_MESSAGE = "\n".join([f"- {emoji} {val}" for emoji, val in EMOJIS_VAL.items()]) +EMOJI_MESSAGE = "\n".join(f"- {emoji} {val}" for emoji, val in EMOJIS_VAL.items())  HELP_MESSAGE_DICT = {      "title": "Spooky Name Rate",      "description": f"Help for the `{Client.prefix}spookynamerate` command", @@ -137,14 +138,12 @@ class SpookyNameRate(Cog):      async def add_name(self, ctx: Context, *, name: str) -> None:          """Use this command to add/register your spookified name."""          if self.poll: -            logger.info(f"{ctx.message.author} tried to add a name, but the poll had already started.") +            logger.info(f"{ctx.author} tried to add a name, but the poll had already started.")              await ctx.send("Sorry, the poll has started! You can try and participate in the next round though!")              return -        message = ctx.message -          for data in (json.loads(user_data) for _, user_data in await self.messages.items()): -            if data["author"] == message.author.id: +            if data["author"] == ctx.author.id:                  await ctx.send(                      "But you have already added an entry! Type "                      f"`{self.bot.command_prefix}spookynamerate " @@ -156,14 +155,14 @@ class SpookyNameRate(Cog):                  await ctx.send("TOO LATE. Someone has already added this name.")                  return -        msg = await (await self.get_channel()).send(f"{message.author.mention} added the name {name!r}!") +        msg = await (await self.get_channel()).send(f"{ctx.author.mention} added the name {name!r}!")          await self.messages.set(              msg.id,              json.dumps(                  {                      "name": name, -                    "author": message.author.id, +                    "author": ctx.author.id,                      "score": 0,                  }              ), @@ -172,7 +171,7 @@ class SpookyNameRate(Cog):          for emoji in EMOJIS_VAL:              await msg.add_reaction(emoji) -        logger.info(f"{message.author} added the name {name!r}") +        logger.info(f"{ctx.author} added the name {name!r}")      @spooky_name_rate.command(name="delete")      async def delete_name(self, ctx: Context) -> None: @@ -185,7 +184,7 @@ class SpookyNameRate(Cog):              if ctx.author.id == data["author"]:                  await self.messages.delete(message_id) -                await ctx.send(f'Name deleted successfully ({data["name"]!r})!') +                await ctx.send(f"Name deleted successfully ({data['name']!r})!")                  return          await ctx.send( @@ -397,5 +396,5 @@ class SpookyNameRate(Cog):  def setup(bot: Bot) -> None: -    """Loads the SpookyNameRate Cog.""" +    """Load the SpookyNameRate Cog."""      bot.add_cog(SpookyNameRate(bot)) diff --git a/bot/exts/halloween/spookyrating.py b/bot/exts/halloween/spookyrating.py index 6f069f8c..dc398e2e 100644 --- a/bot/exts/halloween/spookyrating.py +++ b/bot/exts/halloween/spookyrating.py @@ -7,20 +7,20 @@ from pathlib import Path  import discord  from discord.ext import commands +from bot.bot import Bot  from bot.constants import Colours  log = logging.getLogger(__name__)  with Path("bot/resources/halloween/spooky_rating.json").open(encoding="utf8") as file: -    SPOOKY_DATA = json.load(file) -    SPOOKY_DATA = sorted((int(key), value) for key, value in SPOOKY_DATA.items()) +    data = json.load(file) +    SPOOKY_DATA = sorted((int(key), value) for key, value in data.items())  class SpookyRating(commands.Cog):      """A cog for calculating one's spooky rating.""" -    def __init__(self, bot: commands.Bot): -        self.bot = bot +    def __init__(self):          self.local_random = random.Random()      @commands.command() @@ -61,6 +61,6 @@ class SpookyRating(commands.Cog):          await ctx.send(embed=embed) -def setup(bot: commands.Bot) -> None: -    """Spooky Rating Cog load.""" -    bot.add_cog(SpookyRating(bot)) +def setup(bot: Bot) -> None: +    """Load the Spooky Rating Cog.""" +    bot.add_cog(SpookyRating()) diff --git a/bot/exts/halloween/spookyreact.py b/bot/exts/halloween/spookyreact.py index b335df75..dabc3c1f 100644 --- a/bot/exts/halloween/spookyreact.py +++ b/bot/exts/halloween/spookyreact.py @@ -2,8 +2,9 @@ import logging  import re  import discord -from discord.ext.commands import Bot, Cog +from discord.ext.commands import Cog +from bot.bot import Bot  from bot.constants import Month  from bot.utils.decorators import in_month @@ -28,20 +29,20 @@ class SpookyReact(Cog):      @in_month(Month.OCTOBER)      @Cog.listener() -    async def on_message(self, ctx: discord.Message) -> None: +    async def on_message(self, message: discord.Message) -> None:          """Triggered when the bot sees a message in October.""" -        for trigger in SPOOKY_TRIGGERS.keys(): -            trigger_test = re.search(SPOOKY_TRIGGERS[trigger][0], ctx.content.lower()) +        for name, trigger in SPOOKY_TRIGGERS.items(): +            trigger_test = re.search(trigger[0], message.content.lower())              if trigger_test:                  # Check message for bot replies and/or command invocations                  # Short circuit if they're found, logging is handled in _short_circuit_check -                if await self._short_circuit_check(ctx): +                if await self._short_circuit_check(message):                      return                  else: -                    await ctx.add_reaction(SPOOKY_TRIGGERS[trigger][1]) -                    logging.info(f"Added '{trigger}' reaction to message ID: {ctx.id}") +                    await message.add_reaction(trigger[1]) +                    log.info(f"Added {name!r} reaction to message ID: {message.id}") -    async def _short_circuit_check(self, ctx: discord.Message) -> bool: +    async def _short_circuit_check(self, message: discord.Message) -> bool:          """          Short-circuit helper check. @@ -50,20 +51,20 @@ class SpookyReact(Cog):            * prefix is not None          """          # Check for self reaction -        if ctx.author == self.bot.user: -            logging.debug(f"Ignoring reactions on self message. Message ID: {ctx.id}") +        if message.author == self.bot.user: +            log.debug(f"Ignoring reactions on self message. Message ID: {message.id}")              return True          # Check for command invocation          # Because on_message doesn't give a full Context object, generate one first -        tmp_ctx = await self.bot.get_context(ctx) -        if tmp_ctx.prefix: -            logging.debug(f"Ignoring reactions on command invocation. Message ID: {ctx.id}") +        ctx = await self.bot.get_context(message) +        if ctx.prefix: +            log.debug(f"Ignoring reactions on command invocation. Message ID: {message.id}")              return True          return False  def setup(bot: Bot) -> None: -    """Spooky reaction Cog load.""" +    """Load the Spooky Reaction Cog."""      bot.add_cog(SpookyReact(bot)) diff --git a/bot/exts/halloween/timeleft.py b/bot/exts/halloween/timeleft.py index 47adb09b..f4ab9284 100644 --- a/bot/exts/halloween/timeleft.py +++ b/bot/exts/halloween/timeleft.py @@ -4,13 +4,15 @@ from typing import Tuple  from discord.ext import commands +from bot.bot import Bot +  log = logging.getLogger(__name__)  class TimeLeft(commands.Cog):      """A Cog that tells you how long left until Hacktober is over!""" -    def __init__(self, bot: commands.Bot): +    def __init__(self, bot: Bot):          self.bot = bot      def in_hacktober(self) -> bool: @@ -64,6 +66,6 @@ class TimeLeft(commands.Cog):              ) -def setup(bot: commands.Bot) -> None: -    """Cog load.""" +def setup(bot: Bot) -> None: +    """Load the Time Left Cog."""      bot.add_cog(TimeLeft(bot)) diff --git a/bot/exts/pride/drag_queen_name.py b/bot/exts/pride/drag_queen_name.py index fca9750f..9839f089 100644 --- a/bot/exts/pride/drag_queen_name.py +++ b/bot/exts/pride/drag_queen_name.py @@ -5,14 +5,15 @@ from pathlib import Path  from discord.ext import commands +from bot.bot import Bot +  log = logging.getLogger(__name__)  class DragNames(commands.Cog):      """Gives a random drag queen name!""" -    def __init__(self, bot: commands.Bot): -        self.bot = bot +    def __init__(self):          self.names = self.load_names()      @staticmethod @@ -27,6 +28,6 @@ class DragNames(commands.Cog):          await ctx.send(random.choice(self.names)) -def setup(bot: commands.Bot) -> None: -    """Cog loader for drag queen name generator.""" -    bot.add_cog(DragNames(bot)) +def setup(bot: Bot) -> None: +    """Load the Drag Queen Cog.""" +    bot.add_cog(DragNames()) diff --git a/bot/exts/pride/pride_anthem.py b/bot/exts/pride/pride_anthem.py index 33cb2a9d..a7f8d7ef 100644 --- a/bot/exts/pride/pride_anthem.py +++ b/bot/exts/pride/pride_anthem.py @@ -2,20 +2,22 @@ import json  import logging  import random  from pathlib import Path +from typing import Optional  from discord.ext import commands +from bot.bot import Bot +  log = logging.getLogger(__name__)  class PrideAnthem(commands.Cog):      """Embed a random youtube video for a gay anthem!""" -    def __init__(self, bot: commands.Bot): -        self.bot = bot +    def __init__(self):          self.anthems = self.load_vids() -    def get_video(self, genre: str = None) -> dict: +    def get_video(self, genre: Optional[str] = None) -> dict:          """          Picks a random anthem from the list. @@ -52,6 +54,6 @@ class PrideAnthem(commands.Cog):              await ctx.send("I couldn't find a video, sorry!") -def setup(bot: commands.Bot) -> None: -    """Cog loader for pride anthem.""" -    bot.add_cog(PrideAnthem(bot)) +def setup(bot: Bot) -> None: +    """Load the Pride Anthem Cog.""" +    bot.add_cog(PrideAnthem()) diff --git a/bot/exts/pride/pride_facts.py b/bot/exts/pride/pride_facts.py index 5bd5d0ce..b2daaab7 100644 --- a/bot/exts/pride/pride_facts.py +++ b/bot/exts/pride/pride_facts.py @@ -15,8 +15,6 @@ from bot.utils.decorators import seasonal_task  log = logging.getLogger(__name__) -Sendable = Union[commands.Context, discord.TextChannel] -  class PrideFacts(commands.Cog):      """Provides a new fact every day during the Pride season!""" @@ -44,7 +42,7 @@ class PrideFacts(commands.Cog):      async def send_random_fact(self, ctx: commands.Context) -> None:          """Provides a fact from any previous day, or today."""          now = datetime.utcnow() -        previous_years_facts = (self.facts[x] for x in self.facts.keys() if int(x) < now.year) +        previous_years_facts = (y for x, y in self.facts.items() if int(x) < now.year)          current_year_facts = self.facts.get(str(now.year), [])[:now.day]          previous_facts = current_year_facts + [x for y in previous_years_facts for x in y]          try: @@ -52,7 +50,7 @@ class PrideFacts(commands.Cog):          except IndexError:              await ctx.send("No facts available") -    async def send_select_fact(self, target: Sendable, _date: Union[str, datetime]) -> None: +    async def send_select_fact(self, target: discord.abc.Messageable, _date: Union[str, datetime]) -> None:          """Provides the fact for the specified day, if the day is today, or is in the past."""          now = datetime.utcnow()          if isinstance(_date, str): @@ -76,7 +74,7 @@ class PrideFacts(commands.Cog):              await target.send("The fact for the selected day is not yet available.")      @commands.command(name="pridefact", aliases=["pridefacts"]) -    async def pridefact(self, ctx: commands.Context) -> None: +    async def pridefact(self, ctx: commands.Context, option: str = None) -> None:          """          Sends a message with a pride fact of the day. @@ -85,15 +83,15 @@ class PrideFacts(commands.Cog):          If a date is given as an argument, and the date is in the past, the fact from that day          will be provided.          """ -        message_body = ctx.message.content[len(ctx.invoked_with) + 2:] -        if message_body == "": +        if not option:              await self.send_select_fact(ctx, datetime.utcnow()) -        elif message_body.lower().startswith("rand"): +        elif option.lower().startswith("rand"):              await self.send_random_fact(ctx)          else: -            await self.send_select_fact(ctx, message_body) +            await self.send_select_fact(ctx, option) -    def make_embed(self, fact: str) -> discord.Embed: +    @staticmethod +    def make_embed(fact: str) -> discord.Embed:          """Makes a nice embed for the fact to be sent."""          return discord.Embed(              colour=Colours.pink, diff --git a/bot/exts/valentines/myvalenstate.py b/bot/exts/valentines/myvalenstate.py index 01801847..041af7af 100644 --- a/bot/exts/valentines/myvalenstate.py +++ b/bot/exts/valentines/myvalenstate.py @@ -78,7 +78,7 @@ class MyValenstate(commands.Cog):          )          embed.add_field(name=embed_title, value=embed_text)          embed.set_image(url=STATES[valenstate]["flag"]) -        await ctx.channel.send(embed=embed) +        await ctx.send(embed=embed)  def setup(bot: commands.Bot) -> None: diff --git a/bot/exts/valentines/whoisvalentine.py b/bot/exts/valentines/whoisvalentine.py index 0ff9186c..ab6b1ca1 100644 --- a/bot/exts/valentines/whoisvalentine.py +++ b/bot/exts/valentines/whoisvalentine.py @@ -33,7 +33,7 @@ class ValentineFacts(commands.Cog):                  'facial_reconstruction.jpg/1024px-Saint_Valentine_-_facial_reconstruction.jpg'          ) -        await ctx.channel.send(embed=embed) +        await ctx.send(embed=embed)      @commands.command()      async def valentine_fact(self, ctx: commands.Context) -> None: @@ -44,7 +44,7 @@ class ValentineFacts(commands.Cog):              color=Colours.pink          ) -        await ctx.channel.send(embed=embed) +        await ctx.send(embed=embed)  def setup(bot: commands.Bot) -> None: | 
