From 23e69a01c69e773711e01ed40496f1c391004cd9 Mon Sep 17 00:00:00 2001 From: Phxntxm Date: Sun, 5 Mar 2017 20:45:44 -0600 Subject: [PATCH] Update to work with the rewrite: Batch 1 --- cogs/blackjack.py | 152 ++++++++++++++------------- cogs/chess.py | 44 ++++---- cogs/core.py | 98 +++++++---------- cogs/da.py | 22 ++-- cogs/disabled_playlist.py | 28 ++--- cogs/events.py | 37 ++----- cogs/hangman.py | 34 +++--- cogs/interaction.py | 66 ++++++------ cogs/links.py | 73 +++++++------ cogs/mod.py | 215 +++++++++++++++++--------------------- 10 files changed, 357 insertions(+), 412 deletions(-) diff --git a/cogs/blackjack.py b/cogs/blackjack.py index 1201195..e775eb2 100644 --- a/cogs/blackjack.py +++ b/cogs/blackjack.py @@ -34,17 +34,17 @@ class Blackjack: # When we're done with the game, we need to delete the game itself and remove it's instance from games # To do this, it needs to be able to access this instance of Blackjack game = Game(self.bot, message, self) - self.games[message.server.id] = game + self.games[message.guild.id] = game - @commands.group(pass_context=True, no_pm=True, aliases=['bj'], invoke_without_command=True) + @commands.group(no_pm=True, aliases=['bj'], invoke_without_command=True) @utils.custom_perms(send_messages=True) async def blackjack(self, ctx): """Creates a game/joins the current running game of blackjack EXAMPLE: !blackjack RESULT: A new game of blackjack!""" - # Get this server's game if it exists - game = self.games.get(ctx.message.server.id) + # Get this guild's game if it exists + game = self.games.get(ctx.message.guild.id) # If it doesn't, start one if game is None: self.create_game(ctx.message) @@ -54,15 +54,15 @@ class Blackjack: # If it worked, they're ready to play if status: fmt = "{} has joined the game of blackjack, and will be able to play next round!" - await self.bot.say(fmt.format(ctx.message.author.display_name)) + await ctx.send(fmt.format(ctx.message.author.display_name)) else: # Otherwise, lets check *why* they couldn't join if game.playing(ctx.message.author): - await self.bot.say("You are already playing! Wait for your turn!") + await ctx.send("You are already playing! Wait for your turn!") else: - await self.bot.say("There are already a max number of players playing/waiting to play!") + await ctx.send("There are already a max number of players playing/waiting to play!") - @blackjack.command(pass_context=True, no_pm=True, name='leave', aliases=['quit']) + @blackjack.command(no_pm=True, name='leave', aliases=['quit']) @utils.custom_perms(send_messages=True) async def blackjack_leave(self, ctx): """Leaves the current game of blackjack @@ -70,37 +70,37 @@ class Blackjack: EXAMPLE: !blackjack leave RESULT: You stop losing money in blackjack""" - # Get this server's game if it exists - game = self.games.get(ctx.message.server.id) + # Get this guild's game if it exists + game = self.games.get(ctx.message.guild.id) if game is None: - await self.bot.say("There are currently no games of Blackjack running!") + await ctx.send("There are currently no games of Blackjack running!") return status = game.leave(ctx.message.author) if status: - await self.bot.say("You have left the game, and will be removed at the end of this round") + await ctx.send("You have left the game, and will be removed at the end of this round") else: - await self.bot.say("Either you have already bet, or you are not even playing right now!") + await ctx.send("Either you have already bet, or you are not even playing right now!") - @blackjack.command(pass_context=True, no_pm=True, name='forcestop', aliases=['stop']) - @utils.custom_perms(manage_server=True) + @blackjack.command(no_pm=True, name='forcestop', aliases=['stop']) + @utils.custom_perms(manage_guild=True) async def blackjack_stop(self, ctx): """Forces the game to stop, mostly for use if someone has gone afk EXAMPLE: !blackjack forcestop RESULT: No more blackjack spam""" - # Get this server's game if it exists - game = self.games.get(ctx.message.server.id) + # Get this guild's game if it exists + game = self.games.get(ctx.message.guild.id) if game is None: - await self.bot.say("There are currently no games of Blackjack running!") + await ctx.send("There are currently no games of Blackjack running!") return game.task.cancel() - del self.games[ctx.message.server.id] - await self.bot.say("The blackjack game running here has just ended") + del self.games[ctx.message.guild.id] + await ctx.send("The blackjack game running here has just ended") def FOIL(a, b): @@ -226,7 +226,7 @@ class Game: async def game_task(self): """The task to handle the entire game""" while len(self.players) > 0: - await self.bot.send_message(self.channel, "A new round has started!!") + await self.channel.send("A new round has started!!") # First wait for bets await self.bet_task() @@ -253,25 +253,25 @@ class Game: await self.cleanup() # If we reach the end of this loop, that means there are no more players - del self.bj.games[self.channel.server.id] + del self.bj.games[self.channel.guild.id] async def dealer_task(self): """The task handling the dealer's play after all players have stood""" fmt = "It is the dealer's turn to play\n\n{}".format(self.dealer) - msg = await self.bot.send_message(self.channel, fmt) + msg = await self.channel.send(fmt) while True: await asyncio.sleep(1) if self.dealer.bust: fmt = msg.content + "\n\nDealer has busted!!" - await self.bot.edit_message(msg, fmt) + await msg.edit(content=fmt) return for num in self.dealer.count: if num > 16: return self.hit(self.dealer) fmt = "It is the dealer's turn to play\n\n{}".format(self.dealer) - msg = await self.bot.edit_message(msg, fmt) + msg = await msg.edit(content=fmt) async def round_task(self): """The task handling the round itself, asking each person to hit or stand""" @@ -280,21 +280,25 @@ class Game: # A differen task will handle if a player hit blackjack to start (so they would not be 'playing') # Our check to make sure a valid 'command' was provided - check = lambda m: m.content.lower() in ['hit', 'stand', 'double'] + def check(m): + if m.channel == self.channel && m.author = player.member: + return m.content.lower() in ['hit', 'stand', 'double'] + else: + return False # First lets handle the blackjacks for entry in [p for p in self.players if p['status'] == 'blackjack']: player = entry['player'] fmt = "You got a blackjack {0.member.mention}!\n\n{0}".format(player) - await self.bot.send_message(self.channel, fmt) + await self.channel.send(fmt) # Loop through each player (as long as their status is playing) and they have bet chips for entry in [p for p in self.players if p['status'] == 'playing' and hasattr(p['player'], 'bet')]: player = entry['player'] # Let them know it's their turn to play fmt = "It is your turn to play {0.member.mention}\n\n{0}".format(player) - await self.bot.send_message(self.channel, fmt) + await self.channel.send(fmt) # If they're not playing anymore (i.e. they busted, are standing, etc.) then we don't want to keep asking # them to hit or stand @@ -302,37 +306,28 @@ class Game: # Ask if they want to hit or stand fmt = "Hit, stand, or double?" - await self.bot.send_message(self.channel, fmt) - msg = await self.bot.wait_for_message(timeout=60, author=player.member, channel=self.channel, - check=check) + await self.channel.send(fmt) - # If they took to long, make them stand so the next person can play - if msg is None: - await self.bot.send_message(self.channel, "Took to long! You're standing!") + try: + msg = await self.bot.wait_for('message', timeout=60, check=check) + except asyncio.TimeoutError: + await self.channel.send("Took to long! You're standing!") entry['status'] = 'stand' - # If they want to hit - elif 'hit' in msg.content.lower(): - self.hit(player) - await self.bot.send_message(self.channel, player) - # If they want to stand - elif 'stand' in msg.content.lower(): - self.stand(player) - elif 'double' in msg.content.lower(): - self.double(player) - await self.bot.send_message(self.channel, player) - # TODO: Handle double, split + else: + # If they want to hit + if 'hit' in msg.content.lower(): + self.hit(player) + await self.channel.send(player) + # If they want to stand + elif 'stand' in msg.content.lower(): + self.stand(player) + elif 'double' in msg.content.lower(): + self.double(player) + await self.channel.send(player) + # TODO: Handle double, split async def bet_task(self): """Performs the task of betting""" - - def check(_msg): - """Makes sure the message provided is within the min and max bets""" - try: - msg_length = int(_msg.content) - return self.min_bet <= msg_length <= self.max_bet - except ValueError: - return _msg.content.lower() == 'skip' - # There is one situation that we want to allow that means we cannot loop through players like normally would # be the case: Betting has started; while one person is betting, another joins This means our list has # changed, and neither based on the length or looping through the list itself will handle this To handle @@ -348,28 +343,43 @@ class Game: entry = players[0] player = entry['player'] + def check(_msg): + """Makes sure the message provided is within the min and max bets""" + if _msg.channel == self.channel and _msg.author == player.member: + try: + msg_length = int(_msg.content) + return self.min_bet <= msg_length <= self.max_bet + except ValueError: + return _msg.content.lower() == 'skip' + else: + return false + fmt = "Your turn to bet {0.member.mention}, your current chips are: {0.chips}\n" \ "Current min bet is {1}, current max bet is {2}\n" \ "Place your bet now (please provide only the number;" \ "'skip' if you would like to leave this game)".format(player, self.min_bet, self.max_bet) - await self.bot.send_message(self.channel, fmt) - msg = await self.bot.wait_for_message(timeout=60, author=player.member, channel=self.channel, check=check) - if msg is None: - await self.bot.send_message(self.channel, "You took too long! You're sitting this round out") + await self.channel.send(fmt) + + try: + msg = await self.bot.wait_for("message", timeout=60, check=check) + except asyncio.TimeoutError: + await self.channel.send("You took too long! You're sitting this round out") entry['status'] = 'stand' - elif msg.content.lower() == 'skip': - await self.bot.send_message(self.channel, "Alright, you've been removed from the game") - self.leave(player.member) else: - num = int(msg.content) - # Set the new bet, and remove it from this players chip total - if num <= player.chips: - player.bet = num - player.chips -= num - entry['status'] = 'bet' + if msg.content.lower() == 'skip': + await self.channel.send("Alright, you've been removed from the game") + self.leave(player.member) else: - await self.bot.send_message(self.channel, "You can't bet more than you have!!") + num = int(msg.content) + # Set the new bet, and remove it from this players chip total + if num <= player.chips: + player.bet = num + player.chips -= num + entry['status'] = 'bet' + else: + await self.channel.send("You can't bet more than you have!!") + # Call this so that we can correct the list, if someone has left or join self.player_cleanup() @@ -464,7 +474,7 @@ class Game: # Add that to the main string fmt += "Blackjacks: {}\n".format(_fmt) - await self.bot.send_message(self.channel, fmt) + await self.channel.send(fmt) # Do the same for the dealers hand cards = list(self.dealer.hand.draw(self.dealer.hand.count)) @@ -481,10 +491,10 @@ class Game: self.players.extend(self._added_players) self._added_players.clear() - # What we want to do is remove any players that are in the game and have left the server + # What we want to do is remove any players that are in the game and have left the guild for entry in self.players: m = entry['player'].member - if m not in self.channel.server.members: + if m not in self.channel.guild.members: self._removed_players.append(entry['player']) # Remove the players who left diff --git a/cogs/chess.py b/cogs/chess.py index 1bf2fd8..6922aa2 100644 --- a/cogs/chess.py +++ b/cogs/chess.py @@ -10,7 +10,7 @@ from enum import Enum class Chess: def __init__(self, bot): self.bot = bot - # Our format for games is going to be a little different, because we do want to allow multiple games per server + # Our format for games is going to be a little different, because we do want to allow multiple games per guild # Format should be {'server_id': [Game, Game, Game]} self.games = {} @@ -91,18 +91,18 @@ class Chess: return MoveStatus.invalid def get_game(self, player): - """Provides the game this player is playing, in this server""" - server_games = self.games.get(player.server.id, []) - for game in server_games: + """Provides the game this player is playing, in this guild""" + guild_games = self.games.get(player.guild.id, []) + for game in guild_games: if player in game.challengers.values(): return game return None def in_game(self, player): - """Checks to see if a player is playing in a game right now, in this server""" - server_games = self.games.get(player.server.id, []) - for game in server_games: + """Checks to see if a player is playing in a game right now, in this guild""" + guild_games = self.games.get(player.guild.id, []) + for game in guild_games: if player in game.challengers.values(): return True @@ -111,13 +111,13 @@ class Chess: def start_game(self, player1, player2): game = Game(player1, player2) try: - self.games[player1.server.id].append(game) + self.games[player1.guild.id].append(game) except KeyError: - self.games[player1.server.id] = [game] + self.games[player1.guild.id] = [game] return game - @commands.group(pass_contxt=True, invoke_without_command=True) + @commands.group(invoke_without_command=True) @checks.custom_perms(send_messages=True) async def chess(self, ctx, *, move): """Moves a piece based on the notation provided @@ -142,45 +142,45 @@ class Chess: EXAMPLE: !rook to d4""" result = self.play(ctx.message.author, move) if result is MoveStatus.invalid: - await self.bot.say("That was an invalid move!") + await ctx.send("That was an invalid move!") elif result is MoveStatus.wrong_turn: - await self.bot.say("It is not your turn to play on your game in this server!") + await ctx.send("It is not your turn to play on your game in this guild!") elif result is MoveStatus.no_game: - await self.bot.say("You are not currently playing a game on this server!") + await ctx.send("You are not currently playing a game on this guild!") elif result is MoveStatus.valid: game = self.get_game(ctx.message.author) link = game.draw_board() await self.bot.upload(link) - @commands.command(pass_context=True) + @commands.command() @checks.custom_perms(send_messages=True) async def chess_start(self, ctx, player2: discord.Member): """Starts a chess game with another player - You can play one game on a single server at a time + You can play one game on a single guild at a time EXAMPLE: !chess start @Victim RESULT: A new chess game! Good luck~""" # Lets first check our permissions; we're not going to create a text based board # So we need to be able to attach files in order to send the board - if not ctx.message.channel.permissions_for(ctx.message.server.me).attach_files: - await self.bot.say( + if not ctx.message.channel.permissions_for(ctx.message.guild.me).attach_files: + await ctx.send( "I need to be able to send pictures to provide the board! Please ask someone with mange roles permission, to grant me attach files permission if you want to play this") return # Make sure the author and player 2 are not in a game already if self.in_game(ctx.message.author): - await self.bot.say("Sorry, but you can only be in one game per server at a time") + await ctx.send("Sorry, but you can only be in one game per guild at a time") return if self.in_game(player2): - await self.bot.say("Sorry, but {} is already in a game on this server!".format(player2.display_name)) + await ctx.send("Sorry, but {} is already in a game on this guild!".format(player2.display_name)) return # Start the game game = self.start_game(ctx.message.author, player2) player1 = game.challengers.get('white') - await self.bot.say( + await ctx.send( "{} you have started a chess game with {}\n\n{} will be white this game, and is going first.\nIf you need information about the notation used to play, run {}help chess".format( ctx.message.author.display_name, player2.display_name, ctx.prefix)) @@ -209,7 +209,7 @@ class Game: self.reset_board() # The point of chess revolves around the king's position - # Due to this, we're going to use the king's position a lot, so lets save this variable + # Due to this, we're going to use the king's position a lot, so lets save this variable self.w_king_pos = (0, 4) self.b_king_pos = (7, 4) @@ -388,7 +388,7 @@ class Game: def check(self): """Checks our current board, and checks (based on whose turn it is) if we're in a 'check' state""" # To check for a check, what we should do is loop through the board - # Then check if it's the the current players turn's piece, and compare to moving to the king's position + # Then check if it's the the current players turn's piece, and compare to moving to the king's position for x, row in enumerate(self.board): for y, piece in enumerate(row): if self.white_turn and re.search('B.', piece) and self.valid_move((x, y), self.b_king_pos): diff --git a/cogs/core.py b/cogs/core.py index 646583f..bbb8bb8 100644 --- a/cogs/core.py +++ b/cogs/core.py @@ -23,30 +23,7 @@ class Core: self.results_per_page = 10 self.commands = None - def find_command(self, command): - # This method ensures the command given is valid. We need to loop through commands - # As self.bot.commands only includes parent commands - # So we are splitting the command in parts, looping through the commands - # And getting the subcommand based on the next part - # If we try to access commands of a command that isn't a group - # We'll hit an AttributeError, meaning an invalid command was given - # If we loop through and don't find anything, cmd will still be None - # And we'll report an invalid was given as well - cmd = None - - for part in command.split(): - try: - if cmd is None: - cmd = self.bot.commands.get(part) - else: - cmd = cmd.commands.get(part) - except AttributeError: - cmd = None - break - - return cmd - - @commands.command(pass_context=True) + @commands.command() @utils.custom_perms(send_messages=True) async def help(self, ctx, *, message=None): """This command is used to provide a link to the help URL. @@ -65,7 +42,7 @@ class Core: try: page = int(message) except: - cmd = self.find_command(message) + cmd = self.bot.get_command(message) if cmd is None: entries = sorted(utils.get_all_commands(self.bot)) @@ -73,7 +50,7 @@ class Core: pages = utils.Pages(self.bot, message=ctx.message, entries=entries) await pages.paginate(start_page=page) except utils.CannotPaginate as e: - await self.bot.say(str(e)) + await ctx.send(str(e)) else: # Get the description for a command description = cmd.help @@ -100,11 +77,11 @@ class Core: if subcommands: embed.add_field(name='Subcommands', value="\n".join(subcommands), inline=False) - await self.bot.say(embed=embed) + await ctx.send(embed=embed) @commands.command() @utils.custom_perms(send_messages=True) - async def motd(self, *, date=None): + async def motd(self, ctx, *, date=None): """This command can be used to print the current MOTD (Message of the day) This will most likely not be updated every day, however messages will still be pushed to this every now and then @@ -126,10 +103,10 @@ class Core: motd = latest_motd['motd'] # This will be hit if we do not have any entries for motd except TypeError: - await self.bot.say("No message of the day!") + await ctx.send("No message of the day!") else: fmt = "Last updated: {}\n\n{}".format(date, motd) - await self.bot.say(fmt) + await ctx.send(fmt) else: try: r_filter = pendulum.parse(date) @@ -137,18 +114,18 @@ class Core: date = motd[0]['date'] motd = motd[0]['motd'] fmt = "Message of the day for {}:\n\n{}".format(date, motd) - await self.bot.say(fmt) + await ctx.send(fmt) # This one will be hit if we return None for that day except TypeError: - await self.bot.say("No message of the day for {}!".format(date)) + await ctx.send("No message of the day for {}!".format(date)) # This will be hit if pendulum fails to parse the date passed except ValueError: now = pendulum.utcnow().to_date_string() - await self.bot.say("Invalid date format! Try like {}".format(now)) + await ctx.send("Invalid date format! Try like {}".format(now)) @commands.command() @utils.custom_perms(send_messages=True) - async def calendar(self, month: str = None, year: int = None): + async def calendar(self, ctx, month: str = None, year: int = None): """Provides a printout of the current month's calendar Provide month and year to print the calendar of that year and month @@ -176,30 +153,23 @@ class Core: else: month = months.get(month.lower()) if month is None: - await self.bot.say("Please provide a valid Month!") + await ctx.send("Please provide a valid Month!") return # If year was not passed, use the current year if year is None: year = datetime.datetime.today().year # Here we create the actual "text" calendar that we are printing cal = calendar.TextCalendar().formatmonth(year, month) - await self.bot.say("```\n{}```".format(cal)) + await ctx.send("```\n{}```".format(cal)) @commands.command() @utils.custom_perms(send_messages=True) - async def info(self): + async def info(self, ctx): """This command can be used to print out some of my information""" # fmt is a dictionary so we can set the key to it's output, then print both # The only real use of doing it this way is easier editing if the info # in this command is changed - bot_data = await utils.get_content('bot_data') - total_data = {'member_count': 0, - 'server_count': 0} - for entry in bot_data: - total_data['member_count'] += entry['member_count'] - total_data['server_count'] += entry['server_count'] - # Create the original embed object opts = {'title': 'Dev Server', 'description': 'Join the server above for any questions/suggestions about me.', @@ -207,8 +177,8 @@ class Core: embed = discord.Embed(**opts) # Add the normal values - embed.add_field(name='Total Servers', value=total_data['server_count']) - embed.add_field(name='Total Members', value=total_data['member_count']) + embed.add_field(name='Total Servers', value=len(self.bot.servers)) + embed.add_field(name='Total Members', value=len(set(self.bot.get_all_members()))) # Count the variable values; hangman, tictactoe, etc. hm_games = len(self.bot.get_cog('Hangman').games) @@ -233,20 +203,20 @@ class Core: embed.add_field(name='Uptime', value=(pendulum.utcnow() - self.bot.uptime).in_words()) embed.set_footer(text=self.bot.description) - await self.bot.say(embed=embed) + await ctx.send(embed=embed) @commands.command() @utils.custom_perms(send_messages=True) - async def uptime(self): + async def uptime(self, ctx): """Provides a printout of the current bot's uptime EXAMPLE: !uptime RESULT: A BAJILLION DAYS""" - await self.bot.say("Uptime: ```\n{}```".format((pendulum.utcnow() - self.bot.uptime).in_words())) + await ctx.send("Uptime: ```\n{}```".format((pendulum.utcnow() - self.bot.uptime).in_words())) @commands.command(aliases=['invite']) @utils.custom_perms(send_messages=True) - async def addbot(self): + async def addbot(self, ctx): """Provides a link that you can use to add me to a server EXAMPLE: !addbot @@ -261,13 +231,17 @@ class Core: perms.embed_links = True perms.read_message_history = True perms.attach_files = True + perms.speak = True + perms.connect = True + perms.attach_files = True + perms.add_reactions = True app_info = await self.bot.application_info() - await self.bot.say("Use this URL to add me to a server that you'd like!\n{}" + await ctx.send("Use this URL to add me to a server that you'd like!\n{}" .format(discord.utils.oauth_url(app_info.id, perms))) @commands.command() @utils.custom_perms(send_messages=True) - async def doggo(self): + async def doggo(self, ctx): """Use this to print a random doggo image. EXAMPLE: !doggo @@ -275,7 +249,7 @@ class Core: # Find a random image based on how many we currently have f = random.SystemRandom().choice(glob.glob('images/doggo*')) with open(f, 'rb') as f: - await self.bot.upload(f) + await ctx.send(file=f) @commands.command() @utils.custom_perms(send_messages=True) @@ -287,11 +261,11 @@ class Core: # Find a random image based on how many we currently have f = random.SystemRandom().choice(glob.glob('images/snek*')) with open(f, 'rb') as f: - await self.bot.upload(f) + await ctx.send(file=f) @commands.command() @utils.custom_perms(send_messages=True) - async def joke(self): + async def joke(self, ctx): """Prints a random riddle EXAMPLE: !joke @@ -302,13 +276,13 @@ class Core: try: fortune = subprocess.check_output( fortune_command.split()).decode("utf-8") - await self.bot.say(fortune) + await ctx.send(fortune) except discord.HTTPException: pass else: break - @commands.command(pass_context=True) + @commands.command() @utils.custom_perms(send_messages=True) async def roll(self, ctx, notation: str = "d6"): """Rolls a die based on the notation given @@ -325,7 +299,7 @@ class Core: # Check if something like ed3 was provided, or something else entirely # was provided except (AttributeError, ValueError): - await self.bot.say("Please provide the die notation in #d#!") + await ctx.send("Please provide the die notation in #d#!") return # Dice will be None if d# was provided, assume this means 1d# @@ -334,13 +308,13 @@ class Core: # have it set dice = int(dice) if dice > 10: - await self.bot.say("I'm not rolling more than 10 dice, I have tiny hands") + await ctx.send("I'm not rolling more than 10 dice, I have tiny hands") return if num > 100: - await self.bot.say("What die has more than 100 sides? Please, calm down") + await ctx.send("What die has more than 100 sides? Please, calm down") return if num <= 1: - await self.bot.say("A {} sided die? You know that's impossible right?".format(num)) + await ctx.send("A {} sided die? You know that's impossible right?".format(num)) return value_str = ", ".join(str(random.SystemRandom().randint(1, num)) @@ -350,7 +324,7 @@ class Core: fmt = '{0.message.author.name} has rolled a {2} sided die and got the number {3}!' else: fmt = '{0.message.author.name} has rolled {1}, {2} sided dice and got the numbers {3}!' - await self.bot.say(fmt.format(ctx, dice, num, value_str)) + await ctx.send(fmt.format(ctx, dice, num, value_str)) def setup(bot): diff --git a/cogs/da.py b/cogs/da.py index 7adb2d5..7a6d092 100644 --- a/cogs/da.py +++ b/cogs/da.py @@ -59,9 +59,7 @@ class Deviantart: try: for entry in content: user = discord.utils.get(self.bot.get_all_members(), id=entry['member_id']) - - # If we're sharded, we might not be able to find this user. - # If the bot is not in the server with the member either + # If the bot is not in the server with the member, we might not be able to find this user. if user is None: continue @@ -97,7 +95,7 @@ class Deviantart: result['title'], result['author']['username'], result['url']) - await self.bot.send_message(user, fmt) + await user.sendfmt) # Now we can update the user's last updated for this DA # We want to do this whether or not our last if statement was met r_filter = {'member_id': user.id} @@ -110,12 +108,12 @@ class Deviantart: @commands.group() @utils.custom_perms(send_messages=True) - async def da(self): + async def da(self, ctx): """This provides a sort of 'RSS' feed for subscribed to artists. Subscribe to artists, and I will PM you when new posts come out from these artists""" pass - @da.command(pass_context=True, name='sub', aliases=['add', 'subscribe']) + @da.command(name='sub', aliases=['add', 'subscribe']) @utils.custom_perms(send_messages=True) async def da_sub(self, ctx, *, username): """This can be used to add a feed to your notifications. @@ -130,7 +128,7 @@ class Deviantart: if content is None: entry = {'member_id': ctx.message.author.id, 'subbed': [username], 'last_updated': {}} await utils.add_content('deviantart', entry, r_filter) - await self.bot.say("You have just subscribed to {}!".format(username)) + await ctx.send("You have just subscribed to {}!".format(username)) elif content[0]['subbed'] is None or username not in content[0]['subbed']: if content[0]['subbed'] is None: sub_list = [username] @@ -138,9 +136,9 @@ class Deviantart: content[0]['subbed'].append(username) sub_list = content[0]['subbed'] await utils.update_content('deviantart', {'subbed': sub_list}, r_filter) - await self.bot.say("You have just subscribed to {}!".format(username)) + await ctx.send("You have just subscribed to {}!".format(username)) else: - await self.bot.say("You are already subscribed to that user!") + await ctx.send("You are already subscribed to that user!") @da.command(pass_context=True, name='unsub', aliases=['delete', 'remove', 'unsubscribe']) @utils.custom_perms(send_messages=True) @@ -153,13 +151,13 @@ class Deviantart: content = await utils.get_content('deviantart', r_filter) if content is None or content[0]['subbed'] is None: - await self.bot.say("You are not subscribed to anyone at the moment!") + await ctx.send("You are not subscribed to anyone at the moment!") elif username in content[0]['subbed']: content[0]['subbed'].remove(username) await utils.update_content('deviantart', {'subbed': content[0]['subbed']}, r_filter) - await self.bot.say("You have just unsubscribed from {}!".format(username)) + await ctx.send("You have just unsubscribed from {}!".format(username)) else: - await self.bot.say("You are not subscribed to that user!") + await ctx.send("You are not subscribed to that user!") def setup(bot): diff --git a/cogs/disabled_playlist.py b/cogs/disabled_playlist.py index 90703bc..3ec748f 100644 --- a/cogs/disabled_playlist.py +++ b/cogs/disabled_playlist.py @@ -19,7 +19,7 @@ class Music: async def on_voice_state_update(self, before, after): pass - @commands.command(pass_context=True, no_pm=True, enabled=False) + @commands.command(no_pm=True, enabled=False) @checks.custom_perms(send_messages=True) async def progress(self, ctx): """Provides the progress of the current song @@ -28,7 +28,7 @@ class Music: RESULT: 532 minutes! (Hopefully not)""" pass - @commands.command(pass_context=True, no_pm=True, enabled=False) + @commands.command(no_pm=True, enabled=False) @checks.custom_perms(send_messages=True) async def join(self, ctx, *, channel: discord.Channel): """Joins a voice channel. @@ -37,7 +37,7 @@ class Music: RESULT: I'm in the Music voice channel!""" pass - @commands.command(pass_context=True, no_pm=True, enabled=False) + @commands.command(no_pm=True, enabled=False) @checks.custom_perms(send_messages=True) async def summon(self, ctx): """Summons the bot to join your voice channel. @@ -46,7 +46,7 @@ class Music: RESULT: I'm in your voice channel!""" pass - @commands.command(pass_context=True, no_pm=True, enabled=False) + @commands.command(no_pm=True, enabled=False) @checks.custom_perms(send_messages=True) async def play(self, ctx, *, song: str): """Plays a song. @@ -61,7 +61,7 @@ class Music: """ pass - @commands.command(pass_context=True, no_pm=True, enabled=False) + @commands.command(no_pm=True, enabled=False) @checks.custom_perms(kick_members=True) async def volume(self, ctx, value: int = None): """Sets the volume of the currently playing song. @@ -70,7 +70,7 @@ class Music: RESULT: My volume is now set to 50""" pass - @commands.command(pass_context=True, no_pm=True, enabled=False) + @commands.command(no_pm=True, enabled=False) @checks.custom_perms(kick_members=True) async def pause(self, ctx): """Pauses the currently played song. @@ -79,7 +79,7 @@ class Music: RESULT: I'm paused!""" pass - @commands.command(pass_context=True, no_pm=True, enabled=False) + @commands.command(no_pm=True, enabled=False) @checks.custom_perms(kick_members=True) async def resume(self, ctx): """Resumes the currently played song. @@ -88,7 +88,7 @@ class Music: RESULT: Ain't paused no more!""" pass - @commands.command(pass_context=True, no_pm=True, enabled=False) + @commands.command(no_pm=True, enabled=False) @checks.custom_perms(kick_members=True) async def stop(self, ctx): """Stops playing audio and leaves the voice channel. @@ -98,7 +98,7 @@ class Music: RESULT: No more music""" pass - @commands.command(pass_context=True, no_pm=True, enabled=False) + @commands.command(no_pm=True, enabled=False) @checks.custom_perms(send_messages=True) async def eta(self, ctx): """Provides an ETA on when your next song will play @@ -107,7 +107,7 @@ class Music: RESULT: 5,000 days! Lol have fun""" pass - @commands.command(pass_context=True, no_pm=True, enabled=False) + @commands.command(no_pm=True, enabled=False) @checks.custom_perms(send_messages=True) async def queue(self, ctx): """Provides a printout of the songs that are in the queue. @@ -121,7 +121,7 @@ class Music: RESULT: A list of shitty songs you probably don't wanna listen to""" pass - @commands.command(pass_context=True, no_pm=True, enabled=False) + @commands.command(no_pm=True, enabled=False) @checks.custom_perms(send_messages=True) async def queuelength(self, ctx): """Prints the length of the queue @@ -130,7 +130,7 @@ class Music: RESULT: Probably 10 songs""" pass - @commands.command(pass_context=True, no_pm=True, enabled=False) + @commands.command(no_pm=True, enabled=False) @checks.custom_perms(send_messages=True) async def skip(self, ctx): """Vote to skip a song. The song requester can automatically skip. @@ -142,7 +142,7 @@ class Music: """ pass - @commands.command(pass_context=True, no_pm=True, enabled=False) + @commands.command(no_pm=True, enabled=False) @checks.custom_perms(kick_members=True) async def modskip(self, ctx): """Forces a song skip, can only be used by a moderator @@ -151,7 +151,7 @@ class Music: RESULT: No more terrible song :D""" pass - @commands.command(pass_context=True, no_pm=True, enabled=False) + @commands.command(no_pm=True, enabled=False) @checks.custom_perms(send_messages=True) async def playing(self, ctx): """Shows info about the currently played song. diff --git a/cogs/events.py b/cogs/events.py index eb9bd49..866eefe 100644 --- a/cogs/events.py +++ b/cogs/events.py @@ -48,38 +48,17 @@ class StatsUpdate: log.info('bots.discord.pw statistics returned {} for {}'.format(resp.status, payload)) async def on_server_join(self, server): - r_filter = {'shard_id': config.shard_id} - server_count = len(self.bot.servers) - member_count = len(set(self.bot.get_all_members())) - entry = {'server_count': server_count, 'member_count': member_count, "shard_id": config.shard_id} - # Check if this was successful, if it wasn't, that means a new shard was added and we need to add that entry - if not await config.update_content('bot_data', entry, r_filter): - await config.add_content('bot_data', entry, r_filter) self.bot.loop.create_task(self.update()) async def on_server_leave(self, server): - r_filter = {'shard_id': config.shard_id} - server_count = len(self.bot.servers) - member_count = len(set(self.bot.get_all_members())) - entry = {'server_count': server_count, 'member_count': member_count, "shard_id": config.shard_id} - # Check if this was successful, if it wasn't, that means a new shard was added and we need to add that entry - if not await config.update_content('bot_data', entry, r_filter): - await config.add_content('bot_data', entry, r_filter) self.bot.loop.create_task(self.update()) async def on_ready(self): - r_filter = {'shard_id': config.shard_id} - server_count = len(self.bot.servers) - member_count = len(set(self.bot.get_all_members())) - entry = {'server_count': server_count, 'member_count': member_count, "shard_id": config.shard_id} - # Check if this was successful, if it wasn't, that means a new shard was added and we need to add that entry - if not await config.update_content('bot_data', entry, r_filter): - await config.add_content('bot_data', entry, r_filter) self.bot.loop.create_task(self.update()) async def on_member_join(self, member): - server = member.server - r_filter = {'server_id': server.id} + guild = member.guild + r_filter = {'server_id': guild.id} notifications = await config.get_content('user_notifications', r_filter) try: @@ -91,12 +70,12 @@ class StatsUpdate: if not channel_id: return - channel = server.get_channel(channel_id) - await self.bot.send_message(channel, "Welcome to the '{0.server.name}' server {0.mention}!".format(member)) + channel = guild.get_channel(channel_id) + await channel.send("Welcome to the '{0.server.name}' server {0.mention}!".format(member)) async def on_member_remove(self, member): - server = member.server - r_filter = {'server_id': server.id} + guild = member.guild + r_filter = {'server_id': guild.id} notifications = await config.get_content('user_notifications', r_filter) try: @@ -109,9 +88,7 @@ class StatsUpdate: return channel = server.get_channel(channel_id) - await self.bot.send_message(channel, - "{0} has left the server, I hope it wasn't because of something I said :c".format( - member.display_name)) + await channelsend("{0} has left the server, I hope it wasn't because of something I said :c".format(member.display_name)) def setup(bot): diff --git a/cogs/hangman.py b/cogs/hangman.py index 9a188b3..cfd5798 100644 --- a/cogs/hangman.py +++ b/cogs/hangman.py @@ -104,10 +104,10 @@ class Hangman: def create(self, word, ctx): # Create a new game, then save it as the server's game game = Game(word) - self.games[ctx.message.server.id] = game + self.games[ctx.message.guild.id] = game return game - @commands.group(aliases=['hm'], pass_context=True, no_pm=True, invoke_without_command=True) + @commands.group(aliases=['hm'], no_pm=True, invoke_without_command=True) @commands.cooldown(1, 7, BucketType.user) @checks.custom_perms(send_messages=True) async def hangman(self, ctx, *, guess): @@ -115,10 +115,10 @@ class Hangman: EXAMPLE: !hangman e (or) !hangman The Phrase! RESULT: Hopefully a win!""" - game = self.games.get(ctx.message.server.id) + game = self.games.get(ctx.message.guild.id) if not game: ctx.command.reset_cooldown(ctx) - await self.bot.say("There are currently no hangman games running!") + await ctx.send("There are currently no hangman games running!") return # Check if we are guessing a letter or a phrase. Only one letter can be guessed at a time @@ -128,7 +128,7 @@ class Hangman: if len(guess) == 1: if guess in game.guessed_letters: ctx.command.reset_cooldown(ctx) - await self.bot.say("That letter has already been guessed!") + await ctx.send("That letter has already been guessed!") # Return here as we don't want to count this as a failure return if game.guess_letter(guess): @@ -143,16 +143,16 @@ class Hangman: if game.win(): fmt += " You guys got it! The word was `{}`".format(game.word) - del self.games[ctx.message.server.id] + del self.games[ctx.message.guild.id] elif game.failed(): fmt += " Sorry, you guys failed...the word was `{}`".format(game.word) - del self.games[ctx.message.server.id] + del self.games[ctx.message.guild.id] else: fmt += str(game) - await self.bot.say(fmt) + await ctx.send(fmt) - @hangman.command(name='create', aliases=['start'], no_pm=True, pass_context=True) + @hangman.command(name='create', aliases=['start'], no_pm=True) @checks.custom_perms(send_messages=True) async def create_hangman(self, ctx): """This is used to create a new hangman game @@ -163,16 +163,16 @@ class Hangman: # Only have one hangman game per server, since anyone # In a server (except the creator) can guess towards the current game - if self.games.get(ctx.message.server.id) is not None: - await self.bot.say("Sorry but only one Hangman game can be running per server!") + if self.games.get(ctx.message.guild.id) is not None: + await ctx.send("Sorry but only one Hangman game can be running per server!") return game = self.create(random.SystemRandom().choice(phrases), ctx) # Let them know the game has started, then print the current game so that the blanks are shown - await self.bot.say( + await ctx.send( "Alright, a hangman game has just started, you can start guessing now!\n{}".format(str(game))) - @hangman.command(name='delete', aliases=['stop', 'remove', 'end'], pass_context=True, no_pm=True) + @hangman.command(name='delete', aliases=['stop', 'remove', 'end'], no_pm=True) @checks.custom_perms(kick_members=True) async def stop_game(self, ctx): """Force stops a game of hangman @@ -181,12 +181,12 @@ class Hangman: EXAMPLE: !hangman stop RESULT: No more men being hung""" - if self.games.get(ctx.message.server.id) is None: - await self.bot.say("There are no Hangman games running on this server!") + if self.games.get(ctx.message.guild.id) is None: + await ctx.send("There are no Hangman games running on this server!") return - del self.games[ctx.message.server.id] - await self.bot.say("I have just stopped the game of Hangman, a new should be able to be started now!") + del self.games[ctx.message.guild.id] + await ctx.send("I have just stopped the game of Hangman, a new should be able to be started now!") def setup(bot): diff --git a/cogs/interaction.py b/cogs/interaction.py index 5e9af9d..d20e179 100644 --- a/cogs/interaction.py +++ b/cogs/interaction.py @@ -85,7 +85,7 @@ class Interaction: self.battles = {} def user_battling(self, ctx, player2=None): - battling = self.battles.get(ctx.message.server.id) + battling = self.battles.get(ctx.message.guild.id) # If no one is battling, obviously the user is not battling if battling is None: @@ -101,14 +101,14 @@ class Interaction: # Handles removing the author from the dictionary of battles def battling_off(self, ctx): - battles = self.battles.get(ctx.message.server.id) or {} + battles = self.battles.get(ctx.message.guild.id) or {} player_id = ctx.message.author.id # Create a new dictionary, exactly the way the last one was setup # But don't include any that have the author's ID - self.battles[ctx.message.server.id] = {p1: p2 for p1, p2 in battles.items() if + self.battles[ctx.message.guild.id] = {p1: p2 for p1, p2 in battles.items() if not p2 == player_id and not p1 == player_id} - @commands.command(pass_context=True, no_pm=True) + @commands.command(no_pm=True) @utils.custom_perms(send_messages=True) async def hug(self, ctx, user: discord.Member = None): """Makes me hug a person! @@ -119,9 +119,9 @@ class Interaction: user = ctx.message.author fmt = random.SystemRandom().choice(hugs) - await self.bot.say(fmt.format(user.display_name)) + await ctx.send(fmt.format(user.display_name)) - @commands.command(pass_context=True, no_pm=True) + @commands.command(no_pm=True) @utils.custom_perms(send_messages=True) async def avatar(self, ctx, member: discord.Member = None): """Provides an image for the provided person's avatar (yours if no other member is provided) @@ -133,21 +133,21 @@ class Interaction: member = ctx.message.author url = member.avatar_url - if ctx.message.server.me.permissions_in(ctx.message.channel).attach_files: + if ctx.message.guild.me.permissions_in(ctx.message.channel).attach_files: file = await utils.download_image(url) if file is None: - await self.bot.say(url) + await ctx.send(url) else: if '.gif' in url: filename = 'avatar.gif' else: filename = 'avatar.webp' file = utils.convert_to_jpeg(file) - await self.bot.upload(file, filename=filename) + await ctx.send(file=file, filename=filename) else: - await self.bot.say(url) + await ctx.send(url) - @commands.group(pass_context=True, no_pm=True, invoke_without_command=True) + @commands.group(no_pm=True, invoke_without_command=True) @commands.cooldown(1, 180, BucketType.user) @utils.custom_perms(send_messages=True) async def battle(self, ctx, player2: discord.Member): @@ -157,29 +157,29 @@ class Interaction: RESULT: A battle to the death""" if ctx.message.author.id == player2.id: ctx.command.reset_cooldown(ctx) - await self.bot.say("Why would you want to battle yourself? Suicide is not the answer") + await ctx.send("Why would you want to battle yourself? Suicide is not the answer") return if self.bot.user.id == player2.id: ctx.command.reset_cooldown(ctx) - await self.bot.say("I always win, don't even try it.") + await ctx.send("I always win, don't even try it.") return if self.user_battling(ctx, player2): ctx.command.reset_cooldown(ctx) - await self.bot.say("You or the person you are trying to battle is already in a battle!") + await ctx.send("You or the person you are trying to battle is already in a battle!") return # Add the author and player provided in a new battle - battles = self.battles.get(ctx.message.server.id) or {} + battles = self.battles.get(ctx.message.guild.id) or {} battles[ctx.message.author.id] = player2.id - self.battles[ctx.message.server.id] = battles + self.battles[ctx.message.guild.id] = battles fmt = "{0.message.author.mention} has challenged you to a battle {1.mention}\n" \ "{0.prefix}accept or {0.prefix}decline" # Add a call to turn off battling, if the battle is not accepted/declined in 3 minutes self.bot.loop.call_later(180, self.battling_off, ctx) - await self.bot.say(fmt.format(ctx, player2)) + await ctx.send(fmt.format(ctx, player2)) - @commands.command(pass_context=True, no_pm=True) + @commands.command(no_pm=True) @utils.custom_perms(send_messages=True) async def accept(self, ctx): """Accepts the battle challenge @@ -188,13 +188,13 @@ class Interaction: RESULT: Hopefully the other person's death""" # This is a check to make sure that the author is the one being BATTLED # And not the one that started the battle - battles = self.battles.get(ctx.message.server.id) or {} + battles = self.battles.get(ctx.message.guild.id) or {} p1 = [p1_id for p1_id, p2_id in battles.items() if p2_id == ctx.message.author.id] if len(p1) == 0: - await self.bot.say("You are not currently being challenged to a battle!") + await ctx.send("You are not currently being challenged to a battle!") return - battleP1 = discord.utils.find(lambda m: m.id == p1[0], ctx.message.server.members) + battleP1 = discord.utils.find(lambda m: m.id == p1[0], ctx.message.guild.members) battleP2 = ctx.message.author # Get a random win message from our list @@ -205,13 +205,13 @@ class Interaction: # Randomize the order of who is printed/sent to the update system # All we need to do is change what order the challengers are printed/added as a paramater if random.SystemRandom().randint(0, 1): - await self.bot.say(fmt.format(battleP1.mention, battleP2.mention)) + await ctx.send(fmt.format(battleP1.mention, battleP2.mention)) await utils.update_records('battle_records', battleP1, battleP2) else: - await self.bot.say(fmt.format(battleP2.mention, battleP1.mention)) + await ctx.send(fmt.format(battleP2.mention, battleP1.mention)) await utils.update_records('battle_records', battleP2, battleP1) - @commands.command(pass_context=True, no_pm=True) + @commands.command(no_pm=True) @utils.custom_perms(send_messages=True) async def decline(self, ctx): """Declines the battle challenge @@ -220,20 +220,20 @@ class Interaction: RESULT: You chicken out""" # This is a check to make sure that the author is the one being BATTLED # And not the one that started the battle - battles = self.battles.get(ctx.message.server.id) or {} + battles = self.battles.get(ctx.message.guild.id) or {} p1 = [p1_id for p1_id, p2_id in battles.items() if p2_id == ctx.message.author.id] if len(p1) == 0: - await self.bot.say("You are not currently being challenged to a battle!") + await ctx.send("You are not currently being challenged to a battle!") return - battleP1 = discord.utils.find(lambda m: m.id == p1[0], ctx.message.server.members) + battleP1 = discord.utils.find(lambda m: m.id == p1[0], ctx.message.guild.members) battleP2 = ctx.message.author # There's no need to update the stats for the members if they declined the battle self.battling_off(ctx) - await self.bot.say("{0} has chickened out! What a loser~".format(battleP2.mention, battleP1.mention)) + await ctx.send("{0} has chickened out! What a loser~".format(battleP2.mention, battleP1.mention)) - @commands.command(pass_context=True, no_pm=True) + @commands.command(no_pm=True) @commands.cooldown(1, 180, BucketType.user) @utils.custom_perms(send_messages=True) async def boop(self, ctx, boopee: discord.Member = None, *, message = ""): @@ -244,18 +244,18 @@ class Interaction: booper = ctx.message.author if boopee is None: ctx.command.reset_cooldown(ctx) - await self.bot.say("You try to boop the air, the air boops back. Be afraid....") + await ctx.send("You try to boop the air, the air boops back. Be afraid....") return # To keep formatting easier, keep it either "" or the message with a space in front if message is not None: message = " " + message if boopee.id == booper.id: ctx.command.reset_cooldown(ctx) - await self.bot.say("You can't boop yourself! Silly...") + await ctx.send("You can't boop yourself! Silly...") return if boopee.id == self.bot.user.id: ctx.command.reset_cooldown(ctx) - await self.bot.say("Why the heck are you booping me? Get away from me >:c") + await ctx.send("Why the heck are you booping me? Get away from me >:c") return r_filter = {'member_id': booper.id} @@ -275,7 +275,7 @@ class Interaction: amount = 1 fmt = "{0.mention} has just booped {1.mention}{3}! That's {2} times now!" - await self.bot.say(fmt.format(booper, boopee, amount, message)) + await ctx.send(fmt.format(booper, boopee, amount, message)) def setup(bot): diff --git a/cogs/links.py b/cogs/links.py index 938acf1..f51c9a7 100644 --- a/cogs/links.py +++ b/cogs/links.py @@ -17,13 +17,15 @@ class Links: def __init__(self, bot): self.bot = bot - @commands.command(pass_context=True, aliases=['g']) + @commands.command(aliases=['g']) @utils.custom_perms(send_messages=True) async def google(self, ctx, *, query: str): """Searches google for a provided query EXAMPLE: !g Random cat pictures! RESULT: Links to sites with random cat pictures!""" + await ctx.message.channel.trigger_typing() + url = "https://www.google.com/search" # Turn safe filter on or off, based on whether or not this is a nsfw channel @@ -43,7 +45,7 @@ class Links: data = await utils.request(url, payload=params, attr='text') if data is None: - await self.bot.send_message(ctx.message.channel, "I failed to connect to google! (That can happen??)") + await ctx.send("I failed to connect to google! (That can happen??)") return # Convert to a BeautifulSoup element and loop through each result clasified by h3 tags with a class of 'r' @@ -55,7 +57,7 @@ class Links: try: result_url = re.search('(?<=q=).*(?=&sa=)', element.find('a').get('href')).group(0) except AttributeError: - await self.bot.say("I couldn't find any results for {}!".format(query)) + await ctx.send("I couldn't find any results for {}!".format(query)) return # Get the next sibling, find the span where the description is, and get the text from this @@ -68,15 +70,17 @@ class Links: fmt += '\n\n**URL**: <{}>\n**Description**: {}'.format(result_url, description) fmt = "**Top 3 results for the query** _{}_:{}".format(query, fmt) - await self.bot.say(fmt) + await ctx.send(fmt) - @commands.command(aliases=['yt'], pass_context=True) + @commands.command(aliases=['yt']) @utils.custom_perms(send_messages=True) async def youtube(self, ctx, *, query: str): """Searches youtube for a provided query EXAMPLE: !youtube Cat videos! RESULT: Cat videos!""" + await ctx.message.channel.trigger_typing() + key = utils.youtube_key url = "https://www.googleapis.com/youtube/v3/search" params = {'key': key, @@ -87,13 +91,13 @@ class Links: data = await utils.request(url, payload=params) if data is None: - await self.bot.send_message(ctx.message.channel, "Sorry but I failed to connect to youtube!") + await ctx.send("Sorry but I failed to connect to youtube!") return try: result = data['items'][0] except IndexError: - await self.bot.say("I could not find any results with the search term {}".format(query)) + await ctx.send("I could not find any results with the search term {}".format(query)) return result_url = "https://youtube.com/watch?v={}".format(result['id']['videoId']) @@ -101,15 +105,17 @@ class Links: description = result['snippet']['description'] fmt = "**Title:** {}\n\n**Description:** {}\n\n**URL:** <{}>".format(title, description, result_url) - await self.bot.say(fmt) + await ctx.send(fmt) - @commands.command(pass_context=True) + @commands.command() @utils.custom_perms(send_messages=True) async def wiki(self, ctx, *, query: str): """Pulls the top match for a specific term from wikipedia, and returns the result EXAMPLE: !wiki Test RESULT: A link to the wikipedia article for the word test""" + await ctx.message.channel.trigger_typing() + # All we need to do is search for the term provided, so the action, list, and format never need to change base_url = "https://en.wikipedia.org/w/api.php" params = {"action": "query", @@ -120,11 +126,11 @@ class Links: data = await utils.request(base_url, payload=params) if data is None: - await self.bot.send_message(ctx.message.channel, "Sorry but I failed to connect to Wikipedia!") + await ctx.send("Sorry but I failed to connect to Wikipedia!") return if len(data['query']['search']) == 0: - await self.bot.say("I could not find any results with that term, I tried my best :c") + await ctx.send("I could not find any results with that term, I tried my best :c") return # Wiki articles' URLs are in the format https://en.wikipedia.org/wiki/[Titlehere] # Replace spaces with %20 @@ -136,36 +142,38 @@ class Links: snippet = re.sub('', '', snippet) snippet = re.sub('"', '"', snippet) - await self.bot.say( + await ctx.send( "Here is the best match I found with the query `{}`:\nURL: <{}>\nSnippet: \n```\n{}```".format(query, url, snippet)) - @commands.command(pass_context=True) + @commands.command() @utils.custom_perms(send_messages=True) async def urban(self, ctx, *, msg: str): """Pulls the top urbandictionary.com definition for a term EXAMPLE: !urban a normal phrase RESULT: Probably something lewd; this is urban dictionary we're talking about""" + await ctx.message.channel.trigger_typing() + url = "http://api.urbandictionary.com/v0/define" params = {"term": msg} try: data = await utils.request(url, payload=params) if data is None: - await self.bot.send_message(ctx.message.channel, "Sorry but I failed to connect to urban dictionary!") + await ctx.send("Sorry but I failed to connect to urban dictionary!") return # List is the list of definitions found, if it's empty then nothing was found if len(data['list']) == 0: - await self.bot.say("No result with that term!") + await ctx.send("No result with that term!") # If the list is not empty, use the first result and print it's defintion else: - await self.bot.say(data['list'][0]['definition']) + await ctx.send(data['list'][0]['definition']) # Urban dictionary has some long definitions, some might not be able to be sent except discord.HTTPException: - await self.bot.say('```\nError: Definition is too long for me to send```') + await ctx.send('```\nError: Definition is too long for me to send```') except KeyError: - await self.bot.say("Sorry but I failed to connect to urban dictionary!") + await ctx.send("Sorry but I failed to connect to urban dictionary!") @commands.command(pass_context=True) @utils.custom_perms(send_messages=True) @@ -174,6 +182,8 @@ class Links: EXAMPLE: !derpi Rainbow Dash RESULT: A picture of Rainbow Dash!""" + await ctx.message.channel.trigger_typing() + if len(search) > 0: url = 'https://derpibooru.org/search.json' @@ -192,18 +202,16 @@ class Links: else: params['q'] += ", safe" - await self.bot.say("Looking up an image with those tags....") - try: # Get the response from derpibooru and parse the 'search' result from it data = await utils.request(url, payload=params) if data is None: - await self.bot.send_message(ctx.message.channel, "Sorry but I failed to connect to Derpibooru!") + await ctx.send("Sorry but I failed to connect to Derpibooru!") return results = data['search'] except KeyError: - await self.bot.say("No results with that search term, {0}!".format(ctx.message.author.mention)) + await ctx.send("No results with that search term, {0}!".format(ctx.message.author.mention)) return # The first request we've made ensures there are results @@ -215,7 +223,7 @@ class Links: params['page'] = random.SystemRandom().randint(1, pages) data = await utils.request(url, payload=params) if data is None: - await self.bot.say("Sorry but I failed to connect to Derpibooru!") + await ctx.send("Sorry but I failed to connect to Derpibooru!") return # Now get the results again results = data['search'] @@ -224,14 +232,14 @@ class Links: index = random.SystemRandom().randint(0, len(results) - 1) image_link = 'https://derpibooru.org/{}'.format(results[index]['id']) else: - await self.bot.say("No results with that search term, {0}!".format(ctx.message.author.mention)) + await ctx.send("No results with that search term, {0}!".format(ctx.message.author.mention)) return else: # If no search term was provided, search for a random image # .url will be the URL we end up at, not the one requested. # https://derpibooru.org/images/random redirects to a random image, so this is exactly what we want image_link = await utils.request('https://derpibooru.org/images/random', attr='url') - await self.bot.say(image_link) + await ctx.send(image_link) @commands.command(pass_context=True) @utils.custom_perms(send_messages=True) @@ -242,19 +250,19 @@ class Links: EXAMPLE: !e621 dragon RESULT: A picture of a dragon (hopefully, screw your tagging system e621)""" + await ctx.message.channel.trigger_typing() + # This changes the formatting for queries, so we don't # Have to use e621's stupid formatting when using the command + tags = tags.replace(' ', '_') tags = tags.replace(',_', ' ') url = 'https://e621.net/post/index.json' params = {'limit': 320, 'tags': tags} - # e621 provides a way to change how many images can be shown on one request - # This gives more of a chance of random results, however it causes the lookup to take longer than most - # Due to this, send a message saying we're looking up the information first - await self.bot.say("Looking up an image with those tags....") + r_filter = {'channel_id': ctx.message.channel.id} nsfw_channels = await utils.get_content("nsfw_channels", r_filter) @@ -266,8 +274,7 @@ class Links: data = await utils.request(url, payload=params) if data is None: - await self.bot.send_message(ctx.message.channel, - "Sorry, I had trouble connecting at the moment; please try again later") + await ctx.send("Sorry, I had trouble connecting at the moment; please try again later") return # Try to find an image from the list. If there were no results, we're going to attempt to find @@ -276,9 +283,9 @@ class Links: # i.e. it responded with a 404/504/etc. try: rand_image = data[random.SystemRandom().randint(0, len(data) - 1)]['file_url'] - await self.bot.say(rand_image) + await ctx.send(rand_image) except (ValueError, KeyError): - await self.bot.say("No results with that tag {}".format(ctx.message.author.mention)) + await ctx.send("No results with that tag {}".format(ctx.message.author.mention)) return diff --git a/cogs/mod.py b/cogs/mod.py index c4fd3c2..316be81 100644 --- a/cogs/mod.py +++ b/cogs/mod.py @@ -16,53 +16,30 @@ class Mod: def __init__(self, bot): self.bot = bot - def find_command(self, command): - # This method ensures the command given is valid. We need to loop through commands - # As self.bot.commands only includes parent commands - # So we are splitting the command in parts, looping through the commands - # And getting the subcommand based on the next part - # If we try to access commands of a command that isn't a group - # We'll hit an AttributeError, meaning an invalid command was given - # If we loop through and don't find anything, cmd will still be None - # And we'll report an invalid was given as well - cmd = None - - for part in command.split(): - try: - if cmd is None: - cmd = self.bot.commands.get(part) - else: - cmd = cmd.commands.get(part) - except AttributeError: - cmd = None - break - - return cmd - - @commands.command(pass_context=True, no_pm=True, aliases=['nick']) + @commands.command(no_pm=True, aliases=['nick']) @utils.custom_perms(kick_members=True) async def nickname(self, ctx, *, name=None): """Used to set the nickname for Bonfire (provide no nickname and it will reset) EXAMPLE: !nick Music Bot - RESULT: My nickname is now music bot""" - await self.bot.change_nickname(ctx.message.server.me, name) - await self.bot.say("\N{OK HAND SIGN}") + RESULT: My nickname is now Music Bot""" + await ctx.message.server.me.edit(nick=name) + await ctx.send("\N{OK HAND SIGN}") @commands.command(no_pm=True) @utils.custom_perms(kick_members=True) - async def kick(self, member: discord.Member): + async def kick(self, ctx, member: discord.Member): """Used to kick a member from this server EXAMPLE: !kick @Member RESULT: They're kicked from the server?""" try: - await self.bot.kick(member) - await self.bot.say("\N{OK HAND SIGN}") + await member.kick() + await ctx.send("\N{OK HAND SIGN}") except discord.Forbidden: - await self.bot.say("But I can't, muh permissions >:c") + await ctx.send("But I can't, muh permissions >:c") - @commands.command(pass_context=True, no_pm=True) + @commands.command(no_pm=True) @utils.custom_perms(ban_members=True) async def unban(self, ctx, member_id: int): """Used to unban a member from this server @@ -74,16 +51,15 @@ class Mod: # Lets only accept an int for this method, in order to ensure only an ID is provided # Due to that though, we need to ensure a string is passed as the member's ID - member = discord.Object(id=str(member_id)) try: - await self.bot.unban(ctx.message.server, member) - await self.bot.say("\N{OK HAND SIGN}") + await discord.http.unban(member.id, ctx.guild.id) + await ctx.send("\N{OK HAND SIGN}") except discord.Forbidden: - await self.bot.say("But I can't, muh permissions >:c") + await ctx.send("But I can't, muh permissions >:c") except discord.HTTPException: - await self.bot.say("Sorry, I failed to unban that user!") + await ctx.send("Sorry, I failed to unban that user!") - @commands.command(pass_context=True, no_pm=True) + @commands.command(no_pm=True) @utils.custom_perms(ban_members=True) async def ban(self, ctx, *, member): """Used to ban a member @@ -95,31 +71,35 @@ class Mod: # Lets first check if a user ID was provided, as that will be the easiest case to ban if member.isdigit(): - # First convert it to a discord object based on the ID that was given - member = discord.Object(id=member) - # Next, to ban from the server the API takes a server obejct and uses that ID - # So set "this" server as the member's server. This creates the "fake" member we need - member.server = ctx.message.server + try: + await discord.http.ban(member, ctx.guild.id) + await ctx.send("\N{OK HAND SIGN}") + except discord.Forbidden: + await ctx.send("But I can't, muh permissions >:c") + except discord.HTTPException: + await ctx.send("Sorry, I failed to ban that user!") + finally: + return else: # If no ID was provided, lets try to convert what was given using the internal coverter - converter = commands.converter.UserConverter(ctx, member) + converter = commands.converter.MemberConverter(ctx, member) try: member = converter.convert() except commands.converter.BadArgument: - await self.bot.say( + await ctx.send( '{} does not appear to be a valid member. If this member is not in this server, please provide ' 'their ID'.format(member)) return # Now lets try actually banning the member we've been given try: - await self.bot.ban(member) - await self.bot.say("\N{OK HAND SIGN}") + await member.ban() + await ctx.send("\N{OK HAND SIGN}") except discord.Forbidden: - await self.bot.say("But I can't, muh permissions >:c") + await ctx.send("But I can't, muh permissions >:c") except discord.HTTPException: - await self.bot.say("Sorry, I failed to ban that user!") + await ctx.send("Sorry, I failed to ban that user!") - @commands.command(pass_context=True, no_pm=True) + @commands.command(no_pm=True) @utils.custom_perms(kick_members=True) async def alerts(self, ctx, channel: discord.Channel): """This command is used to set a channel as the server's 'notifications' channel @@ -132,10 +112,10 @@ class Mod: 'channel_id': channel.id} if not await utils.add_content('server_alerts', entry, r_filter): await utils.update_content('server_alerts', entry, r_filter) - await self.bot.say("I have just changed this server's 'notifications' channel" + await ctx.send("I have just changed this server's 'notifications' channel" "\nAll notifications will now go to `{}`".format(channel)) - @commands.command(pass_context=True, no_pm=True) + @commands.command(no_pm=True) @utils.custom_perms(kick_members=True) async def usernotify(self, ctx, on_off: str): """This command can be used to set whether or not you want user notificaitons to show @@ -148,22 +128,21 @@ class Mod: # So we base this channel on it's own and not from alerts # When mod logging becomes available, that will be kept to it's own channel if wanted as well on_off = ctx.message.channel.id if re.search("(on|yes|true)", on_off.lower()) else None - r_filter = {'server_id': ctx.message.server.id} - entry = {'server_id': ctx.message.server.id, + r_filter = {'server_id': ctx.message.guild.id} + entry = {'server_id': ctx.message.guild.id, 'channel_id': on_off} if not await utils.add_content('user_notifications', entry, r_filter): await utils.update_content('user_notifications', entry, r_filter) fmt = "notify" if on_off else "not notify" - await self.bot.say("This server will now {} if someone has joined or left".format(fmt)) + await ctx.send("This server will now {} if someone has joined or left".format(fmt)) - @commands.group(pass_context=True) + @commands.group() async def nsfw(self, ctx): """Handles adding or removing a channel as a nsfw channel""" # This command isn't meant to do anything, so just send an error if an invalid subcommand is passed - if ctx.invoked_subcommand is None: - await self.bot.say('Invalid subcommand passed: {0.subcommand_passed}'.format(ctx)) + pass - @nsfw.command(name="add", pass_context=True) + @nsfw.command(name="add") @utils.custom_perms(kick_members=True) async def nsfw_add(self, ctx): """Registers this channel as a 'nsfw' channel @@ -172,11 +151,11 @@ class Mod: RESULT: ;)""" r_filter = {'channel_id': ctx.message.channel.id} if await utils.add_content('nsfw_channels', r_filter, r_filter): - await self.bot.say("This channel has just been registered as 'nsfw'! Have fun you naughties ;)") + await ctx.send("This channel has just been registered as 'nsfw'! Have fun you naughties ;)") else: - await self.bot.say("This channel is already registered as 'nsfw'!") + await ctx.send("This channel is already registered as 'nsfw'!") - @nsfw.command(name="remove", aliases=["delete"], pass_context=True) + @nsfw.command(name="remove", aliases=["delete"]) @utils.custom_perms(kick_members=True) async def nsfw_remove(self, ctx): """Removes this channel as a 'nsfw' channel @@ -185,11 +164,11 @@ class Mod: RESULT: ;(""" r_filter = {'channel_id': ctx.message.channel.id} if await utils.remove_content('nsfw_channels', r_filter): - await self.bot.say("This channel has just been unregistered as a nsfw channel") + await ctx.send("This channel has just been unregistered as a nsfw channel") else: - await self.bot.say("This channel is not registered as a ''nsfw' channel!") + await ctx.send("This channel is not registered as a ''nsfw' channel!") - @commands.command(pass_context=True) + @commands.command() @utils.custom_perms(kick_members=True) async def say(self, ctx, *, msg: str): """Tells the bot to repeat what you say @@ -197,13 +176,13 @@ class Mod: EXAMPLE: !say I really like orange juice RESULT: I really like orange juice""" fmt = "\u200B{}".format(msg) - await self.bot.say(fmt) + await ctx.send(fmt) try: - await self.bot.delete_message(ctx.message) + await ctx.message.delete() except: pass - @commands.group(pass_context=True, invoke_without_command=True, no_pm=True) + @commands.group(invoke_without_command=True, no_pm=True) @utils.custom_perms(send_messages=True) async def perms(self, ctx, *, command: str = None): """This command can be used to print the current allowed permissions on a specific command @@ -212,20 +191,20 @@ class Mod: EXAMPLE: !perms help RESULT: Hopefully a result saying you just need send_messages permissions; otherwise lol this server's admin doesn't like me """ if command is None: - await self.bot.say( + await ctx.send( "Valid permissions are: ```\n{}```".format("\n".join("{}".format(i) for i in valid_perms))) return - r_filter = {'server_id': ctx.message.server.id} + r_filter = {'server_id': ctx.message.guild.id} server_perms = await utils.get_content('custom_permissions', r_filter) try: server_perms = server_perms[0] except TypeError: server_perms = {} - cmd = self.find_command(command) + cmd = self.bot.get_command(command) if cmd is None: - await self.bot.say("That is not a valid command!") + await ctx.send("That is not a valid command!") return perms_value = server_perms.get(cmd.qualified_name) @@ -240,15 +219,15 @@ class Mod: # Able to manage the server (for the utils on perm commands) for func in cmd.utils: if "is_owner" in func.__qualname__: - await self.bot.say("You need to own the bot to run this command") + await ctx.send("You need to own the bot to run this command") return - await self.bot.say( + await ctx.send( "You are required to have `manage_server` permissions to run `{}`".format(cmd.qualified_name)) return # Perms will be an attribute if custom_perms is found no matter what, so no need to check this perms = "\n".join(attribute for attribute, setting in custom_perms.perms.items() if setting) - await self.bot.say( + await ctx.send( "You are required to have `{}` permissions to run `{}`".format(perms, cmd.qualified_name)) else: # Permissions are saved as bit values, so create an object based on that value @@ -256,10 +235,10 @@ class Mod: # There's no need to check for errors here, as we ensure a permission is valid when adding it permissions = discord.Permissions(perms_value) needed_perm = [perm[0] for perm in permissions if perm[1]][0] - await self.bot.say("You need to have the permission `{}` " + await ctx.send("You need to have the permission `{}` " "to use the command `{}` in this server".format(needed_perm, command)) - @perms.command(name="add", aliases=["setup,create"], pass_context=True, no_pm=True) + @perms.command(name="add", aliases=["setup,create"], no_pm=True) @commands.has_permissions(manage_server=True) async def add_perms(self, ctx, *msg: str): """Sets up custom permissions on the provided command @@ -274,7 +253,7 @@ class Mod: try: permissions = msg[len(msg) - 1] except IndexError: - await self.bot.say("Please provide the permissions you want to setup, the format for this must be in:\n" + await ctx.send("Please provide the permissions you want to setup, the format for this must be in:\n" "`perms add `") return @@ -288,15 +267,15 @@ class Mod: try: setattr(perm_obj, permissions, True) except AttributeError: - await self.bot.say("{} does not appear to be a valid permission! Valid permissions are: ```\n{}```" + await ctx.send("{} does not appear to be a valid permission! Valid permissions are: ```\n{}```" .format(permissions, "\n".join(valid_perms))) return perm_value = perm_obj.value - cmd = self.find_command(command) + cmd = self.bot.get_command(command) if cmd is None: - await self.bot.say( + await ctx.send( "That command does not exist! You can't have custom permissions on a non-existant command....") return @@ -305,12 +284,12 @@ class Mod: # Which means I do not want to check custom permissions at all # Currently the second case is only on adding and removing permissions, to avoid abuse on these for check in cmd.checks: - if "is_owner" == check.__name__ or re.search("has_permissions", str(check)) is not None: - await self.bot.say("This command cannot have custom permissions setup!") + if "is_owner" == check.__name__ or "has_permissions" not in str(check): + await ctx.send("This command cannot have custom permissions setup!") return - r_filter = {'server_id': ctx.message.server.id} - entry = {'server_id': ctx.message.server.id, + r_filter = {'server_id': ctx.message.guild.id} + entry = {'server_id': ctx.message.guild.id, cmd.qualified_name: perm_value} # In all other cases, I've used add_content before update_content @@ -322,10 +301,10 @@ class Mod: # Same case as prefixes, for now, trigger a manual update self.bot.loop.create_task(utils.cache['custom_permissions'].update()) - await self.bot.say("I have just added your custom permissions; " + await ctx.send("I have just added your custom permissions; " "you now need to have `{}` permissions to use the command `{}`".format(permissions, command)) - @perms.command(name="remove", aliases=["delete"], pass_context=True, no_pm=True) + @perms.command(name="remove", aliases=["delete"], no_pm=True) @commands.has_permissions(manage_server=True) async def remove_perms(self, ctx, *, command: str): """Removes the custom permissions setup on the command specified @@ -333,32 +312,32 @@ class Mod: EXAMPLE: !perms remove play RESULT: Freedom!""" - cmd = self.find_command(command) + cmd = self.bot.get_command(command) if cmd is None: - await self.bot.say( + await ctx.send( "That command does not exist! You can't have custom permissions on a non-existant command....") return r_filter = {'server_id': ctx.message.server.id} await utils.replace_content('custom_permissions', r.row.without(cmd.qualified_name), r_filter) - await self.bot.say("I have just removed the custom permissions for {}!".format(cmd)) + await ctx.send("I have just removed the custom permissions for {}!".format(cmd)) # Same case as prefixes, for now, trigger a manual update self.bot.loop.create_task(utils.cache['custom_permissions'].update()) - @commands.command(pass_context=True, no_pm=True) - @utils.custom_perms(manage_server=True) + @commands.command(no_pm=True) + @utils.custom_perms(manage_guild=True) async def prefix(self, ctx, *, prefix: str): """This command can be used to set a custom prefix per server EXAMPLE: !prefix new_prefix RESULT: You probably screwing it up and not realizing you now need to do new_prefixprefix""" - r_filter = {'server_id': ctx.message.server.id} + r_filter = {'server_id': ctx.message.guild.id} if prefix.lower().strip() == "none": prefix = None - entry = {'server_id': ctx.message.server.id, + entry = {'server_id': ctx.message.guild.id, 'prefix': prefix} if not await utils.add_content('prefixes', entry, r_filter): @@ -369,9 +348,9 @@ class Mod: else: fmt = "I have just updated the prefix for this server; you now need to call commands with `{0}`. " \ "For example, you can call this command again with {0}prefix".format(prefix) - await self.bot.say(fmt) + await ctx.send(fmt) - @commands.command(pass_context=True, no_pm=True) + @commands.command(no_pm=True) @utils.custom_perms(manage_messages=True) async def purge(self, ctx, limit: int = 100): """This command is used to a purge a number of messages from the channel @@ -379,15 +358,15 @@ class Mod: EXAMPLE: !purge 50 RESULT: -50 messages in this channel""" if not ctx.message.channel.permissions_for(ctx.message.server.me).manage_messages: - await self.bot.say("I do not have permission to delete messages...") + await ctx.send("I do not have permission to delete messages...") return try: - await self.bot.purge_from(ctx.message.channel, limit=limit) + await ctx.message.channel.purge(limit=limit) except discord.HTTPException: await self.bot.send_message(ctx.message.channel, "Detected messages that are too far back for me to delete;" \ " I can only bulk delete messages that are under 14 days old.") - @commands.command(pass_context=True, no_pm=True) + @commands.command(no_pm=True) @utils.custom_perms(manage_messages=True) async def prune(self, ctx, limit: int = 100): """This command can be used to prune messages from certain members @@ -403,48 +382,48 @@ class Mod: # If no members are provided, assume we're trying to prune our own messages members = ctx.message.mentions if len(members) == 0: - members = [ctx.message.server.me] + members = [ctx.message.guild.me] # If we're not setting the user to the bot, then we're deleting someone elses messages # To do so, we need manage_messages permission, so check if we have that elif not ctx.message.channel.permissions_for(ctx.message.server.me).manage_messages: - await self.bot.say("I do not have permission to delete messages...") + await ctx.send("I do not have permission to delete messages...") return # Since logs_from will give us any message, not just the user's we need # We'll increment count, and stop deleting messages if we hit the limit. count = 0 - async for msg in self.bot.logs_from(ctx.message.channel): + async for msg in ctx.message.channel.history: if msg.author in members: try: - await self.bot.delete_message(msg) + await msg.delete() count += 1 except discord.NotFound: pass if count >= limit: break - msg = await self.bot.say("{} messages succesfully deleted".format(count)) - await asyncio.sleep(60) + msg = await ctx.send("{} messages succesfully deleted".format(count)) + await asyncio.sleep(5) try: - await self.bot.delete_message(msg) + await msg.delete() except discord.NotFound: pass - @commands.group(aliases=['rule'], pass_context=True, no_pm=True, invoke_without_command=True) + @commands.group(aliases=['rule'], no_pm=True, invoke_without_command=True) @utils.custom_perms(send_messages=True) async def rules(self, ctx, rule: int = None): """This command can be used to view the current rules on the server EXAMPLE: !rules 5 RESULT: Rule 5 is printed""" - r_filter = {'server_id': ctx.message.server.id} + r_filter = {'server_id': ctx.message.guild.id} rules = await utils.get_content('rules', r_filter) try: rules = rules[0]['rules'] except TypeError: - await self.bot.say("This server currently has no rules on it! I see you like to live dangerously...") + await ctx.send("This server currently has no rules on it! I see you like to live dangerously...") return if len(rules) == 0: - await self.bot.say("This server currently has no rules on it! I see you like to live dangerously...") + await ctx.send("This server currently has no rules on it! I see you like to live dangerously...") return if rule is None: @@ -453,16 +432,16 @@ class Mod: pages.title = "Rules for {}".format(ctx.message.server.name) await pages.paginate() except utils.CannotPaginate as e: - await self.bot.say(str(e)) + await ctx.send(str(e)) else: try: fmt = rules[rule - 1] except IndexError: - await self.bot.say("That rules does not exist.") + await ctx.send("That rules does not exist.") return - await self.bot.say("Rule {}: \"{}\"".format(rule, fmt)) + await ctx.send("Rule {}: \"{}\"".format(rule, fmt)) - @rules.command(name='add', aliases=['create'], pass_context=True, no_pm=True) + @rules.command(name='add', aliases=['create'], no_pm=True) @utils.custom_perms(manage_server=True) async def rules_add(self, ctx, *, rule: str): """Adds a rule to this server's rules @@ -476,9 +455,9 @@ class Mod: if not await utils.update_content('rules', update, r_filter): await utils.add_content('rules', entry, r_filter) - await self.bot.say("I have just saved your new rule, use the rules command to view this server's current rules") + await ctx.send("I have just saved your new rule, use the rules command to view this server's current rules") - @rules.command(name='remove', aliases=['delete'], pass_context=True, no_pm=True) + @rules.command(name='remove', aliases=['delete'], no_pm=True) @utils.custom_perms(manage_server=True) async def rules_delete(self, ctx, rule: int): """Removes one of the rules from the list of this server's rules @@ -489,9 +468,9 @@ class Mod: r_filter = {'server_id': ctx.message.server.id} update = {'rules': r.row['rules'].delete_at(rule - 1)} if not await utils.update_content('rules', update, r_filter): - await self.bot.say("That is not a valid rule number, try running the command again.") + await ctx.send("That is not a valid rule number, try running the command again.") else: - await self.bot.say("I have just removed that rule from your list of rules!") + await ctx.send("I have just removed that rule from your list of rules!") def setup(bot):