From 734addece0491fe16656a787e5f032e8f7190168 Mon Sep 17 00:00:00 2001 From: AtieP Date: Mon, 28 Sep 2020 16:54:08 +0200 Subject: Add time utils --- bot/utils/time.py | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 bot/utils/time.py (limited to 'bot') diff --git a/bot/utils/time.py b/bot/utils/time.py new file mode 100644 index 00000000..3c57e126 --- /dev/null +++ b/bot/utils/time.py @@ -0,0 +1,84 @@ +import datetime + +from dateutil.relativedelta import relativedelta + + +# All these functions are from https://github.com/python-discord/bot/blob/master/bot/utils/time.py +def _stringify_time_unit(value: int, unit: str) -> str: + """ + Returns a string to represent a value and time unit, ensuring that it uses the right plural form of the unit. + + >>> _stringify_time_unit(1, "seconds") + "1 second" + >>> _stringify_time_unit(24, "hours") + "24 hours" + >>> _stringify_time_unit(0, "minutes") + "less than a minute" + """ + if unit == "seconds" and value == 0: + return "0 seconds" + elif value == 1: + return f"{value} {unit[:-1]}" + elif value == 0: + return f"less than a {unit[:-1]}" + else: + return f"{value} {unit}" + + +def humanize_delta(delta: relativedelta, precision: str = "seconds", max_units: int = 6) -> str: + """ + Returns a human-readable version of the relativedelta. + + precision specifies the smallest unit of time to include (e.g. "seconds", "minutes"). + max_units specifies the maximum number of units of time to include (e.g. 1 may include days but not hours). + """ + if max_units <= 0: + raise ValueError("max_units must be positive") + + units = ( + ("years", delta.years), + ("months", delta.months), + ("days", delta.days), + ("hours", delta.hours), + ("minutes", delta.minutes), + ("seconds", delta.seconds), + ) + + # Add the time units that are >0, but stop at accuracy or max_units. + time_strings = [] + unit_count = 0 + for unit, value in units: + if value: + time_strings.append(_stringify_time_unit(value, unit)) + unit_count += 1 + + if unit == precision or unit_count >= max_units: + break + + # Add the 'and' between the last two units, if necessary + if len(time_strings) > 1: + time_strings[-1] = f"{time_strings[-2]} and {time_strings[-1]}" + del time_strings[-2] + + # If nothing has been found, just make the value 0 precision, e.g. `0 days`. + if not time_strings: + humanized = _stringify_time_unit(0, precision) + else: + humanized = ", ".join(time_strings) + + return humanized + + +def time_since(past_datetime: datetime.datetime, precision: str = "seconds", max_units: int = 6) -> str: + """ + Takes a datetime and returns a human-readable string that describes how long ago that datetime was. + + precision specifies the smallest unit of time to include (e.g. "seconds", "minutes"). + max_units specifies the maximum number of units of time to include (e.g. 1 may include days but not hours). + """ + now = datetime.datetime.utcnow() + delta = abs(relativedelta(now, past_datetime)) + + humanized = humanize_delta(delta, precision, max_units) + + return f"{humanized} ago" -- cgit v1.2.3 From 9813bedd3945d5efb42c6e5ca61782604ae8a343 Mon Sep 17 00:00:00 2001 From: AtieP Date: Mon, 28 Sep 2020 16:55:11 +0200 Subject: Add emojis cog --- bot/exts/evergreen/emojis.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 bot/exts/evergreen/emojis.py (limited to 'bot') diff --git a/bot/exts/evergreen/emojis.py b/bot/exts/evergreen/emojis.py new file mode 100644 index 00000000..67331941 --- /dev/null +++ b/bot/exts/evergreen/emojis.py @@ -0,0 +1,39 @@ +import textwrap + +from discord import Color, Embed, Emoji +from discord.ext import commands + +from bot.utils.time import time_since + + +class Emojis(commands.Cog): + """Has commands related to emojis.""" + + @commands.group(name="emoji", invoke_without_command=True) + async def emojis_group(self, ctx: commands.Context, emoji: Emoji) -> None: + """A group of commands related to emojis.""" + # No parameters = same as invoking info subcommand + await ctx.invoke(self.info_command, emoji) + + @emojis_group.command(name="info") + async def info_command(self, ctx: commands.Context, emoji: Emoji) -> None: + """Returns relevant information about a Discord Emoji.""" + emoji_information = Embed( + title=f'Information about "{emoji.name}"', + description=textwrap.dedent(f""" + Name: {emoji.name} + Created: {time_since(emoji.created_at)} + ID: {emoji.id} + Emote source: [Link]({emoji.url}) + """), + color=Color.blurple() + ) + emoji_information.set_thumbnail( + url=str(emoji.url) + ) + await ctx.send(embed=emoji_information) + + +def setup(bot: commands.Bot) -> None: + """Add the Emojis cog into the bot.""" + bot.add_cog(Emojis()) -- cgit v1.2.3 From cb75d950183da1ed169141dbf95a732fed366450 Mon Sep 17 00:00:00 2001 From: AtieP Date: Mon, 28 Sep 2020 17:37:09 +0200 Subject: No need to typecast emoji.url to str --- bot/exts/evergreen/emojis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/emojis.py b/bot/exts/evergreen/emojis.py index 67331941..fb4c8a44 100644 --- a/bot/exts/evergreen/emojis.py +++ b/bot/exts/evergreen/emojis.py @@ -29,7 +29,7 @@ class Emojis(commands.Cog): color=Color.blurple() ) emoji_information.set_thumbnail( - url=str(emoji.url) + url=emoji.url ) await ctx.send(embed=emoji_information) -- cgit v1.2.3 From 68a7bb5f7c12bd167e7bb7fcbdb37e6f4cbd72a1 Mon Sep 17 00:00:00 2001 From: AtieP Date: Mon, 28 Sep 2020 18:45:29 +0200 Subject: Rename the last description line --- bot/exts/evergreen/emojis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/emojis.py b/bot/exts/evergreen/emojis.py index fb4c8a44..950ec245 100644 --- a/bot/exts/evergreen/emojis.py +++ b/bot/exts/evergreen/emojis.py @@ -24,7 +24,7 @@ class Emojis(commands.Cog): Name: {emoji.name} Created: {time_since(emoji.created_at)} ID: {emoji.id} - Emote source: [Link]({emoji.url}) + [Emoji source image]({emoji.url}) """), color=Color.blurple() ) -- cgit v1.2.3 From 2fd63f6a2813c99d7098e444c5a3145f916b2729 Mon Sep 17 00:00:00 2001 From: AtieP <62116490+AtieP@users.noreply.github.com> Date: Mon, 28 Sep 2020 19:11:42 +0200 Subject: Set precision to hours Co-authored-by: gustavwilliam <65498475+gustavwilliam@users.noreply.github.com> --- bot/exts/evergreen/emojis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/emojis.py b/bot/exts/evergreen/emojis.py index 950ec245..9f825e6d 100644 --- a/bot/exts/evergreen/emojis.py +++ b/bot/exts/evergreen/emojis.py @@ -22,7 +22,7 @@ class Emojis(commands.Cog): title=f'Information about "{emoji.name}"', description=textwrap.dedent(f""" Name: {emoji.name} - Created: {time_since(emoji.created_at)} + Created: {time_since(emoji.created_at, precision="hours")} ID: {emoji.id} [Emoji source image]({emoji.url}) """), -- cgit v1.2.3 From 931fb3ea4a6eb767864b33df5bd17cfb48e1b919 Mon Sep 17 00:00:00 2001 From: Will Da Silva Date: Sun, 4 Oct 2020 22:44:49 -0400 Subject: Verify channel constants on startup Closes #393 --- bot/bot.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/bot.py b/bot/bot.py index ffaf4284..92873ba4 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -45,7 +45,7 @@ class SeasonalBot(commands.Bot): connector=TCPConnector(resolver=AsyncResolver(), family=socket.AF_INET) ) self._guild_available = asyncio.Event() - + self.loop.create_task(self.check_channels()) self.loop.create_task(self.send_log("SeasonalBot", "Connected!")) @property @@ -149,6 +149,15 @@ class SeasonalBot(commands.Bot): log.info("Nickname set successfully") return True + async def check_channels(self) -> None: + await self.wait_until_guild_available() + all_channels = set(self.get_all_channels()) + for name, channel_id in vars(Channels).items(): + if name.startswith('_'): + continue + if channel_id not in all_channels: + log.error(f'Channel "{name}" with id {channel_id} missing') + async def send_log(self, title: str, details: str = None, *, icon: str = None) -> None: """Send an embed message to the devlog channel.""" await self.wait_until_guild_available() -- cgit v1.2.3 From b907c4cc6e943904e506ec49d3a28d98e9073625 Mon Sep 17 00:00:00 2001 From: Will Da Silva Date: Sun, 4 Oct 2020 22:47:16 -0400 Subject: Add docstring to check_channels --- bot/bot.py | 1 + 1 file changed, 1 insertion(+) (limited to 'bot') diff --git a/bot/bot.py b/bot/bot.py index 92873ba4..c004414e 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -150,6 +150,7 @@ class SeasonalBot(commands.Bot): return True async def check_channels(self) -> None: + """Verifies that all channel constants refer to channels which exist.""" await self.wait_until_guild_available() all_channels = set(self.get_all_channels()) for name, channel_id in vars(Channels).items(): -- cgit v1.2.3 From 7bec6f4e9423d8e5a797a2a6e73cd235e0a5f0cf Mon Sep 17 00:00:00 2001 From: Will Da Silva Date: Sun, 4 Oct 2020 22:53:04 -0400 Subject: Capitalize "ID" in error message --- bot/bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/bot.py b/bot/bot.py index c004414e..b486201e 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -157,7 +157,7 @@ class SeasonalBot(commands.Bot): if name.startswith('_'): continue if channel_id not in all_channels: - log.error(f'Channel "{name}" with id {channel_id} missing') + log.error(f'Channel "{name}" with ID {channel_id} missing') async def send_log(self, title: str, details: str = None, *, icon: str = None) -> None: """Send an embed message to the devlog channel.""" -- cgit v1.2.3 From 3616302122f72c19b6ab4877fdb6a5236967110d Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 19 Jan 2021 06:37:09 +0530 Subject: Add connect four cog supporting player vs player and player vs ai --- bot/exts/evergreen/connect_four.py | 377 +++++++++++++++++++++++++++++++++++++ 1 file changed, 377 insertions(+) create mode 100644 bot/exts/evergreen/connect_four.py (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py new file mode 100644 index 00000000..9519f124 --- /dev/null +++ b/bot/exts/evergreen/connect_four.py @@ -0,0 +1,377 @@ +import asyncio +import random +import typing +from functools import partial + +import discord +from discord.ext import commands + +EMOJIS = [":white_circle:", ":blue_circle:", ":red_circle:"] +NUMBERS = [ + ":one:", + ":two:", + ":three:", + ":four:", + ":five:", + ":six:", + ":seven:", + ":eight:", + ":nine:" +] +UNICODE_NUMBERS = [ + "\u0031\u20e3", + "\u0032\u20e3", + "\u0033\u20e3", + "\u0034\u20e3", + "\u0035\u20e3", + "\u0036\u20e3", + "\u0037\u20e3", + "\u0038\u20e3", + "\u0039\u20e3", +] +CROSS_EMOJI = "\u274e" +HAND_RAISED_EMOJI = "\U0001f64b" +Coordinate = typing.Optional[typing.Tuple[int, int]] + + +class Game: + """A Connect 4 Game.""" + + def __init__( + self, + bot: commands.Bot, + channel: discord.TextChannel, + player1: discord.Member, + player2: discord.Member = None, + size: int = 7, + ) -> None: + + self.bot = bot + self.channel = channel + self.player1 = player1 + self.player2 = player2 or AI(game=self) + + self.grid = self.generate_board(size) + self.grid_size = size + + self.unicode_numbers = UNICODE_NUMBERS[:self.grid_size] + + self.message = None + + self.turn = None + self.next = None + + @staticmethod + def generate_board(size: int) -> typing.List[typing.List[int]]: + """Generate the connect 4 board.""" + return [[0 for _ in range(size)] for _ in range(size)] + + async def print_grid(self) -> None: + """Formats and outputs the Connect Four grid to the channel.""" + rows = [" ".join(EMOJIS[s] for s in row) for row in self.grid] + first_row = " ".join(x for x in NUMBERS[:self.grid_size]) + formatted_grid = "\n".join([first_row] + rows) + embed = discord.Embed(title="Connect Four Board", description=formatted_grid) + + if self.message: + await self.message.edit(embed=embed) + else: + self.message = await self.channel.send(embed=embed) + for emoji in self.unicode_numbers: + await self.message.add_reaction(emoji) + + async def start_game(self) -> None: + """Begins the game.""" + self.turn, self.next = self.player1, self.player2 + + while True: + await self.print_grid() + if isinstance(self.turn, AI): + coords = self.turn.play() + else: + coords = await self.player_turn() + + if not coords: + return + + if self.check_win(coords, 1 if self.turn == self.player1 else 2): + if isinstance(self.turn, AI): + await self.channel.send(f"Game Over! {self.turn.mention} lost against AI") + else: + if isinstance(self.next, AI): + await self.channel.send(f"Game Over! {self.turn.mention} won against AI") + else: + await self.channel.send(f"Game Over! {self.turn.mention} won against {self.next.mention}") + await self.print_grid() + return + + self.turn, self.next = self.next, self.turn + + def predicate(self, reaction: discord.Reaction, user: discord.Member) -> bool: + """The predicate to check for the player's reaction.""" + return ( + reaction.message.id == self.message.id + and user.id == self.turn.id + and str(reaction.emoji) in self.unicode_numbers + ) + + async def player_turn(self) -> Coordinate: + """Initiate the player's turn.""" + message = await self.channel.send( + f"{self.turn.mention}, it's your turn! React with a column you want to place your token" + ) + player_num = 1 if self.turn == self.player1 else 2 + while True: + full_column = False + try: + reaction, user = await self.bot.wait_for("reaction_add", check=self.predicate, timeout=30.0) + except asyncio.TimeoutError: + await self.channel.send(f"{self.turn.mention}, you took too long. Game over!") + return + else: + await message.delete() + await self.message.remove_reaction(reaction, user) + column_num = self.unicode_numbers.index(str(reaction.emoji)) + + column = [row[column_num] for row in self.grid] + + for row_num, square in reversed(list(enumerate(column))): + if not square: + self.grid[row_num][column_num] = player_num + coords = row_num, column_num + break + else: + await self.channel.send(f"Column {column_num + 1} is full. Try again") + full_column = True + if not full_column: + break + return coords + + def check_win(self, coords: Coordinate, player_num: int) -> bool: + """Check that placing a counter here would cause the player to win.""" + vertical = [(-1, 0), (1, 0)] + horizontal = [(0, 1), (0, -1)] + forward_diag = [(-1, 1), (1, -1)] + backward_diag = [(-1, -1), (1, 1)] + axes = [vertical, horizontal, forward_diag, backward_diag] + + for axis in axes: + in_a_row = 1 # The initial counter that is compared to + for (row_incr, column_incr) in axis: + row, column = coords + row += row_incr + column += column_incr + + while 0 <= row < self.grid_size and 0 <= column < self.grid_size: + if self.grid[row][column] == player_num: + in_a_row += 1 + row += row_incr + column += column_incr + else: + break + if in_a_row >= 4: + return True + return False + + +class AI: + """The Computer Player for Single-Player games.""" + + def __init__(self, game: Game) -> None: + self.game = game + + def get_possible_places(self) -> typing.List[Coordinate]: + """Gets all the coordinates where the AI could possibly place a counter.""" + possible_coords = [] + for column_num in range(self.game.grid_size): + column = [row[column_num] for row in self.game.grid] + for row_num, square in reversed(list(enumerate(column))): + if not square: + possible_coords.append((row_num, column_num)) + break + return possible_coords + + def check_ai_win(self, coord_list: typing.List[Coordinate]) -> typing.Optional[Coordinate]: + """Check if placing a counter in any possible coordinate would cause the AI to win.""" + if random.randint(1, 10) == 1: # 10% chance of not winning + return + for coords in coord_list: + if self.game.check_win(coords, 2): + return coords + + def check_player_win(self, coord_list: typing.List[Coordinate]) -> typing.Optional[Coordinate]: + """Check if placing a counter in any possible coordinate would stop the player from winning.""" + if random.randint(1, 4) == 1: # 25% chance of not blocking the player + return + for coords in coord_list: + if self.game.check_win(coords, 1): + return coords + + @staticmethod + def random_coords(coord_list: typing.List[Coordinate]) -> Coordinate: + """Picks a random coordinate from the possible ones.""" + return random.choice(coord_list) + + def play(self) -> Coordinate: + """The AI's turn.""" + possible_coords = self.get_possible_places() + + coords = self.check_ai_win(possible_coords) # Win + if not coords: + coords = self.check_player_win(possible_coords) # Try to stop P1 from winning + if not coords: + coords = self.random_coords(possible_coords) + + row, column = coords + self.game.grid[row][column] = 2 + return coords + + +class ConnectFour(commands.Cog): + """Connect Four. The Classic Vertical Four-in-a-row Game!""" + + def __init__(self, bot: commands.Bot) -> None: + self.bot = bot + self.games: typing.List[Game] = [] + self.waiting: typing.List[discord.Member] = [] + + self.max_board_size = 9 + self.min_board_size = 5 + + def get_player( + self, + ctx: commands.Context, + announcement: discord.Message, + reaction: discord.Reaction, + user: discord.Member + ) -> bool: + """Predicate checking the criteria for the announcement message.""" + if self.already_playing(ctx.author): # If they've joined a game since requesting a player 2 + return True # Is dealt with later on + if ( + user.id not in (ctx.me.id, ctx.author.id) + and str(reaction.emoji) == HAND_RAISED_EMOJI + and reaction.message.id == announcement.id + ): + if self.already_playing(user): + self.bot.loop.create_task(ctx.send(f"{user.mention} You're already playing a game!")) + self.bot.loop.create_task(announcement.remove_reaction(reaction, user)) + return False + + if user in self.waiting: + self.bot.loop.create_task(ctx.send( + f"{user.mention} Please cancel your game first before joining another one." + )) + self.bot.loop.create_task(announcement.remove_reaction(reaction, user)) + return False + + return True + + if ( + user.id == ctx.author.id + and str(reaction.emoji) == CROSS_EMOJI + and reaction.message.id == announcement.id + ): + return True + return False + + def already_playing(self, player: discord.Member) -> bool: + """Check if someone is already in a game.""" + return any(player in (game.player1, game.player2) for game in self.games) + + async def _play_game(self, ctx: commands.Context, user: typing.Optional[discord.Member], board_size: int) -> None: + """Helper for playing a game of connect four.""" + try: + game = Game(self.bot, ctx.channel, ctx.author, user, size=board_size) + self.games.append(game) + await game.start_game() + self.games.remove(game) + except Exception: + # End the game in the event of an unforseen error so the players aren't stuck in a game + await ctx.send(f"{ctx.author.mention} {user.mention if user else ''} An error occurred. Game failed") + self.games.remove(game) + raise + + @commands.group(invoke_without_command=True, aliases=[ + "4inarow", "4-in-a-row", "4_in_a_row", "connect4", "connect-four", "connect_four" + ]) + @commands.guild_only() + async def connectfour(self, ctx: commands.Context, board_size: int = 7) -> None: + """ + Play the classic game of Connect Four with someone! + + Sets up a message waiting for someone else to react and play along. + The game will start once someone has reacted. + All inputs will be through reactions. + """ + if self.already_playing(ctx.author): + await ctx.send("You're already playing a game!") + return + + if ctx.author in self.waiting: + await ctx.send("You've already sent out a request for a player 2") + return + + if board_size > self.max_board_size or board_size < self.min_board_size: + await ctx.send(f"{board_size} is not a valid board size. A valid board size it " + f"between `{self.min_board_size}` to `{self.max_board_size}`") + return + + announcement = await ctx.send( + "**Connect Four**: A new game is about to start!\n" + f"Press {HAND_RAISED_EMOJI} to play against {ctx.author.mention}!\n" + f"(Cancel the game with {CROSS_EMOJI}.)" + ) + self.waiting.append(ctx.author) + await announcement.add_reaction(HAND_RAISED_EMOJI) + await announcement.add_reaction(CROSS_EMOJI) + + try: + reaction, user = await self.bot.wait_for( + "reaction_add", + check=partial(self.get_player, ctx, announcement), + timeout=60.0 + ) + except asyncio.TimeoutError: + self.waiting.remove(ctx.author) + await announcement.delete() + await ctx.send(f"{ctx.author.mention} Seems like there's no one here to play" + f"Use `{ctx.prefix}{ctx.invoked_with} ai` to play against a computer." + ) + return + + if str(reaction.emoji) == CROSS_EMOJI: + self.waiting.remove(ctx.author) + await announcement.delete() + await ctx.send(f"{ctx.author.mention} Game cancelled.") + return + + await announcement.delete() + self.waiting.remove(ctx.author) + if self.already_playing(ctx.author): + return + + await self._play_game(ctx, user, board_size) + + @connectfour.command(aliases=["AI", "CPU", "computer", "cpu", "Computer"]) + async def ai(self, ctx: commands.Context, board_size: int = 7) -> None: + """Play Connect Four against a computer player.""" + if self.already_playing(ctx.author): + await ctx.send("You're already playing a game!") + return + + if ctx.author in self.waiting: + await ctx.send("You've already sent out a request for a player 2") + return + + if board_size > self.max_board_size or board_size < self.min_board_size: + await ctx.send(f"{board_size} is not a valid board size. A valid board size it " + f"between `{self.min_board_size}` to `{self.max_board_size}`") + return + + await self._play_game(ctx, user=None, board_size=board_size) + + +def setup(bot: commands.Bot) -> None: + """Load ConnectFour Cog.""" + bot.add_cog(ConnectFour(bot)) -- cgit v1.2.3 From f44a39ddc14ee23dd9394deac4a90cf0300ebbab Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Wed, 20 Jan 2021 05:28:10 +0530 Subject: fix grammar and spacing --- bot/exts/evergreen/connect_four.py | 62 ++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 30 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 9519f124..2592bf3f 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -58,8 +58,8 @@ class Game: self.message = None - self.turn = None - self.next = None + self.player_active = None + self.player_inactive = None @staticmethod def generate_board(size: int) -> typing.List[typing.List[int]]: @@ -82,51 +82,51 @@ class Game: async def start_game(self) -> None: """Begins the game.""" - self.turn, self.next = self.player1, self.player2 + self.player_active, self.player_inactive = self.player1, self.player2 while True: await self.print_grid() - if isinstance(self.turn, AI): - coords = self.turn.play() + if isinstance(self.player_active, AI): + coords = self.player_active.play() else: coords = await self.player_turn() if not coords: return - if self.check_win(coords, 1 if self.turn == self.player1 else 2): - if isinstance(self.turn, AI): - await self.channel.send(f"Game Over! {self.turn.mention} lost against AI") + if self.check_win(coords, 1 if self.player_active == self.player1 else 2): + if isinstance(self.player_active, AI): + await self.channel.send(f"Game Over! {self.player_active.mention} lost against AI") else: - if isinstance(self.next, AI): - await self.channel.send(f"Game Over! {self.turn.mention} won against AI") + if isinstance(self.player_inactive, AI): + await self.channel.send(f"Game Over! {self.player_active.mention} won against AI") else: - await self.channel.send(f"Game Over! {self.turn.mention} won against {self.next.mention}") + await self.channel.send(f"Game Over! {self.player_active.mention} won against {self.player_inactive.mention}") await self.print_grid() return - self.turn, self.next = self.next, self.turn + self.player_active, self.player_inactive = self.player_inactive, self.player_active def predicate(self, reaction: discord.Reaction, user: discord.Member) -> bool: """The predicate to check for the player's reaction.""" return ( reaction.message.id == self.message.id - and user.id == self.turn.id + and user.id == self.player_active.id and str(reaction.emoji) in self.unicode_numbers ) async def player_turn(self) -> Coordinate: """Initiate the player's turn.""" message = await self.channel.send( - f"{self.turn.mention}, it's your turn! React with a column you want to place your token" + f"{self.turn.mention}, it's your turn! React with the column you want to place your token in." ) - player_num = 1 if self.turn == self.player1 else 2 + player_num = 1 if self.player_active == self.player1 else 2 while True: full_column = False try: reaction, user = await self.bot.wait_for("reaction_add", check=self.predicate, timeout=30.0) except asyncio.TimeoutError: - await self.channel.send(f"{self.turn.mention}, you took too long. Game over!") + await self.channel.send(f"{self.player_active.mention}, you took too long. Game over!") return else: await message.delete() @@ -156,7 +156,7 @@ class Game: axes = [vertical, horizontal, forward_diag, backward_diag] for axis in axes: - in_a_row = 1 # The initial counter that is compared to + counters_in_a_row = 1 # The initial counter that is compared to for (row_incr, column_incr) in axis: row, column = coords row += row_incr @@ -164,12 +164,12 @@ class Game: while 0 <= row < self.grid_size and 0 <= column < self.grid_size: if self.grid[row][column] == player_num: - in_a_row += 1 + counters_in_a_row += 1 row += row_incr column += column_incr else: break - if in_a_row >= 4: + if counters_in_a_row >= 4: return True return False @@ -287,16 +287,17 @@ class ConnectFour(commands.Cog): await game.start_game() self.games.remove(game) except Exception: - # End the game in the event of an unforseen error so the players aren't stuck in a game + # End the game in the event of an unforeseen error so the players aren't stuck in a game await ctx.send(f"{ctx.author.mention} {user.mention if user else ''} An error occurred. Game failed") self.games.remove(game) raise - @commands.group(invoke_without_command=True, aliases=[ - "4inarow", "4-in-a-row", "4_in_a_row", "connect4", "connect-four", "connect_four" - ]) + @commands.group( + invoke_without_command=True, + aliases=["4inarow", "connect4", "connectfour", "c4"] + ) @commands.guild_only() - async def connectfour(self, ctx: commands.Context, board_size: int = 7) -> None: + async def connect_four(self, ctx: commands.Context, board_size: int = 7) -> None: """ Play the classic game of Connect Four with someone! @@ -313,8 +314,8 @@ class ConnectFour(commands.Cog): return if board_size > self.max_board_size or board_size < self.min_board_size: - await ctx.send(f"{board_size} is not a valid board size. A valid board size it " - f"between `{self.min_board_size}` to `{self.max_board_size}`") + await ctx.send(f"{board_size} is not a valid board size. A valid board size is " + f"between `{self.min_board_size}` and `{self.max_board_size}`.") return announcement = await ctx.send( @@ -335,9 +336,10 @@ class ConnectFour(commands.Cog): except asyncio.TimeoutError: self.waiting.remove(ctx.author) await announcement.delete() - await ctx.send(f"{ctx.author.mention} Seems like there's no one here to play" - f"Use `{ctx.prefix}{ctx.invoked_with} ai` to play against a computer." - ) + await ctx.send( + f"{ctx.author.mention} Seems like there's no one here to play. " + f"Use `{ctx.prefix}{ctx.invoked_with} ai` to play against a computer." + ) return if str(reaction.emoji) == CROSS_EMOJI: @@ -353,7 +355,7 @@ class ConnectFour(commands.Cog): await self._play_game(ctx, user, board_size) - @connectfour.command(aliases=["AI", "CPU", "computer", "cpu", "Computer"]) + @connectfour.command(aliases=["bot", "computer", "cpu"]) async def ai(self, ctx: commands.Context, board_size: int = 7) -> None: """Play Connect Four against a computer player.""" if self.already_playing(ctx.author): -- cgit v1.2.3 From 24e7f9508b61675d17f8fabf58f2fef4e7f97084 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Wed, 20 Jan 2021 05:45:26 +0530 Subject: COrrect annotations and improve docstrings ; make code more pythonic --- bot/exts/evergreen/connect_four.py | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 2592bf3f..1d2c82a2 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -42,7 +42,7 @@ class Game: bot: commands.Bot, channel: discord.TextChannel, player1: discord.Member, - player2: discord.Member = None, + player2: typing.Optional[discord.Member], size: int = 7, ) -> None: @@ -64,7 +64,7 @@ class Game: @staticmethod def generate_board(size: int) -> typing.List[typing.List[int]]: """Generate the connect 4 board.""" - return [[0 for _ in range(size)] for _ in range(size)] + return [[0]*size]*size async def print_grid(self) -> None: """Formats and outputs the Connect Four grid to the channel.""" @@ -101,7 +101,9 @@ class Game: if isinstance(self.player_inactive, AI): await self.channel.send(f"Game Over! {self.player_active.mention} won against AI") else: - await self.channel.send(f"Game Over! {self.player_active.mention} won against {self.player_inactive.mention}") + await self.channel.send( + f"Game Over! {self.player_active.mention} won against {self.player_inactive.mention}" + ) await self.print_grid() return @@ -213,14 +215,22 @@ class AI: return random.choice(coord_list) def play(self) -> Coordinate: - """The AI's turn.""" + """ + Plays for the AI. + + Gets all possible coords, and determins the move: + 1. coords where it can win. + 2. coords where the player can win. + 3. Random coord + The first possible value is choosen. + """ possible_coords = self.get_possible_places() - coords = self.check_ai_win(possible_coords) # Win - if not coords: - coords = self.check_player_win(possible_coords) # Try to stop P1 from winning - if not coords: - coords = self.random_coords(possible_coords) + coords = ( + self.check_ai_win(possible_coords) + or self.check_player_win(possible_coords) + or self.random_coords(possible_coords) + ) row, column = coords self.game.grid[row][column] = 2 @@ -296,7 +306,6 @@ class ConnectFour(commands.Cog): invoke_without_command=True, aliases=["4inarow", "connect4", "connectfour", "c4"] ) - @commands.guild_only() async def connect_four(self, ctx: commands.Context, board_size: int = 7) -> None: """ Play the classic game of Connect Four with someone! @@ -313,7 +322,7 @@ class ConnectFour(commands.Cog): await ctx.send("You've already sent out a request for a player 2") return - if board_size > self.max_board_size or board_size < self.min_board_size: + if not self.min_board_size <= board_size <= self.max_board_size: await ctx.send(f"{board_size} is not a valid board size. A valid board size is " f"between `{self.min_board_size}` and `{self.max_board_size}`.") return @@ -355,7 +364,7 @@ class ConnectFour(commands.Cog): await self._play_game(ctx, user, board_size) - @connectfour.command(aliases=["bot", "computer", "cpu"]) + @connect_four.command(aliases=["bot", "computer", "cpu"]) async def ai(self, ctx: commands.Context, board_size: int = 7) -> None: """Play Connect Four against a computer player.""" if self.already_playing(ctx.author): -- cgit v1.2.3 From d1acfa3ecc37b63b21a1889d38ae1405b917238f Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Wed, 20 Jan 2021 07:02:08 +0530 Subject: Change Ai to bot's user and add stop game functionality, remove redundant code, and DRY --- bot/exts/evergreen/connect_four.py | 68 ++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 29 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 1d2c82a2..1e5d6fac 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -49,7 +49,7 @@ class Game: self.bot = bot self.channel = channel self.player1 = player1 - self.player2 = player2 or AI(game=self) + self.player2 = player2 or AI(self.bot, game=self) self.grid = self.generate_board(size) self.grid_size = size @@ -64,7 +64,7 @@ class Game: @staticmethod def generate_board(size: int) -> typing.List[typing.List[int]]: """Generate the connect 4 board.""" - return [[0]*size]*size + return [[0 for _ in range(size)] for _ in range(size)] async def print_grid(self) -> None: """Formats and outputs the Connect Four grid to the channel.""" @@ -79,6 +79,7 @@ class Game: self.message = await self.channel.send(embed=embed) for emoji in self.unicode_numbers: await self.message.add_reaction(emoji) + await self.message.add_reaction(CROSS_EMOJI) async def start_game(self) -> None: """Begins the game.""" @@ -96,10 +97,12 @@ class Game: if self.check_win(coords, 1 if self.player_active == self.player1 else 2): if isinstance(self.player_active, AI): - await self.channel.send(f"Game Over! {self.player_active.mention} lost against AI") + await self.channel.send(f"Game Over! {self.player_inactive.mention} lost against" + f" {self.bot.user.mention}") else: if isinstance(self.player_inactive, AI): - await self.channel.send(f"Game Over! {self.player_active.mention} won against AI") + await self.channel.send(f"Game Over! {self.player_active.mention} won against" + f" {self.bot.user.mention}") else: await self.channel.send( f"Game Over! {self.player_active.mention} won against {self.player_inactive.mention}" @@ -114,13 +117,13 @@ class Game: return ( reaction.message.id == self.message.id and user.id == self.player_active.id - and str(reaction.emoji) in self.unicode_numbers + and str(reaction.emoji) in (*self.unicode_numbers, CROSS_EMOJI) ) async def player_turn(self) -> Coordinate: """Initiate the player's turn.""" message = await self.channel.send( - f"{self.turn.mention}, it's your turn! React with the column you want to place your token in." + f"{self.player_active.mention}, it's your turn! React with the column you want to place your token in." ) player_num = 1 if self.player_active == self.player1 else 2 while True: @@ -131,6 +134,13 @@ class Game: await self.channel.send(f"{self.player_active.mention}, you took too long. Game over!") return else: + if str(reaction.emoji) == CROSS_EMOJI: + await message.delete() + await self.channel.send( + f"{user.mention} has abandoned the game :(" + ) + return + await message.delete() await self.message.remove_reaction(reaction, user) column_num = self.unicode_numbers.index(str(reaction.emoji)) @@ -179,8 +189,9 @@ class Game: class AI: """The Computer Player for Single-Player games.""" - def __init__(self, game: Game) -> None: + def __init__(self, bot: commands.Bot, game: Game) -> None: self.game = game + self.mention = bot.user.mention def get_possible_places(self) -> typing.List[Coordinate]: """Gets all the coordinates where the AI could possibly place a counter.""" @@ -248,6 +259,23 @@ class ConnectFour(commands.Cog): self.max_board_size = 9 self.min_board_size = 5 + async def check_author(self, ctx: commands.Context, board_size: int) -> bool: + """Check if the requester is free and the board size is correct.""" + if self.already_playing(ctx.author): + await ctx.send("You're already playing a game!") + return False + + if ctx.author in self.waiting: + await ctx.send("You've already sent out a request for a player 2") + return False + + if not self.min_board_size <= board_size <= self.max_board_size: + await ctx.send(f"{board_size} is not a valid board size. A valid board size is " + f"between `{self.min_board_size}` and `{self.max_board_size}`.") + return False + + return True + def get_player( self, ctx: commands.Context, @@ -314,17 +342,8 @@ class ConnectFour(commands.Cog): The game will start once someone has reacted. All inputs will be through reactions. """ - if self.already_playing(ctx.author): - await ctx.send("You're already playing a game!") - return - - if ctx.author in self.waiting: - await ctx.send("You've already sent out a request for a player 2") - return - - if not self.min_board_size <= board_size <= self.max_board_size: - await ctx.send(f"{board_size} is not a valid board size. A valid board size is " - f"between `{self.min_board_size}` and `{self.max_board_size}`.") + check_author_result = await self.check_author(ctx, board_size) + if not check_author_result: return announcement = await ctx.send( @@ -367,17 +386,8 @@ class ConnectFour(commands.Cog): @connect_four.command(aliases=["bot", "computer", "cpu"]) async def ai(self, ctx: commands.Context, board_size: int = 7) -> None: """Play Connect Four against a computer player.""" - if self.already_playing(ctx.author): - await ctx.send("You're already playing a game!") - return - - if ctx.author in self.waiting: - await ctx.send("You've already sent out a request for a player 2") - return - - if board_size > self.max_board_size or board_size < self.min_board_size: - await ctx.send(f"{board_size} is not a valid board size. A valid board size it " - f"between `{self.min_board_size}` to `{self.max_board_size}`") + check_author_result = await self.check_author(ctx, board_size) + if not check_author_result: return await self._play_game(ctx, user=None, board_size=board_size) -- cgit v1.2.3 From 46e594c390cce07f522329b5fc012b886bcdbb81 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Thu, 21 Jan 2021 07:40:53 +0530 Subject: Add loading message before finishing all reactions and improve embed title --- bot/exts/evergreen/connect_four.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 1e5d6fac..a4f29172 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -68,18 +68,24 @@ class Game: async def print_grid(self) -> None: """Formats and outputs the Connect Four grid to the channel.""" + title = ( + f'Connect 4: {self.player1.display_name}' + f'VS {self.player2.display_name}' + ) + rows = [" ".join(EMOJIS[s] for s in row) for row in self.grid] first_row = " ".join(x for x in NUMBERS[:self.grid_size]) formatted_grid = "\n".join([first_row] + rows) - embed = discord.Embed(title="Connect Four Board", description=formatted_grid) + embed = discord.Embed(title=title, description=formatted_grid) if self.message: await self.message.edit(embed=embed) else: - self.message = await self.channel.send(embed=embed) + self.message = await self.channel.send(content='Loading ....') for emoji in self.unicode_numbers: await self.message.add_reaction(emoji) await self.message.add_reaction(CROSS_EMOJI) + await self.message.edit(content=None, embed=embed) async def start_game(self) -> None: """Begins the game.""" -- cgit v1.2.3 From 089baf161da449995b475971c5e0689a5b24c7e8 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Thu, 21 Jan 2021 09:59:11 +0530 Subject: Improve embeds and docstrings --- bot/exts/evergreen/connect_four.py | 58 +++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 23 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index a4f29172..38647f8e 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -38,12 +38,12 @@ class Game: """A Connect 4 Game.""" def __init__( - self, - bot: commands.Bot, - channel: discord.TextChannel, - player1: discord.Member, - player2: typing.Optional[discord.Member], - size: int = 7, + self, + bot: commands.Bot, + channel: discord.TextChannel, + player1: discord.Member, + player2: typing.Optional[discord.Member], + size: int = 7, ) -> None: self.bot = bot @@ -70,7 +70,7 @@ class Game: """Formats and outputs the Connect Four grid to the channel.""" title = ( f'Connect 4: {self.player1.display_name}' - f'VS {self.player2.display_name}' + f'VS {self.bot.user.display_name if isinstance(self.player2, AI) else self.player2.display_name}' ) rows = [" ".join(EMOJIS[s] for s in row) for row in self.grid] @@ -211,16 +211,26 @@ class AI: return possible_coords def check_ai_win(self, coord_list: typing.List[Coordinate]) -> typing.Optional[Coordinate]: - """Check if placing a counter in any possible coordinate would cause the AI to win.""" - if random.randint(1, 10) == 1: # 10% chance of not winning + """ + Check AI win. + + Check if placing a counter in any possible coordinate would cause the AI to win + with 10% chance of not winning and returning None + """ + if random.randint(1, 10) == 1: return for coords in coord_list: if self.game.check_win(coords, 2): return coords def check_player_win(self, coord_list: typing.List[Coordinate]) -> typing.Optional[Coordinate]: - """Check if placing a counter in any possible coordinate would stop the player from winning.""" - if random.randint(1, 4) == 1: # 25% chance of not blocking the player + """ + Check Player win. + + Check if placing a counter in possible coordinates would stop the player + from winning with 25% of not blocking them and returning None. + """ + if random.randint(1, 4) == 1: return for coords in coord_list: if self.game.check_win(coords, 1): @@ -283,19 +293,20 @@ class ConnectFour(commands.Cog): return True def get_player( - self, - ctx: commands.Context, - announcement: discord.Message, - reaction: discord.Reaction, - user: discord.Member + self, + ctx: commands.Context, + announcement: discord.Message, + reaction: discord.Reaction, + user: discord.Member ) -> bool: """Predicate checking the criteria for the announcement message.""" if self.already_playing(ctx.author): # If they've joined a game since requesting a player 2 return True # Is dealt with later on + if ( - user.id not in (ctx.me.id, ctx.author.id) - and str(reaction.emoji) == HAND_RAISED_EMOJI - and reaction.message.id == announcement.id + user.id not in (ctx.me.id, ctx.author.id) + and str(reaction.emoji) == HAND_RAISED_EMOJI + and reaction.message.id == announcement.id ): if self.already_playing(user): self.bot.loop.create_task(ctx.send(f"{user.mention} You're already playing a game!")) @@ -312,9 +323,9 @@ class ConnectFour(commands.Cog): return True if ( - user.id == ctx.author.id - and str(reaction.emoji) == CROSS_EMOJI - and reaction.message.id == announcement.id + user.id == ctx.author.id + and str(reaction.emoji) == CROSS_EMOJI + and reaction.message.id == announcement.id ): return True return False @@ -333,7 +344,8 @@ class ConnectFour(commands.Cog): except Exception: # End the game in the event of an unforeseen error so the players aren't stuck in a game await ctx.send(f"{ctx.author.mention} {user.mention if user else ''} An error occurred. Game failed") - self.games.remove(game) + if game in self.games: + self.games.remove(game) raise @commands.group( -- cgit v1.2.3 From a972cd19e993e5ea9a1120432d7523329cb22d9b Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Thu, 21 Jan 2021 11:32:41 +0530 Subject: Add ability to get custom tokens from the bot --- bot/exts/evergreen/connect_four.py | 67 +++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 23 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 38647f8e..6ae14f53 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -6,7 +6,7 @@ from functools import partial import discord from discord.ext import commands -EMOJIS = [":white_circle:", ":blue_circle:", ":red_circle:"] +EMOJIS = None NUMBERS = [ ":one:", ":two:", @@ -38,12 +38,12 @@ class Game: """A Connect 4 Game.""" def __init__( - self, - bot: commands.Bot, - channel: discord.TextChannel, - player1: discord.Member, - player2: typing.Optional[discord.Member], - size: int = 7, + self, + bot: commands.Bot, + channel: discord.TextChannel, + player1: discord.Member, + player2: typing.Optional[discord.Member], + size: int = 7, ) -> None: self.bot = bot @@ -293,20 +293,20 @@ class ConnectFour(commands.Cog): return True def get_player( - self, - ctx: commands.Context, - announcement: discord.Message, - reaction: discord.Reaction, - user: discord.Member + self, + ctx: commands.Context, + announcement: discord.Message, + reaction: discord.Reaction, + user: discord.Member ) -> bool: """Predicate checking the criteria for the announcement message.""" if self.already_playing(ctx.author): # If they've joined a game since requesting a player 2 return True # Is dealt with later on if ( - user.id not in (ctx.me.id, ctx.author.id) - and str(reaction.emoji) == HAND_RAISED_EMOJI - and reaction.message.id == announcement.id + user.id not in (ctx.me.id, ctx.author.id) + and str(reaction.emoji) == HAND_RAISED_EMOJI + and reaction.message.id == announcement.id ): if self.already_playing(user): self.bot.loop.create_task(ctx.send(f"{user.mention} You're already playing a game!")) @@ -323,9 +323,9 @@ class ConnectFour(commands.Cog): return True if ( - user.id == ctx.author.id - and str(reaction.emoji) == CROSS_EMOJI - and reaction.message.id == announcement.id + user.id == ctx.author.id + and str(reaction.emoji) == CROSS_EMOJI + and reaction.message.id == announcement.id ): return True return False @@ -334,9 +334,18 @@ class ConnectFour(commands.Cog): """Check if someone is already in a game.""" return any(player in (game.player1, game.player2) for game in self.games) - async def _play_game(self, ctx: commands.Context, user: typing.Optional[discord.Member], board_size: int) -> None: + async def _play_game( + self, + ctx: commands.Context, + user: typing.Optional[discord.Member], + board_size: int, + emoji1: str, + emoji2: str + ) -> None: """Helper for playing a game of connect four.""" try: + global EMOJIS + EMOJIS = [":white_circle:", str(emoji1), str(emoji2)] game = Game(self.bot, ctx.channel, ctx.author, user, size=board_size) self.games.append(game) await game.start_game() @@ -352,7 +361,13 @@ class ConnectFour(commands.Cog): invoke_without_command=True, aliases=["4inarow", "connect4", "connectfour", "c4"] ) - async def connect_four(self, ctx: commands.Context, board_size: int = 7) -> None: + async def connect_four( + self, + ctx: commands.Context, + board_size: int = 7, + emoji1: str = ":blue_circle:", + emoji2: str = ":red_circle:" + ) -> None: """ Play the classic game of Connect Four with someone! @@ -399,16 +414,22 @@ class ConnectFour(commands.Cog): if self.already_playing(ctx.author): return - await self._play_game(ctx, user, board_size) + await self._play_game(ctx, user, board_size, emoji1, emoji2) @connect_four.command(aliases=["bot", "computer", "cpu"]) - async def ai(self, ctx: commands.Context, board_size: int = 7) -> None: + async def ai( + self, + ctx: commands.Context, + board_size: int = 7, + emoji1: str = ":blue_circle:", + emoji2: str = ":red_circle:" + ) -> None: """Play Connect Four against a computer player.""" check_author_result = await self.check_author(ctx, board_size) if not check_author_result: return - await self._play_game(ctx, user=None, board_size=board_size) + await self._play_game(ctx, None, board_size, emoji1, emoji2) def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From 8175bc0fbe1fad08372a27b1fb340baf8f20062b Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Thu, 21 Jan 2021 14:01:45 +0530 Subject: Remove redundant code --- bot/exts/evergreen/connect_four.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 6ae14f53..e6d4b41a 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -133,7 +133,6 @@ class Game: ) player_num = 1 if self.player_active == self.player1 else 2 while True: - full_column = False try: reaction, user = await self.bot.wait_for("reaction_add", check=self.predicate, timeout=30.0) except asyncio.TimeoutError: @@ -149,21 +148,15 @@ class Game: await message.delete() await self.message.remove_reaction(reaction, user) - column_num = self.unicode_numbers.index(str(reaction.emoji)) + column_num = self.unicode_numbers.index(str(reaction.emoji)) column = [row[column_num] for row in self.grid] for row_num, square in reversed(list(enumerate(column))): if not square: self.grid[row_num][column_num] = player_num - coords = row_num, column_num - break - else: - await self.channel.send(f"Column {column_num + 1} is full. Try again") - full_column = True - if not full_column: - break - return coords + return row_num, column_num + message = await self.channel.send(f"Column {column_num + 1} is full. Try again") def check_win(self, coords: Coordinate, player_num: int) -> bool: """Check that placing a counter here would cause the player to win.""" -- cgit v1.2.3 From 35b2984674c3a1645476a8c2172deadd51472f0f Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Thu, 21 Jan 2021 14:14:15 +0530 Subject: Check if the emoji given by user is available --- bot/exts/evergreen/connect_four.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index e6d4b41a..a44d6dbf 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -358,8 +358,8 @@ class ConnectFour(commands.Cog): self, ctx: commands.Context, board_size: int = 7, - emoji1: str = ":blue_circle:", - emoji2: str = ":red_circle:" + emoji1: discord.Emoji = ":blue_circle:", + emoji2: discord.Emoji = ":red_circle:" ) -> None: """ Play the classic game of Connect Four with someone! @@ -407,6 +407,9 @@ class ConnectFour(commands.Cog): if self.already_playing(ctx.author): return + emoji1 = str(emoji1) + emoji2 = str(emoji2) + await self._play_game(ctx, user, board_size, emoji1, emoji2) @connect_four.command(aliases=["bot", "computer", "cpu"]) @@ -414,14 +417,17 @@ class ConnectFour(commands.Cog): self, ctx: commands.Context, board_size: int = 7, - emoji1: str = ":blue_circle:", - emoji2: str = ":red_circle:" + emoji1: discord.Emoji = ":blue_circle:", + emoji2: discord.Emoji = ":red_circle:" ) -> None: """Play Connect Four against a computer player.""" check_author_result = await self.check_author(ctx, board_size) if not check_author_result: return + emoji1 = str(emoji1) + emoji2 = str(emoji2) + await self._play_game(ctx, None, board_size, emoji1, emoji2) -- cgit v1.2.3 From db53775344e0ceef247fb0e045bc515c9d9591b8 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sat, 23 Jan 2021 05:35:09 +0530 Subject: Fix user given emoji check --- bot/exts/evergreen/connect_four.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index a44d6dbf..be370a83 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -6,7 +6,7 @@ from functools import partial import discord from discord.ext import commands -EMOJIS = None +EMOJI_TOKENS = [":white_circle:", ":blue_circle:", ":red_circle:"] NUMBERS = [ ":one:", ":two:", @@ -32,6 +32,7 @@ UNICODE_NUMBERS = [ CROSS_EMOJI = "\u274e" HAND_RAISED_EMOJI = "\U0001f64b" Coordinate = typing.Optional[typing.Tuple[int, int]] +EMOJI_CHECK = typing.Union[discord.Emoji, str] class Game: @@ -336,9 +337,10 @@ class ConnectFour(commands.Cog): emoji2: str ) -> None: """Helper for playing a game of connect four.""" + global EMOJIS + EMOJIS = [":white_circle:", str(emoji1), str(emoji2)] + try: - global EMOJIS - EMOJIS = [":white_circle:", str(emoji1), str(emoji2)] game = Game(self.bot, ctx.channel, ctx.author, user, size=board_size) self.games.append(game) await game.start_game() @@ -358,8 +360,8 @@ class ConnectFour(commands.Cog): self, ctx: commands.Context, board_size: int = 7, - emoji1: discord.Emoji = ":blue_circle:", - emoji2: discord.Emoji = ":red_circle:" + emoji1: EMOJI_CHECK = ":blue_circle:", + emoji2: EMOJI_CHECK = ":red_circle:" ) -> None: """ Play the classic game of Connect Four with someone! @@ -368,6 +370,11 @@ class ConnectFour(commands.Cog): The game will start once someone has reacted. All inputs will be through reactions. """ + if isinstance(emoji1, str) and len(emoji1) > 1: + raise commands.EmojiNotFound(emoji1) + if isinstance(emoji2, str) and len(emoji2) > 1: + raise commands.EmojiNotFound(emoji2) + check_author_result = await self.check_author(ctx, board_size) if not check_author_result: return @@ -407,28 +414,22 @@ class ConnectFour(commands.Cog): if self.already_playing(ctx.author): return - emoji1 = str(emoji1) - emoji2 = str(emoji2) - - await self._play_game(ctx, user, board_size, emoji1, emoji2) + await self._play_game(ctx, user, board_size, str(emoji1), str(emoji2)) @connect_four.command(aliases=["bot", "computer", "cpu"]) async def ai( self, ctx: commands.Context, board_size: int = 7, - emoji1: discord.Emoji = ":blue_circle:", - emoji2: discord.Emoji = ":red_circle:" + emoji1: EMOJI_CHECK = ":blue_circle:" ) -> None: """Play Connect Four against a computer player.""" + if isinstance(emoji1, str) and len(emoji1) > 1: + raise commands.EmojiNotFound(emoji1) check_author_result = await self.check_author(ctx, board_size) if not check_author_result: return - - emoji1 = str(emoji1) - emoji2 = str(emoji2) - - await self._play_game(ctx, None, board_size, emoji1, emoji2) + await self._play_game(ctx, None, board_size, str(emoji1), ":red_circle:") def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From 9b62d84554fe8a27e3baef5e73eaac9127b2e54d Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sat, 23 Jan 2021 17:39:51 +0530 Subject: Add ability to automatically send issues if matching # --- bot/exts/evergreen/issues.py | 96 +++++++++++++++++++++++++++++++------------- 1 file changed, 69 insertions(+), 27 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index e419a6f5..b701346c 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -1,5 +1,7 @@ import logging import random +import re +import typing as t import discord from discord.ext import commands @@ -13,9 +15,7 @@ BAD_RESPONSE = { 404: "Issue/pull request not located! Please enter a valid number!", 403: "Rate limit has been hit! Please try again later!" } - MAX_REQUESTS = 10 - REQUEST_HEADERS = dict() if GITHUB_TOKEN := Tokens.github: REQUEST_HEADERS["Authorization"] = f"token {GITHUB_TOKEN}" @@ -27,31 +27,19 @@ class Issues(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot - @commands.command(aliases=("pr",)) - @override_in_channel(WHITELISTED_CHANNELS + (Channels.dev_contrib, Channels.dev_branding)) - async def issue( - self, - ctx: commands.Context, - numbers: commands.Greedy[int], - repository: str = "sir-lancebot", - user: str = "python-discord" - ) -> None: - """Command to retrieve issue(s) from a GitHub repository.""" + async def fetch_issues( + self, + numbers: set, + repository: str, + user: str + ) -> t.Union[str, list]: + """Retrieve issue(s) from a GitHub repository.""" links = [] - numbers = set(numbers) # Convert from list to set to remove duplicates, if any - if not numbers: - await ctx.invoke(self.bot.get_command('help'), 'issue') - return + return "Numbers not found." if len(numbers) > MAX_REQUESTS: - embed = discord.Embed( - title=random.choice(ERROR_REPLIES), - color=Colours.soft_red, - description=f"Too many issues/PRs! (maximum of {MAX_REQUESTS})" - ) - await ctx.send(embed=embed) - return + return "Max requests hit." for number in numbers: url = f"https://api.github.com/repos/{user}/{repository}/issues/{number}" @@ -63,7 +51,7 @@ class Issues(commands.Cog): if r.status in BAD_RESPONSE: log.warning(f"Received response {r.status} from: {url}") - return await ctx.send(f"[{str(r.status)}] #{number} {BAD_RESPONSE.get(r.status)}") + return f"[{str(r.status)}] #{number} {BAD_RESPONSE.get(r.status)}" # The initial API request is made to the issues API endpoint, which will return information # if the issue or PR is present. However, the scope of information returned for PRs differs @@ -92,15 +80,69 @@ class Issues(commands.Cog): issue_url = json_data.get("html_url") links.append([icon_url, f"[{repository}] #{number} {json_data.get('title')}", issue_url]) - # Issue/PR format: emoji to show if open/closed/merged, number and the title as a singular link. - description_list = ["{0} [{1}]({2})".format(*link) for link in links] + return links + + @staticmethod + def get_embed(result: list, user: str = "python-discord", repository: str = "") -> discord.Embed: + """Get Response Embed.""" + description_list = ["{0} [{1}]({2})".format(*link) for link in result] resp = discord.Embed( colour=Colours.bright_green, description='\n'.join(description_list) ) resp.set_author(name="GitHub", url=f"https://github.com/{user}/{repository}") - await ctx.send(embed=resp) + return resp + + @commands.command(aliases=("pr",)) + @override_in_channel(WHITELISTED_CHANNELS + (Channels.dev_contrib, Channels.dev_branding)) + async def issue( + self, + ctx: commands.Context, + numbers: commands.Greedy[int], + repository: str = "sir-lancebot", + user: str = "python-discord" + ) -> None: + """Command to retrieve issue(s) from a GitHub repository.""" + print(numbers) + result = await self.fetch_issues(set(numbers), repository, user) + + if result == "Numbers not found.": + await ctx.invoke(self.bot.get_command('help'), 'issue') + + elif result == "Max requests hit.": + embed = discord.Embed( + title=random.choice(ERROR_REPLIES), + color=Colours.soft_red, + description=f"Too many issues/PRs! (maximum of {MAX_REQUESTS})" + ) + await ctx.send(embed=embed) + + elif isinstance(result, list): + # Issue/PR format: emoji to show if open/closed/merged, number and the title as a singular link. + resp = self.get_embed(result, user, repository) + await ctx.send(embed=resp) + + elif isinstance(result, str): + await ctx.send(result) + + @commands.Cog.listener() + async def on_message(self, message: discord.Message) -> None: + """Command to retrieve issue(s) from a GitHub repository using automatic linking if matching #.""" + message_repo_issue_map = re.findall(r".+?(bot|meta|sir-lancebot|logcord)#(\d+)", message.content) + links = [] + + if message_repo_issue_map: + for repo_issue in message_repo_issue_map: + result = await self.fetch_issues({repo_issue[1]}, repo_issue[0], "python-discord") + if isinstance(result, list): + links.append(*result) + + if not links: + return + + resp = self.get_embed(links, "python-discord") + await message.channel.send(embed=resp) def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From f701e93cfb768f7a04c786437cdbe3a7105d4bc9 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sun, 24 Jan 2021 16:58:07 +0530 Subject: Send a message on draw (was catching a error earlier) ; Improve send game over (winner/loser) code ; add case_insensitive alias --- bot/exts/evergreen/connect_four.py | 57 ++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 27 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index be370a83..7c5261c5 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -71,7 +71,7 @@ class Game: """Formats and outputs the Connect Four grid to the channel.""" title = ( f'Connect 4: {self.player1.display_name}' - f'VS {self.bot.user.display_name if isinstance(self.player2, AI) else self.player2.display_name}' + f' VS {self.bot.user.display_name if isinstance(self.player2, AI) else self.player2.display_name}' ) rows = [" ".join(EMOJIS[s] for s in row) for row in self.grid] @@ -88,14 +88,23 @@ class Game: await self.message.add_reaction(CROSS_EMOJI) await self.message.edit(content=None, embed=embed) + async def game_over(self, winner: discord.user, loser: discord.user) -> None: + """Removes games from list of current games and announces to public chat.""" + await self.channel.send(f"Game Over! {winner.mention} won against {loser.mention}") + await self.print_grid() + async def start_game(self) -> None: """Begins the game.""" self.player_active, self.player_inactive = self.player1, self.player2 while True: await self.print_grid() + if isinstance(self.player_active, AI): coords = self.player_active.play() + if not coords: + await self.channel.send(f"Game Over! Its's A Draw :tada:") + await self.print_grid() else: coords = await self.player_turn() @@ -103,18 +112,10 @@ class Game: return if self.check_win(coords, 1 if self.player_active == self.player1 else 2): - if isinstance(self.player_active, AI): - await self.channel.send(f"Game Over! {self.player_inactive.mention} lost against" - f" {self.bot.user.mention}") - else: - if isinstance(self.player_inactive, AI): - await self.channel.send(f"Game Over! {self.player_active.mention} won against" - f" {self.bot.user.mention}") - else: - await self.channel.send( - f"Game Over! {self.player_active.mention} won against {self.player_inactive.mention}" - ) - await self.print_grid() + await self.game_over( + self.bot.user if isinstance(self.player_active, AI) else {self.player_active}, + self.bot.user if isinstance(self.player_inactive, AI) else {self.player_inactive}, + ) return self.player_active, self.player_inactive = self.player_inactive, self.player_active @@ -122,9 +123,9 @@ class Game: def predicate(self, reaction: discord.Reaction, user: discord.Member) -> bool: """The predicate to check for the player's reaction.""" return ( - reaction.message.id == self.message.id - and user.id == self.player_active.id - and str(reaction.emoji) in (*self.unicode_numbers, CROSS_EMOJI) + reaction.message.id == self.message.id + and user.id == self.player_active.id + and str(reaction.emoji) in (*self.unicode_numbers, CROSS_EMOJI) ) async def player_turn(self) -> Coordinate: @@ -142,9 +143,7 @@ class Game: else: if str(reaction.emoji) == CROSS_EMOJI: await message.delete() - await self.channel.send( - f"{user.mention} has abandoned the game :(" - ) + await self.channel.send(f"{self.player_active.user} surrendered. Game over!") return await message.delete() @@ -235,7 +234,7 @@ class AI: """Picks a random coordinate from the possible ones.""" return random.choice(coord_list) - def play(self) -> Coordinate: + def play(self) -> typing.Union[Coordinate, bool]: """ Plays for the AI. @@ -247,10 +246,13 @@ class AI: """ possible_coords = self.get_possible_places() + if not possible_coords: + return False + coords = ( - self.check_ai_win(possible_coords) - or self.check_player_win(possible_coords) - or self.random_coords(possible_coords) + self.check_ai_win(possible_coords) + or self.check_player_win(possible_coords) + or self.random_coords(possible_coords) ) row, column = coords @@ -354,14 +356,15 @@ class ConnectFour(commands.Cog): @commands.group( invoke_without_command=True, - aliases=["4inarow", "connect4", "connectfour", "c4"] + aliases=["4inarow", "connect4", "connectfour", "c4"], + case_insensitive=True ) async def connect_four( self, ctx: commands.Context, board_size: int = 7, - emoji1: EMOJI_CHECK = ":blue_circle:", - emoji2: EMOJI_CHECK = ":red_circle:" + emoji1: EMOJI_CHECK = "\U0001f535", + emoji2: EMOJI_CHECK = "\U0001f534" ) -> None: """ Play the classic game of Connect Four with someone! @@ -421,7 +424,7 @@ class ConnectFour(commands.Cog): self, ctx: commands.Context, board_size: int = 7, - emoji1: EMOJI_CHECK = ":blue_circle:" + emoji1: EMOJI_CHECK = "\U0001f535" ) -> None: """Play Connect Four against a computer player.""" if isinstance(emoji1, str) and len(emoji1) > 1: -- cgit v1.2.3 From 914f2a8340c8c5636589f4e11de880f48cac52e2 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sun, 24 Jan 2021 17:02:11 +0530 Subject: Fix lint issues --- bot/exts/evergreen/connect_four.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 7c5261c5..51d1adc3 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -103,7 +103,7 @@ class Game: if isinstance(self.player_active, AI): coords = self.player_active.play() if not coords: - await self.channel.send(f"Game Over! Its's A Draw :tada:") + await self.channel.send("Game Over! It's A Draw :tada:") await self.print_grid() else: coords = await self.player_turn() @@ -123,9 +123,9 @@ class Game: def predicate(self, reaction: discord.Reaction, user: discord.Member) -> bool: """The predicate to check for the player's reaction.""" return ( - reaction.message.id == self.message.id - and user.id == self.player_active.id - and str(reaction.emoji) in (*self.unicode_numbers, CROSS_EMOJI) + reaction.message.id == self.message.id + and user.id == self.player_active.id + and str(reaction.emoji) in (*self.unicode_numbers, CROSS_EMOJI) ) async def player_turn(self) -> Coordinate: @@ -250,9 +250,9 @@ class AI: return False coords = ( - self.check_ai_win(possible_coords) - or self.check_player_win(possible_coords) - or self.random_coords(possible_coords) + self.check_ai_win(possible_coords) + or self.check_player_win(possible_coords) + or self.random_coords(possible_coords) ) row, column = coords -- cgit v1.2.3 From 53af90f92258905c2bfc4c2db2341dfd1fdc0124 Mon Sep 17 00:00:00 2001 From: xithrius Date: Sun, 24 Jan 2021 06:52:15 -0800 Subject: Fixed linting errors. --- bot/bot.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/bot.py b/bot/bot.py index 112c9a48..81d59706 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -37,7 +37,6 @@ class Bot(commands.Bot): self.loop.create_task(self.check_channels()) self.loop.create_task(self.send_log(self.name, "Connected!")) - @property def member(self) -> Optional[discord.Member]: """Retrieves the guild member object for the bot.""" @@ -76,7 +75,7 @@ class Bot(commands.Bot): """Verifies that all channel constants refer to channels which exist.""" await self.wait_until_guild_available() all_channels = set(self.get_all_channels()) - for name, channel_id in vars(Channels).items(): + for name, channel_id in vars(constants.Channels).items(): if name.startswith('_'): continue if channel_id not in all_channels: -- cgit v1.2.3 From fbe073cb5e8dca831b4126c5b221844032870d26 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 26 Jan 2021 16:28:36 +0530 Subject: Add in codeblock check --- bot/exts/evergreen/issues.py | 48 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index b701346c..1924d822 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -4,7 +4,7 @@ import re import typing as t import discord -from discord.ext import commands +from discord.ext import commands, tasks from bot.constants import Channels, Colours, ERROR_REPLIES, Emojis, Tokens, WHITELISTED_CHANNELS from bot.utils.decorators import override_in_channel @@ -17,15 +17,43 @@ BAD_RESPONSE = { } MAX_REQUESTS = 10 REQUEST_HEADERS = dict() +PYDIS_REPOS = "https://api.github.com/orgs/python-discord/repos" + if GITHUB_TOKEN := Tokens.github: REQUEST_HEADERS["Authorization"] = f"token {GITHUB_TOKEN}" - class Issues(commands.Cog): """Cog that allows users to retrieve issues from GitHub.""" def __init__(self, bot: commands.Bot): self.bot = bot + self.repos = [] + self.get_pydis_repos.start() + + @tasks.loop(minutes=30) + async def get_pydis_repos(self) -> None: + async with self.bot.http_session.get(PYDIS_REPOS) as resp: + if resp.status == 200: + data = await resp.json() + for repo in data: + self.repos.append(repo["full_name"].split("/")[1]) + else: + log.debug(f"Failed to get latest Pydis repositories. Status code {resp.status}") + + @staticmethod + def check_in_block(message: discord.Message, repo_issue: str) -> bool: + block = ( + re.findall(r"```([\s\S]*)?```", message.content) + or re.findall(r"```*\n([\s\S]*)?\n```", message.content) + or re.findall(r"```*([\s\S]*)?\n```", message.content) + or re.findall(r"```*\n([\s\S]*)?```", message.content) + or re.findall(r"`([\s\S]*)?`", message.content) + ) + print(block) + + if "#".join(repo_issue.split(" ")) in "".join([*block]): + return True + return False async def fetch_issues( self, @@ -44,7 +72,7 @@ class Issues(commands.Cog): for number in numbers: url = f"https://api.github.com/repos/{user}/{repository}/issues/{number}" merge_url = f"https://api.github.com/repos/{user}/{repository}/pulls/{number}/merge" - + print(url) log.trace(f"Querying GH issues API: {url}") async with self.bot.http_session.get(url, headers=REQUEST_HEADERS) as r: json_data = await r.json() @@ -104,7 +132,6 @@ class Issues(commands.Cog): user: str = "python-discord" ) -> None: """Command to retrieve issue(s) from a GitHub repository.""" - print(numbers) result = await self.fetch_issues(set(numbers), repository, user) if result == "Numbers not found.": @@ -129,14 +156,19 @@ class Issues(commands.Cog): @commands.Cog.listener() async def on_message(self, message: discord.Message) -> None: """Command to retrieve issue(s) from a GitHub repository using automatic linking if matching #.""" - message_repo_issue_map = re.findall(r".+?(bot|meta|sir-lancebot|logcord)#(\d+)", message.content) + repo_regex = "|".join(repo for repo in self.repos) + message_repo_issue_map = re.findall(fr".+?({repo_regex})#(\d+)", message.content) links = [] if message_repo_issue_map: for repo_issue in message_repo_issue_map: - result = await self.fetch_issues({repo_issue[1]}, repo_issue[0], "python-discord") - if isinstance(result, list): - links.append(*result) + if self.check_in_block(message, " ".join([*repo_issue])): + print("in") + continue + else: + result = await self.fetch_issues({repo_issue[1]}, repo_issue[0], "python-discord") + if isinstance(result, list): + links.append(*result) if not links: return -- cgit v1.2.3 From 2dcdec0defb0f75478cd344cabd431d02b506741 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 26 Jan 2021 16:36:24 +0530 Subject: Remove debug code and add docstrings. --- bot/exts/evergreen/issues.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 1924d822..ba8a70cf 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -22,6 +22,7 @@ PYDIS_REPOS = "https://api.github.com/orgs/python-discord/repos" if GITHUB_TOKEN := Tokens.github: REQUEST_HEADERS["Authorization"] = f"token {GITHUB_TOKEN}" + class Issues(commands.Cog): """Cog that allows users to retrieve issues from GitHub.""" @@ -32,6 +33,7 @@ class Issues(commands.Cog): @tasks.loop(minutes=30) async def get_pydis_repos(self) -> None: + """Get all python-discord repositories on github.""" async with self.bot.http_session.get(PYDIS_REPOS) as resp: if resp.status == 200: data = await resp.json() @@ -42,6 +44,7 @@ class Issues(commands.Cog): @staticmethod def check_in_block(message: discord.Message, repo_issue: str) -> bool: + """Check whether the # is in codeblocks.""" block = ( re.findall(r"```([\s\S]*)?```", message.content) or re.findall(r"```*\n([\s\S]*)?\n```", message.content) @@ -49,7 +52,6 @@ class Issues(commands.Cog): or re.findall(r"```*\n([\s\S]*)?```", message.content) or re.findall(r"`([\s\S]*)?`", message.content) ) - print(block) if "#".join(repo_issue.split(" ")) in "".join([*block]): return True @@ -163,7 +165,6 @@ class Issues(commands.Cog): if message_repo_issue_map: for repo_issue in message_repo_issue_map: if self.check_in_block(message, " ".join([*repo_issue])): - print("in") continue else: result = await self.fetch_issues({repo_issue[1]}, repo_issue[0], "python-discord") -- cgit v1.2.3 From d80308f509489bfe6120020758721093af2df7f9 Mon Sep 17 00:00:00 2001 From: Shivansh-007 <69356296+Shivansh-007@users.noreply.github.com> Date: Tue, 26 Jan 2021 16:39:02 +0530 Subject: Remove debug code. Co-authored-by: Xithrius <15021300+Xithrius@users.noreply.github.com> --- bot/exts/evergreen/issues.py | 1 - 1 file changed, 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index ba8a70cf..946da354 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -74,7 +74,6 @@ class Issues(commands.Cog): for number in numbers: url = f"https://api.github.com/repos/{user}/{repository}/issues/{number}" merge_url = f"https://api.github.com/repos/{user}/{repository}/pulls/{number}/merge" - print(url) log.trace(f"Querying GH issues API: {url}") async with self.bot.http_session.get(url, headers=REQUEST_HEADERS) as r: json_data = await r.json() -- cgit v1.2.3 From ec45aac56861f3b7b8813957bf7e0e3a890fc44a Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 26 Jan 2021 16:54:30 +0530 Subject: Cache repo regex --- bot/exts/evergreen/issues.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index ba8a70cf..55bc8cf0 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -39,6 +39,7 @@ class Issues(commands.Cog): data = await resp.json() for repo in data: self.repos.append(repo["full_name"].split("/")[1]) + self.repo_regex = "|".join(repo for repo in self.repos) else: log.debug(f"Failed to get latest Pydis repositories. Status code {resp.status}") @@ -158,8 +159,7 @@ class Issues(commands.Cog): @commands.Cog.listener() async def on_message(self, message: discord.Message) -> None: """Command to retrieve issue(s) from a GitHub repository using automatic linking if matching #.""" - repo_regex = "|".join(repo for repo in self.repos) - message_repo_issue_map = re.findall(fr".+?({repo_regex})#(\d+)", message.content) + message_repo_issue_map = re.findall(fr".+?({self.repo_regex})#(\d+)", message.content) links = [] if message_repo_issue_map: -- cgit v1.2.3 From 65e5558df35892c2136f9182d07307b496582019 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 26 Jan 2021 16:56:18 +0530 Subject: Use list.extend while appending issue links --- bot/exts/evergreen/issues.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 55bc8cf0..724be737 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -169,7 +169,7 @@ class Issues(commands.Cog): else: result = await self.fetch_issues({repo_issue[1]}, repo_issue[0], "python-discord") if isinstance(result, list): - links.append(*result) + links.extend(result) if not links: return -- cgit v1.2.3 From d973c1266b93a5baeb32a2f04ed797b8d0f0cd1b Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 26 Jan 2021 17:07:48 +0530 Subject: Change PYDIS_REPOS to PYTHON_DISCORD_REPOS --- bot/exts/evergreen/issues.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 724be737..95187551 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -17,7 +17,7 @@ BAD_RESPONSE = { } MAX_REQUESTS = 10 REQUEST_HEADERS = dict() -PYDIS_REPOS = "https://api.github.com/orgs/python-discord/repos" +PYTHON_DISCORD_REPOS = "https://api.github.com/orgs/python-discord/repos" if GITHUB_TOKEN := Tokens.github: REQUEST_HEADERS["Authorization"] = f"token {GITHUB_TOKEN}" @@ -34,7 +34,7 @@ class Issues(commands.Cog): @tasks.loop(minutes=30) async def get_pydis_repos(self) -> None: """Get all python-discord repositories on github.""" - async with self.bot.http_session.get(PYDIS_REPOS) as resp: + async with self.bot.http_session.get(PYTHON_DISCORD_REPOS) as resp: if resp.status == 200: data = await resp.json() for repo in data: @@ -155,8 +155,9 @@ class Issues(commands.Cog): elif isinstance(result, str): await ctx.send(result) - + @commands.Cog.listener() + @override_in_channel(WHITELISTED_CHANNELS + (Channels.dev_contrib, Channels.dev_branding)) async def on_message(self, message: discord.Message) -> None: """Command to retrieve issue(s) from a GitHub repository using automatic linking if matching #.""" message_repo_issue_map = re.findall(fr".+?({self.repo_regex})#(\d+)", message.content) -- cgit v1.2.3 From 24f915bbe94452f80c7ab57b90b0f48d09e07e63 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 26 Jan 2021 17:13:12 +0530 Subject: Make the python_discord_repos' orgranisation name configurable --- bot/exts/evergreen/issues.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 95187551..d816770c 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -17,7 +17,7 @@ BAD_RESPONSE = { } MAX_REQUESTS = 10 REQUEST_HEADERS = dict() -PYTHON_DISCORD_REPOS = "https://api.github.com/orgs/python-discord/repos" +PYTHON_DISCORD_REPOS = "https://api.github.com/orgs/{repo}/repos" if GITHUB_TOKEN := Tokens.github: REQUEST_HEADERS["Authorization"] = f"token {GITHUB_TOKEN}" @@ -34,7 +34,7 @@ class Issues(commands.Cog): @tasks.loop(minutes=30) async def get_pydis_repos(self) -> None: """Get all python-discord repositories on github.""" - async with self.bot.http_session.get(PYTHON_DISCORD_REPOS) as resp: + async with self.bot.http_session.get(PYTHON_DISCORD_REPOS.format(repo="python-discord")) as resp: if resp.status == 200: data = await resp.json() for repo in data: @@ -155,7 +155,7 @@ class Issues(commands.Cog): elif isinstance(result, str): await ctx.send(result) - + @commands.Cog.listener() @override_in_channel(WHITELISTED_CHANNELS + (Channels.dev_contrib, Channels.dev_branding)) async def on_message(self, message: discord.Message) -> None: -- cgit v1.2.3 From b6cda1a14a2a2e69dac59de675cbea75638c3f64 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 26 Jan 2021 17:23:30 +0530 Subject: Use enums for fetch issue errors. --- bot/exts/evergreen/issues.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index d816770c..bd62fc22 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -2,6 +2,7 @@ import logging import random import re import typing as t +from enum import Enum import discord from discord.ext import commands, tasks @@ -23,6 +24,12 @@ if GITHUB_TOKEN := Tokens.github: REQUEST_HEADERS["Authorization"] = f"token {GITHUB_TOKEN}" +class FetchIssueErrors(Enum): + value_error = "Numbers not found." + max_requests = "Max requests hit." + + + class Issues(commands.Cog): """Cog that allows users to retrieve issues from GitHub.""" @@ -67,10 +74,10 @@ class Issues(commands.Cog): """Retrieve issue(s) from a GitHub repository.""" links = [] if not numbers: - return "Numbers not found." + return FetchIssueErrors.value_error if len(numbers) > MAX_REQUESTS: - return "Max requests hit." + return FetchIssueErrors.max_requests for number in numbers: url = f"https://api.github.com/repos/{user}/{repository}/issues/{number}" @@ -137,10 +144,10 @@ class Issues(commands.Cog): """Command to retrieve issue(s) from a GitHub repository.""" result = await self.fetch_issues(set(numbers), repository, user) - if result == "Numbers not found.": + if result == FetchIssueErrors.value_error: await ctx.invoke(self.bot.get_command('help'), 'issue') - elif result == "Max requests hit.": + elif result == FetchIssueErrors.max_requests: embed = discord.Embed( title=random.choice(ERROR_REPLIES), color=Colours.soft_red, -- cgit v1.2.3 From 9d5352fcf1c4b9d09d9aba9632689f54beeb4087 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 26 Jan 2021 17:24:26 +0530 Subject: Fix lint issues --- bot/exts/evergreen/issues.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index bd62fc22..d258cc3c 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -2,7 +2,7 @@ import logging import random import re import typing as t -from enum import Enum +from enum import Enum import discord from discord.ext import commands, tasks -- cgit v1.2.3 From 8b71066b6dd645918cdceef389eb98d334c62434 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 26 Jan 2021 17:27:32 +0530 Subject: Add docstring to FetchIssueErrors and remove extra new line --- bot/exts/evergreen/issues.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index d6790edf..c9f87957 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -25,11 +25,12 @@ if GITHUB_TOKEN := Tokens.github: class FetchIssueErrors(Enum): + """Errors returned in fetch issues.""" + value_error = "Numbers not found." max_requests = "Max requests hit." - class Issues(commands.Cog): """Cog that allows users to retrieve issues from GitHub.""" -- cgit v1.2.3 From d2f9aa0d2236426e88334483959938328950f357 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Wed, 27 Jan 2021 10:09:05 +0530 Subject: Improve code block regex --- bot/exts/evergreen/issues.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index c9f87957..d2c70d4b 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -23,6 +23,12 @@ PYTHON_DISCORD_REPOS = "https://api.github.com/orgs/{repo}/repos" if GITHUB_TOKEN := Tokens.github: REQUEST_HEADERS["Authorization"] = f"token {GITHUB_TOKEN}" +CODE_BLOCK_RE = re.compile( + r"^`([^`\n]+)`" # Inline codeblock + r"|```(.+?)```", # Multiline codeblock + re.DOTALL | re.MULTILINE +) + class FetchIssueErrors(Enum): """Errors returned in fetch issues.""" @@ -54,15 +60,11 @@ class Issues(commands.Cog): @staticmethod def check_in_block(message: discord.Message, repo_issue: str) -> bool: """Check whether the # is in codeblocks.""" - block = ( - re.findall(r"```([\s\S]*)?```", message.content) - or re.findall(r"```*\n([\s\S]*)?\n```", message.content) - or re.findall(r"```*([\s\S]*)?\n```", message.content) - or re.findall(r"```*\n([\s\S]*)?```", message.content) - or re.findall(r"`([\s\S]*)?`", message.content) - ) + block = re.findall(CODE_BLOCK_RE, message.content) - if "#".join(repo_issue.split(" ")) in "".join([*block]): + if not block: + return False + elif "#".join(repo_issue.split(" ")) in "".join([*block[0]]): return True return False -- cgit v1.2.3 From a7ffa0926b47bf40cd034eeb2b5e9d5dcd04798f Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Wed, 27 Jan 2021 10:43:19 +0530 Subject: Add check for in category and in remove overide_channel check and do it without decorator --- bot/constants.py | 8 ++++++++ bot/exts/evergreen/issues.py | 19 ++++++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index 1d41a53e..ce1ca29a 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -9,6 +9,7 @@ __all__ = ( "AdventOfCode", "Branding", "Channels", + "Categories", "Client", "Colours", "Emojis", @@ -100,6 +101,7 @@ class Channels(NamedTuple): big_brother_logs = 468507907357409333 bot = 267659945086812160 checkpoint_test = 422077681434099723 + organisation = 551789653284356126 devalerts = 460181980097675264 devlog = int(environ.get("CHANNEL_DEVLOG", 622895325144940554)) dev_contrib = 635950537262759947 @@ -128,6 +130,12 @@ class Channels(NamedTuple): voice_chat_1 = 799647045886541885 +class Categories(NamedTuple): + development = 411199786025484308 + devprojects = 787641585624940544 + media = 799054581991997460 + + class Client(NamedTuple): name = "Sir Lancebot" guild = int(environ.get("BOT_GUILD", 267624335836053506)) diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index d2c70d4b..4ab3df2c 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -7,8 +7,7 @@ from enum import Enum import discord from discord.ext import commands, tasks -from bot.constants import Channels, Colours, ERROR_REPLIES, Emojis, Tokens, WHITELISTED_CHANNELS -from bot.utils.decorators import override_in_channel +from bot.constants import Categories, Channels, Colours, ERROR_REPLIES, Emojis, Tokens, WHITELISTED_CHANNELS log = logging.getLogger(__name__) @@ -16,13 +15,19 @@ BAD_RESPONSE = { 404: "Issue/pull request not located! Please enter a valid number!", 403: "Rate limit has been hit! Please try again later!" } + MAX_REQUESTS = 10 REQUEST_HEADERS = dict() -PYTHON_DISCORD_REPOS = "https://api.github.com/orgs/{repo}/repos" +PYTHON_DISCORD_REPOS = "https://api.github.com/orgs/{repo}/repos" if GITHUB_TOKEN := Tokens.github: REQUEST_HEADERS["Authorization"] = f"token {GITHUB_TOKEN}" +WHITELISTED_CATEGORIES = ( + Categories.devprojects, Categories.media, Categories.development +) +WHITELISTED_CHANNELS += (Channels.organisation) + CODE_BLOCK_RE = re.compile( r"^`([^`\n]+)`" # Inline codeblock r"|```(.+?)```", # Multiline codeblock @@ -135,7 +140,6 @@ class Issues(commands.Cog): return resp @commands.command(aliases=("pr",)) - @override_in_channel(WHITELISTED_CHANNELS + (Channels.dev_contrib, Channels.dev_branding)) async def issue( self, ctx: commands.Context, @@ -144,6 +148,9 @@ class Issues(commands.Cog): user: str = "python-discord" ) -> None: """Command to retrieve issue(s) from a GitHub repository.""" + if ctx.channel.category not in WHITELISTED_CATEGORIES or ctx.channel.category in WHITELISTED_CHANNELS: + return + result = await self.fetch_issues(set(numbers), repository, user) if result == FetchIssueErrors.value_error: @@ -166,9 +173,11 @@ class Issues(commands.Cog): await ctx.send(result) @commands.Cog.listener() - @override_in_channel(WHITELISTED_CHANNELS + (Channels.dev_contrib, Channels.dev_branding)) async def on_message(self, message: discord.Message) -> None: """Command to retrieve issue(s) from a GitHub repository using automatic linking if matching #.""" + if message.channel.category not in WHITELISTED_CATEGORIES or message.channel.category in WHITELISTED_CHANNELS: + return + message_repo_issue_map = re.findall(fr".+?({self.repo_regex})#(\d+)", message.content) links = [] -- cgit v1.2.3 From 65260f66e6e7d3a9bff8b19c4a498643d2e664aa Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Wed, 27 Jan 2021 16:58:53 +0530 Subject: Fix return type annotations --- bot/exts/evergreen/issues.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 4ab3df2c..8b02e874 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -26,7 +26,7 @@ if GITHUB_TOKEN := Tokens.github: WHITELISTED_CATEGORIES = ( Categories.devprojects, Categories.media, Categories.development ) -WHITELISTED_CHANNELS += (Channels.organisation) +WHITELISTED_CHANNELS += Channels.organisation CODE_BLOCK_RE = re.compile( r"^`([^`\n]+)`" # Inline codeblock @@ -78,7 +78,7 @@ class Issues(commands.Cog): numbers: set, repository: str, user: str - ) -> t.Union[str, list]: + ) -> t.Union[FetchIssueErrors, str, list]: """Retrieve issue(s) from a GitHub repository.""" links = [] if not numbers: -- cgit v1.2.3 From 661ab2cc966c96d6f05dfc0444f7569b2a8fd727 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Thu, 28 Jan 2021 04:44:36 +0530 Subject: Add http status dog and add http_cat to group http_status --- bot/exts/evergreen/status_cats.py | 33 -------------------- bot/exts/evergreen/status_codes.py | 63 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 33 deletions(-) delete mode 100644 bot/exts/evergreen/status_cats.py create mode 100644 bot/exts/evergreen/status_codes.py (limited to 'bot') diff --git a/bot/exts/evergreen/status_cats.py b/bot/exts/evergreen/status_cats.py deleted file mode 100644 index 586b8378..00000000 --- a/bot/exts/evergreen/status_cats.py +++ /dev/null @@ -1,33 +0,0 @@ -from http import HTTPStatus - -import discord -from discord.ext import commands - - -class StatusCats(commands.Cog): - """Commands that give HTTP statuses described and visualized by cats.""" - - def __init__(self, bot: commands.Bot): - self.bot = bot - - @commands.command(aliases=['statuscat']) - async def http_cat(self, ctx: commands.Context, code: int) -> None: - """Sends an embed with an image of a cat, potraying the status code.""" - embed = discord.Embed(title=f'**Status: {code}**') - - try: - HTTPStatus(code) - - except ValueError: - embed.set_footer(text='Inputted status code does not exist.') - - else: - embed.set_image(url=f'https://http.cat/{code}.jpg') - - finally: - await ctx.send(embed=embed) - - -def setup(bot: commands.Bot) -> None: - """Load the StatusCats cog.""" - bot.add_cog(StatusCats(bot)) diff --git a/bot/exts/evergreen/status_codes.py b/bot/exts/evergreen/status_codes.py new file mode 100644 index 00000000..eebc23af --- /dev/null +++ b/bot/exts/evergreen/status_codes.py @@ -0,0 +1,63 @@ +import re +from http import HTTPStatus + +import discord +from discord import HTTPException +from discord.ext import commands + + +class StatusCats(commands.Cog): + """Commands that give HTTP statuses described and visualized by cats and dogs.""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + + @commands.group(name="http_status", aliases=("status", "httpstatus")) + async def http_status_group(self, ctx: commands.Context) -> None: + """Group containing dog and cat http status code commands.""" + if not ctx.invoked_subcommand: + await ctx.send_help(ctx.command) + + @http_status_group.command(aliases=['cat']) + async def http_cat(self, ctx: commands.Context, code: int) -> None: + """Sends an embed with an image of a cat, portraying the status code.""" + embed = discord.Embed(title=f'**Status: {code}**') + + try: + HTTPStatus(code) + + except ValueError: + embed.set_footer(text='Inputted status code does not exist.') + + else: + embed.set_image(url=f'https://http.cat/{code}.jpg') + + finally: + await ctx.send(embed=embed) + + @http_status_group.command(aliases=['dog']) + async def http_dog(self, ctx: commands.Context, code: int) -> None: + """Sends an embed with an image of a dog, portraying the status code.""" + embed = discord.Embed(title=f'**Status: {code}**') + + try: + HTTPStatus(code) + async with self.bot.http_session.get( + f'https://httpstatusdogs.com/img/{code}.jpg', + allow_redirects=False + ) as response: + if response.status != 302: + embed.set_image(url=f'https://httpstatusdogs.com/img/{code}.jpg') + else: + raise ValueError + + except ValueError: + embed.set_footer(text='Inputted status code does not exist.') + + finally: + await ctx.send(embed=embed) + + +def setup(bot: commands.Bot) -> None: + """Load the StatusCats cog.""" + bot.add_cog(StatusCats(bot)) -- cgit v1.2.3 From 0ae98d0d79c62cb71cc8287c0b391eef14f284ba Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sat, 30 Jan 2021 06:50:31 +0530 Subject: Fix channel and category check logic --- bot/exts/evergreen/issues.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 8b02e874..55ded054 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -26,7 +26,7 @@ if GITHUB_TOKEN := Tokens.github: WHITELISTED_CATEGORIES = ( Categories.devprojects, Categories.media, Categories.development ) -WHITELISTED_CHANNELS += Channels.organisation +WHITELISTED_CHANNELS_ON_MESSAGE = (Channels.organisation,) CODE_BLOCK_RE = re.compile( r"^`([^`\n]+)`" # Inline codeblock @@ -58,7 +58,7 @@ class Issues(commands.Cog): data = await resp.json() for repo in data: self.repos.append(repo["full_name"].split("/")[1]) - self.repo_regex = "|".join(repo for repo in self.repos) + self.repo_regex = "|".join(self.repos) else: log.debug(f"Failed to get latest Pydis repositories. Status code {resp.status}") @@ -148,7 +148,10 @@ class Issues(commands.Cog): user: str = "python-discord" ) -> None: """Command to retrieve issue(s) from a GitHub repository.""" - if ctx.channel.category not in WHITELISTED_CATEGORIES or ctx.channel.category in WHITELISTED_CHANNELS: + if not( + ctx.channel.category.id in WHITELISTED_CATEGORIES + or ctx.channel.id in WHITELISTED_CHANNELS + ): return result = await self.fetch_issues(set(numbers), repository, user) @@ -175,7 +178,10 @@ class Issues(commands.Cog): @commands.Cog.listener() async def on_message(self, message: discord.Message) -> None: """Command to retrieve issue(s) from a GitHub repository using automatic linking if matching #.""" - if message.channel.category not in WHITELISTED_CATEGORIES or message.channel.category in WHITELISTED_CHANNELS: + if not( + message.channel.category.id in WHITELISTED_CATEGORIES + or message.channel.id in WHITELISTED_CHANNELS_ON_MESSAGE + ): return message_repo_issue_map = re.findall(fr".+?({self.repo_regex})#(\d+)", message.content) @@ -183,9 +189,7 @@ class Issues(commands.Cog): if message_repo_issue_map: for repo_issue in message_repo_issue_map: - if self.check_in_block(message, " ".join([*repo_issue])): - continue - else: + if not self.check_in_block(message, " ".join([*repo_issue])): result = await self.fetch_issues({repo_issue[1]}, repo_issue[0], "python-discord") if isinstance(result, list): links.extend(result) -- cgit v1.2.3 From ac44307a4d4c7aabfafee0af89630a0f748fee00 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sat, 30 Jan 2021 17:19:22 +0530 Subject: Fix PYTHON_DISCORD_REPOS format variable name and give it a better name --- bot/exts/evergreen/issues.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 55ded054..72d88d04 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -19,7 +19,7 @@ BAD_RESPONSE = { MAX_REQUESTS = 10 REQUEST_HEADERS = dict() -PYTHON_DISCORD_REPOS = "https://api.github.com/orgs/{repo}/repos" +REPOS_API = "https://api.github.com/orgs/{org}/repos" if GITHUB_TOKEN := Tokens.github: REQUEST_HEADERS["Authorization"] = f"token {GITHUB_TOKEN}" @@ -53,7 +53,7 @@ class Issues(commands.Cog): @tasks.loop(minutes=30) async def get_pydis_repos(self) -> None: """Get all python-discord repositories on github.""" - async with self.bot.http_session.get(PYTHON_DISCORD_REPOS.format(repo="python-discord")) as resp: + async with self.bot.http_session.get(REPOS_API.format(org="python-discord")) as resp: if resp.status == 200: data = await resp.json() for repo in data: -- cgit v1.2.3 From a563d3ae23c1c1eff01a284e0510bdc364cc415a Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sat, 30 Jan 2021 17:21:11 +0530 Subject: Fix misleading game_over docstring --- bot/exts/evergreen/connect_four.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 51d1adc3..19067277 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -89,7 +89,7 @@ class Game: await self.message.edit(content=None, embed=embed) async def game_over(self, winner: discord.user, loser: discord.user) -> None: - """Removes games from list of current games and announces to public chat.""" + """Announces to public chat.""" await self.channel.send(f"Game Over! {winner.mention} won against {loser.mention}") await self.print_grid() -- cgit v1.2.3 From 79fb946c55b9f3049b0e2f0c5fd38f2ee2ee5add Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sat, 30 Jan 2021 17:22:45 +0530 Subject: Line 114, 115 was cuasing error as a set was being sent to it instead discord.member object --- bot/exts/evergreen/connect_four.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 19067277..858caf78 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -113,8 +113,8 @@ class Game: if self.check_win(coords, 1 if self.player_active == self.player1 else 2): await self.game_over( - self.bot.user if isinstance(self.player_active, AI) else {self.player_active}, - self.bot.user if isinstance(self.player_inactive, AI) else {self.player_inactive}, + self.bot.user if isinstance(self.player_active, AI) else self.player_active, + self.bot.user if isinstance(self.player_inactive, AI) else self.player_inactive, ) return -- cgit v1.2.3 From 9675434e1437b4c182e1eccbeeba9aa064ce779b Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sat, 30 Jan 2021 17:23:37 +0530 Subject: REmove repeating code --- bot/exts/evergreen/connect_four.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 858caf78..30eb0ff9 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -141,12 +141,11 @@ class Game: await self.channel.send(f"{self.player_active.mention}, you took too long. Game over!") return else: + await message.delete() if str(reaction.emoji) == CROSS_EMOJI: - await message.delete() await self.channel.send(f"{self.player_active.user} surrendered. Game over!") return - - await message.delete() + await self.message.remove_reaction(reaction, user) column_num = self.unicode_numbers.index(str(reaction.emoji)) -- cgit v1.2.3 From 630f46a197c89a137e89c0bba526090c8f0ace33 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sat, 30 Jan 2021 17:25:45 +0530 Subject: Error while sending surrender message as it was taking .user instead of .mention --- bot/exts/evergreen/connect_four.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 30eb0ff9..7ad0d723 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -82,7 +82,7 @@ class Game: if self.message: await self.message.edit(embed=embed) else: - self.message = await self.channel.send(content='Loading ....') + self.message = await self.channel.send(content='Loading...') for emoji in self.unicode_numbers: await self.message.add_reaction(emoji) await self.message.add_reaction(CROSS_EMOJI) @@ -143,7 +143,7 @@ class Game: else: await message.delete() if str(reaction.emoji) == CROSS_EMOJI: - await self.channel.send(f"{self.player_active.user} surrendered. Game over!") + await self.channel.send(f"{self.player_active.mention} surrendered. Game over!") return await self.message.remove_reaction(reaction, user) -- cgit v1.2.3 From 46ca17d5fe41e704e40e22839e9d8b21c9a7b659 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sun, 31 Jan 2021 04:55:57 +0530 Subject: Let game_over function handle all gane over instances --- bot/exts/evergreen/connect_four.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 7ad0d723..31b85bbe 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -88,9 +88,14 @@ class Game: await self.message.add_reaction(CROSS_EMOJI) await self.message.edit(content=None, embed=embed) - async def game_over(self, winner: discord.user, loser: discord.user) -> None: + async def game_over(self, action: str, player1: discord.user, player2: discord.user) -> None: """Announces to public chat.""" - await self.channel.send(f"Game Over! {winner.mention} won against {loser.mention}") + if action == "win": + await self.channel.send(f"Game Over! {player1.mention} won against {player2.mention}") + elif action == "draw": + await self.channel.send(f"Game Over! {player1.mention} {player2.mention} It's A Draw :tada:") + elif action == "quit": + await self.channel.send(f"{self.player1.mention} surrendered. Game over!") await self.print_grid() async def start_game(self) -> None: @@ -103,8 +108,11 @@ class Game: if isinstance(self.player_active, AI): coords = self.player_active.play() if not coords: - await self.channel.send("Game Over! It's A Draw :tada:") - await self.print_grid() + await self.game_over( + "draw", + self.bot.user if isinstance(self.player_active, AI) else self.player_active, + self.bot.user if isinstance(self.player_inactive, AI) else self.player_inactive, + ) else: coords = await self.player_turn() @@ -113,6 +121,7 @@ class Game: if self.check_win(coords, 1 if self.player_active == self.player1 else 2): await self.game_over( + "win", self.bot.user if isinstance(self.player_active, AI) else self.player_active, self.bot.user if isinstance(self.player_inactive, AI) else self.player_inactive, ) @@ -143,9 +152,9 @@ class Game: else: await message.delete() if str(reaction.emoji) == CROSS_EMOJI: - await self.channel.send(f"{self.player_active.mention} surrendered. Game over!") + await self.game_over("quit", self.player_active, self.player_inactive) return - + await self.message.remove_reaction(reaction, user) column_num = self.unicode_numbers.index(str(reaction.emoji)) -- cgit v1.2.3 From 259686206e71496131872788a746186ee34920d8 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sun, 31 Jan 2021 05:05:54 +0530 Subject: Add ability to choose ai token while playing against ai --- bot/exts/evergreen/connect_four.py | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 31b85bbe..50632c1b 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -338,6 +338,15 @@ class ConnectFour(commands.Cog): """Check if someone is already in a game.""" return any(player in (game.player1, game.player2) for game in self.games) + @staticmethod + def check_emojis(e1: EMOJI_CHECK, e2: EMOJI_CHECK) -> typing.Tuple[bool, typing.Optional[str]]: + """Validate the emojis, the user put.""" + if isinstance(e1, str) and len(e1) > 1: + return False, e1 + if isinstance(e2, str) and len(e2) > 1: + return False, e2 + return True, None + async def _play_game( self, ctx: commands.Context, @@ -381,10 +390,9 @@ class ConnectFour(commands.Cog): The game will start once someone has reacted. All inputs will be through reactions. """ - if isinstance(emoji1, str) and len(emoji1) > 1: - raise commands.EmojiNotFound(emoji1) - if isinstance(emoji2, str) and len(emoji2) > 1: - raise commands.EmojiNotFound(emoji2) + check, emoji = self.check_emojis(emoji1, emoji2) + if not check: + raise commands.EmojiNotFound(emoji) check_author_result = await self.check_author(ctx, board_size) if not check_author_result: @@ -432,15 +440,19 @@ class ConnectFour(commands.Cog): self, ctx: commands.Context, board_size: int = 7, - emoji1: EMOJI_CHECK = "\U0001f535" + emoji1: EMOJI_CHECK = "\U0001f535", + emoji2: EMOJI_CHECK = "\U0001f534" ) -> None: """Play Connect Four against a computer player.""" - if isinstance(emoji1, str) and len(emoji1) > 1: - raise commands.EmojiNotFound(emoji1) + check, emoji = self.check_emojis(emoji1, emoji2) + if not check: + raise commands.EmojiNotFound(emoji) + check_author_result = await self.check_author(ctx, board_size) if not check_author_result: return - await self._play_game(ctx, None, board_size, str(emoji1), ":red_circle:") + + await self._play_game(ctx, None, board_size, str(emoji1), str(emoji2)) def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From 45af7ff6803e75d70be8d78e232b3d30803ae65d Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sun, 31 Jan 2021 05:13:35 +0530 Subject: Add mod_meta and mod_tools channels to whitelisted --- bot/constants.py | 2 ++ bot/exts/evergreen/issues.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index ce1ca29a..1234ef3b 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -116,6 +116,8 @@ class Channels(NamedTuple): message_log = 467752170159079424 mod_alerts = 473092532147060736 modlog = 282638479504965634 + mod_meta = 775412552795947058 + mod_tools = 775413915391098921 off_topic_0 = 291284109232308226 off_topic_1 = 463035241142026251 off_topic_2 = 463035268514185226 diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 72d88d04..f24e0717 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -26,7 +26,7 @@ if GITHUB_TOKEN := Tokens.github: WHITELISTED_CATEGORIES = ( Categories.devprojects, Categories.media, Categories.development ) -WHITELISTED_CHANNELS_ON_MESSAGE = (Channels.organisation,) +WHITELISTED_CHANNELS_ON_MESSAGE = (Channels.organisation, Channels.mod_meta, Channels.mod_tools) CODE_BLOCK_RE = re.compile( r"^`([^`\n]+)`" # Inline codeblock -- cgit v1.2.3 From f5eae5bec548bc1e450af7f07387531b80869f84 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sun, 31 Jan 2021 05:26:23 +0530 Subject: Remove unused imports --- bot/exts/evergreen/status_codes.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/status_codes.py b/bot/exts/evergreen/status_codes.py index eebc23af..473e778c 100644 --- a/bot/exts/evergreen/status_codes.py +++ b/bot/exts/evergreen/status_codes.py @@ -1,8 +1,6 @@ -import re from http import HTTPStatus import discord -from discord import HTTPException from discord.ext import commands -- cgit v1.2.3 From c60c8471b4e0cb9b54bee80fd43c75c4a2e75b76 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sun, 31 Jan 2021 15:13:58 +0530 Subject: Fix import order --- bot/exts/evergreen/cheatsheet.py | 93 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 bot/exts/evergreen/cheatsheet.py (limited to 'bot') diff --git a/bot/exts/evergreen/cheatsheet.py b/bot/exts/evergreen/cheatsheet.py new file mode 100644 index 00000000..3a689005 --- /dev/null +++ b/bot/exts/evergreen/cheatsheet.py @@ -0,0 +1,93 @@ +import random +import re +import typing as t +from urllib.parse import quote_plus + +from discord import Embed +from discord.ext import commands +from discord.ext.commands import BucketType, Context + +from bot.constants import Channels, Colours, ERROR_REPLIES + +ERROR_MESSAGE = """ +Unknown cheat sheet. Please try to reformulate your query. + +**Examples**: +```md +.cht read json +.cht hello world +.cht lambda +``` +If the problem persists send a message in <#{channel}> +""" + + +class ChtSh(commands.Cog): + """Commands that sends a result of a cht.sh search in code blocks.""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + + @staticmethod + def fmt_error_embed() -> Embed: + """If the cht.sh search returned 404, overwrite it to send a custom error embed.""" + embed = Embed(colour=Colours.soft_red) + embed.title = random.choice(ERROR_REPLIES) + embed.description = ERROR_MESSAGE.format(channel=Channels.dev_contrib) + return embed + + def result_fmt(self, url: str, body_text: str) -> t.Tuple[bool, t.Union[str, Embed]]: + """Format Result.""" + if body_text.startswith("# 404 NOT FOUND"): + embed = self.fmt_error_embed() + return True, embed + + body_space = min(1986 - len(url), 1000) + + if len(body_text) > body_space: + description = f"**Result Of cht.sh**\n" \ + f"```python\n{body_text[:body_space]}\n" \ + f"... (truncated - too many lines)```\n" \ + f"Full results: {url} " + else: + description = f"**Result Of cht.sh**\n" \ + f"```python\n{body_text}```\n" \ + f"{url}" + return False, description + + @commands.command( + name="cheat", + aliases=("cht.sh", "cheatsheet", "cheat-sheet", "cht"), + ) + @commands.cooldown(1, 10, BucketType.user) + async def cheat_sheet( + self, ctx: Context, *search_terms: str + ) -> None: + """ + Search cheat.sh. + + Gets a post from https://cheat.sh/python/ by default. + Usage: + --> .cht read json + """ + url = f'https://cheat.sh/python/{quote_plus(" ".join(search_terms))}' + headers = { + 'User-Agent': 'curl/7.68.0' + } + + escape_tt = str.maketrans({"`": "\\`"}) + ansi_re = re.compile(r"\x1b\[.*?m") + + async with self.bot.http_session.get(url, headers=headers) as response: + result = ansi_re.sub("", await response.text()).translate(escape_tt) + + is_embed, desciprtion = self.result_fmt(url, result) + if is_embed: + await ctx.send(embed=desciprtion) + else: + await ctx.send(content=desciprtion) + + +def setup(bot: commands.Bot) -> None: + """Load the ChtSh cog.""" + bot.add_cog(ChtSh(bot)) -- cgit v1.2.3 From a602361492cc653f8fae82a3b30f36b232ba5024 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Mon, 1 Feb 2021 05:18:28 +0530 Subject: Rename cog CheatSheet ; Change Embed code to a single constructor ; remove headers as chubin/cheat.sh#280 got merged ; improve error embed docstrings --- bot/exts/evergreen/cheatsheet.py | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/cheatsheet.py b/bot/exts/evergreen/cheatsheet.py index 3a689005..211b3246 100644 --- a/bot/exts/evergreen/cheatsheet.py +++ b/bot/exts/evergreen/cheatsheet.py @@ -22,7 +22,7 @@ If the problem persists send a message in <#{channel}> """ -class ChtSh(commands.Cog): +class CheatSheet(commands.Cog): """Commands that sends a result of a cht.sh search in code blocks.""" def __init__(self, bot: commands.Bot): @@ -30,10 +30,17 @@ class ChtSh(commands.Cog): @staticmethod def fmt_error_embed() -> Embed: - """If the cht.sh search returned 404, overwrite it to send a custom error embed.""" - embed = Embed(colour=Colours.soft_red) - embed.title = random.choice(ERROR_REPLIES) - embed.description = ERROR_MESSAGE.format(channel=Channels.dev_contrib) + """ + Format the Error Embed. + + If the cht.sh search returned 404, overwrite it to send a custom error embed. + link -> https://github.com/chubin/cheat.sh/issues/198 + """ + embed = Embed( + title=random.choice(ERROR_REPLIES), + description=ERROR_MESSAGE.format(channel=Channels.dev_contrib), + colour=Colours.soft_red + ) return embed def result_fmt(self, url: str, body_text: str) -> t.Tuple[bool, t.Union[str, Embed]]: @@ -71,23 +78,20 @@ class ChtSh(commands.Cog): --> .cht read json """ url = f'https://cheat.sh/python/{quote_plus(" ".join(search_terms))}' - headers = { - 'User-Agent': 'curl/7.68.0' - } escape_tt = str.maketrans({"`": "\\`"}) ansi_re = re.compile(r"\x1b\[.*?m") - async with self.bot.http_session.get(url, headers=headers) as response: + async with self.bot.http_session.get(url) as response: result = ansi_re.sub("", await response.text()).translate(escape_tt) - is_embed, desciprtion = self.result_fmt(url, result) + is_embed, description = self.result_fmt(url, result) if is_embed: - await ctx.send(embed=desciprtion) + await ctx.send(embed=description) else: - await ctx.send(content=desciprtion) + await ctx.send(content=description) def setup(bot: commands.Bot) -> None: - """Load the ChtSh cog.""" - bot.add_cog(ChtSh(bot)) + """Load the CheatSheet cog.""" + bot.add_cog(CheatSheet(bot)) -- cgit v1.2.3 From c87f6e0561bbeb6510292a0b09a829aa6fa290a7 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Mon, 1 Feb 2021 05:21:32 +0530 Subject: rename the cog to HTTPStatusCodes --- bot/exts/evergreen/status_codes.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/status_codes.py b/bot/exts/evergreen/status_codes.py index 473e778c..19375657 100644 --- a/bot/exts/evergreen/status_codes.py +++ b/bot/exts/evergreen/status_codes.py @@ -4,7 +4,7 @@ import discord from discord.ext import commands -class StatusCats(commands.Cog): +class HTTPStatusCodes(commands.Cog): """Commands that give HTTP statuses described and visualized by cats and dogs.""" def __init__(self, bot: commands.Bot): @@ -57,5 +57,5 @@ class StatusCats(commands.Cog): def setup(bot: commands.Bot) -> None: - """Load the StatusCats cog.""" - bot.add_cog(StatusCats(bot)) + """Load the HTTPStatusCodes cog.""" + bot.add_cog(HTTPStatusCodes(bot)) -- cgit v1.2.3 From e32182ee7000cea8a49d41605bb01563c0d68800 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Mon, 1 Feb 2021 05:28:35 +0530 Subject: Add similar repsonse.status check to too, and instead of ValueError raise NotImplemented error if the status is not implemented yet but is a valid status code --- bot/exts/evergreen/status_codes.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/status_codes.py b/bot/exts/evergreen/status_codes.py index 19375657..bfc4bb1a 100644 --- a/bot/exts/evergreen/status_codes.py +++ b/bot/exts/evergreen/status_codes.py @@ -23,13 +23,18 @@ class HTTPStatusCodes(commands.Cog): try: HTTPStatus(code) + async with self.bot.http_session.get( + f'https://http.cat/{code}.jpg', + allow_redirects=False + ) as response: + if response.status != 404: + embed.set_image(url=f'https://http.cat/{code}.jpg') + else: + raise NotImplementedError except ValueError: embed.set_footer(text='Inputted status code does not exist.') - else: - embed.set_image(url=f'https://http.cat/{code}.jpg') - finally: await ctx.send(embed=embed) @@ -47,11 +52,14 @@ class HTTPStatusCodes(commands.Cog): if response.status != 302: embed.set_image(url=f'https://httpstatusdogs.com/img/{code}.jpg') else: - raise ValueError + raise NotImplementedError except ValueError: embed.set_footer(text='Inputted status code does not exist.') + except NotImplementedError: + embed.set_footer(text='Inputted status code is not implemented by httpstatusdogs.com yet.') + finally: await ctx.send(embed=embed) -- cgit v1.2.3 From 8a92054bab4c3dbd0e42d633d11a87461e1189e1 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Mon, 1 Feb 2021 05:31:48 +0530 Subject: Remove brackets from .join --- bot/exts/evergreen/issues.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index f24e0717..72ca6de4 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -189,7 +189,7 @@ class Issues(commands.Cog): if message_repo_issue_map: for repo_issue in message_repo_issue_map: - if not self.check_in_block(message, " ".join([*repo_issue])): + if not self.check_in_block(message, " ".join(repo_issue)): result = await self.fetch_issues({repo_issue[1]}, repo_issue[0], "python-discord") if isinstance(result, list): links.extend(result) -- cgit v1.2.3 From 29c84ad7cc6729c0887f49206ade8f98e2655fd1 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Mon, 1 Feb 2021 13:37:04 +0530 Subject: Remove the use of globals and instead use class variables --- bot/exts/evergreen/connect_four.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 50632c1b..48473d30 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -6,7 +6,6 @@ from functools import partial import discord from discord.ext import commands -EMOJI_TOKENS = [":white_circle:", ":blue_circle:", ":red_circle:"] NUMBERS = [ ":one:", ":two:", @@ -44,13 +43,15 @@ class Game: channel: discord.TextChannel, player1: discord.Member, player2: typing.Optional[discord.Member], - size: int = 7, + tokens: typing.List[str], + size: int = 7 ) -> None: self.bot = bot self.channel = channel self.player1 = player1 self.player2 = player2 or AI(self.bot, game=self) + self.tokens = tokens self.grid = self.generate_board(size) self.grid_size = size @@ -74,7 +75,7 @@ class Game: f' VS {self.bot.user.display_name if isinstance(self.player2, AI) else self.player2.display_name}' ) - rows = [" ".join(EMOJIS[s] for s in row) for row in self.grid] + rows = [" ".join(self.tokens[s] for s in row) for row in self.grid] first_row = " ".join(x for x in NUMBERS[:self.grid_size]) formatted_grid = "\n".join([first_row] + rows) embed = discord.Embed(title=title, description=formatted_grid) @@ -276,6 +277,8 @@ class ConnectFour(commands.Cog): self.games: typing.List[Game] = [] self.waiting: typing.List[discord.Member] = [] + self.tokens = [":white_circle:", ":blue_circle:", ":red_circle:"] + self.max_board_size = 9 self.min_board_size = 5 @@ -356,11 +359,10 @@ class ConnectFour(commands.Cog): emoji2: str ) -> None: """Helper for playing a game of connect four.""" - global EMOJIS - EMOJIS = [":white_circle:", str(emoji1), str(emoji2)] + self.tokens = [":white_circle:", str(emoji1), str(emoji2)] try: - game = Game(self.bot, ctx.channel, ctx.author, user, size=board_size) + game = Game(self.bot, ctx.channel, ctx.author, user, self.tokens, size=board_size) self.games.append(game) await game.start_game() self.games.remove(game) -- cgit v1.2.3 From 4239b1d07cd0bba543aca8e7c77cee1d8f437b14 Mon Sep 17 00:00:00 2001 From: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> Date: Mon, 1 Feb 2021 11:47:52 +0300 Subject: Fixes Issue Matching Regex Changes the automatic issue matching regex to make it work for repos at the very beginning of messages. --- bot/exts/evergreen/issues.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 72ca6de4..73ebe547 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -184,7 +184,7 @@ class Issues(commands.Cog): ): return - message_repo_issue_map = re.findall(fr".+?({self.repo_regex})#(\d+)", message.content) + message_repo_issue_map = re.findall(fr"({self.repo_regex})#(\d+)", message.content) links = [] if message_repo_issue_map: -- cgit v1.2.3 From 4b8f5789aa0c9f6ce005273ed1affdbc3a87c16a Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Mon, 1 Feb 2021 14:46:55 +0530 Subject: Add check if game is not intialized --- bot/exts/evergreen/connect_four.py | 1 + 1 file changed, 1 insertion(+) (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 48473d30..bf604e2a 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -360,6 +360,7 @@ class ConnectFour(commands.Cog): ) -> None: """Helper for playing a game of connect four.""" self.tokens = [":white_circle:", str(emoji1), str(emoji2)] + game = None # if game fails to intialize in try...except try: game = Game(self.bot, ctx.channel, ctx.author, user, self.tokens, size=board_size) -- cgit v1.2.3 From 5c4cbbeeb5fd9e7f7c651b24b2b1d3bdbcc55110 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 2 Feb 2021 05:09:29 +0530 Subject: Make use of constants --- bot/exts/evergreen/cheatsheet.py | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/cheatsheet.py b/bot/exts/evergreen/cheatsheet.py index 211b3246..4191a83f 100644 --- a/bot/exts/evergreen/cheatsheet.py +++ b/bot/exts/evergreen/cheatsheet.py @@ -7,20 +7,25 @@ from discord import Embed from discord.ext import commands from discord.ext.commands import BucketType, Context +from bot import constants from bot.constants import Channels, Colours, ERROR_REPLIES -ERROR_MESSAGE = """ +ERROR_MESSAGE = f""" Unknown cheat sheet. Please try to reformulate your query. **Examples**: ```md -.cht read json -.cht hello world -.cht lambda +{constants.Client.prefix}cht read json +{constants.Client.prefix}cht hello world +{constants.Client.prefix}cht lambda ``` -If the problem persists send a message in <#{channel}> +If the problem persists send a message in <#{Channels.dev_contrib}> """ +URL = 'https://cheat.sh/python/{search}' +ESCAPE_TT = str.maketrans({"`": "\\`"}) +ANSI_RE = re.compile(r"\x1b\[.*?m") + class CheatSheet(commands.Cog): """Commands that sends a result of a cht.sh search in code blocks.""" @@ -38,7 +43,7 @@ class CheatSheet(commands.Cog): """ embed = Embed( title=random.choice(ERROR_REPLIES), - description=ERROR_MESSAGE.format(channel=Channels.dev_contrib), + description=ERROR_MESSAGE, colour=Colours.soft_red ) return embed @@ -67,9 +72,7 @@ class CheatSheet(commands.Cog): aliases=("cht.sh", "cheatsheet", "cheat-sheet", "cht"), ) @commands.cooldown(1, 10, BucketType.user) - async def cheat_sheet( - self, ctx: Context, *search_terms: str - ) -> None: + async def cheat_sheet(self, ctx: Context, *search_terms: str) -> None: """ Search cheat.sh. @@ -77,15 +80,15 @@ class CheatSheet(commands.Cog): Usage: --> .cht read json """ - url = f'https://cheat.sh/python/{quote_plus(" ".join(search_terms))}' - - escape_tt = str.maketrans({"`": "\\`"}) - ansi_re = re.compile(r"\x1b\[.*?m") - - async with self.bot.http_session.get(url) as response: - result = ansi_re.sub("", await response.text()).translate(escape_tt) - - is_embed, description = self.result_fmt(url, result) + async with self.bot.http_session.get( + URL.format(search=quote_plus(" ".join(search_terms))) + ) as response: + result = ANSI_RE.sub("", await response.text()).translate(ESCAPE_TT) + + is_embed, description = self.result_fmt( + URL.format(search=quote_plus(" ".join(search_terms))), + result + ) if is_embed: await ctx.send(embed=description) else: -- cgit v1.2.3 From 2631004f7d1467bc81090ac481de78cbfe7978e5 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 2 Feb 2021 05:14:34 +0530 Subject: Add override_in_channel deco --- bot/exts/evergreen/cheatsheet.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/cheatsheet.py b/bot/exts/evergreen/cheatsheet.py index 4191a83f..c83af839 100644 --- a/bot/exts/evergreen/cheatsheet.py +++ b/bot/exts/evergreen/cheatsheet.py @@ -8,7 +8,8 @@ from discord.ext import commands from discord.ext.commands import BucketType, Context from bot import constants -from bot.constants import Channels, Colours, ERROR_REPLIES +from bot.constants import Channels, Colours, ERROR_REPLIES, WHITELISTED_CHANNELS +from bot.utils.decorators import override_in_channel ERROR_MESSAGE = f""" Unknown cheat sheet. Please try to reformulate your query. @@ -71,6 +72,7 @@ class CheatSheet(commands.Cog): name="cheat", aliases=("cht.sh", "cheatsheet", "cheat-sheet", "cht"), ) + @override_in_channel(WHITELISTED_CHANNELS) @commands.cooldown(1, 10, BucketType.user) async def cheat_sheet(self, ctx: Context, *search_terms: str) -> None: """ -- cgit v1.2.3 From aee64f82f5a97a4bdd32c6d6d66f6f0eb8ef51f8 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 2 Feb 2021 05:23:34 +0530 Subject: Add not Implemented error handler for .status cat command --- bot/exts/evergreen/status_codes.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'bot') diff --git a/bot/exts/evergreen/status_codes.py b/bot/exts/evergreen/status_codes.py index bfc4bb1a..ff2ac9e1 100644 --- a/bot/exts/evergreen/status_codes.py +++ b/bot/exts/evergreen/status_codes.py @@ -35,6 +35,9 @@ class HTTPStatusCodes(commands.Cog): except ValueError: embed.set_footer(text='Inputted status code does not exist.') + except NotImplementedError: + embed.set_footer(text='Inputted status code is not implemented by http.cat yet.') + finally: await ctx.send(embed=embed) -- cgit v1.2.3 From 3e884eaa43b78b433a470aaff39b03a0f6c2b3c2 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 2 Feb 2021 06:05:46 +0530 Subject: Allow cht.sh command to be used in occupied help channels --- bot/constants.py | 11 +++++------ bot/exts/evergreen/cheatsheet.py | 13 +++++++++---- 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index 1d41a53e..23865272 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -104,12 +104,6 @@ class Channels(NamedTuple): devlog = int(environ.get("CHANNEL_DEVLOG", 622895325144940554)) dev_contrib = 635950537262759947 dev_branding = 753252897059373066 - help_0 = 303906576991780866 - help_1 = 303906556754395136 - help_2 = 303906514266226689 - help_3 = 439702951246692352 - help_4 = 451312046647148554 - help_5 = 454941769734422538 helpers = 385474242440986624 message_log = 467752170159079424 mod_alerts = 473092532147060736 @@ -128,6 +122,10 @@ class Channels(NamedTuple): voice_chat_1 = 799647045886541885 +class Categories(NamedTuple): + help_in_use = 696958401460043776 + + class Client(NamedTuple): name = "Sir Lancebot" guild = int(environ.get("BOT_GUILD", 267624335836053506)) @@ -249,6 +247,7 @@ class Roles(NamedTuple): rockstars = 458226413825294336 core_developers = 587606783669829632 events_lead = 778361735739998228 + everyone = 267624335836053506 class Tokens(NamedTuple): diff --git a/bot/exts/evergreen/cheatsheet.py b/bot/exts/evergreen/cheatsheet.py index c83af839..83098c76 100644 --- a/bot/exts/evergreen/cheatsheet.py +++ b/bot/exts/evergreen/cheatsheet.py @@ -3,13 +3,13 @@ import re import typing as t from urllib.parse import quote_plus -from discord import Embed +from discord import Embed, utils from discord.ext import commands from discord.ext.commands import BucketType, Context from bot import constants -from bot.constants import Channels, Colours, ERROR_REPLIES, WHITELISTED_CHANNELS -from bot.utils.decorators import override_in_channel +from bot.constants import Categories, Channels, Colours, ERROR_REPLIES, Roles, WHITELISTED_CHANNELS +from bot.utils.decorators import with_role ERROR_MESSAGE = f""" Unknown cheat sheet. Please try to reformulate your query. @@ -72,8 +72,8 @@ class CheatSheet(commands.Cog): name="cheat", aliases=("cht.sh", "cheatsheet", "cheat-sheet", "cht"), ) - @override_in_channel(WHITELISTED_CHANNELS) @commands.cooldown(1, 10, BucketType.user) + @with_role(Roles.everyone) async def cheat_sheet(self, ctx: Context, *search_terms: str) -> None: """ Search cheat.sh. @@ -82,6 +82,11 @@ class CheatSheet(commands.Cog): Usage: --> .cht read json """ + category = utils.get(ctx.message.guild.categories, id=Categories.help_in_use) + all_allowed_channels = WHITELISTED_CHANNELS + tuple(category.channels) + if ctx.channel not in all_allowed_channels: + return + async with self.bot.http_session.get( URL.format(search=quote_plus(" ".join(search_terms))) ) as response: -- cgit v1.2.3 From b10b2524a1284f7462f3b0f039827e6d115e7931 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 2 Feb 2021 06:16:38 +0530 Subject: Improve category check code --- bot/exts/evergreen/cheatsheet.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/cheatsheet.py b/bot/exts/evergreen/cheatsheet.py index 83098c76..abc5306b 100644 --- a/bot/exts/evergreen/cheatsheet.py +++ b/bot/exts/evergreen/cheatsheet.py @@ -3,7 +3,7 @@ import re import typing as t from urllib.parse import quote_plus -from discord import Embed, utils +from discord import Embed from discord.ext import commands from discord.ext.commands import BucketType, Context @@ -82,9 +82,10 @@ class CheatSheet(commands.Cog): Usage: --> .cht read json """ - category = utils.get(ctx.message.guild.categories, id=Categories.help_in_use) - all_allowed_channels = WHITELISTED_CHANNELS + tuple(category.channels) - if ctx.channel not in all_allowed_channels: + if not ( + ctx.channel.category.id == Categories.help_in_use + or ctx.channel.id in WHITELISTED_CHANNELS + ): return async with self.bot.http_session.get( -- cgit v1.2.3 From 5190f5b8576267807dd6a4920964d684f0d572a4 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 2 Feb 2021 06:17:58 +0530 Subject: everyone -> everyone_role and remove developers role --- bot/constants.py | 3 +-- bot/exts/evergreen/cheatsheet.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index 23865272..8e210ad3 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -236,7 +236,6 @@ class Roles(NamedTuple): announcements = 463658397560995840 champion = 430492892331769857 contributor = 295488872404484098 - developer = 352427296948486144 devops = 409416496733880320 jammer = 423054537079783434 moderator = 267629731250176001 @@ -247,7 +246,7 @@ class Roles(NamedTuple): rockstars = 458226413825294336 core_developers = 587606783669829632 events_lead = 778361735739998228 - everyone = 267624335836053506 + everyone_role = 267624335836053506 class Tokens(NamedTuple): diff --git a/bot/exts/evergreen/cheatsheet.py b/bot/exts/evergreen/cheatsheet.py index abc5306b..f650e3b0 100644 --- a/bot/exts/evergreen/cheatsheet.py +++ b/bot/exts/evergreen/cheatsheet.py @@ -73,7 +73,7 @@ class CheatSheet(commands.Cog): aliases=("cht.sh", "cheatsheet", "cheat-sheet", "cht"), ) @commands.cooldown(1, 10, BucketType.user) - @with_role(Roles.everyone) + @with_role(Roles.everyone_role) async def cheat_sheet(self, ctx: Context, *search_terms: str) -> None: """ Search cheat.sh. -- cgit v1.2.3 From 5e55ea1dbfd652c10999c88d1c32aebd1be768f0 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Thu, 4 Feb 2021 05:23:54 +0530 Subject: Make use of constants in the url --- bot/exts/evergreen/status_codes.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/status_codes.py b/bot/exts/evergreen/status_codes.py index ff2ac9e1..874c87eb 100644 --- a/bot/exts/evergreen/status_codes.py +++ b/bot/exts/evergreen/status_codes.py @@ -3,6 +3,9 @@ from http import HTTPStatus import discord from discord.ext import commands +HTTP_DOG_URL = "https://httpstatusdogs.com/img/{code}.jpg" +HTTP_CAT_URL = "https://http.cat/{code}.jpg" + class HTTPStatusCodes(commands.Cog): """Commands that give HTTP statuses described and visualized by cats and dogs.""" @@ -16,19 +19,17 @@ class HTTPStatusCodes(commands.Cog): if not ctx.invoked_subcommand: await ctx.send_help(ctx.command) - @http_status_group.command(aliases=['cat']) + @http_status_group.command(name='cat') async def http_cat(self, ctx: commands.Context, code: int) -> None: """Sends an embed with an image of a cat, portraying the status code.""" embed = discord.Embed(title=f'**Status: {code}**') + url = HTTP_CAT_URL.format(code=code) try: HTTPStatus(code) - async with self.bot.http_session.get( - f'https://http.cat/{code}.jpg', - allow_redirects=False - ) as response: + async with self.bot.http_session.get(url, allow_redirects=False) as response: if response.status != 404: - embed.set_image(url=f'https://http.cat/{code}.jpg') + embed.set_image(url=url) else: raise NotImplementedError @@ -41,19 +42,17 @@ class HTTPStatusCodes(commands.Cog): finally: await ctx.send(embed=embed) - @http_status_group.command(aliases=['dog']) + @http_status_group.command(name='dog') async def http_dog(self, ctx: commands.Context, code: int) -> None: """Sends an embed with an image of a dog, portraying the status code.""" embed = discord.Embed(title=f'**Status: {code}**') + url = HTTP_DOG_URL.format(code=code) try: HTTPStatus(code) - async with self.bot.http_session.get( - f'https://httpstatusdogs.com/img/{code}.jpg', - allow_redirects=False - ) as response: + async with self.bot.http_session.get(url, allow_redirects=False) as response: if response.status != 302: - embed.set_image(url=f'https://httpstatusdogs.com/img/{code}.jpg') + embed.set_image(url=url) else: raise NotImplementedError -- cgit v1.2.3 From 4687f3d142a40fecc8d851e598dabb6c474059f1 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Thu, 4 Feb 2021 17:28:03 +0530 Subject: Intial Commit; Change secret functionality and fix member intents issue --- bot/exts/valentines/be_my_valentine.py | 70 +++++++++------------------------- 1 file changed, 17 insertions(+), 53 deletions(-) (limited to 'bot') diff --git a/bot/exts/valentines/be_my_valentine.py b/bot/exts/valentines/be_my_valentine.py index 4db4d191..818d539a 100644 --- a/bot/exts/valentines/be_my_valentine.py +++ b/bot/exts/valentines/be_my_valentine.py @@ -2,13 +2,13 @@ import logging import random from json import load from pathlib import Path -from typing import Optional, Tuple +from typing import Tuple import discord from discord.ext import commands from discord.ext.commands.cooldowns import BucketType -from bot.constants import Channels, Client, Colours, Lovefest, Month +from bot.constants import Channels, Colours, Lovefest, Month from bot.utils.decorators import in_month log = logging.getLogger(__name__) @@ -70,15 +70,14 @@ class BeMyValentine(commands.Cog): @commands.cooldown(1, 1800, BucketType.user) @commands.group(name='bemyvalentine', invoke_without_command=True) async def send_valentine( - self, ctx: commands.Context, user: Optional[discord.Member] = None, *, valentine_type: str = None + self, ctx: commands.Context, user: discord.Member, *, valentine_type: str = None ) -> None: """ Send a valentine to user, if specified, or to a random user with the lovefest role. - syntax: .bemyvalentine [user](optional) [p/poem/c/compliment/or you can type your own valentine message] + syntax: .bemyvalentine [user] [p/poem/c/compliment/or you can type your own valentine message] (optional) - example: .bemyvalentine (sends valentine as a poem or a compliment to a random user) example: .bemyvalentine Iceman#6508 p (sends a poem to Iceman) 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. @@ -88,26 +87,18 @@ class BeMyValentine(commands.Cog): msg = "You are supposed to use this command in the server." return await ctx.send(msg) - if user: - if Lovefest.role_id not in [role.id for role in user.roles]: - message = f"You cannot send a valentine to {user} as he/she does not have the lovefest role!" - return await ctx.send(message) + if Lovefest.role_id not in [role.id for role in user.roles]: + message = f"You cannot send a valentine to {user} as he/she does not have the lovefest role!" + return await ctx.send(message) if user == ctx.author: # Well a user can't valentine himself/herself. return await ctx.send("Come on dude, you can't send a valentine to yourself :expressionless:") emoji_1, emoji_2 = self.random_emoji() - lovefest_role = discord.utils.get(ctx.guild.roles, id=Lovefest.role_id) channel = self.bot.get_channel(Channels.community_bot_commands) valentine, title = self.valentine_check(valentine_type) - if user is None: - author = ctx.author - user = self.random_user(author, lovefest_role.members) - if user is None: - return await ctx.send("There are no users avilable to whome your valentine can be sent.") - embed = discord.Embed( title=f'{emoji_1} {title} {user.display_name} {emoji_2}', description=f'{valentine} \n **{emoji_2}From {ctx.author}{emoji_1}**', @@ -118,47 +109,31 @@ class BeMyValentine(commands.Cog): @commands.cooldown(1, 1800, BucketType.user) @send_valentine.command(name='secret') async def anonymous( - self, ctx: commands.Context, user: Optional[discord.Member] = None, *, valentine_type: str = None + self, ctx: commands.Context, user: discord.Member, *, valentine_type: str = None ) -> None: """ Send an anonymous Valentine via DM to to a user, if specified, or to a random with the lovefest role. - **This command should be DMed to the bot.** - - syntax : .bemyvalentine secret [user](optional) [p/poem/c/compliment/or you can type your own valentine message] + syntax : .bemyvalentine secret [user] [p/poem/c/compliment/or you can type your own valentine message] (optional) - example : .bemyvalentine secret (sends valentine as a poem or a compliment to a random user in DM making you - anonymous) example : .bemyvalentine secret Iceman#6508 p (sends a poem to Iceman in DM making you anonymous) 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." - return await ctx.send(msg) - - if user: - if Lovefest.role_id not in [role.id for role in user.roles]: - message = f"You cannot send a valentine to {user} as he/she does not have the lovefest role!" - return await ctx.send(message) + if Lovefest.role_id not in [role.id for role in user.roles]: + message = f"You cannot send a valentine to {user} as he/she does not have the lovefest role!" + await ctx.message.delete() + return await ctx.author.send(message) if user == ctx.author: # Well a user cant valentine himself/herself. - return await ctx.send('Come on dude, you cant send a valentine to yourself :expressionless:') + await ctx.message.delete() + return await ctx.author.send('Come on dude, you cant send a valentine to yourself :expressionless:') - guild = self.bot.get_guild(id=Client.guild) emoji_1, emoji_2 = self.random_emoji() - lovefest_role = discord.utils.get(guild.roles, id=Lovefest.role_id) valentine, title = self.valentine_check(valentine_type) - if user is None: - author = ctx.author - user = self.random_user(author, lovefest_role.members) - if user is None: - return await ctx.send("There are no users avilable to whome your valentine can be sent.") - embed = discord.Embed( title=f'{emoji_1}{title} {user.display_name}{emoji_2}', description=f'{valentine} \n **{emoji_2}From anonymous{emoji_1}**', @@ -166,8 +141,9 @@ class BeMyValentine(commands.Cog): ) try: await user.send(embed=embed) + await ctx.message.delete() except discord.Forbidden: - await ctx.author.send(f"{user} has DMs disabled, so I couldn't send the message. Sorry!") + await ctx.send(f"{user} has DMs disabled, so I couldn't send the message. Sorry!") else: await ctx.author.send(f"Your message has been sent to {user}") @@ -190,18 +166,6 @@ class BeMyValentine(commands.Cog): title = 'A message for' return valentine, title - @staticmethod - def random_user(author: discord.Member, members: discord.Member) -> None: - """ - Picks a random member from the list provided in `members`. - - The invoking author is ignored. - """ - if author in members: - members.remove(author) - - return random.choice(members) if members else None - @staticmethod def random_emoji() -> Tuple[str, str]: """Return two random emoji from the module-defined constants.""" -- cgit v1.2.3 From ae518304b130af53846d8cbd425463661dbc068f Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Fri, 5 Feb 2021 06:43:25 +0530 Subject: Fix return statements and return type annotations --- bot/exts/valentines/be_my_valentine.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/valentines/be_my_valentine.py b/bot/exts/valentines/be_my_valentine.py index 818d539a..41959409 100644 --- a/bot/exts/valentines/be_my_valentine.py +++ b/bot/exts/valentines/be_my_valentine.py @@ -85,15 +85,18 @@ class BeMyValentine(commands.Cog): 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." - return await ctx.send(msg) + await ctx.send(msg) + return if Lovefest.role_id not in [role.id for role in user.roles]: message = f"You cannot send a valentine to {user} as he/she does not have the lovefest role!" - return await ctx.send(message) + await ctx.send(message) + return if user == ctx.author: # Well a user can't valentine himself/herself. - return await ctx.send("Come on dude, you can't send a valentine to yourself :expressionless:") + await ctx.send("Come on dude, you can't send a valentine to yourself :expressionless:") + return emoji_1, emoji_2 = self.random_emoji() channel = self.bot.get_channel(Channels.community_bot_commands) -- cgit v1.2.3 From 1951ce5fe0a2ae3bd8ef27abe68b1abe3b12be28 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Fri, 5 Feb 2021 06:46:48 +0530 Subject: Remove code that requires intents.member set True --- bot/exts/valentines/lovecalculator.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'bot') diff --git a/bot/exts/valentines/lovecalculator.py b/bot/exts/valentines/lovecalculator.py index c75ea6cf..5cc08fed 100644 --- a/bot/exts/valentines/lovecalculator.py +++ b/bot/exts/valentines/lovecalculator.py @@ -11,8 +11,6 @@ from discord import Member from discord.ext import commands from discord.ext.commands import BadArgument, Cog, clean_content -from bot.constants import Roles - log = logging.getLogger(__name__) with Path("bot/resources/valentines/love_matches.json").open(encoding="utf8") as file: @@ -28,7 +26,7 @@ class LoveCalculator(Cog): @commands.command(aliases=('love_calculator', 'love_calc')) @commands.cooldown(rate=1, per=5, type=commands.BucketType.user) - async def love(self, ctx: commands.Context, who: Union[Member, str], whom: Union[Member, str] = None) -> None: + async def love(self, ctx: commands.Context, who: Union[Member, str], whom: Union[Member, str]) -> None: """ Tells you how much the two love each other. @@ -46,13 +44,7 @@ class LoveCalculator(Cog): If you want to use multiple words for one argument, you must include quotes. .love "Zes Vappa" "morning coffee" - - 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: Union[Member, str]) -> str: if isinstance(arg, Member): # If we are given a member, return name#discrim without any extra changes -- cgit v1.2.3 From d9a40f8591de1537b38d261e77b42ddc8cbc5688 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Fri, 5 Feb 2021 06:54:02 +0530 Subject: If whom is None, take the user as whom --- bot/exts/valentines/lovecalculator.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/valentines/lovecalculator.py b/bot/exts/valentines/lovecalculator.py index 5cc08fed..966acc82 100644 --- a/bot/exts/valentines/lovecalculator.py +++ b/bot/exts/valentines/lovecalculator.py @@ -4,7 +4,7 @@ import json import logging import random from pathlib import Path -from typing import Union +from typing import Coroutine, Union import discord from discord import Member @@ -26,7 +26,7 @@ class LoveCalculator(Cog): @commands.command(aliases=('love_calculator', 'love_calc')) @commands.cooldown(rate=1, per=5, type=commands.BucketType.user) - async def love(self, ctx: commands.Context, who: Union[Member, str], whom: Union[Member, str]) -> None: + async def love(self, ctx: commands.Context, who: Union[Member, str], whom: Union[Member, str] = None) -> None: """ Tells you how much the two love each other. @@ -45,7 +45,10 @@ class LoveCalculator(Cog): If you want to use multiple words for one argument, you must include quotes. .love "Zes Vappa" "morning coffee" """ - def normalize(arg: Union[Member, str]) -> str: + if whom is None: + whom = ctx.author + + def normalize(arg: Union[Member, str]) -> Coroutine: if isinstance(arg, Member): # If we are given a member, return name#discrim without any extra changes arg = str(arg) -- cgit v1.2.3 From 3d30a1ff9103fc59bd7fcc0ec8b1e7304beb08d4 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Fri, 5 Feb 2021 09:27:25 +0530 Subject: Abrupt response, so make the bot type --- bot/exts/evergreen/cheatsheet.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/cheatsheet.py b/bot/exts/evergreen/cheatsheet.py index f650e3b0..b3ee0b94 100644 --- a/bot/exts/evergreen/cheatsheet.py +++ b/bot/exts/evergreen/cheatsheet.py @@ -88,19 +88,20 @@ class CheatSheet(commands.Cog): ): return - async with self.bot.http_session.get( - URL.format(search=quote_plus(" ".join(search_terms))) - ) as response: - result = ANSI_RE.sub("", await response.text()).translate(ESCAPE_TT) - - is_embed, description = self.result_fmt( - URL.format(search=quote_plus(" ".join(search_terms))), - result - ) - if is_embed: - await ctx.send(embed=description) - else: - await ctx.send(content=description) + async with ctx.typing(): + async with self.bot.http_session.get( + URL.format(search=quote_plus(" ".join(search_terms))) + ) as response: + result = ANSI_RE.sub("", await response.text()).translate(ESCAPE_TT) + + is_embed, description = self.result_fmt( + URL.format(search=quote_plus(" ".join(search_terms))), + result + ) + if is_embed: + await ctx.send(embed=description) + else: + await ctx.send(content=description) def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From f6cccfe73321173d24667321b41f2e2b05f29aac Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Fri, 5 Feb 2021 09:28:28 +0530 Subject: Move repeated code to a single variable --- bot/exts/evergreen/cheatsheet.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/cheatsheet.py b/bot/exts/evergreen/cheatsheet.py index b3ee0b94..acd77e59 100644 --- a/bot/exts/evergreen/cheatsheet.py +++ b/bot/exts/evergreen/cheatsheet.py @@ -89,13 +89,15 @@ class CheatSheet(commands.Cog): return async with ctx.typing(): + search_string = quote_plus(" ".join(search_terms)) + async with self.bot.http_session.get( - URL.format(search=quote_plus(" ".join(search_terms))) + URL.format(search=search_string) ) as response: result = ANSI_RE.sub("", await response.text()).translate(ESCAPE_TT) is_embed, description = self.result_fmt( - URL.format(search=quote_plus(" ".join(search_terms))), + URL.format(search=search_string), result ) if is_embed: -- cgit v1.2.3 From 95950b93f5e01819921f9bc32a1613bdf1ddd13b Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Fri, 5 Feb 2021 09:30:10 +0530 Subject: Use brackets instead of / for multi line strings --- bot/exts/evergreen/cheatsheet.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/cheatsheet.py b/bot/exts/evergreen/cheatsheet.py index acd77e59..dd44c68e 100644 --- a/bot/exts/evergreen/cheatsheet.py +++ b/bot/exts/evergreen/cheatsheet.py @@ -58,14 +58,14 @@ class CheatSheet(commands.Cog): body_space = min(1986 - len(url), 1000) if len(body_text) > body_space: - description = f"**Result Of cht.sh**\n" \ - f"```python\n{body_text[:body_space]}\n" \ - f"... (truncated - too many lines)```\n" \ - f"Full results: {url} " + description = (f"**Result Of cht.sh**\n" + f"```python\n{body_text[:body_space]}\n" + f"... (truncated - too many lines)```\n" + f"Full results: {url} ") else: - description = f"**Result Of cht.sh**\n" \ - f"```python\n{body_text}```\n" \ - f"{url}" + description = (f"**Result Of cht.sh**\n" + f"```python\n{body_text}```\n" + f"{url}") return False, description @commands.command( -- cgit v1.2.3 From 23c0b2f9464b993c8f2fd33dc2941bef8b0a9851 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Fri, 5 Feb 2021 09:31:09 +0530 Subject: Fix indentation --- bot/exts/evergreen/cheatsheet.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/cheatsheet.py b/bot/exts/evergreen/cheatsheet.py index dd44c68e..97485365 100644 --- a/bot/exts/evergreen/cheatsheet.py +++ b/bot/exts/evergreen/cheatsheet.py @@ -59,13 +59,13 @@ class CheatSheet(commands.Cog): if len(body_text) > body_space: description = (f"**Result Of cht.sh**\n" - f"```python\n{body_text[:body_space]}\n" - f"... (truncated - too many lines)```\n" - f"Full results: {url} ") + f"```python\n{body_text[:body_space]}\n" + f"... (truncated - too many lines)```\n" + f"Full results: {url} ") else: description = (f"**Result Of cht.sh**\n" - f"```python\n{body_text}```\n" - f"{url}") + f"```python\n{body_text}```\n" + f"{url}") return False, description @commands.command( @@ -83,8 +83,8 @@ class CheatSheet(commands.Cog): --> .cht read json """ if not ( - ctx.channel.category.id == Categories.help_in_use - or ctx.channel.id in WHITELISTED_CHANNELS + ctx.channel.category.id == Categories.help_in_use + or ctx.channel.id in WHITELISTED_CHANNELS ): return -- cgit v1.2.3 From 0d5da9e1304865034e8a2349d33b132e149ad890 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 5 Feb 2021 19:17:59 +0000 Subject: First pass of easy to produce errors --- bot/exts/easter/easter_riddle.py | 13 ++++++++++++- bot/exts/evergreen/issues.py | 7 ++++++- bot/exts/evergreen/wolfram.py | 3 ++- bot/exts/halloween/candy_collection.py | 3 +++ 4 files changed, 23 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/easter_riddle.py b/bot/exts/easter/easter_riddle.py index 3c612eb1..a93b3745 100644 --- a/bot/exts/easter/easter_riddle.py +++ b/bot/exts/easter/easter_riddle.py @@ -7,7 +7,7 @@ from pathlib import Path import discord from discord.ext import commands -from bot.constants import Colours +from bot.constants import Colours, NEGATIVE_REPLIES log = logging.getLogger(__name__) @@ -36,6 +36,17 @@ class EasterRiddle(commands.Cog): if self.current_channel: return await ctx.send(f"A riddle is already being solved in {self.current_channel.mention}!") + # Don't let users start in a DM + if not ctx.guild: + await ctx.send( + embed=discord.Embed( + title=random.choice(NEGATIVE_REPLIES), + description="You can't start riddles in DMs", + colour=discord.Colour.red() + ) + ) + return + self.current_channel = ctx.message.channel random_question = random.choice(RIDDLE_QUESTIONS) diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 73ebe547..1f22f287 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -178,7 +178,12 @@ class Issues(commands.Cog): @commands.Cog.listener() async def on_message(self, message: discord.Message) -> None: """Command to retrieve issue(s) from a GitHub repository using automatic linking if matching #.""" - if not( + # Ignore messages from DMs + if not message.guild: + return + + # Ignore messages not in whitelisted categories / channels + if not ( message.channel.category.id in WHITELISTED_CATEGORIES or message.channel.id in WHITELISTED_CHANNELS_ON_MESSAGE ): diff --git a/bot/exts/evergreen/wolfram.py b/bot/exts/evergreen/wolfram.py index 898e8d2a..077a99f5 100644 --- a/bot/exts/evergreen/wolfram.py +++ b/bot/exts/evergreen/wolfram.py @@ -62,7 +62,8 @@ def custom_cooldown(*ignore: List[int]) -> Callable: # if the invoked command is help we don't want to increase the ratelimits since it's not actually # invoking the command/making a request, so instead just check if the user/guild are on cooldown. guild_cooldown = not guildcd.get_bucket(ctx.message).get_tokens() == 0 # if guild is on cooldown - if not any(r.id in ignore for r in ctx.author.roles): # check user bucket if user is not ignored + # check the message is in a guild, and check user bucket if user is not ignored + if ctx.guild and not any(r.id in ignore for r in ctx.author.roles): return guild_cooldown and not usercd.get_bucket(ctx.message).get_tokens() == 0 return guild_cooldown diff --git a/bot/exts/halloween/candy_collection.py b/bot/exts/halloween/candy_collection.py index 0cb37ecd..40e21f40 100644 --- a/bot/exts/halloween/candy_collection.py +++ b/bot/exts/halloween/candy_collection.py @@ -47,6 +47,9 @@ class CandyCollection(commands.Cog): @commands.Cog.listener() async def on_message(self, message: discord.Message) -> None: """Randomly adds candy or skull reaction to non-bot messages in the Event channel.""" + # Ignore messages in DMs + if not message.guild: + return # make sure its a human message if message.author.bot: return -- cgit v1.2.3 From 370535b80690f89544840dc3967bfa7c59e6e667 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sat, 6 Feb 2021 08:43:07 +0530 Subject: Improve grammar and update docstrings, add try..except block while sending DMs --- bot/exts/valentines/be_my_valentine.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'bot') diff --git a/bot/exts/valentines/be_my_valentine.py b/bot/exts/valentines/be_my_valentine.py index 41959409..26966804 100644 --- a/bot/exts/valentines/be_my_valentine.py +++ b/bot/exts/valentines/be_my_valentine.py @@ -73,7 +73,7 @@ class BeMyValentine(commands.Cog): self, ctx: commands.Context, user: discord.Member, *, valentine_type: str = None ) -> None: """ - Send a valentine to user, if specified, or to a random user with the lovefest role. + Send a valentine to a specified user with the lovefest role. syntax: .bemyvalentine [user] [p/poem/c/compliment/or you can type your own valentine message] (optional) @@ -89,7 +89,7 @@ class BeMyValentine(commands.Cog): return if Lovefest.role_id not in [role.id for role in user.roles]: - message = f"You cannot send a valentine to {user} as he/she does not have the lovefest role!" + message = f"You cannot send a valentine to {user} as they do not have the lovefest role!" await ctx.send(message) return @@ -115,7 +115,7 @@ class BeMyValentine(commands.Cog): self, ctx: commands.Context, user: discord.Member, *, valentine_type: str = None ) -> None: """ - Send an anonymous Valentine via DM to to a user, if specified, or to a random with the lovefest role. + Send an anonymous Valentine via DM to to a specified user with the lovefest role. syntax : .bemyvalentine secret [user] [p/poem/c/compliment/or you can type your own valentine message] (optional) @@ -125,14 +125,17 @@ class BeMyValentine(commands.Cog): Iceman in DM making you anonymous) """ if Lovefest.role_id not in [role.id for role in user.roles]: - message = f"You cannot send a valentine to {user} as he/she does not have the lovefest role!" + message = f"You cannot send a valentine to {user} as they do not have the lovefest role!" await ctx.message.delete() - return await ctx.author.send(message) + try: + await ctx.author.send(message) + except discord.Forbidden: + await ctx.send(message) if user == ctx.author: # Well a user cant valentine himself/herself. await ctx.message.delete() - return await ctx.author.send('Come on dude, you cant send a valentine to yourself :expressionless:') + await ctx.send('Come on dude, you cant send a valentine to yourself :expressionless:') emoji_1, emoji_2 = self.random_emoji() valentine, title = self.valentine_check(valentine_type) -- cgit v1.2.3 From a1ba7e857ecfae6382afc6f7fd479a246d953d36 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sat, 6 Feb 2021 09:09:25 +0530 Subject: Slight modifications to functionality of bemyvalentine secret and its messages --- bot/exts/valentines/be_my_valentine.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/exts/valentines/be_my_valentine.py b/bot/exts/valentines/be_my_valentine.py index 26966804..d5668738 100644 --- a/bot/exts/valentines/be_my_valentine.py +++ b/bot/exts/valentines/be_my_valentine.py @@ -95,7 +95,7 @@ class BeMyValentine(commands.Cog): if user == ctx.author: # Well a user can't valentine himself/herself. - await ctx.send("Come on dude, you can't send a valentine to yourself :expressionless:") + await ctx.send("Come on, you can't send a valentine to yourself :expressionless:") return emoji_1, emoji_2 = self.random_emoji() @@ -109,7 +109,7 @@ class BeMyValentine(commands.Cog): ) await channel.send(user.mention, embed=embed) - @commands.cooldown(1, 1800, BucketType.user) + # @commands.cooldown(1, 1800, BucketType.user) @send_valentine.command(name='secret') async def anonymous( self, ctx: commands.Context, user: discord.Member, *, valentine_type: str = None @@ -131,11 +131,12 @@ class BeMyValentine(commands.Cog): await ctx.author.send(message) except discord.Forbidden: await ctx.send(message) + return if user == ctx.author: # Well a user cant valentine himself/herself. - await ctx.message.delete() - await ctx.send('Come on dude, you cant send a valentine to yourself :expressionless:') + await ctx.send('Come on, you cant send a valentine to yourself :expressionless:') + return emoji_1, emoji_2 = self.random_emoji() valentine, title = self.valentine_check(valentine_type) -- cgit v1.2.3 From 4d8e0c205aaa4a8e47486cccbeee383b5d899191 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sat, 6 Feb 2021 09:09:51 +0530 Subject: Remove debug code --- bot/exts/valentines/be_my_valentine.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/valentines/be_my_valentine.py b/bot/exts/valentines/be_my_valentine.py index d5668738..9ffa8769 100644 --- a/bot/exts/valentines/be_my_valentine.py +++ b/bot/exts/valentines/be_my_valentine.py @@ -109,7 +109,7 @@ class BeMyValentine(commands.Cog): ) await channel.send(user.mention, embed=embed) - # @commands.cooldown(1, 1800, BucketType.user) + @commands.cooldown(1, 1800, BucketType.user) @send_valentine.command(name='secret') async def anonymous( self, ctx: commands.Context, user: discord.Member, *, valentine_type: str = None -- cgit v1.2.3 From 24342ed41fea4079f464954fcaf873edcedabb07 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Sat, 6 Feb 2021 09:11:38 +0530 Subject: Small grammar fix --- bot/exts/valentines/be_my_valentine.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/valentines/be_my_valentine.py b/bot/exts/valentines/be_my_valentine.py index 9ffa8769..d79b28e8 100644 --- a/bot/exts/valentines/be_my_valentine.py +++ b/bot/exts/valentines/be_my_valentine.py @@ -135,7 +135,7 @@ class BeMyValentine(commands.Cog): if user == ctx.author: # Well a user cant valentine himself/herself. - await ctx.send('Come on, you cant send a valentine to yourself :expressionless:') + await ctx.send('Come on, you can\'t send a valentine to yourself :expressionless:') return emoji_1, emoji_2 = self.random_emoji() -- cgit v1.2.3 From 0073e85b0adce4de6246a2e1013e3d84808de481 Mon Sep 17 00:00:00 2001 From: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> Date: Sun, 7 Feb 2021 00:39:09 +0300 Subject: Overhauls In Channel Check Upgrades in channel check to support categories, and in the case of overrides, roles too. Signed-off-by: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> --- bot/__main__.py | 5 +-- bot/utils/decorators.py | 110 +++++++++++++++++++++++++++--------------------- 2 files changed, 63 insertions(+), 52 deletions(-) (limited to 'bot') diff --git a/bot/__main__.py b/bot/__main__.py index e9b14a53..c6e5fa57 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -6,10 +6,9 @@ from sentry_sdk.integrations.redis import RedisIntegration from bot.bot import bot from bot.constants import Client, GIT_SHA, STAFF_ROLES, WHITELISTED_CHANNELS -from bot.utils.decorators import in_channel_check +from bot.utils.decorators import whitelist_check from bot.utils.extensions import walk_extensions - sentry_logging = LoggingIntegration( level=logging.DEBUG, event_level=logging.WARNING @@ -26,7 +25,7 @@ sentry_sdk.init( log = logging.getLogger(__name__) -bot.add_check(in_channel_check(*WHITELISTED_CHANNELS, bypass_roles=STAFF_ROLES)) +bot.add_check(whitelist_check(channels=WHITELISTED_CHANNELS, roles=STAFF_ROLES)) for ext in walk_extensions(): bot.load_extension(ext) diff --git a/bot/utils/decorators.py b/bot/utils/decorators.py index 9cdaad3f..66b30b97 100644 --- a/bot/utils/decorators.py +++ b/bot/utils/decorators.py @@ -13,6 +13,7 @@ from discord.ext.commands import CheckFailure, Command, Context from bot.constants import ERROR_REPLIES, Month from bot.utils import human_months, resolve_current_month +from bot.utils.checks import in_whitelist_check ONE_DAY = 24 * 60 * 60 @@ -186,82 +187,93 @@ def without_role(*role_ids: int) -> t.Callable: return commands.check(predicate) -def in_channel_check(*channels: int, bypass_roles: t.Container[int] = None) -> t.Callable[[Context], bool]: +def whitelist_check(**default_kwargs: t.Container[int]) -> t.Callable[[Context], bool]: """ - Checks that the message is in a whitelisted channel or optionally has a bypass role. + Checks if a message is sent in a whitelisted context. - If `in_channel_override` is present, check if it contains channels - and use them in place of the global whitelist. + All arguments from `in_whitelist_check` are supported, with the exception of "fail_silently". + If `whitelist_override` is present, it is added to the global whitelist. """ def predicate(ctx: Context) -> bool: + # Skip DM invocations if not ctx.guild: log.debug(f"{ctx.author} tried to use the '{ctx.command.name}' command from a DM.") return True - if ctx.channel.id in channels: - log.debug( - f"{ctx.author} tried to call the '{ctx.command.name}' command " - f"and the command was used in a whitelisted channel." - ) - return True - if bypass_roles and any(r.id in bypass_roles for r in ctx.author.roles): - log.debug( - f"{ctx.author} called the '{ctx.command.name}' command and " - f"had a role to bypass the in_channel check." - ) - return True + kwargs = default_kwargs.copy() - if hasattr(ctx.command.callback, "in_channel_override"): - override = ctx.command.callback.in_channel_override - if override is None: + # Update kwargs based on override + if hasattr(ctx.command.callback, "override"): + # Remove default kwargs if reset is True + if ctx.command.callback.override_reset: + kwargs = {} log.debug( - f"{ctx.author} called the '{ctx.command.name}' command " - f"and the command was whitelisted to bypass the in_channel check." + f"{ctx.author} called the '{ctx.command.name}' command and " + f"overrode default checks." ) - return True - else: - if ctx.channel.id in override: - log.debug( - f"{ctx.author} tried to call the '{ctx.command.name}' command " - f"and the command was used in an overridden whitelisted channel." - ) - return True - log.debug( - f"{ctx.author} tried to call the '{ctx.command.name}' command. " - f"The overridden in_channel check failed." - ) - channels_str = ', '.join(f"<#{c_id}>" for c_id in override) - raise InChannelCheckFailure( - f"Sorry, but you may only use this command within {channels_str}." - ) + # Merge overwrites and defaults + for arg in ctx.command.callback.override: + default_value = kwargs.get(arg) + new_value = ctx.command.callback.override[arg] + + # Skip values that don't need merging, or can't be merged + if default_value is None or isinstance(arg, int): + kwargs[arg] = new_value + + # Merge containers + elif isinstance(default_value, t.Container): + if isinstance(new_value, t.Container): + kwargs[arg] = (*default_value, *new_value) + else: + kwargs[arg] = new_value + + log.debug( + f"Updated default check arguments for '{ctx.command.name}' " + f"invoked by {ctx.author}." + ) + + log.trace(f"Calling whitelist check for {ctx.author} for command {ctx.command.name}.") + result = in_whitelist_check(ctx, fail_silently=True, **kwargs) + + # Return if check passed + if result: + log.debug( + f"{ctx.author} tried to call the '{ctx.command.name}' command " + f"and the command was used in an overridden context." + ) + return result log.debug( f"{ctx.author} tried to call the '{ctx.command.name}' command. " - f"The in_channel check failed." - ) - - channels_str = ', '.join(f"<#{c_id}>" for c_id in channels) - raise InChannelCheckFailure( - f"Sorry, but you may only use this command within {channels_str}." + f"The whitelist check failed." ) - return predicate + # Raise error if the check did not pass + channels = kwargs.get("channels") + if channels: + channels_str = ', '.join(f"<#{c_id}>" for c_id in channels) + message = f"Sorry, but you may only use this command within {channels_str}." + else: + message = "Sorry, but you may not use this command." + raise InChannelCheckFailure(message) -in_channel = commands.check(in_channel_check) + return predicate -def override_in_channel(channels: t.Tuple[int] = None) -> t.Callable: +def whitelist_override(bypass_defaults: bool = False, **kwargs: t.Container[int]) -> t.Callable: """ - Set command callback attribute for detection in `in_channel_check`. + Override global whitelist context, with the kwargs specified. - Override global whitelist if channels are specified. + All arguments from `in_whitelist_check` are supported, with the exception of `fail_silently`. + Set `bypass_defaults` to True if you want to completely bypass global checks. This decorator has to go before (below) below the `command` decorator. """ def inner(func: t.Callable) -> t.Callable: - func.in_channel_override = channels + func.override = kwargs + func.override_reset = bypass_defaults return func return inner -- cgit v1.2.3 From 9e714107d3ebe6b5f17a9705cdb69aafd7e0a07d Mon Sep 17 00:00:00 2001 From: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> Date: Sun, 7 Feb 2021 00:42:19 +0300 Subject: Switches To Whitelist Check Switches all instances of override_in_channel to whitelist override. Signed-off-by: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> --- bot/exts/christmas/advent_of_code/_cog.py | 20 ++++++++++---------- bot/exts/evergreen/conversationstarters.py | 4 ++-- bot/exts/halloween/hacktoberstats.py | 8 ++++---- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'bot') diff --git a/bot/exts/christmas/advent_of_code/_cog.py b/bot/exts/christmas/advent_of_code/_cog.py index c3b87f96..466edd48 100644 --- a/bot/exts/christmas/advent_of_code/_cog.py +++ b/bot/exts/christmas/advent_of_code/_cog.py @@ -11,7 +11,7 @@ from bot.constants import ( AdventOfCode as AocConfig, Channels, Colours, Emojis, Month, Roles, WHITELISTED_CHANNELS, ) from bot.exts.christmas.advent_of_code import _helpers -from bot.utils.decorators import InChannelCheckFailure, in_month, override_in_channel, with_role +from bot.utils.decorators import InChannelCheckFailure, in_month, whitelist_override, with_role log = logging.getLogger(__name__) @@ -50,7 +50,7 @@ class AdventOfCode(commands.Cog): self.status_task.add_done_callback(_helpers.background_task_callback) @commands.group(name="adventofcode", aliases=("aoc",)) - @override_in_channel(AOC_WHITELIST) + @whitelist_override(channels=AOC_WHITELIST) async def adventofcode_group(self, ctx: commands.Context) -> None: """All of the Advent of Code commands.""" if not ctx.invoked_subcommand: @@ -61,7 +61,7 @@ class AdventOfCode(commands.Cog): aliases=("sub", "notifications", "notify", "notifs"), brief="Notifications for new days" ) - @override_in_channel(AOC_WHITELIST) + @whitelist_override(channels=AOC_WHITELIST) async def aoc_subscribe(self, ctx: commands.Context) -> None: """Assign the role for notifications about new days being ready.""" current_year = datetime.now().year @@ -82,7 +82,7 @@ class AdventOfCode(commands.Cog): @in_month(Month.DECEMBER) @adventofcode_group.command(name="unsubscribe", aliases=("unsub",), brief="Notifications for new days") - @override_in_channel(AOC_WHITELIST) + @whitelist_override(channels=AOC_WHITELIST) async def aoc_unsubscribe(self, ctx: commands.Context) -> None: """Remove the role for notifications about new days being ready.""" role = ctx.guild.get_role(AocConfig.role_id) @@ -94,7 +94,7 @@ class AdventOfCode(commands.Cog): await ctx.send("Hey, you don't even get any notifications about new Advent of Code tasks currently anyway.") @adventofcode_group.command(name="countdown", aliases=("count", "c"), brief="Return time left until next day") - @override_in_channel(AOC_WHITELIST) + @whitelist_override(channels=AOC_WHITELIST) async def aoc_countdown(self, ctx: commands.Context) -> None: """Return time left until next day.""" if not _helpers.is_in_advent(): @@ -123,13 +123,13 @@ class AdventOfCode(commands.Cog): await ctx.send(f"There are {hours} hours and {minutes} minutes left until day {tomorrow.day}.") @adventofcode_group.command(name="about", aliases=("ab", "info"), brief="Learn about Advent of Code") - @override_in_channel(AOC_WHITELIST) + @whitelist_override(channels=AOC_WHITELIST) async def about_aoc(self, ctx: commands.Context) -> None: """Respond with an explanation of all things Advent of Code.""" await ctx.send("", embed=self.cached_about_aoc) @adventofcode_group.command(name="join", aliases=("j",), brief="Learn how to join the leaderboard (via DM)") - @override_in_channel(AOC_WHITELIST) + @whitelist_override(channels=AOC_WHITELIST) async def join_leaderboard(self, ctx: commands.Context) -> None: """DM the user the information for joining the Python Discord leaderboard.""" current_year = datetime.now().year @@ -178,7 +178,7 @@ class AdventOfCode(commands.Cog): aliases=("board", "lb"), brief="Get a snapshot of the PyDis private AoC leaderboard", ) - @override_in_channel(AOC_WHITELIST_RESTRICTED) + @whitelist_override(channels=AOC_WHITELIST_RESTRICTED) async def aoc_leaderboard(self, ctx: commands.Context) -> None: """Get the current top scorers of the Python Discord Leaderboard.""" async with ctx.typing(): @@ -203,7 +203,7 @@ class AdventOfCode(commands.Cog): aliases=("globalboard", "gb"), brief="Get a link to the global leaderboard", ) - @override_in_channel(AOC_WHITELIST_RESTRICTED) + @whitelist_override(channels=AOC_WHITELIST_RESTRICTED) async def aoc_global_leaderboard(self, ctx: commands.Context) -> None: """Get a link to the global Advent of Code leaderboard.""" url = self.global_leaderboard_url @@ -219,7 +219,7 @@ class AdventOfCode(commands.Cog): aliases=("dailystats", "ds"), brief="Get daily statistics for the Python Discord leaderboard" ) - @override_in_channel(AOC_WHITELIST_RESTRICTED) + @whitelist_override(channels=AOC_WHITELIST_RESTRICTED) async def private_leaderboard_daily_stats(self, ctx: commands.Context) -> None: """Send an embed with daily completion statistics for the Python Discord leaderboard.""" try: diff --git a/bot/exts/evergreen/conversationstarters.py b/bot/exts/evergreen/conversationstarters.py index 576b8d76..e7058961 100644 --- a/bot/exts/evergreen/conversationstarters.py +++ b/bot/exts/evergreen/conversationstarters.py @@ -5,7 +5,7 @@ from discord import Color, Embed from discord.ext import commands from bot.constants import WHITELISTED_CHANNELS -from bot.utils.decorators import override_in_channel +from bot.utils.decorators import whitelist_override from bot.utils.randomization import RandomCycle SUGGESTION_FORM = 'https://forms.gle/zw6kkJqv8U43Nfjg9' @@ -38,7 +38,7 @@ class ConvoStarters(commands.Cog): self.bot = bot @commands.command() - @override_in_channel(ALL_ALLOWED_CHANNELS) + @whitelist_override(channels=ALL_ALLOWED_CHANNELS) async def topic(self, ctx: commands.Context) -> None: """ Responds with a random topic to start a conversation. diff --git a/bot/exts/halloween/hacktoberstats.py b/bot/exts/halloween/hacktoberstats.py index a1c55922..d9fc0e8a 100644 --- a/bot/exts/halloween/hacktoberstats.py +++ b/bot/exts/halloween/hacktoberstats.py @@ -11,7 +11,7 @@ from async_rediscache import RedisCache from discord.ext import commands from bot.constants import Channels, Month, NEGATIVE_REPLIES, Tokens, WHITELISTED_CHANNELS -from bot.utils.decorators import in_month, override_in_channel +from bot.utils.decorators import in_month, whitelist_override log = logging.getLogger(__name__) @@ -44,7 +44,7 @@ class HacktoberStats(commands.Cog): @in_month(Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER) @commands.group(name="hacktoberstats", aliases=("hackstats",), invoke_without_command=True) - @override_in_channel(HACKTOBER_WHITELIST) + @whitelist_override(channels=HACKTOBER_WHITELIST) async def hacktoberstats_group(self, ctx: commands.Context, github_username: str = None) -> None: """ Display an embed for a user's Hacktoberfest contributions. @@ -72,7 +72,7 @@ class HacktoberStats(commands.Cog): @in_month(Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER) @hacktoberstats_group.command(name="link") - @override_in_channel(HACKTOBER_WHITELIST) + @whitelist_override(channels=HACKTOBER_WHITELIST) async def link_user(self, ctx: commands.Context, github_username: str = None) -> None: """ Link the invoking user's Github github_username to their Discord ID. @@ -96,7 +96,7 @@ class HacktoberStats(commands.Cog): @in_month(Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER) @hacktoberstats_group.command(name="unlink") - @override_in_channel(HACKTOBER_WHITELIST) + @whitelist_override(channels=HACKTOBER_WHITELIST) async def unlink_user(self, ctx: commands.Context) -> None: """Remove the invoking user's account link from the log.""" author_id, author_mention = self._author_mention_from_context(ctx) -- cgit v1.2.3 From ba439921a2164613ea7809cc006c621500bd727e Mon Sep 17 00:00:00 2001 From: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> Date: Sun, 7 Feb 2021 09:42:24 +0300 Subject: Adds Whitelist Check To Cheat Sheet Signed-off-by: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> --- bot/exts/evergreen/cheatsheet.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/cheatsheet.py b/bot/exts/evergreen/cheatsheet.py index 97485365..8e61f63e 100644 --- a/bot/exts/evergreen/cheatsheet.py +++ b/bot/exts/evergreen/cheatsheet.py @@ -8,8 +8,8 @@ from discord.ext import commands from discord.ext.commands import BucketType, Context from bot import constants -from bot.constants import Categories, Channels, Colours, ERROR_REPLIES, Roles, WHITELISTED_CHANNELS -from bot.utils.decorators import with_role +from bot.constants import Categories, Channels, Colours, ERROR_REPLIES +from bot.utils.decorators import whitelist_override ERROR_MESSAGE = f""" Unknown cheat sheet. Please try to reformulate your query. @@ -73,7 +73,7 @@ class CheatSheet(commands.Cog): aliases=("cht.sh", "cheatsheet", "cheat-sheet", "cht"), ) @commands.cooldown(1, 10, BucketType.user) - @with_role(Roles.everyone_role) + @whitelist_override(categories=[Categories.help_in_use]) async def cheat_sheet(self, ctx: Context, *search_terms: str) -> None: """ Search cheat.sh. @@ -82,12 +82,6 @@ class CheatSheet(commands.Cog): Usage: --> .cht read json """ - if not ( - ctx.channel.category.id == Categories.help_in_use - or ctx.channel.id in WHITELISTED_CHANNELS - ): - return - async with ctx.typing(): search_string = quote_plus(" ".join(search_terms)) -- cgit v1.2.3 From 73f11e22deda8bc25a03c75f3b7f380dd7f67f4e Mon Sep 17 00:00:00 2001 From: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> Date: Sun, 7 Feb 2021 10:09:06 +0300 Subject: Adds Category Channels To Error Message Adds the channels within categories to the failure message of the command whitelist check. Signed-off-by: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> --- bot/utils/decorators.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/utils/decorators.py b/bot/utils/decorators.py index 66b30b97..c12a15ff 100644 --- a/bot/utils/decorators.py +++ b/bot/utils/decorators.py @@ -250,7 +250,18 @@ def whitelist_check(**default_kwargs: t.Container[int]) -> t.Callable[[Context], ) # Raise error if the check did not pass - channels = kwargs.get("channels") + channels = set(kwargs.get("channels") or {}) + categories = kwargs.get("categories") + + # Add all whitelisted category channels + if categories: + for category_id in categories: + category = ctx.guild.get_channel(category_id) + if category is None: + continue + + [channels.add(channel.id) for channel in category.text_channels] + if channels: channels_str = ', '.join(f"<#{c_id}>" for c_id in channels) message = f"Sorry, but you may only use this command within {channels_str}." -- cgit v1.2.3 From 3242cc6c1dba0a0ecf3b5c0cdf5b90a4784dbfd1 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Mon, 8 Feb 2021 05:51:14 +0530 Subject: Add curl User Agent Headers --- bot/exts/evergreen/cheatsheet.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/cheatsheet.py b/bot/exts/evergreen/cheatsheet.py index 97485365..f6dce995 100644 --- a/bot/exts/evergreen/cheatsheet.py +++ b/bot/exts/evergreen/cheatsheet.py @@ -26,6 +26,7 @@ If the problem persists send a message in <#{Channels.dev_contrib}> URL = 'https://cheat.sh/python/{search}' ESCAPE_TT = str.maketrans({"`": "\\`"}) ANSI_RE = re.compile(r"\x1b\[.*?m") +HEADERS = {'User-Agent': 'curl/7.68.0'} class CheatSheet(commands.Cog): @@ -92,7 +93,7 @@ class CheatSheet(commands.Cog): search_string = quote_plus(" ".join(search_terms)) async with self.bot.http_session.get( - URL.format(search=search_string) + URL.format(search=search_string), headers=HEADERS ) as response: result = ANSI_RE.sub("", await response.text()).translate(ESCAPE_TT) -- cgit v1.2.3 From 8321add8d6a55132c96a620da2aac5c4bc44c284 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Mon, 8 Feb 2021 06:59:24 +0530 Subject: Use emojis library to do the check instead of checking len() == 1 since some emojis are made of len() > 1 --- Pipfile | 1 + Pipfile.lock | 55 ++++++++++++++++++++++---------------- bot/exts/evergreen/connect_four.py | 9 ++++--- 3 files changed, 39 insertions(+), 26 deletions(-) (limited to 'bot') diff --git a/Pipfile b/Pipfile index c382902f..e7e01a31 100644 --- a/Pipfile +++ b/Pipfile @@ -14,6 +14,7 @@ sentry-sdk = "~=0.19" PyYAML = "~=5.3.1" "discord.py" = {extras = ["voice"], version = "~=1.5.1"} async-rediscache = {extras = ["fakeredis"], version = "~=0.1.4"} +emojis = "~=0.6.0" [dev-packages] flake8 = "~=3.8" diff --git a/Pipfile.lock b/Pipfile.lock index be6f9574..cca89cf9 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "9be419062bd9db364ac9dddfcd50aef9c932384b45850363e482591fe7d12403" + "sha256": "b4aaaacbab13179145e36d7b86c736db512286f6cce8e513cc30c48d68fe3810" }, "pipfile-spec": 6, "requires": { @@ -119,6 +119,7 @@ "sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009", "sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03", "sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b", + "sha256:7ef7d4ced6b325e92eb4d3502946c78c5367bc416398d387b39591532536734e", "sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909", "sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53", "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35", @@ -160,6 +161,14 @@ "index": "pypi", "version": "==1.5.1" }, + "emojis": { + "hashes": [ + "sha256:7da34c8a78ae262fd68cef9e2c78a3c1feb59784489eeea0f54ba1d4b7111c7c", + "sha256:bf605d1f1a27a81cd37fe82eb65781c904467f569295a541c33710b97e4225ec" + ], + "index": "pypi", + "version": "==0.6.0" + }, "fakeredis": { "hashes": [ "sha256:01cb47d2286825a171fb49c0e445b1fa9307087e07cbb3d027ea10dbff108b6a", @@ -229,11 +238,11 @@ }, "idna": { "hashes": [ - "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", - "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" + "sha256:5205d03e7bcbb919cc9c19885f9920d622ca52448306f2377daede5cf3faac16", + "sha256:c5b02147e01ea9920e6b0a3f1f7bb833612d507592c837a6c49552768f4054e1" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.10" + "markers": "python_version >= '3.4'", + "version": "==3.1" }, "multidict": { "hashes": [ @@ -436,11 +445,11 @@ }, "urllib3": { "hashes": [ - "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08", - "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473" + "sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80", + "sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", - "version": "==1.26.2" + "version": "==1.26.3" }, "yarl": { "hashes": [ @@ -514,11 +523,11 @@ }, "flake8-annotations": { "hashes": [ - "sha256:0bcebb0792f1f96d617ded674dca7bf64181870bfe5dace353a1483551f8e5f1", - "sha256:bebd11a850f6987a943ce8cdff4159767e0f5f89b3c88aca64680c2175ee02df" + "sha256:3a377140556aecf11fa9f3bb18c10db01f5ea56dc79a730e2ec9b4f1f49e2055", + "sha256:e17947a48a5b9f632fe0c72682fc797c385e451048e7dfb20139f448a074cb3e" ], "index": "pypi", - "version": "==2.4.1" + "version": "==2.5.0" }, "flake8-bugbear": { "hashes": [ @@ -576,11 +585,11 @@ }, "identify": { "hashes": [ - "sha256:943cd299ac7f5715fcb3f684e2fc1594c1e0f22a90d15398e5888143bd4144b5", - "sha256:cc86e6a9a390879dcc2976cef169dd9cc48843ed70b7380f321d1b118163c60e" + "sha256:70b638cf4743f33042bebb3b51e25261a0a10e80f978739f17e7fd4837664a66", + "sha256:9dfb63a2e871b807e3ba62f029813552a24b5289504f5b071dea9b041aee9fe4" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.5.10" + "version": "==1.5.13" }, "mccabe": { "hashes": [ @@ -606,11 +615,11 @@ }, "pre-commit": { "hashes": [ - "sha256:6c86d977d00ddc8a60d68eec19f51ef212d9462937acf3ea37c7adec32284ac0", - "sha256:ee784c11953e6d8badb97d19bc46b997a3a9eded849881ec587accd8608d74a4" + "sha256:16212d1fde2bed88159287da88ff03796863854b04dc9f838a55979325a3d20e", + "sha256:399baf78f13f4de82a29b649afd74bef2c4e28eb4f021661fc7f29246e8c7a3a" ], "index": "pypi", - "version": "==2.9.3" + "version": "==2.10.1" }, "pycodestyle": { "hashes": [ @@ -665,10 +674,10 @@ }, "snowballstemmer": { "hashes": [ - "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0", - "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52" + "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2", + "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914" ], - "version": "==2.0.0" + "version": "==2.1.0" }, "toml": { "hashes": [ @@ -680,11 +689,11 @@ }, "virtualenv": { "hashes": [ - "sha256:54b05fc737ea9c9ee9f8340f579e5da5b09fb64fd010ab5757eb90268616907c", - "sha256:b7a8ec323ee02fb2312f098b6b4c9de99559b462775bc8fe3627a73706603c1b" + "sha256:147b43894e51dd6bba882cf9c282447f780e2251cd35172403745fc381a0a80d", + "sha256:2be72df684b74df0ea47679a7df93fd0e04e72520022c57b479d8f881485dbe3" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==20.2.2" + "version": "==20.4.2" } } } diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index bf604e2a..02e876f4 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -4,6 +4,7 @@ import typing from functools import partial import discord +import emojis from discord.ext import commands NUMBERS = [ @@ -342,11 +343,13 @@ class ConnectFour(commands.Cog): return any(player in (game.player1, game.player2) for game in self.games) @staticmethod - def check_emojis(e1: EMOJI_CHECK, e2: EMOJI_CHECK) -> typing.Tuple[bool, typing.Optional[str]]: + def check_emojis( + e1: EMOJI_CHECK, e2: EMOJI_CHECK + ) -> typing.Tuple[bool, typing.Optional[str]]: """Validate the emojis, the user put.""" - if isinstance(e1, str) and len(e1) > 1: + if isinstance(e1, str) and emojis.count(e1) != 1: return False, e1 - if isinstance(e2, str) and len(e2) > 1: + if isinstance(e2, str) and emojis.count(e2) != 1: return False, e2 return True, None -- cgit v1.2.3 From af1d11067daf1304c3c166202c13d8373da9e9b7 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Mon, 8 Feb 2021 14:08:54 +0530 Subject: Add comment explaining why we need to pass curl as user agent --- bot/exts/evergreen/cheatsheet.py | 1 + 1 file changed, 1 insertion(+) (limited to 'bot') diff --git a/bot/exts/evergreen/cheatsheet.py b/bot/exts/evergreen/cheatsheet.py index f6dce995..a64ddd69 100644 --- a/bot/exts/evergreen/cheatsheet.py +++ b/bot/exts/evergreen/cheatsheet.py @@ -26,6 +26,7 @@ If the problem persists send a message in <#{Channels.dev_contrib}> URL = 'https://cheat.sh/python/{search}' ESCAPE_TT = str.maketrans({"`": "\\`"}) ANSI_RE = re.compile(r"\x1b\[.*?m") +# We need to pass headers as curl otherwise it would default to aiohttp which would return raw html. HEADERS = {'User-Agent': 'curl/7.68.0'} -- cgit v1.2.3 From 2f032a71beadd6c9613b89d525004c98a4cf6ab9 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Tue, 9 Feb 2021 11:41:28 +0100 Subject: Add location mocks to the wolfram cog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously the server IP address could be leaked using some query such as “what is the weather here?” or simply “what’s my ip?”. This aims to fix it by using mock locations. --- bot/exts/evergreen/wolfram.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/wolfram.py b/bot/exts/evergreen/wolfram.py index 898e8d2a..d3b4df5c 100644 --- a/bot/exts/evergreen/wolfram.py +++ b/bot/exts/evergreen/wolfram.py @@ -108,7 +108,10 @@ async def get_pod_pages(ctx: Context, bot: commands.Bot, query: str) -> Optional "input": query, "appid": APPID, "output": DEFAULT_OUTPUT_FORMAT, - "format": "image,plaintext" + "format": "image,plaintext", + "location": "the moon", + "latlong": "0.0,0.0", + "ip": "1.1.1.1" }) request_url = QUERY.format(request="query", data=url_str) -- cgit v1.2.3 From 87c4066eb016dace5d48d87fba83ce6424408878 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Tue, 9 Feb 2021 12:22:26 +0100 Subject: Apply mock locations to every subcommands --- bot/exts/evergreen/wolfram.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'bot') diff --git a/bot/exts/evergreen/wolfram.py b/bot/exts/evergreen/wolfram.py index d3b4df5c..437d9e1a 100644 --- a/bot/exts/evergreen/wolfram.py +++ b/bot/exts/evergreen/wolfram.py @@ -171,6 +171,9 @@ class Wolfram(Cog): url_str = parse.urlencode({ "i": query, "appid": APPID, + "location": "the moon", + "latlong": "0.0,0.0", + "ip": "1.1.1.1" }) query = QUERY.format(request="simple", data=url_str) @@ -251,6 +254,9 @@ class Wolfram(Cog): url_str = parse.urlencode({ "i": query, "appid": APPID, + "location": "the moon", + "latlong": "0.0,0.0", + "ip": "1.1.1.1" }) query = QUERY.format(request="result", data=url_str) -- cgit v1.2.3 From 4c6d87c48bc44235a511f9266f986c219ac93f7e Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 13 Feb 2021 15:44:27 +0000 Subject: Raise user input error to reset cd --- bot/exts/valentines/be_my_valentine.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'bot') diff --git a/bot/exts/valentines/be_my_valentine.py b/bot/exts/valentines/be_my_valentine.py index d79b28e8..aac38edb 100644 --- a/bot/exts/valentines/be_my_valentine.py +++ b/bot/exts/valentines/be_my_valentine.py @@ -86,17 +86,17 @@ class BeMyValentine(commands.Cog): # This command should only be used in the server msg = "You are supposed to use this command in the server." await ctx.send(msg) - return + raise commands.UserInputError if Lovefest.role_id not in [role.id for role in user.roles]: message = f"You cannot send a valentine to {user} as they do not have the lovefest role!" await ctx.send(message) - return + raise commands.UserInputError if user == ctx.author: # Well a user can't valentine himself/herself. await ctx.send("Come on, you can't send a valentine to yourself :expressionless:") - return + raise commands.UserInputError emoji_1, emoji_2 = self.random_emoji() channel = self.bot.get_channel(Channels.community_bot_commands) @@ -131,12 +131,12 @@ class BeMyValentine(commands.Cog): await ctx.author.send(message) except discord.Forbidden: await ctx.send(message) - return + raise commands.UserInputError if user == ctx.author: # Well a user cant valentine himself/herself. await ctx.send('Come on, you can\'t send a valentine to yourself :expressionless:') - return + raise commands.UserInputError emoji_1, emoji_2 = self.random_emoji() valentine, title = self.valentine_check(valentine_type) @@ -151,6 +151,7 @@ class BeMyValentine(commands.Cog): await ctx.message.delete() except discord.Forbidden: await ctx.send(f"{user} has DMs disabled, so I couldn't send the message. Sorry!") + raise commands.UserInputError else: await ctx.author.send(f"Your message has been sent to {user}") -- cgit v1.2.3 From 8bc6f497d01d6b848ba868f4ac662100cdee48d3 Mon Sep 17 00:00:00 2001 From: MrKomodoDragon Date: Sat, 13 Feb 2021 11:03:14 -0800 Subject: Added description and url to embed of xkcd command --- bot/exts/evergreen/xkcd.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'bot') diff --git a/bot/exts/evergreen/xkcd.py b/bot/exts/evergreen/xkcd.py index d3224bfe..43f05864 100644 --- a/bot/exts/evergreen/xkcd.py +++ b/bot/exts/evergreen/xkcd.py @@ -69,6 +69,8 @@ class XKCD(Cog): return embed.title = f"XKCD comic #{info['num']}" + embed.description = info['alt'] + embed.url = f"{BASE_URL}/{comic}" if info["img"][-3:] in ("jpg", "png", "gif"): embed.set_image(url=info["img"]) -- cgit v1.2.3 From 7343af2b3a3cd0d0333a16de0557435ba21ba7ce Mon Sep 17 00:00:00 2001 From: MrKomodoDragon Date: Sat, 13 Feb 2021 11:34:37 -0800 Subject: FIxed error in which link would 404 if user did .xkcd latest --- Pipfile.lock | 132 ++++++++++++++++++++++----------------------- bot/exts/evergreen/xkcd.py | 2 +- 2 files changed, 67 insertions(+), 67 deletions(-) (limited to 'bot') diff --git a/Pipfile.lock b/Pipfile.lock index be6f9574..bd894ffa 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -103,44 +103,45 @@ }, "cffi": { "hashes": [ - "sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e", - "sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d", - "sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a", - "sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec", - "sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362", - "sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668", - "sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c", - "sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b", - "sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06", - "sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698", - "sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2", - "sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c", - "sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7", - "sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009", - "sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03", - "sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b", - "sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909", - "sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53", - "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35", - "sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26", - "sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b", - "sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01", - "sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb", - "sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293", - "sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd", - "sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d", - "sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3", - "sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d", - "sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e", - "sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca", - "sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d", - "sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775", - "sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375", - "sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b", - "sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b", - "sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f" - ], - "version": "==1.14.4" + "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813", + "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06", + "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea", + "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee", + "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396", + "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73", + "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315", + "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1", + "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49", + "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892", + "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482", + "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058", + "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5", + "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53", + "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045", + "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3", + "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5", + "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e", + "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c", + "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369", + "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827", + "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053", + "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa", + "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4", + "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322", + "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132", + "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62", + "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa", + "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0", + "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396", + "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e", + "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991", + "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6", + "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1", + "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406", + "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d", + "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c" + ], + "version": "==1.14.5" }, "chardet": { "hashes": [ @@ -229,11 +230,11 @@ }, "idna": { "hashes": [ - "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", - "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" + "sha256:5205d03e7bcbb919cc9c19885f9920d622ca52448306f2377daede5cf3faac16", + "sha256:c5b02147e01ea9920e6b0a3f1f7bb833612d507592c837a6c49552768f4054e1" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.10" + "markers": "python_version >= '3.4'", + "version": "==3.1" }, "multidict": { "hashes": [ @@ -405,11 +406,10 @@ }, "sentry-sdk": { "hashes": [ - "sha256:0a711ec952441c2ec89b8f5d226c33bc697914f46e876b44a4edd3e7864cf4d0", - "sha256:737a094e49a529dd0fdcaafa9e97cf7c3d5eb964bd229821d640bc77f3502b3f" + "sha256:3693cb47ba8d90c004ac002425770b32aaf0c83a846ec48e2d1364e7db1d072d" ], "index": "pypi", - "version": "==0.19.5" + "version": "==0.20.1" }, "six": { "hashes": [ @@ -428,19 +428,19 @@ }, "soupsieve": { "hashes": [ - "sha256:4bb21a6ee4707bf43b61230e80740e71bfe56e55d1f1f50924b087bb2975c851", - "sha256:6dc52924dc0bc710a5d16794e6b3480b2c7c08b07729505feab2b2c16661ff6e" + "sha256:407fa1e8eb3458d1b5614df51d9651a1180ea5fedf07feb46e45d7e25e6d6cdd", + "sha256:d3a5ea5b350423f47d07639f74475afedad48cf41c0ad7a82ca13a3928af34f6" ], "markers": "python_version >= '3.0'", - "version": "==2.1" + "version": "==2.2" }, "urllib3": { "hashes": [ - "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08", - "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473" + "sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80", + "sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", - "version": "==1.26.2" + "version": "==1.26.3" }, "yarl": { "hashes": [ @@ -514,11 +514,11 @@ }, "flake8-annotations": { "hashes": [ - "sha256:0bcebb0792f1f96d617ded674dca7bf64181870bfe5dace353a1483551f8e5f1", - "sha256:bebd11a850f6987a943ce8cdff4159767e0f5f89b3c88aca64680c2175ee02df" + "sha256:3a377140556aecf11fa9f3bb18c10db01f5ea56dc79a730e2ec9b4f1f49e2055", + "sha256:e17947a48a5b9f632fe0c72682fc797c385e451048e7dfb20139f448a074cb3e" ], "index": "pypi", - "version": "==2.4.1" + "version": "==2.5.0" }, "flake8-bugbear": { "hashes": [ @@ -576,11 +576,11 @@ }, "identify": { "hashes": [ - "sha256:943cd299ac7f5715fcb3f684e2fc1594c1e0f22a90d15398e5888143bd4144b5", - "sha256:cc86e6a9a390879dcc2976cef169dd9cc48843ed70b7380f321d1b118163c60e" + "sha256:70b638cf4743f33042bebb3b51e25261a0a10e80f978739f17e7fd4837664a66", + "sha256:9dfb63a2e871b807e3ba62f029813552a24b5289504f5b071dea9b041aee9fe4" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.5.10" + "version": "==1.5.13" }, "mccabe": { "hashes": [ @@ -606,11 +606,11 @@ }, "pre-commit": { "hashes": [ - "sha256:6c86d977d00ddc8a60d68eec19f51ef212d9462937acf3ea37c7adec32284ac0", - "sha256:ee784c11953e6d8badb97d19bc46b997a3a9eded849881ec587accd8608d74a4" + "sha256:16212d1fde2bed88159287da88ff03796863854b04dc9f838a55979325a3d20e", + "sha256:399baf78f13f4de82a29b649afd74bef2c4e28eb4f021661fc7f29246e8c7a3a" ], "index": "pypi", - "version": "==2.9.3" + "version": "==2.10.1" }, "pycodestyle": { "hashes": [ @@ -665,10 +665,10 @@ }, "snowballstemmer": { "hashes": [ - "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0", - "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52" + "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2", + "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914" ], - "version": "==2.0.0" + "version": "==2.1.0" }, "toml": { "hashes": [ @@ -680,11 +680,11 @@ }, "virtualenv": { "hashes": [ - "sha256:54b05fc737ea9c9ee9f8340f579e5da5b09fb64fd010ab5757eb90268616907c", - "sha256:b7a8ec323ee02fb2312f098b6b4c9de99559b462775bc8fe3627a73706603c1b" + "sha256:147b43894e51dd6bba882cf9c282447f780e2251cd35172403745fc381a0a80d", + "sha256:2be72df684b74df0ea47679a7df93fd0e04e72520022c57b479d8f881485dbe3" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==20.2.2" + "version": "==20.4.2" } } } diff --git a/bot/exts/evergreen/xkcd.py b/bot/exts/evergreen/xkcd.py index 43f05864..1ff98ca2 100644 --- a/bot/exts/evergreen/xkcd.py +++ b/bot/exts/evergreen/xkcd.py @@ -70,7 +70,7 @@ class XKCD(Cog): embed.title = f"XKCD comic #{info['num']}" embed.description = info['alt'] - embed.url = f"{BASE_URL}/{comic}" + embed.url = f"{BASE_URL}/{info['num']}" if info["img"][-3:] in ("jpg", "png", "gif"): embed.set_image(url=info["img"]) -- cgit v1.2.3 From 2d33d53bf2c3a26e68abdcf2a2f91dac5bd495fc Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 13 Feb 2021 23:12:43 +0000 Subject: Output message in the same embed. --- bot/exts/valentines/be_my_valentine.py | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) (limited to 'bot') diff --git a/bot/exts/valentines/be_my_valentine.py b/bot/exts/valentines/be_my_valentine.py index aac38edb..fe52936b 100644 --- a/bot/exts/valentines/be_my_valentine.py +++ b/bot/exts/valentines/be_my_valentine.py @@ -84,19 +84,16 @@ class BeMyValentine(commands.Cog): """ 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." - await ctx.send(msg) - raise commands.UserInputError + raise commands.UserInputError("You are supposed to use this command in the server.") if Lovefest.role_id not in [role.id for role in user.roles]: - message = f"You cannot send a valentine to {user} as they do not have the lovefest role!" - await ctx.send(message) - raise commands.UserInputError + raise commands.UserInputError( + f"You cannot send a valentine to {user} as they do not have the lovefest role!" + ) if user == ctx.author: # Well a user can't valentine himself/herself. - await ctx.send("Come on, you can't send a valentine to yourself :expressionless:") - raise commands.UserInputError + raise commands.UserInputError("Come on, you can't send a valentine to yourself :expressionless:") emoji_1, emoji_2 = self.random_emoji() channel = self.bot.get_channel(Channels.community_bot_commands) @@ -125,18 +122,14 @@ class BeMyValentine(commands.Cog): Iceman in DM making you anonymous) """ if Lovefest.role_id not in [role.id for role in user.roles]: - message = f"You cannot send a valentine to {user} as they do not have the lovefest role!" await ctx.message.delete() - try: - await ctx.author.send(message) - except discord.Forbidden: - await ctx.send(message) - raise commands.UserInputError + raise commands.UserInputError( + f"You cannot send a valentine to {user}> as they do not have the lovefest role!" + ) if user == ctx.author: # Well a user cant valentine himself/herself. - await ctx.send('Come on, you can\'t send a valentine to yourself :expressionless:') - raise commands.UserInputError + raise commands.UserInputError("Come on, you can't send a valentine to yourself :expressionless:") emoji_1, emoji_2 = self.random_emoji() valentine, title = self.valentine_check(valentine_type) @@ -146,12 +139,11 @@ class BeMyValentine(commands.Cog): description=f'{valentine} \n **{emoji_2}From anonymous{emoji_1}**', color=Colours.pink ) + await ctx.message.delete() try: await user.send(embed=embed) - await ctx.message.delete() except discord.Forbidden: - await ctx.send(f"{user} has DMs disabled, so I couldn't send the message. Sorry!") - raise commands.UserInputError + raise commands.UserInputError(f"{user} has DMs disabled, so I couldn't send the message. Sorry!") else: await ctx.author.send(f"Your message has been sent to {user}") -- cgit v1.2.3 From ab5e00d836a4c01c581a877c2dc992f3fa8d9243 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 13 Feb 2021 23:16:48 +0000 Subject: Remove leftover > from testing. --- bot/exts/valentines/be_my_valentine.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/valentines/be_my_valentine.py b/bot/exts/valentines/be_my_valentine.py index fe52936b..f3392bcb 100644 --- a/bot/exts/valentines/be_my_valentine.py +++ b/bot/exts/valentines/be_my_valentine.py @@ -124,7 +124,7 @@ class BeMyValentine(commands.Cog): if Lovefest.role_id not in [role.id for role in user.roles]: await ctx.message.delete() raise commands.UserInputError( - f"You cannot send a valentine to {user}> as they do not have the lovefest role!" + f"You cannot send a valentine to {user} as they do not have the lovefest role!" ) if user == ctx.author: -- cgit v1.2.3 From 7ba7149c688ba35d60934fdc68b92b82862065c7 Mon Sep 17 00:00:00 2001 From: MrKomodoDragon Date: Tue, 16 Feb 2021 09:10:57 -0800 Subject: Add .pyfacts command --- bot/exts/evergreen/pythonfacts.py | 23 +++++++++++++++++++++++ bot/resources/evergreen/python_facts.txt | 3 +++ 2 files changed, 26 insertions(+) create mode 100644 bot/exts/evergreen/pythonfacts.py create mode 100644 bot/resources/evergreen/python_facts.txt (limited to 'bot') diff --git a/bot/exts/evergreen/pythonfacts.py b/bot/exts/evergreen/pythonfacts.py new file mode 100644 index 00000000..ba792561 --- /dev/null +++ b/bot/exts/evergreen/pythonfacts.py @@ -0,0 +1,23 @@ +import random + +import discord +from discord.ext import commands +from discord.ext.commands.bot import Bot + + +class PythonFacts(commands.Cog): + """Gives a random fun fact about Python.""" + + def __init__(self, bot: Bot) -> None: + self.bot = bot + + @commands.command(name='pythonfact', aliases=['pyfact']) + async def get_python_fact(self, ctx: commands.Context) -> None: + """Gives a Random fun fact about Python.""" + with open('bot/resources/evergreen/python_facts.txt') as file: + await ctx.send(embed=discord.Embed(title='Python Facts', description=f'**{random.choice(list(file))}**')) + + +def setup(bot: commands.Bot) -> None: + """Adding the cog to the bot.""" + bot.add_cog(PythonFacts(bot)) diff --git a/bot/resources/evergreen/python_facts.txt b/bot/resources/evergreen/python_facts.txt new file mode 100644 index 00000000..d9e63a11 --- /dev/null +++ b/bot/resources/evergreen/python_facts.txt @@ -0,0 +1,3 @@ +Python was named after Monty Python, which Guido van Rossum likes. +If you type `import this` in the Python REPL, you'll get a poem about the philosophies about Python. (check it out by doing !zen in <#267659945086812160>) +If you type `import antigravity` in the Python REPL, you'll be directed to an [xkcd comic](https://xkcd.com/353/) about how easy Python is. -- cgit v1.2.3 From fdfa5c75b74a898512bfac6fa3ac14d452eae05d Mon Sep 17 00:00:00 2001 From: MrKomodoDragon Date: Tue, 16 Feb 2021 10:44:21 -0800 Subject: Remove unused import --- bot/exts/evergreen/pythonfacts.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/pythonfacts.py b/bot/exts/evergreen/pythonfacts.py index ba792561..b1c28d4b 100644 --- a/bot/exts/evergreen/pythonfacts.py +++ b/bot/exts/evergreen/pythonfacts.py @@ -2,13 +2,12 @@ import random import discord from discord.ext import commands -from discord.ext.commands.bot import Bot class PythonFacts(commands.Cog): """Gives a random fun fact about Python.""" - def __init__(self, bot: Bot) -> None: + def __init__(self, bot: commands.Bot) -> None: self.bot = bot @commands.command(name='pythonfact', aliases=['pyfact']) -- cgit v1.2.3 From 06d600f0fd927e566d23879638d10c6d66a63a21 Mon Sep 17 00:00:00 2001 From: MrKomodoDragon Date: Tue, 16 Feb 2021 10:48:13 -0800 Subject: Move loading of file outside of command --- bot/exts/evergreen/pythonfacts.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/pythonfacts.py b/bot/exts/evergreen/pythonfacts.py index b1c28d4b..c6592add 100644 --- a/bot/exts/evergreen/pythonfacts.py +++ b/bot/exts/evergreen/pythonfacts.py @@ -4,6 +4,10 @@ import discord from discord.ext import commands +with open('bot/resources/evergreen/python_facts.txt') as file: + FACTS = list(file) + + class PythonFacts(commands.Cog): """Gives a random fun fact about Python.""" @@ -13,8 +17,7 @@ class PythonFacts(commands.Cog): @commands.command(name='pythonfact', aliases=['pyfact']) async def get_python_fact(self, ctx: commands.Context) -> None: """Gives a Random fun fact about Python.""" - with open('bot/resources/evergreen/python_facts.txt') as file: - await ctx.send(embed=discord.Embed(title='Python Facts', description=f'**{random.choice(list(file))}**')) + await ctx.send(embed=discord.Embed(title='Python Facts', description=f'**{random.choice(FACTS)}**')) def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From 57aec016ac74465212744a9ec4173515dca98ba1 Mon Sep 17 00:00:00 2001 From: MrKomodoDragon <74436682+MrKomodoDragon@users.noreply.github.com> Date: Tue, 16 Feb 2021 17:57:51 -0800 Subject: Remove bold Co-authored-by: Shivansh-007 <69356296+Shivansh-007@users.noreply.github.com> --- bot/exts/evergreen/pythonfacts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/pythonfacts.py b/bot/exts/evergreen/pythonfacts.py index c6592add..fcb78168 100644 --- a/bot/exts/evergreen/pythonfacts.py +++ b/bot/exts/evergreen/pythonfacts.py @@ -17,7 +17,7 @@ class PythonFacts(commands.Cog): @commands.command(name='pythonfact', aliases=['pyfact']) async def get_python_fact(self, ctx: commands.Context) -> None: """Gives a Random fun fact about Python.""" - await ctx.send(embed=discord.Embed(title='Python Facts', description=f'**{random.choice(FACTS)}**')) + await ctx.send(embed=discord.Embed(title='Python Facts', description=random.choice(FACTS))) def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From a68e8f558cfee18bdb04c9e9a07cc9d293bd6c71 Mon Sep 17 00:00:00 2001 From: MrKomodoDragon <74436682+MrKomodoDragon@users.noreply.github.com> Date: Tue, 16 Feb 2021 17:58:31 -0800 Subject: Update docstring for Cog Co-authored-by: Shivansh-007 <69356296+Shivansh-007@users.noreply.github.com> --- bot/exts/evergreen/pythonfacts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/pythonfacts.py b/bot/exts/evergreen/pythonfacts.py index fcb78168..dbc38ef4 100644 --- a/bot/exts/evergreen/pythonfacts.py +++ b/bot/exts/evergreen/pythonfacts.py @@ -21,5 +21,5 @@ class PythonFacts(commands.Cog): def setup(bot: commands.Bot) -> None: - """Adding the cog to the bot.""" + """Load PythonFacts Cog.""" bot.add_cog(PythonFacts(bot)) -- cgit v1.2.3 From 6aae339f33ee471bafe9338db5046b774c6b4aad Mon Sep 17 00:00:00 2001 From: MrKomodoDragon <74436682+MrKomodoDragon@users.noreply.github.com> Date: Tue, 16 Feb 2021 18:03:31 -0800 Subject: Change Docstring for command Co-authored-by: Shivansh-007 <69356296+Shivansh-007@users.noreply.github.com> --- bot/exts/evergreen/pythonfacts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/pythonfacts.py b/bot/exts/evergreen/pythonfacts.py index dbc38ef4..c0cdf111 100644 --- a/bot/exts/evergreen/pythonfacts.py +++ b/bot/exts/evergreen/pythonfacts.py @@ -16,7 +16,7 @@ class PythonFacts(commands.Cog): @commands.command(name='pythonfact', aliases=['pyfact']) async def get_python_fact(self, ctx: commands.Context) -> None: - """Gives a Random fun fact about Python.""" + """Sends a Random fun fact about Python.""" await ctx.send(embed=discord.Embed(title='Python Facts', description=random.choice(FACTS))) -- cgit v1.2.3 From 5164ba4e367efbfe78f8dd2b08646fe6605a8b42 Mon Sep 17 00:00:00 2001 From: MrKomodoDragon Date: Tue, 16 Feb 2021 18:21:12 -0800 Subject: Add colors and move embed out of send statement; add more info about Monty Python for Fact 1 --- bot/exts/evergreen/pythonfacts.py | 7 +++++-- bot/resources/evergreen/python_facts.txt | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/pythonfacts.py b/bot/exts/evergreen/pythonfacts.py index c0cdf111..734782b8 100644 --- a/bot/exts/evergreen/pythonfacts.py +++ b/bot/exts/evergreen/pythonfacts.py @@ -7,9 +7,11 @@ from discord.ext import commands with open('bot/resources/evergreen/python_facts.txt') as file: FACTS = list(file) +COLORS = [0x4B8BBE, 0xFFD43B, ] + class PythonFacts(commands.Cog): - """Gives a random fun fact about Python.""" + """Sends a random fun fact about Python.""" def __init__(self, bot: commands.Bot) -> None: self.bot = bot @@ -17,7 +19,8 @@ class PythonFacts(commands.Cog): @commands.command(name='pythonfact', aliases=['pyfact']) async def get_python_fact(self, ctx: commands.Context) -> None: """Sends a Random fun fact about Python.""" - await ctx.send(embed=discord.Embed(title='Python Facts', description=random.choice(FACTS))) + embed = discord.Embed(title='Python Facts', description=random.choice(FACTS), colour=random.choice(COLORS)) + await ctx.send(embed=embed) def setup(bot: commands.Bot) -> None: diff --git a/bot/resources/evergreen/python_facts.txt b/bot/resources/evergreen/python_facts.txt index d9e63a11..0abd971b 100644 --- a/bot/resources/evergreen/python_facts.txt +++ b/bot/resources/evergreen/python_facts.txt @@ -1,3 +1,3 @@ -Python was named after Monty Python, which Guido van Rossum likes. +Python was named after Monty Python, a British Comedy Troupe, which Guido van Rossum likes. If you type `import this` in the Python REPL, you'll get a poem about the philosophies about Python. (check it out by doing !zen in <#267659945086812160>) If you type `import antigravity` in the Python REPL, you'll be directed to an [xkcd comic](https://xkcd.com/353/) about how easy Python is. -- cgit v1.2.3 From 7bc0ea474ed39dbddca3958bb90fc072f0d7aa1d Mon Sep 17 00:00:00 2001 From: Arez1337 <> Date: Sat, 20 Feb 2021 20:43:59 +0100 Subject: Removed the Question about the Nile and changed the IDs to matc the order again --- bot/resources/evergreen/trivia_quiz.json | 57 ++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 24 deletions(-) (limited to 'bot') diff --git a/bot/resources/evergreen/trivia_quiz.json b/bot/resources/evergreen/trivia_quiz.json index faa3bc3b..a4225eb1 100644 --- a/bot/resources/evergreen/trivia_quiz.json +++ b/bot/resources/evergreen/trivia_quiz.json @@ -2,36 +2,51 @@ "retro": [ { "id": 1, - "hints": ["It is not a mainline Mario Game, although the plumber is present.", "It is not a mainline Zelda Game, although Link is present."], + "hints": [ + "It is not a mainline Mario Game, although the plumber is present.", + "It is not a mainline Zelda Game, although Link is present." + ], "question": "What is the best selling game on the Nintendo GameCube?", "answer": "Super Smash Bros" }, { "id": 2, - "hints": ["It was released before the 90's.", "It was released after 1980."], + "hints": [ + "It was released before the 90's.", + "It was released after 1980." + ], "question": "What year was Tetris released?", "answer": "1984" }, { "id": 3, - "hints": ["The occupation was in construction", "He appeared as this kind of worker in 1981's Donkey Kong"], + "hints": [ + "The occupation was in construction", + "He appeared as this kind of worker in 1981's Donkey Kong" + ], "question": "What was Mario's original occupation?", "answer": "Carpenter" }, { "id": 4, - "hints": ["It was revealed in the Nintendo Character Guide in 1993.", "His last name has to do with eating Mario's enemies."], + "hints": [ + "It was revealed in the Nintendo Character Guide in 1993.", + "His last name has to do with eating Mario's enemies." + ], "question": "What is Yoshi's (from Mario Bros.) full name?", "answer": "Yoshisaur Munchakoopas" }, { "id": 5, - "hints": ["The game was released in 1990.", "It was released on the SNES."], + "hints": [ + "The game was released in 1990.", + "It was released on the SNES." + ], "question": "What was the first game Yoshi appeared in?", "answer": "Super Mario World" } ], - "general":[ + "general": [ { "id": 100, "question": "Name \"the land of a thousand lakes\"", @@ -114,7 +129,7 @@ "id": 113, "question": "What's the name of the tallest waterfall in the world.", "answer": "Angel Falls", - "info": "Angel Falls (Salto Ángel) in Venezuela is the highest waterfall in the world. The falls are 3230 feet in height, with an uninterrupted drop of 2647 feet. Angel Falls is located on a tributary of the Rio Caroni." + "info": "Angel Falls (Salto \u00c1ngel) in Venezuela is the highest waterfall in the world. The falls are 3230 feet in height, with an uninterrupted drop of 2647 feet. Angel Falls is located on a tributary of the Rio Caroni." }, { "id": 114, @@ -180,7 +195,7 @@ "id": 124, "question": "When did the Second World War end?", "answer": "1945", - "info": "World War 2 ended with the unconditional surrender of the Axis powers. On 8 May 1945, the Allies accepted Germany's surrender, about a week after Adolf Hitler had committed suicide. VE Day – Victory in Europe celebrates the end of the Second World War on 8 May 1945." + "info": "World War 2 ended with the unconditional surrender of the Axis powers. On 8 May 1945, the Allies accepted Germany's surrender, about a week after Adolf Hitler had committed suicide. VE Day \u2013 Victory in Europe celebrates the end of the Second World War on 8 May 1945." }, { "id": 125, @@ -190,72 +205,66 @@ }, { "id": 126, - "question": "What's the name of the largest river in the world?", - "answer": "Nile", - "info": "The Nile, which is about 6,650 km (4,130 mi) long, is an \"international\" river as its drainage basin covers eleven countries, namely, Tanzania, Uganda, Rwanda, Burundi, the Democratic Republic of the Congo, Kenya, Ethiopia, Eritrea, South Sudan, Republic of the Sudan and Egypt." - }, - { - "id": 127, "question": "Which is the smallest planet in the Solar System?", "answer": "Mercury", "info": "Mercury is the smallest planet in our solar system. It's just a little bigger than Earth's moon. It is the closest planet to the sun, but it's actually not the hottest. Venus is hotter." }, { - "id": 128, + "id": 127, "question": "What is the smallest country?", "answer": "Vatican City", "info": "With an area of 0.17 square miles (0.44 km2) and a population right around 1,000, Vatican City is the smallest country in the world, both in terms of size and population." }, { - "id": 129, + "id": 128, "question": "What's the name of the largest bird?", "answer": "Ostrich", "info": "The largest living bird, a member of the Struthioniformes, is the ostrich (Struthio camelus), from the plains of Africa and Arabia. A large male ostrich can reach a height of 2.8 metres (9.2 feet) and weigh over 156 kilograms (344 pounds)." }, { - "id": 130, + "id": 129, "question": "What does the acronym GPRS stand for?", "answer": "General Packet Radio Service", "info": "General Packet Radio Service (GPRS) is a packet-based mobile data service on the global system for mobile communications (GSM) of 3G and 2G cellular communication systems. It is a non-voice, high-speed and useful packet-switching technology intended for GSM networks." }, { - "id": 131, + "id": 130, "question": "In what country is the Ebro river located?", "answer": "Spain", "info": "The Ebro river is located in Spain. It is 930 kilometers long and it's the second longest river that ends on the Mediterranean Sea." }, { - "id": 132, + "id": 131, "question": "What year was the IBM PC model 5150 introduced into the market?", "answer": "1981", "info": "The IBM PC was introduced into the market in 1981. It used the Intel 8088, with a clock speed of 4.77 MHz, along with the MDA and CGA as a video card." }, { - "id": 133, + "id": 132, "question": "What's the world's largest urban area?", "answer": "Tokyo", "info": "Tokyo is the most populated city in the world, with a population of 37 million people. It is located in Japan." }, { - "id": 134, + "id": 133, "question": "How many planets are there in the Solar system?", "answer": "8", "info": "In the Solar system, there are 8 planets: Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus and Neptune. Pluto isn't considered a planet in the Solar System anymore." }, { - "id": 135, + "id": 134, "question": "What is the capital of Iraq?", "answer": "Baghdad", "info": "Baghdad is the capital of Iraq. It has a population of 7 million people." }, { - "id": 136, + "id": 135, "question": "The United Nations headquarters is located at which city?", "answer": "New York", "info": "The United Nations is headquartered in New York City in a complex designed by a board of architects led by Wallace Harrison and built by the architectural firm Harrison & Abramovitz. The complex has served as the official headquarters of the United Nations since its completion in 1951." }, { - "id": 137, + "id": 136, "question": "At what year did Christopher Columbus discover America?", "answer": "1492", "info": "The explorer Christopher Columbus made four trips across the Atlantic Ocean from Spain: in 1492, 1493, 1498 and 1502. He was determined to find a direct water route west from Europe to Asia, but he never did. Instead, he stumbled upon the Americas" -- cgit v1.2.3 From 8cdd0b337fadc7085638517af5e8a7474ea3271c Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Mon, 22 Feb 2021 20:40:10 +0530 Subject: Improve wikipedia command to send a snippet of wikipedia article and use pagination instead of asking user for input --- bot/exts/evergreen/wikipedia.py | 168 ++++++++++++++++++---------------------- 1 file changed, 76 insertions(+), 92 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/wikipedia.py b/bot/exts/evergreen/wikipedia.py index be36e2c4..0d100d90 100644 --- a/bot/exts/evergreen/wikipedia.py +++ b/bot/exts/evergreen/wikipedia.py @@ -1,114 +1,98 @@ -import asyncio -import datetime import logging +import re +from datetime import datetime +from enum import Enum +from html import unescape from typing import List, Optional -from aiohttp import client_exceptions -from discord import Color, Embed, Message +from discord import Color, Embed from discord.ext import commands -from bot.constants import Wikipedia +from bot.bot import Bot +from bot.utils import LinePaginator log = logging.getLogger(__name__) -SEARCH_API = "https://en.wikipedia.org/w/api.php?action=query&list=search&srsearch={search_term}&format=json" -WIKIPEDIA_URL = "https://en.wikipedia.org/wiki/{title}" +SEARCH_API = "https://en.wikipedia.org/w/api.php?action=query&list=search&prop=info&inprop=url&utf8=& \ + format=json&origin=*&srlimit={number_of_results}&srsearch={string}" +WIKI_THUMBNAIL = "https://upload.wikimedia.org/wikipedia/en/thumb/8/80/Wikipedia-logo-v2.svg" \ + "/330px-Wikipedia-logo-v2.svg.png" +WIKI_SNIPPET_REGEX = r'(|<[^>]*>)' +WIKI_SEARCH_RESULT = ( + "**[{name}]({url})**\n" + "{description}\n" +) -class WikipediaSearch(commands.Cog): - """Get info from wikipedia.""" +class WikipediaSearchErrors(Enum): + """Errors returned in wikipedia search function.""" - def __init__(self, bot: commands.Bot): - self.bot = bot - self.http_session = bot.http_session + no_results = "Sorry, we could not find a wikipedia article using that search term." + api_issue = "Whoops, the Wikipedia API is having some issues right now. Try again later." - @staticmethod - def formatted_wiki_url(index: int, title: str) -> str: - """Formating wikipedia link with index and title.""" - return f'`{index}` [{title}]({WIKIPEDIA_URL.format(title=title.replace(" ", "_"))})' - async def search_wikipedia(self, search_term: str) -> Optional[List[str]]: - """Search wikipedia and return the first 10 pages found.""" - pages = [] - async with self.http_session.get(SEARCH_API.format(search_term=search_term)) as response: - try: - data = await response.json() +class WikipediaSearch(commands.Cog): + """Get info from wikipedia.""" - search_results = data["query"]["search"] + def __init__(self, bot: Bot): + self.bot = bot - # Ignore pages with "may refer to" - for search_result in search_results: - log.info("trying to append titles") - if "may refer to" not in search_result["snippet"]: - pages.append(search_result["title"]) - except client_exceptions.ContentTypeError: - pages = None + async def wiki_request(self, ctx: commands.Context, search: str) -> Optional[List[str]]: + """Search wikipedia search string and return formatted first 10 pages found.""" + url = SEARCH_API.format(number_of_results=10, string=search) + async with self.bot.http_session.get(url=url) as resp: + if resp.status == 200: + raw_data = await resp.json() + number_of_results = raw_data['query']['searchinfo']['totalhits'] + + if number_of_results: + results = raw_data['query']['search'] + lines = [] + + for article in results: + formatting = { + 'name': article['title'], + 'description': unescape( + re.sub( + WIKI_SNIPPET_REGEX, '', article['snippet'] + ) + ), + 'url': f"https://en.wikipedia.org/?curid={article['pageid']}" + } + line = WIKI_SEARCH_RESULT.format(**formatting) + lines.append(line) + + return lines - log.info("Finished appending titles") - return pages + else: + await ctx.send( + WikipediaSearchErrors.no_results.value + ) + return None + else: + await ctx.send( + WikipediaSearchErrors.api_issue.value + ) + return None @commands.cooldown(1, 10, commands.BucketType.user) @commands.command(name="wikipedia", aliases=["wiki"]) async def wikipedia_search_command(self, ctx: commands.Context, *, search: str) -> None: - """Return list of results containing your search query from wikipedia.""" - titles = await self.search_wikipedia(search) - - def check(message: Message) -> bool: - return message.author.id == ctx.author.id and message.channel == ctx.channel - - if not titles: - await ctx.send("Sorry, we could not find a wikipedia article using that search term") - return - - async with ctx.typing(): - log.info("Finished appending titles to titles_no_underscore list") - - s_desc = "\n".join(self.formatted_wiki_url(index, title) for index, title in enumerate(titles, start=1)) - embed = Embed(colour=Color.blue(), title=f"Wikipedia results for `{search}`", description=s_desc) - embed.timestamp = datetime.datetime.utcnow() - await ctx.send(embed=embed) - embed = Embed(colour=Color.green(), description="Enter number to choose") - msg = await ctx.send(embed=embed) - titles_len = len(titles) # getting length of list - - for retry_count in range(1, Wikipedia.total_chance + 1): - retries_left = Wikipedia.total_chance - retry_count - if retry_count < Wikipedia.total_chance: - error_msg = f"You have `{retries_left}/{Wikipedia.total_chance}` chances left" - else: - error_msg = 'Please try again by using `.wiki` command' - try: - message = await ctx.bot.wait_for('message', timeout=60.0, check=check) - response_from_user = await self.bot.get_context(message) - - if response_from_user.command: - return - - response = int(message.content) - if response < 0: - await ctx.send(f"Sorry, but you can't give negative index, {error_msg}") - elif response == 0: - await ctx.send(f"Sorry, please give an integer between `1` to `{titles_len}`, {error_msg}") - else: - await ctx.send(WIKIPEDIA_URL.format(title=titles[response - 1].replace(" ", "_"))) - break - - except asyncio.TimeoutError: - embed = Embed(colour=Color.red(), description=f"Time's up {ctx.author.mention}") - await msg.edit(embed=embed) - break - - except ValueError: - await ctx.send(f"Sorry, but you cannot do that, I will only accept an positive integer, {error_msg}") - - except IndexError: - await ctx.send(f"Sorry, please give an integer between `1` to `{titles_len}`, {error_msg}") - - except Exception as e: - log.info(f"Caught exception {e}, breaking out of retry loop") - break - - -def setup(bot: commands.Bot) -> None: + """Sends paginated top 10 results of Wikipedia search..""" + contents = await self.wiki_request(ctx, search) + + if contents: + embed = Embed( + title="Wikipedia Search Results", + colour=Color.blurple() + ) + embed.set_thumbnail(url=WIKI_THUMBNAIL) + embed.timestamp = datetime.utcnow() + await LinePaginator.paginate( + contents, ctx, embed + ) + + +def setup(bot: Bot) -> None: """Wikipedia Cog load.""" bot.add_cog(WikipediaSearch(bot)) -- cgit v1.2.3 From 86dc294eb22f233ccd381529a8191d2285889784 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Mon, 22 Feb 2021 20:40:56 +0530 Subject: Goodbye Wikipedia Class, no need of you anymore --- bot/constants.py | 4 ---- 1 file changed, 4 deletions(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index bb538487..c31cd958 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -281,10 +281,6 @@ class RedisConfig(NamedTuple): use_fakeredis = environ.get("USE_FAKEREDIS", "false").lower() == "true" -class Wikipedia: - total_chance = 3 - - class Source: github = "https://github.com/python-discord/sir-lancebot" github_avatar_url = "https://avatars1.githubusercontent.com/u/9919" -- cgit v1.2.3 From 16476ab7b4d5efe36a9e101b382f7be24888dec5 Mon Sep 17 00:00:00 2001 From: MrKomodoDragon Date: Mon, 22 Feb 2021 11:13:01 -0800 Subject: Switch to itertools.cycle and add colors to constants.py --- bot/constants.py | 2 ++ bot/exts/evergreen/pythonfacts.py | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index bb538487..3aec6ba3 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -156,6 +156,8 @@ class Colours: soft_orange = 0xf9cb54 soft_red = 0xcd6d6d yellow = 0xf9f586 + python_blue = 0x4B8BBE + python_yellow = 0xFFD43B class Emojis: diff --git a/bot/exts/evergreen/pythonfacts.py b/bot/exts/evergreen/pythonfacts.py index 734782b8..8e6d300b 100644 --- a/bot/exts/evergreen/pythonfacts.py +++ b/bot/exts/evergreen/pythonfacts.py @@ -1,13 +1,16 @@ -import random +import itertools import discord from discord.ext import commands +from bot.constants import Colours with open('bot/resources/evergreen/python_facts.txt') as file: FACTS = list(file) + FACT_CYCLE = itertools.cycle(FACTS) -COLORS = [0x4B8BBE, 0xFFD43B, ] +COLORS = [Colours.python_blue, Colours.python_yellow] +COLOR_CYCLE = itertools.cycle(COLORS) class PythonFacts(commands.Cog): @@ -19,7 +22,7 @@ class PythonFacts(commands.Cog): @commands.command(name='pythonfact', aliases=['pyfact']) async def get_python_fact(self, ctx: commands.Context) -> None: """Sends a Random fun fact about Python.""" - embed = discord.Embed(title='Python Facts', description=random.choice(FACTS), colour=random.choice(COLORS)) + embed = discord.Embed(title='Python Facts', description=next(FACT_CYCLE), colour=next(COLOR_CYCLE)) await ctx.send(embed=embed) -- cgit v1.2.3 From fa9e205338429def46b1c962138eda52c44ba824 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 23 Feb 2021 12:06:59 +0530 Subject: Add log.info() statement if the wikipedia api request status code is not 200 --- bot/exts/evergreen/wikipedia.py | 1 + 1 file changed, 1 insertion(+) (limited to 'bot') diff --git a/bot/exts/evergreen/wikipedia.py b/bot/exts/evergreen/wikipedia.py index 0d100d90..0b64136f 100644 --- a/bot/exts/evergreen/wikipedia.py +++ b/bot/exts/evergreen/wikipedia.py @@ -70,6 +70,7 @@ class WikipediaSearch(commands.Cog): ) return None else: + log.info(f"Unexpected response `{resp.status}` while searching wikipedia for `{search}`") await ctx.send( WikipediaSearchErrors.api_issue.value ) -- cgit v1.2.3 From 13dad6bf796a6009db4ff768795a3d45d044ff0e Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 23 Feb 2021 16:46:08 +0530 Subject: Fix pipfile conflicts, and add/use emojis from constants.py --- Pipfile.lock | 21 +++++++++++++++------ bot/constants.py | 5 ++++- bot/exts/evergreen/connect_four.py | 37 +++++++++---------------------------- 3 files changed, 28 insertions(+), 35 deletions(-) (limited to 'bot') diff --git a/Pipfile.lock b/Pipfile.lock index bd894ffa..ec801979 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "9be419062bd9db364ac9dddfcd50aef9c932384b45850363e482591fe7d12403" + "sha256": "b4aaaacbab13179145e36d7b86c736db512286f6cce8e513cc30c48d68fe3810" }, "pipfile-spec": 6, "requires": { @@ -161,6 +161,14 @@ "index": "pypi", "version": "==1.5.1" }, + "emojis": { + "hashes": [ + "sha256:7da34c8a78ae262fd68cef9e2c78a3c1feb59784489eeea0f54ba1d4b7111c7c", + "sha256:bf605d1f1a27a81cd37fe82eb65781c904467f569295a541c33710b97e4225ec" + ], + "index": "pypi", + "version": "==0.6.0" + }, "fakeredis": { "hashes": [ "sha256:01cb47d2286825a171fb49c0e445b1fa9307087e07cbb3d027ea10dbff108b6a", @@ -406,10 +414,11 @@ }, "sentry-sdk": { "hashes": [ - "sha256:3693cb47ba8d90c004ac002425770b32aaf0c83a846ec48e2d1364e7db1d072d" + "sha256:4ae8d1ced6c67f1c8ea51d82a16721c166c489b76876c9f2c202b8a50334b237", + "sha256:e75c8c58932bda8cd293ea8e4b242527129e1caaec91433d21b8b2f20fee030b" ], "index": "pypi", - "version": "==0.20.1" + "version": "==0.20.3" }, "six": { "hashes": [ @@ -576,11 +585,11 @@ }, "identify": { "hashes": [ - "sha256:70b638cf4743f33042bebb3b51e25261a0a10e80f978739f17e7fd4837664a66", - "sha256:9dfb63a2e871b807e3ba62f029813552a24b5289504f5b071dea9b041aee9fe4" + "sha256:de7129142a5c86d75a52b96f394d94d96d497881d2aaf8eafe320cdbe8ac4bcc", + "sha256:e0dae57c0397629ce13c289f6ddde0204edf518f557bfdb1e56474aa143e77c3" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.5.13" + "version": "==1.5.14" }, "mccabe": { "hashes": [ diff --git a/bot/constants.py b/bot/constants.py index bb538487..682ccf6f 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -165,6 +165,7 @@ class Emojis: envelope = "\U0001F4E8" trashcan = "<:trashcan:637136429717389331>" ok_hand = ":ok_hand:" + hand_raised = "\U0001f64b" dice_1 = "<:dice_1:755891608859443290>" dice_2 = "<:dice_2:755891608741740635>" @@ -179,7 +180,6 @@ class Emojis: pull_request_closed = "<:PRClosed:629695470519713818>" merge = "<:PRMerged:629695470570176522>" - # TicTacToe Emojis number_emojis = { 1: "\u0031\ufe0f\u20e3", 2: "\u0032\ufe0f\u20e3", @@ -191,8 +191,11 @@ class Emojis: 8: "\u0038\ufe0f\u20e3", 9: "\u0039\ufe0f\u20e3" } + confirmation = "\u2705" decline = "\u274c" + incident_unactioned = "<:incident_unactioned:719645583245180960>" + x = "\U0001f1fd" o = "\U0001f1f4" diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 02e876f4..65458dbc 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -7,30 +7,11 @@ import discord import emojis from discord.ext import commands -NUMBERS = [ - ":one:", - ":two:", - ":three:", - ":four:", - ":five:", - ":six:", - ":seven:", - ":eight:", - ":nine:" -] -UNICODE_NUMBERS = [ - "\u0031\u20e3", - "\u0032\u20e3", - "\u0033\u20e3", - "\u0034\u20e3", - "\u0035\u20e3", - "\u0036\u20e3", - "\u0037\u20e3", - "\u0038\u20e3", - "\u0039\u20e3", -] -CROSS_EMOJI = "\u274e" -HAND_RAISED_EMOJI = "\U0001f64b" +from bot.constants import Emojis + +NUMBERS = list(Emojis.number_emojis.values()) +CROSS_EMOJI = Emojis.incident_unactioned + Coordinate = typing.Optional[typing.Tuple[int, int]] EMOJI_CHECK = typing.Union[discord.Emoji, str] @@ -57,7 +38,7 @@ class Game: self.grid = self.generate_board(size) self.grid_size = size - self.unicode_numbers = UNICODE_NUMBERS[:self.grid_size] + self.unicode_numbers = NUMBERS[:self.grid_size] self.message = None @@ -313,7 +294,7 @@ class ConnectFour(commands.Cog): if ( user.id not in (ctx.me.id, ctx.author.id) - and str(reaction.emoji) == HAND_RAISED_EMOJI + and str(reaction.emoji) == Emojis.hand_raised and reaction.message.id == announcement.id ): if self.already_playing(user): @@ -406,11 +387,11 @@ class ConnectFour(commands.Cog): announcement = await ctx.send( "**Connect Four**: A new game is about to start!\n" - f"Press {HAND_RAISED_EMOJI} to play against {ctx.author.mention}!\n" + f"Press {Emojis.hand_raised} to play against {ctx.author.mention}!\n" f"(Cancel the game with {CROSS_EMOJI}.)" ) self.waiting.append(ctx.author) - await announcement.add_reaction(HAND_RAISED_EMOJI) + await announcement.add_reaction(Emojis.hand_raised) await announcement.add_reaction(CROSS_EMOJI) try: -- cgit v1.2.3 From aef25cb560eb525305c583a8ff2834b503cb91d4 Mon Sep 17 00:00:00 2001 From: MrKomodoDragon Date: Tue, 23 Feb 2021 09:03:05 -0800 Subject: Remove unused variables --- bot/exts/evergreen/pythonfacts.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/pythonfacts.py b/bot/exts/evergreen/pythonfacts.py index 8e6d300b..11b258f9 100644 --- a/bot/exts/evergreen/pythonfacts.py +++ b/bot/exts/evergreen/pythonfacts.py @@ -6,11 +6,9 @@ from discord.ext import commands from bot.constants import Colours with open('bot/resources/evergreen/python_facts.txt') as file: - FACTS = list(file) - FACT_CYCLE = itertools.cycle(FACTS) + FACTS = itertools.cycle(list(file)) -COLORS = [Colours.python_blue, Colours.python_yellow] -COLOR_CYCLE = itertools.cycle(COLORS) +COLORS = itertools.cycle([Colours.python_blue, Colours.python_yellow]) class PythonFacts(commands.Cog): @@ -22,7 +20,7 @@ class PythonFacts(commands.Cog): @commands.command(name='pythonfact', aliases=['pyfact']) async def get_python_fact(self, ctx: commands.Context) -> None: """Sends a Random fun fact about Python.""" - embed = discord.Embed(title='Python Facts', description=next(FACT_CYCLE), colour=next(COLOR_CYCLE)) + embed = discord.Embed(title='Python Facts', description=next(FACTS), colour=next(COLORS)) await ctx.send(embed=embed) -- cgit v1.2.3 From b70a3fb551600fc34ea4d9e5111957149dceb1a2 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Wed, 24 Feb 2021 17:28:08 +0530 Subject: Make connect 4 and its sub command ai guild only --- bot/exts/evergreen/connect_four.py | 3 + bot/exts/evergreen/error_handler.py | 129 ------------------------------------ 2 files changed, 3 insertions(+), 129 deletions(-) delete mode 100644 bot/exts/evergreen/error_handler.py (limited to 'bot') diff --git a/bot/exts/evergreen/connect_four.py b/bot/exts/evergreen/connect_four.py index 65458dbc..7e3ec42b 100644 --- a/bot/exts/evergreen/connect_four.py +++ b/bot/exts/evergreen/connect_four.py @@ -6,6 +6,7 @@ from functools import partial import discord import emojis from discord.ext import commands +from discord.ext.commands import guild_only from bot.constants import Emojis @@ -358,6 +359,7 @@ class ConnectFour(commands.Cog): self.games.remove(game) raise + @guild_only() @commands.group( invoke_without_command=True, aliases=["4inarow", "connect4", "connectfour", "c4"], @@ -422,6 +424,7 @@ class ConnectFour(commands.Cog): await self._play_game(ctx, user, board_size, str(emoji1), str(emoji2)) + @guild_only() @connect_four.command(aliases=["bot", "computer", "cpu"]) async def ai( self, diff --git a/bot/exts/evergreen/error_handler.py b/bot/exts/evergreen/error_handler.py deleted file mode 100644 index 99af1519..00000000 --- a/bot/exts/evergreen/error_handler.py +++ /dev/null @@ -1,129 +0,0 @@ -import logging -import math -import random -from typing import Iterable, Union - -from discord import Embed, Message -from discord.ext import commands -from sentry_sdk import push_scope - -from bot.constants import Colours, ERROR_REPLIES, NEGATIVE_REPLIES -from bot.utils.decorators import InChannelCheckFailure, InMonthCheckFailure -from bot.utils.exceptions import UserNotPlayingError - -log = logging.getLogger(__name__) - - -class CommandErrorHandler(commands.Cog): - """A error handler for the PythonDiscord server.""" - - def __init__(self, bot: commands.Bot): - self.bot = bot - - @staticmethod - def revert_cooldown_counter(command: commands.Command, message: Message) -> None: - """Undoes the last cooldown counter for user-error cases.""" - if command._buckets.valid: - bucket = command._buckets.get_bucket(message) - bucket._tokens = min(bucket.rate, bucket._tokens + 1) - logging.debug("Cooldown counter reverted as the command was not used correctly.") - - @staticmethod - def error_embed(message: str, title: Union[Iterable, str] = ERROR_REPLIES) -> Embed: - """Build a basic embed with red colour and either a random error title or a title provided.""" - embed = Embed(colour=Colours.soft_red) - if isinstance(title, str): - embed.title = title - else: - embed.title = random.choice(title) - embed.description = message - return embed - - @commands.Cog.listener() - async def on_command_error(self, ctx: commands.Context, error: commands.CommandError) -> None: - """Activates when a command opens an error.""" - if getattr(error, 'handled', False): - logging.debug(f"Command {ctx.command} had its error already handled locally; ignoring.") - return - - error = getattr(error, 'original', error) - logging.debug( - f"Error Encountered: {type(error).__name__} - {str(error)}, " - f"Command: {ctx.command}, " - f"Author: {ctx.author}, " - f"Channel: {ctx.channel}" - ) - - if isinstance(error, commands.CommandNotFound): - return - - if isinstance(error, (InChannelCheckFailure, InMonthCheckFailure)): - await ctx.send(embed=self.error_embed(str(error), NEGATIVE_REPLIES), delete_after=7.5) - return - - if isinstance(error, commands.UserInputError): - self.revert_cooldown_counter(ctx.command, ctx.message) - embed = self.error_embed( - f"Your input was invalid: {error}\n\nUsage:\n```{ctx.prefix}{ctx.command} {ctx.command.signature}```" - ) - await ctx.send(embed=embed) - return - - if isinstance(error, commands.CommandOnCooldown): - mins, secs = divmod(math.ceil(error.retry_after), 60) - embed = self.error_embed( - f"This command is on cooldown:\nPlease retry in {mins} minutes {secs} seconds.", - NEGATIVE_REPLIES - ) - await ctx.send(embed=embed, delete_after=7.5) - return - - if isinstance(error, commands.DisabledCommand): - await ctx.send(embed=self.error_embed("This command has been disabled.", NEGATIVE_REPLIES)) - return - - if isinstance(error, commands.NoPrivateMessage): - await ctx.send(embed=self.error_embed("This command can only be used in the server.", NEGATIVE_REPLIES)) - return - - if isinstance(error, commands.BadArgument): - self.revert_cooldown_counter(ctx.command, ctx.message) - embed = self.error_embed( - "The argument you provided was invalid: " - f"{error}\n\nUsage:\n```{ctx.prefix}{ctx.command} {ctx.command.signature}```" - ) - await ctx.send(embed=embed) - return - - if isinstance(error, commands.CheckFailure): - await ctx.send(embed=self.error_embed("You are not authorized to use this command.", NEGATIVE_REPLIES)) - return - - if isinstance(error, UserNotPlayingError): - await ctx.send("Game not found.") - return - - with push_scope() as scope: - scope.user = { - "id": ctx.author.id, - "username": str(ctx.author) - } - - scope.set_tag("command", ctx.command.qualified_name) - scope.set_tag("message_id", ctx.message.id) - scope.set_tag("channel_id", ctx.channel.id) - - scope.set_extra("full_message", ctx.message.content) - - if ctx.guild is not None: - scope.set_extra( - "jump_to", - f"https://discordapp.com/channels/{ctx.guild.id}/{ctx.channel.id}/{ctx.message.id}" - ) - - log.exception(f"Unhandled command error: {str(error)}", exc_info=error) - - -def setup(bot: commands.Bot) -> None: - """Error handler Cog load.""" - bot.add_cog(CommandErrorHandler(bot)) -- cgit v1.2.3 From fadb1c4e13086d9ecf17629d98668364bd78bf54 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Wed, 24 Feb 2021 17:28:38 +0530 Subject: Mentioned community bot commands channel while sending embed for No Private Message error --- bot/exts/evergreen/error_handler.py | 133 ++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 bot/exts/evergreen/error_handler.py (limited to 'bot') diff --git a/bot/exts/evergreen/error_handler.py b/bot/exts/evergreen/error_handler.py new file mode 100644 index 00000000..54878c08 --- /dev/null +++ b/bot/exts/evergreen/error_handler.py @@ -0,0 +1,133 @@ +import logging +import math +import random +from typing import Iterable, Union + +from discord import Embed, Message +from discord.ext import commands +from sentry_sdk import push_scope + +from bot.constants import Colours, ERROR_REPLIES, NEGATIVE_REPLIES, Channels +from bot.utils.decorators import InChannelCheckFailure, InMonthCheckFailure +from bot.utils.exceptions import UserNotPlayingError + +log = logging.getLogger(__name__) + + +class CommandErrorHandler(commands.Cog): + """A error handler for the PythonDiscord server.""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + + @staticmethod + def revert_cooldown_counter(command: commands.Command, message: Message) -> None: + """Undoes the last cooldown counter for user-error cases.""" + if command._buckets.valid: + bucket = command._buckets.get_bucket(message) + bucket._tokens = min(bucket.rate, bucket._tokens + 1) + logging.debug("Cooldown counter reverted as the command was not used correctly.") + + @staticmethod + def error_embed(message: str, title: Union[Iterable, str] = ERROR_REPLIES) -> Embed: + """Build a basic embed with red colour and either a random error title or a title provided.""" + embed = Embed(colour=Colours.soft_red) + if isinstance(title, str): + embed.title = title + else: + embed.title = random.choice(title) + embed.description = message + return embed + + @commands.Cog.listener() + async def on_command_error(self, ctx: commands.Context, error: commands.CommandError) -> None: + """Activates when a command opens an error.""" + if getattr(error, 'handled', False): + logging.debug(f"Command {ctx.command} had its error already handled locally; ignoring.") + return + + error = getattr(error, 'original', error) + logging.debug( + f"Error Encountered: {type(error).__name__} - {str(error)}, " + f"Command: {ctx.command}, " + f"Author: {ctx.author}, " + f"Channel: {ctx.channel}" + ) + + if isinstance(error, commands.CommandNotFound): + return + + if isinstance(error, (InChannelCheckFailure, InMonthCheckFailure)): + await ctx.send(embed=self.error_embed(str(error), NEGATIVE_REPLIES), delete_after=7.5) + return + + if isinstance(error, commands.UserInputError): + self.revert_cooldown_counter(ctx.command, ctx.message) + embed = self.error_embed( + f"Your input was invalid: {error}\n\nUsage:\n```{ctx.prefix}{ctx.command} {ctx.command.signature}```" + ) + await ctx.send(embed=embed) + return + + if isinstance(error, commands.CommandOnCooldown): + mins, secs = divmod(math.ceil(error.retry_after), 60) + embed = self.error_embed( + f"This command is on cooldown:\nPlease retry in {mins} minutes {secs} seconds.", + NEGATIVE_REPLIES + ) + await ctx.send(embed=embed, delete_after=7.5) + return + + if isinstance(error, commands.DisabledCommand): + await ctx.send(embed=self.error_embed("This command has been disabled.", NEGATIVE_REPLIES)) + return + + if isinstance(error, commands.NoPrivateMessage): + await ctx.send( + embed=self.error_embed( + f"This command can only be used in the server. Go to <#{Channels.community_bot_commands}> instead!", + NEGATIVE_REPLIES) + ) + return + + if isinstance(error, commands.BadArgument): + self.revert_cooldown_counter(ctx.command, ctx.message) + embed = self.error_embed( + "The argument you provided was invalid: " + f"{error}\n\nUsage:\n```{ctx.prefix}{ctx.command} {ctx.command.signature}```" + ) + await ctx.send(embed=embed) + return + + if isinstance(error, commands.CheckFailure): + await ctx.send(embed=self.error_embed("You are not authorized to use this command.", NEGATIVE_REPLIES)) + return + + if isinstance(error, UserNotPlayingError): + await ctx.send("Game not found.") + return + + with push_scope() as scope: + scope.user = { + "id": ctx.author.id, + "username": str(ctx.author) + } + + scope.set_tag("command", ctx.command.qualified_name) + scope.set_tag("message_id", ctx.message.id) + scope.set_tag("channel_id", ctx.channel.id) + + scope.set_extra("full_message", ctx.message.content) + + if ctx.guild is not None: + scope.set_extra( + "jump_to", + f"https://discordapp.com/channels/{ctx.guild.id}/{ctx.channel.id}/{ctx.message.id}" + ) + + log.exception(f"Unhandled command error: {str(error)}", exc_info=error) + + +def setup(bot: commands.Bot) -> None: + """Error handler Cog load.""" + bot.add_cog(CommandErrorHandler(bot)) -- cgit v1.2.3 From 598cb12f628547ce1542c6094908df48f4b757ec Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Wed, 24 Feb 2021 17:34:42 +0530 Subject: Make Flake8 happy (reorder imports) --- bot/exts/evergreen/error_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/error_handler.py b/bot/exts/evergreen/error_handler.py index 54878c08..83091ba8 100644 --- a/bot/exts/evergreen/error_handler.py +++ b/bot/exts/evergreen/error_handler.py @@ -7,7 +7,7 @@ from discord import Embed, Message from discord.ext import commands from sentry_sdk import push_scope -from bot.constants import Colours, ERROR_REPLIES, NEGATIVE_REPLIES, Channels +from bot.constants import Channels, Colours, ERROR_REPLIES, NEGATIVE_REPLIES from bot.utils.decorators import InChannelCheckFailure, InMonthCheckFailure from bot.utils.exceptions import UserNotPlayingError -- cgit v1.2.3 From 550e0e8488c77db0a0c43e2bfc948a65551f5be8 Mon Sep 17 00:00:00 2001 From: Shivansh-007 <69356296+Shivansh-007@users.noreply.github.com> Date: Wed, 24 Feb 2021 19:30:21 +0530 Subject: Correct the parentheses format Co-authored-by: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> --- bot/exts/evergreen/error_handler.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/error_handler.py b/bot/exts/evergreen/error_handler.py index 83091ba8..28902503 100644 --- a/bot/exts/evergreen/error_handler.py +++ b/bot/exts/evergreen/error_handler.py @@ -86,7 +86,8 @@ class CommandErrorHandler(commands.Cog): await ctx.send( embed=self.error_embed( f"This command can only be used in the server. Go to <#{Channels.community_bot_commands}> instead!", - NEGATIVE_REPLIES) + NEGATIVE_REPLIES + ) ) return -- cgit v1.2.3 From 439873db9749f2df7f0bfe02793aac80d3a708a6 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Thu, 25 Feb 2021 10:36:59 +0530 Subject: Don't use enums for wikipedia error messages, use brackets instead of '\' for long variable values, pass in ctx.channel instead of the full ctx --- bot/exts/evergreen/wikipedia.py | 49 ++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 27 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/wikipedia.py b/bot/exts/evergreen/wikipedia.py index 0b64136f..068c4f43 100644 --- a/bot/exts/evergreen/wikipedia.py +++ b/bot/exts/evergreen/wikipedia.py @@ -1,11 +1,10 @@ import logging import re from datetime import datetime -from enum import Enum from html import unescape from typing import List, Optional -from discord import Color, Embed +from discord import Color, Embed, TextChannel from discord.ext import commands from bot.bot import Bot @@ -13,10 +12,14 @@ from bot.utils import LinePaginator log = logging.getLogger(__name__) -SEARCH_API = "https://en.wikipedia.org/w/api.php?action=query&list=search&prop=info&inprop=url&utf8=& \ - format=json&origin=*&srlimit={number_of_results}&srsearch={string}" -WIKI_THUMBNAIL = "https://upload.wikimedia.org/wikipedia/en/thumb/8/80/Wikipedia-logo-v2.svg" \ - "/330px-Wikipedia-logo-v2.svg.png" +SEARCH_API = ( + "https://en.wikipedia.org/w/api.php?action=query&list=search&prop=info&inprop=url&utf8=&" + "format=json&origin=*&srlimit={number_of_results}&srsearch={string}" +) +WIKI_THUMBNAIL = ( + "https://upload.wikimedia.org/wikipedia/en/thumb/8/80/Wikipedia-logo-v2.svg" + "/330px-Wikipedia-logo-v2.svg.png" +) WIKI_SNIPPET_REGEX = r'(|<[^>]*>)' WIKI_SEARCH_RESULT = ( "**[{name}]({url})**\n" @@ -24,20 +27,13 @@ WIKI_SEARCH_RESULT = ( ) -class WikipediaSearchErrors(Enum): - """Errors returned in wikipedia search function.""" - - no_results = "Sorry, we could not find a wikipedia article using that search term." - api_issue = "Whoops, the Wikipedia API is having some issues right now. Try again later." - - class WikipediaSearch(commands.Cog): """Get info from wikipedia.""" def __init__(self, bot: Bot): self.bot = bot - async def wiki_request(self, ctx: commands.Context, search: str) -> Optional[List[str]]: + async def wiki_request(self, channel: TextChannel, search: str) -> Optional[List[str]]: """Search wikipedia search string and return formatted first 10 pages found.""" url = SEARCH_API.format(number_of_results=10, string=search) async with self.bot.http_session.get(url=url) as resp: @@ -50,37 +46,36 @@ class WikipediaSearch(commands.Cog): lines = [] for article in results: - formatting = { - 'name': article['title'], - 'description': unescape( + line = WIKI_SEARCH_RESULT.format( + name=article['title'], + description=unescape( re.sub( WIKI_SNIPPET_REGEX, '', article['snippet'] ) ), - 'url': f"https://en.wikipedia.org/?curid={article['pageid']}" - } - line = WIKI_SEARCH_RESULT.format(**formatting) + url=f"https://en.wikipedia.org/?curid={article['pageid']}" + ) lines.append(line) return lines else: - await ctx.send( - WikipediaSearchErrors.no_results.value + await channel.send( + "Sorry, we could not find a wikipedia article using that search term." ) - return None + return else: log.info(f"Unexpected response `{resp.status}` while searching wikipedia for `{search}`") - await ctx.send( - WikipediaSearchErrors.api_issue.value + await channel.send( + "Whoops, the Wikipedia API is having some issues right now. Try again later." ) - return None + return @commands.cooldown(1, 10, commands.BucketType.user) @commands.command(name="wikipedia", aliases=["wiki"]) async def wikipedia_search_command(self, ctx: commands.Context, *, search: str) -> None: """Sends paginated top 10 results of Wikipedia search..""" - contents = await self.wiki_request(ctx, search) + contents = await self.wiki_request(ctx.channel, search) if contents: embed = Embed( -- cgit v1.2.3 From 3766b1424d7ca37ffd7d2477b7a82f192a5fedb4 Mon Sep 17 00:00:00 2001 From: xithrius Date: Thu, 25 Feb 2021 17:55:42 -0800 Subject: Added more topics. --- bot/resources/evergreen/py_topics.yaml | 53 +++++++++++++++++++++++++++------- bot/resources/evergreen/starter.yaml | 11 +++++++ 2 files changed, 54 insertions(+), 10 deletions(-) (limited to 'bot') diff --git a/bot/resources/evergreen/py_topics.yaml b/bot/resources/evergreen/py_topics.yaml index 1e53429a..4973d25a 100644 --- a/bot/resources/evergreen/py_topics.yaml +++ b/bot/resources/evergreen/py_topics.yaml @@ -3,8 +3,6 @@ # python-general 267624335836053506: - What's your favorite PEP? - - What's your current text editor/IDE, and what functionality do you like about it the most when programming in Python? - - What functionality is your text editor/IDE missing for programming Python? - What parts of your life has Python automated, if any? - Which Python project are you the most proud of making? - What made you want to learn Python? @@ -16,23 +14,34 @@ - What feature do you think should be added to Python? - Has Python helped you in school? If so, how? - What was the first thing you created with Python? + - What is your favorite Python package? + - What standard library module is really underrated? + - Have you published any packages on PyPi? If so, what are they? + - What are you currently working on in Python? + - What's your favorite script and how has it helped you in day to day activities? + - When you were first learning, what is something that stumped you? + - When you were first learning, what is a resource you wish you had? + - What is something you know now that you wish you knew when you were starting out? + - What is something simple that you still error on today? + +# algos-and-data-structs +650401909852864553: + - # async 630504881542791169: - Are there any frameworks you wish were async? - How have coroutines changed the way you write Python? + - What is your favorite async library? # c-extensions 728390945384431688: - -# computer-science -650401909852864553: - - - # databases 342318764227821568: - Where do you get your best data? + - What is your preferred database and for what use? # data-science 366673247892275221: @@ -45,11 +54,18 @@ - What feature would you be the most interested in making? - What feature would you like to see added to the library? what feature in the library do you think is redundant? - Do you think there's a way in which Discord could handle bots better? + - What's one feature you wish more developers had in their bots? + +# editors-ides +813178633006350366: + - What's your current text editor/IDE, and what functionality do you like about it the most when programming in Python? + - What functionality is your text editor/IDE missing for programming Python? # esoteric-python 470884583684964352: - What's a common part of programming we can make harder? - What are the pros and cons of messing with __magic__()? + - What's your favorite Python hack? # game-development 660625198390837248: @@ -57,7 +73,7 @@ # microcontrollers 545603026732318730: - - + - What is your favorite version of the Raspberry Pi? # networking 716325106619777044: @@ -67,23 +83,40 @@ 366674035876167691: - If you could wish for a library involving net-sec, what would it be? -# software-testing -463035728335732738: +# software-design +782713858615017503: - # tools-and-devops 463035462760792066: - What editor would you recommend to a beginner? Why? - What editor would you recommend to be the most efficient? Why? + - How often do you use GitHub Actions and workflows to automate your repositories? + - What's your favorite app on GitHub? + +# unit-testing +463035728335732738: + - # unix 491523972836360192: - - + - What's your favorite Bash command? + - What's your most used Bash command? + - How often do you update your Unix machine? + - How often do you upgrade on production? # user-interfaces 338993628049571840: - What's the most impressive Desktop Application you've made with Python so far? + - Have you ever made your own GUI? If so, how? + - Do you perfer Command Line Interfaces (CLI) or Graphic User Interfaces (GUI)? + - What's your favorite CLI (Command Line Interface) or TLI (Terminal Line Interface)? + - What's your best GUI project? # web-development 366673702533988363: - How has Python helped you in web development? + - What tools do you use for web development? + - What is your favorite API library? + - What do you use for your frontend? + - What does your stack look like? diff --git a/bot/resources/evergreen/starter.yaml b/bot/resources/evergreen/starter.yaml index 53c89364..cacaacb6 100644 --- a/bot/resources/evergreen/starter.yaml +++ b/bot/resources/evergreen/starter.yaml @@ -20,3 +20,14 @@ - If you had $100 bill in your Easter Basket, what would you do with it? - What would you do if you know you could succeed at anything you chose to do? - If you could take only three things from your house, what would they be? +- What's the best pastry? +- What's your favourite kind of soup? +- What is the most useless talent that you have? +- Would you rather fight 100 duck sized horses or one horse sized duck? +- What is your favourite colour? +- What's your favourite type of weather? +- Tea or coffee? What about milk? +- Do you speak a language other than English? +- What is your favorite TV show? +- What is your favorite media genre? +- How many years have you spent coding? -- cgit v1.2.3 From f429ce6aaa57d680893be0cbd5a7760de947aac6 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 28 Feb 2021 19:48:13 +0000 Subject: Add issue cog to staff channels. --- bot/constants.py | 2 ++ bot/exts/evergreen/issues.py | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index 682ccf6f..9b7e37f8 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -124,6 +124,7 @@ class Channels(NamedTuple): hacktoberfest_2020 = 760857070781071431 voice_chat_0 = 412357430186344448 voice_chat_1 = 799647045886541885 + staff_voice = 541638762007101470 class Categories(NamedTuple): @@ -131,6 +132,7 @@ class Categories(NamedTuple): development = 411199786025484308 devprojects = 787641585624940544 media = 799054581991997460 + staff = 364918151625965579 class Client(NamedTuple): diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 73ebe547..03d0a86b 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -24,9 +24,11 @@ if GITHUB_TOKEN := Tokens.github: REQUEST_HEADERS["Authorization"] = f"token {GITHUB_TOKEN}" WHITELISTED_CATEGORIES = ( - Categories.devprojects, Categories.media, Categories.development + Categories.devprojects, Categories.media, Categories.development, Categories.staff +) +WHITELISTED_CHANNELS_ON_MESSAGE = ( + Channels.organisation, Channels.mod_meta, Channels.mod_tools, Channels.staff_voice ) -WHITELISTED_CHANNELS_ON_MESSAGE = (Channels.organisation, Channels.mod_meta, Channels.mod_tools) CODE_BLOCK_RE = re.compile( r"^`([^`\n]+)`" # Inline codeblock -- cgit v1.2.3 From b61aa3079d7d1bcaf4e5e6754544143ce1a156a8 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 28 Feb 2021 20:13:08 +0000 Subject: Fix ordering of categories in issues cog --- bot/exts/evergreen/issues.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 03d0a86b..bbcbf611 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -24,7 +24,7 @@ if GITHUB_TOKEN := Tokens.github: REQUEST_HEADERS["Authorization"] = f"token {GITHUB_TOKEN}" WHITELISTED_CATEGORIES = ( - Categories.devprojects, Categories.media, Categories.development, Categories.staff + Categories.development, Categories.devprojects, Categories.media, Categories.staff ) WHITELISTED_CHANNELS_ON_MESSAGE = ( Channels.organisation, Channels.mod_meta, Channels.mod_tools, Channels.staff_voice -- cgit v1.2.3 From f74a49f3e686b41a52ce097a97260b263067cd68 Mon Sep 17 00:00:00 2001 From: Xithrius <15021300+Xithrius@users.noreply.github.com> Date: Sun, 28 Feb 2021 21:49:46 -0800 Subject: Removed wordy-ness of one singular question. Co-authored-by: ChrisJL --- bot/resources/evergreen/py_topics.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/resources/evergreen/py_topics.yaml b/bot/resources/evergreen/py_topics.yaml index 4973d25a..8cf9582d 100644 --- a/bot/resources/evergreen/py_topics.yaml +++ b/bot/resources/evergreen/py_topics.yaml @@ -21,7 +21,7 @@ - What's your favorite script and how has it helped you in day to day activities? - When you were first learning, what is something that stumped you? - When you were first learning, what is a resource you wish you had? - - What is something you know now that you wish you knew when you were starting out? + - What is something you know now, that you wish you knew when starting out? - What is something simple that you still error on today? # algos-and-data-structs -- cgit v1.2.3 From f9339e6043acc2161c3723624cd6ae33dce26bca Mon Sep 17 00:00:00 2001 From: xithrius Date: Sun, 28 Feb 2021 21:53:13 -0800 Subject: There's no such thing as TLI. Added TUI. --- bot/resources/evergreen/py_topics.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/resources/evergreen/py_topics.yaml b/bot/resources/evergreen/py_topics.yaml index 8cf9582d..f3b2eaa3 100644 --- a/bot/resources/evergreen/py_topics.yaml +++ b/bot/resources/evergreen/py_topics.yaml @@ -110,7 +110,7 @@ - What's the most impressive Desktop Application you've made with Python so far? - Have you ever made your own GUI? If so, how? - Do you perfer Command Line Interfaces (CLI) or Graphic User Interfaces (GUI)? - - What's your favorite CLI (Command Line Interface) or TLI (Terminal Line Interface)? + - What's your favorite CLI (Command Line Interface) or TUI (Terminal Line Interface)? - What's your best GUI project? # web-development -- cgit v1.2.3 From add46b3680d5b9570ddf464ed0674c2b5ad4474d Mon Sep 17 00:00:00 2001 From: Xithrius <15021300+Xithrius@users.noreply.github.com> Date: Sun, 28 Feb 2021 22:06:44 -0800 Subject: "colour" to "color". Co-authored-by: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> --- bot/resources/evergreen/starter.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/resources/evergreen/starter.yaml b/bot/resources/evergreen/starter.yaml index cacaacb6..949220f9 100644 --- a/bot/resources/evergreen/starter.yaml +++ b/bot/resources/evergreen/starter.yaml @@ -24,7 +24,7 @@ - What's your favourite kind of soup? - What is the most useless talent that you have? - Would you rather fight 100 duck sized horses or one horse sized duck? -- What is your favourite colour? +- What is your favourite color? - What's your favourite type of weather? - Tea or coffee? What about milk? - Do you speak a language other than English? -- cgit v1.2.3 From 167774ea84ec528845a17d41065983e3ef696d12 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 2 Mar 2021 15:51:56 +0530 Subject: Fix Channel Check to use channel ids instead of channel objects, and skip channel check if debug is true --- bot/bot.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/bot.py b/bot/bot.py index 81d59706..176422aa 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -74,11 +74,16 @@ class Bot(commands.Bot): async def check_channels(self) -> None: """Verifies that all channel constants refer to channels which exist.""" await self.wait_until_guild_available() - all_channels = set(self.get_all_channels()) + + if constants.Client.debug: + log.info("Skipping Channels Check.") + return + + all_channels_ids = [channel.id for channel in set(self.get_all_channels())] for name, channel_id in vars(constants.Channels).items(): if name.startswith('_'): continue - if channel_id not in all_channels: + if channel_id not in all_channels_ids: log.error(f'Channel "{name}" with ID {channel_id} missing') async def send_log(self, title: str, details: str = None, *, icon: str = None) -> None: -- cgit v1.2.3 From 674838787fb1916dce98b50bae78159a54833c42 Mon Sep 17 00:00:00 2001 From: Shivansh-007 Date: Tue, 2 Mar 2021 16:00:24 +0530 Subject: Don't use sets --- bot/bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/bot.py b/bot/bot.py index 176422aa..e9750697 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -79,7 +79,7 @@ class Bot(commands.Bot): log.info("Skipping Channels Check.") return - all_channels_ids = [channel.id for channel in set(self.get_all_channels())] + all_channels_ids = [channel.id for channel in self.get_all_channels()] for name, channel_id in vars(constants.Channels).items(): if name.startswith('_'): continue -- cgit v1.2.3 From 1e240e7fbac71b0546ef090732c7417bab4e1563 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Tue, 2 Mar 2021 14:27:58 -0600 Subject: initial commit of earth_photos --- bot/exts/easter/earth_photos.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 bot/exts/easter/earth_photos.py (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py new file mode 100644 index 00000000..ceffeb48 --- /dev/null +++ b/bot/exts/easter/earth_photos.py @@ -0,0 +1,27 @@ +import asyncio +import logging +import random +from unsplash.api import Api +from unsplash.auth import Auth + +import discord +from discord.ext import commands + +log = logging.getLogger(__name__) + +class EarthPhotos(commands.Cog): + """This cog contains the command for earth photos.""" + + def init(self, bot: commands.Bot): + self.bot = bot + self.current_channel = None + + @commands.command(aliases=["earth"]) + async def earth_photos(self, ctx: commands.Context): + """ + Returns a random photo of earth. + """ + + + + -- cgit v1.2.3 From 99a9d7a1b7651caea4cf1587c89485497c061387 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Tue, 2 Mar 2021 15:22:39 -0600 Subject: Update earth_photos.py --- bot/exts/easter/earth_photos.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index ceffeb48..436b39a7 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -1,14 +1,24 @@ import asyncio import logging import random -from unsplash.api import Api -from unsplash.auth import Auth +from unsplash.api import Api as uApi +from unsplash.auth import Auth as uAuth import discord from discord.ext import commands +from bot.constants import Tokens + log = logging.getLogger(__name__) +UnClient_id = Tokens.UNSPLASH_API + +UnClient_secret = Tokens.UNSPLASH_SECRET + +redirect_uri = "urn:ietf:wg:oauth:2.0:oob" + +unsplash_auth = uAuth(client_id, + class EarthPhotos(commands.Cog): """This cog contains the command for earth photos.""" @@ -19,7 +29,7 @@ class EarthPhotos(commands.Cog): @commands.command(aliases=["earth"]) async def earth_photos(self, ctx: commands.Context): """ - Returns a random photo of earth. + Returns a random photo of earth, sourced from Unsplash. """ -- cgit v1.2.3 From 0260ad04af6e98c7fd804c58913412b6b936eb73 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Tue, 2 Mar 2021 21:39:01 -0600 Subject: finished function --- Pipfile | 1 + Pipfile.lock | 26 +++++++++++++++++--------- bot/constants.py | 1 + bot/exts/easter/earth_photos.py | 35 +++++++++++++++++++---------------- 4 files changed, 38 insertions(+), 25 deletions(-) (limited to 'bot') diff --git a/Pipfile b/Pipfile index e7e01a31..1a2d464e 100644 --- a/Pipfile +++ b/Pipfile @@ -15,6 +15,7 @@ PyYAML = "~=5.3.1" "discord.py" = {extras = ["voice"], version = "~=1.5.1"} async-rediscache = {extras = ["fakeredis"], version = "~=0.1.4"} emojis = "~=0.6.0" +requests = "~=2.25.1" [dev-packages] flake8 = "~=3.8" diff --git a/Pipfile.lock b/Pipfile.lock index ec801979..34cd08cf 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "b4aaaacbab13179145e36d7b86c736db512286f6cce8e513cc30c48d68fe3810" + "sha256": "53409f1c6726e95cf348740b1dc55124b77a1f327aea273dce041b5056270b2e" }, "pipfile-spec": 6, "requires": { @@ -238,11 +238,11 @@ }, "idna": { "hashes": [ - "sha256:5205d03e7bcbb919cc9c19885f9920d622ca52448306f2377daede5cf3faac16", - "sha256:c5b02147e01ea9920e6b0a3f1f7bb833612d507592c837a6c49552768f4054e1" + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" ], - "markers": "python_version >= '3.4'", - "version": "==3.1" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.10" }, "multidict": { "hashes": [ @@ -412,6 +412,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==3.5.3" }, + "requests": { + "hashes": [ + "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804", + "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e" + ], + "index": "pypi", + "version": "==2.25.1" + }, "sentry-sdk": { "hashes": [ "sha256:4ae8d1ced6c67f1c8ea51d82a16721c166c489b76876c9f2c202b8a50334b237", @@ -585,11 +593,11 @@ }, "identify": { "hashes": [ - "sha256:de7129142a5c86d75a52b96f394d94d96d497881d2aaf8eafe320cdbe8ac4bcc", - "sha256:e0dae57c0397629ce13c289f6ddde0204edf518f557bfdb1e56474aa143e77c3" + "sha256:9cdd81e5d2b6e76c3006d5226316dd947bd6324fbeebb881bec489202fa09d3a", + "sha256:b99aa309329c4fea679463eb35d169f3fbe13e66e9dd6162ad1856cbeb03dcbd" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.5.14" + "markers": "python_full_version >= '3.6.1'", + "version": "==2.0.0" }, "mccabe": { "hashes": [ diff --git a/bot/constants.py b/bot/constants.py index db34b55a..f8ea5743 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -271,6 +271,7 @@ class Tokens(NamedTuple): igdb_client_id = environ.get("IGDB_CLIENT_ID") igdb_client_secret = environ.get("IGDB_CLIENT_SECRET") github = environ.get("GITHUB_TOKEN") + unsplash_key = environ.get("UNSPLASH_KEY") class Wolfram(NamedTuple): diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 436b39a7..478502eb 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -1,8 +1,5 @@ -import asyncio import logging -import random -from unsplash.api import Api as uApi -from unsplash.auth import Auth as uAuth +import requests import discord from discord.ext import commands @@ -11,27 +8,33 @@ from bot.constants import Tokens log = logging.getLogger(__name__) -UnClient_id = Tokens.UNSPLASH_API +UnClient_id = Tokens.unsplash_key -UnClient_secret = Tokens.UNSPLASH_SECRET - -redirect_uri = "urn:ietf:wg:oauth:2.0:oob" - -unsplash_auth = uAuth(client_id, class EarthPhotos(commands.Cog): """This cog contains the command for earth photos.""" - + def init(self, bot: commands.Bot): self.bot = bot self.current_channel = None - + @commands.command(aliases=["earth"]) async def earth_photos(self, ctx: commands.Context): """ Returns a random photo of earth, sourced from Unsplash. """ - - - - + photorequest = requests.get("https://api.unsplash.com/photos/random?query=earth&client_id=" + UnClient_id) + photojson = photorequest.json() + photourls = photojson.get('urls') + urltosend = photourls.get('regular') + userjson = photojson.get('user') + userName = userjson.get('name') + embed = discord.Embed(title="Earth Photo", description="A photo of Earth from Unsplash.", color=0x66ff00) + embed.set_image(url=urltosend) + embed.set_footer(text="Image by " + userName + " on Unsplash.") + await ctx.send(embed=embed) + + +def setup(bot: commands.Bot) -> None: + """Cog load""" + bot.add_cog(EarthPhotos(bot)) -- cgit v1.2.3 From 51f16ed0a4e1ce43d7ce4cef1701a886d1b8492d Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Tue, 2 Mar 2021 21:58:27 -0600 Subject: Update earth_photos.py --- bot/exts/easter/earth_photos.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 478502eb..2ca43e42 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -1,9 +1,10 @@ -import logging -import requests - import discord from discord.ext import commands +import logging + +import requests + from bot.constants import Tokens log = logging.getLogger(__name__) @@ -15,6 +16,7 @@ class EarthPhotos(commands.Cog): """This cog contains the command for earth photos.""" def init(self, bot: commands.Bot): + """Init function.""" self.bot = bot self.current_channel = None @@ -28,13 +30,13 @@ class EarthPhotos(commands.Cog): photourls = photojson.get('urls') urltosend = photourls.get('regular') userjson = photojson.get('user') - userName = userjson.get('name') + username = userjson.get('name') embed = discord.Embed(title="Earth Photo", description="A photo of Earth from Unsplash.", color=0x66ff00) embed.set_image(url=urltosend) - embed.set_footer(text="Image by " + userName + " on Unsplash.") + embed.set_footer(text="Image by " + username + " on Unsplash.") await ctx.send(embed=embed) def setup(bot: commands.Bot) -> None: - """Cog load""" + """Cog load.""" bot.add_cog(EarthPhotos(bot)) -- cgit v1.2.3 From 286d40bb887246216da23857b4eeb8364fcbf9c7 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Tue, 2 Mar 2021 22:04:47 -0600 Subject: linting changes --- bot/exts/easter/earth_photos.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 2ca43e42..e660112f 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -1,8 +1,10 @@ import discord -from discord.ext import commands import logging +from discord.ext import commands + + import requests from bot.constants import Tokens @@ -22,9 +24,7 @@ class EarthPhotos(commands.Cog): @commands.command(aliases=["earth"]) async def earth_photos(self, ctx: commands.Context): - """ - Returns a random photo of earth, sourced from Unsplash. - """ + """Returns a random photo of earth, sourced from Unsplash.""" photorequest = requests.get("https://api.unsplash.com/photos/random?query=earth&client_id=" + UnClient_id) photojson = photorequest.json() photourls = photojson.get('urls') -- cgit v1.2.3 From 8220661e8ef65ef4bbe92613ed2d3f273d43d76f Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Tue, 2 Mar 2021 22:09:10 -0600 Subject: more linting fixes --- bot/exts/easter/earth_photos.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index e660112f..c9cfc9c8 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -1,11 +1,9 @@ -import discord - import logging -from discord.ext import commands - +import discord import requests +from discord.ext import commands from bot.constants import Tokens -- cgit v1.2.3 From da54e5181cbf2ab3406be4a8ab9628e346d3c328 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Tue, 2 Mar 2021 22:15:57 -0600 Subject: lint fixes --- bot/exts/easter/earth_photos.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index c9cfc9c8..909fcbd8 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -1,7 +1,6 @@ import logging import discord - import requests from discord.ext import commands @@ -15,13 +14,13 @@ UnClient_id = Tokens.unsplash_key class EarthPhotos(commands.Cog): """This cog contains the command for earth photos.""" - def init(self, bot: commands.Bot): + def init(self, bot: commands.Bot) -> None: """Init function.""" self.bot = bot self.current_channel = None @commands.command(aliases=["earth"]) - async def earth_photos(self, ctx: commands.Context): + async def earth_photos(self, ctx: commands.Context) -> None: """Returns a random photo of earth, sourced from Unsplash.""" photorequest = requests.get("https://api.unsplash.com/photos/random?query=earth&client_id=" + UnClient_id) photojson = photorequest.json() -- cgit v1.2.3 From 029f5f0d6b38f70000013ca52c859a3486cdf544 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Wed, 3 Mar 2021 07:14:06 -0600 Subject: Update bot/exts/easter/earth_photos.py Co-authored-by: Shivansh-007 <69356296+Shivansh-007@users.noreply.github.com> --- bot/exts/easter/earth_photos.py | 1 - 1 file changed, 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 909fcbd8..b41b277c 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -15,7 +15,6 @@ class EarthPhotos(commands.Cog): """This cog contains the command for earth photos.""" def init(self, bot: commands.Bot) -> None: - """Init function.""" self.bot = bot self.current_channel = None -- cgit v1.2.3 From 883405e6f419ebfe4799086bf4e7516fd1588c4d Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Wed, 3 Mar 2021 07:43:41 -0600 Subject: init to __init__ Co-authored-by: Shivansh-007 <69356296+Shivansh-007@users.noreply.github.com> --- bot/exts/easter/earth_photos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index b41b277c..db295285 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -14,7 +14,7 @@ UnClient_id = Tokens.unsplash_key class EarthPhotos(commands.Cog): """This cog contains the command for earth photos.""" - def init(self, bot: commands.Bot) -> None: + def __init__(self, bot: commands.Bot) -> None: self.bot = bot self.current_channel = None -- cgit v1.2.3 From 246e5bd7109ba906162989e42c77d68402359106 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Wed, 3 Mar 2021 09:26:48 -0600 Subject: Fix docstrings Co-authored-by: Shivansh-007 <69356296+Shivansh-007@users.noreply.github.com> --- bot/exts/easter/earth_photos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index db295285..4c319eaa 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -34,5 +34,5 @@ class EarthPhotos(commands.Cog): def setup(bot: commands.Bot) -> None: - """Cog load.""" + """Load the Earth Photos cog.""" bot.add_cog(EarthPhotos(bot)) -- cgit v1.2.3 From 4a0401ddb322fba53e2025a63fdf8d0a52e12076 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Wed, 3 Mar 2021 09:32:47 -0600 Subject: Update earth_photos.py --- bot/exts/easter/earth_photos.py | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 4c319eaa..52bbaf36 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -1,13 +1,9 @@ -import logging - +import aiohttp import discord -import requests from discord.ext import commands from bot.constants import Tokens -log = logging.getLogger(__name__) - UnClient_id = Tokens.unsplash_key @@ -21,16 +17,14 @@ class EarthPhotos(commands.Cog): @commands.command(aliases=["earth"]) async def earth_photos(self, ctx: commands.Context) -> None: """Returns a random photo of earth, sourced from Unsplash.""" - photorequest = requests.get("https://api.unsplash.com/photos/random?query=earth&client_id=" + UnClient_id) - photojson = photorequest.json() - photourls = photojson.get('urls') - urltosend = photourls.get('regular') - userjson = photojson.get('user') - username = userjson.get('name') - embed = discord.Embed(title="Earth Photo", description="A photo of Earth from Unsplash.", color=0x66ff00) - embed.set_image(url=urltosend) - embed.set_footer(text="Image by " + username + " on Unsplash.") - await ctx.send(embed=embed) + async with ctx.typing(): + async with aiohttp.ClientSession as session: + async with session.get( + 'https://api.unsplash.com/photos/random?query=earth&client_id=' + UnClientId + ) as r: + jsondata = await r.json() + await ctx.send("Still a placeholder") + def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From a2c68caf0e39e6947372d303dcc707f26f1a744f Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Wed, 3 Mar 2021 09:57:07 -0600 Subject: Update earth_photos.py --- bot/exts/easter/earth_photos.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 52bbaf36..adae0dcd 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -20,10 +20,18 @@ class EarthPhotos(commands.Cog): async with ctx.typing(): async with aiohttp.ClientSession as session: async with session.get( - 'https://api.unsplash.com/photos/random?query=earth&client_id=' + UnClientId - ) as r: + 'https://api.unsplash.com/photos/random?query=earth&client_id=' + UnClientId) as r: jsondata = await r.json() - await ctx.send("Still a placeholder") + linksdata = jsondata.get("urls") + downloadlinksdata = jsondata.get("links") + async with session.get( + downloadlinksdata.get("download_location") + "?client_id=" + UnClient_id) as er: + pass + await ctx.send("Still a work in progress") + + + + -- cgit v1.2.3 From 01a1624b14cc5d60b2e76871361e14f9cbfd69ce Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Wed, 3 Mar 2021 09:57:49 -0600 Subject: asyncio start --- bot/exts/easter/earth_photos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index adae0dcd..26beda79 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -27,7 +27,7 @@ class EarthPhotos(commands.Cog): async with session.get( downloadlinksdata.get("download_location") + "?client_id=" + UnClient_id) as er: pass - await ctx.send("Still a work in progress") + await ctx.send("Still a work in progress, coming soon.") -- cgit v1.2.3 From 3b0949c96926fa30aa650bfd9c9a43e4fd52521f Mon Sep 17 00:00:00 2001 From: Kronifer Date: Wed, 3 Mar 2021 16:39:05 +0000 Subject: linting --- Pipfile | 1 + Pipfile.lock | 76 ++++++++++++++++++++++++++++++++++++++--- bot/exts/easter/earth_photos.py | 14 ++++---- 3 files changed, 79 insertions(+), 12 deletions(-) (limited to 'bot') diff --git a/Pipfile b/Pipfile index 1a2d464e..1d1df3d7 100644 --- a/Pipfile +++ b/Pipfile @@ -16,6 +16,7 @@ PyYAML = "~=5.3.1" async-rediscache = {extras = ["fakeredis"], version = "~=0.1.4"} emojis = "~=0.6.0" requests = "~=2.25.1" +pre-commit = "*" [dev-packages] flake8 = "~=3.8" diff --git a/Pipfile.lock b/Pipfile.lock index 34cd08cf..b58db761 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "53409f1c6726e95cf348740b1dc55124b77a1f327aea273dce041b5056270b2e" + "sha256": "434b76f6a372bf3ddc418d7b6bdba4d8906cbebb76553ffebf0b15d572e83487" }, "pipfile-spec": 6, "requires": { @@ -50,6 +50,13 @@ ], "version": "==1.3.1" }, + "appdirs": { + "hashes": [ + "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", + "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128" + ], + "version": "==1.4.4" + }, "arrow": { "hashes": [ "sha256:e098abbd9af3665aea81bdd6c869e93af4feb078e98468dd351c383af187aac5", @@ -143,6 +150,14 @@ ], "version": "==1.14.5" }, + "cfgv": { + "hashes": [ + "sha256:32e43d604bbe7896fe7c248a9c2276447dbef840feb28fe20494f62af110211d", + "sha256:cf22deb93d4bcf92f345a5c3cd39d3d41d6340adc60c78bbbd6588c384fda6a1" + ], + "markers": "python_full_version >= '3.6.1'", + "version": "==3.2.0" + }, "chardet": { "hashes": [ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", @@ -161,6 +176,13 @@ "index": "pypi", "version": "==1.5.1" }, + "distlib": { + "hashes": [ + "sha256:8c09de2c67b3e7deef7184574fc060ab8a793e7adbb183d942c389c8b13c52fb", + "sha256:edf6116872c863e1aa9d5bb7cb5e05a022c519a4594dc703843343a9ddd9bff1" + ], + "version": "==0.3.1" + }, "emojis": { "hashes": [ "sha256:7da34c8a78ae262fd68cef9e2c78a3c1feb59784489eeea0f54ba1d4b7111c7c", @@ -176,6 +198,13 @@ ], "version": "==1.4.5" }, + "filelock": { + "hashes": [ + "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59", + "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836" + ], + "version": "==3.0.12" + }, "fuzzywuzzy": { "hashes": [ "sha256:45016e92264780e58972dca1b3d939ac864b78437422beecebb3095f8efd00e8", @@ -236,6 +265,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.1.0" }, + "identify": { + "hashes": [ + "sha256:2179e7359471ab55729f201b3fdf7dc2778e221f868410fedcb0987b791ba552", + "sha256:2a5fdf2f5319cc357eda2550bea713a404392495961022cf2462624ce62f0f46" + ], + "markers": "python_full_version >= '3.6.1'", + "version": "==2.1.0" + }, "idna": { "hashes": [ "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", @@ -267,6 +304,13 @@ "markers": "python_version >= '3.5'", "version": "==4.7.6" }, + "nodeenv": { + "hashes": [ + "sha256:5304d424c529c997bc888453aeaa6362d242b6b4631e90f3d4bf1b290f1c84a9", + "sha256:ab45090ae383b716c4ef89e690c41ff8c2b257b85b309f01f3654df3d084bd7c" + ], + "version": "==1.5.0" + }, "pillow": { "hashes": [ "sha256:0295442429645fa16d05bd567ef5cff178482439c9aad0411d3f0ce9b88b3a6f", @@ -301,6 +345,14 @@ "index": "pypi", "version": "==7.2.0" }, + "pre-commit": { + "hashes": [ + "sha256:16212d1fde2bed88159287da88ff03796863854b04dc9f838a55979325a3d20e", + "sha256:399baf78f13f4de82a29b649afd74bef2c4e28eb4f021661fc7f29246e8c7a3a" + ], + "index": "pypi", + "version": "==2.10.1" + }, "pycares": { "hashes": [ "sha256:050f00b39ed77ea8a4e555f09417d4b1a6b5baa24bb9531a3e15d003d2319b3f", @@ -451,6 +503,14 @@ "markers": "python_version >= '3.0'", "version": "==2.2" }, + "toml": { + "hashes": [ + "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", + "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.10.2" + }, "urllib3": { "hashes": [ "sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80", @@ -459,6 +519,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", "version": "==1.26.3" }, + "virtualenv": { + "hashes": [ + "sha256:147b43894e51dd6bba882cf9c282447f780e2251cd35172403745fc381a0a80d", + "sha256:2be72df684b74df0ea47679a7df93fd0e04e72520022c57b479d8f881485dbe3" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==20.4.2" + }, "yarl": { "hashes": [ "sha256:040b237f58ff7d800e6e0fd89c8439b841f777dd99b4a9cca04d6935564b9409", @@ -593,11 +661,11 @@ }, "identify": { "hashes": [ - "sha256:9cdd81e5d2b6e76c3006d5226316dd947bd6324fbeebb881bec489202fa09d3a", - "sha256:b99aa309329c4fea679463eb35d169f3fbe13e66e9dd6162ad1856cbeb03dcbd" + "sha256:2179e7359471ab55729f201b3fdf7dc2778e221f868410fedcb0987b791ba552", + "sha256:2a5fdf2f5319cc357eda2550bea713a404392495961022cf2462624ce62f0f46" ], "markers": "python_full_version >= '3.6.1'", - "version": "==2.0.0" + "version": "==2.1.0" }, "mccabe": { "hashes": [ diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 26beda79..8e90c9e7 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -20,19 +20,17 @@ class EarthPhotos(commands.Cog): async with ctx.typing(): async with aiohttp.ClientSession as session: async with session.get( - 'https://api.unsplash.com/photos/random?query=earth&client_id=' + UnClientId) as r: + 'https://api.unsplash.com/photos/random?query=earth&client_id=' + UnClient_id) as r: jsondata = await r.json() linksdata = jsondata.get("urls") + embedlink = linksdata.get("full") downloadlinksdata = jsondata.get("links") async with session.get( downloadlinksdata.get("download_location") + "?client_id=" + UnClient_id) as er: - pass - await ctx.send("Still a work in progress, coming soon.") - - - - - + er.status() + embed = discord.Embed(title="In progress") + embed.set_photo(url=embedlink) + await ctx.send(embed=embed) def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From 443c623548caf8edb82d0b9cfe41afcf594f0161 Mon Sep 17 00:00:00 2001 From: Kronifer Date: Wed, 3 Mar 2021 16:48:19 +0000 Subject: final lint fix --- bot/exts/easter/earth_photos.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 8e90c9e7..e3d5936e 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -20,13 +20,13 @@ class EarthPhotos(commands.Cog): async with ctx.typing(): async with aiohttp.ClientSession as session: async with session.get( - 'https://api.unsplash.com/photos/random?query=earth&client_id=' + UnClient_id) as r: + 'https://api.unsplash.com/photos/random?query=earth&client_id=' + UnClient_id) as r: jsondata = await r.json() linksdata = jsondata.get("urls") embedlink = linksdata.get("full") downloadlinksdata = jsondata.get("links") async with session.get( - downloadlinksdata.get("download_location") + "?client_id=" + UnClient_id) as er: + downloadlinksdata.get("download_location") + "?client_id=" + UnClient_id) as er: er.status() embed = discord.Embed(title="In progress") embed.set_photo(url=embedlink) -- cgit v1.2.3 From f0cd29587f29731286be8c29d1ee0ca20d37d42f Mon Sep 17 00:00:00 2001 From: Kronifer Date: Wed, 3 Mar 2021 17:07:20 +0000 Subject: possible final update --- bot/exts/easter/earth_photos.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index e3d5936e..0ac470ce 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -18,19 +18,27 @@ class EarthPhotos(commands.Cog): async def earth_photos(self, ctx: commands.Context) -> None: """Returns a random photo of earth, sourced from Unsplash.""" async with ctx.typing(): - async with aiohttp.ClientSession as session: + async with aiohttp.ClientSession() as session: async with session.get( 'https://api.unsplash.com/photos/random?query=earth&client_id=' + UnClient_id) as r: jsondata = await r.json() linksdata = jsondata.get("urls") embedlink = linksdata.get("full") downloadlinksdata = jsondata.get("links") + userdata = jsondata.get("user") + username = userdata.get("name") + userlinks = userdata.get("links") + profile = userlinks.get("html") async with session.get( downloadlinksdata.get("download_location") + "?client_id=" + UnClient_id) as er: - er.status() - embed = discord.Embed(title="In progress") - embed.set_photo(url=embedlink) - await ctx.send(embed=embed) + er.status + embed = discord.Embed( + title="Earth Photo", + description="A photo of earth from Unsplash.", + color=0x66ff00) + embed.set_image(url=embedlink) + embed.add_field(title="Author", value="Made by [" + username + "](" + profile + ") on Unsplash.") + await ctx.send(embed=embed) def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From b2ee1b9e79766b8cfe7b45670f6c86e7166ee84f Mon Sep 17 00:00:00 2001 From: Kronifer Date: Wed, 3 Mar 2021 20:20:22 +0000 Subject: fstrings, colours, and self.bot --- Pipfile | 2 -- bot/constants.py | 1 + bot/exts/easter/earth_photos.py | 48 ++++++++++++++++++++--------------------- 3 files changed, 25 insertions(+), 26 deletions(-) (limited to 'bot') diff --git a/Pipfile b/Pipfile index 1d1df3d7..e7e01a31 100644 --- a/Pipfile +++ b/Pipfile @@ -15,8 +15,6 @@ PyYAML = "~=5.3.1" "discord.py" = {extras = ["voice"], version = "~=1.5.1"} async-rediscache = {extras = ["fakeredis"], version = "~=0.1.4"} emojis = "~=0.6.0" -requests = "~=2.25.1" -pre-commit = "*" [dev-packages] flake8 = "~=3.8" diff --git a/bot/constants.py b/bot/constants.py index f8ea5743..c570b17f 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -158,6 +158,7 @@ class Colours: soft_orange = 0xf9cb54 soft_red = 0xcd6d6d yellow = 0xf9f586 + grass_green = 0x66ff00 class Emojis: diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 0ac470ce..a49e666c 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -1,8 +1,8 @@ -import aiohttp import discord from discord.ext import commands from bot.constants import Tokens +from bot.constants import Colours UnClient_id = Tokens.unsplash_key @@ -10,35 +10,35 @@ UnClient_id = Tokens.unsplash_key class EarthPhotos(commands.Cog): """This cog contains the command for earth photos.""" - def __init__(self, bot: commands.Bot) -> None: + def __init__(self, bot: commands.Bot): self.bot = bot - self.current_channel = None @commands.command(aliases=["earth"]) async def earth_photos(self, ctx: commands.Context) -> None: """Returns a random photo of earth, sourced from Unsplash.""" async with ctx.typing(): - async with aiohttp.ClientSession() as session: - async with session.get( - 'https://api.unsplash.com/photos/random?query=earth&client_id=' + UnClient_id) as r: - jsondata = await r.json() - linksdata = jsondata.get("urls") - embedlink = linksdata.get("full") - downloadlinksdata = jsondata.get("links") - userdata = jsondata.get("user") - username = userdata.get("name") - userlinks = userdata.get("links") - profile = userlinks.get("html") - async with session.get( - downloadlinksdata.get("download_location") + "?client_id=" + UnClient_id) as er: - er.status - embed = discord.Embed( - title="Earth Photo", - description="A photo of earth from Unsplash.", - color=0x66ff00) - embed.set_image(url=embedlink) - embed.add_field(title="Author", value="Made by [" + username + "](" + profile + ") on Unsplash.") - await ctx.send(embed=embed) + async with self.bot.http_session.get( + 'https://api.unsplash.com/photos/random', + params={"query": "planet_earth", "client_id": UnClient_id}) as r: + jsondata = await r.json() + linksdata = jsondata.get("urls") + embedlink = linksdata.get("full") + downloadlinksdata = jsondata.get("links") + userdata = jsondata.get("user") + username = userdata.get("name") + userlinks = userdata.get("links") + profile = userlinks.get("html") + async with self.bot.http_session.get( + downloadlinksdata.get("download_location"), + params={"client_id": UnClient_id}) as er: + er.status + embed = discord.Embed( + title="Earth Photo", + description="A photo of earth from Unsplash.", + color=Colours.grass_green) + embed.set_image(url=embedlink) + embed.add_field(name="Author", value=f"Made by [{username}]({profile}) on Unsplash.") + await ctx.send(embed=embed) def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From 4cf72b014efbd8141e30482984e68e65c08e312d Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Wed, 3 Mar 2021 14:28:43 -0600 Subject: Fixed import --- bot/exts/easter/earth_photos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index a49e666c..b496cbea 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -1,8 +1,8 @@ import discord from discord.ext import commands -from bot.constants import Tokens from bot.constants import Colours +from bot.constants import Tokens UnClient_id = Tokens.unsplash_key -- cgit v1.2.3 From 6c46dca3525758f1c1841f1dba312bb45c28531e Mon Sep 17 00:00:00 2001 From: Kronifer Date: Wed, 3 Mar 2021 22:27:37 +0000 Subject: minor change to getting image --- bot/exts/easter/earth_photos.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index a49e666c..66780f6a 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -19,10 +19,10 @@ class EarthPhotos(commands.Cog): async with ctx.typing(): async with self.bot.http_session.get( 'https://api.unsplash.com/photos/random', - params={"query": "planet_earth", "client_id": UnClient_id}) as r: + params={"query": "earth", "client_id": UnClient_id}) as r: jsondata = await r.json() linksdata = jsondata.get("urls") - embedlink = linksdata.get("full") + embedlink = linksdata.get("regular") downloadlinksdata = jsondata.get("links") userdata = jsondata.get("user") username = userdata.get("name") -- cgit v1.2.3 From 01c380754e7466654924238dcee2f2077dd752a7 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Wed, 3 Mar 2021 19:03:40 -0600 Subject: Format change Co-authored-by: Shivansh-007 <69356296+Shivansh-007@users.noreply.github.com> --- bot/exts/easter/earth_photos.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index efc5081a..a544ab59 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -35,7 +35,8 @@ class EarthPhotos(commands.Cog): embed = discord.Embed( title="Earth Photo", description="A photo of earth from Unsplash.", - color=Colours.grass_green) + color=Colours.grass_green + ) embed.set_image(url=embedlink) embed.add_field(name="Author", value=f"Made by [{username}]({profile}) on Unsplash.") await ctx.send(embed=embed) -- cgit v1.2.3 From fa38d70fc16e34ff3aff58bfbc7533f586a8eb97 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Wed, 3 Mar 2021 19:05:16 -0600 Subject: More formatting Co-authored-by: Shivansh-007 <69356296+Shivansh-007@users.noreply.github.com> --- bot/exts/easter/earth_photos.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index a544ab59..f0c57fc5 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -30,7 +30,8 @@ class EarthPhotos(commands.Cog): profile = userlinks.get("html") async with self.bot.http_session.get( downloadlinksdata.get("download_location"), - params={"client_id": UnClient_id}) as er: + params={"client_id": UnClient_id} + ) as er: er.status embed = discord.Embed( title="Earth Photo", -- cgit v1.2.3 From 825080e805787afc1f36a80b4fa3f73040ebdc75 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Wed, 3 Mar 2021 19:05:37 -0600 Subject: Format change Co-authored-by: Shivansh-007 <69356296+Shivansh-007@users.noreply.github.com> --- bot/exts/easter/earth_photos.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index f0c57fc5..6bfc26b0 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -19,7 +19,8 @@ class EarthPhotos(commands.Cog): async with ctx.typing(): async with self.bot.http_session.get( 'https://api.unsplash.com/photos/random', - params={"query": "earth", "client_id": UnClient_id}) as r: + params={"query": "earth", "client_id": UnClient_id} + ) as r: jsondata = await r.json() linksdata = jsondata.get("urls") embedlink = linksdata.get("regular") -- cgit v1.2.3 From 05e18c02cd076a70e3aac370e7d120a16c84aab7 Mon Sep 17 00:00:00 2001 From: Kronifer Date: Thu, 4 Mar 2021 01:31:14 +0000 Subject: Revert "Format change" This reverts commit 825080e805787afc1f36a80b4fa3f73040ebdc75. --- bot/exts/easter/earth_photos.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 6bfc26b0..f0c57fc5 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -19,8 +19,7 @@ class EarthPhotos(commands.Cog): async with ctx.typing(): async with self.bot.http_session.get( 'https://api.unsplash.com/photos/random', - params={"query": "earth", "client_id": UnClient_id} - ) as r: + params={"query": "earth", "client_id": UnClient_id}) as r: jsondata = await r.json() linksdata = jsondata.get("urls") embedlink = linksdata.get("regular") -- cgit v1.2.3 From 60712f67c3e0f77023a481e5cbf0ce9816a7368e Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Wed, 3 Mar 2021 20:16:59 -0600 Subject: requested changes by @Shivansh-007 --- bot/exts/easter/earth_photos.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index f0c57fc5..001f8f41 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -31,8 +31,8 @@ class EarthPhotos(commands.Cog): async with self.bot.http_session.get( downloadlinksdata.get("download_location"), params={"client_id": UnClient_id} - ) as er: - er.status + ) as _: + pass embed = discord.Embed( title="Earth Photo", description="A photo of earth from Unsplash.", -- cgit v1.2.3 From e222ece92b4d14f4a9bb148f28acf9770da44d1b Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Thu, 4 Mar 2021 10:35:38 -0600 Subject: Changes requested by @ChrisLovering --- bot/exts/easter/earth_photos.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 001f8f41..3ab8e7d9 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -1,10 +1,12 @@ +import logging + import discord from discord.ext import commands from bot.constants import Colours from bot.constants import Tokens -UnClient_id = Tokens.unsplash_key +log = logging.getLogger(__name__) class EarthPhotos(commands.Cog): @@ -19,7 +21,7 @@ class EarthPhotos(commands.Cog): async with ctx.typing(): async with self.bot.http_session.get( 'https://api.unsplash.com/photos/random', - params={"query": "earth", "client_id": UnClient_id}) as r: + params={"query": "earth", "client_id": Tokens.unsplash_access_key}) as r: jsondata = await r.json() linksdata = jsondata.get("urls") embedlink = linksdata.get("regular") @@ -30,9 +32,10 @@ class EarthPhotos(commands.Cog): profile = userlinks.get("html") async with self.bot.http_session.get( downloadlinksdata.get("download_location"), - params={"client_id": UnClient_id} - ) as _: + params={"client_id": Tokens.unsplash_access_key} + ) as er: pass + embed = discord.Embed( title="Earth Photo", description="A photo of earth from Unsplash.", @@ -45,4 +48,7 @@ class EarthPhotos(commands.Cog): def setup(bot: commands.Bot) -> None: """Load the Earth Photos cog.""" + if not Tokens.unsplash_access_key: + log.warning("No Unsplash access key found. Cog not loading.") + return bot.add_cog(EarthPhotos(bot)) -- cgit v1.2.3 From 512a5b3f085510d5862589ecc21bd253cb219207 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Thu, 4 Mar 2021 10:37:53 -0600 Subject: Changes requested by @ChrisLovering --- bot/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index c570b17f..721defc8 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -272,7 +272,7 @@ class Tokens(NamedTuple): igdb_client_id = environ.get("IGDB_CLIENT_ID") igdb_client_secret = environ.get("IGDB_CLIENT_SECRET") github = environ.get("GITHUB_TOKEN") - unsplash_key = environ.get("UNSPLASH_KEY") + unsplash_access_key = environ.get("UNSPLASH_KEY") class Wolfram(NamedTuple): -- cgit v1.2.3 From 8b05f80392174a1a8b47e872b955d59bdcd4472f Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Thu, 4 Mar 2021 10:40:42 -0600 Subject: small lint fix --- bot/exts/easter/earth_photos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 3ab8e7d9..beb16772 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -33,7 +33,7 @@ class EarthPhotos(commands.Cog): async with self.bot.http_session.get( downloadlinksdata.get("download_location"), params={"client_id": Tokens.unsplash_access_key} - ) as er: + ) as _: pass embed = discord.Embed( -- cgit v1.2.3 From f22aa5bd3f706751556def22d5660cdc8d93fde1 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Thu, 4 Mar 2021 10:56:06 -0600 Subject: Format fix Co-authored-by: Shivansh-007 <69356296+Shivansh-007@users.noreply.github.com> --- bot/exts/easter/earth_photos.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index beb16772..3abedd0c 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -21,7 +21,8 @@ class EarthPhotos(commands.Cog): async with ctx.typing(): async with self.bot.http_session.get( 'https://api.unsplash.com/photos/random', - params={"query": "earth", "client_id": Tokens.unsplash_access_key}) as r: + params={"query": "earth", "client_id": Tokens.unsplash_access_key} + ) as r: jsondata = await r.json() linksdata = jsondata.get("urls") embedlink = linksdata.get("regular") -- cgit v1.2.3 From 1e1f4035f14592d7beaf93cbd3ae8e3895de588c Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Thu, 4 Mar 2021 10:56:36 -0600 Subject: String upgrade Co-authored-by: Shivansh-007 <69356296+Shivansh-007@users.noreply.github.com> --- bot/exts/easter/earth_photos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 3abedd0c..d3b21644 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -39,7 +39,7 @@ class EarthPhotos(commands.Cog): embed = discord.Embed( title="Earth Photo", - description="A photo of earth from Unsplash.", + description="A photo of Earth 🌎 from Unsplash.", color=Colours.grass_green ) embed.set_image(url=embedlink) -- cgit v1.2.3 From 3fa4049b0c16777c7a9349dc9058d89a4a44b5c7 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Thu, 4 Mar 2021 10:58:25 -0600 Subject: Update earth_photos.py --- bot/exts/easter/earth_photos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index d3b21644..71fb1313 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -43,7 +43,7 @@ class EarthPhotos(commands.Cog): color=Colours.grass_green ) embed.set_image(url=embedlink) - embed.add_field(name="Author", value=f"Made by [{username}]({profile}) on Unsplash.") + embed.add_field(name="Author", value=f"Photo by [{username}]({profile}) on Unsplash.") await ctx.send(embed=embed) -- cgit v1.2.3 From c25381fffd3b42bd1345dd9a910218c70877d2d3 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Thu, 4 Mar 2021 10:59:36 -0600 Subject: suggestion by @Shivansh-007 --- bot/exts/easter/earth_photos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 71fb1313..1cf2d11a 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -44,7 +44,7 @@ class EarthPhotos(commands.Cog): ) embed.set_image(url=embedlink) embed.add_field(name="Author", value=f"Photo by [{username}]({profile}) on Unsplash.") - await ctx.send(embed=embed) + await ctx.send(embed=embed) def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From 68ff4f3a524e90099e6953bd601321623e789e66 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Thu, 4 Mar 2021 11:04:05 -0600 Subject: clarification in some areas --- bot/exts/easter/earth_photos.py | 1 + 1 file changed, 1 insertion(+) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 1cf2d11a..c1704e12 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -31,6 +31,7 @@ class EarthPhotos(commands.Cog): username = userdata.get("name") userlinks = userdata.get("links") profile = userlinks.get("html") + # Extra request as per Unsplash Guidelines async with self.bot.http_session.get( downloadlinksdata.get("download_location"), params={"client_id": Tokens.unsplash_access_key} -- cgit v1.2.3 From 55e33789830c00fc970c74be142857f90678cda7 Mon Sep 17 00:00:00 2001 From: MrKomodoDragon Date: Thu, 4 Mar 2021 11:20:37 -0800 Subject: Add link to discussion for suggesting facts in Embed --- bot/exts/evergreen/pythonfacts.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/pythonfacts.py b/bot/exts/evergreen/pythonfacts.py index 11b258f9..fb96a19d 100644 --- a/bot/exts/evergreen/pythonfacts.py +++ b/bot/exts/evergreen/pythonfacts.py @@ -20,7 +20,12 @@ class PythonFacts(commands.Cog): @commands.command(name='pythonfact', aliases=['pyfact']) async def get_python_fact(self, ctx: commands.Context) -> None: """Sends a Random fun fact about Python.""" - embed = discord.Embed(title='Python Facts', description=next(FACTS), colour=next(COLORS)) + embed = discord.Embed(title='Python Facts', + description=next(FACTS), + colour=next(COLORS)) + embed.add_field(name='Suggestions', + value="Want to suggest more facts? " + "Suggest more facts [here!](https://github.com/python-discord/meta/discussions/93)") await ctx.send(embed=embed) -- cgit v1.2.3 From cce1b2cb25b572ac3e976b190d7eae417240ae76 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Thu, 4 Mar 2021 13:26:42 -0600 Subject: API guideline fix for Unsplash --- bot/exts/easter/earth_photos.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index c1704e12..39bb627e 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -31,7 +31,6 @@ class EarthPhotos(commands.Cog): username = userdata.get("name") userlinks = userdata.get("links") profile = userlinks.get("html") - # Extra request as per Unsplash Guidelines async with self.bot.http_session.get( downloadlinksdata.get("download_location"), params={"client_id": Tokens.unsplash_access_key} @@ -44,7 +43,9 @@ class EarthPhotos(commands.Cog): color=Colours.grass_green ) embed.set_image(url=embedlink) - embed.add_field(name="Author", value=f"Photo by [{username}]({profile}) on Unsplash.") + embed.add_field(name="Author", + value=f"Photo by [{username}]({profile}?utm_source=sir_lancebot&utm_medium=referral)\ + on [Unsplash](https://unsplash.com?utm_source=sir_lancebot&utm_medium=referral).") await ctx.send(embed=embed) -- cgit v1.2.3 From 6b8a81e7a698eb362b4bea7bb73ef369d589cbfc Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Thu, 4 Mar 2021 13:30:17 -0600 Subject: whitespace fix --- bot/exts/easter/earth_photos.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 39bb627e..9bcca583 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -39,11 +39,11 @@ class EarthPhotos(commands.Cog): embed = discord.Embed( title="Earth Photo", - description="A photo of Earth 🌎 from Unsplash.", + description="A photo of Earth 🌎 from Unsplash.", color=Colours.grass_green ) embed.set_image(url=embedlink) - embed.add_field(name="Author", + embed.add_field(name="Author", value=f"Photo by [{username}]({profile}?utm_source=sir_lancebot&utm_medium=referral)\ on [Unsplash](https://unsplash.com?utm_source=sir_lancebot&utm_medium=referral).") await ctx.send(embed=embed) -- cgit v1.2.3 From 43d42c9fc254e79ecb8e98e42ff4ea9aa43c707a Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Thu, 4 Mar 2021 13:44:31 -0600 Subject: linting fix --- bot/exts/easter/earth_photos.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 9bcca583..26f3d115 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -21,7 +21,7 @@ class EarthPhotos(commands.Cog): async with ctx.typing(): async with self.bot.http_session.get( 'https://api.unsplash.com/photos/random', - params={"query": "earth", "client_id": Tokens.unsplash_access_key} + params={"query": "planet_earth", "client_id": Tokens.unsplash_access_key} ) as r: jsondata = await r.json() linksdata = jsondata.get("urls") @@ -31,6 +31,8 @@ class EarthPhotos(commands.Cog): username = userdata.get("name") userlinks = userdata.get("links") profile = userlinks.get("html") + # Referral flags + rf = "?utm_source=sir_lancebot&utm_medium=referral" async with self.bot.http_session.get( downloadlinksdata.get("download_location"), params={"client_id": Tokens.unsplash_access_key} @@ -39,13 +41,13 @@ class EarthPhotos(commands.Cog): embed = discord.Embed( title="Earth Photo", - description="A photo of Earth 🌎 from Unsplash.", + description="A photo of Earth 🌎 from Unsplash.", color=Colours.grass_green ) embed.set_image(url=embedlink) embed.add_field(name="Author", - value=f"Photo by [{username}]({profile}?utm_source=sir_lancebot&utm_medium=referral)\ - on [Unsplash](https://unsplash.com?utm_source=sir_lancebot&utm_medium=referral).") + value=f"Photo by [{username}]({profile}" + rf + ") \ +on [Unsplash](https://unsplash.com?" + rf + ").") await ctx.send(embed=embed) -- cgit v1.2.3 From e6f2d51cfc35ae8bafc160fb3449911457442252 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Thu, 4 Mar 2021 13:53:45 -0600 Subject: style guidelines --- bot/exts/easter/earth_photos.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 26f3d115..96282d24 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -45,9 +45,11 @@ class EarthPhotos(commands.Cog): color=Colours.grass_green ) embed.set_image(url=embedlink) - embed.add_field(name="Author", - value=f"Photo by [{username}]({profile}" + rf + ") \ -on [Unsplash](https://unsplash.com?" + rf + ").") + embed.add_field( + name="Author", + value=f"Photo by [{username}]({profile}{rf}) \ + on [Unsplash](https://unsplash.com{rf})." + ) await ctx.send(embed=embed) -- cgit v1.2.3 From 1ae9948c04257c27fb2e71e5ae03a05bcd1db60e Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Thu, 4 Mar 2021 13:57:26 -0600 Subject: single space fix --- bot/exts/easter/earth_photos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 96282d24..12fe6f1c 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -41,7 +41,7 @@ class EarthPhotos(commands.Cog): embed = discord.Embed( title="Earth Photo", - description="A photo of Earth 🌎 from Unsplash.", + description="A photo of Earth 🌎 from Unsplash.", color=Colours.grass_green ) embed.set_image(url=embedlink) -- cgit v1.2.3 From 1669b50e026678fd8e9fe6f72677e1de5943dd66 Mon Sep 17 00:00:00 2001 From: MrKomodoDragon Date: Thu, 4 Mar 2021 12:18:25 -0800 Subject: Remove "Want to suggest a fact?" for consistency --- bot/exts/evergreen/pythonfacts.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/pythonfacts.py b/bot/exts/evergreen/pythonfacts.py index fb96a19d..457c2fd3 100644 --- a/bot/exts/evergreen/pythonfacts.py +++ b/bot/exts/evergreen/pythonfacts.py @@ -24,8 +24,7 @@ class PythonFacts(commands.Cog): description=next(FACTS), colour=next(COLORS)) embed.add_field(name='Suggestions', - value="Want to suggest more facts? " - "Suggest more facts [here!](https://github.com/python-discord/meta/discussions/93)") + value="Suggest more facts [here!](https://github.com/python-discord/meta/discussions/93)") await ctx.send(embed=embed) -- cgit v1.2.3 From 334885c1b98ac4dcd475baac358eb8981a65b9c5 Mon Sep 17 00:00:00 2001 From: Dillon Runke <44979306+Kronifer@users.noreply.github.com> Date: Thu, 4 Mar 2021 16:17:42 -0600 Subject: Update earth_photos.py --- bot/exts/easter/earth_photos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 12fe6f1c..60e34b15 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -32,7 +32,7 @@ class EarthPhotos(commands.Cog): userlinks = userdata.get("links") profile = userlinks.get("html") # Referral flags - rf = "?utm_source=sir_lancebot&utm_medium=referral" + rf = "?utm_source=Sir%20Lancebot&utm_medium=referral" async with self.bot.http_session.get( downloadlinksdata.get("download_location"), params={"client_id": Tokens.unsplash_access_key} -- cgit v1.2.3 From bd49374ca6efad79b97d891882b05b8568f10fb4 Mon Sep 17 00:00:00 2001 From: MrKomodoDragon <74436682+MrKomodoDragon@users.noreply.github.com> Date: Thu, 4 Mar 2021 14:39:47 -0800 Subject: Remove arrows (whoopsies)! --- bot/constants.py | 3 --- 1 file changed, 3 deletions(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index f6e09ae7..b8e30a7c 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -158,12 +158,9 @@ class Colours: soft_orange = 0xf9cb54 soft_red = 0xcd6d6d yellow = 0xf9f586 -<<<<<<< master python_blue = 0x4B8BBE python_yellow = 0xFFD43B -======= grass_green = 0x66ff00 ->>>>>>> master class Emojis: -- cgit v1.2.3 From bb8820c9df9a01f39e3d97f76ca25007dd9f4c9e Mon Sep 17 00:00:00 2001 From: kosayoda Date: Sun, 7 Mar 2021 01:35:49 +0800 Subject: Unify emoji count and emoji information to a cog. --- bot/exts/evergreen/emoji.py | 122 ++++++++++++++++++++++++++++++++++++++ bot/exts/evergreen/emoji_count.py | 97 ------------------------------ bot/exts/evergreen/emojis.py | 39 ------------ 3 files changed, 122 insertions(+), 136 deletions(-) create mode 100644 bot/exts/evergreen/emoji.py delete mode 100644 bot/exts/evergreen/emoji_count.py delete mode 100644 bot/exts/evergreen/emojis.py (limited to 'bot') diff --git a/bot/exts/evergreen/emoji.py b/bot/exts/evergreen/emoji.py new file mode 100644 index 00000000..a24d420c --- /dev/null +++ b/bot/exts/evergreen/emoji.py @@ -0,0 +1,122 @@ +import datetime +import logging +import random +import textwrap +from collections import defaultdict +from typing import List, Tuple + +from discord import Color, Embed, Emoji +from discord.ext import commands + +from bot.constants import Colours, ERROR_REPLIES +from bot.utils.pagination import LinePaginator +from bot.utils.time import time_since + +log = logging.getLogger(__name__) + + +class Emoji(commands.Cog): + """A collection of commands related to emojis in the server.""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + + @staticmethod + def embed_builder(emoji: dict) -> Tuple[Embed, List[str]]: + """Generates an embed with the emoji names and count.""" + embed = Embed( + color=Colours.orange, + title="Emoji Count", + timestamp=datetime.datetime.utcnow() + ) + msg = [] + + if len(emoji) == 1: + for category_name, category_emojis in emoji.items(): + if len(category_emojis) == 1: + msg.append(f"There is **{len(category_emojis)}** emoji in **{category_name}** category") + else: + msg.append(f"There are **{len(category_emojis)}** emojis in **{category_name}** category") + embed.set_thumbnail(url=random.choice(category_emojis).url) + + else: + for category_name, category_emojis in emoji.items(): + emoji_choice = random.choice(category_emojis) + if len(category_emojis) > 1: + emoji_info = f"There are **{len(category_emojis)}** emojis in **{category_name}** category" + else: + emoji_info = f"There is **{len(category_emojis)}** emoji in **{category_name}** category" + if emoji_choice.animated: + msg.append(f' {emoji_info}') + else: + msg.append(f'<:{emoji_choice.name}:{emoji_choice.id}> {emoji_info}') + return embed, msg + + @staticmethod + def generate_invalid_embed(emojis: list) -> Tuple[Embed, List[str]]: + """Generates error embed.""" + embed = Embed( + color=Colours.soft_red, + title=random.choice(ERROR_REPLIES) + ) + msg = [] + + emoji_dict = defaultdict(list) + for emoji in emojis: + emoji_dict[emoji.name.split("_")[0]].append(emoji) + + error_comp = ', '.join(emoji_dict) + msg.append(f"These are the valid categories\n```{error_comp}```") + return embed, msg + + @commands.group(name="emoji", invoke_without_command=True) + async def emoji_group(self, ctx: commands.Context) -> None: + """A group of commands related to emojis.""" + await ctx.send_help(ctx.command) + + @emoji_group.command(name="count", aliases=("c",)) + async def count_command(self, ctx: commands.Context, *, category_query: str = None) -> None: + """Returns embed with emoji category and info given by the user.""" + emoji_dict = defaultdict(list) + + if not ctx.guild.emojis: + await ctx.send("No emojis found.") + return + log.trace(f"Emoji Category {'' if category_query else 'not '}provided by the user") + for emoji in ctx.guild.emojis: + emoji_category = emoji.name.split("_")[0] + + if category_query is not None and emoji_category not in category_query: + continue + + emoji_dict[emoji_category].append(emoji) + + if not emoji_dict: + log.trace("Invalid name provided by the user") + embed, msg = self.generate_invalid_embed(ctx.guild.emojis) + else: + embed, msg = self.embed_builder(emoji_dict) + await LinePaginator.paginate(lines=msg, ctx=ctx, embed=embed) + + @emoji_group.command(name="info", aliases=("i",)) + async def info_command(self, ctx: commands.Context, emoji: Emoji) -> None: + """Returns relevant information about a Discord Emoji.""" + emoji_information = Embed( + title=f'Information about "{emoji.name}"', + description=textwrap.dedent(f""" + Name: {emoji.name} + Created: {time_since(emoji.created_at, precision="hours")} + ID: {emoji.id} + [Emoji source image]({emoji.url}) + """), + color=Color.blurple() + ) + emoji_information.set_thumbnail( + url=emoji.url + ) + await ctx.send(embed=emoji_information) + + +def setup(bot: commands.Bot) -> None: + """Add the Emoji cog into the bot.""" + bot.add_cog(Emoji(bot)) diff --git a/bot/exts/evergreen/emoji_count.py b/bot/exts/evergreen/emoji_count.py deleted file mode 100644 index cc43e9ab..00000000 --- a/bot/exts/evergreen/emoji_count.py +++ /dev/null @@ -1,97 +0,0 @@ -import datetime -import logging -import random -from collections import defaultdict -from typing import List, Tuple - -import discord -from discord.ext import commands - -from bot.constants import Colours, ERROR_REPLIES -from bot.utils.pagination import LinePaginator - -log = logging.getLogger(__name__) - - -class EmojiCount(commands.Cog): - """Command that give random emoji based on category.""" - - def __init__(self, bot: commands.Bot): - self.bot = bot - - @staticmethod - def embed_builder(emoji: dict) -> Tuple[discord.Embed, List[str]]: - """Generates an embed with the emoji names and count.""" - embed = discord.Embed( - color=Colours.orange, - title="Emoji Count", - timestamp=datetime.datetime.utcnow() - ) - msg = [] - - if len(emoji) == 1: - for category_name, category_emojis in emoji.items(): - if len(category_emojis) == 1: - msg.append(f"There is **{len(category_emojis)}** emoji in **{category_name}** category") - else: - msg.append(f"There are **{len(category_emojis)}** emojis in **{category_name}** category") - embed.set_thumbnail(url=random.choice(category_emojis).url) - - else: - for category_name, category_emojis in emoji.items(): - emoji_choice = random.choice(category_emojis) - if len(category_emojis) > 1: - emoji_info = f"There are **{len(category_emojis)}** emojis in **{category_name}** category" - else: - emoji_info = f"There is **{len(category_emojis)}** emoji in **{category_name}** category" - if emoji_choice.animated: - msg.append(f' {emoji_info}') - else: - msg.append(f'<:{emoji_choice.name}:{emoji_choice.id}> {emoji_info}') - return embed, msg - - @staticmethod - def generate_invalid_embed(emojis: list) -> Tuple[discord.Embed, List[str]]: - """Generates error embed.""" - embed = discord.Embed( - color=Colours.soft_red, - title=random.choice(ERROR_REPLIES) - ) - msg = [] - - emoji_dict = defaultdict(list) - for emoji in emojis: - emoji_dict[emoji.name.split("_")[0]].append(emoji) - - error_comp = ', '.join(emoji_dict) - msg.append(f"These are the valid categories\n```{error_comp}```") - return embed, msg - - @commands.command(name="emojicount", aliases=["ec", "emojis"]) - async def emoji_count(self, ctx: commands.Context, *, category_query: str = None) -> None: - """Returns embed with emoji category and info given by the user.""" - emoji_dict = defaultdict(list) - - if not ctx.guild.emojis: - await ctx.send("No emojis found.") - return - log.trace(f"Emoji Category {'' if category_query else 'not '}provided by the user") - for emoji in ctx.guild.emojis: - emoji_category = emoji.name.split("_")[0] - - if category_query is not None and emoji_category not in category_query: - continue - - emoji_dict[emoji_category].append(emoji) - - if not emoji_dict: - log.trace("Invalid name provided by the user") - embed, msg = self.generate_invalid_embed(ctx.guild.emojis) - else: - embed, msg = self.embed_builder(emoji_dict) - await LinePaginator.paginate(lines=msg, ctx=ctx, embed=embed) - - -def setup(bot: commands.Bot) -> None: - """Emoji Count Cog load.""" - bot.add_cog(EmojiCount(bot)) diff --git a/bot/exts/evergreen/emojis.py b/bot/exts/evergreen/emojis.py deleted file mode 100644 index 9f825e6d..00000000 --- a/bot/exts/evergreen/emojis.py +++ /dev/null @@ -1,39 +0,0 @@ -import textwrap - -from discord import Color, Embed, Emoji -from discord.ext import commands - -from bot.utils.time import time_since - - -class Emojis(commands.Cog): - """Has commands related to emojis.""" - - @commands.group(name="emoji", invoke_without_command=True) - async def emojis_group(self, ctx: commands.Context, emoji: Emoji) -> None: - """A group of commands related to emojis.""" - # No parameters = same as invoking info subcommand - await ctx.invoke(self.info_command, emoji) - - @emojis_group.command(name="info") - async def info_command(self, ctx: commands.Context, emoji: Emoji) -> None: - """Returns relevant information about a Discord Emoji.""" - emoji_information = Embed( - title=f'Information about "{emoji.name}"', - description=textwrap.dedent(f""" - Name: {emoji.name} - Created: {time_since(emoji.created_at, precision="hours")} - ID: {emoji.id} - [Emoji source image]({emoji.url}) - """), - color=Color.blurple() - ) - emoji_information.set_thumbnail( - url=emoji.url - ) - await ctx.send(embed=emoji_information) - - -def setup(bot: commands.Bot) -> None: - """Add the Emojis cog into the bot.""" - bot.add_cog(Emojis()) -- cgit v1.2.3 From af22fe556a3b1ab8a98245cc8f96e1d81d0f4289 Mon Sep 17 00:00:00 2001 From: kosayoda Date: Sun, 7 Mar 2021 11:49:58 +0800 Subject: Improve emoji information embed visuals. --- bot/exts/evergreen/emoji.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/emoji.py b/bot/exts/evergreen/emoji.py index a24d420c..8e5279f3 100644 --- a/bot/exts/evergreen/emoji.py +++ b/bot/exts/evergreen/emoji.py @@ -1,9 +1,9 @@ -import datetime import logging import random import textwrap from collections import defaultdict -from typing import List, Tuple +from datetime import datetime +from typing import List, Optional, Tuple from discord import Color, Embed, Emoji from discord.ext import commands @@ -27,7 +27,7 @@ class Emoji(commands.Cog): embed = Embed( color=Colours.orange, title="Emoji Count", - timestamp=datetime.datetime.utcnow() + timestamp=datetime.utcnow() ) msg = [] @@ -54,7 +54,7 @@ class Emoji(commands.Cog): @staticmethod def generate_invalid_embed(emojis: list) -> Tuple[Embed, List[str]]: - """Generates error embed.""" + """Generates error embed for invalid emoji categories.""" embed = Embed( color=Colours.soft_red, title=random.choice(ERROR_REPLIES) @@ -70,9 +70,12 @@ class Emoji(commands.Cog): return embed, msg @commands.group(name="emoji", invoke_without_command=True) - async def emoji_group(self, ctx: commands.Context) -> None: + async def emoji_group(self, ctx: commands.Context, emoji: Optional[Emoji]) -> None: """A group of commands related to emojis.""" - await ctx.send_help(ctx.command) + if emoji is not None: + await ctx.invoke(self.info_command, emoji) + else: + await ctx.send_help(ctx.command) @emoji_group.command(name="count", aliases=("c",)) async def count_command(self, ctx: commands.Context, *, category_query: str = None) -> None: @@ -102,18 +105,17 @@ class Emoji(commands.Cog): async def info_command(self, ctx: commands.Context, emoji: Emoji) -> None: """Returns relevant information about a Discord Emoji.""" emoji_information = Embed( - title=f'Information about "{emoji.name}"', + title=f"Emoji Information: {emoji.name}", description=textwrap.dedent(f""" - Name: {emoji.name} - Created: {time_since(emoji.created_at, precision="hours")} - ID: {emoji.id} - [Emoji source image]({emoji.url}) + **Name:** {emoji.name} + **Created:** {time_since(emoji.created_at, precision="hours")} + **Date:** {datetime.strftime(emoji.created_at, "%d/%m/%Y")} + **ID:** {emoji.id} """), - color=Color.blurple() - ) - emoji_information.set_thumbnail( - url=emoji.url - ) + color=Color.blurple(), + url=str(emoji.url), + ).set_thumbnail(url=emoji.url) + await ctx.send(embed=emoji_information) -- cgit v1.2.3 From 5c46abf4b88b4d45f672082c829b1ec6cec12296 Mon Sep 17 00:00:00 2001 From: kosayoda Date: Mon, 8 Mar 2021 16:44:21 +0800 Subject: Rename cog to avoid name conflict with discordpy. --- bot/exts/evergreen/emoji.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/emoji.py b/bot/exts/evergreen/emoji.py index 8e5279f3..e07b1505 100644 --- a/bot/exts/evergreen/emoji.py +++ b/bot/exts/evergreen/emoji.py @@ -15,7 +15,7 @@ from bot.utils.time import time_since log = logging.getLogger(__name__) -class Emoji(commands.Cog): +class Emojis(commands.Cog): """A collection of commands related to emojis in the server.""" def __init__(self, bot: commands.Bot): @@ -120,5 +120,5 @@ class Emoji(commands.Cog): def setup(bot: commands.Bot) -> None: - """Add the Emoji cog into the bot.""" - bot.add_cog(Emoji(bot)) + """Add the Emojis cog into the bot.""" + bot.add_cog(Emojis(bot)) -- cgit v1.2.3 From cfd59aed903c2ed2d57f4fc804bd978e07090ae1 Mon Sep 17 00:00:00 2001 From: kosayoda Date: Mon, 8 Mar 2021 16:51:27 +0800 Subject: Improve punctuation and wording of .emoji count. --- bot/exts/evergreen/emoji.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/emoji.py b/bot/exts/evergreen/emoji.py index e07b1505..99f71218 100644 --- a/bot/exts/evergreen/emoji.py +++ b/bot/exts/evergreen/emoji.py @@ -34,18 +34,18 @@ class Emojis(commands.Cog): if len(emoji) == 1: for category_name, category_emojis in emoji.items(): if len(category_emojis) == 1: - msg.append(f"There is **{len(category_emojis)}** emoji in **{category_name}** category") + msg.append(f"There is **{len(category_emojis)}** emoji in the **{category_name}** category.") else: - msg.append(f"There are **{len(category_emojis)}** emojis in **{category_name}** category") + msg.append(f"There are **{len(category_emojis)}** emojis in the **{category_name}** category.") embed.set_thumbnail(url=random.choice(category_emojis).url) else: for category_name, category_emojis in emoji.items(): emoji_choice = random.choice(category_emojis) if len(category_emojis) > 1: - emoji_info = f"There are **{len(category_emojis)}** emojis in **{category_name}** category" + emoji_info = f"There are **{len(category_emojis)}** emojis in the **{category_name}** category." else: - emoji_info = f"There is **{len(category_emojis)}** emoji in **{category_name}** category" + emoji_info = f"There is **{len(category_emojis)}** emoji in the **{category_name}** category." if emoji_choice.animated: msg.append(f' {emoji_info}') else: @@ -66,7 +66,7 @@ class Emojis(commands.Cog): emoji_dict[emoji.name.split("_")[0]].append(emoji) error_comp = ', '.join(emoji_dict) - msg.append(f"These are the valid categories\n```{error_comp}```") + msg.append(f"These are the valid emoji categories:\n```{error_comp}```") return embed, msg @commands.group(name="emoji", invoke_without_command=True) -- cgit v1.2.3 From 6c89267f2ce07a3a55dff933f5d76aba2a695f48 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 8 Mar 2021 19:33:41 +0100 Subject: Properly rename countdown_task -> notification_task The old name was still in use in the cog_unload, making it fail --- bot/exts/christmas/advent_of_code/_cog.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/christmas/advent_of_code/_cog.py b/bot/exts/christmas/advent_of_code/_cog.py index 466edd48..2203bf00 100644 --- a/bot/exts/christmas/advent_of_code/_cog.py +++ b/bot/exts/christmas/advent_of_code/_cog.py @@ -36,7 +36,7 @@ class AdventOfCode(commands.Cog): self.about_aoc_filepath = Path("./bot/resources/advent_of_code/about.json") self.cached_about_aoc = self._build_about_embed() - self.countdown_task = None + self.notification_task = None self.status_task = None notification_coro = _helpers.new_puzzle_notification(self.bot) @@ -268,7 +268,7 @@ class AdventOfCode(commands.Cog): def cog_unload(self) -> None: """Cancel season-related tasks on cog unload.""" log.debug("Unloading the cog and canceling the background task.") - self.countdown_task.cancel() + self.notification_task.cancel() self.status_task.cancel() def _build_about_embed(self) -> discord.Embed: -- cgit v1.2.3 From e6e12c3d3b8a9233cdd92c380c720aa461ab4565 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 8 Mar 2021 19:39:09 +0100 Subject: Restrict the aoc leaderboard commands to december --- bot/exts/christmas/advent_of_code/_cog.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'bot') diff --git a/bot/exts/christmas/advent_of_code/_cog.py b/bot/exts/christmas/advent_of_code/_cog.py index 2203bf00..c86ce18a 100644 --- a/bot/exts/christmas/advent_of_code/_cog.py +++ b/bot/exts/christmas/advent_of_code/_cog.py @@ -173,6 +173,7 @@ class AdventOfCode(commands.Cog): else: await ctx.message.add_reaction(Emojis.envelope) + @in_month(Month.DECEMBER) @adventofcode_group.command( name="leaderboard", aliases=("board", "lb"), @@ -198,6 +199,7 @@ class AdventOfCode(commands.Cog): await ctx.send(content=f"{header}\n\n{table}", embed=info_embed) + @in_month(Month.DECEMBER) @adventofcode_group.command( name="global", aliases=("globalboard", "gb"), -- cgit v1.2.3 From 8b0c1cd3b6729558218bd85aeb660d1975877345 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Tue, 9 Mar 2021 10:21:47 +0100 Subject: Remove useless initialization in the AoC cog --- bot/exts/christmas/advent_of_code/_cog.py | 3 --- 1 file changed, 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/christmas/advent_of_code/_cog.py b/bot/exts/christmas/advent_of_code/_cog.py index c86ce18a..29902306 100644 --- a/bot/exts/christmas/advent_of_code/_cog.py +++ b/bot/exts/christmas/advent_of_code/_cog.py @@ -36,9 +36,6 @@ class AdventOfCode(commands.Cog): self.about_aoc_filepath = Path("./bot/resources/advent_of_code/about.json") self.cached_about_aoc = self._build_about_embed() - self.notification_task = None - self.status_task = None - notification_coro = _helpers.new_puzzle_notification(self.bot) self.notification_task = self.bot.loop.create_task(notification_coro) self.notification_task.set_name("Daily AoC Notification") -- cgit v1.2.3 From ccfb8a7deea064b3b1e02d233d033cec20891eba Mon Sep 17 00:00:00 2001 From: Dillon Runke <44979306+Kronifer@users.noreply.github.com> Date: Tue, 9 Mar 2021 16:54:57 -0600 Subject: small style fix --- bot/exts/easter/earth_photos.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 60e34b15..58d7de61 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -46,10 +46,9 @@ class EarthPhotos(commands.Cog): ) embed.set_image(url=embedlink) embed.add_field( - name="Author", - value=f"Photo by [{username}]({profile}{rf}) \ - on [Unsplash](https://unsplash.com{rf})." - ) + value=f"Photo by [{username}]({profile}{rf}) " + f"on [Unsplash](https://unsplash.com{rf})." + ) await ctx.send(embed=embed) -- cgit v1.2.3 From abc41bde93fb51eeac6d7a80286fde184a665ba0 Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Tue, 9 Mar 2021 17:06:17 -0600 Subject: embed fix --- bot/exts/easter/earth_photos.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 58d7de61..89d37e11 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -46,9 +46,10 @@ class EarthPhotos(commands.Cog): ) embed.set_image(url=embedlink) embed.add_field( - value=f"Photo by [{username}]({profile}{rf}) " - f"on [Unsplash](https://unsplash.com{rf})." - ) + name="Author", + value=f"Photo by [{username}]({profile}{rf}) " + f"on [Unsplash](https://unsplash.com{rf})." + ) await ctx.send(embed=embed) -- cgit v1.2.3 From 3939fa7e065a0ccab7e4aa0ece866ec99c016139 Mon Sep 17 00:00:00 2001 From: Dillon Runke <44979306+Kronifer@users.noreply.github.com> Date: Wed, 10 Mar 2021 07:50:44 -0600 Subject: suggestion by @Xithrius Co-authored-by: Shivansh-007 <69356296+Shivansh-007@users.noreply.github.com> --- bot/exts/easter/earth_photos.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/earth_photos.py b/bot/exts/easter/earth_photos.py index 89d37e11..bf658391 100644 --- a/bot/exts/easter/earth_photos.py +++ b/bot/exts/easter/earth_photos.py @@ -47,8 +47,10 @@ class EarthPhotos(commands.Cog): embed.set_image(url=embedlink) embed.add_field( name="Author", - value=f"Photo by [{username}]({profile}{rf}) " - f"on [Unsplash](https://unsplash.com{rf})." + value=( + f"Photo by [{username}]({profile}{rf}) " + f"on [Unsplash](https://unsplash.com{rf})." + ) ) await ctx.send(embed=embed) -- cgit v1.2.3 From 11bf3700c10c29b27ddd14c5282b239bb6f1f191 Mon Sep 17 00:00:00 2001 From: JagTheFriend Date: Tue, 9 Mar 2021 22:03:55 +0200 Subject: Removed requesting to bots. Added grammer. --- bot/exts/evergreen/tic_tac_toe.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/tic_tac_toe.py b/bot/exts/evergreen/tic_tac_toe.py index e1190502..6e21528e 100644 --- a/bot/exts/evergreen/tic_tac_toe.py +++ b/bot/exts/evergreen/tic_tac_toe.py @@ -10,8 +10,8 @@ from bot.constants import Emojis from bot.utils.pagination import LinePaginator CONFIRMATION_MESSAGE = ( - "{opponent}, {requester} wants to play Tic-Tac-Toe against you. React to this message with " - f"{Emojis.confirmation} to accept or with {Emojis.decline} to decline." + "{opponent}, {requester} wants to play Tic-Tac-Toe against you." + f"\nReact to this message with {Emojis.confirmation} to accept or with {Emojis.decline} to decline." ) @@ -253,7 +253,7 @@ class TicTacToe(Cog): @guild_only() @is_channel_free() @is_requester_free() - @group(name="tictactoe", aliases=("ttt",), invoke_without_command=True) + @group(name="tictactoe", aliases=("ttt", "tic"), invoke_without_command=True) async def tic_tac_toe(self, ctx: Context, opponent: t.Optional[discord.User]) -> None: """Tic Tac Toe game. Play against friends or AI. Use reactions to add your mark to field.""" if opponent == ctx.author: @@ -276,6 +276,10 @@ class TicTacToe(Cog): ) self.games.append(game) if opponent is not None: + if opponent.bot: # check whether the opponent is a bot or not + await ctx.send("You can't play Tic-Tac-Toe with bots!") + return + confirmed, msg = await game.get_confirmation() if not confirmed: -- cgit v1.2.3 From 1cd9c7a4f74834d799bfc706f5f28cb4147fa0ff Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Thu, 11 Mar 2021 12:24:49 -0500 Subject: change ctx.send_help to ctx.invoke(help_command) ; --- bot/exts/christmas/advent_of_code/_cog.py | 3 ++- bot/exts/evergreen/emoji.py | 3 ++- bot/exts/evergreen/game.py | 3 ++- bot/exts/evergreen/minesweeper.py | 3 ++- bot/exts/evergreen/movie.py | 3 ++- bot/exts/evergreen/snakes/_snakes_cog.py | 3 ++- bot/exts/evergreen/space.py | 3 ++- bot/exts/evergreen/status_codes.py | 3 ++- bot/exts/utils/extensions.py | 12 ++++++++---- bot/exts/valentines/be_my_valentine.py | 3 ++- 10 files changed, 26 insertions(+), 13 deletions(-) (limited to 'bot') diff --git a/bot/exts/christmas/advent_of_code/_cog.py b/bot/exts/christmas/advent_of_code/_cog.py index 29902306..bf008ee9 100644 --- a/bot/exts/christmas/advent_of_code/_cog.py +++ b/bot/exts/christmas/advent_of_code/_cog.py @@ -51,7 +51,8 @@ class AdventOfCode(commands.Cog): async def adventofcode_group(self, ctx: commands.Context) -> None: """All of the Advent of Code commands.""" if not ctx.invoked_subcommand: - await ctx.send_help(ctx.command) + help_command = self.bot.get_command("help") + await ctx.invoke(help_command, ctx.command.name) @adventofcode_group.command( name="subscribe", diff --git a/bot/exts/evergreen/emoji.py b/bot/exts/evergreen/emoji.py index 99f71218..40bf83e8 100644 --- a/bot/exts/evergreen/emoji.py +++ b/bot/exts/evergreen/emoji.py @@ -75,7 +75,8 @@ class Emojis(commands.Cog): if emoji is not None: await ctx.invoke(self.info_command, emoji) else: - await ctx.send_help(ctx.command) + help_command = self.bot.get_command("help") + await ctx.invoke(help_command, ctx.command.name) @emoji_group.command(name="count", aliases=("c",)) async def count_command(self, ctx: commands.Context, *, category_query: str = None) -> None: diff --git a/bot/exts/evergreen/game.py b/bot/exts/evergreen/game.py index d37be0e2..d49a8858 100644 --- a/bot/exts/evergreen/game.py +++ b/bot/exts/evergreen/game.py @@ -234,7 +234,8 @@ class Games(Cog): """ # When user didn't specified genre, send help message if genre is None: - await ctx.send_help("games") + help_command = self.bot.get_command("help") + await ctx.invoke(help_command, ctx.command.name) return # Capitalize genre for check diff --git a/bot/exts/evergreen/minesweeper.py b/bot/exts/evergreen/minesweeper.py index 286ac7a5..06a75c2b 100644 --- a/bot/exts/evergreen/minesweeper.py +++ b/bot/exts/evergreen/minesweeper.py @@ -83,7 +83,8 @@ class Minesweeper(commands.Cog): @commands.group(name='minesweeper', aliases=('ms',), invoke_without_command=True) async def minesweeper_group(self, ctx: commands.Context) -> None: """Commands for Playing Minesweeper.""" - await ctx.send_help(ctx.command) + help_command = ctx.bot.get_command("help") + await ctx.invoke(help_command, ctx.command.name) @staticmethod def get_neighbours(x: int, y: int) -> typing.Generator[typing.Tuple[int, int], None, None]: diff --git a/bot/exts/evergreen/movie.py b/bot/exts/evergreen/movie.py index 340a5724..238ab038 100644 --- a/bot/exts/evergreen/movie.py +++ b/bot/exts/evergreen/movie.py @@ -73,7 +73,8 @@ class Movie(Cog): try: result = await self.get_movies_list(self.http_session, MovieGenres[genre].value, 1) except KeyError: - await ctx.send_help('movies') + help_command = self.bot.get_command("help") + await ctx.invoke(help_command, ctx.command.name) return # Check if "results" is in result. If not, throw error. diff --git a/bot/exts/evergreen/snakes/_snakes_cog.py b/bot/exts/evergreen/snakes/_snakes_cog.py index d5e4f206..819a98b2 100644 --- a/bot/exts/evergreen/snakes/_snakes_cog.py +++ b/bot/exts/evergreen/snakes/_snakes_cog.py @@ -440,7 +440,8 @@ class Snakes(Cog): @group(name='snakes', aliases=('snake',), invoke_without_command=True) async def snakes_group(self, ctx: Context) -> None: """Commands from our first code jam.""" - await ctx.send_help(ctx.command) + help_command = self.bot.get_command("help") + await ctx.invoke(help_command, ctx.command.name) @bot_has_permissions(manage_messages=True) @snakes_group.command(name='antidote') diff --git a/bot/exts/evergreen/space.py b/bot/exts/evergreen/space.py index bc8e3118..e388e13f 100644 --- a/bot/exts/evergreen/space.py +++ b/bot/exts/evergreen/space.py @@ -63,7 +63,8 @@ class Space(Cog): @group(name="space", invoke_without_command=True) async def space(self, ctx: Context) -> None: """Head command that contains commands about space.""" - await ctx.send_help("space") + help_command = self.bot.get_command("help") + await ctx.invoke(help_command, ctx.command.name) @space.command(name="apod") async def apod(self, ctx: Context, date: Optional[str] = None) -> None: diff --git a/bot/exts/evergreen/status_codes.py b/bot/exts/evergreen/status_codes.py index 874c87eb..d06724eb 100644 --- a/bot/exts/evergreen/status_codes.py +++ b/bot/exts/evergreen/status_codes.py @@ -17,7 +17,8 @@ class HTTPStatusCodes(commands.Cog): async def http_status_group(self, ctx: commands.Context) -> None: """Group containing dog and cat http status code commands.""" if not ctx.invoked_subcommand: - await ctx.send_help(ctx.command) + help_command = self.bot.get_command("help") + await ctx.invoke(help_command, ctx.command.name) @http_status_group.command(name='cat') async def http_cat(self, ctx: commands.Context, code: int) -> None: diff --git a/bot/exts/utils/extensions.py b/bot/exts/utils/extensions.py index bb22c353..f7ff2396 100644 --- a/bot/exts/utils/extensions.py +++ b/bot/exts/utils/extensions.py @@ -77,7 +77,8 @@ class Extensions(commands.Cog): @group(name="extensions", aliases=("ext", "exts", "c", "cogs"), invoke_without_command=True) async def extensions_group(self, ctx: Context) -> None: """Load, unload, reload, and list loaded extensions.""" - await ctx.send_help(ctx.command) + help_command = self.bot.get_command("help") + await ctx.invoke(help_command, ctx.command.name) @extensions_group.command(name="load", aliases=("l",)) async def load_command(self, ctx: Context, *extensions: Extension) -> None: @@ -87,7 +88,8 @@ class Extensions(commands.Cog): If '\*' or '\*\*' is given as the name, all unloaded extensions will be loaded. """ # noqa: W605 if not extensions: - await ctx.send_help(ctx.command) + help_command = self.bot.get_command("help") + await ctx.invoke(help_command, "extensions", ctx.command.name) return if "*" in extensions or "**" in extensions: @@ -104,7 +106,8 @@ class Extensions(commands.Cog): If '\*' or '\*\*' is given as the name, all loaded extensions will be unloaded. """ # noqa: W605 if not extensions: - await ctx.send_help(ctx.command) + help_command = self.bot.get_command("help") + await ctx.invoke(help_command, "extensions", ctx.command.name) return blacklisted = "\n".join(UNLOAD_BLACKLIST & set(extensions)) @@ -130,7 +133,8 @@ class Extensions(commands.Cog): If '\*\*' is given as the name, all extensions, including unloaded ones, will be reloaded. """ # noqa: W605 if not extensions: - await ctx.send_help(ctx.command) + help_command = self.bot.get_command("help") + await ctx.invoke(help_command, "extensions", ctx.command.name) return if "**" in extensions: diff --git a/bot/exts/valentines/be_my_valentine.py b/bot/exts/valentines/be_my_valentine.py index f3392bcb..59bd42d3 100644 --- a/bot/exts/valentines/be_my_valentine.py +++ b/bot/exts/valentines/be_my_valentine.py @@ -43,7 +43,8 @@ class BeMyValentine(commands.Cog): 2) use the command \".lovefest unsub\" to get rid of the lovefest role. """ if not ctx.invoked_subcommand: - await ctx.send_help(ctx.command) + help_command = self.bot.get_command("help") + await ctx.invoke(help_command, ctx.command.name) @lovefest_role.command(name="sub") async def add_role(self, ctx: commands.Context) -> None: -- cgit v1.2.3 From cc72d484115a8acebf0fafe8bb332817168d3acd Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Fri, 12 Mar 2021 19:17:39 -0500 Subject: make utility invoke_help_command function --- bot/exts/christmas/advent_of_code/_cog.py | 4 ++-- bot/exts/evergreen/emoji.py | 4 ++-- bot/exts/evergreen/game.py | 4 ++-- bot/exts/evergreen/minesweeper.py | 4 ++-- bot/exts/evergreen/movie.py | 4 ++-- bot/exts/evergreen/snakes/_snakes_cog.py | 4 ++-- bot/exts/evergreen/space.py | 4 ++-- bot/exts/evergreen/status_codes.py | 4 ++-- bot/exts/utils/extensions.py | 14 +++++--------- bot/exts/valentines/be_my_valentine.py | 4 ++-- bot/utils/extensions.py | 12 ++++++++++++ 11 files changed, 35 insertions(+), 27 deletions(-) (limited to 'bot') diff --git a/bot/exts/christmas/advent_of_code/_cog.py b/bot/exts/christmas/advent_of_code/_cog.py index bf008ee9..6ba5c2af 100644 --- a/bot/exts/christmas/advent_of_code/_cog.py +++ b/bot/exts/christmas/advent_of_code/_cog.py @@ -12,6 +12,7 @@ from bot.constants import ( ) from bot.exts.christmas.advent_of_code import _helpers from bot.utils.decorators import InChannelCheckFailure, in_month, whitelist_override, with_role +from bot.utils.extensions import invoke_help_command log = logging.getLogger(__name__) @@ -51,8 +52,7 @@ class AdventOfCode(commands.Cog): async def adventofcode_group(self, ctx: commands.Context) -> None: """All of the Advent of Code commands.""" if not ctx.invoked_subcommand: - help_command = self.bot.get_command("help") - await ctx.invoke(help_command, ctx.command.name) + await invoke_help_command(ctx, ctx.command.name) @adventofcode_group.command( name="subscribe", diff --git a/bot/exts/evergreen/emoji.py b/bot/exts/evergreen/emoji.py index 40bf83e8..042e539d 100644 --- a/bot/exts/evergreen/emoji.py +++ b/bot/exts/evergreen/emoji.py @@ -11,6 +11,7 @@ from discord.ext import commands from bot.constants import Colours, ERROR_REPLIES from bot.utils.pagination import LinePaginator from bot.utils.time import time_since +from bot.utils.extensions import invoke_help_command log = logging.getLogger(__name__) @@ -75,8 +76,7 @@ class Emojis(commands.Cog): if emoji is not None: await ctx.invoke(self.info_command, emoji) else: - help_command = self.bot.get_command("help") - await ctx.invoke(help_command, ctx.command.name) + await invoke_help_command(ctx, ctx.command.name) @emoji_group.command(name="count", aliases=("c",)) async def count_command(self, ctx: commands.Context, *, category_query: str = None) -> None: diff --git a/bot/exts/evergreen/game.py b/bot/exts/evergreen/game.py index d49a8858..ab4cae77 100644 --- a/bot/exts/evergreen/game.py +++ b/bot/exts/evergreen/game.py @@ -16,6 +16,7 @@ from bot.bot import Bot from bot.constants import STAFF_ROLES, Tokens from bot.utils.decorators import with_role from bot.utils.pagination import ImagePaginator, LinePaginator +from bot.utils.extensions import invoke_help_command # Base URL of IGDB API BASE_URL = "https://api.igdb.com/v4" @@ -234,8 +235,7 @@ class Games(Cog): """ # When user didn't specified genre, send help message if genre is None: - help_command = self.bot.get_command("help") - await ctx.invoke(help_command, ctx.command.name) + await invoke_help_command(ctx, ctx.command.name) return # Capitalize genre for check diff --git a/bot/exts/evergreen/minesweeper.py b/bot/exts/evergreen/minesweeper.py index 06a75c2b..cfe7150e 100644 --- a/bot/exts/evergreen/minesweeper.py +++ b/bot/exts/evergreen/minesweeper.py @@ -8,6 +8,7 @@ from discord.ext import commands from bot.constants import Client from bot.utils.exceptions import UserNotPlayingError +from bot.utils.extensions import invoke_help_command MESSAGE_MAPPING = { 0: ":stop_button:", @@ -83,8 +84,7 @@ class Minesweeper(commands.Cog): @commands.group(name='minesweeper', aliases=('ms',), invoke_without_command=True) async def minesweeper_group(self, ctx: commands.Context) -> None: """Commands for Playing Minesweeper.""" - help_command = ctx.bot.get_command("help") - await ctx.invoke(help_command, ctx.command.name) + await invoke_help_command(ctx, ctx.command.name) @staticmethod def get_neighbours(x: int, y: int) -> typing.Generator[typing.Tuple[int, int], None, None]: diff --git a/bot/exts/evergreen/movie.py b/bot/exts/evergreen/movie.py index 238ab038..9aa3aea7 100644 --- a/bot/exts/evergreen/movie.py +++ b/bot/exts/evergreen/movie.py @@ -10,6 +10,7 @@ from discord.ext.commands import Bot, Cog, Context, group from bot.constants import Tokens from bot.utils.pagination import ImagePaginator +from bot.utils.extensions import invoke_help_command # Define base URL of TMDB BASE_URL = "https://api.themoviedb.org/3/" @@ -73,8 +74,7 @@ class Movie(Cog): try: result = await self.get_movies_list(self.http_session, MovieGenres[genre].value, 1) except KeyError: - help_command = self.bot.get_command("help") - await ctx.invoke(help_command, ctx.command.name) + await invoke_help_command(ctx, ctx.command.name) return # Check if "results" is in result. If not, throw error. diff --git a/bot/exts/evergreen/snakes/_snakes_cog.py b/bot/exts/evergreen/snakes/_snakes_cog.py index 819a98b2..d0e60819 100644 --- a/bot/exts/evergreen/snakes/_snakes_cog.py +++ b/bot/exts/evergreen/snakes/_snakes_cog.py @@ -22,6 +22,7 @@ from bot.constants import ERROR_REPLIES, Tokens from bot.exts.evergreen.snakes import _utils as utils from bot.exts.evergreen.snakes._converter import Snake from bot.utils.decorators import locked +from bot.utils.extensions import invoke_help_command log = logging.getLogger(__name__) @@ -440,8 +441,7 @@ class Snakes(Cog): @group(name='snakes', aliases=('snake',), invoke_without_command=True) async def snakes_group(self, ctx: Context) -> None: """Commands from our first code jam.""" - help_command = self.bot.get_command("help") - await ctx.invoke(help_command, ctx.command.name) + await invoke_help_command(ctx, ctx.command.name) @bot_has_permissions(manage_messages=True) @snakes_group.command(name='antidote') diff --git a/bot/exts/evergreen/space.py b/bot/exts/evergreen/space.py index e388e13f..305d6721 100644 --- a/bot/exts/evergreen/space.py +++ b/bot/exts/evergreen/space.py @@ -10,6 +10,7 @@ from discord.ext.commands import BadArgument, Cog, Context, Converter, group from bot.bot import Bot from bot.constants import Tokens +from bot.utils.extensions import invoke_help_command logger = logging.getLogger(__name__) @@ -63,8 +64,7 @@ class Space(Cog): @group(name="space", invoke_without_command=True) async def space(self, ctx: Context) -> None: """Head command that contains commands about space.""" - help_command = self.bot.get_command("help") - await ctx.invoke(help_command, ctx.command.name) + await invoke_help_command(ctx, ctx.command.name) @space.command(name="apod") async def apod(self, ctx: Context, date: Optional[str] = None) -> None: diff --git a/bot/exts/evergreen/status_codes.py b/bot/exts/evergreen/status_codes.py index d06724eb..a037e117 100644 --- a/bot/exts/evergreen/status_codes.py +++ b/bot/exts/evergreen/status_codes.py @@ -2,6 +2,7 @@ from http import HTTPStatus import discord from discord.ext import commands +from bot.utils.extensions import invoke_help_command HTTP_DOG_URL = "https://httpstatusdogs.com/img/{code}.jpg" HTTP_CAT_URL = "https://http.cat/{code}.jpg" @@ -17,8 +18,7 @@ class HTTPStatusCodes(commands.Cog): async def http_status_group(self, ctx: commands.Context) -> None: """Group containing dog and cat http status code commands.""" if not ctx.invoked_subcommand: - help_command = self.bot.get_command("help") - await ctx.invoke(help_command, ctx.command.name) + await invoke_help_command(ctx, ctx.command.name) @http_status_group.command(name='cat') async def http_cat(self, ctx: commands.Context, code: int) -> None: diff --git a/bot/exts/utils/extensions.py b/bot/exts/utils/extensions.py index f7ff2396..9c126a7b 100644 --- a/bot/exts/utils/extensions.py +++ b/bot/exts/utils/extensions.py @@ -11,7 +11,7 @@ from bot import exts from bot.bot import Bot from bot.constants import Client, Emojis, MODERATION_ROLES, Roles from bot.utils.checks import with_role_check -from bot.utils.extensions import EXTENSIONS, unqualify +from bot.utils.extensions import EXTENSIONS, unqualify, invoke_help_command from bot.utils.pagination import LinePaginator log = logging.getLogger(__name__) @@ -77,8 +77,7 @@ class Extensions(commands.Cog): @group(name="extensions", aliases=("ext", "exts", "c", "cogs"), invoke_without_command=True) async def extensions_group(self, ctx: Context) -> None: """Load, unload, reload, and list loaded extensions.""" - help_command = self.bot.get_command("help") - await ctx.invoke(help_command, ctx.command.name) + await invoke_help_command(ctx, ctx.command.name) @extensions_group.command(name="load", aliases=("l",)) async def load_command(self, ctx: Context, *extensions: Extension) -> None: @@ -88,8 +87,7 @@ class Extensions(commands.Cog): If '\*' or '\*\*' is given as the name, all unloaded extensions will be loaded. """ # noqa: W605 if not extensions: - help_command = self.bot.get_command("help") - await ctx.invoke(help_command, "extensions", ctx.command.name) + await invoke_help_command(ctx, "extensions", ctx.command.name) return if "*" in extensions or "**" in extensions: @@ -106,8 +104,7 @@ class Extensions(commands.Cog): If '\*' or '\*\*' is given as the name, all loaded extensions will be unloaded. """ # noqa: W605 if not extensions: - help_command = self.bot.get_command("help") - await ctx.invoke(help_command, "extensions", ctx.command.name) + await invoke_help_command(ctx, "extensions", ctx.command.name) return blacklisted = "\n".join(UNLOAD_BLACKLIST & set(extensions)) @@ -133,8 +130,7 @@ class Extensions(commands.Cog): If '\*\*' is given as the name, all extensions, including unloaded ones, will be reloaded. """ # noqa: W605 if not extensions: - help_command = self.bot.get_command("help") - await ctx.invoke(help_command, "extensions", ctx.command.name) + await invoke_help_command(ctx, "extensions", ctx.command.name) return if "**" in extensions: diff --git a/bot/exts/valentines/be_my_valentine.py b/bot/exts/valentines/be_my_valentine.py index 59bd42d3..d5cc8644 100644 --- a/bot/exts/valentines/be_my_valentine.py +++ b/bot/exts/valentines/be_my_valentine.py @@ -10,6 +10,7 @@ from discord.ext.commands.cooldowns import BucketType from bot.constants import Channels, Colours, Lovefest, Month from bot.utils.decorators import in_month +from bot.utils.extensions import invoke_help_command log = logging.getLogger(__name__) @@ -43,8 +44,7 @@ class BeMyValentine(commands.Cog): 2) use the command \".lovefest unsub\" to get rid of the lovefest role. """ if not ctx.invoked_subcommand: - help_command = self.bot.get_command("help") - await ctx.invoke(help_command, ctx.command.name) + await invoke_help_command(ctx, ctx.command.name) @lovefest_role.command(name="sub") async def add_role(self, ctx: commands.Context) -> None: diff --git a/bot/utils/extensions.py b/bot/utils/extensions.py index 50350ea8..56f6dd00 100644 --- a/bot/utils/extensions.py +++ b/bot/utils/extensions.py @@ -4,6 +4,7 @@ import pkgutil from typing import Iterator, NoReturn from bot import exts +from discord.ext.commands import Context def unqualify(name: str) -> str: @@ -31,4 +32,15 @@ def walk_extensions() -> Iterator[str]: yield module.name +async def invoke_help_command(ctx: Context, *commands: str) -> None: + """Invoke the help command, and will use the default help command + if the help exten is not loaded. + """ + + if 'bot.exts.evergreen.help' in ctx.bot.extensions: + help_command = ctx.bot.get_command('help') + await ctx.invoke(help_command, *commands) + return + await ctx.send_help(''.join(commands)) + EXTENSIONS = frozenset(walk_extensions()) -- cgit v1.2.3 From ccf7d118eb2dea996b10bf0a4cfca977c452f636 Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Fri, 12 Mar 2021 20:01:24 -0500 Subject: Make flake8 happy. --- bot/exts/evergreen/game.py | 2 +- bot/exts/evergreen/status_codes.py | 1 + bot/exts/utils/extensions.py | 2 +- bot/utils/extensions.py | 7 ++----- 4 files changed, 5 insertions(+), 7 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/game.py b/bot/exts/evergreen/game.py index ab4cae77..a6bfecaa 100644 --- a/bot/exts/evergreen/game.py +++ b/bot/exts/evergreen/game.py @@ -15,8 +15,8 @@ from discord.ext.commands import Cog, Context, group from bot.bot import Bot from bot.constants import STAFF_ROLES, Tokens from bot.utils.decorators import with_role -from bot.utils.pagination import ImagePaginator, LinePaginator from bot.utils.extensions import invoke_help_command +from bot.utils.pagination import ImagePaginator, LinePaginator # Base URL of IGDB API BASE_URL = "https://api.igdb.com/v4" diff --git a/bot/exts/evergreen/status_codes.py b/bot/exts/evergreen/status_codes.py index a037e117..127f3424 100644 --- a/bot/exts/evergreen/status_codes.py +++ b/bot/exts/evergreen/status_codes.py @@ -2,6 +2,7 @@ from http import HTTPStatus import discord from discord.ext import commands + from bot.utils.extensions import invoke_help_command HTTP_DOG_URL = "https://httpstatusdogs.com/img/{code}.jpg" diff --git a/bot/exts/utils/extensions.py b/bot/exts/utils/extensions.py index 9c126a7b..4bd606b0 100644 --- a/bot/exts/utils/extensions.py +++ b/bot/exts/utils/extensions.py @@ -11,7 +11,7 @@ from bot import exts from bot.bot import Bot from bot.constants import Client, Emojis, MODERATION_ROLES, Roles from bot.utils.checks import with_role_check -from bot.utils.extensions import EXTENSIONS, unqualify, invoke_help_command +from bot.utils.extensions import EXTENSIONS, invoke_help_command, unqualify from bot.utils.pagination import LinePaginator log = logging.getLogger(__name__) diff --git a/bot/utils/extensions.py b/bot/utils/extensions.py index 56f6dd00..afc57383 100644 --- a/bot/utils/extensions.py +++ b/bot/utils/extensions.py @@ -1,10 +1,10 @@ +from discord.ext.commands import Context import importlib import inspect import pkgutil from typing import Iterator, NoReturn from bot import exts -from discord.ext.commands import Context def unqualify(name: str) -> str: @@ -33,10 +33,7 @@ def walk_extensions() -> Iterator[str]: async def invoke_help_command(ctx: Context, *commands: str) -> None: - """Invoke the help command, and will use the default help command - if the help exten is not loaded. - """ - + """Invoke the help command or default help command if help extensions is not loaded.""" if 'bot.exts.evergreen.help' in ctx.bot.extensions: help_command = ctx.bot.get_command('help') await ctx.invoke(help_command, *commands) -- cgit v1.2.3 From b395c05cc0885c427afab80e914d098dd9edc742 Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Fri, 12 Mar 2021 20:06:56 -0500 Subject: Make flake8 happy again. --- bot/exts/evergreen/emoji.py | 2 +- bot/exts/evergreen/movie.py | 2 +- bot/utils/extensions.py | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/emoji.py b/bot/exts/evergreen/emoji.py index 042e539d..e55a11ad 100644 --- a/bot/exts/evergreen/emoji.py +++ b/bot/exts/evergreen/emoji.py @@ -9,9 +9,9 @@ from discord import Color, Embed, Emoji from discord.ext import commands from bot.constants import Colours, ERROR_REPLIES +from bot.utils.extensions import invoke_help_command from bot.utils.pagination import LinePaginator from bot.utils.time import time_since -from bot.utils.extensions import invoke_help_command log = logging.getLogger(__name__) diff --git a/bot/exts/evergreen/movie.py b/bot/exts/evergreen/movie.py index 9aa3aea7..63ce81da 100644 --- a/bot/exts/evergreen/movie.py +++ b/bot/exts/evergreen/movie.py @@ -9,8 +9,8 @@ from discord import Embed from discord.ext.commands import Bot, Cog, Context, group from bot.constants import Tokens -from bot.utils.pagination import ImagePaginator from bot.utils.extensions import invoke_help_command +from bot.utils.pagination import ImagePaginator # Define base URL of TMDB BASE_URL = "https://api.themoviedb.org/3/" diff --git a/bot/utils/extensions.py b/bot/utils/extensions.py index afc57383..ffa8a936 100644 --- a/bot/utils/extensions.py +++ b/bot/utils/extensions.py @@ -1,9 +1,10 @@ -from discord.ext.commands import Context import importlib import inspect import pkgutil from typing import Iterator, NoReturn +from discord.ext.commands import Context + from bot import exts -- cgit v1.2.3 From 9ec1cf9b983a69c381507f82c317e0465eecdc35 Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Sat, 13 Mar 2021 10:16:31 -0500 Subject: make invoke_help_command only take ctx --- bot/exts/christmas/advent_of_code/_cog.py | 2 +- bot/exts/evergreen/emoji.py | 2 +- bot/exts/evergreen/game.py | 2 +- bot/exts/evergreen/minesweeper.py | 2 +- bot/exts/evergreen/movie.py | 2 +- bot/exts/evergreen/snakes/_snakes_cog.py | 2 +- bot/exts/evergreen/space.py | 2 +- bot/exts/evergreen/status_codes.py | 2 +- bot/exts/utils/extensions.py | 8 ++++---- bot/exts/valentines/be_my_valentine.py | 2 +- bot/utils/extensions.py | 6 +++--- 11 files changed, 16 insertions(+), 16 deletions(-) (limited to 'bot') diff --git a/bot/exts/christmas/advent_of_code/_cog.py b/bot/exts/christmas/advent_of_code/_cog.py index 6ba5c2af..dc3d7616 100644 --- a/bot/exts/christmas/advent_of_code/_cog.py +++ b/bot/exts/christmas/advent_of_code/_cog.py @@ -52,7 +52,7 @@ class AdventOfCode(commands.Cog): async def adventofcode_group(self, ctx: commands.Context) -> None: """All of the Advent of Code commands.""" if not ctx.invoked_subcommand: - await invoke_help_command(ctx, ctx.command.name) + await invoke_help_command(ctx) @adventofcode_group.command( name="subscribe", diff --git a/bot/exts/evergreen/emoji.py b/bot/exts/evergreen/emoji.py index e55a11ad..fa3044e3 100644 --- a/bot/exts/evergreen/emoji.py +++ b/bot/exts/evergreen/emoji.py @@ -76,7 +76,7 @@ class Emojis(commands.Cog): if emoji is not None: await ctx.invoke(self.info_command, emoji) else: - await invoke_help_command(ctx, ctx.command.name) + await invoke_help_command(ctx) @emoji_group.command(name="count", aliases=("c",)) async def count_command(self, ctx: commands.Context, *, category_query: str = None) -> None: diff --git a/bot/exts/evergreen/game.py b/bot/exts/evergreen/game.py index a6bfecaa..068d3f68 100644 --- a/bot/exts/evergreen/game.py +++ b/bot/exts/evergreen/game.py @@ -235,7 +235,7 @@ class Games(Cog): """ # When user didn't specified genre, send help message if genre is None: - await invoke_help_command(ctx, ctx.command.name) + await invoke_help_command(ctx) return # Capitalize genre for check diff --git a/bot/exts/evergreen/minesweeper.py b/bot/exts/evergreen/minesweeper.py index cfe7150e..3031debc 100644 --- a/bot/exts/evergreen/minesweeper.py +++ b/bot/exts/evergreen/minesweeper.py @@ -84,7 +84,7 @@ class Minesweeper(commands.Cog): @commands.group(name='minesweeper', aliases=('ms',), invoke_without_command=True) async def minesweeper_group(self, ctx: commands.Context) -> None: """Commands for Playing Minesweeper.""" - await invoke_help_command(ctx, ctx.command.name) + await invoke_help_command(ctx) @staticmethod def get_neighbours(x: int, y: int) -> typing.Generator[typing.Tuple[int, int], None, None]: diff --git a/bot/exts/evergreen/movie.py b/bot/exts/evergreen/movie.py index 63ce81da..b3bfe998 100644 --- a/bot/exts/evergreen/movie.py +++ b/bot/exts/evergreen/movie.py @@ -74,7 +74,7 @@ class Movie(Cog): try: result = await self.get_movies_list(self.http_session, MovieGenres[genre].value, 1) except KeyError: - await invoke_help_command(ctx, ctx.command.name) + await invoke_help_command(ctx) return # Check if "results" is in result. If not, throw error. diff --git a/bot/exts/evergreen/snakes/_snakes_cog.py b/bot/exts/evergreen/snakes/_snakes_cog.py index d0e60819..3732b559 100644 --- a/bot/exts/evergreen/snakes/_snakes_cog.py +++ b/bot/exts/evergreen/snakes/_snakes_cog.py @@ -441,7 +441,7 @@ class Snakes(Cog): @group(name='snakes', aliases=('snake',), invoke_without_command=True) async def snakes_group(self, ctx: Context) -> None: """Commands from our first code jam.""" - await invoke_help_command(ctx, ctx.command.name) + await invoke_help_command(ctx) @bot_has_permissions(manage_messages=True) @snakes_group.command(name='antidote') diff --git a/bot/exts/evergreen/space.py b/bot/exts/evergreen/space.py index 305d6721..323ff659 100644 --- a/bot/exts/evergreen/space.py +++ b/bot/exts/evergreen/space.py @@ -64,7 +64,7 @@ class Space(Cog): @group(name="space", invoke_without_command=True) async def space(self, ctx: Context) -> None: """Head command that contains commands about space.""" - await invoke_help_command(ctx, ctx.command.name) + await invoke_help_command(ctx) @space.command(name="apod") async def apod(self, ctx: Context, date: Optional[str] = None) -> None: diff --git a/bot/exts/evergreen/status_codes.py b/bot/exts/evergreen/status_codes.py index 127f3424..7c00fe20 100644 --- a/bot/exts/evergreen/status_codes.py +++ b/bot/exts/evergreen/status_codes.py @@ -19,7 +19,7 @@ class HTTPStatusCodes(commands.Cog): async def http_status_group(self, ctx: commands.Context) -> None: """Group containing dog and cat http status code commands.""" if not ctx.invoked_subcommand: - await invoke_help_command(ctx, ctx.command.name) + await invoke_help_command(ctx) @http_status_group.command(name='cat') async def http_cat(self, ctx: commands.Context, code: int) -> None: diff --git a/bot/exts/utils/extensions.py b/bot/exts/utils/extensions.py index 4bd606b0..64e404d2 100644 --- a/bot/exts/utils/extensions.py +++ b/bot/exts/utils/extensions.py @@ -77,7 +77,7 @@ class Extensions(commands.Cog): @group(name="extensions", aliases=("ext", "exts", "c", "cogs"), invoke_without_command=True) async def extensions_group(self, ctx: Context) -> None: """Load, unload, reload, and list loaded extensions.""" - await invoke_help_command(ctx, ctx.command.name) + await invoke_help_command(ctx) @extensions_group.command(name="load", aliases=("l",)) async def load_command(self, ctx: Context, *extensions: Extension) -> None: @@ -87,7 +87,7 @@ class Extensions(commands.Cog): If '\*' or '\*\*' is given as the name, all unloaded extensions will be loaded. """ # noqa: W605 if not extensions: - await invoke_help_command(ctx, "extensions", ctx.command.name) + await invoke_help_command(ctx) return if "*" in extensions or "**" in extensions: @@ -104,7 +104,7 @@ class Extensions(commands.Cog): If '\*' or '\*\*' is given as the name, all loaded extensions will be unloaded. """ # noqa: W605 if not extensions: - await invoke_help_command(ctx, "extensions", ctx.command.name) + await invoke_help_command(ctx) return blacklisted = "\n".join(UNLOAD_BLACKLIST & set(extensions)) @@ -130,7 +130,7 @@ class Extensions(commands.Cog): If '\*\*' is given as the name, all extensions, including unloaded ones, will be reloaded. """ # noqa: W605 if not extensions: - await invoke_help_command(ctx, "extensions", ctx.command.name) + await invoke_help_command(ctx) return if "**" in extensions: diff --git a/bot/exts/valentines/be_my_valentine.py b/bot/exts/valentines/be_my_valentine.py index d5cc8644..09591cf8 100644 --- a/bot/exts/valentines/be_my_valentine.py +++ b/bot/exts/valentines/be_my_valentine.py @@ -44,7 +44,7 @@ class BeMyValentine(commands.Cog): 2) use the command \".lovefest unsub\" to get rid of the lovefest role. """ if not ctx.invoked_subcommand: - await invoke_help_command(ctx, ctx.command.name) + await invoke_help_command(ctx) @lovefest_role.command(name="sub") async def add_role(self, ctx: commands.Context) -> None: diff --git a/bot/utils/extensions.py b/bot/utils/extensions.py index ffa8a936..459588a1 100644 --- a/bot/utils/extensions.py +++ b/bot/utils/extensions.py @@ -33,12 +33,12 @@ def walk_extensions() -> Iterator[str]: yield module.name -async def invoke_help_command(ctx: Context, *commands: str) -> None: +async def invoke_help_command(ctx: Context) -> None: """Invoke the help command or default help command if help extensions is not loaded.""" if 'bot.exts.evergreen.help' in ctx.bot.extensions: help_command = ctx.bot.get_command('help') - await ctx.invoke(help_command, *commands) + await ctx.invoke(help_command, ctx.command.qualified_name) return - await ctx.send_help(''.join(commands)) + await ctx.send_help(ctx.command) EXTENSIONS = frozenset(walk_extensions()) -- cgit v1.2.3 From 87219f3a0c299d62a95341a90237715f1cff64d8 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Sat, 13 Mar 2021 20:13:12 +0000 Subject: master => main --- .github/workflows/build.yaml | 2 +- .github/workflows/lint.yaml | 2 +- .github/workflows/sentry_release.yaml | 4 ++-- CONTRIBUTING.md | 8 ++++---- README.md | 10 +++++----- bot/exts/christmas/advent_of_code/_helpers.py | 2 +- bot/exts/evergreen/source.py | 2 +- bot/resources/halloween/spooky_rating.json | 18 +++++++++--------- bot/utils/time.py | 2 +- 9 files changed, 25 insertions(+), 25 deletions(-) (limited to 'bot') diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 9d12cd10..08721dfd 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -4,7 +4,7 @@ on: workflow_run: workflows: ["Lint"] branches: - - master + - main types: - completed diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index a5f45255..7f157da3 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -3,7 +3,7 @@ name: Lint on: push: branches: - - master + - main pull_request: diff --git a/.github/workflows/sentry_release.yaml b/.github/workflows/sentry_release.yaml index 0e02dd0c..3d15e01e 100644 --- a/.github/workflows/sentry_release.yaml +++ b/.github/workflows/sentry_release.yaml @@ -3,14 +3,14 @@ name: Create Sentry release on: push: branches: - - master + - main jobs: create_sentry_release: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@master + uses: actions/checkout@main - name: Create a Sentry.io release uses: tclindner/sentry-releases-action@v1.2.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7cf83db5..3a1803e2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ Sir Lancebot is a community project for the Python Discord community over at https://discord.gg/python. We will be providing support for those of you who are new to Git, and this project is to be considered educational. -Our projects are open-source and are automatically deployed whenever commits are pushed to the `master` branch on each repository, so we've created a set of guidelines in order to keep everything clean and in working order. +Our projects are open-source and are automatically deployed whenever commits are pushed to the `main` branch on each repository, so we've created a set of guidelines in order to keep everything clean and in working order. Note that contributions may be rejected on the basis of a contributor failing to follow these guidelines. @@ -12,7 +12,7 @@ Note that contributions may be rejected on the basis of a contributor failing to 2. Your pull request must solve an issue created or approved by a staff member. These will be labeled with the `approved` label. Feel free to suggest issues of your own, which staff can review for approval. 3. **No force-pushes** or modifying the Git history in any way. 4. If you have direct access to the repository, **create a branch for your changes** and create a pull request for that branch. If not, create a branch on a fork of the repository and create a pull request from there. - * It's common practice for a repository to reject direct pushes to `master`, so make branching a habit! + * It's common practice for a repository to reject direct pushes to `main`, so make branching a habit! * If PRing from your own fork, **ensure that "Allow edits from maintainers" is checked**. This gives permission for maintainers to commit changes directly to your fork, speeding up the review process. 5. **Adhere to the prevailing code style**, which we enforce using [`flake8`](http://flake8.pycqa.org/en/latest/index.html) and [`pre-commit`](https://pre-commit.com/). * Run `flake8` and `pre-commit` against your code [**before** you push it](https://soundcloud.com/lemonsaurusrex/lint-before-you-push). Your commit will be rejected by the build server if it fails to lint. @@ -22,7 +22,7 @@ Note that contributions may be rejected on the basis of a contributor failing to * Avoid making minor commits for fixing typos or linting errors. Since you've already set up a `pre-commit` hook to run the linting pipeline before a commit, you shouldn't be committing linting issues anyway. * A more in-depth guide to writing great commit messages can be found in Chris Beam's [*How to Write a Git Commit Message*](https://chris.beams.io/posts/git-commit/) 7. **Avoid frequent pushes to the main repository**. This goes for PRs opened against your fork as well. Our test build pipelines are triggered every time a push to the repository (or PR) is made. Try to batch your commits until you've finished working for that session, or you've reached a point where collaborators need your commits to continue their own work. This also provides you the opportunity to amend commits for minor changes rather than having to commit them on their own because you've already pushed. - * This includes merging master into your branch. Try to leave merging from master for after your PR passes review; a maintainer will bring your PR up to date before merging. Exceptions to this include: resolving merge conflicts, needing something that was pushed to master for your branch, or something was pushed to master that could potentionally affect the functionality of what you're writing. + * This includes merging main into your branch. Try to leave merging from main for after your PR passes review; a maintainer will bring your PR up to date before merging. Exceptions to this include: resolving merge conflicts, needing something that was pushed to main for your branch, or something was pushed to main that could potentionally affect the functionality of what you're writing. 8. **Don't fight the framework**. Every framework has its flaws, but the frameworks we've picked out have been carefully chosen for their particular merits. If you can avoid it, please resist reimplementing swathes of framework logic - the work has already been done for you! 9. If someone is working on an issue or pull request, **do not open your own pull request for the same task**. Instead, collaborate with the author(s) of the existing pull request. Duplicate PRs opened without communicating with the other author(s) and/or PyDis staff will be closed. Communication is key, and there's no point in two separate implementations of the same thing. * One option is to fork the other contributor's repository and submit your changes to their branch with your own pull request. We suggest following these guidelines when interacting with their repository as well. @@ -39,7 +39,7 @@ All projects evolve over time, and this contribution guide is no different. This ## Supplemental Information ### Developer Environment -Sir Lancebot utilizes [Pipenv](https://pipenv.readthedocs.io/en/latest/) for installation and dependency management. For users unfamiliar with the Pipenv workflow, Pipenv's documentation provides a [Basic Usage](https://pipenv.readthedocs.io/en/latest/basics/) tutorial, along with some of the more advanced workflows. A project-specific installation guide can be found in [Sir Lancebot's README](https://github.com/python-discord/sir-lancebot/blob/master/README.md). +Sir Lancebot utilizes [Pipenv](https://pipenv.readthedocs.io/en/latest/) for installation and dependency management. For users unfamiliar with the Pipenv workflow, Pipenv's documentation provides a [Basic Usage](https://pipenv.readthedocs.io/en/latest/basics/) tutorial, along with some of the more advanced workflows. A project-specific installation guide can be found in [Sir Lancebot's README](https://github.com/python-discord/sir-lancebot/blob/main/README.md). When pulling down changes from GitHub, remember to sync your environment using `pipenv sync --dev` to ensure you're using the most up-to-date versions the project's dependencies. diff --git a/README.md b/README.md index 6b453879..11b46aac 100755 --- a/README.md +++ b/README.md @@ -22,9 +22,9 @@ Before you start, please take some time to read through our [contributing guidel See [Sir Lancebot's Wiki](https://pythondiscord.com/pages/contributing/sir-lancebot/) for in-depth guides on getting started with the project! -[1]:https://github.com/python-discord/sir-lancebot/workflows/Lint/badge.svg?branch=master -[2]:https://github.com/python-discord/sir-lancebot/actions?query=workflow%3ALint+branch%3Amaster -[3]:https://github.com/python-discord/sir-lancebot/workflows/Build/badge.svg?branch=master -[4]:https://github.com/python-discord/sir-lancebot/actions?query=workflow%3ABuild+branch%3Amaster -[5]: https://raw.githubusercontent.com/python-discord/branding/master/logos/badge/badge_github.svg +[1]:https://github.com/python-discord/sir-lancebot/workflows/Lint/badge.svg?branch=main +[2]:https://github.com/python-discord/sir-lancebot/actions?query=workflow%3ALint+branch%3Amain +[3]:https://github.com/python-discord/sir-lancebot/workflows/Build/badge.svg?branch=main +[4]:https://github.com/python-discord/sir-lancebot/actions?query=workflow%3ABuild+branch%3Amain +[5]: https://raw.githubusercontent.com/python-discord/branding/main/logos/badge/badge_github.svg [6]: https://discord.gg/python diff --git a/bot/exts/christmas/advent_of_code/_helpers.py b/bot/exts/christmas/advent_of_code/_helpers.py index b7adc895..a16a4871 100644 --- a/bot/exts/christmas/advent_of_code/_helpers.py +++ b/bot/exts/christmas/advent_of_code/_helpers.py @@ -44,7 +44,7 @@ REQUIRED_CACHE_KEYS = ( AOC_EMBED_THUMBNAIL = ( "https://raw.githubusercontent.com/python-discord" - "/branding/master/seasonal/christmas/server_icons/festive_256.gif" + "/branding/main/seasonal/christmas/server_icons/festive_256.gif" ) # Create an easy constant for the EST timezone diff --git a/bot/exts/evergreen/source.py b/bot/exts/evergreen/source.py index cdfe54ec..45752bf9 100644 --- a/bot/exts/evergreen/source.py +++ b/bot/exts/evergreen/source.py @@ -76,7 +76,7 @@ class BotSource(commands.Cog): file_location = Path(filename).relative_to(Path.cwd()).as_posix() - url = f"{Source.github}/blob/master/{file_location}{lines_extension}" + url = f"{Source.github}/blob/main/{file_location}{lines_extension}" return url, file_location, first_line_no or None diff --git a/bot/resources/halloween/spooky_rating.json b/bot/resources/halloween/spooky_rating.json index 533e7107..8e3e66bb 100644 --- a/bot/resources/halloween/spooky_rating.json +++ b/bot/resources/halloween/spooky_rating.json @@ -2,46 +2,46 @@ "-1": { "title": "\uD83D\uDD6F You're not scarin' anyone \uD83D\uDD6F", "text": "No matter what you say or do, nobody even flinches when you try to scare them. Was your costume this year only a white sheet with holes for eyes? Or did you even bother with a costume at all? Either way, don't expect too many treats when going from door-to-door.", - "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/master/bot/resources/halloween/spookyrating/candle.jpeg" + "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/main/bot/resources/halloween/spookyrating/candle.jpeg" }, "5": { "title": "\uD83D\uDC76 Like taking candy from a baby \uD83D\uDC76", "text": "Your scaring will probably make a baby cry... but that's the limit on your frightening powers. Be careful not to get to the point where everyone's running away from you because they don't like you, not because they're scared of you.", - "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/master/bot/resources/halloween/spookyrating/baby.jpeg" + "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/main/bot/resources/halloween/spookyrating/baby.jpeg" }, "20": { "title": "\uD83C\uDFDA You're skills are forming... \uD83C\uDFDA", "text": "As you become the Devil's apprentice, you begin to make people jump every time you sneak up on them. A good start, but you have to learn not to wear the same costume every year until it doesn't fit you. People will notice you and your prowess will decrease.", - "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/master/bot/resources/halloween/spookyrating/tiger.jpeg" + "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/main/bot/resources/halloween/spookyrating/tiger.jpeg" }, "30": { "title": "\uD83D\uDC80 Picture Perfect... \uD83D\uDC80", "text": "You've nailed the costume this year! You look suuuper scary! Now make sure to play the part and act out your costume and you'll be sure to give a few people a massive fright!", - "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/master/bot/resources/halloween/spookyrating/costume.jpeg" + "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/main/bot/resources/halloween/spookyrating/costume.jpeg" }, "50": { "title": "\uD83D\uDC7B Uhm... are you human \uD83D\uDC7B", "text": "Uhm... you're too good to be human and now you're beginning to sound like a ghost. You're almost invisible when haunting and nobody truly knows where you are at any given time. But they will always scream at the sound of a ghost...", - "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/master/bot/resources/halloween/spookyrating/ghost.jpeg" + "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/main/bot/resources/halloween/spookyrating/ghost.jpeg" }, "65": { "title": "\uD83C\uDF83 That potion can't be real \uD83C\uDF83", "text": "You're carrying... some... unknown liquids and no one knows who they are but yourself. Be careful on who you use these powerful spells on, because no Mage has the power to do any irreversible enchantments because even you won't know what will happen to these mortals.", - "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/master/bot/resources/halloween/spookyrating/necromancer.jepg" + "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/main/bot/resources/halloween/spookyrating/necromancer.jepg" }, "80": { "title": "\uD83E\uDD21 The most sinister face \uD83E\uDD21", "text": "Who knew something intended to be playful could be so menacing... Especially other people seeing you in their nightmares, continuing to haunt them day by day, stuck in their head throughout the entire year. Make sure to pull a face they will never forget.", - "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/master/bot/resources/halloween/spookyrating/clown.jpeg" + "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/main/bot/resources/halloween/spookyrating/clown.jpeg" }, "95": { "title": "\uD83D\uDE08 The Devil's Accomplice \uD83D\uDE08", "text": "Imagine being allies with the most evil character with an aim to scare people to death. Force people to suffer as they proceed straight to hell to meet your boss and best friend. Not even you know the power He has...", - "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/master/bot/resources/halloween/spookyrating/jackolantern.jpg" + "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/main/bot/resources/halloween/spookyrating/jackolantern.jpg" }, "100": { "title":"\uD83D\uDC7F The Devil Himself \uD83D\uDC7F", "text": "You are the evillest creature in existence to scare anyone and everyone humanly possible. The reason your underlings are called mortals is that they die. With your help, they die a lot quicker. With all the evil power in the universe, you know what to do.", - "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/master/bot/resources/halloween/spookyrating/devil.jpeg" + "image": "https://raw.githubusercontent.com/python-discord/sir-lancebot/main/bot/resources/halloween/spookyrating/devil.jpeg" } } diff --git a/bot/utils/time.py b/bot/utils/time.py index 3c57e126..fbf2fd21 100644 --- a/bot/utils/time.py +++ b/bot/utils/time.py @@ -3,7 +3,7 @@ import datetime from dateutil.relativedelta import relativedelta -# All these functions are from https://github.com/python-discord/bot/blob/master/bot/utils/time.py +# All these functions are from https://github.com/python-discord/bot/blob/main/bot/utils/time.py def _stringify_time_unit(value: int, unit: str) -> str: """ Returns a string to represent a value and time unit, ensuring that it uses the right plural form of the unit. -- cgit v1.2.3 From 0e074b798dd8b47c86043f85b8fac71b76cb8d1b Mon Sep 17 00:00:00 2001 From: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> Date: Sat, 13 Mar 2021 23:26:24 +0300 Subject: Removes Unused Roles & Channels Removes roles and channels from constants.py that are not used anywhere in the project. Signed-off-by: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> --- bot/constants.py | 25 ------------------------- bot/exts/christmas/advent_of_code/_cog.py | 2 +- 2 files changed, 1 insertion(+), 26 deletions(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index b8e30a7c..416dd0e7 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -94,33 +94,18 @@ class Branding: class Channels(NamedTuple): - admins = 365960823622991872 advent_of_code = int(environ.get("AOC_CHANNEL_ID", 782715290437943306)) advent_of_code_commands = int(environ.get("AOC_COMMANDS_CHANNEL_ID", 607247579608121354)) - announcements = int(environ.get("CHANNEL_ANNOUNCEMENTS", 354619224620138496)) - big_brother_logs = 468507907357409333 bot = 267659945086812160 - checkpoint_test = 422077681434099723 organisation = 551789653284356126 - devalerts = 460181980097675264 devlog = int(environ.get("CHANNEL_DEVLOG", 622895325144940554)) dev_contrib = 635950537262759947 - dev_branding = 753252897059373066 - helpers = 385474242440986624 - message_log = 467752170159079424 - mod_alerts = 473092532147060736 - modlog = 282638479504965634 mod_meta = 775412552795947058 mod_tools = 775413915391098921 off_topic_0 = 291284109232308226 off_topic_1 = 463035241142026251 off_topic_2 = 463035268514185226 - python = 267624335836053506 - reddit = 458224812528238616 community_bot_commands = int(environ.get("CHANNEL_COMMUNITY_BOT_COMMANDS", 607247579608121354)) - staff_lounge = 464905259261755392 - verification = 352442727016693763 - python_discussion = 267624335836053506 hacktoberfest_2020 = 760857070781071431 voice_chat_0 = 412357430186344448 voice_chat_1 = 799647045886541885 @@ -248,20 +233,10 @@ if Client.month_override is not None: class Roles(NamedTuple): admin = int(environ.get("BOT_ADMIN_ROLE_ID", 267628507062992896)) - announcements = 463658397560995840 - champion = 430492892331769857 - contributor = 295488872404484098 - devops = 409416496733880320 - jammer = 423054537079783434 moderator = 267629731250176001 - muted = 277914926603829249 owner = 267627879762755584 - verified = 352427296948486144 helpers = int(environ.get("ROLE_HELPERS", 267630620367257601)) - rockstars = 458226413825294336 core_developers = 587606783669829632 - events_lead = 778361735739998228 - everyone_role = 267624335836053506 class Tokens(NamedTuple): diff --git a/bot/exts/christmas/advent_of_code/_cog.py b/bot/exts/christmas/advent_of_code/_cog.py index dc3d7616..8376987d 100644 --- a/bot/exts/christmas/advent_of_code/_cog.py +++ b/bot/exts/christmas/advent_of_code/_cog.py @@ -244,7 +244,7 @@ class AdventOfCode(commands.Cog): info_embed = _helpers.get_summary_embed(leaderboard) await ctx.send(f"```\n{table}\n```", embed=info_embed) - @with_role(Roles.admin, Roles.events_lead) + @with_role(Roles.admin) @adventofcode_group.command( name="refresh", aliases=("fetch",), -- cgit v1.2.3 From 1dea5902487a93d1f9a6382d838928d0a9739627 Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Fri, 19 Mar 2021 15:10:58 -0400 Subject: Make .github a group, and add github repo + user commands --- bot/exts/evergreen/githubinfo.py | 72 +++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 8 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index 2e38e3ab..74371244 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -8,9 +8,12 @@ from discord.ext import commands from discord.ext.commands.cooldowns import BucketType from bot.constants import NEGATIVE_REPLIES +from bot.exts.utils.extensions import invoke_help_command log = logging.getLogger(__name__) +GITHUB_API_URL = "https://api.github.com" + class GithubInfo(commands.Cog): """Fetches info from GitHub.""" @@ -23,21 +26,27 @@ class GithubInfo(commands.Cog): async with self.bot.http_session.get(url) as r: return await r.json() - @commands.command(name='github', aliases=['gh']) - @commands.cooldown(1, 60, BucketType.user) - async def get_github_info(self, ctx: commands.Context, username: Optional[str]) -> None: + @commands.group(name='github', aliases=('gh',)) + @commands.cooldown(1, 10, BucketType.user) + async def github_group(self, ctx: commands.Context): + """Commands for finding info related to Github.""" + if ctx.invoked_subcommand is None: + await invoke_help_command(ctx) + + @github_group.command(name='user', aliases=('userinfo',)) + async def github_user_info(self, ctx: commands.Context, username: Optional[str]) -> None: """ Fetches a user's GitHub information. Username is optional and sends the help command if not specified. """ if username is None: - await ctx.invoke(self.bot.get_command('help'), 'github') + await invoke_help_command(ctx) ctx.command.reset_cooldown(ctx) return async with ctx.typing(): - user_data = await self.fetch_data(f"https://api.github.com/users/{username}") + user_data = await self.fetch_data(f"{GITHUB_API_URL}/users/{username}") # User_data will not have a message key if the user exists if user_data.get('message') is not None: @@ -74,24 +83,71 @@ class GithubInfo(commands.Cog): embed.add_field(name="Followers", value=f"[{user_data['followers']}]({user_data['html_url']}?tab=followers)") - embed.add_field(name="\u200b", value="\u200b") embed.add_field(name="Following", value=f"[{user_data['following']}]({user_data['html_url']}?tab=following)") embed.add_field(name="Public repos", value=f"[{user_data['public_repos']}]({user_data['html_url']}?tab=repositories)") - embed.add_field(name="\u200b", value="\u200b") if user_data['type'] == "User": embed.add_field(name="Gists", value=f"[{gists}](https://gist.github.com/{username})") embed.add_field(name=f"Organization{'s' if len(orgs)!=1 else ''}", value=orgs_to_add if orgs else "No organizations") - embed.add_field(name="\u200b", value="\u200b") embed.add_field(name="Website", value=blog) await ctx.send(embed=embed) + @github_group.command(name='repo', aliases=('repositories',)) + async def github_repo_info(self, ctx: commands.Context, repo: Optional[str]): + """ + Fetches a repositories's GitHub information. Repository should look like `user/reponame`. + + Repository is optional and sends the help command if not specified. + """ + if repo is None: + await invoke_help_command(ctx) + ctx.command.reset_cooldown() + return + async with ctx.typing(): + repo_data = await self.fetch_data(f"{GITHUB_API_URL}/repos/{repo}") + + # There won't be a message key if this repo exists + if repo_data.get('message') is not None: + await ctx.send(embed=discord.Embed(title=random.choice(NEGATIVE_REPLIES), + description=f"The requested repository was not found.", + colour=discord.Colour.red())) + return + + repo_owner = repo_data['owner'] + + parent = repo_data.get('parent') + + embed = discord.Embed(title=f"{repo_data['name']}", + description=repo_data["description"], + colour=0x7289da, + url=repo_data['html_url'], + timestamp=datetime.strptime(repo_data['pushed_at'], "%Y-%m-%dT%H:%M:%SZ") + ) + + # If it's a fork, then it will have a parent key + if parent: + embed.description += f"\nForked from [{parent['full_name']}]({parent['html_url']})" + + embed.set_author( + name=repo_owner["login"], + url=repo_owner["html_url"], + icon_url=repo_owner["avatar_url"] + ) + + repo_created_at = datetime.strptime(repo_data['created_at'], "%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y") + + embed.set_footer(text=f"{repo_data['forks_count']} " + f"⑂ • {repo_data['stargazers_count']} ⭐ • Created At {repo_created_at} • " + " Last commit ") + + await ctx.send(embed=embed) + def setup(bot: commands.Bot) -> None: """Adding the cog to the bot.""" -- cgit v1.2.3 From b3c25c888b16ea707e974282c249eaf9799e184d Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Fri, 19 Mar 2021 15:19:05 -0400 Subject: Make alias repository, not repositories --- bot/exts/evergreen/githubinfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index 74371244..b683065e 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -98,7 +98,7 @@ class GithubInfo(commands.Cog): await ctx.send(embed=embed) - @github_group.command(name='repo', aliases=('repositories',)) + @github_group.command(name='repo', aliases=('repository',)) async def github_repo_info(self, ctx: commands.Context, repo: Optional[str]): """ Fetches a repositories's GitHub information. Repository should look like `user/reponame`. -- cgit v1.2.3 From 658b3b4de1112378e9694b95bcba3d4b8c5213f7 Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Fri, 19 Mar 2021 15:23:24 -0400 Subject: Missed a \n --- bot/exts/evergreen/githubinfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index b683065e..521b94e7 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -132,7 +132,7 @@ class GithubInfo(commands.Cog): # If it's a fork, then it will have a parent key if parent: - embed.description += f"\nForked from [{parent['full_name']}]({parent['html_url']})" + embed.description += f"\n\nForked from [{parent['full_name']}]({parent['html_url']})" embed.set_author( name=repo_owner["login"], -- cgit v1.2.3 From 01ce649b05999b029490bff00e07cd9f32e285e8 Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Fri, 19 Mar 2021 15:27:53 -0400 Subject: Make flake8 happy --- bot/exts/evergreen/githubinfo.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index 521b94e7..2c7dd885 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -28,7 +28,7 @@ class GithubInfo(commands.Cog): @commands.group(name='github', aliases=('gh',)) @commands.cooldown(1, 10, BucketType.user) - async def github_group(self, ctx: commands.Context): + async def github_group(self, ctx: commands.Context) -> None: """Commands for finding info related to Github.""" if ctx.invoked_subcommand is None: await invoke_help_command(ctx) @@ -99,7 +99,7 @@ class GithubInfo(commands.Cog): await ctx.send(embed=embed) @github_group.command(name='repo', aliases=('repository',)) - async def github_repo_info(self, ctx: commands.Context, repo: Optional[str]): + async def github_repo_info(self, ctx: commands.Context, repo: Optional[str]) -> None: """ Fetches a repositories's GitHub information. Repository should look like `user/reponame`. @@ -115,7 +115,7 @@ class GithubInfo(commands.Cog): # There won't be a message key if this repo exists if repo_data.get('message') is not None: await ctx.send(embed=discord.Embed(title=random.choice(NEGATIVE_REPLIES), - description=f"The requested repository was not found.", + description="The requested repository was not found.", colour=discord.Colour.red())) return -- cgit v1.2.3 From 060c5403a7ea1866731ec2bb23d3e7ba4234fe8c Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Fri, 19 Mar 2021 21:07:35 -0400 Subject: Make better aliases and follow style guidelines --- bot/exts/evergreen/githubinfo.py | 41 ++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index 2c7dd885..8dbcc681 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -98,37 +98,38 @@ class GithubInfo(commands.Cog): await ctx.send(embed=embed) - @github_group.command(name='repo', aliases=('repository',)) - async def github_repo_info(self, ctx: commands.Context, repo: Optional[str]) -> None: + @github_group.command(name='repository', aliases=('repo', 'git')) + async def github_repo_info(self, ctx: commands.Context, repo: str) -> None: """ Fetches a repositories's GitHub information. Repository should look like `user/reponame`. Repository is optional and sends the help command if not specified. """ - if repo is None: - await invoke_help_command(ctx) - ctx.command.reset_cooldown() - return async with ctx.typing(): repo_data = await self.fetch_data(f"{GITHUB_API_URL}/repos/{repo}") # There won't be a message key if this repo exists if repo_data.get('message') is not None: - await ctx.send(embed=discord.Embed(title=random.choice(NEGATIVE_REPLIES), - description="The requested repository was not found.", - colour=discord.Colour.red())) + embed = discord.Embed( + title=random.choice(NEGATIVE_REPLIES), + description="The requested repository was not found.", + colour=discord.Colour.red() + ) + + await ctx.send(embed=embed) return repo_owner = repo_data['owner'] parent = repo_data.get('parent') - embed = discord.Embed(title=f"{repo_data['name']}", - description=repo_data["description"], - colour=0x7289da, - url=repo_data['html_url'], - timestamp=datetime.strptime(repo_data['pushed_at'], "%Y-%m-%dT%H:%M:%SZ") - ) + embed = discord.Embed( + title=f"{repo_data['name']}", + description=repo_data["description"], + colour=0x7289da, + url=repo_data['html_url'], + timestamp=datetime.strptime(repo_data['pushed_at'], "%Y-%m-%dT%H:%M:%SZ") + ) # If it's a fork, then it will have a parent key if parent: @@ -142,9 +143,13 @@ class GithubInfo(commands.Cog): repo_created_at = datetime.strptime(repo_data['created_at'], "%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y") - embed.set_footer(text=f"{repo_data['forks_count']} " - f"⑂ • {repo_data['stargazers_count']} ⭐ • Created At {repo_created_at} • " - " Last commit ") + embed.set_footer( + text=( + f"{repo_data['forks_count']} " + f"⑂ • {repo_data['stargazers_count']} ⭐ • Created At {repo_created_at} • " + " Last commit " + ) + ) await ctx.send(embed=embed) -- cgit v1.2.3 From ad3c78e7a1ed8f4c54c21ab45e85be6c18e5c63f Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Fri, 19 Mar 2021 21:25:11 -0400 Subject: Make git alias for the group instead --- bot/exts/evergreen/githubinfo.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index 8dbcc681..58162e42 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -26,7 +26,7 @@ class GithubInfo(commands.Cog): async with self.bot.http_session.get(url) as r: return await r.json() - @commands.group(name='github', aliases=('gh',)) + @commands.group(name='github', aliases=('gh', 'git')) @commands.cooldown(1, 10, BucketType.user) async def github_group(self, ctx: commands.Context) -> None: """Commands for finding info related to Github.""" @@ -98,7 +98,7 @@ class GithubInfo(commands.Cog): await ctx.send(embed=embed) - @github_group.command(name='repository', aliases=('repo', 'git')) + @github_group.command(name='repository', aliases=('repo')) async def github_repo_info(self, ctx: commands.Context, repo: str) -> None: """ Fetches a repositories's GitHub information. Repository should look like `user/reponame`. -- cgit v1.2.3 From 6387376cdb000b6e33dd1c67d9b7a24d1d7705b4 Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Fri, 19 Mar 2021 21:26:59 -0400 Subject: Forgot a comma for the tuple --- bot/exts/evergreen/githubinfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index 58162e42..da2b37ac 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -98,7 +98,7 @@ class GithubInfo(commands.Cog): await ctx.send(embed=embed) - @github_group.command(name='repository', aliases=('repo')) + @github_group.command(name='repository', aliases=('repo',)) async def github_repo_info(self, ctx: commands.Context, repo: str) -> None: """ Fetches a repositories's GitHub information. Repository should look like `user/reponame`. -- cgit v1.2.3 From 9e01d6b85dd27d8ecb5f00a5cf20f332d534e584 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 20 Mar 2021 11:13:46 +0000 Subject: Only output override channels & bot commands channel on whitelist error Previously this would output all channels, and could result in an error. This change ensures only the main bot channel & and any overridden channels are shown in the embed. We do this before the categories block as the categories kwarg itself is an override, so we want to include those in any output. --- bot/utils/decorators.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/utils/decorators.py b/bot/utils/decorators.py index c12a15ff..f0e2ff99 100644 --- a/bot/utils/decorators.py +++ b/bot/utils/decorators.py @@ -11,7 +11,7 @@ from discord import Colour, Embed from discord.ext import commands from discord.ext.commands import CheckFailure, Command, Context -from bot.constants import ERROR_REPLIES, Month +from bot.constants import Channels, ERROR_REPLIES, Month, WHITELISTED_CHANNELS from bot.utils import human_months, resolve_current_month from bot.utils.checks import in_whitelist_check @@ -253,6 +253,12 @@ def whitelist_check(**default_kwargs: t.Container[int]) -> t.Callable[[Context], channels = set(kwargs.get("channels") or {}) categories = kwargs.get("categories") + # Only output override channels + community_bot_commands + if channels: + default_whitelist_channels = set(WHITELISTED_CHANNELS) + default_whitelist_channels.discard(Channels.community_bot_commands) + channels.difference_update(default_whitelist_channels) + # Add all whitelisted category channels if categories: for category_id in categories: -- cgit v1.2.3 From e0dbf3b9c01774fc4570ce29b6898c5a32f32a1f Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Sat, 20 Mar 2021 07:53:45 -0400 Subject: Update bot/exts/evergreen/githubinfo.py Co-authored-by: Shivansh-007 --- bot/exts/evergreen/githubinfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index da2b37ac..cffdc0b2 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -101,7 +101,7 @@ class GithubInfo(commands.Cog): @github_group.command(name='repository', aliases=('repo',)) async def github_repo_info(self, ctx: commands.Context, repo: str) -> None: """ - Fetches a repositories's GitHub information. Repository should look like `user/reponame`. + Fetches a repositories' GitHub information. The repository should look like `user/reponame`. Repository is optional and sends the help command if not specified. """ -- cgit v1.2.3 From 087b58209b52f835eef6493d2269d98867f39b0c Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Sat, 20 Mar 2021 11:02:28 -0400 Subject: Follow style guildines and use better colours --- bot/exts/evergreen/githubinfo.py | 48 ++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 21 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index da2b37ac..ec2f9d98 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -1,13 +1,12 @@ import logging import random from datetime import datetime -from typing import Optional import discord from discord.ext import commands from discord.ext.commands.cooldowns import BucketType -from bot.constants import NEGATIVE_REPLIES +from bot.constants import NEGATIVE_REPLIES, Colours from bot.exts.utils.extensions import invoke_help_command log = logging.getLogger(__name__) @@ -34,25 +33,24 @@ class GithubInfo(commands.Cog): await invoke_help_command(ctx) @github_group.command(name='user', aliases=('userinfo',)) - async def github_user_info(self, ctx: commands.Context, username: Optional[str]) -> None: + async def github_user_info(self, ctx: commands.Context, username: str) -> None: """ Fetches a user's GitHub information. Username is optional and sends the help command if not specified. """ - if username is None: - await invoke_help_command(ctx) - ctx.command.reset_cooldown(ctx) - return - async with ctx.typing(): user_data = await self.fetch_data(f"{GITHUB_API_URL}/users/{username}") # User_data will not have a message key if the user exists if user_data.get('message') is not None: - await ctx.send(embed=discord.Embed(title=random.choice(NEGATIVE_REPLIES), - description=f"The profile for `{username}` was not found.", - colour=discord.Colour.red())) + embed = discord.Embed( + title=random.choice(NEGATIVE_REPLIES), + description=f"The profile for `{username}` was not found.", + colour=Colours.soft_red + ) + + await ctx.send() return org_data = await self.fetch_data(user_data['organizations_url']) @@ -72,7 +70,7 @@ class GithubInfo(commands.Cog): embed = discord.Embed( title=f"`{user_data['login']}`'s GitHub profile info", description=f"```{user_data['bio']}```\n" if user_data['bio'] is not None else "", - colour=0x7289da, + colour=discord.Colour.blurple(), url=user_data['html_url'], timestamp=datetime.strptime(user_data['created_at'], "%Y-%m-%dT%H:%M:%SZ") ) @@ -81,19 +79,27 @@ class GithubInfo(commands.Cog): if user_data['type'] == "User": - embed.add_field(name="Followers", - value=f"[{user_data['followers']}]({user_data['html_url']}?tab=followers)") - embed.add_field(name="Following", - value=f"[{user_data['following']}]({user_data['html_url']}?tab=following)") + embed.add_field( + name="Followers", + value=f"[{user_data['followers']}]({user_data['html_url']}?tab=followers)" + ) + embed.add_field( + name="Following", + value=f"[{user_data['following']}]({user_data['html_url']}?tab=following)" + ) - embed.add_field(name="Public repos", - value=f"[{user_data['public_repos']}]({user_data['html_url']}?tab=repositories)") + embed.add_field( + name="Public repos", + value=f"[{user_data['public_repos']}]({user_data['html_url']}?tab=repositories)" + ) if user_data['type'] == "User": embed.add_field(name="Gists", value=f"[{gists}](https://gist.github.com/{username})") - embed.add_field(name=f"Organization{'s' if len(orgs)!=1 else ''}", - value=orgs_to_add if orgs else "No organizations") + embed.add_field( + name=f"Organization{'s' if len(orgs)!=1 else ''}", + value=orgs_to_add if orgs else "No organizations" + ) embed.add_field(name="Website", value=blog) await ctx.send(embed=embed) @@ -113,7 +119,7 @@ class GithubInfo(commands.Cog): embed = discord.Embed( title=random.choice(NEGATIVE_REPLIES), description="The requested repository was not found.", - colour=discord.Colour.red() + colour=Colours.soft_red ) await ctx.send(embed=embed) -- cgit v1.2.3 From 7fb2134e40f7d9b47759797785d9e47ff059ff7c Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Sat, 20 Mar 2021 11:14:33 -0400 Subject: Make a new line for `created_at` Co-authored-by: Shivansh-007 --- bot/exts/evergreen/githubinfo.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index cffdc0b2..75db10d4 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -145,9 +145,10 @@ class GithubInfo(commands.Cog): embed.set_footer( text=( - f"{repo_data['forks_count']} " - f"⑂ • {repo_data['stargazers_count']} ⭐ • Created At {repo_created_at} • " - " Last commit " + f"{repo_data['forks_count']} ⑂ " + f"• {repo_data['stargazers_count']} ⭐ " + f"• Created At {repo_created_at} " + f"• Last commit " ) ) -- cgit v1.2.3 From d945ec3314500e579d8e79f086d53453886daf9a Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Sat, 20 Mar 2021 11:28:17 -0400 Subject: Fix trailing whitespace --- bot/exts/evergreen/githubinfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index 0b2c4c77..07175857 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -152,7 +152,7 @@ class GithubInfo(commands.Cog): embed.set_footer( text=( f"{repo_data['forks_count']} ⑂ " - f"• {repo_data['stargazers_count']} ⭐ " + f"• {repo_data['stargazers_count']} ⭐ " f"• Created At {repo_created_at} " f"• Last commit " ) -- cgit v1.2.3 From 5c8e3008ee5f37bbcab24552fd4c933c8271aa58 Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Sat, 20 Mar 2021 11:37:56 -0400 Subject: Fix imports --- bot/exts/evergreen/githubinfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index 07175857..ebb265b5 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -6,7 +6,7 @@ import discord from discord.ext import commands from discord.ext.commands.cooldowns import BucketType -from bot.constants import NEGATIVE_REPLIES, Colours +from bot.constants import Colours, NEGATIVE_REPLIES from bot.exts.utils.extensions import invoke_help_command log = logging.getLogger(__name__) -- cgit v1.2.3 From 69569fe2c5dafb659b3c56e764d034281686492e Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Sat, 20 Mar 2021 11:41:12 -0400 Subject: Change --- bot/exts/evergreen/githubinfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index ebb265b5..5559a464 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -132,7 +132,7 @@ class GithubInfo(commands.Cog): embed = discord.Embed( title=f"{repo_data['name']}", description=repo_data["description"], - colour=0x7289da, + colour=discord.Colour.blurple(), url=repo_data['html_url'], timestamp=datetime.strptime(repo_data['pushed_at'], "%Y-%m-%dT%H:%M:%SZ") ) -- cgit v1.2.3 From 85c6dfa00e01abea8b65654aed59a520af3c18a6 Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Sat, 20 Mar 2021 12:15:57 -0400 Subject: Make last commit not a timestamp to improve readability --- bot/exts/evergreen/githubinfo.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index 5559a464..67d91589 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -133,8 +133,7 @@ class GithubInfo(commands.Cog): title=f"{repo_data['name']}", description=repo_data["description"], colour=discord.Colour.blurple(), - url=repo_data['html_url'], - timestamp=datetime.strptime(repo_data['pushed_at'], "%Y-%m-%dT%H:%M:%SZ") + url=repo_data['html_url'] ) # If it's a fork, then it will have a parent key @@ -148,13 +147,14 @@ class GithubInfo(commands.Cog): ) repo_created_at = datetime.strptime(repo_data['created_at'], "%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y") + last_pushed = datetime.strptime(repo_data['pushed_at'], "%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y at %H:%M") embed.set_footer( text=( f"{repo_data['forks_count']} ⑂ " f"• {repo_data['stargazers_count']} ⭐ " f"• Created At {repo_created_at} " - f"• Last commit " + f"• Last Commit {last_pushed}" ) ) -- cgit v1.2.3 From ed26d381e1959523b9a5da2866f7f1f917ee7bae Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Sun, 21 Mar 2021 08:36:09 -0400 Subject: Add the embed kwarg to ctx.send --- bot/exts/evergreen/githubinfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index 67d91589..1be2e385 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -50,7 +50,7 @@ class GithubInfo(commands.Cog): colour=Colours.soft_red ) - await ctx.send() + await ctx.send(embed=embed) return org_data = await self.fetch_data(user_data['organizations_url']) -- cgit v1.2.3 From 1e9a88f5b59cf7d1c4e24f48cc09aa98e5f6499b Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 21 Mar 2021 18:11:50 +0000 Subject: Replace list comp with a set update + sequence --- bot/utils/decorators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/utils/decorators.py b/bot/utils/decorators.py index f0e2ff99..60066dc4 100644 --- a/bot/utils/decorators.py +++ b/bot/utils/decorators.py @@ -266,7 +266,7 @@ def whitelist_check(**default_kwargs: t.Container[int]) -> t.Callable[[Context], if category is None: continue - [channels.add(channel.id) for channel in category.text_channels] + channels.update(channel.id for channel in category.text_channels) if channels: channels_str = ', '.join(f"<#{c_id}>" for c_id in channels) -- cgit v1.2.3 From faccb5d2828d046d5e3a1e21c63f392529be4691 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Wed, 24 Mar 2021 09:24:32 +0100 Subject: Remove broken link from the April fool collection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Its’a braken --- bot/resources/easter/april_fools_vids.json | 4 ---- 1 file changed, 4 deletions(-) (limited to 'bot') diff --git a/bot/resources/easter/april_fools_vids.json b/bot/resources/easter/april_fools_vids.json index 5f0ba06e..d8c1efa1 100644 --- a/bot/resources/easter/april_fools_vids.json +++ b/bot/resources/easter/april_fools_vids.json @@ -16,10 +16,6 @@ "title": "Haptic Helpers: bringing you to your senses", "link": "https://youtu.be/3MA6_21nka8" }, - { - "title": "Introducing Google Gnome", - "link": "https://youtu.be/vNOllWX-2aE" - }, { "title": "Introducing Google Wind", "link": "https://youtu.be/QAwL0O5nXe0" -- cgit v1.2.3 From 8b72a57f05c85fbdd6f9735f8cf722f7d63df659 Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Wed, 24 Mar 2021 13:31:13 -0400 Subject: Update docstrings because user and repo are now mandatory arguments --- bot/exts/evergreen/githubinfo.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index 1be2e385..34e30d0b 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -34,11 +34,7 @@ class GithubInfo(commands.Cog): @github_group.command(name='user', aliases=('userinfo',)) async def github_user_info(self, ctx: commands.Context, username: str) -> None: - """ - Fetches a user's GitHub information. - - Username is optional and sends the help command if not specified. - """ + """Fetches a user's GitHub information.""" async with ctx.typing(): user_data = await self.fetch_data(f"{GITHUB_API_URL}/users/{username}") @@ -106,11 +102,7 @@ class GithubInfo(commands.Cog): @github_group.command(name='repository', aliases=('repo',)) async def github_repo_info(self, ctx: commands.Context, repo: str) -> None: - """ - Fetches a repositories' GitHub information. The repository should look like `user/reponame`. - - Repository is optional and sends the help command if not specified. - """ + """Fetches a repositories' GitHub information. The repository should look like `user/reponame`.""" async with ctx.typing(): repo_data = await self.fetch_data(f"{GITHUB_API_URL}/repos/{repo}") -- cgit v1.2.3 From e044bf3d716dc166704ba31def82bd34a68acb42 Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Wed, 24 Mar 2021 13:34:47 -0400 Subject: Info -> information Co-authored-by: Shivansh-007 --- bot/exts/evergreen/githubinfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index 34e30d0b..712a516b 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -28,7 +28,7 @@ class GithubInfo(commands.Cog): @commands.group(name='github', aliases=('gh', 'git')) @commands.cooldown(1, 10, BucketType.user) async def github_group(self, ctx: commands.Context) -> None: - """Commands for finding info related to Github.""" + """Commands for finding information related to GitHub.""" if ctx.invoked_subcommand is None: await invoke_help_command(ctx) -- cgit v1.2.3 From ed5dc457c51aae388e5d4607639fb79be958ff27 Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Thu, 25 Mar 2021 19:22:12 -0400 Subject: Quote reponame and username --- bot/exts/evergreen/githubinfo.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index 34e30d0b..56195e8c 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -1,6 +1,7 @@ import logging import random from datetime import datetime +from urllib.parse import quote import discord from discord.ext import commands @@ -90,7 +91,7 @@ class GithubInfo(commands.Cog): ) if user_data['type'] == "User": - embed.add_field(name="Gists", value=f"[{gists}](https://gist.github.com/{username})") + embed.add_field(name="Gists", value=f"[{gists}](https://gist.github.com/{quote(username, safe='')})") embed.add_field( name=f"Organization{'s' if len(orgs)!=1 else ''}", @@ -103,8 +104,18 @@ class GithubInfo(commands.Cog): @github_group.command(name='repository', aliases=('repo',)) async def github_repo_info(self, ctx: commands.Context, repo: str) -> None: """Fetches a repositories' GitHub information. The repository should look like `user/reponame`.""" + if repo.count('/') != 1: + embed = discord.Embed( + title=random.choice(NEGATIVE_REPLIES), + description="The repository should look like `user/reponame`.", + colour=Colours.soft_red + ) + + await ctx.send(embed=embed) + return + async with ctx.typing(): - repo_data = await self.fetch_data(f"{GITHUB_API_URL}/repos/{repo}") + repo_data = await self.fetch_data(f"{GITHUB_API_URL}/repos/{quote(repo)}") # There won't be a message key if this repo exists if repo_data.get('message') is not None: -- cgit v1.2.3 From 8f79d6705dd8d62a51d34f12f27fa9643fc3b04c Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Thu, 25 Mar 2021 21:44:26 -0400 Subject: Make requested changes --- bot/exts/evergreen/githubinfo.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index 94a3166b..1b64b0eb 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -40,7 +40,7 @@ class GithubInfo(commands.Cog): user_data = await self.fetch_data(f"{GITHUB_API_URL}/users/{username}") # User_data will not have a message key if the user exists - if user_data.get('message') is not None: + if "message" in user_data: embed = discord.Embed( title=random.choice(NEGATIVE_REPLIES), description=f"The profile for `{username}` was not found.", @@ -118,7 +118,7 @@ class GithubInfo(commands.Cog): repo_data = await self.fetch_data(f"{GITHUB_API_URL}/repos/{quote(repo)}") # There won't be a message key if this repo exists - if repo_data.get('message') is not None: + if "message" in repo_data: embed = discord.Embed( title=random.choice(NEGATIVE_REPLIES), description="The requested repository was not found.", @@ -128,20 +128,21 @@ class GithubInfo(commands.Cog): await ctx.send(embed=embed) return - repo_owner = repo_data['owner'] - - parent = repo_data.get('parent') - embed = discord.Embed( - title=f"{repo_data['name']}", + title=repo_data['name'], description=repo_data["description"], colour=discord.Colour.blurple(), url=repo_data['html_url'] ) # If it's a fork, then it will have a parent key - if parent: + try: + parent = repo_data["parent"] embed.description += f"\n\nForked from [{parent['full_name']}]({parent['html_url']})" + except KeyError: + log.debug("Repository is not a fork.") + + repo_owner = repo_data['owner'] embed.set_author( name=repo_owner["login"], -- cgit v1.2.3 From f6a28d5833160dccb6d308fd8e27c6afb9729643 Mon Sep 17 00:00:00 2001 From: Neil Shah <78612612+NeilShah2026@users.noreply.github.com> Date: Fri, 26 Mar 2021 09:50:03 -0400 Subject: Added 3 More Elements To The Json --- bot/resources/easter/april_fools_vids.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'bot') diff --git a/bot/resources/easter/april_fools_vids.json b/bot/resources/easter/april_fools_vids.json index d8c1efa1..d029ff86 100644 --- a/bot/resources/easter/april_fools_vids.json +++ b/bot/resources/easter/april_fools_vids.json @@ -116,6 +116,18 @@ "title": "Introducing Gmail Motion", "link": "https://youtu.be/Bu927_ul_X0" } + { + "title": "Introducing GeForce GTX G-Assist", + "link": "https://youtu.be/smM-Wdk2RLQ" + } + { + "title": "The Hovering Mouse - Project McFly | Razer", + "link": "https://youtu.be/IlCx5gjAmqI" + } + { + "title": "Be the Machine | Project Venom v2", + "link": "https://youtu.be/j8UJE7DoyJ8" + } ] } -- cgit v1.2.3 From 877671523c18aad4bb5061a1a2379beb5c761e3c Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Fri, 26 Mar 2021 14:54:07 -0400 Subject: Make repository accept either user/reponame or user reponame --- bot/exts/evergreen/githubinfo.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py index 1b64b0eb..c8a6b3f7 100644 --- a/bot/exts/evergreen/githubinfo.py +++ b/bot/exts/evergreen/githubinfo.py @@ -102,12 +102,17 @@ class GithubInfo(commands.Cog): await ctx.send(embed=embed) @github_group.command(name='repository', aliases=('repo',)) - async def github_repo_info(self, ctx: commands.Context, repo: str) -> None: - """Fetches a repositories' GitHub information. The repository should look like `user/reponame`.""" + async def github_repo_info(self, ctx: commands.Context, *repo: str) -> None: + """ + Fetches a repositories' GitHub information. + + The repository should look like `user/reponame` or `user reponame`. + """ + repo = '/'.join(repo) if repo.count('/') != 1: embed = discord.Embed( title=random.choice(NEGATIVE_REPLIES), - description="The repository should look like `user/reponame`.", + description="The repository should look like `user/reponame` or `user reponame`.", colour=Colours.soft_red ) -- cgit v1.2.3 From dfe0e6001d4c1886e29b20eafacf4de1cc3a938b Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Sat, 27 Mar 2021 18:17:26 +0100 Subject: Allow automatic linking of issues everywhere We have been limiting the channels where automatic linking issues can be used in (See #566). Since we haven't seen any potential issue with it, we can allow it everywhere to avoid updating it every two days or because of missing channels. --- bot/exts/evergreen/issues.py | 6 ------ 1 file changed, 6 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index bbcbf611..6ca0c3c9 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -180,12 +180,6 @@ class Issues(commands.Cog): @commands.Cog.listener() async def on_message(self, message: discord.Message) -> None: """Command to retrieve issue(s) from a GitHub repository using automatic linking if matching #.""" - if not( - message.channel.category.id in WHITELISTED_CATEGORIES - or message.channel.id in WHITELISTED_CHANNELS_ON_MESSAGE - ): - return - message_repo_issue_map = re.findall(fr"({self.repo_regex})#(\d+)", message.content) links = [] -- cgit v1.2.3 From d03a41dfbeb3653fbc96ae4c6e3160fe581b1d16 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Sat, 27 Mar 2021 18:33:36 +0100 Subject: Remove unused WHITELISTED_CHANNELS_ON_MESSAGE constant --- bot/exts/evergreen/issues.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 6ca0c3c9..3d23b869 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -7,7 +7,7 @@ from enum import Enum import discord from discord.ext import commands, tasks -from bot.constants import Categories, Channels, Colours, ERROR_REPLIES, Emojis, Tokens, WHITELISTED_CHANNELS +from bot.constants import Categories, Colours, ERROR_REPLIES, Emojis, Tokens, WHITELISTED_CHANNELS log = logging.getLogger(__name__) @@ -26,9 +26,6 @@ if GITHUB_TOKEN := Tokens.github: WHITELISTED_CATEGORIES = ( Categories.development, Categories.devprojects, Categories.media, Categories.staff ) -WHITELISTED_CHANNELS_ON_MESSAGE = ( - Channels.organisation, Channels.mod_meta, Channels.mod_tools, Channels.staff_voice -) CODE_BLOCK_RE = re.compile( r"^`([^`\n]+)`" # Inline codeblock -- cgit v1.2.3 From 73970e6ba6909bf7ab5023377585ee12cdc77b97 Mon Sep 17 00:00:00 2001 From: Xithrius Date: Sun, 28 Mar 2021 14:45:12 -0700 Subject: Added more topics. --- bot/resources/evergreen/py_topics.yaml | 2 +- bot/resources/evergreen/starter.yaml | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/resources/evergreen/py_topics.yaml b/bot/resources/evergreen/py_topics.yaml index f3b2eaa3..7d5f7cb0 100644 --- a/bot/resources/evergreen/py_topics.yaml +++ b/bot/resources/evergreen/py_topics.yaml @@ -69,7 +69,7 @@ # game-development 660625198390837248: - - + - What is your favorite game mechanic? # microcontrollers 545603026732318730: diff --git a/bot/resources/evergreen/starter.yaml b/bot/resources/evergreen/starter.yaml index 949220f9..4fec6a10 100644 --- a/bot/resources/evergreen/starter.yaml +++ b/bot/resources/evergreen/starter.yaml @@ -31,3 +31,22 @@ - What is your favorite TV show? - What is your favorite media genre? - How many years have you spent coding? +- What book do you highly recommend everyone to read? +- What websites do you use daily to keep yourself up to date with the industry? +- What made you want to join this Discord server? +- How are you? +- What is the best advice you have ever gotten in regards to programming/software? +- What is the most satisfying thing you've done in your life? +- Who is your favorite music composer/producer/singer? +- What is your favorite song? +- What is your favorite video game? +- What are your hobbies other than programming? +- Who is your favorite Writer? +- What is your favorite movie? +- What is your favorite sport? +- What is your favorite fruit? +- What is your favorite juice? +- What is the best scenery you've ever seen? +- What artistic talents do you have? +- What is the tallest building you've entered? +- What is the oldest computer you've ever used? -- cgit v1.2.3 From ab126639380b337493606bc6c90acb5046e9f76e Mon Sep 17 00:00:00 2001 From: Boris Muratov <8bee278@gmail.com> Date: Mon, 29 Mar 2021 01:00:05 +0300 Subject: Add more game dev topics --- bot/resources/evergreen/py_topics.yaml | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'bot') diff --git a/bot/resources/evergreen/py_topics.yaml b/bot/resources/evergreen/py_topics.yaml index 7d5f7cb0..6b7e0206 100644 --- a/bot/resources/evergreen/py_topics.yaml +++ b/bot/resources/evergreen/py_topics.yaml @@ -70,6 +70,10 @@ # game-development 660625198390837248: - What is your favorite game mechanic? + - What is your favorite framework and why? + - What games do you know that were written in Python? + - What books or tutorials would you recommend for game-development beginners? + - What made you start developing games? # microcontrollers 545603026732318730: -- cgit v1.2.3 From 4bf63f11929a22ffbb9d8859b76ed5437b0a4f13 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Tue, 30 Mar 2021 16:51:29 +0200 Subject: Add missing commas to april_fools_vids.json #639 left the json file in a broken state, not letting the bot start. --- bot/resources/easter/april_fools_vids.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/resources/easter/april_fools_vids.json b/bot/resources/easter/april_fools_vids.json index d029ff86..b2cbd07b 100644 --- a/bot/resources/easter/april_fools_vids.json +++ b/bot/resources/easter/april_fools_vids.json @@ -115,15 +115,15 @@ { "title": "Introducing Gmail Motion", "link": "https://youtu.be/Bu927_ul_X0" - } + }, { "title": "Introducing GeForce GTX G-Assist", "link": "https://youtu.be/smM-Wdk2RLQ" - } + }, { "title": "The Hovering Mouse - Project McFly | Razer", "link": "https://youtu.be/IlCx5gjAmqI" - } + }, { "title": "Be the Machine | Project Venom v2", "link": "https://youtu.be/j8UJE7DoyJ8" -- cgit v1.2.3 From e3b7b3bc5b56b805112558377e25e2537cc86083 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 2 Apr 2021 14:53:27 +0100 Subject: Don't allow users to run the issue command in DMs, given error feedback. --- bot/exts/evergreen/issues.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 1f22f287..0f0be33a 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -7,7 +7,16 @@ from enum import Enum import discord from discord.ext import commands, tasks -from bot.constants import Categories, Channels, Colours, ERROR_REPLIES, Emojis, Tokens, WHITELISTED_CHANNELS +from bot.constants import ( + Categories, + Channels, + Colours, + ERROR_REPLIES, + Emojis, + NEGATIVE_REPLIES, + Tokens, + WHITELISTED_CHANNELS +) log = logging.getLogger(__name__) @@ -148,11 +157,20 @@ class Issues(commands.Cog): user: str = "python-discord" ) -> None: """Command to retrieve issue(s) from a GitHub repository.""" - if not( + if not ctx.guild or not( ctx.channel.category.id in WHITELISTED_CATEGORIES or ctx.channel.id in WHITELISTED_CHANNELS ): - return + await ctx.send( + embed=discord.Embed( + title=random.choice(NEGATIVE_REPLIES), + description=( + "You can't run this command in this channel. " + f"Try again in {Channels.community_bot_commands}" + ), + colour=discord.Colour.red() + ) + ) result = await self.fetch_issues(set(numbers), repository, user) -- cgit v1.2.3 From 6a8a582c49c2a3d97a2a061eca157502acb0618d Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 2 Apr 2021 17:02:47 +0100 Subject: Send error embed when a user tries to retrieve an issue in DMs --- bot/exts/evergreen/issues.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index ca0e4494..4a73d20b 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -168,11 +168,12 @@ class Issues(commands.Cog): title=random.choice(NEGATIVE_REPLIES), description=( "You can't run this command in this channel. " - f"Try again in {Channels.community_bot_commands}" + f"Try again in <#{Channels.community_bot_commands}>" ), colour=discord.Colour.red() ) ) + return result = await self.fetch_issues(set(numbers), repository, user) @@ -198,12 +199,8 @@ class Issues(commands.Cog): @commands.Cog.listener() async def on_message(self, message: discord.Message) -> None: """Command to retrieve issue(s) from a GitHub repository using automatic linking if matching #.""" - # Ignore messages from DMs - if not message.guild: - return - - # Ignore messages not in whitelisted categories / channels - if not ( + # Ignore messages not in whitelisted categories / channels, only when in guild. + if message.guild and not ( message.channel.category.id in WHITELISTED_CATEGORIES or message.channel.id in WHITELISTED_CHANNELS_ON_MESSAGE ): @@ -213,6 +210,18 @@ class Issues(commands.Cog): links = [] if message_repo_issue_map: + if not message.guild: + await message.channel.send( + embed=discord.Embed( + title=random.choice(NEGATIVE_REPLIES), + description=( + "You can't retreive issues from DMs. " + f"Try again in <#{Channels.community_bot_commands}>" + ), + colour=discord.Colour.red() + ) + ) + return for repo_issue in message_repo_issue_map: if not self.check_in_block(message, " ".join(repo_issue)): result = await self.fetch_issues({repo_issue[1]}, repo_issue[0], "python-discord") -- cgit v1.2.3 From 4e151344832b2e17a188c943aa5eedc51bead3cc Mon Sep 17 00:00:00 2001 From: Sougata das Date: Fri, 2 Apr 2021 23:32:53 +0530 Subject: Update battleship.py --- bot/exts/evergreen/battleship.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/battleship.py b/bot/exts/evergreen/battleship.py index fa3fb35c..1681434f 100644 --- a/bot/exts/evergreen/battleship.py +++ b/bot/exts/evergreen/battleship.py @@ -227,7 +227,7 @@ class Game: if message.content.lower() == "surrender": self.surrender = True return True - self.match = re.match("([A-J]|[a-j]) ?((10)|[1-9])", message.content.strip()) + self.match = re.fullmatch("([A-J]|[a-j]) ?((10)|[1-9])", message.content.strip()) if not self.match: self.bot.loop.create_task(message.add_reaction(CROSS_EMOJI)) return bool(self.match) -- cgit v1.2.3 From 50cd34e73d77bf71fe214250d5f20a2b4d98664d Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Mon, 5 Apr 2021 15:01:58 +0100 Subject: fix: use get_user in 8bitify to avoid events issues --- bot/exts/evergreen/8bitify.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/8bitify.py b/bot/exts/evergreen/8bitify.py index 54e68f80..ee2b4034 100644 --- a/bot/exts/evergreen/8bitify.py +++ b/bot/exts/evergreen/8bitify.py @@ -25,7 +25,8 @@ class EightBitify(commands.Cog): async def eightbit_command(self, ctx: commands.Context) -> None: """Pixelates your avatar and changes the palette to an 8bit one.""" async with ctx.typing(): - image_bytes = await ctx.author.avatar_url.read() + author = await self.bot.get_user(ctx.author.id) + image_bytes = await author.avatar_url.read() avatar = Image.open(BytesIO(image_bytes)) avatar = avatar.convert("RGBA").resize((1024, 1024)) -- cgit v1.2.3 From 9edeff2eea5df363446e98d2905283562849619b Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 5 Apr 2021 16:08:24 +0200 Subject: Issues: remove duplicates --- bot/exts/evergreen/issues.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 3d23b869..d7e29a90 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -181,6 +181,9 @@ class Issues(commands.Cog): links = [] if message_repo_issue_map: + # Remove duplicates + message_repo_issue_map = set(message_repo_issue_map) + for repo_issue in message_repo_issue_map: if not self.check_in_block(message, " ".join(repo_issue)): result = await self.fetch_issues({repo_issue[1]}, repo_issue[0], "python-discord") -- cgit v1.2.3 From 0e2422f7caaec73fbee9708c507d9be23635dd78 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 5 Apr 2021 16:43:28 +0200 Subject: Issues: limit results to 5 --- bot/exts/evergreen/issues.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index d7e29a90..afaa7012 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -15,8 +15,6 @@ BAD_RESPONSE = { 404: "Issue/pull request not located! Please enter a valid number!", 403: "Rate limit has been hit! Please try again later!" } - -MAX_REQUESTS = 10 REQUEST_HEADERS = dict() REPOS_API = "https://api.github.com/orgs/{org}/repos" @@ -33,6 +31,9 @@ CODE_BLOCK_RE = re.compile( re.DOTALL | re.MULTILINE ) +# Maximum number of issues in one message +MAXIMUM_ISSUES = 5 + class FetchIssueErrors(Enum): """Errors returned in fetch issues.""" @@ -83,7 +84,7 @@ class Issues(commands.Cog): if not numbers: return FetchIssueErrors.value_error - if len(numbers) > MAX_REQUESTS: + if len(numbers) > MAXIMUM_ISSUES: return FetchIssueErrors.max_requests for number in numbers: @@ -162,7 +163,7 @@ class Issues(commands.Cog): embed = discord.Embed( title=random.choice(ERROR_REPLIES), color=Colours.soft_red, - description=f"Too many issues/PRs! (maximum of {MAX_REQUESTS})" + description=f"Too many issues/PRs! (maximum of {MAXIMUM_ISSUES})" ) await ctx.send(embed=embed) @@ -184,6 +185,15 @@ class Issues(commands.Cog): # Remove duplicates message_repo_issue_map = set(message_repo_issue_map) + if len(message_repo_issue_map) > MAXIMUM_ISSUES: + embed = discord.Embed( + title=random.choice(ERROR_REPLIES), + color=Colours.soft_red, + description=f"Too many issues/PRs! (maximum of {MAXIMUM_ISSUES})" + ) + await message.channel.send(embed=embed) + return + for repo_issue in message_repo_issue_map: if not self.check_in_block(message, " ".join(repo_issue)): result = await self.fetch_issues({repo_issue[1]}, repo_issue[0], "python-discord") -- cgit v1.2.3 From 30756d4dcc2dcdba334cc3493d82eccdc9c6aded Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Mon, 5 Apr 2021 15:45:10 +0100 Subject: fix: use api fetch not cache get --- bot/exts/evergreen/8bitify.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/8bitify.py b/bot/exts/evergreen/8bitify.py index ee2b4034..7eb4d313 100644 --- a/bot/exts/evergreen/8bitify.py +++ b/bot/exts/evergreen/8bitify.py @@ -25,7 +25,7 @@ class EightBitify(commands.Cog): async def eightbit_command(self, ctx: commands.Context) -> None: """Pixelates your avatar and changes the palette to an 8bit one.""" async with ctx.typing(): - author = await self.bot.get_user(ctx.author.id) + author = await self.bot.fetch_user(ctx.author.id) image_bytes = await author.avatar_url.read() avatar = Image.open(BytesIO(image_bytes)) avatar = avatar.convert("RGBA").resize((1024, 1024)) -- cgit v1.2.3 From 08b1348b33d2d865987f2677a68ba62645db2abe Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Tue, 6 Apr 2021 10:05:40 +0200 Subject: Rewrite issue cog - Switch to a dataclass based communication - Use GitHub headers when querying the repo_regex - Properly handle non-200 return codes - Use @whitelist_override --- bot/exts/evergreen/issues.py | 205 +++++++++++++++++++++++++------------------ 1 file changed, 119 insertions(+), 86 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index afaa7012..dce11678 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -2,12 +2,13 @@ import logging import random import re import typing as t -from enum import Enum +from dataclasses import dataclass import discord from discord.ext import commands, tasks from bot.constants import Categories, Colours, ERROR_REPLIES, Emojis, Tokens, WHITELISTED_CHANNELS +from bot.utils.decorators import whitelist_override log = logging.getLogger(__name__) @@ -17,7 +18,10 @@ BAD_RESPONSE = { } REQUEST_HEADERS = dict() -REPOS_API = "https://api.github.com/orgs/{org}/repos" +REPOSITORY_ENDPOINT = "https://api.github.com/orgs/{org}/repos" +ISSUE_ENDPOINT = "https://api.github.com/repos/{user}/{repository}/issues/{number}" +PR_MERGE_ENDPOINT = "https://api.github.com/repos/{user}/{repository}/pulls/{number}/merge" + if GITHUB_TOKEN := Tokens.github: REQUEST_HEADERS["Authorization"] = f"token {GITHUB_TOKEN}" @@ -35,11 +39,23 @@ CODE_BLOCK_RE = re.compile( MAXIMUM_ISSUES = 5 -class FetchIssueErrors(Enum): - """Errors returned in fetch issues.""" +@dataclass +class FetchError: + """Dataclass representing an error while fetching an issue.""" + + return_code: int + message: str + - value_error = "Numbers not found." - max_requests = "Max requests hit." +@dataclass +class IssueState: + """Dataclass representing the state of an issue.""" + + repository: str + number: int + url: str + title: str + icon_url: str class Issues(commands.Cog): @@ -48,19 +64,27 @@ class Issues(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot self.repos = [] + self.repo_regex = None self.get_pydis_repos.start() @tasks.loop(minutes=30) async def get_pydis_repos(self) -> None: - """Get all python-discord repositories on github.""" - async with self.bot.http_session.get(REPOS_API.format(org="python-discord")) as resp: + """ + Get all python-discord repositories on github. + + This task will update a pipe-separated list of repositories in self.repo_regex. + """ + async with self.bot.http_session.get( + REPOSITORY_ENDPOINT.format(org="python-discord"), + headers=REQUEST_HEADERS + ) as resp: if resp.status == 200: data = await resp.json() for repo in data: self.repos.append(repo["full_name"].split("/")[1]) self.repo_regex = "|".join(self.repos) else: - log.debug(f"Failed to get latest Pydis repositories. Status code {resp.status}") + log.warning(f"Failed to get latest Pydis repositories. Status code {resp.status}") @staticmethod def check_in_block(message: discord.Message, repo_issue: str) -> bool: @@ -75,70 +99,85 @@ class Issues(commands.Cog): async def fetch_issues( self, - numbers: set, + number: int, repository: str, user: str - ) -> t.Union[FetchIssueErrors, str, list]: - """Retrieve issue(s) from a GitHub repository.""" - links = [] - if not numbers: - return FetchIssueErrors.value_error - - if len(numbers) > MAXIMUM_ISSUES: - return FetchIssueErrors.max_requests - - for number in numbers: - url = f"https://api.github.com/repos/{user}/{repository}/issues/{number}" - merge_url = f"https://api.github.com/repos/{user}/{repository}/pulls/{number}/merge" - log.trace(f"Querying GH issues API: {url}") - async with self.bot.http_session.get(url, headers=REQUEST_HEADERS) as r: - json_data = await r.json() - - if r.status in BAD_RESPONSE: - log.warning(f"Received response {r.status} from: {url}") - return f"[{str(r.status)}] #{number} {BAD_RESPONSE.get(r.status)}" - - # The initial API request is made to the issues API endpoint, which will return information - # if the issue or PR is present. However, the scope of information returned for PRs differs - # from issues: if the 'issues' key is present in the response then we can pull the data we - # need from the initial API call. - if "issues" in json_data.get("html_url"): + ) -> t.Union[IssueState, FetchError]: + """ + Retrieve an issue from a GitHub repository. + + returns IssueState on success, FetchError on failure. + """ + url = ISSUE_ENDPOINT.format(user=user, repository=repository, number=number) + merge_url = PR_MERGE_ENDPOINT.format(user=user, repository=repository, number=number) + log.trace(f"Querying GH issues API: {url}") + + async with self.bot.http_session.get(url, headers=REQUEST_HEADERS) as r: + json_data = await r.json() + + if r.status == 403: + if "X-RateLimit-Remaining" in r.headers and r.headers["X-RateLimit-Remaining"] == "0": + log.info(f"Ratelimit reached while fetching {url}") + return FetchError(403, "Ratelimit reached, please retry in a few minutes.") + return FetchError(403, "Cannot access issue.") + elif r.status in (404, 410): + return FetchError(r.status, "Issue not found.") + elif r.status != 200: + return FetchError(r.status, "Error while fetching issue.") + + # The initial API request is made to the issues API endpoint, which will return information + # if the issue or PR is present. However, the scope of information returned for PRs differs + # from issues: if the 'issues' key is present in the response then we can pull the data we + # need from the initial API call. + if "issues" in json_data.get("html_url"): + if json_data.get("state") == "open": + icon_url = Emojis.issue + else: + icon_url = Emojis.issue_closed + + # If the 'issues' key is not contained in the API response and there is no error code, then + # we know that a PR has been requested and a call to the pulls API endpoint is necessary + # to get the desired information for the PR. + else: + log.trace(f"PR provided, querying GH pulls API for additional information: {merge_url}") + async with self.bot.http_session.get(merge_url) as m: if json_data.get("state") == "open": - icon_url = Emojis.issue + icon_url = Emojis.pull_request + # When the status is 204 this means that the state of the PR is merged + elif m.status == 204: + icon_url = Emojis.merge else: - icon_url = Emojis.issue_closed - - # If the 'issues' key is not contained in the API response and there is no error code, then - # we know that a PR has been requested and a call to the pulls API endpoint is necessary - # to get the desired information for the PR. - else: - log.trace(f"PR provided, querying GH pulls API for additional information: {merge_url}") - async with self.bot.http_session.get(merge_url) as m: - if json_data.get("state") == "open": - icon_url = Emojis.pull_request - # When the status is 204 this means that the state of the PR is merged - elif m.status == 204: - icon_url = Emojis.merge - else: - icon_url = Emojis.pull_request_closed + icon_url = Emojis.pull_request_closed - issue_url = json_data.get("html_url") - links.append([icon_url, f"[{repository}] #{number} {json_data.get('title')}", issue_url]) + issue_url = json_data.get("html_url") - return links + return IssueState(repository, number, issue_url, json_data.get('title', ''), icon_url) @staticmethod - def get_embed(result: list, user: str = "python-discord", repository: str = "") -> discord.Embed: - """Get Response Embed.""" - description_list = ["{0} [{1}]({2})".format(*link) for link in result] + def format_embed( + results: t.List[t.Union[IssueState, FetchError]], + user: str, + repository: t.Optional[str] = None + ) -> discord.Embed: + """Take a list of IssueState or FetchError and format a Discord embed for them.""" + description_list = [] + + for result in results: + if isinstance(result, IssueState): + description_list.append(f"{result.icon_url} [{result.title}]({result.url})") + elif isinstance(result, FetchError): + description_list.append(f"[{result.return_code}] {result.message}") + resp = discord.Embed( colour=Colours.bright_green, description='\n'.join(description_list) ) - resp.set_author(name="GitHub", url=f"https://github.com/{user}/{repository}") + embed_url = f"https://github.com/{user}/{repository}" if repository else f"https://github.com/{user}" + resp.set_author(name="GitHub", url=embed_url) return resp + @whitelist_override(channels=WHITELISTED_CHANNELS, categories=WHITELISTED_CATEGORIES) @commands.command(aliases=("pr",)) async def issue( self, @@ -148,62 +187,56 @@ class Issues(commands.Cog): user: str = "python-discord" ) -> None: """Command to retrieve issue(s) from a GitHub repository.""" - if not( - ctx.channel.category.id in WHITELISTED_CATEGORIES - or ctx.channel.id in WHITELISTED_CHANNELS - ): - return - - result = await self.fetch_issues(set(numbers), repository, user) - - if result == FetchIssueErrors.value_error: - await ctx.invoke(self.bot.get_command('help'), 'issue') + # Remove duplicates + numbers = set(numbers) - elif result == FetchIssueErrors.max_requests: + if len(numbers) > MAXIMUM_ISSUES: embed = discord.Embed( title=random.choice(ERROR_REPLIES), color=Colours.soft_red, description=f"Too many issues/PRs! (maximum of {MAXIMUM_ISSUES})" ) await ctx.send(embed=embed) + await ctx.invoke(self.bot.get_command('help'), 'issue') - elif isinstance(result, list): - # Issue/PR format: emoji to show if open/closed/merged, number and the title as a singular link. - resp = self.get_embed(result, user, repository) - await ctx.send(embed=resp) - - elif isinstance(result, str): - await ctx.send(result) + results = [await self.fetch_issues(number, repository, user) for number in numbers] + await ctx.send(embed=self.format_embed(results)) @commands.Cog.listener() async def on_message(self, message: discord.Message) -> None: """Command to retrieve issue(s) from a GitHub repository using automatic linking if matching #.""" - message_repo_issue_map = re.findall(fr"({self.repo_regex})#(\d+)", message.content) + if not self.repo_regex: + log.warning("repo_regex isn't ready, cannot look for issues.") + return + + # `issues` will hold a list of two element tuples `(repository, issue_number)` + issues = re.findall(fr"({self.repo_regex})#(\d+)", message.content) links = [] - if message_repo_issue_map: + if issues: + log.trace(f"Found {issues = }") # Remove duplicates - message_repo_issue_map = set(message_repo_issue_map) + issues = set(issues) - if len(message_repo_issue_map) > MAXIMUM_ISSUES: + if len(issues) > MAXIMUM_ISSUES: embed = discord.Embed( title=random.choice(ERROR_REPLIES), color=Colours.soft_red, description=f"Too many issues/PRs! (maximum of {MAXIMUM_ISSUES})" ) - await message.channel.send(embed=embed) + await message.channel.send(embed=embed).delete(delay=5) return - for repo_issue in message_repo_issue_map: + for repo_issue in issues: if not self.check_in_block(message, " ".join(repo_issue)): - result = await self.fetch_issues({repo_issue[1]}, repo_issue[0], "python-discord") - if isinstance(result, list): - links.extend(result) + result = await self.fetch_issues(repo_issue[1], repo_issue[0], "python-discord") + if isinstance(result, IssueState): + links.append(result) if not links: return - resp = self.get_embed(links, "python-discord") + resp = self.format_embed(links, "python-discord") await message.channel.send(embed=resp) -- cgit v1.2.3 From f8e14d089e87cc2628a9087a60bf0c3cc6eefc39 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Tue, 6 Apr 2021 10:13:31 +0200 Subject: Issues: ignore bots --- bot/exts/evergreen/issues.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index dce11678..7e9defbe 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -209,6 +209,10 @@ class Issues(commands.Cog): log.warning("repo_regex isn't ready, cannot look for issues.") return + # Ignore bots + if message.author.bot: + return + # `issues` will hold a list of two element tuples `(repository, issue_number)` issues = re.findall(fr"({self.repo_regex})#(\d+)", message.content) links = [] -- cgit v1.2.3 From fd2ff1d06e31a9b0f412c2a81e373bf46fe192f7 Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Thu, 8 Apr 2021 03:15:47 +0100 Subject: increase the number of repos per page we fetch from github --- bot/exts/evergreen/issues.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 4a73d20b..58f9d7aa 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -28,7 +28,7 @@ BAD_RESPONSE = { MAX_REQUESTS = 10 REQUEST_HEADERS = dict() -REPOS_API = "https://api.github.com/orgs/{org}/repos" +REPOS_API = "https://api.github.com/orgs/{org}/repos?per_page=100" if GITHUB_TOKEN := Tokens.github: REQUEST_HEADERS["Authorization"] = f"token {GITHUB_TOKEN}" -- cgit v1.2.3 From 291997462779b79ff088432d7333bee9b2ff2f2c Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Thu, 8 Apr 2021 09:07:01 +0200 Subject: Refactor issue cog Co-authored-by: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> --- bot/exts/evergreen/issues.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 7255d450..bcaeee1f 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -115,7 +115,7 @@ class Issues(commands.Cog): """ Retrieve an issue from a GitHub repository. - returns IssueState on success, FetchError on failure. + Returns IssueState on success, FetchError on failure. """ url = ISSUE_ENDPOINT.format(user=user, repository=repository, number=number) merge_url = PR_MERGE_ENDPOINT.format(user=user, repository=repository, number=number) @@ -125,7 +125,7 @@ class Issues(commands.Cog): json_data = await r.json() if r.status == 403: - if "X-RateLimit-Remaining" in r.headers and r.headers["X-RateLimit-Remaining"] == "0": + if r.headers.get("X-RateLimit-Remaining") == "0": log.info(f"Ratelimit reached while fetching {url}") return FetchError(403, "Ratelimit reached, please retry in a few minutes.") return FetchError(403, "Cannot access issue.") @@ -138,7 +138,7 @@ class Issues(commands.Cog): # if the issue or PR is present. However, the scope of information returned for PRs differs # from issues: if the 'issues' key is present in the response then we can pull the data we # need from the initial API call. - if "issues" in json_data.get("html_url"): + if "issues" in json_data["html_url"]: if json_data.get("state") == "open": icon_url = Emojis.issue else: @@ -251,7 +251,7 @@ class Issues(commands.Cog): color=Colours.soft_red, description=f"Too many issues/PRs! (maximum of {MAXIMUM_ISSUES})" ) - await message.channel.send(embed=embed).delete(delay=5) + await message.channel.send(embed=embed, delete_after=5) return for repo_issue in issues: -- cgit v1.2.3 From cd0153d36f081f2a0a41b610eac86ff52211e5c5 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Thu, 8 Apr 2021 09:10:48 +0200 Subject: Issues: make use of invoke_help_command Co-authored-by: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> --- bot/exts/evergreen/issues.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index bcaeee1f..d8b373d7 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -18,6 +18,7 @@ from bot.constants import ( WHITELISTED_CHANNELS ) from bot.utils.decorators import whitelist_override +from bot.utils.extensions import invoke_help_command log = logging.getLogger(__name__) @@ -206,7 +207,7 @@ class Issues(commands.Cog): description=f"Too many issues/PRs! (maximum of {MAXIMUM_ISSUES})" ) await ctx.send(embed=embed) - await ctx.invoke(self.bot.get_command('help'), 'issue') + await invoke_help_command(ctx) results = [await self.fetch_issues(number, repository, user) for number in numbers] await ctx.send(embed=self.format_embed(results, user, repository)) -- cgit v1.2.3 From a52eeb5e253a31c447d28fe663f3a60c0c9efcdc Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Thu, 8 Apr 2021 11:35:43 +0200 Subject: Issues: add accept header --- bot/exts/evergreen/issues.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index d8b373d7..5ea8a6bf 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -26,7 +26,9 @@ BAD_RESPONSE = { 404: "Issue/pull request not located! Please enter a valid number!", 403: "Rate limit has been hit! Please try again later!" } -REQUEST_HEADERS = dict() +REQUEST_HEADERS = { + "Accept": "application/vnd.github.v3+json" +} REPOSITORY_ENDPOINT = "https://api.github.com/orgs/{org}/repos" ISSUE_ENDPOINT = "https://api.github.com/repos/{user}/{repository}/issues/{number}" -- cgit v1.2.3 From 37a3b571467bb889526b7d21db17f7644453a85e Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Thu, 8 Apr 2021 11:39:45 +0200 Subject: Issues: icon_url -> emoji_url --- bot/exts/evergreen/issues.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 5ea8a6bf..9b04c8c1 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -67,7 +67,7 @@ class IssueState: number: int url: str title: str - icon_url: str + emoji_url: str class Issues(commands.Cog): @@ -176,7 +176,7 @@ class Issues(commands.Cog): for result in results: if isinstance(result, IssueState): - description_list.append(f"{result.icon_url} [{result.title}]({result.url})") + description_list.append(f"{result.emoji_url} [{result.title}]({result.url})") elif isinstance(result, FetchError): description_list.append(f"[{result.return_code}] {result.message}") -- cgit v1.2.3 From c272bdf0149d741efad477b77a7e123a42569f68 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Thu, 8 Apr 2021 11:41:23 +0200 Subject: Issues: add red cross emoji for failed issues Co-authored-by: Shivansh-007 --- bot/exts/evergreen/issues.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 83cafcc8..5ad13628 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -178,7 +178,7 @@ class Issues(commands.Cog): if isinstance(result, IssueState): description_list.append(f"{result.emoji_url} [{result.title}]({result.url})") elif isinstance(result, FetchError): - description_list.append(f"[{result.return_code}] {result.message}") + description_list.append(f":x: [{result.return_code}] {result.message}") resp = discord.Embed( colour=Colours.bright_green, -- cgit v1.2.3 From 0ff42e4e2197822bd1e1a63e5ebd73d75588b1eb Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Thu, 8 Apr 2021 11:51:16 +0200 Subject: Issues: emoji_url -> emoji --- bot/exts/evergreen/issues.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 83cafcc8..10aa347d 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -67,7 +67,7 @@ class IssueState: number: int url: str title: str - emoji_url: str + emoji: str class Issues(commands.Cog): @@ -143,9 +143,9 @@ class Issues(commands.Cog): # need from the initial API call. if "issues" in json_data["html_url"]: if json_data.get("state") == "open": - icon_url = Emojis.issue + emoji = Emojis.issue else: - icon_url = Emojis.issue_closed + emoji = Emojis.issue_closed # If the 'issues' key is not contained in the API response and there is no error code, then # we know that a PR has been requested and a call to the pulls API endpoint is necessary @@ -154,16 +154,16 @@ class Issues(commands.Cog): log.trace(f"PR provided, querying GH pulls API for additional information: {merge_url}") async with self.bot.http_session.get(merge_url) as m: if json_data.get("state") == "open": - icon_url = Emojis.pull_request + emoji = Emojis.pull_request # When the status is 204 this means that the state of the PR is merged elif m.status == 204: - icon_url = Emojis.merge + emoji = Emojis.merge else: - icon_url = Emojis.pull_request_closed + emoji = Emojis.pull_request_closed issue_url = json_data.get("html_url") - return IssueState(repository, number, issue_url, json_data.get('title', ''), icon_url) + return IssueState(repository, number, issue_url, json_data.get('title', ''), emoji) @staticmethod def format_embed( @@ -176,7 +176,7 @@ class Issues(commands.Cog): for result in results: if isinstance(result, IssueState): - description_list.append(f"{result.emoji_url} [{result.title}]({result.url})") + description_list.append(f"{result.emoji} [{result.title}]({result.url})") elif isinstance(result, FetchError): description_list.append(f"[{result.return_code}] {result.message}") -- cgit v1.2.3 From c94a45a10bac63eff1ce066707fe2df0b1243daa Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Thu, 8 Apr 2021 12:37:14 -0400 Subject: Use PRDraft emoji when the pr is a draft pr for the .issue|.pr command --- bot/constants.py | 1 + bot/exts/evergreen/issues.py | 13 ++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index 416dd0e7..e59fa641 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -168,6 +168,7 @@ class Emojis: issue_closed = "<:IssueClosed:629695470570307614>" pull_request = "<:PROpen:629695470175780875>" pull_request_closed = "<:PRClosed:629695470519713818>" + pull_request_draft = "<:PRDraft:829755345425399848>" merge = "<:PRMerged:629695470570176522>" number_emojis = { diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 4a73d20b..e83f1a3e 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -100,7 +100,7 @@ class Issues(commands.Cog): for number in numbers: url = f"https://api.github.com/repos/{user}/{repository}/issues/{number}" - merge_url = f"https://api.github.com/repos/{user}/{repository}/pulls/{number}/merge" + pulls_url = f"https://api.github.com/repos/{user}/{repository}/pulls/{number}" log.trace(f"Querying GH issues API: {url}") async with self.bot.http_session.get(url, headers=REQUEST_HEADERS) as r: json_data = await r.json() @@ -123,12 +123,15 @@ class Issues(commands.Cog): # we know that a PR has been requested and a call to the pulls API endpoint is necessary # to get the desired information for the PR. else: - log.trace(f"PR provided, querying GH pulls API for additional information: {merge_url}") - async with self.bot.http_session.get(merge_url) as m: - if json_data.get("state") == "open": + log.trace(f"PR provided, querying GH pulls API for additional information: {pulls_url}") + async with self.bot.http_session.get(pulls_url) as p: + pull_data = await p.json() + if pull_data["draft"]: + icon_url = Emojis.pull_request_draft + elif pull_data["state"] == "open": icon_url = Emojis.pull_request # When the status is 204 this means that the state of the PR is merged - elif m.status == 204: + elif pull_data["merged_at"] is not None: icon_url = Emojis.merge else: icon_url = Emojis.pull_request_closed -- cgit v1.2.3 From 22ba746b3892857d1b2050eab7c1c72cd435ef48 Mon Sep 17 00:00:00 2001 From: onerandomusername <71233171+onerandomusername@users.noreply.github.com> Date: Thu, 8 Apr 2021 13:01:36 -0400 Subject: Remove topic that doesn't make sense in discord Removed the `Name one thing you like about a person to your right.` topic as it doesn't make sense in discord --- bot/resources/evergreen/starter.yaml | 1 - 1 file changed, 1 deletion(-) (limited to 'bot') diff --git a/bot/resources/evergreen/starter.yaml b/bot/resources/evergreen/starter.yaml index 4fec6a10..6b0de0ef 100644 --- a/bot/resources/evergreen/starter.yaml +++ b/bot/resources/evergreen/starter.yaml @@ -6,7 +6,6 @@ - "What is better: Milk, Dark or White chocolate?" - What is your favourite holiday? - If you could have any superpower, what would it be? -- Name one thing you like about a person to your right. - If you could be anyone else for one day, who would it be? - What Easter tradition do you enjoy most? - What is the best gift you've been given? -- cgit v1.2.3 From 6b6e2bd0ec58197a88ca9fdc8cc3eeccbf8ebab5 Mon Sep 17 00:00:00 2001 From: Shakya Majumdar Date: Thu, 8 Apr 2021 23:45:35 +0530 Subject: Add latex cog --- Pipfile | 1 + Pipfile.lock | 339 +++++++++++++++++++++++++++++++------------- bot/exts/evergreen/latex.py | 57 ++++++++ 3 files changed, 300 insertions(+), 97 deletions(-) create mode 100644 bot/exts/evergreen/latex.py (limited to 'bot') diff --git a/Pipfile b/Pipfile index 25e96c92..f20f6845 100644 --- a/Pipfile +++ b/Pipfile @@ -15,6 +15,7 @@ PyYAML = "~=5.4" "discord.py" = {extras = ["voice"], version = "~=1.5.1"} async-rediscache = {extras = ["fakeredis"], version = "~=0.1.4"} emojis = "~=0.6.0" +matplotlib = "~=3.4.1" [dev-packages] flake8 = "~=3.8" diff --git a/Pipfile.lock b/Pipfile.lock index 64cae8cc..d7fc6b27 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "427595155192c24bd1b3de5e8ffc242dc55f4390b9b90257179b5fa76457b611" + "sha256": "03b52d5b9fdfa6d037780d5aa2896c82fd5454a40bd69acf7e9b0e129557dbd5" }, "pipfile-spec": 6, "requires": { @@ -40,6 +40,7 @@ "sha256:c506853ba52e516b264b106321c424d03f3ddef2813246432fa9d1cefd361c81", "sha256:fb83326d8295e8840e4ba774edf346e87eca78ba8a89c55d2690352842c15ba5" ], + "markers": "python_full_version >= '3.5.3'", "version": "==3.6.3" }, "aioredis": { @@ -73,6 +74,7 @@ "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f", "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3" ], + "markers": "python_full_version >= '3.5.3'", "version": "==3.0.1" }, "attrs": { @@ -80,6 +82,7 @@ "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6", "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==20.3.0" }, "beautifulsoup4": { @@ -147,6 +150,13 @@ ], "version": "==3.0.4" }, + "cycler": { + "hashes": [ + "sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d", + "sha256:cd7b2d1018258d7247a71425e9f26463dfb444d411c39569972f4ce586b0c9d8" + ], + "version": "==0.10.0" + }, "discord.py": { "extras": [ "voice" @@ -225,6 +235,7 @@ "sha256:f52010e0a44e3d8530437e7da38d11fb822acfb0d5b12e9cd5ba655509937ca0", "sha256:f8196f739092a78e4f6b1b2172679ed3343c39c61a3e9d722ce6fcf1dac2824a" ], + "markers": "python_version >= '3.6'", "version": "==2.0.0" }, "idna": { @@ -232,8 +243,72 @@ "sha256:5205d03e7bcbb919cc9c19885f9920d622ca52448306f2377daede5cf3faac16", "sha256:c5b02147e01ea9920e6b0a3f1f7bb833612d507592c837a6c49552768f4054e1" ], + "markers": "python_version >= '3.4'", "version": "==3.1" }, + "kiwisolver": { + "hashes": [ + "sha256:0cd53f403202159b44528498de18f9285b04482bab2a6fc3f5dd8dbb9352e30d", + "sha256:1e1bc12fb773a7b2ffdeb8380609f4f8064777877b2225dec3da711b421fda31", + "sha256:225e2e18f271e0ed8157d7f4518ffbf99b9450fca398d561eb5c4a87d0986dd9", + "sha256:232c9e11fd7ac3a470d65cd67e4359eee155ec57e822e5220322d7b2ac84fbf0", + "sha256:31dfd2ac56edc0ff9ac295193eeaea1c0c923c0355bf948fbd99ed6018010b72", + "sha256:33449715e0101e4d34f64990352bce4095c8bf13bed1b390773fc0a7295967b3", + "sha256:401a2e9afa8588589775fe34fc22d918ae839aaaf0c0e96441c0fdbce6d8ebe6", + "sha256:44a62e24d9b01ba94ae7a4a6c3fb215dc4af1dde817e7498d901e229aaf50e4e", + "sha256:50af681a36b2a1dee1d3c169ade9fdc59207d3c31e522519181e12f1b3ba7000", + "sha256:563c649cfdef27d081c84e72a03b48ea9408c16657500c312575ae9d9f7bc1c3", + "sha256:5989db3b3b34b76c09253deeaf7fbc2707616f130e166996606c284395da3f18", + "sha256:5a7a7dbff17e66fac9142ae2ecafb719393aaee6a3768c9de2fd425c63b53e21", + "sha256:5c3e6455341008a054cccee8c5d24481bcfe1acdbc9add30aa95798e95c65621", + "sha256:5f6ccd3dd0b9739edcf407514016108e2280769c73a85b9e59aa390046dbf08b", + "sha256:72c99e39d005b793fb7d3d4e660aed6b6281b502e8c1eaf8ee8346023c8e03bc", + "sha256:78751b33595f7f9511952e7e60ce858c6d64db2e062afb325985ddbd34b5c131", + "sha256:834ee27348c4aefc20b479335fd422a2c69db55f7d9ab61721ac8cd83eb78882", + "sha256:8be8d84b7d4f2ba4ffff3665bcd0211318aa632395a1a41553250484a871d454", + "sha256:950a199911a8d94683a6b10321f9345d5a3a8433ec58b217ace979e18f16e248", + "sha256:a357fd4f15ee49b4a98b44ec23a34a95f1e00292a139d6015c11f55774ef10de", + "sha256:a53d27d0c2a0ebd07e395e56a1fbdf75ffedc4a05943daf472af163413ce9598", + "sha256:acef3d59d47dd85ecf909c359d0fd2c81ed33bdff70216d3956b463e12c38a54", + "sha256:b38694dcdac990a743aa654037ff1188c7a9801ac3ccc548d3341014bc5ca278", + "sha256:b9edd0110a77fc321ab090aaa1cfcaba1d8499850a12848b81be2222eab648f6", + "sha256:c08e95114951dc2090c4a630c2385bef681cacf12636fb0241accdc6b303fd81", + "sha256:c5518d51a0735b1e6cee1fdce66359f8d2b59c3ca85dc2b0813a8aa86818a030", + "sha256:c8fd0f1ae9d92b42854b2979024d7597685ce4ada367172ed7c09edf2cef9cb8", + "sha256:ca3820eb7f7faf7f0aa88de0e54681bddcb46e485beb844fcecbcd1c8bd01689", + "sha256:cf8b574c7b9aa060c62116d4181f3a1a4e821b2ec5cbfe3775809474113748d4", + "sha256:d3155d828dec1d43283bd24d3d3e0d9c7c350cdfcc0bd06c0ad1209c1bbc36d0", + "sha256:f8d6f8db88049a699817fd9178782867bf22283e3813064302ac59f61d95be05", + "sha256:fd34fbbfbc40628200730bc1febe30631347103fc8d3d4fa012c21ab9c11eca9" + ], + "markers": "python_version >= '3.6'", + "version": "==1.3.1" + }, + "matplotlib": { + "hashes": [ + "sha256:1f83a32e4b6045191f9d34e4dc68c0a17c870b57ef9cca518e516da591246e79", + "sha256:2eee37340ca1b353e0a43a33da79d0cd4bcb087064a0c3c3d1329cdea8fbc6f3", + "sha256:53ceb12ef44f8982b45adc7a0889a7e2df1d758e8b360f460e435abe8a8cd658", + "sha256:574306171b84cd6854c83dc87bc353cacc0f60184149fb00c9ea871eca8c1ecb", + "sha256:7561fd541477d41f3aa09457c434dd1f7604f3bd26d7858d52018f5dfe1c06d1", + "sha256:7a54efd6fcad9cb3cd5ef2064b5a3eeb0b63c99f26c346bdcf66e7c98294d7cc", + "sha256:7f16660edf9a8bcc0f766f51c9e1b9d2dc6ceff6bf636d2dbd8eb925d5832dfd", + "sha256:81e6fe8b18ef5be67f40a1d4f07d5a4ed21d3878530193898449ddef7793952f", + "sha256:84a10e462120aa7d9eb6186b50917ed5a6286ee61157bfc17c5b47987d1a9068", + "sha256:84d4c4f650f356678a5d658a43ca21a41fca13f9b8b00169c0b76e6a6a948908", + "sha256:86dc94e44403fa0f2b1dd76c9794d66a34e821361962fe7c4e078746362e3b14", + "sha256:90dbc007f6389bcfd9ef4fe5d4c78c8d2efe4e0ebefd48b4f221cdfed5672be2", + "sha256:9f374961a3996c2d1b41ba3145462c3708a89759e604112073ed6c8bdf9f622f", + "sha256:a18cc1ab4a35b845cf33b7880c979f5c609fd26c2d6e74ddfacb73dcc60dd956", + "sha256:a97781453ac79409ddf455fccf344860719d95142f9c334f2a8f3fff049ffec3", + "sha256:a989022f89cda417f82dbf65e0a830832afd8af743d05d1414fb49549287ff04", + "sha256:ac2a30a09984c2719f112a574b6543ccb82d020fd1b23b4d55bf4759ba8dd8f5", + "sha256:be4430b33b25e127fc4ea239cc386389de420be4d63e71d5359c20b562951ce1", + "sha256:c45e7bf89ea33a2adaef34774df4e692c7436a18a48bcb0e47a53e698a39fa39" + ], + "index": "pypi", + "version": "==3.4.1" + }, "multidict": { "hashes": [ "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a", @@ -254,46 +329,77 @@ "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255", "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d" ], + "markers": "python_version >= '3.5'", "version": "==4.7.6" }, + "numpy": { + "hashes": [ + "sha256:2428b109306075d89d21135bdd6b785f132a1f5a3260c371cee1fae427e12727", + "sha256:377751954da04d4a6950191b20539066b4e19e3b559d4695399c5e8e3e683bf6", + "sha256:4703b9e937df83f5b6b7447ca5912b5f5f297aba45f91dbbbc63ff9278c7aa98", + "sha256:471c0571d0895c68da309dacee4e95a0811d0a9f9f532a48dc1bea5f3b7ad2b7", + "sha256:61d5b4cf73622e4d0c6b83408a16631b670fc045afd6540679aa35591a17fe6d", + "sha256:6c915ee7dba1071554e70a3664a839fbc033e1d6528199d4621eeaaa5487ccd2", + "sha256:6e51e417d9ae2e7848314994e6fc3832c9d426abce9328cf7571eefceb43e6c9", + "sha256:719656636c48be22c23641859ff2419b27b6bdf844b36a2447cb39caceb00935", + "sha256:780ae5284cb770ade51d4b4a7dce4faa554eb1d88a56d0e8b9f35fca9b0270ff", + "sha256:878922bf5ad7550aa044aa9301d417e2d3ae50f0f577de92051d739ac6096cee", + "sha256:924dc3f83de20437de95a73516f36e09918e9c9c18d5eac520062c49191025fb", + "sha256:97ce8b8ace7d3b9288d88177e66ee75480fb79b9cf745e91ecfe65d91a856042", + "sha256:9c0fab855ae790ca74b27e55240fe4f2a36a364a3f1ebcfd1fb5ac4088f1cec3", + "sha256:9cab23439eb1ebfed1aaec9cd42b7dc50fc96d5cd3147da348d9161f0501ada5", + "sha256:a8e6859913ec8eeef3dbe9aed3bf475347642d1cdd6217c30f28dee8903528e6", + "sha256:aa046527c04688af680217fffac61eec2350ef3f3d7320c07fd33f5c6e7b4d5f", + "sha256:abc81829c4039e7e4c30f7897938fa5d4916a09c2c7eb9b244b7a35ddc9656f4", + "sha256:bad70051de2c50b1a6259a6df1daaafe8c480ca98132da98976d8591c412e737", + "sha256:c73a7975d77f15f7f68dacfb2bca3d3f479f158313642e8ea9058eea06637931", + "sha256:d15007f857d6995db15195217afdbddfcd203dfaa0ba6878a2f580eaf810ecd6", + "sha256:d76061ae5cab49b83a8cf3feacefc2053fac672728802ac137dd8c4123397677", + "sha256:e8e4fbbb7e7634f263c5b0150a629342cc19b47c5eba8d1cd4363ab3455ab576", + "sha256:e9459f40244bb02b2f14f6af0cd0732791d72232bbb0dc4bab57ef88e75f6935", + "sha256:edb1f041a9146dcf02cd7df7187db46ab524b9af2515f392f337c7cbbf5b52cd" + ], + "markers": "python_version >= '3.7'", + "version": "==1.20.2" + }, "pillow": { "hashes": [ - "sha256:01bb0a34f1a6689b138c0089d670ae2e8f886d2666a9b2f2019031abdea673c4", - "sha256:07872f1d8421db5a3fe770f7480835e5e90fddb58f36c216d4a2ac0d594de474", - "sha256:1022f8f6dc3c5b0dcf928f1c49ba2ac73051f576af100d57776e2b65c1f76a8d", - "sha256:14415e9e28410232370615dbde0cf0a00e526f522f665460344a5b96973a3086", - "sha256:172acfaf00434a28dddfe592d83f2980e22e63c769ff4a448ddf7b7a38ffd165", - "sha256:1c5e3c36f02c815766ae9dd91899b1c5b4652f2a37b7a51609f3bd467c0f11fb", - "sha256:292f2aa1ae5c5c1451cb4b558addb88c257411d3fd71c6cf45562911baffc979", - "sha256:2a40d7d4b17db87f5b9a1efc0aff56000e1d0d5ece415090c102aafa0ccbe858", - "sha256:2f0d7034d5faae9a8d1019d152ede924f653df2ce77d3bba4ce62cd21b5f94ae", - "sha256:33fdbd4f5608c852d97264f9d2e3b54e9e9959083d008145175b86100b275e5b", - "sha256:3b13d89d97b551e02549d1f0edf22bed6acfd6fd2e888cd1e9a953bf215f0e81", - "sha256:3e759bcc03d6f39bc751e56d86bc87252b9a21c689a27c5ed753717a87d53a5b", - "sha256:3ec87bd1248b23a2e4e19e774367fbe30fddc73913edc5f9b37470624f55dc1f", - "sha256:436b0a2dd9fe3f7aa6a444af6bdf53c1eb8f5ced9ea3ef104daa83f0ea18e7bc", - "sha256:43b3c859912e8bf754b3c5142df624794b18eb7ae07cfeddc917e1a9406a3ef2", - "sha256:4fe74636ee71c57a7f65d7b21a9f127d842b4fb75511e5d256ace258826eb352", - "sha256:59445af66b59cc39530b4f810776928d75e95f41e945f0c32a3de4aceb93c15d", - "sha256:69da5b1d7102a61ce9b45deb2920a2012d52fd8f4201495ea9411d0071b0ec22", - "sha256:7094bbdecb95ebe53166e4c12cf5e28310c2b550b08c07c5dc15433898e2238e", - "sha256:8211cac9bf10461f9e33fe9a3af6c5131f3fdd0d10672afc2abb2c70cf95c5ca", - "sha256:8cf77e458bd996dc85455f10fe443c0c946f5b13253773439bcbec08aa1aebc2", - "sha256:924fc33cb4acaf6267b8ca3b8f1922620d57a28470d5e4f49672cea9a841eb08", - "sha256:99ce3333b40b7a4435e0a18baad468d44ab118a4b1da0af0a888893d03253f1d", - "sha256:a7d690b2c5f7e4a932374615fedceb1e305d2dd5363c1de15961725fe10e7d16", - "sha256:b9af590adc1e46898a1276527f3cfe2da8048ae43fbbf9b1bf9395f6c99d9b47", - "sha256:bb18422ad00c1fecc731d06592e99c3be2c634da19e26942ba2f13d805005cf2", - "sha256:c10af40ee2f1a99e1ae755ab1f773916e8bca3364029a042cd9161c400416bd8", - "sha256:c143c409e7bc1db784471fe9d0bf95f37c4458e879ad84cfae640cb74ee11a26", - "sha256:c448d2b335e21951416a30cd48d35588d122a912d5fe9e41900afacecc7d21a1", - "sha256:d30f30c044bdc0ab8f3924e1eeaac87e0ff8a27e87369c5cac4064b6ec78fd83", - "sha256:df534e64d4f3e84e8f1e1a37da3f541555d947c1c1c09b32178537f0f243f69d", - "sha256:f6fc18f9c9c7959bf58e6faf801d14fafb6d4717faaf6f79a68c8bb2a13dcf20", - "sha256:ff83dfeb04c98bb3e7948f876c17513a34e9a19fd92e292288649164924c1b39" + "sha256:01425106e4e8cee195a411f729cff2a7d61813b0b11737c12bd5991f5f14bcd5", + "sha256:031a6c88c77d08aab84fecc05c3cde8414cd6f8406f4d2b16fed1e97634cc8a4", + "sha256:083781abd261bdabf090ad07bb69f8f5599943ddb539d64497ed021b2a67e5a9", + "sha256:0d19d70ee7c2ba97631bae1e7d4725cdb2ecf238178096e8c82ee481e189168a", + "sha256:0e04d61f0064b545b989126197930807c86bcbd4534d39168f4aa5fda39bb8f9", + "sha256:12e5e7471f9b637762453da74e390e56cc43e486a88289995c1f4c1dc0bfe727", + "sha256:22fd0f42ad15dfdde6c581347eaa4adb9a6fc4b865f90b23378aa7914895e120", + "sha256:238c197fc275b475e87c1453b05b467d2d02c2915fdfdd4af126145ff2e4610c", + "sha256:3b570f84a6161cf8865c4e08adf629441f56e32f180f7aa4ccbd2e0a5a02cba2", + "sha256:463822e2f0d81459e113372a168f2ff59723e78528f91f0bd25680ac185cf797", + "sha256:4d98abdd6b1e3bf1a1cbb14c3895226816e666749ac040c4e2554231068c639b", + "sha256:5afe6b237a0b81bd54b53f835a153770802f164c5570bab5e005aad693dab87f", + "sha256:5b70110acb39f3aff6b74cf09bb4169b167e2660dabc304c1e25b6555fa781ef", + "sha256:5cbf3e3b1014dddc45496e8cf38b9f099c95a326275885199f427825c6522232", + "sha256:624b977355cde8b065f6d51b98497d6cd5fbdd4f36405f7a8790e3376125e2bb", + "sha256:63728564c1410d99e6d1ae8e3b810fe012bc440952168af0a2877e8ff5ab96b9", + "sha256:66cc56579fd91f517290ab02c51e3a80f581aba45fd924fcdee01fa06e635812", + "sha256:6c32cc3145928c4305d142ebec682419a6c0a8ce9e33db900027ddca1ec39178", + "sha256:8bb1e155a74e1bfbacd84555ea62fa21c58e0b4e7e6b20e4447b8d07990ac78b", + "sha256:95d5ef984eff897850f3a83883363da64aae1000e79cb3c321915468e8c6add5", + "sha256:a013cbe25d20c2e0c4e85a9daf438f85121a4d0344ddc76e33fd7e3965d9af4b", + "sha256:a787ab10d7bb5494e5f76536ac460741788f1fbce851068d73a87ca7c35fc3e1", + "sha256:a7d5e9fad90eff8f6f6106d3b98b553a88b6f976e51fce287192a5d2d5363713", + "sha256:aac00e4bc94d1b7813fe882c28990c1bc2f9d0e1aa765a5f2b516e8a6a16a9e4", + "sha256:b91c36492a4bbb1ee855b7d16fe51379e5f96b85692dc8210831fbb24c43e484", + "sha256:c03c07ed32c5324939b19e36ae5f75c660c81461e312a41aea30acdd46f93a7c", + "sha256:c5236606e8570542ed424849f7852a0ff0bce2c4c8d0ba05cc202a5a9c97dee9", + "sha256:c6b39294464b03457f9064e98c124e09008b35a62e3189d3513e5148611c9388", + "sha256:cb7a09e173903541fa888ba010c345893cd9fc1b5891aaf060f6ca77b6a3722d", + "sha256:d68cb92c408261f806b15923834203f024110a2e2872ecb0bd2a110f89d3c602", + "sha256:dc38f57d8f20f06dd7c3161c59ca2c86893632623f33a42d592f097b00f720a9", + "sha256:e98eca29a05913e82177b3ba3d198b1728e164869c613d76d0de4bde6768a50e", + "sha256:f217c3954ce5fd88303fc0c317af55d5e0204106d86dea17eb8205700d47dec2" ], "index": "pypi", - "version": "==8.1.1" + "version": "==8.2.0" }, "pycares": { "hashes": [ @@ -334,6 +440,7 @@ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.20" }, "pynacl": { @@ -362,11 +469,20 @@ ], "version": "==1.3.0" }, + "pyparsing": { + "hashes": [ + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.4.7" + }, "python-dateutil": { "hashes": [ "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.8.1" }, "pytz": { @@ -379,36 +495,45 @@ }, "pyyaml": { "hashes": [ - "sha256:02c78d77281d8f8d07a255e57abdbf43b02257f59f50cc6b636937d68efa5dd0", - "sha256:0dc9f2eb2e3c97640928dec63fd8dc1dd91e6b6ed236bd5ac00332b99b5c2ff9", - "sha256:124fd7c7bc1e95b1eafc60825f2daf67c73ce7b33f1194731240d24b0d1bf628", - "sha256:26fcb33776857f4072601502d93e1a619f166c9c00befb52826e7b774efaa9db", - "sha256:31ba07c54ef4a897758563e3a0fcc60077698df10180abe4b8165d9895c00ebf", - "sha256:3c49e39ac034fd64fd576d63bb4db53cda89b362768a67f07749d55f128ac18a", - "sha256:52bf0930903818e600ae6c2901f748bc4869c0c406056f679ab9614e5d21a166", - "sha256:5a3f345acff76cad4aa9cb171ee76c590f37394186325d53d1aa25318b0d4a09", - "sha256:5e7ac4e0e79a53451dc2814f6876c2fa6f71452de1498bbe29c0b54b69a986f4", - "sha256:7242790ab6c20316b8e7bb545be48d7ed36e26bbe279fd56f2c4a12510e60b4b", - "sha256:737bd70e454a284d456aa1fa71a0b429dd527bcbf52c5c33f7c8eee81ac16b89", - "sha256:8635d53223b1f561b081ff4adecb828fd484b8efffe542edcfdff471997f7c39", - "sha256:8b818b6c5a920cbe4203b5a6b14256f0e5244338244560da89b7b0f1313ea4b6", - "sha256:8bf38641b4713d77da19e91f8b5296b832e4db87338d6aeffe422d42f1ca896d", - "sha256:a36a48a51e5471513a5aea920cdad84cbd56d70a5057cca3499a637496ea379c", - "sha256:b2243dd033fd02c01212ad5c601dafb44fbb293065f430b0d3dbf03f3254d615", - "sha256:cc547d3ead3754712223abb7b403f0a184e4c3eae18c9bb7fd15adef1597cc4b", - "sha256:cc552b6434b90d9dbed6a4f13339625dc466fd82597119897e9489c953acbc22", - "sha256:f3790156c606299ff499ec44db422f66f05a7363b39eb9d5b064f17bd7d7c47b", - "sha256:f7a21e3d99aa3095ef0553e7ceba36fb693998fbb1226f1392ce33681047465f", - "sha256:fdc6b2cb4b19e431994f25a9160695cc59a4e861710cc6fc97161c5e845fc579" + "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf", + "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696", + "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393", + "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77", + "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922", + "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5", + "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8", + "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10", + "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc", + "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018", + "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e", + "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253", + "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347", + "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183", + "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541", + "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb", + "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185", + "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc", + "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db", + "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa", + "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46", + "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122", + "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b", + "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63", + "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df", + "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc", + "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247", + "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6", + "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0" ], "index": "pypi", - "version": "==5.4" + "version": "==5.4.1" }, "redis": { "hashes": [ "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2", "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==3.5.3" }, "sentry-sdk": { @@ -424,6 +549,7 @@ "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.15.0" }, "sortedcontainers": { @@ -446,6 +572,7 @@ "sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df", "sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", "version": "==1.26.4" }, "yarl": { @@ -468,6 +595,7 @@ "sha256:f18d68f2be6bf0e89f1521af2b1bb46e66ab0018faafa81d70f358153170a317", "sha256:f379b7f83f23fe12823085cd6b906edc49df969eb99757f58ff382349a3303c6" ], + "markers": "python_version >= '3.5'", "version": "==1.5.1" } }, @@ -484,6 +612,7 @@ "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6", "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==20.3.0" }, "cfgv": { @@ -491,6 +620,7 @@ "sha256:32e43d604bbe7896fe7c248a9c2276447dbef840feb28fe20494f62af110211d", "sha256:cf22deb93d4bcf92f345a5c3cd39d3d41d6340adc60c78bbbd6588c384fda6a1" ], + "markers": "python_full_version >= '3.6.1'", "version": "==3.2.0" }, "distlib": { @@ -509,19 +639,19 @@ }, "flake8": { "hashes": [ - "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839", - "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b" + "sha256:12d05ab02614b6aee8df7c36b97d1a3b2372761222b19b58621355e82acddcff", + "sha256:78873e372b12b093da7b5e5ed302e8ad9e988b38b063b61ad937f26ca58fc5f0" ], "index": "pypi", - "version": "==3.8.4" + "version": "==3.9.0" }, "flake8-annotations": { "hashes": [ - "sha256:3a377140556aecf11fa9f3bb18c10db01f5ea56dc79a730e2ec9b4f1f49e2055", - "sha256:e17947a48a5b9f632fe0c72682fc797c385e451048e7dfb20139f448a074cb3e" + "sha256:0d6cd2e770b5095f09689c9d84cc054c51b929c41a68969ea1beb4b825cac515", + "sha256:d10c4638231f8a50c0a597c4efce42bd7b7d85df4f620a0ddaca526138936a4f" ], "index": "pypi", - "version": "==2.5.0" + "version": "==2.6.2" }, "flake8-bugbear": { "hashes": [ @@ -533,11 +663,11 @@ }, "flake8-docstrings": { "hashes": [ - "sha256:3d5a31c7ec6b7367ea6506a87ec293b94a0a46c0bce2bb4975b7f1d09b6f3717", - "sha256:a256ba91bc52307bef1de59e2a009c3cf61c3d0952dbe035d6ff7208940c2edc" + "sha256:99cac583d6c7e32dd28bbfbef120a7c0d1b6dde4adb5a9fd441c4227a6534bde", + "sha256:9fe7c6a306064af8e62a055c2f61e9eb1da55f84bb39caef2b84ce53708ac34b" ], "index": "pypi", - "version": "==1.5.0" + "version": "==1.6.0" }, "flake8-import-order": { "hashes": [ @@ -582,6 +712,7 @@ "sha256:43cb1965e84cdd247e875dec6d13332ef5be355ddc16776396d98089b9053d87", "sha256:c7c0f590526008911ccc5ceee6ed7b085cbc92f7b6591d0ee5913a130ad64034" ], + "markers": "python_full_version >= '3.6.1'", "version": "==2.2.2" }, "mccabe": { @@ -608,65 +739,77 @@ }, "pre-commit": { "hashes": [ - "sha256:16212d1fde2bed88159287da88ff03796863854b04dc9f838a55979325a3d20e", - "sha256:399baf78f13f4de82a29b649afd74bef2c4e28eb4f021661fc7f29246e8c7a3a" + "sha256:029d53cb83c241fe7d66eeee1e24db426f42c858f15a38d20bcefd8d8e05c9da", + "sha256:46b6ffbab37986c47d0a35e40906ae029376deed89a0eb2e446fb6e67b220427" ], "index": "pypi", - "version": "==2.10.1" + "version": "==2.12.0" }, "pycodestyle": { "hashes": [ - "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367", - "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e" + "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068", + "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef" ], - "version": "==2.6.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.7.0" }, "pydocstyle": { "hashes": [ "sha256:164befb520d851dbcf0e029681b91f4f599c62c5cd8933fd54b1bfbd50e89e1f", "sha256:d4449cf16d7e6709f63192146706933c7a334af7c0f083904799ccb851c50f6d" ], + "markers": "python_version >= '3.6'", "version": "==6.0.0" }, "pyflakes": { "hashes": [ - "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92", - "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8" + "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3", + "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db" ], - "version": "==2.2.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.3.1" }, "pyyaml": { "hashes": [ - "sha256:02c78d77281d8f8d07a255e57abdbf43b02257f59f50cc6b636937d68efa5dd0", - "sha256:0dc9f2eb2e3c97640928dec63fd8dc1dd91e6b6ed236bd5ac00332b99b5c2ff9", - "sha256:124fd7c7bc1e95b1eafc60825f2daf67c73ce7b33f1194731240d24b0d1bf628", - "sha256:26fcb33776857f4072601502d93e1a619f166c9c00befb52826e7b774efaa9db", - "sha256:31ba07c54ef4a897758563e3a0fcc60077698df10180abe4b8165d9895c00ebf", - "sha256:3c49e39ac034fd64fd576d63bb4db53cda89b362768a67f07749d55f128ac18a", - "sha256:52bf0930903818e600ae6c2901f748bc4869c0c406056f679ab9614e5d21a166", - "sha256:5a3f345acff76cad4aa9cb171ee76c590f37394186325d53d1aa25318b0d4a09", - "sha256:5e7ac4e0e79a53451dc2814f6876c2fa6f71452de1498bbe29c0b54b69a986f4", - "sha256:7242790ab6c20316b8e7bb545be48d7ed36e26bbe279fd56f2c4a12510e60b4b", - "sha256:737bd70e454a284d456aa1fa71a0b429dd527bcbf52c5c33f7c8eee81ac16b89", - "sha256:8635d53223b1f561b081ff4adecb828fd484b8efffe542edcfdff471997f7c39", - "sha256:8b818b6c5a920cbe4203b5a6b14256f0e5244338244560da89b7b0f1313ea4b6", - "sha256:8bf38641b4713d77da19e91f8b5296b832e4db87338d6aeffe422d42f1ca896d", - "sha256:a36a48a51e5471513a5aea920cdad84cbd56d70a5057cca3499a637496ea379c", - "sha256:b2243dd033fd02c01212ad5c601dafb44fbb293065f430b0d3dbf03f3254d615", - "sha256:cc547d3ead3754712223abb7b403f0a184e4c3eae18c9bb7fd15adef1597cc4b", - "sha256:cc552b6434b90d9dbed6a4f13339625dc466fd82597119897e9489c953acbc22", - "sha256:f3790156c606299ff499ec44db422f66f05a7363b39eb9d5b064f17bd7d7c47b", - "sha256:f7a21e3d99aa3095ef0553e7ceba36fb693998fbb1226f1392ce33681047465f", - "sha256:fdc6b2cb4b19e431994f25a9160695cc59a4e861710cc6fc97161c5e845fc579" + "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf", + "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696", + "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393", + "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77", + "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922", + "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5", + "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8", + "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10", + "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc", + "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018", + "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e", + "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253", + "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347", + "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183", + "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541", + "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb", + "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185", + "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc", + "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db", + "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa", + "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46", + "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122", + "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b", + "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63", + "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df", + "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc", + "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247", + "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6", + "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0" ], "index": "pypi", - "version": "==5.4" + "version": "==5.4.1" }, "six": { "hashes": [ "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.15.0" }, "snowballstemmer": { @@ -681,6 +824,7 @@ "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.10.2" }, "virtualenv": { @@ -688,6 +832,7 @@ "sha256:49ec4eb4c224c6f7dd81bb6d0a28a09ecae5894f4e593c89b0db0885f565a107", "sha256:83f95875d382c7abafe06bd2a4cdd1b363e1bb77e02f155ebe8ac082a916b37c" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==20.4.3" } } diff --git a/bot/exts/evergreen/latex.py b/bot/exts/evergreen/latex.py new file mode 100644 index 00000000..79b50ccd --- /dev/null +++ b/bot/exts/evergreen/latex.py @@ -0,0 +1,57 @@ +from io import BytesIO +from typing import Union + +import discord +import matplotlib.pyplot as plt +from discord.ext import commands + +# configure fonts and colors for matplotlib +plt.rcParams.update( + { + "font.size": 16, + "mathtext.fontset": "cm", # Computer Modern font set + "mathtext.rm": "serif", + "figure.facecolor": "38383F", # matches Discord's dark mode background color + "text.color": "white", + } +) + + +class Latex(commands.Cog): + """Renders latex.""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + + @staticmethod + def _render(text: str) -> Union[BytesIO, str]: + """Return the rendered image if latex compiles without errors, otherwise return the error message.""" + text = text.replace(r"\\", "$\n$") # matplotlib uses \n for newlines, not \\ + fig = plt.figure() + + try: + fig.text(0, 1, text, horizontalalignment="left", verticalalignment="top") + + rendered_image = BytesIO() + plt.savefig(rendered_image, bbox_inches="tight", dpi=600) + rendered_image.seek(0) + return rendered_image + + except ValueError as e: + return str(e) + + @commands.command() + async def latex(self, ctx: commands.Context, *, text: str) -> None: + """Renders the text in latex and sends the image.""" + async with ctx.typing(): + image = self._render(text) + + if isinstance(image, BytesIO): + await ctx.send(file=discord.File(image, "latex.png")) + else: + await ctx.send(image) + + +def setup(bot: commands.Bot) -> None: + """Load the Latex Cog.""" + bot.add_cog(Latex(bot)) -- cgit v1.2.3 From a36a58d81b64412458a7b51fbfb4a37e88a060fe Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 8 Apr 2021 19:28:59 +0100 Subject: Add word boundaries to the issues regex --- bot/exts/evergreen/issues.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 0d43326d..b653f7ae 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -226,7 +226,7 @@ class Issues(commands.Cog): return # `issues` will hold a list of two element tuples `(repository, issue_number)` - issues = re.findall(fr"({self.repo_regex})#(\d+)", message.content) + issues = re.findall(fr"\b({self.repo_regex})#(\d+)\b", message.content) links = [] if issues: -- cgit v1.2.3 From 3e09dd8500d91486a2a3c776cb213d61204f3c61 Mon Sep 17 00:00:00 2001 From: Shakya Majumdar Date: Fri, 9 Apr 2021 11:56:02 +0530 Subject: add markdown support --- bot/exts/evergreen/latex.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/latex.py b/bot/exts/evergreen/latex.py index 79b50ccd..1f9de163 100644 --- a/bot/exts/evergreen/latex.py +++ b/bot/exts/evergreen/latex.py @@ -1,3 +1,4 @@ +import re from io import BytesIO from typing import Union @@ -16,6 +17,16 @@ plt.rcParams.update( } ) +FORMATTED_CODE_REGEX = re.compile( + r"(?P(?P```)|``?)" # code delimiter: 1-3 backticks; (?P=block) only matches if it's a block + r"(?(block)(?:(?P[a-z]+)\n)?)" # if we're in a block, match optional language (only letters plus newline) + r"(?:[ \t]*\n)*" # any blank (empty or tabs/spaces only) lines before the code + r"(?P.*?)" # extract all code inside the markup + r"\s*" # any more whitespace before the end of the code markup + r"(?P=delim)", # match the exact same delimiter from the start again + re.DOTALL | re.IGNORECASE, # "." also matches newlines, case insensitive +) + class Latex(commands.Cog): """Renders latex.""" @@ -26,7 +37,6 @@ class Latex(commands.Cog): @staticmethod def _render(text: str) -> Union[BytesIO, str]: """Return the rendered image if latex compiles without errors, otherwise return the error message.""" - text = text.replace(r"\\", "$\n$") # matplotlib uses \n for newlines, not \\ fig = plt.figure() try: @@ -40,16 +50,26 @@ class Latex(commands.Cog): except ValueError as e: return str(e) + @staticmethod + def _prepare_input(text: str) -> str: + text = text.replace(r"\\", "$\n$") # matplotlib uses \n for newlines, not \\ + + if match := FORMATTED_CODE_REGEX.match(text): + return match.group("code") + else: + return text + @commands.command() async def latex(self, ctx: commands.Context, *, text: str) -> None: """Renders the text in latex and sends the image.""" + text = self._prepare_input(text) async with ctx.typing(): image = self._render(text) if isinstance(image, BytesIO): await ctx.send(file=discord.File(image, "latex.png")) else: - await ctx.send(image) + await ctx.send("```" + image + "```") def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From 0f2c076e6e64cf8f09fc8a89872767121acdfd83 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Fri, 9 Apr 2021 09:16:40 +0200 Subject: Issues: use soft_red instead of red Co-authored-by: Shivansh-007 --- bot/exts/evergreen/issues.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index b653f7ae..3fb69127 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -239,7 +239,7 @@ class Issues(commands.Cog): "You can't retrieve issues from DMs. " f"Try again in <#{Channels.community_bot_commands}>" ), - colour=discord.Colour.red() + colour=Colours.soft_red ) ) return -- cgit v1.2.3 From e095a4f71f81547378af7c5cdd42fed4cbf8a5ac Mon Sep 17 00:00:00 2001 From: Shakya Majumdar Date: Fri, 9 Apr 2021 19:12:18 +0530 Subject: run _render in executor, raise BadArgument for invalid input --- bot/exts/evergreen/latex.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/latex.py b/bot/exts/evergreen/latex.py index 1f9de163..b9652a75 100644 --- a/bot/exts/evergreen/latex.py +++ b/bot/exts/evergreen/latex.py @@ -1,6 +1,8 @@ +import asyncio import re +from concurrent.futures import ThreadPoolExecutor +from functools import partial from io import BytesIO -from typing import Union import discord import matplotlib.pyplot as plt @@ -31,12 +33,9 @@ FORMATTED_CODE_REGEX = re.compile( class Latex(commands.Cog): """Renders latex.""" - def __init__(self, bot: commands.Bot): - self.bot = bot - @staticmethod - def _render(text: str) -> Union[BytesIO, str]: - """Return the rendered image if latex compiles without errors, otherwise return the error message.""" + def _render(text: str) -> BytesIO: + """Return the rendered image if latex compiles without errors, otherwise raise a BadArgument Exception.""" fig = plt.figure() try: @@ -48,7 +47,7 @@ class Latex(commands.Cog): return rendered_image except ValueError as e: - return str(e) + raise commands.BadArgument(str(e)) @staticmethod def _prepare_input(text: str) -> str: @@ -64,12 +63,13 @@ class Latex(commands.Cog): """Renders the text in latex and sends the image.""" text = self._prepare_input(text) async with ctx.typing(): - image = self._render(text) - if isinstance(image, BytesIO): - await ctx.send(file=discord.File(image, "latex.png")) - else: - await ctx.send("```" + image + "```") + with ThreadPoolExecutor() as pool: + image = await asyncio.get_running_loop().run_in_executor( + pool, partial(self._render, text) + ) + + await ctx.send(file=discord.File(image, "latex.png")) def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From 29c77d6c36d693daeff33fc1ed3240c8927e5217 Mon Sep 17 00:00:00 2001 From: Shakya Majumdar Date: Fri, 9 Apr 2021 19:38:11 +0530 Subject: remove redundant use of functools.partial --- bot/exts/evergreen/latex.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/latex.py b/bot/exts/evergreen/latex.py index b9652a75..a8ed56fb 100644 --- a/bot/exts/evergreen/latex.py +++ b/bot/exts/evergreen/latex.py @@ -1,7 +1,6 @@ import asyncio import re from concurrent.futures import ThreadPoolExecutor -from functools import partial from io import BytesIO import discord @@ -66,7 +65,7 @@ class Latex(commands.Cog): with ThreadPoolExecutor() as pool: image = await asyncio.get_running_loop().run_in_executor( - pool, partial(self._render, text) + pool, self._render, text ) await ctx.send(file=discord.File(image, "latex.png")) -- cgit v1.2.3 From edb6ffab317499689d7b8f5d0b884a8d10a01a76 Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Fri, 9 Apr 2021 13:28:36 -0400 Subject: Update comment --- bot/exts/evergreen/issues.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 7604c438..fa07b674 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -158,7 +158,7 @@ class Issues(commands.Cog): emoji = Emojis.pull_request_draft elif pull_data["state"] == "open": emoji = Emojis.pull_request - # When the status is 204 this means that the state of the PR is merged + # When 'merged_at' is not None, this means that the state of the PR is merged elif pull_data["merged_at"] is not None: emoji = Emojis.merge else: -- cgit v1.2.3 From 4675123f4e3e5a23623a2f2b062f754370c42673 Mon Sep 17 00:00:00 2001 From: Shakya Majumdar Date: Fri, 9 Apr 2021 23:12:54 +0530 Subject: exclude non error-causing lines from try-except --- bot/exts/evergreen/latex.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/latex.py b/bot/exts/evergreen/latex.py index a8ed56fb..7cc3432f 100644 --- a/bot/exts/evergreen/latex.py +++ b/bot/exts/evergreen/latex.py @@ -36,18 +36,17 @@ class Latex(commands.Cog): def _render(text: str) -> BytesIO: """Return the rendered image if latex compiles without errors, otherwise raise a BadArgument Exception.""" fig = plt.figure() + rendered_image = BytesIO() + fig.text(0, 1, text, horizontalalignment="left", verticalalignment="top") try: - fig.text(0, 1, text, horizontalalignment="left", verticalalignment="top") - - rendered_image = BytesIO() plt.savefig(rendered_image, bbox_inches="tight", dpi=600) - rendered_image.seek(0) - return rendered_image - except ValueError as e: raise commands.BadArgument(str(e)) + rendered_image.seek(0) + return rendered_image + @staticmethod def _prepare_input(text: str) -> str: text = text.replace(r"\\", "$\n$") # matplotlib uses \n for newlines, not \\ -- cgit v1.2.3 From 0e9ea17010310c7d63d9b0fbba9e3a441cf2c1b5 Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Sat, 10 Apr 2021 05:56:22 +0100 Subject: add timed command for timed execution of commands --- bot/exts/evergreen/timed.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 bot/exts/evergreen/timed.py (limited to 'bot') diff --git a/bot/exts/evergreen/timed.py b/bot/exts/evergreen/timed.py new file mode 100644 index 00000000..0537141b --- /dev/null +++ b/bot/exts/evergreen/timed.py @@ -0,0 +1,36 @@ +from copy import copy +from time import perf_counter + +from discord import Message +from discord.ext import commands + + +class TimedCommands(commands.Cog): + """Time the command execution of a command.""" + + def __init__(self, bot: commands.Bot) -> None: + self.bot = bot + + @staticmethod + async def create_execution_context(ctx: commands.Context, command: str) -> commands.Context: + """Get a new execution context for a command.""" + msg: Message = copy(ctx.message) + msg._update({"content": f"{ctx.prefix}{command}"}) + + return await ctx.bot.get_context(msg) + + @commands.command(name="timed", aliases=["t"]) + async def timed(self, ctx: commands.Context, *, command: str) -> None: + """Time the command execution of a command.""" + new_ctx = await self.create_execution_context(ctx, command) + + t_start = perf_counter() + await new_ctx.command.invoke(new_ctx) + t_end = perf_counter() + + await ctx.send(f"Command execution for `{new_ctx.command}` finished in {(t_end - t_start):.4f} seconds.") + + +def setup(bot: commands.Bot) -> None: + """Cog load.""" + bot.add_cog(TimedCommands(bot)) -- cgit v1.2.3 From 4bdc3a934c5c9564829466a175f3a8c4545448ba Mon Sep 17 00:00:00 2001 From: Shakya Majumdar Date: Sat, 10 Apr 2021 10:56:39 +0530 Subject: change background color to match discord theme exactly --- bot/exts/evergreen/latex.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/latex.py b/bot/exts/evergreen/latex.py index 7cc3432f..d140e79d 100644 --- a/bot/exts/evergreen/latex.py +++ b/bot/exts/evergreen/latex.py @@ -13,19 +13,19 @@ plt.rcParams.update( "font.size": 16, "mathtext.fontset": "cm", # Computer Modern font set "mathtext.rm": "serif", - "figure.facecolor": "38383F", # matches Discord's dark mode background color + "figure.facecolor": "36393F", # matches Discord's dark mode background color "text.color": "white", } ) FORMATTED_CODE_REGEX = re.compile( - r"(?P(?P```)|``?)" # code delimiter: 1-3 backticks; (?P=block) only matches if it's a block - r"(?(block)(?:(?P[a-z]+)\n)?)" # if we're in a block, match optional language (only letters plus newline) - r"(?:[ \t]*\n)*" # any blank (empty or tabs/spaces only) lines before the code - r"(?P.*?)" # extract all code inside the markup - r"\s*" # any more whitespace before the end of the code markup - r"(?P=delim)", # match the exact same delimiter from the start again - re.DOTALL | re.IGNORECASE, # "." also matches newlines, case insensitive + r"(?P(?P```)|``?)" # code delimiter: 1-3 backticks; (?P=block) only matches if it's a block + r"(?(block)(?:(?P[a-z]+)\n)?)" # if we're in a block, match optional language (only letters plus newline) + r"(?:[ \t]*\n)*" # any blank (empty or tabs/spaces only) lines before the code + r"(?P.*?)" # extract all code inside the markup + r"\s*" # any more whitespace before the end of the code markup + r"(?P=delim)", # match the exact same delimiter from the start again + re.DOTALL | re.IGNORECASE, # "." also matches newlines, case insensitive ) -- cgit v1.2.3 From d7263238b68a3d55f47ec944cc9e85450e2800b6 Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Sat, 10 Apr 2021 21:48:26 +0100 Subject: removed unused cog init and fixed timing timed command --- bot/exts/evergreen/timed.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/timed.py b/bot/exts/evergreen/timed.py index 0537141b..58da3dc8 100644 --- a/bot/exts/evergreen/timed.py +++ b/bot/exts/evergreen/timed.py @@ -8,9 +8,6 @@ from discord.ext import commands class TimedCommands(commands.Cog): """Time the command execution of a command.""" - def __init__(self, bot: commands.Bot) -> None: - self.bot = bot - @staticmethod async def create_execution_context(ctx: commands.Context, command: str) -> commands.Context: """Get a new execution context for a command.""" @@ -24,6 +21,9 @@ class TimedCommands(commands.Cog): """Time the command execution of a command.""" new_ctx = await self.create_execution_context(ctx, command) + if new_ctx.command and new_ctx.command.qualified_name == "timed": + return await ctx.send("You are not allowed to time the execution of the `timed` command.") + t_start = perf_counter() await new_ctx.command.invoke(new_ctx) t_end = perf_counter() -- cgit v1.2.3 From bf1cd68efaa7f0fe5037c69fbdc7cfffcf284a2d Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Sun, 11 Apr 2021 01:11:21 +0100 Subject: fix message updating and return types --- bot/exts/evergreen/timed.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/timed.py b/bot/exts/evergreen/timed.py index 58da3dc8..57575993 100644 --- a/bot/exts/evergreen/timed.py +++ b/bot/exts/evergreen/timed.py @@ -12,7 +12,7 @@ class TimedCommands(commands.Cog): async def create_execution_context(ctx: commands.Context, command: str) -> commands.Context: """Get a new execution context for a command.""" msg: Message = copy(ctx.message) - msg._update({"content": f"{ctx.prefix}{command}"}) + msg.content = f"{ctx.prefix}{command}" return await ctx.bot.get_context(msg) @@ -22,7 +22,8 @@ class TimedCommands(commands.Cog): new_ctx = await self.create_execution_context(ctx, command) if new_ctx.command and new_ctx.command.qualified_name == "timed": - return await ctx.send("You are not allowed to time the execution of the `timed` command.") + await ctx.send("You are not allowed to time the execution of the `timed` command.") + return t_start = perf_counter() await new_ctx.command.invoke(new_ctx) -- cgit v1.2.3 From b0892e5afbbb13167c7c295c8f8241a2146eddf7 Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Sun, 11 Apr 2021 04:03:59 +0100 Subject: return and send message if command isnt found while timing --- bot/exts/evergreen/timed.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/timed.py b/bot/exts/evergreen/timed.py index 57575993..a0f29838 100644 --- a/bot/exts/evergreen/timed.py +++ b/bot/exts/evergreen/timed.py @@ -21,7 +21,11 @@ class TimedCommands(commands.Cog): """Time the command execution of a command.""" new_ctx = await self.create_execution_context(ctx, command) - if new_ctx.command and new_ctx.command.qualified_name == "timed": + if not new_ctx.command: + await ctx.send("The command you are trying to time doesn't exist. Use `.help` for a list of commands.") + return + + if new_ctx.command.qualified_name == "timed": await ctx.send("You are not allowed to time the execution of the `timed` command.") return -- cgit v1.2.3 From 7c7c6dd2318815bc14e1cb20d5dd5fbd416712a0 Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Sun, 11 Apr 2021 04:19:58 +0100 Subject: fix: use ctx.prefix when suggesting the help command --- bot/exts/evergreen/timed.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/timed.py b/bot/exts/evergreen/timed.py index a0f29838..604204b0 100644 --- a/bot/exts/evergreen/timed.py +++ b/bot/exts/evergreen/timed.py @@ -22,7 +22,10 @@ class TimedCommands(commands.Cog): new_ctx = await self.create_execution_context(ctx, command) if not new_ctx.command: - await ctx.send("The command you are trying to time doesn't exist. Use `.help` for a list of commands.") + help_command = f"{ctx.prefix}help" + error = f"The command you are trying to time doesn't exist. Use `{help_command}` for a list of commands." + + await ctx.send(error) return if new_ctx.command.qualified_name == "timed": -- cgit v1.2.3 From e51dfab90242822aeab6bd42e69296c133efe042 Mon Sep 17 00:00:00 2001 From: Shakya Majumdar Date: Sun, 11 Apr 2021 10:22:15 +0530 Subject: add caching --- .gitignore | 2 +- bot/exts/evergreen/latex.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/.gitignore b/.gitignore index d3d2bb8d..ce122d29 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ # bot (project-specific) log/* data/* - +_latex_cache/* diff --git a/bot/exts/evergreen/latex.py b/bot/exts/evergreen/latex.py index d140e79d..0c29f958 100644 --- a/bot/exts/evergreen/latex.py +++ b/bot/exts/evergreen/latex.py @@ -1,4 +1,6 @@ import asyncio +import hashlib +import pathlib import re from concurrent.futures import ThreadPoolExecutor from io import BytesIO @@ -28,6 +30,10 @@ FORMATTED_CODE_REGEX = re.compile( re.DOTALL | re.IGNORECASE, # "." also matches newlines, case insensitive ) +CACHE_DIRECTORY = pathlib.Path("_latex_cache") +if not CACHE_DIRECTORY.exists(): + CACHE_DIRECTORY.mkdir() + class Latex(commands.Cog): """Renders latex.""" @@ -60,7 +66,12 @@ class Latex(commands.Cog): async def latex(self, ctx: commands.Context, *, text: str) -> None: """Renders the text in latex and sends the image.""" text = self._prepare_input(text) + query_hash = hashlib.md5(text.encode()).hexdigest() + image_path = CACHE_DIRECTORY.joinpath(f"{query_hash}.png") async with ctx.typing(): + if image_path.exists(): + await ctx.send(file=discord.File(image_path)) + return with ThreadPoolExecutor() as pool: image = await asyncio.get_running_loop().run_in_executor( @@ -69,6 +80,9 @@ class Latex(commands.Cog): await ctx.send(file=discord.File(image, "latex.png")) + with open(image_path, "wb") as f: + f.write(image.getbuffer()) + def setup(bot: commands.Bot) -> None: """Load the Latex Cog.""" -- cgit v1.2.3 From 51d9b5413ceb8319e0ce9847ee048f112b21fdff Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Sun, 11 Apr 2021 16:48:25 +0200 Subject: Issues: add `type=public` This will make sure that even if a privileged token is passed we won't leak any private information. --- bot/exts/evergreen/issues.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index fa07b674..42ab97c3 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -30,7 +30,7 @@ REQUEST_HEADERS = { "Accept": "application/vnd.github.v3+json" } -REPOSITORY_ENDPOINT = "https://api.github.com/orgs/{org}/repos?per_page=100" +REPOSITORY_ENDPOINT = "https://api.github.com/orgs/{org}/repos?per_page=100&type=public" ISSUE_ENDPOINT = "https://api.github.com/repos/{user}/{repository}/issues/{number}" PR_ENDPOINT = "https://api.github.com/repos/{user}/{repository}/pulls/{number}" -- cgit v1.2.3 From 17cf2b391df6d02083386a450c0f4569ba421762 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 11 Apr 2021 16:21:44 +0100 Subject: Add env var for trashcan eomji override --- bot/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index 416dd0e7..1d35b3f1 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -153,7 +153,7 @@ class Emojis: christmas_tree = "\U0001F384" check = "\u2611" envelope = "\U0001F4E8" - trashcan = "<:trashcan:637136429717389331>" + trashcan = environ.get("TRASHCAN_EMOJI", "<:trashcan:637136429717389331>") ok_hand = ":ok_hand:" hand_raised = "\U0001f64b" -- cgit v1.2.3 From 7f6fa93dc43a1885c3ea0dfd695dec639822647c Mon Sep 17 00:00:00 2001 From: Shakya Majumdar Date: Sun, 11 Apr 2021 21:03:48 +0530 Subject: add max_concurrency, move file-saving to _render --- bot/exts/evergreen/latex.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/latex.py b/bot/exts/evergreen/latex.py index 0c29f958..c4a8597c 100644 --- a/bot/exts/evergreen/latex.py +++ b/bot/exts/evergreen/latex.py @@ -31,16 +31,19 @@ FORMATTED_CODE_REGEX = re.compile( ) CACHE_DIRECTORY = pathlib.Path("_latex_cache") -if not CACHE_DIRECTORY.exists(): - CACHE_DIRECTORY.mkdir() +CACHE_DIRECTORY.mkdir(exist_ok=True) class Latex(commands.Cog): """Renders latex.""" @staticmethod - def _render(text: str) -> BytesIO: - """Return the rendered image if latex compiles without errors, otherwise raise a BadArgument Exception.""" + def _render(text: str, filepath: pathlib.Path) -> BytesIO: + """ + Return the rendered image if latex compiles without errors, otherwise raise a BadArgument Exception. + + Saves rendered image to cache. + """ fig = plt.figure() rendered_image = BytesIO() fig.text(0, 1, text, horizontalalignment="left", verticalalignment="top") @@ -51,6 +54,10 @@ class Latex(commands.Cog): raise commands.BadArgument(str(e)) rendered_image.seek(0) + + with open(filepath, "wb") as f: + f.write(rendered_image.getbuffer()) + return rendered_image @staticmethod @@ -63,6 +70,7 @@ class Latex(commands.Cog): return text @commands.command() + @commands.max_concurrency(1, commands.BucketType.guild, wait=True) async def latex(self, ctx: commands.Context, *, text: str) -> None: """Renders the text in latex and sends the image.""" text = self._prepare_input(text) @@ -75,14 +83,11 @@ class Latex(commands.Cog): with ThreadPoolExecutor() as pool: image = await asyncio.get_running_loop().run_in_executor( - pool, self._render, text + pool, self._render, text, image_path ) await ctx.send(file=discord.File(image, "latex.png")) - with open(image_path, "wb") as f: - f.write(image.getbuffer()) - def setup(bot: commands.Bot) -> None: """Load the Latex Cog.""" -- cgit v1.2.3 From b8e8be4dff862997b8ba30ce48092c1c529d34c3 Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Sun, 11 Apr 2021 19:02:01 +0100 Subject: fix: put april fools video links in correct channel names --- bot/resources/easter/april_fools_vids.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/resources/easter/april_fools_vids.json b/bot/resources/easter/april_fools_vids.json index b2cbd07b..49a28bfa 100644 --- a/bot/resources/easter/april_fools_vids.json +++ b/bot/resources/easter/april_fools_vids.json @@ -115,11 +115,15 @@ { "title": "Introducing Gmail Motion", "link": "https://youtu.be/Bu927_ul_X0" - }, + } + ], + "nvidia": [ { "title": "Introducing GeForce GTX G-Assist", "link": "https://youtu.be/smM-Wdk2RLQ" - }, + } + ], + "razer": [ { "title": "The Hovering Mouse - Project McFly | Razer", "link": "https://youtu.be/IlCx5gjAmqI" @@ -129,5 +133,4 @@ "link": "https://youtu.be/j8UJE7DoyJ8" } ] - } -- cgit v1.2.3 From 652e306064efb451660e7c08dc88aeafdcf7360e Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Sun, 11 Apr 2021 19:12:10 +0100 Subject: chore: add time as alias of timed Co-authored-by: Matteo Bertucci --- bot/exts/evergreen/timed.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/timed.py b/bot/exts/evergreen/timed.py index 604204b0..635ccb32 100644 --- a/bot/exts/evergreen/timed.py +++ b/bot/exts/evergreen/timed.py @@ -16,7 +16,7 @@ class TimedCommands(commands.Cog): return await ctx.bot.get_context(msg) - @commands.command(name="timed", aliases=["t"]) + @commands.command(name="timed", aliases=["time", "t"]) async def timed(self, ctx: commands.Context, *, command: str) -> None: """Time the command execution of a command.""" new_ctx = await self.create_execution_context(ctx, command) -- cgit v1.2.3 From e187a3c67bcc93e8a688bac1a49541914f8b4871 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 12 Apr 2021 17:00:55 +0200 Subject: Allow automatic linking of issues outside of the python-discord organisation Actions python-discord/organisation#345 --- bot/exts/evergreen/issues.py | 75 ++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 41 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 42ab97c3..6797559c 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -5,7 +5,7 @@ import typing as t from dataclasses import dataclass import discord -from discord.ext import commands, tasks +from discord.ext import commands from bot.constants import ( Categories, @@ -50,6 +50,21 @@ CODE_BLOCK_RE = re.compile( # Maximum number of issues in one message MAXIMUM_ISSUES = 5 +# Regex used when looking for automatic linking in messages +AUTOMATIC_REGEX = re.compile(r"((?P.+?)\/)?(?P.+?)#(?P.+?)") + + +@dataclass +class FoundIssue: + """Dataclass representing an issue found by the regex.""" + + organisation: t.Optional[str] + repository: str + number: str + + def __hash__(self) -> int: + return hash(self.organisation) + hash(self.repository) + hash(self.number) + @dataclass class FetchError: @@ -76,38 +91,11 @@ class Issues(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot self.repos = [] - self.repo_regex = None - self.get_pydis_repos.start() - - @tasks.loop(minutes=30) - async def get_pydis_repos(self) -> None: - """ - Get all python-discord repositories on github. - - This task will update a pipe-separated list of repositories in self.repo_regex. - """ - async with self.bot.http_session.get( - REPOSITORY_ENDPOINT.format(org="python-discord"), - headers=REQUEST_HEADERS - ) as resp: - if resp.status == 200: - data = await resp.json() - for repo in data: - self.repos.append(repo["full_name"].split("/")[1]) - self.repo_regex = "|".join(self.repos) - else: - log.warning(f"Failed to get latest Pydis repositories. Status code {resp.status}") @staticmethod - def check_in_block(message: discord.Message, repo_issue: str) -> bool: - """Check whether the # is in codeblocks.""" - block = re.findall(CODE_BLOCK_RE, message.content) - - if not block: - return False - elif "#".join(repo_issue.split(" ")) in "".join([*block[0]]): - return True - return False + def remove_codeblocks(message: str) -> str: + """Remove any codeblock in a message.""" + return re.sub(CODE_BLOCK_RE, "", message) async def fetch_issues( self, @@ -219,17 +207,19 @@ class Issues(commands.Cog): @commands.Cog.listener() async def on_message(self, message: discord.Message) -> None: - """Command to retrieve issue(s) from a GitHub repository using automatic linking if matching #.""" - if not self.repo_regex: - log.warning("repo_regex isn't ready, cannot look for issues.") - return + """ + Automatic issue linking. + Listener to retrieve issue(s) from a GitHub repository using automatic linking if matching /#. + """ # Ignore bots if message.author.bot: return - # `issues` will hold a list of two element tuples `(repository, issue_number)` - issues = re.findall(fr"\b({self.repo_regex})#(\d+)\b", message.content) + issues = [ + FoundIssue(*match.group("org", "repo", "number")) + for match in AUTOMATIC_REGEX.finditer(self.remove_codeblocks(message.content)) + ] links = [] if issues: @@ -261,10 +251,13 @@ class Issues(commands.Cog): return for repo_issue in issues: - if not self.check_in_block(message, " ".join(repo_issue)): - result = await self.fetch_issues(repo_issue[1], repo_issue[0], "python-discord") - if isinstance(result, IssueState): - links.append(result) + result = await self.fetch_issues( + int(repo_issue.number), + repo_issue.repository, + repo_issue.organisation or "python-discord" + ) + if isinstance(result, IssueState): + links.append(result) if not links: return -- cgit v1.2.3 From 52dbe86fb8ff7d659e3ea7f7e49f1442e004e34d Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 12 Apr 2021 17:07:39 +0200 Subject: Issues: change hashing of FoundIssue to use a tuple --- bot/exts/evergreen/issues.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 6797559c..bb6273bb 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -63,7 +63,7 @@ class FoundIssue: number: str def __hash__(self) -> int: - return hash(self.organisation) + hash(self.repository) + hash(self.number) + return hash((self.organisation, self.repository, self.number)) @dataclass -- cgit v1.2.3 From 375c247ad0098db12b40fc2c1ad36e417c95f9e9 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 12 Apr 2021 16:59:54 +0100 Subject: Remove inappropriate riddle --- bot/resources/easter/easter_riddle.json | 8 -------- 1 file changed, 8 deletions(-) (limited to 'bot') diff --git a/bot/resources/easter/easter_riddle.json b/bot/resources/easter/easter_riddle.json index e93f6dad..f7eb63d8 100644 --- a/bot/resources/easter/easter_riddle.json +++ b/bot/resources/easter/easter_riddle.json @@ -63,14 +63,6 @@ ], "correct_answer": "A chocolate one" }, - { - "question": "Where does the Easter Bunny get his eggs?", - "riddles": [ - "Not a bush or tree", - "Emoji for a body part" - ], - "correct_answer": "Eggplants" - }, { "question": "Why did the Easter Bunny have to fire the duck?", "riddles": [ -- cgit v1.2.3 From 83245fa2d55e4430d2fff6a9aa6225ac1ee8de08 Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Mon, 12 Apr 2021 19:47:41 +0100 Subject: feat: rewrite portion of fool command to allow all videos --- bot/exts/easter/april_fools_vids.py | 10 +- bot/resources/easter/april_fools_vids.json | 266 ++++++++++++++--------------- 2 files changed, 135 insertions(+), 141 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/april_fools_vids.py b/bot/exts/easter/april_fools_vids.py index efe7e677..97cb407c 100644 --- a/bot/exts/easter/april_fools_vids.py +++ b/bot/exts/easter/april_fools_vids.py @@ -14,7 +14,6 @@ class AprilFoolVideos(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot self.yt_vids = self.load_json() - self.youtubers = ['google'] # will add more in future @staticmethod def load_json() -> dict: @@ -27,10 +26,11 @@ class AprilFoolVideos(commands.Cog): @commands.command(name='fool') async def april_fools(self, ctx: commands.Context) -> None: """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) - await ctx.send(f"Check out this April Fools' video by {random_youtuber}.\n\n{random_vid['link']}") + video = random.choice(self.yt_vids) + + channel, url = video["channel"], video["url"] + + await ctx.send(f"Check out this April Fools' video by {channel}.\n\n{url}") def setup(bot: commands.Bot) -> None: diff --git a/bot/resources/easter/april_fools_vids.json b/bot/resources/easter/april_fools_vids.json index 49a28bfa..e1e8c70a 100644 --- a/bot/resources/easter/april_fools_vids.json +++ b/bot/resources/easter/april_fools_vids.json @@ -1,136 +1,130 @@ -{ - "google": [ - { - "title": "Introducing Bad Joke Detector", - "link": "https://youtu.be/OYcv406J_J4" - }, - { - "title": "Introducing Google Cloud Hummus API - Find your Hummus!", - "link": "https://youtu.be/0_5X6N6DHyk" - }, - { - "title": "Introducing Google Play for Pets", - "link": "https://youtu.be/UmJ2NBHXTqo" - }, - { - "title": "Haptic Helpers: bringing you to your senses", - "link": "https://youtu.be/3MA6_21nka8" - }, - { - "title": "Introducing Google Wind", - "link": "https://youtu.be/QAwL0O5nXe0" - }, - { - "title": "Experience YouTube in #SnoopaVision", - "link": "https://youtu.be/DPEJB-FCItk" - }, - { - "title": "Introducing the self-driving bicycle in the Netherlands", - "link": "https://youtu.be/LSZPNwZex9s" - }, - { - "title": "Android Developer Story: The Guardian goes galactic with Android and Google Play", - "link": "https://youtu.be/dFrgNiweQDk" - }, - { - "title": "Introducing new delivery technology from Google Express", - "link": "https://youtu.be/F0F6SnbqUcE" - }, - { - "title": "Google Cardboard Plastic", - "link": "https://youtu.be/VkOuShXpoKc" - }, - { - "title": "Google Photos: Search your photos by emoji", - "link": "https://youtu.be/HQtGFBbwKEk" - }, - { - "title": "Introducing Google Actual Cloud Platform", - "link": "https://youtu.be/Cp10_PygJ4o" - }, - { - "title": "Introducing Dial-Up mode", - "link": "https://youtu.be/XTTtkisylQw" - }, - { - "title": "Smartbox by Inbox: the mailbox of tomorrow, today", - "link": "https://youtu.be/hydLZJXG3Tk" - }, - { - "title": "Introducing Coffee to the Home", - "link": "https://youtu.be/U2JBFlW--UU" - }, - { - "title": "Chrome for Android and iOS: Emojify the Web", - "link": "https://youtu.be/G3NXNnoGr3Y" - }, - { - "title": "Google Maps: Pokémon Challenge", - "link": "https://youtu.be/4YMD6xELI_k" - }, - { - "title": "Introducing Google Fiber to the Pole", - "link": "https://youtu.be/qcgWRpQP6ds" - }, - { - "title": "Introducing Gmail Blue", - "link": "https://youtu.be/Zr4JwPb99qU" - }, - { - "title": "Introducing Google Nose", - "link": "https://youtu.be/VFbYadm_mrw" - }, - { - "title": "Explore Treasure Mode with Google Maps", - "link": "https://youtu.be/_qFFHC0eIUc" - }, - { - "title": "YouTube's ready to select a winner", - "link": "https://youtu.be/H542nLTTbu0" - }, - { - "title": "A word about Gmail Tap", - "link": "https://youtu.be/Je7Xq9tdCJc" - }, - { - "title": "Introducing the Google Fiber Bar", - "link": "https://youtu.be/re0VRK6ouwI" - }, - { - "title": "Introducing Gmail Tap", - "link": "https://youtu.be/1KhZKNZO8mQ" - }, - { - "title": "Chrome Multitask Mode", - "link": "https://youtu.be/UiLSiqyDf4Y" - }, - { - "title": "Google Maps 8-bit for NES", - "link": "https://youtu.be/rznYifPHxDg" - }, - { - "title": "Being a Google Autocompleter", - "link": "https://youtu.be/blB_X38YSxQ" - }, - { - "title": "Introducing Gmail Motion", - "link": "https://youtu.be/Bu927_ul_X0" - } - ], - "nvidia": [ - { - "title": "Introducing GeForce GTX G-Assist", - "link": "https://youtu.be/smM-Wdk2RLQ" - } - ], - "razer": [ - { - "title": "The Hovering Mouse - Project McFly | Razer", - "link": "https://youtu.be/IlCx5gjAmqI" - }, - { - "title": "Be the Machine | Project Venom v2", - "link": "https://youtu.be/j8UJE7DoyJ8" - } - ] -} +[ + { + "url": "https://youtu.be/OYcv406J_J4", + "channel": "google" + }, + { + "url": "https://youtu.be/0_5X6N6DHyk", + "channel": "google" + }, + { + "url": "https://youtu.be/UmJ2NBHXTqo", + "channel": "google" + }, + { + "url": "https://youtu.be/3MA6_21nka8", + "channel": "google" + }, + { + "url": "https://youtu.be/QAwL0O5nXe0", + "channel": "google" + }, + { + "url": "https://youtu.be/DPEJB-FCItk", + "channel": "google" + }, + { + "url": "https://youtu.be/LSZPNwZex9s", + "channel": "google" + }, + { + "url": "https://youtu.be/dFrgNiweQDk", + "channel": "google" + }, + { + "url": "https://youtu.be/F0F6SnbqUcE", + "channel": "google" + }, + { + "url": "https://youtu.be/VkOuShXpoKc", + "channel": "google" + }, + { + "url": "https://youtu.be/HQtGFBbwKEk", + "channel": "google" + }, + { + "url": "https://youtu.be/Cp10_PygJ4o", + "channel": "google" + }, + { + "url": "https://youtu.be/XTTtkisylQw", + "channel": "google" + }, + { + "url": "https://youtu.be/hydLZJXG3Tk", + "channel": "google" + }, + { + "url": "https://youtu.be/U2JBFlW--UU", + "channel": "google" + }, + { + "url": "https://youtu.be/G3NXNnoGr3Y", + "channel": "google" + }, + { + "url": "https://youtu.be/4YMD6xELI_k", + "channel": "google" + }, + { + "url": "https://youtu.be/qcgWRpQP6ds", + "channel": "google" + }, + { + "url": "https://youtu.be/Zr4JwPb99qU", + "channel": "google" + }, + { + "url": "https://youtu.be/VFbYadm_mrw", + "channel": "google" + }, + { + "url": "https://youtu.be/_qFFHC0eIUc", + "channel": "google" + }, + { + "url": "https://youtu.be/H542nLTTbu0", + "channel": "google" + }, + { + "url": "https://youtu.be/Je7Xq9tdCJc", + "channel": "google" + }, + { + "url": "https://youtu.be/re0VRK6ouwI", + "channel": "google" + }, + { + "url": "https://youtu.be/1KhZKNZO8mQ", + "channel": "google" + }, + { + "url": "https://youtu.be/UiLSiqyDf4Y", + "channel": "google" + }, + { + "url": "https://youtu.be/rznYifPHxDg", + "channel": "google" + }, + { + "url": "https://youtu.be/blB_X38YSxQ", + "channel": "google" + }, + { + "url": "https://youtu.be/Bu927_ul_X0", + "channel": "google" + }, + { + "url": "https://youtu.be/smM-Wdk2RLQ", + "channel": "nvidia" + }, + { + "url": "https://youtu.be/IlCx5gjAmqI", + "channel": "razer" + }, + { + "url": "https://youtu.be/j8UJE7DoyJ8", + "channel": "razer" + } +] -- cgit v1.2.3 From 607e83bf78728f990377cf3f8d0c3b080b07476b Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Mon, 12 Apr 2021 19:54:19 +0100 Subject: chore: remove unnecessary utility function and simplify code --- bot/exts/easter/april_fools_vids.py | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'bot') diff --git a/bot/exts/easter/april_fools_vids.py b/bot/exts/easter/april_fools_vids.py index 97cb407c..c7a3c014 100644 --- a/bot/exts/easter/april_fools_vids.py +++ b/bot/exts/easter/april_fools_vids.py @@ -1,32 +1,22 @@ import logging import random from json import load -from pathlib import Path from discord.ext import commands log = logging.getLogger(__name__) +with open("bot/resources/easter/april_fools_vids.json", encoding="utf-8") as f: + ALL_VIDS = load(f) + class AprilFoolVideos(commands.Cog): """A cog for April Fools' that gets a random April Fools' video from Youtube.""" - def __init__(self, bot: commands.Bot): - self.bot = bot - self.yt_vids = self.load_json() - - @staticmethod - def load_json() -> dict: - """A function to load JSON data.""" - p = Path('bot/resources/easter/april_fools_vids.json') - with p.open(encoding="utf-8") as json_file: - all_vids = load(json_file) - return all_vids - @commands.command(name='fool') async def april_fools(self, ctx: commands.Context) -> None: """Get a random April Fools' video from Youtube.""" - video = random.choice(self.yt_vids) + video = random.choice(ALL_VIDS) channel, url = video["channel"], video["url"] -- cgit v1.2.3 From ccdf1c9efc273f2945baed90008ab3fdd73a53a1 Mon Sep 17 00:00:00 2001 From: laundmo Date: Tue, 13 Apr 2021 15:54:03 +0200 Subject: Update issue matching regex fixes it being unable to get issue numbers larger than 9 limits it somewhat length-wise and character-wise to the actual github limits --- bot/exts/evergreen/issues.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index bb6273bb..4dd10d13 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -51,7 +51,8 @@ CODE_BLOCK_RE = re.compile( MAXIMUM_ISSUES = 5 # Regex used when looking for automatic linking in messages -AUTOMATIC_REGEX = re.compile(r"((?P.+?)\/)?(?P.+?)#(?P.+?)") +# regex101 of current regex https://regex101.com/r/V2ji8M/6 +AUTOMATIC_REGEX = re.compile(r"((?P[a-zA-Z0-9][a-zA-Z0-9\-]{1,39})\/)?(?P[\w\-\.]{1,100})#(?P[0-9]+)") @dataclass -- cgit v1.2.3 From a3ce39f9d2cb5a91743ce3e2a35535a65fa4034b Mon Sep 17 00:00:00 2001 From: laundmo Date: Tue, 13 Apr 2021 15:57:50 +0200 Subject: Linebreak to hopefully not run into linter issues editing this from the web version because im at work and this fixes the issue linking being basically unusable --- bot/exts/evergreen/issues.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py index 4dd10d13..a0316080 100644 --- a/bot/exts/evergreen/issues.py +++ b/bot/exts/evergreen/issues.py @@ -52,7 +52,9 @@ MAXIMUM_ISSUES = 5 # Regex used when looking for automatic linking in messages # regex101 of current regex https://regex101.com/r/V2ji8M/6 -AUTOMATIC_REGEX = re.compile(r"((?P[a-zA-Z0-9][a-zA-Z0-9\-]{1,39})\/)?(?P[\w\-\.]{1,100})#(?P[0-9]+)") +AUTOMATIC_REGEX = re.compile( + r"((?P[a-zA-Z0-9][a-zA-Z0-9\-]{1,39})\/)?(?P[\w\-\.]{1,100})#(?P[0-9]+)" +) @dataclass -- cgit v1.2.3 From 7d9cf84c7de1845bfdb5203ed8cf62b33b76cc3a Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Tue, 13 Apr 2021 15:45:07 +0100 Subject: feat: add ping command --- bot/exts/evergreen/ping.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 bot/exts/evergreen/ping.py (limited to 'bot') diff --git a/bot/exts/evergreen/ping.py b/bot/exts/evergreen/ping.py new file mode 100644 index 00000000..022d6373 --- /dev/null +++ b/bot/exts/evergreen/ping.py @@ -0,0 +1,27 @@ +from discord import Embed +from discord.ext import commands + +from bot.constants import Colours + + +class Ping(commands.Cog): + """Ping the bot to see its latency and state.""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + + @commands.command(name="ping") + async def ping(self, ctx: commands.Context) -> None: + """Ping the bot to see its latency and state.""" + embed = Embed( + title="Pong!", + colour=Colours.bright_green, + description=f"WS Latency: {round(self.bot.latency * 1000)}ms", + ) + + await ctx.send(embed=embed) + + +def setup(bot: commands.Bot) -> None: + """Cog load.""" + bot.add_cog(Ping(bot)) -- cgit v1.2.3 From a66058467005209b6f8b4f55dc9750ebf54c86f3 Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Tue, 13 Apr 2021 15:51:11 +0100 Subject: chore: add ping_pong emoji --- bot/exts/evergreen/ping.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/ping.py b/bot/exts/evergreen/ping.py index 022d6373..637f71e8 100644 --- a/bot/exts/evergreen/ping.py +++ b/bot/exts/evergreen/ping.py @@ -14,7 +14,7 @@ class Ping(commands.Cog): async def ping(self, ctx: commands.Context) -> None: """Ping the bot to see its latency and state.""" embed = Embed( - title="Pong!", + title=":ping_pong: Pong!", colour=Colours.bright_green, description=f"WS Latency: {round(self.bot.latency * 1000)}ms", ) -- cgit v1.2.3 From 897d892a8666b94d6bdf8a3cdee79cca63b59812 Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Tue, 13 Apr 2021 16:00:22 +0100 Subject: chore: use discord terminology Co-authored-by: Joe Banks --- bot/exts/evergreen/ping.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/evergreen/ping.py b/bot/exts/evergreen/ping.py index 637f71e8..97f8b34d 100644 --- a/bot/exts/evergreen/ping.py +++ b/bot/exts/evergreen/ping.py @@ -16,7 +16,7 @@ class Ping(commands.Cog): embed = Embed( title=":ping_pong: Pong!", colour=Colours.bright_green, - description=f"WS Latency: {round(self.bot.latency * 1000)}ms", + description=f"Gateway Latency: {round(self.bot.latency * 1000)}ms", ) await ctx.send(embed=embed) -- cgit v1.2.3 From fbe8e0a5bf4ffb4443a54588b7f55f25306eee6f Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Mon, 12 Apr 2021 21:49:45 +0100 Subject: fix: display help for the correct command when an error occurs in timed --- bot/exts/evergreen/error_handler.py | 10 ++++++++-- bot/exts/evergreen/timed.py | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/evergreen/error_handler.py b/bot/exts/evergreen/error_handler.py index 28902503..8db49748 100644 --- a/bot/exts/evergreen/error_handler.py +++ b/bot/exts/evergreen/error_handler.py @@ -46,6 +46,11 @@ class CommandErrorHandler(commands.Cog): logging.debug(f"Command {ctx.command} had its error already handled locally; ignoring.") return + parent_command = "" + if subctx := getattr(ctx, "subcontext", None): + parent_command = f"{ctx.command} " + ctx = subctx + error = getattr(error, 'original', error) logging.debug( f"Error Encountered: {type(error).__name__} - {str(error)}, " @@ -63,8 +68,9 @@ class CommandErrorHandler(commands.Cog): if isinstance(error, commands.UserInputError): self.revert_cooldown_counter(ctx.command, ctx.message) + usage = f"```{ctx.prefix}{parent_command}{ctx.command} {ctx.command.signature}```" embed = self.error_embed( - f"Your input was invalid: {error}\n\nUsage:\n```{ctx.prefix}{ctx.command} {ctx.command.signature}```" + f"Your input was invalid: {error}\n\nUsage:{usage}" ) await ctx.send(embed=embed) return @@ -95,7 +101,7 @@ class CommandErrorHandler(commands.Cog): self.revert_cooldown_counter(ctx.command, ctx.message) embed = self.error_embed( "The argument you provided was invalid: " - f"{error}\n\nUsage:\n```{ctx.prefix}{ctx.command} {ctx.command.signature}```" + f"{error}\n\nUsage:\n```{ctx.prefix}{parent_command}{ctx.command} {ctx.command.signature}```" ) await ctx.send(embed=embed) return diff --git a/bot/exts/evergreen/timed.py b/bot/exts/evergreen/timed.py index 635ccb32..5f177fd6 100644 --- a/bot/exts/evergreen/timed.py +++ b/bot/exts/evergreen/timed.py @@ -21,7 +21,9 @@ class TimedCommands(commands.Cog): """Time the command execution of a command.""" new_ctx = await self.create_execution_context(ctx, command) - if not new_ctx.command: + ctx.subcontext = new_ctx + + if not ctx.subcontext.command: help_command = f"{ctx.prefix}help" error = f"The command you are trying to time doesn't exist. Use `{help_command}` for a list of commands." -- cgit v1.2.3