diff options
Diffstat (limited to 'bot/exts/halloween')
| -rw-r--r-- | bot/exts/halloween/8ball.py | 19 | ||||
| -rw-r--r-- | bot/exts/halloween/candy_collection.py | 51 | ||||
| -rw-r--r-- | bot/exts/halloween/hacktober-issue-finder.py | 77 | ||||
| -rw-r--r-- | bot/exts/halloween/hacktoberstats.py | 115 | ||||
| -rw-r--r-- | bot/exts/halloween/halloween_facts.py | 16 | ||||
| -rw-r--r-- | bot/exts/halloween/halloweenify.py | 21 | ||||
| -rw-r--r-- | bot/exts/halloween/monsterbio.py | 12 | ||||
| -rw-r--r-- | bot/exts/halloween/monstersurvey.py | 98 | ||||
| -rw-r--r-- | bot/exts/halloween/scarymovie.py | 92 | ||||
| -rw-r--r-- | bot/exts/halloween/spookygif.py | 23 | ||||
| -rw-r--r-- | bot/exts/halloween/spookynamerate.py | 23 | ||||
| -rw-r--r-- | bot/exts/halloween/spookyrating.py | 24 | ||||
| -rw-r--r-- | bot/exts/halloween/spookyreact.py | 43 | ||||
| -rw-r--r-- | bot/exts/halloween/timeleft.py | 11 |
14 files changed, 304 insertions, 321 deletions
diff --git a/bot/exts/halloween/8ball.py b/bot/exts/halloween/8ball.py index 1df48fbf..d6c5a299 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',)) + @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..14efa1fb 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 @@ -21,11 +22,11 @@ EMOJIS = dict( CANDY="\N{CANDY}", SKULL="\N{SKULL}", MEDALS=( - '\N{FIRST PLACE MEDAL}', - '\N{SECOND PLACE MEDAL}', - '\N{THIRD PLACE MEDAL}', - '\N{SPORTS MEDAL}', - '\N{SPORTS MEDAL}', + "\N{FIRST PLACE MEDAL}", + "\N{SECOND PLACE MEDAL}", + "\N{THIRD PLACE MEDAL}", + "\N{SPORTS MEDAL}", + "\N{SPORTS MEDAL}", ), ) @@ -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): @@ -105,7 +106,7 @@ class CandyCollection(commands.Cog): await self.candy_records.decrement(user.id, lost) if lost == prev_record: - await CandyCollection.send_spook_msg(user, message.channel, 'all of your') + await CandyCollection.send_spook_msg(user, message.channel, "all of your") else: await CandyCollection.send_spook_msg(user, message.channel, lost) else: @@ -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 @@ -170,10 +173,10 @@ class CandyCollection(commands.Cog): ) top_five = top_sorted[:5] - return '\n'.join( + 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( @@ -182,7 +185,7 @@ class CandyCollection(commands.Cog): inline=False ) e.add_field( - name='\u200b', + name="\u200b", value="Candies will randomly appear on messages sent. " "\nHit the candy when it appears as fast as possible to get the candy! " "\nBut beware the ghosts...", @@ -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..20a06770 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,41 @@ 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}) by the GitHub api.") + await ctx.send( + f"ERROR: expected 200 status (got {response.status}) by the GitHub api.\n" + f"{await response.text()}" + ) + return None + data = await response.json() + + if len(data["items"]) == 0: + log.error(f"no issues returned by GitHub API, with url: {response.url}") + await ctx.send(f"ERROR: no issues returned by 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: @@ -103,7 +104,7 @@ class HacktoberIssues(commands.Cog): labels = [label["name"] for label in issue["labels"]] embed = discord.Embed(title=title) - embed.description = body[:500] + '...' if len(body) > 500 else body + embed.description = body[:500] + "..." if len(body) > 500 else body embed.add_field(name="labels", value="\n".join(labels)) embed.url = issue_url embed.set_footer(text=issue_url) @@ -111,6 +112,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..b74e680b 100644 --- a/bot/exts/halloween/hacktoberstats.py +++ b/bot/exts/halloween/hacktoberstats.py @@ -5,12 +5,12 @@ 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.constants import Channels, Month, NEGATIVE_REPLIES, Tokens, WHITELISTED_CHANNELS +from bot.bot import Bot +from bot.constants import Channels, Colours, Month, NEGATIVE_REPLIES, Tokens, WHITELISTED_CHANNELS from bot.utils.decorators import in_month, whitelist_override log = logging.getLogger(__name__) @@ -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) @@ -138,7 +138,7 @@ class HacktoberStats(commands.Cog): if prs: stats_embed = await self.build_embed(github_username, prs) - await ctx.send('Here are some stats!', embed=stats_embed) + await ctx.send("Here are some stats!", embed=stats_embed) else: await ctx.send(f"No valid Hacktoberfest PRs found for '{github_username}'") @@ -157,7 +157,7 @@ class HacktoberStats(commands.Cog): stats_embed = discord.Embed( title=f"{github_username}'s Hacktoberfest", - color=discord.Color(0x9c4af7), + color=Colours.purple, 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.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,13 +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() - return jsonresp + async with self.bot.http_session.get(url, headers=headers) as resp: + return await resp.json() @staticmethod def _has_label(pr: dict, labels: Union[List[str], str]) -> bool: @@ -319,40 +314,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 +354,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 +371,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. @@ -397,9 +386,9 @@ class HacktoberStats(commands.Cog): in_review = [] accepted = [] for pr in prs: - if (pr['created_at'] + timedelta(REVIEW_DAYS)) > now: + 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 +427,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..3a89b5aa 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,19 +22,17 @@ 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) def random_fact(self) -> Tuple[int, str]: """Return a random fact from the loaded facts.""" @@ -53,6 +53,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..df55b55d 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: @@ -27,16 +26,16 @@ class Halloweenify(commands.Cog): # Choose a random character from our list we loaded above and set apart the nickname and image url. character = choice(data["characters"]) - nickname = ''.join([nickname for nickname in character]) - image = ''.join([character[nickname] for nickname in character]) + nickname = "".join([nickname for nickname in character]) + image = "".join([character[nickname] for nickname in character]) # Build up a Embed embed = discord.Embed() embed.colour = discord.Colour.dark_orange() embed.title = "Not spooky enough?" embed.description = ( - f"**{ctx.author.display_name}** wasn\'t spooky enough for you? That\'s understandable, " - f"{ctx.author.display_name} isn\'t scary at all! " + f"**{ctx.author.display_name}** wasn't spooky enough for you? That's understandable, " + f"{ctx.author.display_name} isn't scary at all! " "Let me think of something better. Hmm... I got it!\n\n " ) embed.set_image(url=image) @@ -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..dbafa43f 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"])) @@ -39,7 +37,7 @@ class MonsterBio(commands.Cog): continue options = seeded_random.sample(TEXT_OPTIONS[key], value) - words[key] = ' '.join(options) + words[key] = " ".join(options) embed = discord.Embed( title=f"{name}'s Biography", @@ -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..231454ea 100644 --- a/bot/exts/halloween/monstersurvey.py +++ b/bot/exts/halloween/monstersurvey.py @@ -1,6 +1,6 @@ import json import logging -import os +import pathlib from discord import Embed from discord.ext import commands @@ -9,8 +9,8 @@ from discord.ext.commands import Bot, Cog, Context log = logging.getLogger(__name__) EMOJIS = { - 'SUCCESS': u'\u2705', - 'ERROR': u'\u274C' + "SUCCESS": u"\u2705", + "ERROR": u"\u274C" } @@ -23,18 +23,17 @@ 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) + self.registry_path = pathlib.Path("bot", "resources", "halloween", "monstersurvey.json") + with self.registry_path.open(encoding="utf8") as data: + self.voter_registry = json.load(data) def json_write(self) -> None: """Write voting results to a local JSON file.""" log.info("Saved Monster Survey Results") - with open(self.registry_location, 'w', encoding="utf8") as jason: - json.dump(self.voter_registry, jason, indent=2) + with self.registry_path.open("w", encoding="utf8") as data: + json.dump(self.voter_registry, data, indent=2) def cast_vote(self, id: int, monster: str) -> None: """ @@ -43,54 +42,54 @@ class MonsterSurvey(Cog): If the user has already voted, their existing vote is removed. """ vr = self.voter_registry - for m in vr.keys(): - if id not in vr[m]['votes'] and m == monster: - vr[m]['votes'].append(id) + for m in vr: + if id not in vr[m]["votes"] and m == monster: + vr[m]["votes"].append(id) else: - if id in vr[m]['votes'] and m != monster: - vr[m]['votes'].remove(id) + if id in vr[m]["votes"] and m != monster: + vr[m]["votes"].remove(id) def get_name_by_leaderboard_index(self, n: int) -> str: """Return the monster at the specified leaderboard index.""" n = n - 1 vr = self.voter_registry - top = sorted(vr, key=lambda k: len(vr[k]['votes']), reverse=True) + top = sorted(vr, key=lambda k: len(vr[k]["votes"]), reverse=True) name = top[n] if n >= 0 else None return name @commands.group( - name='monster', - aliases=('mon',) + name="monster", + aliases=("mon",) ) async def monster_group(self, ctx: Context) -> None: """The base voting command. If nothing is called, then it will return an embed.""" if ctx.invoked_subcommand is None: async with ctx.typing(): default_embed = Embed( - title='Monster Voting', + title="Monster Voting", color=0xFF6800, - description='Vote for your favorite monster!' + description="Vote for your favorite monster!" ) default_embed.add_field( - name='.monster show monster_name(optional)', - value='Show a specific monster. If none is listed, it will give you an error with valid choices.', + name=".monster show monster_name(optional)", + value="Show a specific monster. If none is listed, it will give you an error with valid choices.", inline=False) default_embed.add_field( - name='.monster vote monster_name', - value='Vote for a specific monster. You get one vote, but can change it at any time.', + name=".monster vote monster_name", + value="Vote for a specific monster. You get one vote, but can change it at any time.", inline=False ) default_embed.add_field( - name='.monster leaderboard', - value='Which monster has the most votes? This command will tell you.', + name=".monster leaderboard", + value="Which monster has the most votes? This command will tell you.", inline=False ) - default_embed.set_footer(text=f"Monsters choices are: {', '.join(self.voter_registry.keys())}") + default_embed.set_footer(text=f"Monsters choices are: {', '.join(self.voter_registry)}") await ctx.send(embed=default_embed) @monster_group.command( - name='vote' + name="vote" ) async def monster_vote(self, ctx: Context, name: str = None) -> None: """ @@ -111,37 +110,37 @@ class MonsterSurvey(Cog): name = name.lower() vote_embed = Embed( - name='Monster Voting', + name="Monster Voting", color=0xFF6800 ) m = self.voter_registry.get(name) if m is None: - vote_embed.description = f'You cannot vote for {name} because it\'s not in the running.' + vote_embed.description = f"You cannot vote for {name} because it's not in the running." vote_embed.add_field( - name='Use `.monster show {monster_name}` for more information on a specific monster', - value='or use `.monster vote {monster}` to cast your vote for said monster.', + name="Use `.monster show {monster_name}` for more information on a specific monster", + value="or use `.monster vote {monster}` to cast your vote for said monster.", inline=False ) vote_embed.add_field( - name='You may vote for or show the following monsters:', - value=f"{', '.join(self.voter_registry.keys())}" + name="You may vote for or show the following monsters:", + value=", ".join(self.voter_registry.keys()) ) else: self.cast_vote(ctx.author.id, name) vote_embed.add_field( - name='Vote successful!', - value=f'You have successfully voted for {m["full_name"]}!', + name="Vote successful!", + value=f"You have successfully voted for {m['full_name']}!", inline=False ) - vote_embed.set_thumbnail(url=m['image']) + vote_embed.set_thumbnail(url=m["image"]) vote_embed.set_footer(text="Please note that any previous votes have been removed.") self.json_write() await ctx.send(embed=vote_embed) @monster_group.command( - name='show' + name="show" ) async def monster_show(self, ctx: Context, name: str = None) -> None: """Shows the named monster. If one is not named, it sends the default voting embed instead.""" @@ -159,31 +158,31 @@ class MonsterSurvey(Cog): m = self.voter_registry.get(name) if not m: - await ctx.send('That monster does not exist.') + await ctx.send("That monster does not exist.") await ctx.invoke(self.monster_vote) return - embed = Embed(title=m['full_name'], color=0xFF6800) - embed.add_field(name='Summary', value=m['summary']) - embed.set_image(url=m['image']) - embed.set_footer(text=f'To vote for this monster, type .monster vote {name}') + embed = Embed(title=m["full_name"], color=0xFF6800) + embed.add_field(name="Summary", value=m["summary"]) + embed.set_image(url=m["image"]) + embed.set_footer(text=f"To vote for this monster, type .monster vote {name}") await ctx.send(embed=embed) @monster_group.command( - name='leaderboard', - aliases=('lb',) + name="leaderboard", + aliases=("lb",) ) async def monster_leaderboard(self, ctx: Context) -> None: """Shows the current standings.""" async with ctx.typing(): vr = self.voter_registry - top = sorted(vr, key=lambda k: len(vr[k]['votes']), reverse=True) - total_votes = sum(len(m['votes']) for m in self.voter_registry.values()) + top = sorted(vr, key=lambda k: len(vr[k]["votes"]), reverse=True) + total_votes = sum(len(m["votes"]) for m in self.voter_registry.values()) embed = Embed(title="Monster Survey Leader Board", color=0xFF6800) for rank, m in enumerate(top): - votes = len(vr[m]['votes']) + votes = len(vr[m]["votes"]) percentage = ((votes / total_votes) * 100) if total_votes > 0 else 0 embed.add_field(name=f"{rank+1}. {vr[m]['full_name']}", value=( @@ -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..f4cf41db 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,40 +66,37 @@ 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 = [] - for actor in movie.get('credits', {}).get('cast', [])[:3]: - cast.append(actor.get('name')) + for actor in movie.get("credits", {}).get("cast", [])[:3]: + cast.append(actor.get("name")) # Get director name - director = movie.get('credits', {}).get('crew', []) + director = movie.get("credits", {}).get("crew", []) if director: - director = director[0].get('name') + director = director[0].get("name") # Determine the spookiness rating - rating = '' - rating_count = movie.get('vote_average', 0) - - if rating_count: - rating_count /= 2 + rating = "" + rating_count = movie.get("vote_average", 0) / 2 for _ in range(int(rating_count)): - rating += ':skull:' + rating += ":skull:" if (rating_count % 1) >= .5: - rating += ':bat:' + rating += ":bat:" # Try to get year of release and runtime - year = movie.get('release_date', [])[:4] - runtime = movie.get('runtime') + year = movie.get("release_date", [])[:4] + runtime = movie.get("runtime") runtime = f"{runtime} minutes" if runtime else None # 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..ffb91b1b 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..87172922 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", @@ -80,7 +81,7 @@ class SpookyNameRate(Cog): # The data cache stores small information such as the current name that is going on and whether it is the first time # the bot is running data = RedisCache() - debug = getenv('SPOOKYNAMERATE_DEBUG', False) # Enable if you do not want to limit the commands to October or if + debug = getenv("SPOOKYNAMERATE_DEBUG", False) # Enable if you do not want to limit the commands to October or if # you do not want to wait till 12 UTC. Note: if debug is enabled and you run `.cogs reload spookynamerate`, it # will automatically start the scoring and announcing the result (without waiting for 12, so do not expect it to.). # Also, it won't wait for the two hours (when the poll closes). @@ -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..6c79fbed 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() @@ -46,21 +46,21 @@ class SpookyRating(commands.Cog): _, data = SPOOKY_DATA[index] embed = discord.Embed( - title=data['title'], - description=f'{who} scored {spooky_percent}%!', + title=data["title"], + description=f"{who} scored {spooky_percent}%!", color=Colours.orange ) embed.add_field( - name='A whisper from Satan', - value=data['text'] + name="A whisper from Satan", + value=data["text"] ) embed.set_thumbnail( - url=data['image'] + url=data["image"] ) 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..25e783f4 100644 --- a/bot/exts/halloween/spookyreact.py +++ b/bot/exts/halloween/spookyreact.py @@ -2,21 +2,22 @@ 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 log = logging.getLogger(__name__) SPOOKY_TRIGGERS = { - 'spooky': (r"\bspo{2,}ky\b", "\U0001F47B"), - 'skeleton': (r"\bskeleton\b", "\U0001F480"), - 'doot': (r"\bdo{2,}t\b", "\U0001F480"), - 'pumpkin': (r"\bpumpkin\b", "\U0001F383"), - 'halloween': (r"\bhalloween\b", "\U0001F383"), - 'jack-o-lantern': (r"\bjack-o-lantern\b", "\U0001F383"), - 'danger': (r"\bdanger\b", "\U00002620") + "spooky": (r"\bspo{2,}ky\b", "\U0001F47B"), + "skeleton": (r"\bskeleton\b", "\U0001F480"), + "doot": (r"\bdo{2,}t\b", "\U0001F480"), + "pumpkin": (r"\bpumpkin\b", "\U0001F383"), + "halloween": (r"\bhalloween\b", "\U0001F383"), + "jack-o-lantern": (r"\bjack-o-lantern\b", "\U0001F383"), + "danger": (r"\bdanger\b", "\U00002620") } @@ -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..e80025dc 100644 --- a/bot/exts/halloween/timeleft.py +++ b/bot/exts/halloween/timeleft.py @@ -4,15 +4,14 @@ 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): - self.bot = bot - def in_hacktober(self) -> bool: """Return True if the current time is within Hacktoberfest.""" _, end, start = self.load_date() @@ -64,6 +63,6 @@ class TimeLeft(commands.Cog): ) -def setup(bot: commands.Bot) -> None: - """Cog load.""" - bot.add_cog(TimeLeft(bot)) +def setup(bot: Bot) -> None: + """Load the Time Left Cog.""" + bot.add_cog(TimeLeft()) |