diff options
43 files changed, 68 insertions, 328 deletions
diff --git a/bot/__init__.py b/bot/__init__.py index 7c564178..861a27fe 100644 --- a/bot/__init__.py +++ b/bot/__init__.py @@ -20,7 +20,6 @@ def monkeypatch_trace(self, msg, *args, **kwargs): To pass exception information, use the keyword argument exc_info with a true value, e.g. logger.trace("Houston, we have an %s", "interesting problem", exc_info=1) """ - if self.isEnabledFor(logging.TRACE): self._log(logging.TRACE, msg, args, **kwargs) @@ -25,7 +25,6 @@ class SeasonalBot(commands.Bot): def load_extensions(self, exts: List[str]): """Unload all current extensions, then load the given extensions.""" - # Unload all cogs extensions = list(self.extensions.keys()) for extension in extensions: @@ -43,7 +42,6 @@ class SeasonalBot(commands.Bot): async def send_log(self, title: str, details: str = None, *, icon: str = None): """Send an embed message to the devlog channel.""" - devlog = self.get_channel(constants.Channels.devlog) if not devlog: @@ -60,7 +58,6 @@ class SeasonalBot(commands.Bot): async def on_command_error(self, context, exception): """Check command errors for UserInputError and reset the cooldown if thrown.""" - if isinstance(exception, commands.UserInputError): context.command.reset_cooldown(context) else: diff --git a/bot/decorators.py b/bot/decorators.py index 15f7fed2..dfe80e5c 100644 --- a/bot/decorators.py +++ b/bot/decorators.py @@ -15,7 +15,6 @@ log = logging.getLogger(__name__) def with_role(*role_ids: int): """Check to see whether the invoking user has any of the roles specified in role_ids.""" - async def predicate(ctx: Context): if not ctx.guild: # Return False in a DM log.debug(f"{ctx.author} tried to use the '{ctx.command.name}'command from a DM. " @@ -35,7 +34,6 @@ def with_role(*role_ids: int): def without_role(*role_ids: int): """Check whether the invoking user does not have all of the roles specified in role_ids.""" - async def predicate(ctx: Context): if not ctx.guild: # Return False in a DM log.debug(f"{ctx.author} tried to use the '{ctx.command.name}' command from a DM. " @@ -52,7 +50,6 @@ def without_role(*role_ids: int): def in_channel(channel_id): """Check that the command invocation is in the channel specified by channel_id.""" - async def predicate(ctx: Context): check = ctx.channel.id == channel_id log.debug(f"{ctx.author} tried to call the '{ctx.command.name}' command. " @@ -69,7 +66,6 @@ def locked(): This decorator has to go before (below) the `command` decorator. """ - def wrap(func): func.__locks = WeakValueDictionary() diff --git a/bot/pagination.py b/bot/pagination.py index 1091878a..e6cea41f 100644 --- a/bot/pagination.py +++ b/bot/pagination.py @@ -43,7 +43,6 @@ class LinePaginator(Paginator): Allows for configuration of the maximum number of lines per page. """ - self.prefix = prefix self.suffix = suffix self.max_size = max_size - len(suffix) @@ -74,7 +73,6 @@ class LinePaginator(Paginator): RuntimeError The line was too big for the current `max_size`. """ - if len(line) > self.max_size - len(self.prefix) - 2: raise RuntimeError('Line exceeds maximum page size %s' % (self.max_size - len(self.prefix) - 2)) @@ -130,10 +128,8 @@ class LinePaginator(Paginator): :param timeout: The amount of time in seconds to disable pagination of no reaction is added :param footer_text: Text to prefix the page number in the footer with """ - def event_check(reaction_: Reaction, user_: Member): """Make sure that this reaction is what we want to operate on.""" - no_restrictions = ( # Pagination is not restricted not restrict_to_user @@ -321,7 +317,6 @@ class ImagePaginator(Paginator): :param line: str to be page content / title :param empty: if there should be new lines between entries """ - if line: self._count = len(line) else: @@ -335,7 +330,6 @@ class ImagePaginator(Paginator): :param image: image url to be appended """ - self.images.append(image) @classmethod @@ -365,7 +359,6 @@ class ImagePaginator(Paginator): :param suffix: suffix of message :param timeout: timeout for when reactions get auto-removed """ - def check_event(reaction_: Reaction, member: Member) -> bool: """ Checks each reaction added, if it matches our conditions pass the wait_for. @@ -373,7 +366,6 @@ class ImagePaginator(Paginator): :param reaction_: reaction added :param member: reaction added by member """ - return all(( # Reaction is on the same message sent reaction_.message.id == message.id, diff --git a/bot/seasons/christmas/adventofcode.py b/bot/seasons/christmas/adventofcode.py index 5d05dce6..c30de7b5 100644 --- a/bot/seasons/christmas/adventofcode.py +++ b/bot/seasons/christmas/adventofcode.py @@ -26,14 +26,12 @@ COUNTDOWN_STEP = 60 * 5 def is_in_advent() -> bool: """Utility function to check if we are between December 1st and December 25th.""" - # Run the code from the 1st to the 24th return datetime.now(EST).day in range(1, 25) and datetime.now(EST).month == 12 def time_left_to_aoc_midnight() -> Tuple[datetime, timedelta]: """Calculates the amount of time left until midnight in UTC-5 (Advent of Code maintainer timezone).""" - # Change all time properties back to 00:00 todays_midnight = datetime.now(EST).replace(microsecond=0, second=0, @@ -49,7 +47,6 @@ def time_left_to_aoc_midnight() -> Tuple[datetime, timedelta]: async def countdown_status(bot: commands.Bot): """Set the playing status of the bot to the minutes & hours left until the next day's challenge.""" - while is_in_advent(): _, time_left = time_left_to_aoc_midnight() @@ -77,12 +74,11 @@ async def countdown_status(bot: commands.Bot): async def day_countdown(bot: commands.Bot): """ - Calculate the number of seconds left until the next day of advent. + Calculate the number of seconds left until the next day of Advent. Once we have calculated this we should then sleep that number and when the time is reached, ping the Advent of Code role notifying them that the new challenge is ready. """ - while is_in_advent(): tomorrow, time_left = time_left_to_aoc_midnight() @@ -104,7 +100,7 @@ async def day_countdown(bot: commands.Bot): class AdventOfCode(commands.Cog): - """Advent of Code festivities! Ho Ho Ho.""" + """Advent of Code festivities! Ho Ho Ho!""" def __init__(self, bot: commands.Bot): self.bot = bot @@ -131,7 +127,6 @@ class AdventOfCode(commands.Cog): @commands.group(name="adventofcode", aliases=("aoc",), invoke_without_command=True) async def adventofcode_group(self, ctx: commands.Context): """All of the Advent of Code commands.""" - await ctx.invoke(self.bot.get_command("help"), "adventofcode") @adventofcode_group.command( @@ -141,7 +136,6 @@ class AdventOfCode(commands.Cog): ) async def aoc_subscribe(self, ctx: commands.Context): """Assign the role for notifications about new days being ready.""" - role = ctx.guild.get_role(AocConfig.role_id) unsubscribe_command = f"{ctx.prefix}{ctx.command.root_parent} unsubscribe" @@ -156,7 +150,6 @@ class AdventOfCode(commands.Cog): @adventofcode_group.command(name="unsubscribe", aliases=("unsub",), brief="Notifications for new days") async def aoc_unsubscribe(self, ctx: commands.Context): """Remove the role for notifications about new days being ready.""" - role = ctx.guild.get_role(AocConfig.role_id) if role in ctx.author.roles: @@ -168,7 +161,6 @@ class AdventOfCode(commands.Cog): @adventofcode_group.command(name="countdown", aliases=("count", "c"), brief="Return time left until next day") async def aoc_countdown(self, ctx: commands.Context): """Return time left until next day.""" - if not is_in_advent(): datetime_now = datetime.now(EST) december_first = datetime(datetime_now.year + 1, 12, 1, tzinfo=EST) @@ -186,13 +178,11 @@ class AdventOfCode(commands.Cog): @adventofcode_group.command(name="about", aliases=("ab", "info"), brief="Learn about Advent of Code") async def about_aoc(self, ctx: commands.Context): """Respond with an explanation of all things Advent of Code.""" - await ctx.send("", embed=self.cached_about_aoc) @adventofcode_group.command(name="join", aliases=("j",), brief="Learn how to join PyDis' private AoC leaderboard") async def join_leaderboard(self, ctx: commands.Context): """DM the user the information for joining the PyDis AoC private leaderboard.""" - author = ctx.message.author log.info(f"{author.name} ({author.id}) has requested the PyDis AoC leaderboard code") @@ -219,7 +209,6 @@ class AdventOfCode(commands.Cog): Advent of Code section of the bot constants. number_of_people_to_display values greater than this limit will default to this maximum and provide feedback to the user. """ - async with ctx.typing(): await self._check_leaderboard_cache(ctx) @@ -259,7 +248,6 @@ class AdventOfCode(commands.Cog): Embed will display the total members and the number of users who have completed each day's puzzle """ - async with ctx.typing(): await self._check_leaderboard_cache(ctx) @@ -305,7 +293,6 @@ class AdventOfCode(commands.Cog): Advent of Code section of the bot constants. number_of_people_to_display values greater than this limit will default to this maximum and provide feedback to the user. """ - async with ctx.typing(): await self._check_leaderboard_cache(ctx, global_board=True) @@ -336,7 +323,6 @@ class AdventOfCode(commands.Cog): global_board is a boolean to toggle between the global board and the Pydis private board """ - # Toggle between global & private leaderboards if global_board: log.debug("Checking global leaderboard cache") @@ -371,7 +357,7 @@ class AdventOfCode(commands.Cog): ) async def _check_n_entries(self, ctx: commands.Context, number_of_people_to_display: int) -> int: - # Check for n > max_entries and n <= 0 + """Check for n > max_entries and n <= 0""" max_entries = AocConfig.leaderboard_max_displayed_members author = ctx.message.author if not 0 <= number_of_people_to_display <= max_entries: @@ -390,7 +376,6 @@ class AdventOfCode(commands.Cog): def _build_about_embed(self) -> discord.Embed: """Build and return the informational "About AoC" embed from the resources file.""" - with self.about_aoc_filepath.open("r") as f: embed_fields = json.load(f) @@ -405,7 +390,6 @@ class AdventOfCode(commands.Cog): async def _boardgetter(self, global_board: bool): """Invoke the proper leaderboard getter based on the global_board boolean.""" - if global_board: self.cached_global_leaderboard = await AocGlobalLeaderboard.from_url() else: @@ -426,7 +410,6 @@ class AocMember: def __repr__(self): """Generate a user-friendly representation of the AocMember & their score.""" - return f"<{self.name} ({self.aoc_id}): {self.local_score}>" @classmethod @@ -440,7 +423,6 @@ class AocMember: Returns an AocMember object """ - return cls( name=injson["name"] if injson["name"] else "Anonymous User", aoc_id=int(injson["id"]), @@ -462,7 +444,6 @@ class AocMember: Returns a list of 25 lists, where each nested list contains a pair of booleans representing the code challenge completion status for that day """ - # Basic input validation if not isinstance(injson, dict): raise ValueError @@ -487,7 +468,6 @@ class AocMember: @staticmethod def _completions_from_starboard(starboard: list) -> tuple: """Return days completed, as a (1 star, 2 star) tuple, from starboard.""" - completions = [0, 0] for day in starboard: if day[0]: @@ -515,7 +495,6 @@ class AocPrivateLeaderboard: If n is not specified, default to the top 10 """ - return self.members[:n] def calculate_daily_completion(self) -> List[tuple]: @@ -525,7 +504,6 @@ class AocPrivateLeaderboard: Return a list of tuples for each day containing the number of users who completed each part of the challenge """ - daily_member_completions = [] for day in range(25): one_star_count = 0 @@ -550,7 +528,6 @@ class AocPrivateLeaderboard: If no year is input, year defaults to the current year """ - api_url = f"https://adventofcode.com/{year}/leaderboard/private/view/{leaderboard_id}.json" log.debug("Querying Advent of Code Private Leaderboard API") @@ -567,7 +544,6 @@ class AocPrivateLeaderboard: @classmethod def from_json(cls, injson: dict) -> "AocPrivateLeaderboard": """Generate an AocPrivateLeaderboard object from AoC's private leaderboard API JSON.""" - return cls( members=cls._sorted_members(injson["members"]), owner_id=injson["owner_id"], event_year=injson["event"] ) @@ -575,7 +551,6 @@ class AocPrivateLeaderboard: @classmethod async def from_url(cls) -> "AocPrivateLeaderboard": """Helper wrapping of AocPrivateLeaderboard.json_from_url and AocPrivateLeaderboard.from_json.""" - api_json = await cls.json_from_url() return cls.from_json(api_json) @@ -586,7 +561,6 @@ class AocPrivateLeaderboard: Output list is sorted based on the AocMember.local_score """ - members = [AocMember.member_from_json(injson[member]) for member in injson] members.sort(key=lambda x: x.local_score, reverse=True) @@ -599,7 +573,6 @@ class AocPrivateLeaderboard: Returns a string to be used as the content of the bot's leaderboard response """ - stargroup = f"{Emojis.star}, {Emojis.star*2}" header = f"{' '*3}{'Score'} {'Name':^25} {stargroup:^7}\n{'-'*44}" table = "" @@ -632,7 +605,6 @@ class AocGlobalLeaderboard: If n is not specified, default to the top 10 """ - return self.members[:n] @classmethod @@ -642,7 +614,6 @@ class AocGlobalLeaderboard: Because there is no API for this, web scraping needs to be used """ - aoc_url = f"https://adventofcode.com/{AocConfig.year}/leaderboard" async with aiohttp.ClientSession(headers=AOC_REQUEST_HEADER) as session: @@ -688,7 +659,6 @@ class AocGlobalLeaderboard: Returns a string to be used as the content of the bot's leaderboard response """ - header = f"{' '*4}{'Score'} {'Name':^25}\n{'-'*36}" table = "" for member in members_to_print: @@ -706,12 +676,10 @@ class AocGlobalLeaderboard: def _error_embed_helper(title: str, description: str) -> discord.Embed: """Return a red-colored Embed with the given title and description.""" - return discord.Embed(title=title, description=description, colour=discord.Colour.red()) def setup(bot: commands.Bot) -> None: """Advent of Code Cog load.""" - bot.add_cog(AdventOfCode(bot)) log.info("AdventOfCode cog loaded") diff --git a/bot/seasons/easter/april_fools_vids.py b/bot/seasons/easter/april_fools_vids.py index 5dae8485..c504229d 100644 --- a/bot/seasons/easter/april_fools_vids.py +++ b/bot/seasons/easter/april_fools_vids.py @@ -9,7 +9,8 @@ log = logging.getLogger(__name__) class AprilFoolVideos(commands.Cog): - """A cog for april fools that gets a random april fools video from youtube.""" + """A cog for April Fools' that gets a random April Fools' video from Youtube.""" + def __init__(self, bot): self.bot = bot self.yt_vids = self.load_json() @@ -17,7 +18,7 @@ class AprilFoolVideos(commands.Cog): @staticmethod def load_json(): - """A function to load json data.""" + """A function to load JSON data.""" p = Path('bot', 'resources', 'easter', 'april_fools_vids.json') with p.open() as json_file: all_vids = load(json_file) @@ -25,7 +26,7 @@ class AprilFoolVideos(commands.Cog): @commands.command(name='fool') async def aprial_fools(self, ctx): - """Gets a random april fools video from youtube.""" + """Get a random April Fools' video from Youtube.""" random_youtuber = random.choice(self.youtubers) category = self.yt_vids[random_youtuber] random_vid = random.choice(category) @@ -33,6 +34,6 @@ class AprilFoolVideos(commands.Cog): def setup(bot): - """A function to add the cog.""" + """April Fools' Cog load.""" bot.add_cog(AprilFoolVideos(bot)) log.info('April Fools videos cog loaded!') diff --git a/bot/seasons/easter/avatar_easterifier.py b/bot/seasons/easter/avatar_easterifier.py index 9f7ea271..445c5039 100644 --- a/bot/seasons/easter/avatar_easterifier.py +++ b/bot/seasons/easter/avatar_easterifier.py @@ -31,12 +31,10 @@ class AvatarEasterifier(commands.Cog): Returns a merge between the original colour and the closest colour """ - r1, g1, b1 = x def distance(point): """Finds the difference between a pastel colour and the original pixel colour""" - r2, g2, b2 = point return ((r1 - r2)**2 + (g1 - g2)**2 + (b1 - b2)**2) @@ -45,6 +43,7 @@ class AvatarEasterifier(commands.Cog): r = (r1 + r2) // 2 g = (g1 + g2) // 2 b = (b1 + b2) // 2 + return (r, g, b) @commands.command(pass_context=True, aliases=["easterify"]) @@ -57,7 +56,6 @@ class AvatarEasterifier(commands.Cog): Colours are split by spaces, unless you wrap the colour name in double quotes. Discord colour names, HTML colour names, XKCD colour names and hex values are accepted. """ - async def send(*args, **kwargs): """ This replaces the original ctx.send. @@ -127,7 +125,6 @@ class AvatarEasterifier(commands.Cog): def setup(bot): - """Cog load.""" - + """Avatar Easterifier Cog load.""" bot.add_cog(AvatarEasterifier(bot)) log.info("AvatarEasterifier cog loaded") diff --git a/bot/seasons/easter/conversationstarters.py b/bot/seasons/easter/conversationstarters.py index b479406b..4432c348 100644 --- a/bot/seasons/easter/conversationstarters.py +++ b/bot/seasons/easter/conversationstarters.py @@ -20,12 +20,10 @@ class ConvoStarters(commands.Cog): @commands.command() async def topic(self, ctx): """Responds with a random topic to start a conversation.""" - await ctx.send(random.choice(starters['starters'])) def setup(bot): """Conversation starters Cog load.""" - bot.add_cog(ConvoStarters(bot)) log.info("ConvoStarters cog loaded") diff --git a/bot/seasons/easter/egg_decorating.py b/bot/seasons/easter/egg_decorating.py index d283e42a..58d070bc 100644 --- a/bot/seasons/easter/egg_decorating.py +++ b/bot/seasons/easter/egg_decorating.py @@ -51,7 +51,6 @@ class EggDecorating(commands.Cog): Colours are split by spaces, unless you wrap the colour name in double quotes. Discord colour names, HTML colour names, XKCD colour names and hex values are accepted. """ - if len(colours) < 2: return await ctx.send("You must include at least 2 colours!") @@ -72,7 +71,7 @@ class EggDecorating(commands.Cog): return await ctx.send(f"Sorry, I don't know the colour {invalid[0]}!") async with ctx.typing(): - # expand list to 8 colours + # Expand list to 8 colours colours_n = len(colours) if colours_n < 8: q, r = divmod(8, colours_n) @@ -113,7 +112,6 @@ class EggDecorating(commands.Cog): def setup(bot): - """Cog load.""" - + """Egg decorating Cog load.""" bot.add_cog(EggDecorating(bot)) log.info("EggDecorating cog loaded.") diff --git a/bot/seasons/easter/egg_hunt/__init__.py b/bot/seasons/easter/egg_hunt/__init__.py index 43bda223..0e4b9e16 100644 --- a/bot/seasons/easter/egg_hunt/__init__.py +++ b/bot/seasons/easter/egg_hunt/__init__.py @@ -7,6 +7,5 @@ log = logging.getLogger(__name__) def setup(bot): """Easter Egg Hunt Cog load.""" - bot.add_cog(EggHunt()) log.info("EggHunt cog loaded") diff --git a/bot/seasons/easter/egg_hunt/cog.py b/bot/seasons/easter/egg_hunt/cog.py index c9e2dc18..9c20ba89 100644 --- a/bot/seasons/easter/egg_hunt/cog.py +++ b/bot/seasons/easter/egg_hunt/cog.py @@ -31,7 +31,6 @@ MUTED = GUILD.get_role(MainRoles.muted) def get_team_role(user: discord.Member) -> discord.Role: """Helper function to get the team role for a member.""" - if Roles.white in user.roles: return Roles.white if Roles.blurple in user.roles: @@ -40,7 +39,6 @@ def get_team_role(user: discord.Member) -> discord.Role: async def assign_team(user: discord.Member) -> discord.Member: """Helper function to assign a new team role for a member.""" - db = sqlite3.connect(DB_PATH) c = db.cursor() c.execute(f"SELECT team FROM user_scores WHERE user_id = {user.id}") @@ -81,7 +79,6 @@ class EggMessage: @staticmethod def add_user_score_sql(user_id: int, team: str, score: int) -> str: """Builds the SQL for adding a score to a user in the database.""" - return ( "INSERT INTO user_scores(user_id, team, score)" f"VALUES({user_id}, '{team}', {score})" @@ -91,12 +88,10 @@ class EggMessage: @staticmethod def add_team_score_sql(team_name: str, score: int) -> str: """Builds the SQL for adding a score to a team in the database.""" - return f"UPDATE team_scores SET team_score=team_score+{score} WHERE team_id='{team_name}'" def finalise_score(self): """Sums and actions scoring for this egg drop session.""" - db = sqlite3.connect(DB_PATH) c = db.cursor() @@ -139,7 +134,6 @@ class EggMessage: async def start_timeout(self, seconds: int = 5): """Begins a task that will sleep until the given seconds before finalizing the session.""" - if self.timeout_task: self.timeout_task.cancel() self.timeout_task = None @@ -156,7 +150,6 @@ class EggMessage: def is_valid_react(self, reaction: discord.Reaction, user: discord.Member) -> bool: """Validates a reaction event was meant for this session.""" - if user.bot: return False if reaction.message.id != self.message.id: @@ -164,7 +157,7 @@ class EggMessage: if reaction.emoji != self.egg: return False - # ignore the pushished + # Ignore the pushished if MUTED in user.roles: return False @@ -172,7 +165,6 @@ class EggMessage: async def collect_reacts(self, reaction: discord.Reaction, user: discord.Member): """Handles emitted reaction_add events via listener.""" - if not self.is_valid_react(reaction, user): return @@ -191,7 +183,6 @@ class EggMessage: async def start(self): """Starts the egg drop session.""" - log.debug(f"EggHunt session started for message {self.message.id}.") bot.add_listener(self.collect_reacts, name="on_reaction_add") with contextlib.suppress(discord.Forbidden): @@ -290,7 +281,6 @@ class SuperEggMessage(EggMessage): async def start_timeout(self, seconds=None): """Starts the super egg session.""" - if not seconds: return count = 4 @@ -348,7 +338,6 @@ class EggHunt(commands.Cog): def prepare_db(self): """Ensures database tables all exist and if not, creates them.""" - db = sqlite3.connect(DB_PATH) c = db.cursor() @@ -370,19 +359,16 @@ class EggHunt(commands.Cog): def task_cleanup(self, task): """Returns task result and restarts. Used as a done callback to show raised exceptions.""" - task.result() self.task = asyncio.create_task(self.super_egg()) @staticmethod def current_timestamp() -> float: """Returns a timestamp of the current UTC time.""" - return datetime.utcnow().replace(tzinfo=timezone.utc).timestamp() async def super_egg(self): """Manages the timing of super egg drops.""" - while True: now = int(self.current_timestamp()) @@ -470,7 +456,6 @@ class EggHunt(commands.Cog): @commands.Cog.listener() async def on_raw_reaction_add(self, payload): """Reaction event listener for reaction logging for later anti-cheat analysis.""" - if payload.channel_id not in EggHuntSettings.allowed_channels: return @@ -487,7 +472,6 @@ class EggHunt(commands.Cog): @commands.Cog.listener() async def on_message(self, message): """Message event listener for random egg drops.""" - if self.current_timestamp() < EggHuntSettings.start_time: return @@ -526,13 +510,11 @@ class EggHunt(commands.Cog): out. They stay around for 5 minutes and the team with the most reacts wins the points. """ - await ctx.invoke(bot.get_command("help"), command="hunt") @hunt.command() async def countdown(self, ctx): """Show the time status of the Egg Hunt event.""" - now = self.current_timestamp() if now > EggHuntSettings.end_time: return await ctx.send("The Hunt has ended.") @@ -551,7 +533,6 @@ class EggHunt(commands.Cog): @hunt.command() async def leaderboard(self, ctx): """Show the Egg Hunt Leaderboards.""" - db = sqlite3.connect(DB_PATH) c = db.cursor() c.execute(f"SELECT *, RANK() OVER(ORDER BY score DESC) AS rank FROM user_scores LIMIT 10") @@ -593,7 +574,6 @@ class EggHunt(commands.Cog): @hunt.command() async def rank(self, ctx, *, member: discord.Member = None): """Get your ranking in the Egg Hunt Leaderboard.""" - member = member or ctx.author db = sqlite3.connect(DB_PATH) c = db.cursor() @@ -614,7 +594,6 @@ class EggHunt(commands.Cog): @hunt.command() async def clear_db(self, ctx): """Resets the database to it's initial state.""" - def check(msg): if msg.author != ctx.author: return False diff --git a/bot/seasons/easter/egghead_quiz.py b/bot/seasons/easter/egghead_quiz.py index 8dd2c21d..7adeaebd 100644 --- a/bot/seasons/easter/egghead_quiz.py +++ b/bot/seasons/easter/egghead_quiz.py @@ -41,7 +41,6 @@ class EggheadQuiz(commands.Cog): Also informs of the percentages and votes of each option """ - random_question = random.choice(EGGHEAD_QUESTIONS) question, answers = random_question["question"], random_question["answers"] answers = [(EMOJIS[i], a) for i, a in enumerate(answers)] @@ -69,7 +68,7 @@ class EggheadQuiz(commands.Cog): total_no = sum([len(await r.users().flatten()) for r in msg.reactions]) - len(valid_emojis) # - bot's reactions if total_no == 0: - return await msg.delete() # to avoid ZeroDivisionError if nobody reacts + return await msg.delete() # To avoid ZeroDivisionError if nobody reacts results = ["**VOTES:**"] for emoji, _ in answers: @@ -115,7 +114,6 @@ class EggheadQuiz(commands.Cog): def setup(bot): - """Cog load.""" - + """Egghead Quiz Cog load.""" bot.add_cog(EggheadQuiz(bot)) log.info("EggheadQuiz bot loaded") diff --git a/bot/seasons/easter/traditions.py b/bot/seasons/easter/traditions.py index 05cd79f3..bed874f9 100644 --- a/bot/seasons/easter/traditions.py +++ b/bot/seasons/easter/traditions.py @@ -20,7 +20,6 @@ class Traditions(commands.Cog): @commands.command(aliases=('eastercustoms',)) async def easter_tradition(self, ctx): """Responds with a random tradition or custom""" - random_country = random.choice(list(traditions)) await ctx.send(f"{random_country}:\n{traditions[random_country]}") @@ -28,6 +27,5 @@ class Traditions(commands.Cog): def setup(bot): """Traditions Cog load.""" - bot.add_cog(Traditions(bot)) log.info("Traditions cog loaded") diff --git a/bot/seasons/evergreen/error_handler.py b/bot/seasons/evergreen/error_handler.py index 26afe814..f4457f8f 100644 --- a/bot/seasons/evergreen/error_handler.py +++ b/bot/seasons/evergreen/error_handler.py @@ -27,7 +27,6 @@ class CommandErrorHandler(commands.Cog): @commands.Cog.listener()
async def on_command_error(self, ctx, error):
"""Activates when a command opens an error."""
-
if hasattr(ctx.command, 'on_error'):
return logging.debug(
"A command error occured but the command had it's own error handler."
@@ -101,6 +100,5 @@ class CommandErrorHandler(commands.Cog): def setup(bot):
"""Error handler Cog load."""
-
bot.add_cog(CommandErrorHandler(bot))
log.info("CommandErrorHandler cog loaded")
diff --git a/bot/seasons/evergreen/fun.py b/bot/seasons/evergreen/fun.py index 05cf504e..ce3484f7 100644 --- a/bot/seasons/evergreen/fun.py +++ b/bot/seasons/evergreen/fun.py @@ -17,7 +17,6 @@ class Fun(commands.Cog): @commands.command() async def roll(self, ctx, num_rolls: int = 1): """Outputs a number of random dice emotes (up to 6).""" - output = "" if num_rolls > 6: num_rolls = 6 @@ -31,6 +30,5 @@ class Fun(commands.Cog): def setup(bot): """Fun Cog load.""" - bot.add_cog(Fun(bot)) log.info("Fun cog loaded") diff --git a/bot/seasons/evergreen/magic_8ball.py b/bot/seasons/evergreen/magic_8ball.py index 0b4eeb62..9add06af 100644 --- a/bot/seasons/evergreen/magic_8ball.py +++ b/bot/seasons/evergreen/magic_8ball.py @@ -18,7 +18,7 @@ class Magic8ball(commands.Cog): @commands.command(name="8ball") async def output_answer(self, ctx, *, question): - """Return a magic 8 ball answer from answers list.""" + """Return a Magic 8ball answer from answers list.""" if len(question.split()) >= 3: answer = random.choice(self.answers) await ctx.send(answer) @@ -27,7 +27,6 @@ class Magic8ball(commands.Cog): def setup(bot): - """Magic 8ball cog load.""" - + """Magic 8ball Cog load.""" bot.add_cog(Magic8ball(bot)) log.info("Magic8ball cog loaded") diff --git a/bot/seasons/evergreen/snakes/__init__.py b/bot/seasons/evergreen/snakes/__init__.py index 5188200e..d0e57dae 100644 --- a/bot/seasons/evergreen/snakes/__init__.py +++ b/bot/seasons/evergreen/snakes/__init__.py @@ -7,6 +7,5 @@ log = logging.getLogger(__name__) def setup(bot): """Snakes Cog load.""" - bot.add_cog(Snakes(bot)) log.info("Snakes cog loaded") diff --git a/bot/seasons/evergreen/snakes/converter.py b/bot/seasons/evergreen/snakes/converter.py index ec9c9870..f2637530 100644 --- a/bot/seasons/evergreen/snakes/converter.py +++ b/bot/seasons/evergreen/snakes/converter.py @@ -20,7 +20,6 @@ class Snake(Converter): async def convert(self, ctx, name): """Convert the input snake name to the closest matching Snake object.""" - await self.build_list() name = name.lower() @@ -61,7 +60,6 @@ class Snake(Converter): @classmethod async def build_list(cls): """Build list of snakes from the static snake resources.""" - # Get all the snakes if cls.snakes is None: with (SNAKE_RESOURCES / "snake_names.json").open() as snakefile: @@ -80,10 +78,7 @@ class Snake(Converter): This is stupid. We should find a way to somehow get the global session into a global context, so I can get it from here. - - :return: """ - await cls.build_list() names = [snake['scientific'] for snake in cls.snakes] return random.choice(names) diff --git a/bot/seasons/evergreen/snakes/snakes_cog.py b/bot/seasons/evergreen/snakes/snakes_cog.py index 3ffdf1bf..6698183f 100644 --- a/bot/seasons/evergreen/snakes/snakes_cog.py +++ b/bot/seasons/evergreen/snakes/snakes_cog.py @@ -156,7 +156,6 @@ class Snakes(Cog): @staticmethod def _beautiful_pastel(hue): """Returns random bright pastels.""" - light = random.uniform(0.7, 0.85) saturation = 1 @@ -176,7 +175,6 @@ class Snakes(Cog): Written by juan and Someone during the first code jam. """ - snake = Image.open(buffer) # Get the size of the snake icon, configure the height of the image box (yes, it changes) @@ -254,7 +252,6 @@ class Snakes(Cog): @staticmethod def _snakify(message): """Sssnakifffiesss a sstring.""" - # Replace fricatives with exaggerated snake fricatives. simple_fricatives = [ "f", "s", "z", "h", @@ -277,7 +274,6 @@ class Snakes(Cog): async def _fetch(self, session, url, params=None): """Asynchronous web request helper method.""" - if params is None: params = {} @@ -291,7 +287,6 @@ class Snakes(Cog): Else, just return whatever the last message is. """ - long_message = random.choice(messages) if len(long_message.split()) < 3 and retries > 0: return self._get_random_long_message( @@ -312,7 +307,6 @@ class Snakes(Cog): :param name: The name of the snake to get information for - omit for a random snake :return: A dict containing information on a snake """ - snake_info = {} async with aiohttp.ClientSession() as session: @@ -327,7 +321,7 @@ class Snakes(Cog): json = await self._fetch(session, URL, params=params) - # wikipedia does have a error page + # Wikipedia does have a error page try: pageid = json["query"]["search"][0]["pageid"] except KeyError: @@ -348,7 +342,7 @@ class Snakes(Cog): json = await self._fetch(session, URL, params=params) - # constructing dict - handle exceptions later + # Constructing dict - handle exceptions later try: snake_info["title"] = json["query"]["pages"][f"{pageid}"]["title"] snake_info["extract"] = json["query"]["pages"][f"{pageid}"]["extract"] @@ -380,7 +374,7 @@ class Snakes(Cog): ] for image in snake_info["images"]: - # images come in the format of `File:filename.extension` + # Images come in the format of `File:filename.extension` file, sep, filename = image["title"].partition(':') filename = filename.replace(" ", "%20") # Wikipedia returns good data! @@ -417,15 +411,9 @@ class Snakes(Cog): return random.choice(self.snake_names) async def _validate_answer(self, ctx: Context, message: Message, answer: str, options: list): - """ - Validate the answer using a reaction event loop. - - :return: - """ - + """Validate the answer using a reaction event loop.""" def predicate(reaction, user): """Test if the the answer is valid and can be evaluated.""" - return ( reaction.message.id == message.id # The reaction is attached to the question we asked. and user == ctx.author # It's the user who triggered the quiz. @@ -457,7 +445,6 @@ class Snakes(Cog): @group(name='snakes', aliases=('snake',), invoke_without_command=True) async def snakes_group(self, ctx: Context): """Commands from our first code jam.""" - await ctx.invoke(self.bot.get_command("help"), "snake") @bot_has_permissions(manage_messages=True) @@ -478,10 +465,8 @@ class Snakes(Cog): This game was created by Lord Bisk and Runew0lf. """ - def predicate(reaction_: Reaction, user_: Member): """Make sure that this reaction is what we want to operate on.""" - return ( all(( # Reaction is on this message @@ -613,7 +598,6 @@ class Snakes(Cog): Written by Momo and kel. Modified by juan and lemon. """ - with ctx.typing(): # Generate random snake attributes @@ -657,7 +641,6 @@ class Snakes(Cog): Created by Ava and eivl. """ - with ctx.typing(): if name is None: name = await Snake.random() @@ -707,7 +690,6 @@ class Snakes(Cog): Made by Ava and eivl. Modified by lemon. """ - with ctx.typing(): image = None @@ -741,7 +723,6 @@ class Snakes(Cog): Written by Momo and kel. """ - # Pick a random snake to hatch. snake_name = random.choice(list(utils.snakes.keys())) snake_image = utils.snakes[snake_name] @@ -774,7 +755,6 @@ class Snakes(Cog): Written by Samuel. Modified by gdude. """ - url = "http://www.omdbapi.com/" page = random.randint(1, 27) @@ -845,7 +825,6 @@ class Snakes(Cog): This was created by Mushy and Cardium, and modified by Urthas and lemon. """ - # Prepare a question. question = random.choice(self.snake_quizzes) answer = question["answerkey"] @@ -886,7 +865,6 @@ class Snakes(Cog): This was written by Iceman, and modified for inclusion into the bot by lemon. """ - snake_name = await self._get_snake_name() snake_name = snake_name['name'] snake_prefix = "" @@ -944,8 +922,7 @@ class Snakes(Cog): Written by Momo and kel. Modified by lemon. """ - - # check if there is already a game in this channel + # Check if there is already a game in this channel if ctx.channel in self.active_sal: await ctx.send(f"{ctx.author.mention} A game is already in progress in this channel.") return @@ -958,7 +935,6 @@ class Snakes(Cog): @snakes_group.command(name='about') async def about_command(self, ctx: Context): """Show an embed with information about the event, its participants, and its winners.""" - contributors = [ "<@!245270749919576066>", "<@!396290259907903491>", @@ -1006,7 +982,6 @@ class Snakes(Cog): Created by juan and Someone during the first code jam. """ - # Get the snake data we need if not name: name_obj = await self._get_snake_name() @@ -1046,7 +1021,6 @@ class Snakes(Cog): Written by Andrew and Prithaj. Modified by lemon. """ - question = random.choice(self.snake_facts)["fact"] embed = Embed( title="Snake fact", @@ -1058,7 +1032,6 @@ class Snakes(Cog): @snakes_group.command(name='help') async def help_command(self, ctx: Context): """Invokes the help command for the Snakes Cog.""" - log.debug(f"{ctx.author} requested info about the snakes cog") return await ctx.invoke(self.bot.get_command("help"), "Snakes") @@ -1075,7 +1048,6 @@ class Snakes(Cog): Written by Momo and kel. Modified by lemon. """ - with ctx.typing(): embed = Embed() user = ctx.message.author @@ -1116,7 +1088,6 @@ class Snakes(Cog): Written by Andrew and Prithaj. """ - # Are we searching for anything specific? if search: query = search + ' snake' @@ -1156,7 +1127,6 @@ class Snakes(Cog): Written by Prithaj and Andrew. Modified by lemon. """ - embed = Embed( title="Zzzen of Pythhon", color=SNAKE_COLOR @@ -1179,7 +1149,6 @@ class Snakes(Cog): @video_command.error async def command_error(self, ctx, error): """Local error handler for the Snake Cog.""" - embed = Embed() embed.colour = Colour.red() diff --git a/bot/seasons/evergreen/snakes/utils.py b/bot/seasons/evergreen/snakes/utils.py index e2ed60bd..0d1505f7 100644 --- a/bot/seasons/evergreen/snakes/utils.py +++ b/bot/seasons/evergreen/snakes/utils.py @@ -113,20 +113,17 @@ ANGLE_RANGE = math.pi * 2 def get_resource(file: str) -> List[dict]: """Load Snake resources JSON.""" - with (SNAKE_RESOURCES / f"{file}.json").open(encoding="utf-8") as snakefile: return json.load(snakefile) def smoothstep(t): """Smooth curve with a zero derivative at 0 and 1, making it useful for interpolating.""" - return t * t * (3. - 2. * t) def lerp(t, a, b): """Linear interpolation between a and b, given a fraction t.""" - return a + t * (b - a) @@ -159,7 +156,6 @@ class PerlinNoiseFactory(object): If ``unbias`` is true, the smoothstep function will be applied to the output before returning it, to counteract some of Perlin noise's significant bias towards the center of its output range. """ - self.dimension = dimension self.octaves = octaves self.tile = tile + (0,) * dimension @@ -177,7 +173,6 @@ class PerlinNoiseFactory(object): This is the "gradient" vector, in that the grid tile slopes towards it """ - # 1 dimension is special, since the only unit vector is trivial; # instead, use a slope between -1 and 1 if self.dimension == 1: @@ -194,7 +189,6 @@ class PerlinNoiseFactory(object): def get_plain_noise(self, *point): """Get plain noise for a single point, without taking into account either octaves or tiling.""" - if len(point) != self.dimension: raise ValueError("Expected {0} values, got {1}".format( self.dimension, len(point))) @@ -247,7 +241,6 @@ class PerlinNoiseFactory(object): The number of values given should match the number of dimensions. """ - ret = 0 for o in range(self.octaves): o2 = 1 << o @@ -308,7 +301,6 @@ def create_snek_frame( :param text_color: the color of the text. :return: a PIL image, representing a single frame. """ - start_x = random.randint(image_margins[X], image_dimensions[X] - image_margins[X]) start_y = random.randint(image_margins[Y], image_dimensions[Y] - image_margins[Y]) points = [(start_x, start_y)] @@ -363,7 +355,6 @@ def create_snek_frame( def frame_to_png_bytes(image: Image): """Convert image to byte stream.""" - stream = io.BytesIO() image.save(stream, format='PNG') return stream.getvalue() @@ -410,10 +401,8 @@ class SnakeAndLaddersGame: Listen for reactions until players have joined, and the game has been started. """ - def startup_event_check(reaction_: Reaction, user_: Member): """Make sure that this reaction is what we want to operate on.""" - return ( all(( reaction_.message.id == startup.id, # Reaction is on startup message @@ -494,7 +483,6 @@ class SnakeAndLaddersGame: Prevent player joining if they have already joined, if the game is full, or if the game is in a waiting state. """ - for p in self.players: if user == p: await self.channel.send(user.mention + " You are already in the game.", delete_after=10) @@ -521,7 +509,6 @@ class SnakeAndLaddersGame: Leaving is prevented if the user initiated the game or if they weren't part of it in the first place. """ - if user == self.author: await self.channel.send( user.mention + " You are the author, and cannot leave the game. Execute " @@ -547,7 +534,6 @@ class SnakeAndLaddersGame: async def cancel_game(self, user: Member): """Allow the game author to cancel the running game.""" - if not user == self.author: await self.channel.send(user.mention + " Only the author of the game can cancel it.", delete_after=10) return @@ -561,7 +547,6 @@ class SnakeAndLaddersGame: The game cannot be started if there aren't enough players joined or if the game is in a waiting state. """ - if not user == self.author: await self.channel.send(user.mention + " Only the author of the game can start it.", delete_after=10) return @@ -581,10 +566,8 @@ class SnakeAndLaddersGame: async def start_round(self): """Begin the round.""" - def game_event_check(reaction_: Reaction, user_: Member): """Make sure that this reaction is what we want to operate on.""" - return ( all(( reaction_.message.id == self.positions.id, # Reaction is on positions message @@ -676,7 +659,6 @@ class SnakeAndLaddersGame: async def player_roll(self, user: Member): """Handle the player's roll.""" - if user.id not in self.player_tiles: await self.channel.send(user.mention + " You are not in the match.", delete_after=10) return diff --git a/bot/seasons/evergreen/uptime.py b/bot/seasons/evergreen/uptime.py index 32c2b59d..92066e0a 100644 --- a/bot/seasons/evergreen/uptime.py +++ b/bot/seasons/evergreen/uptime.py @@ -18,7 +18,6 @@ class Uptime(commands.Cog): @commands.command(name="uptime") async def uptime(self, ctx): """Responds with the uptime of the bot.""" - difference = relativedelta(start_time - arrow.utcnow()) uptime_string = start_time.shift( seconds=-difference.seconds, @@ -31,6 +30,5 @@ class Uptime(commands.Cog): def setup(bot): """Uptime Cog load.""" - bot.add_cog(Uptime(bot)) log.info("Uptime cog loaded") diff --git a/bot/seasons/halloween/candy_collection.py b/bot/seasons/halloween/candy_collection.py index 70648e64..1f219425 100644 --- a/bot/seasons/halloween/candy_collection.py +++ b/bot/seasons/halloween/candy_collection.py @@ -36,7 +36,6 @@ class CandyCollection(commands.Cog): @commands.Cog.listener() async def on_message(self, message): """Randomly adds candy or skull reaction to non-bot messages in the Event channel.""" - # make sure its a human message if message.author.bot: return @@ -58,7 +57,6 @@ class CandyCollection(commands.Cog): @commands.Cog.listener() async def on_reaction_add(self, reaction, user): """Add/remove candies from a person if the reaction satisfies criteria.""" - message = reaction.message # check to ensure the reactor is human if user.bot: @@ -110,7 +108,6 @@ class CandyCollection(commands.Cog): This event has a higher probability of occurring than a reaction add to a message without an existing reaction. """ - if random.randint(1, ADD_SKULL_EXISTING_REACTION_CHANCE) == 1: d = {"reaction": '\N{SKULL}', "msg_id": message.id, "won": False} self.msg_reacted.append(d) @@ -123,7 +120,6 @@ class CandyCollection(commands.Cog): async def ten_recent_msg(self): """Get the last 10 messages sent in the channel.""" - ten_recent = [] recent_msg = max(message.id for message in self.bot._connection._messages @@ -141,7 +137,6 @@ class CandyCollection(commands.Cog): async def get_message(self, msg_id): """Get the message from its ID.""" - try: o = discord.Object(id=msg_id + 1) # Use history rather than get_message due to @@ -158,12 +153,10 @@ class CandyCollection(commands.Cog): async def hacktober_channel(self): """Get #hacktoberbot channel from its ID.""" - return self.bot.get_channel(id=Hacktoberfest.channel_id) async def remove_reactions(self, reaction): """Remove all candy/skull reactions.""" - try: async for user in reaction.users(): await reaction.message.remove_reaction(reaction.emoji, user) @@ -173,7 +166,6 @@ class CandyCollection(commands.Cog): async def send_spook_msg(self, author, channel, candies): """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.") @@ -181,15 +173,13 @@ class CandyCollection(commands.Cog): def save_to_json(self): """Save JSON to a local file.""" - with open(json_location, 'w') as outfile: json.dump(self.candy_json, outfile) @commands.command() async def candy(self, ctx): """Get the candy leaderboard and save to JSON.""" - - # use run_in_executor to prevent blocking + # Use run_in_executor to prevent blocking thing = functools.partial(self.save_to_json) await self.bot.loop.run_in_executor(None, thing) @@ -225,6 +215,5 @@ class CandyCollection(commands.Cog): def setup(bot): """Candy Collection game Cog load.""" - bot.add_cog(CandyCollection(bot)) log.info("CandyCollection cog loaded") diff --git a/bot/seasons/halloween/hacktoberstats.py b/bot/seasons/halloween/hacktoberstats.py index 42623669..c30ad90f 100644 --- a/bot/seasons/halloween/hacktoberstats.py +++ b/bot/seasons/halloween/hacktoberstats.py @@ -34,7 +34,6 @@ class HacktoberStats(commands.Cog): linked their Discord name to GitHub using .stats link. If invoked with a github_username, get that user's contributions """ - if not github_username: author_id, author_mention = HacktoberStats._author_mention_from_context(ctx) @@ -65,7 +64,6 @@ class HacktoberStats(commands.Cog): } } """ - author_id, author_mention = HacktoberStats._author_mention_from_context(ctx) if github_username: if str(author_id) in self.linked_accounts.keys(): @@ -89,7 +87,6 @@ class HacktoberStats(commands.Cog): @hacktoberstats_group.command(name="unlink") async def unlink_user(self, ctx: commands.Context): """Remove the invoking user's account link from the log.""" - author_id, author_mention = HacktoberStats._author_mention_from_context(ctx) stored_user = self.linked_accounts.pop(author_id, None) @@ -114,7 +111,6 @@ class HacktoberStats(commands.Cog): } } """ - if self.link_json.exists(): logging.info(f"Loading linked GitHub accounts from '{self.link_json}'") with open(self.link_json, 'r') as fID: @@ -138,7 +134,6 @@ class HacktoberStats(commands.Cog): } } """ - logging.info(f"Saving linked_accounts to '{self.link_json}'") with open(self.link_json, 'w') as fID: json.dump(self.linked_accounts, fID, default=str) @@ -154,7 +149,6 @@ class HacktoberStats(commands.Cog): Otherwise, post a helpful error message """ - async with ctx.typing(): prs = await self.get_october_prs(github_username) @@ -166,7 +160,6 @@ class HacktoberStats(commands.Cog): def build_embed(self, github_username: str, prs: typing.List[dict]) -> discord.Embed: """Return a stats embed built from github_username's PRs.""" - logging.info(f"Building Hacktoberfest embed for GitHub user: '{github_username}'") pr_stats = self._summarize_prs(prs) @@ -221,7 +214,6 @@ class HacktoberStats(commands.Cog): Otherwise, return None """ - logging.info(f"Generating Hacktoberfest PR query for GitHub user: '{github_username}'") base_url = "https://api.github.com/search/issues?q=" not_label = "invalid" @@ -278,7 +270,6 @@ class HacktoberStats(commands.Cog): V "python-discord/seasonalbot" """ - exp = r"https?:\/\/api.github.com\/repos\/([/\-\_\.\w]+)" return re.findall(exp, in_url)[0] @@ -293,7 +284,6 @@ class HacktoberStats(commands.Cog): "top5": [(repo_shortname, ncontributions), ...] } """ - contributed_repos = [pr["repo_shortname"] for pr in prs] return {"n_prs": len(prs), "top5": Counter(contributed_repos).most_common(5)} @@ -309,7 +299,6 @@ class HacktoberStats(commands.Cog): n contribution(s) to [shortname](url) ... """ - baseURL = "https://www.github.com/" contributionstrs = [] for repo in stats['top5']: @@ -321,7 +310,6 @@ class HacktoberStats(commands.Cog): @staticmethod def _contributionator(n: int) -> str: """Return "contribution" or "contributions" based on the value of n.""" - if n == 1: return "contribution" else: @@ -330,7 +318,6 @@ class HacktoberStats(commands.Cog): @staticmethod def _author_mention_from_context(ctx: commands.Context) -> typing.Tuple: """Return stringified Message author ID and mentionable string from commands.Context.""" - author_id = str(ctx.message.author.id) author_mention = ctx.message.author.mention @@ -339,6 +326,5 @@ class HacktoberStats(commands.Cog): def setup(bot): """Hacktoberstats Cog load.""" - bot.add_cog(HacktoberStats(bot)) log.info("HacktoberStats cog loaded") diff --git a/bot/seasons/halloween/halloween_facts.py b/bot/seasons/halloween/halloween_facts.py index ee90dbd3..e8392b28 100644 --- a/bot/seasons/halloween/halloween_facts.py +++ b/bot/seasons/halloween/halloween_facts.py @@ -39,19 +39,16 @@ class HalloweenFacts(commands.Cog): @commands.Cog.listener() async def on_ready(self): """Get event Channel object and initialize fact task loop.""" - self.channel = self.bot.get_channel(Hacktoberfest.channel_id) self.bot.loop.create_task(self._fact_publisher_task()) def random_fact(self): """Return a random fact from the loaded facts.""" - return random.choice(self.facts) @commands.command(name="spookyfact", aliases=("halloweenfact",), brief="Get the most recent Halloween fact") async def get_random_fact(self, ctx): """Reply with the most recent Halloween fact.""" - index, fact = self.random_fact() embed = self._build_embed(index, fact) await ctx.send(embed=embed) @@ -59,7 +56,6 @@ class HalloweenFacts(commands.Cog): @staticmethod def _build_embed(index, fact): """Builds a Discord embed from the given fact and its index.""" - emoji = random.choice(SPOOKY_EMOJIS) title = f"{emoji} Halloween Fact #{index + 1}" return discord.Embed(title=title, description=fact, color=PUMPKIN_ORANGE) @@ -67,6 +63,5 @@ class HalloweenFacts(commands.Cog): def setup(bot): """Halloween facts Cog load.""" - bot.add_cog(HalloweenFacts(bot)) log.info("HalloweenFacts cog loaded") diff --git a/bot/seasons/halloween/halloweenify.py b/bot/seasons/halloween/halloweenify.py index ce057889..4d56e2f8 100644 --- a/bot/seasons/halloween/halloweenify.py +++ b/bot/seasons/halloween/halloweenify.py @@ -19,8 +19,7 @@ class Halloweenify(commands.Cog): @commands.cooldown(1, 300, BucketType.user) @commands.command() async def halloweenify(self, ctx): - """Change your nickname into a much spookier one.""" - + """Change your nickname into a much spookier one!""" async with ctx.typing(): with open(Path('bot', 'resources', 'halloween', 'halloweenify.json'), 'r') as f: data = load(f) @@ -49,6 +48,5 @@ class Halloweenify(commands.Cog): def setup(bot): """Halloweenify Cog load.""" - bot.add_cog(Halloweenify(bot)) log.info("Halloweenify cog loaded") diff --git a/bot/seasons/halloween/monstersurvey.py b/bot/seasons/halloween/monstersurvey.py index 2ae98f6e..4e967cca 100644 --- a/bot/seasons/halloween/monstersurvey.py +++ b/bot/seasons/halloween/monstersurvey.py @@ -25,7 +25,6 @@ class MonsterSurvey(Cog): def __init__(self, bot: Bot): """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') as jason: @@ -33,7 +32,6 @@ class MonsterSurvey(Cog): def json_write(self): """Write voting results to a local JSON file.""" - log.info("Saved Monster Survey Results") with open(self.registry_location, 'w') as jason: json.dump(self.voter_registry, jason, indent=2) @@ -48,7 +46,6 @@ class MonsterSurvey(Cog): :param monster: the string key of the json that represents a monster :return: None """ - vr = self.voter_registry for m in vr.keys(): if id not in vr[m]['votes'] and m == monster: @@ -59,7 +56,6 @@ class MonsterSurvey(Cog): def get_name_by_leaderboard_index(self, n): """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) @@ -72,7 +68,6 @@ class MonsterSurvey(Cog): ) async def monster_group(self, ctx: Context): """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( @@ -107,7 +102,6 @@ class MonsterSurvey(Cog): Displays a list of monsters that can be voted for if one is not specified. """ - if name is None: await ctx.invoke(self.monster_leaderboard) return @@ -161,7 +155,6 @@ class MonsterSurvey(Cog): :param name: :return: """ - if name is None: await ctx.invoke(self.monster_leaderboard) return @@ -198,7 +191,6 @@ class MonsterSurvey(Cog): :param ctx: :return: """ - async with ctx.typing(): vr = self.voter_registry top = sorted(vr, key=lambda k: len(vr[k]['votes']), reverse=True) @@ -225,6 +217,5 @@ class MonsterSurvey(Cog): def setup(bot): """Monster survey Cog load.""" - bot.add_cog(MonsterSurvey(bot)) log.info("MonsterSurvey cog loaded") diff --git a/bot/seasons/halloween/scarymovie.py b/bot/seasons/halloween/scarymovie.py index 3878ef7f..cd95a3a2 100644 --- a/bot/seasons/halloween/scarymovie.py +++ b/bot/seasons/halloween/scarymovie.py @@ -22,7 +22,6 @@ class ScaryMovie(commands.Cog): @commands.command(name='scarymovie', alias=['smovie']) async def random_movie(self, ctx): """Randomly select a scary movie and display information about it.""" - async with ctx.typing(): selection = await self.select_movie() movie_details = await self.format_metadata(selection) @@ -31,8 +30,7 @@ class ScaryMovie(commands.Cog): @staticmethod async def select_movie(): - """Selects a random movie and returns a json of movie details from TMDb.""" - + """Selects a random movie and returns a JSON of movie details from TMDb.""" url = 'https://api.themoviedb.org/4/discover/movie' params = { 'with_genres': '27', @@ -65,8 +63,7 @@ class ScaryMovie(commands.Cog): @staticmethod async def format_metadata(movie): - """Formats raw TMDb data to be embedded in discord chat.""" - + """Formats raw TMDb data to be embedded in Discord chat.""" # Build the relevant URLs. movie_id = movie.get("id") poster_path = movie.get("poster_path") @@ -131,6 +128,5 @@ class ScaryMovie(commands.Cog): def setup(bot): """Scary movie Cog load.""" - bot.add_cog(ScaryMovie(bot)) log.info("ScaryMovie cog loaded") diff --git a/bot/seasons/halloween/spookyavatar.py b/bot/seasons/halloween/spookyavatar.py index 15c7c431..4b0ba9f5 100644 --- a/bot/seasons/halloween/spookyavatar.py +++ b/bot/seasons/halloween/spookyavatar.py @@ -19,8 +19,7 @@ class SpookyAvatar(commands.Cog): self.bot = bot async def get(self, url): - """Returns the contents of the supplied url.""" - + """Returns the contents of the supplied URL.""" async with aiohttp.ClientSession() as session: async with session.get(url) as resp: return await resp.read() @@ -29,7 +28,6 @@ class SpookyAvatar(commands.Cog): brief='Spookify an user\'s avatar.') async def spooky_avatar(self, ctx, user: discord.Member = None): """A command to print the user's spookified avatar.""" - if user is None: user = ctx.message.author @@ -50,6 +48,5 @@ class SpookyAvatar(commands.Cog): def setup(bot): """Spooky avatar Cog load.""" - bot.add_cog(SpookyAvatar(bot)) log.info("SpookyAvatar cog loaded") diff --git a/bot/seasons/halloween/spookygif.py b/bot/seasons/halloween/spookygif.py index 37d46c01..ba2ad6e5 100644 --- a/bot/seasons/halloween/spookygif.py +++ b/bot/seasons/halloween/spookygif.py @@ -18,7 +18,6 @@ class SpookyGif(commands.Cog): @commands.command(name="spookygif", aliases=("sgif", "scarygif")) async def spookygif(self, ctx): """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'} @@ -36,6 +35,5 @@ class SpookyGif(commands.Cog): def setup(bot): """Spooky GIF Cog load.""" - bot.add_cog(SpookyGif(bot)) log.info("SpookyGif cog loaded") diff --git a/bot/seasons/halloween/spookyrating.py b/bot/seasons/halloween/spookyrating.py index a9cfda9b..18a963e0 100644 --- a/bot/seasons/halloween/spookyrating.py +++ b/bot/seasons/halloween/spookyrating.py @@ -31,7 +31,6 @@ class SpookyRating(commands.Cog): Any user will always yield the same result, no matter who calls the command """ - if who is None: who = ctx.author @@ -63,6 +62,6 @@ class SpookyRating(commands.Cog): def setup(bot): - """Cog load.""" + """Spooky Rating Cog load.""" bot.add_cog(SpookyRating(bot)) log.info("SpookyRating cog loaded") diff --git a/bot/seasons/halloween/spookyreact.py b/bot/seasons/halloween/spookyreact.py index 9b14507a..5a086072 100644 --- a/bot/seasons/halloween/spookyreact.py +++ b/bot/seasons/halloween/spookyreact.py @@ -32,7 +32,6 @@ class SpookyReact(Cog): Seasonalbot's own messages are ignored """ - for trigger in SPOOKY_TRIGGERS.keys(): trigger_test = re.search(SPOOKY_TRIGGERS[trigger][0], ctx.content.lower()) if trigger_test: @@ -52,7 +51,6 @@ class SpookyReact(Cog): * author is the bot * 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}") @@ -70,6 +68,5 @@ class SpookyReact(Cog): def setup(bot): """Spooky reaction Cog load.""" - bot.add_cog(SpookyReact(bot)) log.info("SpookyReact cog loaded") diff --git a/bot/seasons/halloween/spookysound.py b/bot/seasons/halloween/spookysound.py index 7c4d8113..995f0403 100644 --- a/bot/seasons/halloween/spookysound.py +++ b/bot/seasons/halloween/spookysound.py @@ -26,7 +26,6 @@ class SpookySound(commands.Cog): Cannot be used more than once in 2 minutes. """ - if not self.channel: await self.bot.wait_until_ready() self.channel = self.bot.get_channel(Hacktoberfest.voice_id) @@ -45,6 +44,5 @@ class SpookySound(commands.Cog): def setup(bot): """Spooky sound Cog load.""" - bot.add_cog(SpookySound(bot)) log.info("SpookySound cog loaded") diff --git a/bot/seasons/halloween/timeleft.py b/bot/seasons/halloween/timeleft.py index 3ea2d9ad..a2b16a6c 100644 --- a/bot/seasons/halloween/timeleft.py +++ b/bot/seasons/halloween/timeleft.py @@ -15,13 +15,11 @@ class TimeLeft(commands.Cog): @staticmethod def in_october(): """Return True if the current month is October.""" - return datetime.utcnow().month == 10 @staticmethod def load_date(): """Return of a tuple of the current time and the end and start times of the next October.""" - now = datetime.utcnow() year = now.year if now.month > 10: @@ -38,7 +36,6 @@ class TimeLeft(commands.Cog): Whilst in October, displays the days, hours and minutes left. Only displays the days left until the beginning and end whilst in a different month """ - now, end, start = self.load_date() diff = end - now days, seconds = diff.days, diff.seconds @@ -58,6 +55,5 @@ class TimeLeft(commands.Cog): def setup(bot): """Cog load.""" - bot.add_cog(TimeLeft(bot)) log.info("TimeLeft cog loaded") diff --git a/bot/seasons/season.py b/bot/seasons/season.py index 6d992276..4809c2e8 100644 --- a/bot/seasons/season.py +++ b/bot/seasons/season.py @@ -22,7 +22,6 @@ ICON_BASE_URL = "https://raw.githubusercontent.com/python-discord/branding/maste def get_seasons() -> List[str]: """Returns all the Season objects located in /bot/seasons/.""" - seasons = [] for module in pkgutil.iter_modules([Path("bot", "seasons")]): @@ -33,7 +32,6 @@ def get_seasons() -> List[str]: def get_season_class(season_name: str) -> Type["SeasonBase"]: """Gets the season class of the season module.""" - season_lib = importlib.import_module(f"bot.seasons.{season_name}") class_name = season_name.replace("_", " ").title().replace(" ", "") return getattr(season_lib, class_name) @@ -41,7 +39,6 @@ def get_season_class(season_name: str) -> Type["SeasonBase"]: def get_season(season_name: str = None, date: datetime.datetime = None) -> "SeasonBase": """Returns a Season object based on either a string or a date.""" - # If either both or neither are set, raise an error. if not bool(season_name) ^ bool(date): raise UserWarning("This function requires either a season or a date in order to run.") @@ -91,7 +88,6 @@ class SeasonBase: @staticmethod def current_year() -> int: """Returns the current year.""" - return datetime.date.today().year @classmethod @@ -101,7 +97,6 @@ class SeasonBase: If no start_date was defined, returns the minimum datetime to ensure it's always below checked dates. """ - if not cls.start_date: return datetime.datetime.min return datetime.datetime.strptime(f"{cls.start_date}/{cls.current_year()}", cls.date_format) @@ -113,7 +108,6 @@ class SeasonBase: If no end_date was defined, returns the minimum datetime to ensure it's always above checked dates. """ - if not cls.end_date: return datetime.datetime.max return datetime.datetime.strptime(f"{cls.end_date}/{cls.current_year()}", cls.date_format) @@ -121,13 +115,11 @@ class SeasonBase: @classmethod def is_between_dates(cls, date: datetime.datetime) -> bool: """Determines if the given date falls between the season's date range.""" - return cls.start() <= date <= cls.end() @property def name_clean(self) -> str: """Return the Season's name with underscores replaced by whitespace.""" - return self.name.replace("_", " ").title() @property @@ -138,7 +130,6 @@ class SeasonBase: It's recommended to define one in most cases by overwriting this as a normal attribute in the inheriting class. """ - return f"New Season, {self.name_clean}!" async def get_icon(self, avatar: bool = False) -> bytes: @@ -151,7 +142,6 @@ class SeasonBase: including the starting slash. e.g. `/logos/logo_seasonal/valentines/loved_up.png` """ - if avatar: icon = self.bot_icon or self.icon else: @@ -171,7 +161,6 @@ class SeasonBase: Returns False if it failed to change the username, falling back to nick. Returns None if `debug` was True and username change wasn't attempted. """ - guild = bot.get_guild(Client.guild) result = None @@ -183,12 +172,12 @@ class SeasonBase: else: if bot.user.name != self.bot_name: - # attempt to change user details + # Attempt to change user details log.debug(f"Changing username to {self.bot_name}") with contextlib.suppress(discord.HTTPException): await bot.user.edit(username=self.bot_name) - # fallback on nickname if failed due to ratelimit + # Fallback on nickname if failed due to ratelimit if bot.user.name != self.bot_name: log.warning(f"Username failed to change: Changing nickname to {self.bot_name}") await guild.me.edit(nick=self.bot_name) @@ -196,7 +185,7 @@ class SeasonBase: else: result = True - # remove nickname if an old one exists + # Remove nickname if an old one exists if guild.me.nick and guild.me.nick != self.bot_name: log.debug(f"Clearing old nickname of {guild.me.nick}") await guild.me.edit(nick=None) @@ -209,11 +198,10 @@ class SeasonBase: Returns True if successful. """ - - # track old avatar hash for later comparison + # Track old avatar hash for later comparison old_avatar = bot.user.avatar - # attempt the change + # Attempt the change log.debug(f"Changing avatar to {self.bot_icon or self.icon}") icon = await self.get_icon(avatar=True) with contextlib.suppress(discord.HTTPException, asyncio.TimeoutError): @@ -233,13 +221,12 @@ class SeasonBase: Returns True if was successful. """ - guild = bot.get_guild(Client.guild) - # track old icon hash for later comparison + # Track old icon hash for later comparison old_icon = guild.icon - # attempt the change + # Attempt the change log.debug(f"Changing server icon to {self.icon}") icon = await self.get_icon() with contextlib.suppress(discord.HTTPException, asyncio.TimeoutError): @@ -260,8 +247,7 @@ class SeasonBase: It will skip the announcement if the current active season is the "evergreen" default season. """ - - # don't actually announce if reverting to normal season + # Don't actually announce if reverting to normal season if self.name == "evergreen": log.debug(f"Season Changed: {self.name}") return @@ -270,11 +256,11 @@ class SeasonBase: channel = guild.get_channel(Channels.announcements) mention = f"<@&{Roles.announcements}>" - # build cog info output + # Build cog info output doc = inspect.getdoc(self) announce = "\n\n".join(l.replace("\n", " ") for l in doc.split("\n\n")) - # no announcement message found + # No announcement message found if not doc: return @@ -284,7 +270,7 @@ class SeasonBase: if self.icon: embed.set_image(url=ICON_BASE_URL+self.icon) - # find any seasonal commands + # Find any seasonal commands cogs = [] for cog in bot.cogs.values(): if "evergreen" in cog.__module__: @@ -317,7 +303,6 @@ class SeasonBase: If in debug mode, the avatar, server icon, and announcement will be skipped. """ - # Prepare all the seasonal cogs, and then the evergreen ones. extensions = [] for ext_folder in {self.name, "evergreen"}: @@ -371,13 +356,12 @@ class SeasonManager(commands.Cog): async def load_seasons(self): """Asynchronous timer loop to check for a new season every midnight.""" - await self.bot.wait_until_ready() await self.season.load() while True: - await asyncio.sleep(self.sleep_time) # sleep until midnight - self.sleep_time = 86400 # next time, sleep for 24 hours. + await asyncio.sleep(self.sleep_time) # Sleep until midnight + self.sleep_time = 86400 # Next time, sleep for 24 hours. # If the season has changed, load it. new_season = get_season(date=datetime.datetime.utcnow()) @@ -388,7 +372,6 @@ class SeasonManager(commands.Cog): @commands.command(name="season") async def change_season(self, ctx, new_season: str): """Changes the currently active season on the bot.""" - self.season = get_season(season_name=new_season) await self.season.load() await ctx.send(f"Season changed to {new_season}.") @@ -397,8 +380,7 @@ class SeasonManager(commands.Cog): @commands.command(name="seasons") async def show_seasons(self, ctx): """Shows the available seasons and their dates.""" - - # sort by start order, followed by lower duration + # Sort by start order, followed by lower duration def season_key(season_class: Type[SeasonBase]): return season_class.start(), season_class.end() - datetime.datetime.max @@ -420,11 +402,11 @@ class SeasonManager(commands.Cog): else: period = f"{start} to {end}" - # bold period if current date matches season date range + # Bold period if current date matches season date range is_current = season.is_between_dates(datetime.datetime.utcnow()) pdec = "**" if is_current else "" - # underline currently active season + # Underline currently active season is_active = current_season == season.name sdec = "__" if is_active else "" @@ -447,8 +429,7 @@ class SeasonManager(commands.Cog): @refresh.command(name="avatar") async def refresh_avatar(self, ctx): """Re-applies the bot avatar for the currently loaded season.""" - - # attempt the change + # Attempt the change is_changed = await self.season.apply_avatar() if is_changed: @@ -458,7 +439,7 @@ class SeasonManager(commands.Cog): colour = discord.Colour.red() title = "Avatar Failed to Refresh" - # report back details + # Report back details season_name = type(self.season).__name__ embed = discord.Embed( description=f"**Season:** {season_name}\n**Avatar:** {self.season.bot_icon or self.season.icon}", @@ -471,8 +452,7 @@ class SeasonManager(commands.Cog): @refresh.command(name="icon") async def refresh_server_icon(self, ctx): """Re-applies the server icon for the currently loaded season.""" - - # attempt the change + # Attempt the change is_changed = await self.season.apply_server_icon() if is_changed: @@ -482,7 +462,7 @@ class SeasonManager(commands.Cog): colour = discord.Colour.red() title = "Server Icon Failed to Refresh" - # report back details + # Report back details season_name = type(self.season).__name__ embed = discord.Embed( description=f"**Season:** {season_name}\n**Icon:** {self.season.icon}", @@ -495,11 +475,10 @@ class SeasonManager(commands.Cog): @refresh.command(name="username", aliases=("name",)) async def refresh_username(self, ctx): """Re-applies the bot username for the currently loaded season.""" - old_username = str(bot.user) old_display_name = ctx.guild.me.display_name - # attempt the change + # Attempt the change is_changed = await self.season.apply_username() if is_changed: @@ -511,7 +490,7 @@ class SeasonManager(commands.Cog): else: colour = discord.Colour.red() - # if None, it's because it wasn't meant to change username + # If None, it's because it wasn't meant to change username if is_changed is None: title = "Nickname Refreshed" else: @@ -520,7 +499,7 @@ class SeasonManager(commands.Cog): old_name = old_display_name new_name = self.season.bot_name - # report back details + # Report back details season_name = type(self.season).__name__ embed = discord.Embed( description=f"**Season:** {season_name}\n" @@ -535,10 +514,8 @@ class SeasonManager(commands.Cog): @commands.command() async def announce(self, ctx): """Announces the currently loaded season.""" - await self.season.announce_season() def cog_unload(self): """Cancel season-related tasks on cog unload.""" - self.season_task.cancel() diff --git a/bot/seasons/valentines/be_my_valentine.py b/bot/seasons/valentines/be_my_valentine.py index 55c4adb1..90e4d5db 100644 --- a/bot/seasons/valentines/be_my_valentine.py +++ b/bot/seasons/valentines/be_my_valentine.py @@ -25,7 +25,6 @@ class BeMyValentine(commands.Cog): @staticmethod def load_json(): """Load Valentines messages from the static resources.""" - p = Path('bot', 'resources', 'valentines', 'bemyvalentine_valentines.json') with p.open() as json_data: valentines = load(json_data) @@ -41,13 +40,11 @@ class BeMyValentine(commands.Cog): 1) use the command \".lovefest sub\" to get the lovefest role. 2) use the command \".lovefest unsub\" to get rid of the lovefest role. """ - await ctx.invoke(self.bot.get_command("help"), "lovefest") @lovefest_role.command(name="sub") async def add_role(self, ctx): """Adds the lovefest role.""" - user = ctx.author role = discord.utils.get(ctx.guild.roles, id=Lovefest.role_id) if Lovefest.role_id not in [role.id for role in ctx.message.author.roles]: @@ -59,7 +56,6 @@ class BeMyValentine(commands.Cog): @lovefest_role.command(name="unsub") async def remove_role(self, ctx): """Removes the lovefest role.""" - user = ctx.author role = discord.utils.get(ctx.guild.roles, id=Lovefest.role_id) if Lovefest.role_id not in [role.id for role in ctx.message.author.roles]: @@ -82,7 +78,6 @@ class BeMyValentine(commands.Cog): example: .bemyvalentine Iceman Hey I love you, wanna hang around ? (sends the custom message to Iceman) NOTE : AVOID TAGGING THE USER MOST OF THE TIMES.JUST TRIM THE '@' when using this command. """ - if ctx.guild is None: # This command should only be used in the server msg = "You are supposed to use this command in the server." @@ -132,7 +127,6 @@ class BeMyValentine(commands.Cog): example : .bemyvalentine secret Iceman#6508 Hey I love you, wanna hang around ? (sends the custom message to Iceman in DM making you anonymous) """ - if ctx.guild is not None: # This command is only DM specific msg = "You are not supposed to use this command in the server, DM the command to the bot." @@ -172,7 +166,6 @@ class BeMyValentine(commands.Cog): def valentine_check(self, valentine_type): """Return the appropriate Valentine type & title based on the invoking user's input.""" - if valentine_type is None: valentine, title = self.random_valentine() @@ -200,7 +193,6 @@ class BeMyValentine(commands.Cog): :param author: member who invoked the command :param members: list of discord.Member objects """ - if author in members: members.remove(author) @@ -209,14 +201,12 @@ class BeMyValentine(commands.Cog): @staticmethod def random_emoji(): """Return two random emoji from the module-defined constants.""" - EMOJI_1 = random.choice(HEART_EMOJIS) EMOJI_2 = random.choice(HEART_EMOJIS) return EMOJI_1, EMOJI_2 def random_valentine(self): """Grabs a random poem or a compliment (any message).""" - valentine_poem = random.choice(self.valentines['valentine_poems']) valentine_compliment = random.choice(self.valentines['valentine_compliments']) random_valentine = random.choice([valentine_compliment, valentine_poem]) @@ -228,19 +218,16 @@ class BeMyValentine(commands.Cog): def valentine_poem(self): """Grabs a random poem.""" - valentine_poem = random.choice(self.valentines['valentine_poems']) return valentine_poem def valentine_compliment(self): """Grabs a random compliment.""" - valentine_compliment = random.choice(self.valentines['valentine_compliments']) return valentine_compliment def setup(bot): """Be my Valentine Cog load.""" - bot.add_cog(BeMyValentine(bot)) log.info("BeMyValentine cog loaded") diff --git a/bot/seasons/valentines/lovecalculator.py b/bot/seasons/valentines/lovecalculator.py index cd684f9d..ca8eaaf6 100644 --- a/bot/seasons/valentines/lovecalculator.py +++ b/bot/seasons/valentines/lovecalculator.py @@ -49,41 +49,39 @@ class LoveCalculator(Cog): If only one argument is provided, the subject will become one of the helpers at random. """ - if whom is None: staff = ctx.guild.get_role(Roles.helpers).members whom = random.choice(staff) def normalize(arg): if isinstance(arg, Member): - # if we are given a member, return name#discrim without any extra changes + # If we are given a member, return name#discrim without any extra changes arg = str(arg) else: - # otherwise normalise case and remove any leading/trailing whitespace + # Otherwise normalise case and remove any leading/trailing whitespace arg = arg.strip().title() - # this has to be done manually to be applied to usernames + # This has to be done manually to be applied to usernames return clean_content(escape_markdown=True).convert(ctx, arg) who, whom = [await normalize(arg) for arg in (who, whom)] - # make sure user didn't provide something silly such as 10 spaces + # Make sure user didn't provide something silly such as 10 spaces if not (who and whom): raise BadArgument('Arguments be non-empty strings.') - # hash inputs to guarantee consistent results (hashing algorithm choice arbitrary) + # Hash inputs to guarantee consistent results (hashing algorithm choice arbitrary) # - # hashlib is used over the builtin hash() function - # to guarantee same result over multiple runtimes + # hashlib is used over the builtin hash() to guarantee same result over multiple runtimes m = hashlib.sha256(who.encode() + whom.encode()) - # mod 101 for [0, 100] + # Mod 101 for [0, 100] love_percent = sum(m.digest()) % 101 # We need the -1 due to how bisect returns the point # see the documentation for further detail # https://docs.python.org/3/library/bisect.html#bisect.bisect index = bisect.bisect(LOVE_DATA, (love_percent,)) - 1 - # we already have the nearest "fit" love level - # we only need the dict, so we can ditch the first element + # We already have the nearest "fit" love level + # We only need the dict, so we can ditch the first element _, data = LOVE_DATA[index] status = random.choice(data['titles']) @@ -102,6 +100,5 @@ class LoveCalculator(Cog): def setup(bot): """Love calculator Cog load.""" - bot.add_cog(LoveCalculator(bot)) log.info("LoveCalculator cog loaded") diff --git a/bot/seasons/valentines/movie_generator.py b/bot/seasons/valentines/movie_generator.py index a09a563f..fa5f236a 100644 --- a/bot/seasons/valentines/movie_generator.py +++ b/bot/seasons/valentines/movie_generator.py @@ -12,7 +12,7 @@ log = logging.getLogger(__name__) class RomanceMovieFinder(commands.Cog): - """A cog that returns a random romance movie suggestion to a user.""" + """A Cog that returns a random romance movie suggestion to a user.""" def __init__(self, bot): self.bot = bot @@ -20,8 +20,7 @@ class RomanceMovieFinder(commands.Cog): @commands.command(name="romancemovie") async def romance_movie(self, ctx): """Randomly selects a romance movie and displays information about it.""" - - # selecting a random int to parse it to the page parameter + # Selecting a random int to parse it to the page parameter random_page = random.randint(0, 20) # TMDB api params params = { @@ -33,13 +32,13 @@ class RomanceMovieFinder(commands.Cog): "page": random_page, "with_genres": "10749" } - # the api request url + # The api request url request_url = "https://api.themoviedb.org/3/discover/movie?" + parse.urlencode(params) async with self.bot.http_session.get(request_url) as resp: - # trying to load the json file returned from the api + # Trying to load the json file returned from the api try: data = await resp.json() - # selecting random result from results object in the json file + # Selecting random result from results object in the json file selected_movie = random.choice(data["results"]) embed = discord.Embed( @@ -60,6 +59,5 @@ class RomanceMovieFinder(commands.Cog): def setup(bot): """Romance movie Cog load.""" - bot.add_cog(RomanceMovieFinder(bot)) log.info("RomanceMovieFinder cog loaded") diff --git a/bot/seasons/valentines/myvalenstate.py b/bot/seasons/valentines/myvalenstate.py index 344f52f6..6a8d8b1d 100644 --- a/bot/seasons/valentines/myvalenstate.py +++ b/bot/seasons/valentines/myvalenstate.py @@ -23,7 +23,6 @@ class MyValenstate(commands.Cog): def levenshtein(self, source, goal): """Calculates the Levenshtein Distance between source and goal.""" - if len(source) < len(goal): return self.levenshtein(goal, source) if len(source) == 0: @@ -45,7 +44,6 @@ class MyValenstate(commands.Cog): @commands.command() async def myvalenstate(self, ctx, *, name=None): """Find the vacation spot(s) with the most matching characters to the invoking user.""" - eq_chars = collections.defaultdict(int) if name is None: author = ctx.message.author.name.lower().replace(' ', '') @@ -85,6 +83,5 @@ class MyValenstate(commands.Cog): def setup(bot): """Valenstate Cog load.""" - bot.add_cog(MyValenstate(bot)) log.info("MyValenstate cog loaded") diff --git a/bot/seasons/valentines/pickuplines.py b/bot/seasons/valentines/pickuplines.py index ad75c93f..00ed5453 100644 --- a/bot/seasons/valentines/pickuplines.py +++ b/bot/seasons/valentines/pickuplines.py @@ -27,7 +27,6 @@ class PickupLine(commands.Cog): Note that most of them are very cheesy. """ - random_line = random.choice(pickup_lines['lines']) embed = discord.Embed( title=':cheese: Your pickup line :cheese:', @@ -42,6 +41,5 @@ class PickupLine(commands.Cog): def setup(bot): """Pickup lines Cog load.""" - bot.add_cog(PickupLine(bot)) log.info('PickupLine cog loaded') diff --git a/bot/seasons/valentines/savethedate.py b/bot/seasons/valentines/savethedate.py index 281625a4..a2d9a22d 100644 --- a/bot/seasons/valentines/savethedate.py +++ b/bot/seasons/valentines/savethedate.py @@ -25,7 +25,6 @@ class SaveTheDate(commands.Cog): @commands.command() async def savethedate(self, ctx): """Gives you ideas for what to do on a date with your valentine.""" - random_date = random.choice(VALENTINES_DATES['ideas']) emoji_1 = random.choice(HEART_EMOJIS) emoji_2 = random.choice(HEART_EMOJIS) @@ -39,6 +38,5 @@ class SaveTheDate(commands.Cog): def setup(bot): """Save the date Cog Load.""" - bot.add_cog(SaveTheDate(bot)) log.info("SaveTheDate cog loaded") diff --git a/bot/seasons/valentines/valentine_zodiac.py b/bot/seasons/valentines/valentine_zodiac.py index 1700260e..7f78d3bc 100644 --- a/bot/seasons/valentines/valentine_zodiac.py +++ b/bot/seasons/valentines/valentine_zodiac.py @@ -15,7 +15,7 @@ HEART_EMOJIS = [":heart:", ":gift_heart:", ":revolving_hearts:", ":sparkling_hea class ValentineZodiac(commands.Cog): - """A cog that returns a counter compatible zodiac sign to the given user's zodiac sign.""" + """A Cog that returns a counter compatible zodiac sign to the given user's zodiac sign.""" def __init__(self, bot): self.bot = bot @@ -23,8 +23,7 @@ class ValentineZodiac(commands.Cog): @staticmethod def load_json(): - """Load Zodiac compatibility from static JSON resource.""" - + """Load zodiac compatibility from static JSON resource.""" p = Path('bot', 'resources', 'valentines', 'zodiac_compatibility.json') with p.open() as json_data: zodiacs = load(json_data) @@ -33,7 +32,6 @@ class ValentineZodiac(commands.Cog): @commands.command(name="partnerzodiac") async def counter_zodiac(self, ctx, zodiac_sign): """Provides a counter compatible zodiac sign to the given user's zodiac sign.""" - try: compatible_zodiac = random.choice(self.zodiacs[zodiac_sign.lower()]) except KeyError: @@ -55,7 +53,6 @@ class ValentineZodiac(commands.Cog): def setup(bot): - """Valentine Zodiac Cog load.""" - + """Valentine zodiac Cog load.""" bot.add_cog(ValentineZodiac(bot)) log.info("ValentineZodiac cog loaded") diff --git a/bot/seasons/valentines/whoisvalentine.py b/bot/seasons/valentines/whoisvalentine.py index 96d97e22..0a868fe6 100644 --- a/bot/seasons/valentines/whoisvalentine.py +++ b/bot/seasons/valentines/whoisvalentine.py @@ -23,7 +23,6 @@ class ValentineFacts(commands.Cog): @commands.command(aliases=('whoisvalentine', 'saint_valentine')) async def who_is_valentine(self, ctx): """Displays info about Saint Valentine.""" - embed = discord.Embed( title="Who is Saint Valentine?", description=FACTS['whois'], @@ -39,7 +38,6 @@ class ValentineFacts(commands.Cog): @commands.command() async def valentine_fact(self, ctx): """Shows a random fact about Valentine's Day.""" - embed = discord.Embed( title=choice(FACTS['titles']), description=choice(FACTS['text']), @@ -51,6 +49,5 @@ class ValentineFacts(commands.Cog): def setup(bot): """Who is Valentine Cog load.""" - bot.add_cog(ValentineFacts(bot)) log.info("ValentineFacts cog loaded") diff --git a/bot/utils/halloween/spookifications.py b/bot/utils/halloween/spookifications.py index 390cfa49..69b49919 100644 --- a/bot/utils/halloween/spookifications.py +++ b/bot/utils/halloween/spookifications.py @@ -13,7 +13,6 @@ def inversion(im): Returns an inverted image when supplied with an Image object. """ - im = im.convert('RGB') inv = ImageOps.invert(im) return inv @@ -21,7 +20,6 @@ def inversion(im): def pentagram(im): """Adds pentagram to the image.""" - im = im.convert('RGB') wt, ht = im.size penta = Image.open('bot/resources/halloween/bloody-pentagram.png') @@ -37,7 +35,6 @@ def bat(im): The bat silhoutte is of a size at least one-fifths that of the original image and may be rotated up to 90 degrees anti-clockwise. """ - im = im.convert('RGB') wt, ht = im.size bat = Image.open('bot/resources/halloween/bat-clipart.png') @@ -55,7 +52,6 @@ def bat(im): def get_random_effect(im): """Randomly selects and applies an effect.""" - effects = [inversion, pentagram, bat] effect = choice(effects) log.info("Spookyavatar's chosen effect: " + effect.__name__) |