1
0
Fork 0
mirror of synced 2024-06-03 03:04:33 +12:00

Update to work with the rewrite: Batch 1

This commit is contained in:
Phxntxm 2017-03-05 20:45:44 -06:00
parent 4b4649b0de
commit 23e69a01c6
10 changed files with 357 additions and 412 deletions

View file

@ -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 # 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 # To do this, it needs to be able to access this instance of Blackjack
game = Game(self.bot, message, self) 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) @utils.custom_perms(send_messages=True)
async def blackjack(self, ctx): async def blackjack(self, ctx):
"""Creates a game/joins the current running game of blackjack """Creates a game/joins the current running game of blackjack
EXAMPLE: !blackjack EXAMPLE: !blackjack
RESULT: A new game of blackjack!""" RESULT: A new game of blackjack!"""
# Get this server's game if it exists # Get this guild's game if it exists
game = self.games.get(ctx.message.server.id) game = self.games.get(ctx.message.guild.id)
# If it doesn't, start one # If it doesn't, start one
if game is None: if game is None:
self.create_game(ctx.message) self.create_game(ctx.message)
@ -54,15 +54,15 @@ class Blackjack:
# If it worked, they're ready to play # If it worked, they're ready to play
if status: if status:
fmt = "{} has joined the game of blackjack, and will be able to play next round!" 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: else:
# Otherwise, lets check *why* they couldn't join # Otherwise, lets check *why* they couldn't join
if game.playing(ctx.message.author): 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: 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) @utils.custom_perms(send_messages=True)
async def blackjack_leave(self, ctx): async def blackjack_leave(self, ctx):
"""Leaves the current game of blackjack """Leaves the current game of blackjack
@ -70,37 +70,37 @@ class Blackjack:
EXAMPLE: !blackjack leave EXAMPLE: !blackjack leave
RESULT: You stop losing money in blackjack""" RESULT: You stop losing money in blackjack"""
# Get this server's game if it exists # Get this guild's game if it exists
game = self.games.get(ctx.message.server.id) game = self.games.get(ctx.message.guild.id)
if game is None: 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 return
status = game.leave(ctx.message.author) status = game.leave(ctx.message.author)
if status: 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: 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']) @blackjack.command(no_pm=True, name='forcestop', aliases=['stop'])
@utils.custom_perms(manage_server=True) @utils.custom_perms(manage_guild=True)
async def blackjack_stop(self, ctx): async def blackjack_stop(self, ctx):
"""Forces the game to stop, mostly for use if someone has gone afk """Forces the game to stop, mostly for use if someone has gone afk
EXAMPLE: !blackjack forcestop EXAMPLE: !blackjack forcestop
RESULT: No more blackjack spam""" RESULT: No more blackjack spam"""
# Get this server's game if it exists # Get this guild's game if it exists
game = self.games.get(ctx.message.server.id) game = self.games.get(ctx.message.guild.id)
if game is None: 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 return
game.task.cancel() game.task.cancel()
del self.games[ctx.message.server.id] del self.games[ctx.message.guild.id]
await self.bot.say("The blackjack game running here has just ended") await ctx.send("The blackjack game running here has just ended")
def FOIL(a, b): def FOIL(a, b):
@ -226,7 +226,7 @@ class Game:
async def game_task(self): async def game_task(self):
"""The task to handle the entire game""" """The task to handle the entire game"""
while len(self.players) > 0: 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 # First wait for bets
await self.bet_task() await self.bet_task()
@ -253,25 +253,25 @@ class Game:
await self.cleanup() await self.cleanup()
# If we reach the end of this loop, that means there are no more players # 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): async def dealer_task(self):
"""The task handling the dealer's play after all players have stood""" """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) 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: while True:
await asyncio.sleep(1) await asyncio.sleep(1)
if self.dealer.bust: if self.dealer.bust:
fmt = msg.content + "\n\nDealer has busted!!" fmt = msg.content + "\n\nDealer has busted!!"
await self.bot.edit_message(msg, fmt) await msg.edit(content=fmt)
return return
for num in self.dealer.count: for num in self.dealer.count:
if num > 16: if num > 16:
return return
self.hit(self.dealer) self.hit(self.dealer)
fmt = "It is the dealer's turn to play\n\n{}".format(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): async def round_task(self):
"""The task handling the round itself, asking each person to hit or stand""" """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') # 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 # 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 # First lets handle the blackjacks
for entry in [p for p in self.players if p['status'] == 'blackjack']: for entry in [p for p in self.players if p['status'] == 'blackjack']:
player = entry['player'] player = entry['player']
fmt = "You got a blackjack {0.member.mention}!\n\n{0}".format(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 # 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')]: for entry in [p for p in self.players if p['status'] == 'playing' and hasattr(p['player'], 'bet')]:
player = entry['player'] player = entry['player']
# Let them know it's their turn to play # Let them know it's their turn to play
fmt = "It is your turn to play {0.member.mention}\n\n{0}".format(player) 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 # 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 # them to hit or stand
@ -302,37 +306,28 @@ class Game:
# Ask if they want to hit or stand # Ask if they want to hit or stand
fmt = "Hit, stand, or double?" fmt = "Hit, stand, or double?"
await self.bot.send_message(self.channel, fmt) await self.channel.send(fmt)
msg = await self.bot.wait_for_message(timeout=60, author=player.member, channel=self.channel,
check=check)
# If they took to long, make them stand so the next person can play try:
if msg is None: msg = await self.bot.wait_for('message', timeout=60, check=check)
await self.bot.send_message(self.channel, "Took to long! You're standing!") except asyncio.TimeoutError:
await self.channel.send("Took to long! You're standing!")
entry['status'] = 'stand' entry['status'] = 'stand'
# If they want to hit else:
elif 'hit' in msg.content.lower(): # If they want to hit
self.hit(player) if 'hit' in msg.content.lower():
await self.bot.send_message(self.channel, player) self.hit(player)
# If they want to stand await self.channel.send(player)
elif 'stand' in msg.content.lower(): # If they want to stand
self.stand(player) elif 'stand' in msg.content.lower():
elif 'double' in msg.content.lower(): self.stand(player)
self.double(player) elif 'double' in msg.content.lower():
await self.bot.send_message(self.channel, player) self.double(player)
# TODO: Handle double, split await self.channel.send(player)
# TODO: Handle double, split
async def bet_task(self): async def bet_task(self):
"""Performs the task of betting""" """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 # 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 # 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 # 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] entry = players[0]
player = entry['player'] 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" \ 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" \ "Current min bet is {1}, current max bet is {2}\n" \
"Place your bet now (please provide only the number;" \ "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) "'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.channel.send(fmt)
await self.bot.send_message(self.channel, "You took too long! You're sitting this round out")
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' 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: else:
num = int(msg.content) if msg.content.lower() == 'skip':
# Set the new bet, and remove it from this players chip total await self.channel.send("Alright, you've been removed from the game")
if num <= player.chips: self.leave(player.member)
player.bet = num
player.chips -= num
entry['status'] = 'bet'
else: 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 # Call this so that we can correct the list, if someone has left or join
self.player_cleanup() self.player_cleanup()
@ -464,7 +474,7 @@ class Game:
# Add that to the main string # Add that to the main string
fmt += "Blackjacks: {}\n".format(_fmt) 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 # Do the same for the dealers hand
cards = list(self.dealer.hand.draw(self.dealer.hand.count)) cards = list(self.dealer.hand.draw(self.dealer.hand.count))
@ -481,10 +491,10 @@ class Game:
self.players.extend(self._added_players) self.players.extend(self._added_players)
self._added_players.clear() 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: for entry in self.players:
m = entry['player'].member 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']) self._removed_players.append(entry['player'])
# Remove the players who left # Remove the players who left

View file

@ -10,7 +10,7 @@ from enum import Enum
class Chess: class Chess:
def __init__(self, bot): def __init__(self, bot):
self.bot = 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]} # Format should be {'server_id': [Game, Game, Game]}
self.games = {} self.games = {}
@ -91,18 +91,18 @@ class Chess:
return MoveStatus.invalid return MoveStatus.invalid
def get_game(self, player): def get_game(self, player):
"""Provides the game this player is playing, in this server""" """Provides the game this player is playing, in this guild"""
server_games = self.games.get(player.server.id, []) guild_games = self.games.get(player.guild.id, [])
for game in server_games: for game in guild_games:
if player in game.challengers.values(): if player in game.challengers.values():
return game return game
return None return None
def in_game(self, player): def in_game(self, player):
"""Checks to see if a player is playing in a game right now, in this server""" """Checks to see if a player is playing in a game right now, in this guild"""
server_games = self.games.get(player.server.id, []) guild_games = self.games.get(player.guild.id, [])
for game in server_games: for game in guild_games:
if player in game.challengers.values(): if player in game.challengers.values():
return True return True
@ -111,13 +111,13 @@ class Chess:
def start_game(self, player1, player2): def start_game(self, player1, player2):
game = Game(player1, player2) game = Game(player1, player2)
try: try:
self.games[player1.server.id].append(game) self.games[player1.guild.id].append(game)
except KeyError: except KeyError:
self.games[player1.server.id] = [game] self.games[player1.guild.id] = [game]
return game return game
@commands.group(pass_contxt=True, invoke_without_command=True) @commands.group(invoke_without_command=True)
@checks.custom_perms(send_messages=True) @checks.custom_perms(send_messages=True)
async def chess(self, ctx, *, move): async def chess(self, ctx, *, move):
"""Moves a piece based on the notation provided """Moves a piece based on the notation provided
@ -142,45 +142,45 @@ class Chess:
EXAMPLE: !rook to d4""" EXAMPLE: !rook to d4"""
result = self.play(ctx.message.author, move) result = self.play(ctx.message.author, move)
if result is MoveStatus.invalid: 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: 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: 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: elif result is MoveStatus.valid:
game = self.get_game(ctx.message.author) game = self.get_game(ctx.message.author)
link = game.draw_board() link = game.draw_board()
await self.bot.upload(link) await self.bot.upload(link)
@commands.command(pass_context=True) @commands.command()
@checks.custom_perms(send_messages=True) @checks.custom_perms(send_messages=True)
async def chess_start(self, ctx, player2: discord.Member): async def chess_start(self, ctx, player2: discord.Member):
"""Starts a chess game with another player """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 EXAMPLE: !chess start @Victim
RESULT: A new chess game! Good luck~""" RESULT: A new chess game! Good luck~"""
# Lets first check our permissions; we're not going to create a text based board # 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 # 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: if not ctx.message.channel.permissions_for(ctx.message.guild.me).attach_files:
await self.bot.say( 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") "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 return
# Make sure the author and player 2 are not in a game already # Make sure the author and player 2 are not in a game already
if self.in_game(ctx.message.author): 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 return
if self.in_game(player2): 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 return
# Start the game # Start the game
game = self.start_game(ctx.message.author, player2) game = self.start_game(ctx.message.author, player2)
player1 = game.challengers.get('white') 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( "{} 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)) ctx.message.author.display_name, player2.display_name, ctx.prefix))
@ -209,7 +209,7 @@ class Game:
self.reset_board() self.reset_board()
# The point of chess revolves around the king's position # 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.w_king_pos = (0, 4)
self.b_king_pos = (7, 4) self.b_king_pos = (7, 4)
@ -388,7 +388,7 @@ class Game:
def check(self): def check(self):
"""Checks our current board, and checks (based on whose turn it is) if we're in a 'check' state""" """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 # 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 x, row in enumerate(self.board):
for y, piece in enumerate(row): 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): if self.white_turn and re.search('B.', piece) and self.valid_move((x, y), self.b_king_pos):

View file

@ -23,30 +23,7 @@ class Core:
self.results_per_page = 10 self.results_per_page = 10
self.commands = None self.commands = None
def find_command(self, command): @commands.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)
@utils.custom_perms(send_messages=True) @utils.custom_perms(send_messages=True)
async def help(self, ctx, *, message=None): async def help(self, ctx, *, message=None):
"""This command is used to provide a link to the help URL. """This command is used to provide a link to the help URL.
@ -65,7 +42,7 @@ class Core:
try: try:
page = int(message) page = int(message)
except: except:
cmd = self.find_command(message) cmd = self.bot.get_command(message)
if cmd is None: if cmd is None:
entries = sorted(utils.get_all_commands(self.bot)) entries = sorted(utils.get_all_commands(self.bot))
@ -73,7 +50,7 @@ class Core:
pages = utils.Pages(self.bot, message=ctx.message, entries=entries) pages = utils.Pages(self.bot, message=ctx.message, entries=entries)
await pages.paginate(start_page=page) await pages.paginate(start_page=page)
except utils.CannotPaginate as e: except utils.CannotPaginate as e:
await self.bot.say(str(e)) await ctx.send(str(e))
else: else:
# Get the description for a command # Get the description for a command
description = cmd.help description = cmd.help
@ -100,11 +77,11 @@ class Core:
if subcommands: if subcommands:
embed.add_field(name='Subcommands', value="\n".join(subcommands), inline=False) embed.add_field(name='Subcommands', value="\n".join(subcommands), inline=False)
await self.bot.say(embed=embed) await ctx.send(embed=embed)
@commands.command() @commands.command()
@utils.custom_perms(send_messages=True) @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 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 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'] motd = latest_motd['motd']
# This will be hit if we do not have any entries for motd # This will be hit if we do not have any entries for motd
except TypeError: except TypeError:
await self.bot.say("No message of the day!") await ctx.send("No message of the day!")
else: else:
fmt = "Last updated: {}\n\n{}".format(date, motd) fmt = "Last updated: {}\n\n{}".format(date, motd)
await self.bot.say(fmt) await ctx.send(fmt)
else: else:
try: try:
r_filter = pendulum.parse(date) r_filter = pendulum.parse(date)
@ -137,18 +114,18 @@ class Core:
date = motd[0]['date'] date = motd[0]['date']
motd = motd[0]['motd'] motd = motd[0]['motd']
fmt = "Message of the day for {}:\n\n{}".format(date, 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 # This one will be hit if we return None for that day
except TypeError: 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 # This will be hit if pendulum fails to parse the date passed
except ValueError: except ValueError:
now = pendulum.utcnow().to_date_string() 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() @commands.command()
@utils.custom_perms(send_messages=True) @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 """Provides a printout of the current month's calendar
Provide month and year to print the calendar of that year and month Provide month and year to print the calendar of that year and month
@ -176,30 +153,23 @@ class Core:
else: else:
month = months.get(month.lower()) month = months.get(month.lower())
if month is None: if month is None:
await self.bot.say("Please provide a valid Month!") await ctx.send("Please provide a valid Month!")
return return
# If year was not passed, use the current year # If year was not passed, use the current year
if year is None: if year is None:
year = datetime.datetime.today().year year = datetime.datetime.today().year
# Here we create the actual "text" calendar that we are printing # Here we create the actual "text" calendar that we are printing
cal = calendar.TextCalendar().formatmonth(year, month) cal = calendar.TextCalendar().formatmonth(year, month)
await self.bot.say("```\n{}```".format(cal)) await ctx.send("```\n{}```".format(cal))
@commands.command() @commands.command()
@utils.custom_perms(send_messages=True) @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""" """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 # 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 # The only real use of doing it this way is easier editing if the info
# in this command is changed # 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 # Create the original embed object
opts = {'title': 'Dev Server', opts = {'title': 'Dev Server',
'description': 'Join the server above for any questions/suggestions about me.', 'description': 'Join the server above for any questions/suggestions about me.',
@ -207,8 +177,8 @@ class Core:
embed = discord.Embed(**opts) embed = discord.Embed(**opts)
# Add the normal values # Add the normal values
embed.add_field(name='Total Servers', value=total_data['server_count']) embed.add_field(name='Total Servers', value=len(self.bot.servers))
embed.add_field(name='Total Members', value=total_data['member_count']) embed.add_field(name='Total Members', value=len(set(self.bot.get_all_members())))
# Count the variable values; hangman, tictactoe, etc. # Count the variable values; hangman, tictactoe, etc.
hm_games = len(self.bot.get_cog('Hangman').games) 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.add_field(name='Uptime', value=(pendulum.utcnow() - self.bot.uptime).in_words())
embed.set_footer(text=self.bot.description) embed.set_footer(text=self.bot.description)
await self.bot.say(embed=embed) await ctx.send(embed=embed)
@commands.command() @commands.command()
@utils.custom_perms(send_messages=True) @utils.custom_perms(send_messages=True)
async def uptime(self): async def uptime(self, ctx):
"""Provides a printout of the current bot's uptime """Provides a printout of the current bot's uptime
EXAMPLE: !uptime EXAMPLE: !uptime
RESULT: A BAJILLION DAYS""" 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']) @commands.command(aliases=['invite'])
@utils.custom_perms(send_messages=True) @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 """Provides a link that you can use to add me to a server
EXAMPLE: !addbot EXAMPLE: !addbot
@ -261,13 +231,17 @@ class Core:
perms.embed_links = True perms.embed_links = True
perms.read_message_history = True perms.read_message_history = True
perms.attach_files = 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() 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))) .format(discord.utils.oauth_url(app_info.id, perms)))
@commands.command() @commands.command()
@utils.custom_perms(send_messages=True) @utils.custom_perms(send_messages=True)
async def doggo(self): async def doggo(self, ctx):
"""Use this to print a random doggo image. """Use this to print a random doggo image.
EXAMPLE: !doggo EXAMPLE: !doggo
@ -275,7 +249,7 @@ class Core:
# Find a random image based on how many we currently have # Find a random image based on how many we currently have
f = random.SystemRandom().choice(glob.glob('images/doggo*')) f = random.SystemRandom().choice(glob.glob('images/doggo*'))
with open(f, 'rb') as f: with open(f, 'rb') as f:
await self.bot.upload(f) await ctx.send(file=f)
@commands.command() @commands.command()
@utils.custom_perms(send_messages=True) @utils.custom_perms(send_messages=True)
@ -287,11 +261,11 @@ class Core:
# Find a random image based on how many we currently have # Find a random image based on how many we currently have
f = random.SystemRandom().choice(glob.glob('images/snek*')) f = random.SystemRandom().choice(glob.glob('images/snek*'))
with open(f, 'rb') as f: with open(f, 'rb') as f:
await self.bot.upload(f) await ctx.send(file=f)
@commands.command() @commands.command()
@utils.custom_perms(send_messages=True) @utils.custom_perms(send_messages=True)
async def joke(self): async def joke(self, ctx):
"""Prints a random riddle """Prints a random riddle
EXAMPLE: !joke EXAMPLE: !joke
@ -302,13 +276,13 @@ class Core:
try: try:
fortune = subprocess.check_output( fortune = subprocess.check_output(
fortune_command.split()).decode("utf-8") fortune_command.split()).decode("utf-8")
await self.bot.say(fortune) await ctx.send(fortune)
except discord.HTTPException: except discord.HTTPException:
pass pass
else: else:
break break
@commands.command(pass_context=True) @commands.command()
@utils.custom_perms(send_messages=True) @utils.custom_perms(send_messages=True)
async def roll(self, ctx, notation: str = "d6"): async def roll(self, ctx, notation: str = "d6"):
"""Rolls a die based on the notation given """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 # Check if something like ed3 was provided, or something else entirely
# was provided # was provided
except (AttributeError, ValueError): 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 return
# Dice will be None if d# was provided, assume this means 1d# # Dice will be None if d# was provided, assume this means 1d#
@ -334,13 +308,13 @@ class Core:
# have it set # have it set
dice = int(dice) dice = int(dice)
if dice > 10: 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 return
if num > 100: 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 return
if num <= 1: 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 return
value_str = ", ".join(str(random.SystemRandom().randint(1, num)) 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}!' fmt = '{0.message.author.name} has rolled a {2} sided die and got the number {3}!'
else: else:
fmt = '{0.message.author.name} has rolled {1}, {2} sided dice and got the numbers {3}!' 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): def setup(bot):

View file

@ -59,9 +59,7 @@ class Deviantart:
try: try:
for entry in content: for entry in content:
user = discord.utils.get(self.bot.get_all_members(), id=entry['member_id']) user = discord.utils.get(self.bot.get_all_members(), id=entry['member_id'])
# If the bot is not in the server with the member, we might not be able to find this user.
# 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 user is None: if user is None:
continue continue
@ -97,7 +95,7 @@ class Deviantart:
result['title'], result['title'],
result['author']['username'], result['author']['username'],
result['url']) result['url'])
await self.bot.send_message(user, fmt) await user.sendfmt)
# Now we can update the user's last updated for this DA # 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 # We want to do this whether or not our last if statement was met
r_filter = {'member_id': user.id} r_filter = {'member_id': user.id}
@ -110,12 +108,12 @@ class Deviantart:
@commands.group() @commands.group()
@utils.custom_perms(send_messages=True) @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. """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""" Subscribe to artists, and I will PM you when new posts come out from these artists"""
pass pass
@da.command(pass_context=True, name='sub', aliases=['add', 'subscribe']) @da.command(name='sub', aliases=['add', 'subscribe'])
@utils.custom_perms(send_messages=True) @utils.custom_perms(send_messages=True)
async def da_sub(self, ctx, *, username): async def da_sub(self, ctx, *, username):
"""This can be used to add a feed to your notifications. """This can be used to add a feed to your notifications.
@ -130,7 +128,7 @@ class Deviantart:
if content is None: if content is None:
entry = {'member_id': ctx.message.author.id, 'subbed': [username], 'last_updated': {}} entry = {'member_id': ctx.message.author.id, 'subbed': [username], 'last_updated': {}}
await utils.add_content('deviantart', entry, r_filter) 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']: elif content[0]['subbed'] is None or username not in content[0]['subbed']:
if content[0]['subbed'] is None: if content[0]['subbed'] is None:
sub_list = [username] sub_list = [username]
@ -138,9 +136,9 @@ class Deviantart:
content[0]['subbed'].append(username) content[0]['subbed'].append(username)
sub_list = content[0]['subbed'] sub_list = content[0]['subbed']
await utils.update_content('deviantart', {'subbed': sub_list}, r_filter) 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: 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']) @da.command(pass_context=True, name='unsub', aliases=['delete', 'remove', 'unsubscribe'])
@utils.custom_perms(send_messages=True) @utils.custom_perms(send_messages=True)
@ -153,13 +151,13 @@ class Deviantart:
content = await utils.get_content('deviantart', r_filter) content = await utils.get_content('deviantart', r_filter)
if content is None or content[0]['subbed'] is None: 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']: elif username in content[0]['subbed']:
content[0]['subbed'].remove(username) content[0]['subbed'].remove(username)
await utils.update_content('deviantart', {'subbed': content[0]['subbed']}, r_filter) 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: 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): def setup(bot):

View file

@ -19,7 +19,7 @@ class Music:
async def on_voice_state_update(self, before, after): async def on_voice_state_update(self, before, after):
pass pass
@commands.command(pass_context=True, no_pm=True, enabled=False) @commands.command(no_pm=True, enabled=False)
@checks.custom_perms(send_messages=True) @checks.custom_perms(send_messages=True)
async def progress(self, ctx): async def progress(self, ctx):
"""Provides the progress of the current song """Provides the progress of the current song
@ -28,7 +28,7 @@ class Music:
RESULT: 532 minutes! (Hopefully not)""" RESULT: 532 minutes! (Hopefully not)"""
pass pass
@commands.command(pass_context=True, no_pm=True, enabled=False) @commands.command(no_pm=True, enabled=False)
@checks.custom_perms(send_messages=True) @checks.custom_perms(send_messages=True)
async def join(self, ctx, *, channel: discord.Channel): async def join(self, ctx, *, channel: discord.Channel):
"""Joins a voice channel. """Joins a voice channel.
@ -37,7 +37,7 @@ class Music:
RESULT: I'm in the Music voice channel!""" RESULT: I'm in the Music voice channel!"""
pass pass
@commands.command(pass_context=True, no_pm=True, enabled=False) @commands.command(no_pm=True, enabled=False)
@checks.custom_perms(send_messages=True) @checks.custom_perms(send_messages=True)
async def summon(self, ctx): async def summon(self, ctx):
"""Summons the bot to join your voice channel. """Summons the bot to join your voice channel.
@ -46,7 +46,7 @@ class Music:
RESULT: I'm in your voice channel!""" RESULT: I'm in your voice channel!"""
pass pass
@commands.command(pass_context=True, no_pm=True, enabled=False) @commands.command(no_pm=True, enabled=False)
@checks.custom_perms(send_messages=True) @checks.custom_perms(send_messages=True)
async def play(self, ctx, *, song: str): async def play(self, ctx, *, song: str):
"""Plays a song. """Plays a song.
@ -61,7 +61,7 @@ class Music:
""" """
pass pass
@commands.command(pass_context=True, no_pm=True, enabled=False) @commands.command(no_pm=True, enabled=False)
@checks.custom_perms(kick_members=True) @checks.custom_perms(kick_members=True)
async def volume(self, ctx, value: int = None): async def volume(self, ctx, value: int = None):
"""Sets the volume of the currently playing song. """Sets the volume of the currently playing song.
@ -70,7 +70,7 @@ class Music:
RESULT: My volume is now set to 50""" RESULT: My volume is now set to 50"""
pass pass
@commands.command(pass_context=True, no_pm=True, enabled=False) @commands.command(no_pm=True, enabled=False)
@checks.custom_perms(kick_members=True) @checks.custom_perms(kick_members=True)
async def pause(self, ctx): async def pause(self, ctx):
"""Pauses the currently played song. """Pauses the currently played song.
@ -79,7 +79,7 @@ class Music:
RESULT: I'm paused!""" RESULT: I'm paused!"""
pass pass
@commands.command(pass_context=True, no_pm=True, enabled=False) @commands.command(no_pm=True, enabled=False)
@checks.custom_perms(kick_members=True) @checks.custom_perms(kick_members=True)
async def resume(self, ctx): async def resume(self, ctx):
"""Resumes the currently played song. """Resumes the currently played song.
@ -88,7 +88,7 @@ class Music:
RESULT: Ain't paused no more!""" RESULT: Ain't paused no more!"""
pass pass
@commands.command(pass_context=True, no_pm=True, enabled=False) @commands.command(no_pm=True, enabled=False)
@checks.custom_perms(kick_members=True) @checks.custom_perms(kick_members=True)
async def stop(self, ctx): async def stop(self, ctx):
"""Stops playing audio and leaves the voice channel. """Stops playing audio and leaves the voice channel.
@ -98,7 +98,7 @@ class Music:
RESULT: No more music""" RESULT: No more music"""
pass pass
@commands.command(pass_context=True, no_pm=True, enabled=False) @commands.command(no_pm=True, enabled=False)
@checks.custom_perms(send_messages=True) @checks.custom_perms(send_messages=True)
async def eta(self, ctx): async def eta(self, ctx):
"""Provides an ETA on when your next song will play """Provides an ETA on when your next song will play
@ -107,7 +107,7 @@ class Music:
RESULT: 5,000 days! Lol have fun""" RESULT: 5,000 days! Lol have fun"""
pass pass
@commands.command(pass_context=True, no_pm=True, enabled=False) @commands.command(no_pm=True, enabled=False)
@checks.custom_perms(send_messages=True) @checks.custom_perms(send_messages=True)
async def queue(self, ctx): async def queue(self, ctx):
"""Provides a printout of the songs that are in the queue. """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""" RESULT: A list of shitty songs you probably don't wanna listen to"""
pass pass
@commands.command(pass_context=True, no_pm=True, enabled=False) @commands.command(no_pm=True, enabled=False)
@checks.custom_perms(send_messages=True) @checks.custom_perms(send_messages=True)
async def queuelength(self, ctx): async def queuelength(self, ctx):
"""Prints the length of the queue """Prints the length of the queue
@ -130,7 +130,7 @@ class Music:
RESULT: Probably 10 songs""" RESULT: Probably 10 songs"""
pass pass
@commands.command(pass_context=True, no_pm=True, enabled=False) @commands.command(no_pm=True, enabled=False)
@checks.custom_perms(send_messages=True) @checks.custom_perms(send_messages=True)
async def skip(self, ctx): async def skip(self, ctx):
"""Vote to skip a song. The song requester can automatically skip. """Vote to skip a song. The song requester can automatically skip.
@ -142,7 +142,7 @@ class Music:
""" """
pass pass
@commands.command(pass_context=True, no_pm=True, enabled=False) @commands.command(no_pm=True, enabled=False)
@checks.custom_perms(kick_members=True) @checks.custom_perms(kick_members=True)
async def modskip(self, ctx): async def modskip(self, ctx):
"""Forces a song skip, can only be used by a moderator """Forces a song skip, can only be used by a moderator
@ -151,7 +151,7 @@ class Music:
RESULT: No more terrible song :D""" RESULT: No more terrible song :D"""
pass pass
@commands.command(pass_context=True, no_pm=True, enabled=False) @commands.command(no_pm=True, enabled=False)
@checks.custom_perms(send_messages=True) @checks.custom_perms(send_messages=True)
async def playing(self, ctx): async def playing(self, ctx):
"""Shows info about the currently played song. """Shows info about the currently played song.

View file

@ -48,38 +48,17 @@ class StatsUpdate:
log.info('bots.discord.pw statistics returned {} for {}'.format(resp.status, payload)) log.info('bots.discord.pw statistics returned {} for {}'.format(resp.status, payload))
async def on_server_join(self, server): 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()) self.bot.loop.create_task(self.update())
async def on_server_leave(self, server): 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()) self.bot.loop.create_task(self.update())
async def on_ready(self): 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()) self.bot.loop.create_task(self.update())
async def on_member_join(self, member): async def on_member_join(self, member):
server = member.server guild = member.guild
r_filter = {'server_id': server.id} r_filter = {'server_id': guild.id}
notifications = await config.get_content('user_notifications', r_filter) notifications = await config.get_content('user_notifications', r_filter)
try: try:
@ -91,12 +70,12 @@ class StatsUpdate:
if not channel_id: if not channel_id:
return return
channel = server.get_channel(channel_id) channel = guild.get_channel(channel_id)
await self.bot.send_message(channel, "Welcome to the '{0.server.name}' server {0.mention}!".format(member)) await channel.send("Welcome to the '{0.server.name}' server {0.mention}!".format(member))
async def on_member_remove(self, member): async def on_member_remove(self, member):
server = member.server guild = member.guild
r_filter = {'server_id': server.id} r_filter = {'server_id': guild.id}
notifications = await config.get_content('user_notifications', r_filter) notifications = await config.get_content('user_notifications', r_filter)
try: try:
@ -109,9 +88,7 @@ class StatsUpdate:
return return
channel = server.get_channel(channel_id) channel = server.get_channel(channel_id)
await self.bot.send_message(channel, await channelsend("{0} has left the server, I hope it wasn't because of something I said :c".format(member.display_name))
"{0} has left the server, I hope it wasn't because of something I said :c".format(
member.display_name))
def setup(bot): def setup(bot):

View file

@ -104,10 +104,10 @@ class Hangman:
def create(self, word, ctx): def create(self, word, ctx):
# Create a new game, then save it as the server's game # Create a new game, then save it as the server's game
game = Game(word) game = Game(word)
self.games[ctx.message.server.id] = game self.games[ctx.message.guild.id] = game
return 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) @commands.cooldown(1, 7, BucketType.user)
@checks.custom_perms(send_messages=True) @checks.custom_perms(send_messages=True)
async def hangman(self, ctx, *, guess): async def hangman(self, ctx, *, guess):
@ -115,10 +115,10 @@ class Hangman:
EXAMPLE: !hangman e (or) !hangman The Phrase! EXAMPLE: !hangman e (or) !hangman The Phrase!
RESULT: Hopefully a win!""" RESULT: Hopefully a win!"""
game = self.games.get(ctx.message.server.id) game = self.games.get(ctx.message.guild.id)
if not game: if not game:
ctx.command.reset_cooldown(ctx) 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 return
# Check if we are guessing a letter or a phrase. Only one letter can be guessed at a time # 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 len(guess) == 1:
if guess in game.guessed_letters: if guess in game.guessed_letters:
ctx.command.reset_cooldown(ctx) 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 here as we don't want to count this as a failure
return return
if game.guess_letter(guess): if game.guess_letter(guess):
@ -143,16 +143,16 @@ class Hangman:
if game.win(): if game.win():
fmt += " You guys got it! The word was `{}`".format(game.word) 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(): elif game.failed():
fmt += " Sorry, you guys failed...the word was `{}`".format(game.word) 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: else:
fmt += str(game) 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) @checks.custom_perms(send_messages=True)
async def create_hangman(self, ctx): async def create_hangman(self, ctx):
"""This is used to create a new hangman game """This is used to create a new hangman game
@ -163,16 +163,16 @@ class Hangman:
# Only have one hangman game per server, since anyone # Only have one hangman game per server, since anyone
# In a server (except the creator) can guess towards the current game # In a server (except the creator) can guess towards the current game
if self.games.get(ctx.message.server.id) is not None: if self.games.get(ctx.message.guild.id) is not None:
await self.bot.say("Sorry but only one Hangman game can be running per server!") await ctx.send("Sorry but only one Hangman game can be running per server!")
return return
game = self.create(random.SystemRandom().choice(phrases), ctx) 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 # 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))) "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) @checks.custom_perms(kick_members=True)
async def stop_game(self, ctx): async def stop_game(self, ctx):
"""Force stops a game of hangman """Force stops a game of hangman
@ -181,12 +181,12 @@ class Hangman:
EXAMPLE: !hangman stop EXAMPLE: !hangman stop
RESULT: No more men being hung""" RESULT: No more men being hung"""
if self.games.get(ctx.message.server.id) is None: if self.games.get(ctx.message.guild.id) is None:
await self.bot.say("There are no Hangman games running on this server!") await ctx.send("There are no Hangman games running on this server!")
return return
del self.games[ctx.message.server.id] del self.games[ctx.message.guild.id]
await self.bot.say("I have just stopped the game of Hangman, a new should be able to be started now!") await ctx.send("I have just stopped the game of Hangman, a new should be able to be started now!")
def setup(bot): def setup(bot):

View file

@ -85,7 +85,7 @@ class Interaction:
self.battles = {} self.battles = {}
def user_battling(self, ctx, player2=None): 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 no one is battling, obviously the user is not battling
if battling is None: if battling is None:
@ -101,14 +101,14 @@ class Interaction:
# Handles removing the author from the dictionary of battles # Handles removing the author from the dictionary of battles
def battling_off(self, ctx): 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 player_id = ctx.message.author.id
# Create a new dictionary, exactly the way the last one was setup # Create a new dictionary, exactly the way the last one was setup
# But don't include any that have the author's ID # 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} 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) @utils.custom_perms(send_messages=True)
async def hug(self, ctx, user: discord.Member = None): async def hug(self, ctx, user: discord.Member = None):
"""Makes me hug a person! """Makes me hug a person!
@ -119,9 +119,9 @@ class Interaction:
user = ctx.message.author user = ctx.message.author
fmt = random.SystemRandom().choice(hugs) 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) @utils.custom_perms(send_messages=True)
async def avatar(self, ctx, member: discord.Member = None): 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) """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 member = ctx.message.author
url = member.avatar_url 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) file = await utils.download_image(url)
if file is None: if file is None:
await self.bot.say(url) await ctx.send(url)
else: else:
if '.gif' in url: if '.gif' in url:
filename = 'avatar.gif' filename = 'avatar.gif'
else: else:
filename = 'avatar.webp' filename = 'avatar.webp'
file = utils.convert_to_jpeg(file) file = utils.convert_to_jpeg(file)
await self.bot.upload(file, filename=filename) await ctx.send(file=file, filename=filename)
else: 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) @commands.cooldown(1, 180, BucketType.user)
@utils.custom_perms(send_messages=True) @utils.custom_perms(send_messages=True)
async def battle(self, ctx, player2: discord.Member): async def battle(self, ctx, player2: discord.Member):
@ -157,29 +157,29 @@ class Interaction:
RESULT: A battle to the death""" RESULT: A battle to the death"""
if ctx.message.author.id == player2.id: if ctx.message.author.id == player2.id:
ctx.command.reset_cooldown(ctx) 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 return
if self.bot.user.id == player2.id: if self.bot.user.id == player2.id:
ctx.command.reset_cooldown(ctx) 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 return
if self.user_battling(ctx, player2): if self.user_battling(ctx, player2):
ctx.command.reset_cooldown(ctx) 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 return
# Add the author and player provided in a new battle # 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 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" \ fmt = "{0.message.author.mention} has challenged you to a battle {1.mention}\n" \
"{0.prefix}accept or {0.prefix}decline" "{0.prefix}accept or {0.prefix}decline"
# Add a call to turn off battling, if the battle is not accepted/declined in 3 minutes # 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) 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) @utils.custom_perms(send_messages=True)
async def accept(self, ctx): async def accept(self, ctx):
"""Accepts the battle challenge """Accepts the battle challenge
@ -188,13 +188,13 @@ class Interaction:
RESULT: Hopefully the other person's death""" RESULT: Hopefully the other person's death"""
# This is a check to make sure that the author is the one being BATTLED # This is a check to make sure that the author is the one being BATTLED
# And not the one that started the battle # 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] p1 = [p1_id for p1_id, p2_id in battles.items() if p2_id == ctx.message.author.id]
if len(p1) == 0: 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 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 battleP2 = ctx.message.author
# Get a random win message from our list # 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 # 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 # All we need to do is change what order the challengers are printed/added as a paramater
if random.SystemRandom().randint(0, 1): 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) await utils.update_records('battle_records', battleP1, battleP2)
else: 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) 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) @utils.custom_perms(send_messages=True)
async def decline(self, ctx): async def decline(self, ctx):
"""Declines the battle challenge """Declines the battle challenge
@ -220,20 +220,20 @@ class Interaction:
RESULT: You chicken out""" RESULT: You chicken out"""
# This is a check to make sure that the author is the one being BATTLED # This is a check to make sure that the author is the one being BATTLED
# And not the one that started the battle # 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] p1 = [p1_id for p1_id, p2_id in battles.items() if p2_id == ctx.message.author.id]
if len(p1) == 0: 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 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 battleP2 = ctx.message.author
# There's no need to update the stats for the members if they declined the battle # There's no need to update the stats for the members if they declined the battle
self.battling_off(ctx) 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) @commands.cooldown(1, 180, BucketType.user)
@utils.custom_perms(send_messages=True) @utils.custom_perms(send_messages=True)
async def boop(self, ctx, boopee: discord.Member = None, *, message = ""): async def boop(self, ctx, boopee: discord.Member = None, *, message = ""):
@ -244,18 +244,18 @@ class Interaction:
booper = ctx.message.author booper = ctx.message.author
if boopee is None: if boopee is None:
ctx.command.reset_cooldown(ctx) 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 return
# To keep formatting easier, keep it either "" or the message with a space in front # To keep formatting easier, keep it either "" or the message with a space in front
if message is not None: if message is not None:
message = " " + message message = " " + message
if boopee.id == booper.id: if boopee.id == booper.id:
ctx.command.reset_cooldown(ctx) 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 return
if boopee.id == self.bot.user.id: if boopee.id == self.bot.user.id:
ctx.command.reset_cooldown(ctx) 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 return
r_filter = {'member_id': booper.id} r_filter = {'member_id': booper.id}
@ -275,7 +275,7 @@ class Interaction:
amount = 1 amount = 1
fmt = "{0.mention} has just booped {1.mention}{3}! That's {2} times now!" 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): def setup(bot):

View file

@ -17,13 +17,15 @@ class Links:
def __init__(self, bot): def __init__(self, bot):
self.bot = bot self.bot = bot
@commands.command(pass_context=True, aliases=['g']) @commands.command(aliases=['g'])
@utils.custom_perms(send_messages=True) @utils.custom_perms(send_messages=True)
async def google(self, ctx, *, query: str): async def google(self, ctx, *, query: str):
"""Searches google for a provided query """Searches google for a provided query
EXAMPLE: !g Random cat pictures! EXAMPLE: !g Random cat pictures!
RESULT: Links to sites with random cat pictures!""" RESULT: Links to sites with random cat pictures!"""
await ctx.message.channel.trigger_typing()
url = "https://www.google.com/search" url = "https://www.google.com/search"
# Turn safe filter on or off, based on whether or not this is a nsfw channel # 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') data = await utils.request(url, payload=params, attr='text')
if data is None: 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 return
# Convert to a BeautifulSoup element and loop through each result clasified by h3 tags with a class of 'r' # 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: try:
result_url = re.search('(?<=q=).*(?=&sa=)', element.find('a').get('href')).group(0) result_url = re.search('(?<=q=).*(?=&sa=)', element.find('a').get('href')).group(0)
except AttributeError: 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 return
# Get the next sibling, find the span where the description is, and get the text from this # 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 += '\n\n**URL**: <{}>\n**Description**: {}'.format(result_url, description)
fmt = "**Top 3 results for the query** _{}_:{}".format(query, fmt) 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) @utils.custom_perms(send_messages=True)
async def youtube(self, ctx, *, query: str): async def youtube(self, ctx, *, query: str):
"""Searches youtube for a provided query """Searches youtube for a provided query
EXAMPLE: !youtube Cat videos! EXAMPLE: !youtube Cat videos!
RESULT: Cat videos!""" RESULT: Cat videos!"""
await ctx.message.channel.trigger_typing()
key = utils.youtube_key key = utils.youtube_key
url = "https://www.googleapis.com/youtube/v3/search" url = "https://www.googleapis.com/youtube/v3/search"
params = {'key': key, params = {'key': key,
@ -87,13 +91,13 @@ class Links:
data = await utils.request(url, payload=params) data = await utils.request(url, payload=params)
if data is None: 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 return
try: try:
result = data['items'][0] result = data['items'][0]
except IndexError: 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 return
result_url = "https://youtube.com/watch?v={}".format(result['id']['videoId']) result_url = "https://youtube.com/watch?v={}".format(result['id']['videoId'])
@ -101,15 +105,17 @@ class Links:
description = result['snippet']['description'] description = result['snippet']['description']
fmt = "**Title:** {}\n\n**Description:** {}\n\n**URL:** <{}>".format(title, description, result_url) 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) @utils.custom_perms(send_messages=True)
async def wiki(self, ctx, *, query: str): async def wiki(self, ctx, *, query: str):
"""Pulls the top match for a specific term from wikipedia, and returns the result """Pulls the top match for a specific term from wikipedia, and returns the result
EXAMPLE: !wiki Test EXAMPLE: !wiki Test
RESULT: A link to the wikipedia article for the word 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 # 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" base_url = "https://en.wikipedia.org/w/api.php"
params = {"action": "query", params = {"action": "query",
@ -120,11 +126,11 @@ class Links:
data = await utils.request(base_url, payload=params) data = await utils.request(base_url, payload=params)
if data is None: 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 return
if len(data['query']['search']) == 0: 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 return
# Wiki articles' URLs are in the format https://en.wikipedia.org/wiki/[Titlehere] # Wiki articles' URLs are in the format https://en.wikipedia.org/wiki/[Titlehere]
# Replace spaces with %20 # Replace spaces with %20
@ -136,36 +142,38 @@ class Links:
snippet = re.sub('</span>', '', snippet) snippet = re.sub('</span>', '', snippet)
snippet = re.sub('&quot;', '"', snippet) snippet = re.sub('&quot;', '"', 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, "Here is the best match I found with the query `{}`:\nURL: <{}>\nSnippet: \n```\n{}```".format(query, url,
snippet)) snippet))
@commands.command(pass_context=True) @commands.command()
@utils.custom_perms(send_messages=True) @utils.custom_perms(send_messages=True)
async def urban(self, ctx, *, msg: str): async def urban(self, ctx, *, msg: str):
"""Pulls the top urbandictionary.com definition for a term """Pulls the top urbandictionary.com definition for a term
EXAMPLE: !urban a normal phrase EXAMPLE: !urban a normal phrase
RESULT: Probably something lewd; this is urban dictionary we're talking about""" 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" url = "http://api.urbandictionary.com/v0/define"
params = {"term": msg} params = {"term": msg}
try: try:
data = await utils.request(url, payload=params) data = await utils.request(url, payload=params)
if data is None: 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 return
# List is the list of definitions found, if it's empty then nothing was found # List is the list of definitions found, if it's empty then nothing was found
if len(data['list']) == 0: 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 # If the list is not empty, use the first result and print it's defintion
else: 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 # Urban dictionary has some long definitions, some might not be able to be sent
except discord.HTTPException: 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: 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) @commands.command(pass_context=True)
@utils.custom_perms(send_messages=True) @utils.custom_perms(send_messages=True)
@ -174,6 +182,8 @@ class Links:
EXAMPLE: !derpi Rainbow Dash EXAMPLE: !derpi Rainbow Dash
RESULT: A picture of Rainbow Dash!""" RESULT: A picture of Rainbow Dash!"""
await ctx.message.channel.trigger_typing()
if len(search) > 0: if len(search) > 0:
url = 'https://derpibooru.org/search.json' url = 'https://derpibooru.org/search.json'
@ -192,18 +202,16 @@ class Links:
else: else:
params['q'] += ", safe" params['q'] += ", safe"
await self.bot.say("Looking up an image with those tags....")
try: try:
# Get the response from derpibooru and parse the 'search' result from it # Get the response from derpibooru and parse the 'search' result from it
data = await utils.request(url, payload=params) data = await utils.request(url, payload=params)
if data is None: 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 return
results = data['search'] results = data['search']
except KeyError: 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 return
# The first request we've made ensures there are results # The first request we've made ensures there are results
@ -215,7 +223,7 @@ class Links:
params['page'] = random.SystemRandom().randint(1, pages) params['page'] = random.SystemRandom().randint(1, pages)
data = await utils.request(url, payload=params) data = await utils.request(url, payload=params)
if data is None: 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 return
# Now get the results again # Now get the results again
results = data['search'] results = data['search']
@ -224,14 +232,14 @@ class Links:
index = random.SystemRandom().randint(0, len(results) - 1) index = random.SystemRandom().randint(0, len(results) - 1)
image_link = 'https://derpibooru.org/{}'.format(results[index]['id']) image_link = 'https://derpibooru.org/{}'.format(results[index]['id'])
else: 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 return
else: else:
# If no search term was provided, search for a random image # If no search term was provided, search for a random image
# .url will be the URL we end up at, not the one requested. # .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 # 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') 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) @commands.command(pass_context=True)
@utils.custom_perms(send_messages=True) @utils.custom_perms(send_messages=True)
@ -242,19 +250,19 @@ class Links:
EXAMPLE: !e621 dragon EXAMPLE: !e621 dragon
RESULT: A picture of a dragon (hopefully, screw your tagging system e621)""" 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 # This changes the formatting for queries, so we don't
# Have to use e621's stupid formatting when using the command # Have to use e621's stupid formatting when using the command
tags = tags.replace(' ', '_') tags = tags.replace(' ', '_')
tags = tags.replace(',_', ' ') tags = tags.replace(',_', ' ')
url = 'https://e621.net/post/index.json' url = 'https://e621.net/post/index.json'
params = {'limit': 320, params = {'limit': 320,
'tags': tags} '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} r_filter = {'channel_id': ctx.message.channel.id}
nsfw_channels = await utils.get_content("nsfw_channels", r_filter) nsfw_channels = await utils.get_content("nsfw_channels", r_filter)
@ -266,8 +274,7 @@ class Links:
data = await utils.request(url, payload=params) data = await utils.request(url, payload=params)
if data is None: if data is None:
await self.bot.send_message(ctx.message.channel, await ctx.send("Sorry, I had trouble connecting at the moment; please try again later")
"Sorry, I had trouble connecting at the moment; please try again later")
return return
# Try to find an image from the list. If there were no results, we're going to attempt to find # 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. # i.e. it responded with a 404/504/etc.
try: try:
rand_image = data[random.SystemRandom().randint(0, len(data) - 1)]['file_url'] 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): 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 return

View file

@ -16,53 +16,30 @@ class Mod:
def __init__(self, bot): def __init__(self, bot):
self.bot = bot self.bot = bot
def find_command(self, command): @commands.command(no_pm=True, aliases=['nick'])
# 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'])
@utils.custom_perms(kick_members=True) @utils.custom_perms(kick_members=True)
async def nickname(self, ctx, *, name=None): async def nickname(self, ctx, *, name=None):
"""Used to set the nickname for Bonfire (provide no nickname and it will reset) """Used to set the nickname for Bonfire (provide no nickname and it will reset)
EXAMPLE: !nick Music Bot EXAMPLE: !nick Music Bot
RESULT: My nickname is now music bot""" RESULT: My nickname is now Music Bot"""
await self.bot.change_nickname(ctx.message.server.me, name) await ctx.message.server.me.edit(nick=name)
await self.bot.say("\N{OK HAND SIGN}") await ctx.send("\N{OK HAND SIGN}")
@commands.command(no_pm=True) @commands.command(no_pm=True)
@utils.custom_perms(kick_members=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 """Used to kick a member from this server
EXAMPLE: !kick @Member EXAMPLE: !kick @Member
RESULT: They're kicked from the server?""" RESULT: They're kicked from the server?"""
try: try:
await self.bot.kick(member) await member.kick()
await self.bot.say("\N{OK HAND SIGN}") await ctx.send("\N{OK HAND SIGN}")
except discord.Forbidden: 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) @utils.custom_perms(ban_members=True)
async def unban(self, ctx, member_id: int): async def unban(self, ctx, member_id: int):
"""Used to unban a member from this server """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 # 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 # 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: try:
await self.bot.unban(ctx.message.server, member) await discord.http.unban(member.id, ctx.guild.id)
await self.bot.say("\N{OK HAND SIGN}") await ctx.send("\N{OK HAND SIGN}")
except discord.Forbidden: 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: 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) @utils.custom_perms(ban_members=True)
async def ban(self, ctx, *, member): async def ban(self, ctx, *, member):
"""Used to ban a 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 # Lets first check if a user ID was provided, as that will be the easiest case to ban
if member.isdigit(): if member.isdigit():
# First convert it to a discord object based on the ID that was given try:
member = discord.Object(id=member) await discord.http.ban(member, ctx.guild.id)
# Next, to ban from the server the API takes a server obejct and uses that ID await ctx.send("\N{OK HAND SIGN}")
# So set "this" server as the member's server. This creates the "fake" member we need except discord.Forbidden:
member.server = ctx.message.server 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: else:
# If no ID was provided, lets try to convert what was given using the internal coverter # 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: try:
member = converter.convert() member = converter.convert()
except commands.converter.BadArgument: 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 ' '{} does not appear to be a valid member. If this member is not in this server, please provide '
'their ID'.format(member)) 'their ID'.format(member))
return return
# Now lets try actually banning the member we've been given # Now lets try actually banning the member we've been given
try: try:
await self.bot.ban(member) await member.ban()
await self.bot.say("\N{OK HAND SIGN}") await ctx.send("\N{OK HAND SIGN}")
except discord.Forbidden: 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: 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) @utils.custom_perms(kick_members=True)
async def alerts(self, ctx, channel: discord.Channel): async def alerts(self, ctx, channel: discord.Channel):
"""This command is used to set a channel as the server's 'notifications' 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} 'channel_id': channel.id}
if not await utils.add_content('server_alerts', entry, r_filter): if not await utils.add_content('server_alerts', entry, r_filter):
await utils.update_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)) "\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) @utils.custom_perms(kick_members=True)
async def usernotify(self, ctx, on_off: str): async def usernotify(self, ctx, on_off: str):
"""This command can be used to set whether or not you want user notificaitons to show """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 # 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 # 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 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} r_filter = {'server_id': ctx.message.guild.id}
entry = {'server_id': ctx.message.server.id, entry = {'server_id': ctx.message.guild.id,
'channel_id': on_off} 'channel_id': on_off}
if not await utils.add_content('user_notifications', entry, r_filter): if not await utils.add_content('user_notifications', entry, r_filter):
await utils.update_content('user_notifications', entry, r_filter) await utils.update_content('user_notifications', entry, r_filter)
fmt = "notify" if on_off else "not notify" 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): async def nsfw(self, ctx):
"""Handles adding or removing a channel as a nsfw channel""" """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 # 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: pass
await self.bot.say('Invalid subcommand passed: {0.subcommand_passed}'.format(ctx))
@nsfw.command(name="add", pass_context=True) @nsfw.command(name="add")
@utils.custom_perms(kick_members=True) @utils.custom_perms(kick_members=True)
async def nsfw_add(self, ctx): async def nsfw_add(self, ctx):
"""Registers this channel as a 'nsfw' channel """Registers this channel as a 'nsfw' channel
@ -172,11 +151,11 @@ class Mod:
RESULT: ;)""" RESULT: ;)"""
r_filter = {'channel_id': ctx.message.channel.id} r_filter = {'channel_id': ctx.message.channel.id}
if await utils.add_content('nsfw_channels', r_filter, r_filter): 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: 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) @utils.custom_perms(kick_members=True)
async def nsfw_remove(self, ctx): async def nsfw_remove(self, ctx):
"""Removes this channel as a 'nsfw' channel """Removes this channel as a 'nsfw' channel
@ -185,11 +164,11 @@ class Mod:
RESULT: ;(""" RESULT: ;("""
r_filter = {'channel_id': ctx.message.channel.id} r_filter = {'channel_id': ctx.message.channel.id}
if await utils.remove_content('nsfw_channels', r_filter): 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: 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) @utils.custom_perms(kick_members=True)
async def say(self, ctx, *, msg: str): async def say(self, ctx, *, msg: str):
"""Tells the bot to repeat what you say """Tells the bot to repeat what you say
@ -197,13 +176,13 @@ class Mod:
EXAMPLE: !say I really like orange juice EXAMPLE: !say I really like orange juice
RESULT: I really like orange juice""" RESULT: I really like orange juice"""
fmt = "\u200B{}".format(msg) fmt = "\u200B{}".format(msg)
await self.bot.say(fmt) await ctx.send(fmt)
try: try:
await self.bot.delete_message(ctx.message) await ctx.message.delete()
except: except:
pass 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) @utils.custom_perms(send_messages=True)
async def perms(self, ctx, *, command: str = None): async def perms(self, ctx, *, command: str = None):
"""This command can be used to print the current allowed permissions on a specific command """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 EXAMPLE: !perms help RESULT: Hopefully a result saying you just need send_messages permissions; otherwise lol
this server's admin doesn't like me """ this server's admin doesn't like me """
if command is None: 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))) "Valid permissions are: ```\n{}```".format("\n".join("{}".format(i) for i in valid_perms)))
return 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) server_perms = await utils.get_content('custom_permissions', r_filter)
try: try:
server_perms = server_perms[0] server_perms = server_perms[0]
except TypeError: except TypeError:
server_perms = {} server_perms = {}
cmd = self.find_command(command) cmd = self.bot.get_command(command)
if cmd is None: if cmd is None:
await self.bot.say("That is not a valid command!") await ctx.send("That is not a valid command!")
return return
perms_value = server_perms.get(cmd.qualified_name) 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) # Able to manage the server (for the utils on perm commands)
for func in cmd.utils: for func in cmd.utils:
if "is_owner" in func.__qualname__: 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 return
await self.bot.say( await ctx.send(
"You are required to have `manage_server` permissions to run `{}`".format(cmd.qualified_name)) "You are required to have `manage_server` permissions to run `{}`".format(cmd.qualified_name))
return return
# Perms will be an attribute if custom_perms is found no matter what, so no need to check this # 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) 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)) "You are required to have `{}` permissions to run `{}`".format(perms, cmd.qualified_name))
else: else:
# Permissions are saved as bit values, so create an object based on that value # 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 # There's no need to check for errors here, as we ensure a permission is valid when adding it
permissions = discord.Permissions(perms_value) permissions = discord.Permissions(perms_value)
needed_perm = [perm[0] for perm in permissions if perm[1]][0] 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)) "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) @commands.has_permissions(manage_server=True)
async def add_perms(self, ctx, *msg: str): async def add_perms(self, ctx, *msg: str):
"""Sets up custom permissions on the provided command """Sets up custom permissions on the provided command
@ -274,7 +253,7 @@ class Mod:
try: try:
permissions = msg[len(msg) - 1] permissions = msg[len(msg) - 1]
except IndexError: 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 <command> <permission>`") "`perms add <command> <permission>`")
return return
@ -288,15 +267,15 @@ class Mod:
try: try:
setattr(perm_obj, permissions, True) setattr(perm_obj, permissions, True)
except AttributeError: 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))) .format(permissions, "\n".join(valid_perms)))
return return
perm_value = perm_obj.value perm_value = perm_obj.value
cmd = self.find_command(command) cmd = self.bot.get_command(command)
if cmd is None: 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....") "That command does not exist! You can't have custom permissions on a non-existant command....")
return return
@ -305,12 +284,12 @@ class Mod:
# Which means I do not want to check custom permissions at all # 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 # Currently the second case is only on adding and removing permissions, to avoid abuse on these
for check in cmd.checks: for check in cmd.checks:
if "is_owner" == check.__name__ or re.search("has_permissions", str(check)) is not None: if "is_owner" == check.__name__ or "has_permissions" not in str(check):
await self.bot.say("This command cannot have custom permissions setup!") await ctx.send("This command cannot have custom permissions setup!")
return return
r_filter = {'server_id': ctx.message.server.id} r_filter = {'server_id': ctx.message.guild.id}
entry = {'server_id': ctx.message.server.id, entry = {'server_id': ctx.message.guild.id,
cmd.qualified_name: perm_value} cmd.qualified_name: perm_value}
# In all other cases, I've used add_content before update_content # 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 # Same case as prefixes, for now, trigger a manual update
self.bot.loop.create_task(utils.cache['custom_permissions'].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)) "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) @commands.has_permissions(manage_server=True)
async def remove_perms(self, ctx, *, command: str): async def remove_perms(self, ctx, *, command: str):
"""Removes the custom permissions setup on the command specified """Removes the custom permissions setup on the command specified
@ -333,32 +312,32 @@ class Mod:
EXAMPLE: !perms remove play EXAMPLE: !perms remove play
RESULT: Freedom!""" RESULT: Freedom!"""
cmd = self.find_command(command) cmd = self.bot.get_command(command)
if cmd is None: 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....") "That command does not exist! You can't have custom permissions on a non-existant command....")
return return
r_filter = {'server_id': ctx.message.server.id} r_filter = {'server_id': ctx.message.server.id}
await utils.replace_content('custom_permissions', r.row.without(cmd.qualified_name), r_filter) 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 # Same case as prefixes, for now, trigger a manual update
self.bot.loop.create_task(utils.cache['custom_permissions'].update()) self.bot.loop.create_task(utils.cache['custom_permissions'].update())
@commands.command(pass_context=True, no_pm=True) @commands.command(no_pm=True)
@utils.custom_perms(manage_server=True) @utils.custom_perms(manage_guild=True)
async def prefix(self, ctx, *, prefix: str): async def prefix(self, ctx, *, prefix: str):
"""This command can be used to set a custom prefix per server """This command can be used to set a custom prefix per server
EXAMPLE: !prefix new_prefix EXAMPLE: !prefix new_prefix
RESULT: You probably screwing it up and not realizing you now need to do new_prefixprefix""" 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": if prefix.lower().strip() == "none":
prefix = None prefix = None
entry = {'server_id': ctx.message.server.id, entry = {'server_id': ctx.message.guild.id,
'prefix': prefix} 'prefix': prefix}
if not await utils.add_content('prefixes', entry, r_filter): if not await utils.add_content('prefixes', entry, r_filter):
@ -369,9 +348,9 @@ class Mod:
else: else:
fmt = "I have just updated the prefix for this server; you now need to call commands with `{0}`. " \ 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) "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) @utils.custom_perms(manage_messages=True)
async def purge(self, ctx, limit: int = 100): async def purge(self, ctx, limit: int = 100):
"""This command is used to a purge a number of messages from the channel """This command is used to a purge a number of messages from the channel
@ -379,15 +358,15 @@ class Mod:
EXAMPLE: !purge 50 EXAMPLE: !purge 50
RESULT: -50 messages in this channel""" RESULT: -50 messages in this channel"""
if not ctx.message.channel.permissions_for(ctx.message.server.me).manage_messages: 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 return
try: try:
await self.bot.purge_from(ctx.message.channel, limit=limit) await ctx.message.channel.purge(limit=limit)
except discord.HTTPException: except discord.HTTPException:
await self.bot.send_message(ctx.message.channel, "Detected messages that are too far back for me to delete;" \ 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.") " 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) @utils.custom_perms(manage_messages=True)
async def prune(self, ctx, limit: int = 100): async def prune(self, ctx, limit: int = 100):
"""This command can be used to prune messages from certain members """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 # If no members are provided, assume we're trying to prune our own messages
members = ctx.message.mentions members = ctx.message.mentions
if len(members) == 0: 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 # 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 # 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: 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 return
# Since logs_from will give us any message, not just the user's we need # 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. # We'll increment count, and stop deleting messages if we hit the limit.
count = 0 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: if msg.author in members:
try: try:
await self.bot.delete_message(msg) await msg.delete()
count += 1 count += 1
except discord.NotFound: except discord.NotFound:
pass pass
if count >= limit: if count >= limit:
break break
msg = await self.bot.say("{} messages succesfully deleted".format(count)) msg = await ctx.send("{} messages succesfully deleted".format(count))
await asyncio.sleep(60) await asyncio.sleep(5)
try: try:
await self.bot.delete_message(msg) await msg.delete()
except discord.NotFound: except discord.NotFound:
pass 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) @utils.custom_perms(send_messages=True)
async def rules(self, ctx, rule: int = None): async def rules(self, ctx, rule: int = None):
"""This command can be used to view the current rules on the server """This command can be used to view the current rules on the server
EXAMPLE: !rules 5 EXAMPLE: !rules 5
RESULT: Rule 5 is printed""" 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) rules = await utils.get_content('rules', r_filter)
try: try:
rules = rules[0]['rules'] rules = rules[0]['rules']
except TypeError: 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 return
if len(rules) == 0: 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 return
if rule is None: if rule is None:
@ -453,16 +432,16 @@ class Mod:
pages.title = "Rules for {}".format(ctx.message.server.name) pages.title = "Rules for {}".format(ctx.message.server.name)
await pages.paginate() await pages.paginate()
except utils.CannotPaginate as e: except utils.CannotPaginate as e:
await self.bot.say(str(e)) await ctx.send(str(e))
else: else:
try: try:
fmt = rules[rule - 1] fmt = rules[rule - 1]
except IndexError: except IndexError:
await self.bot.say("That rules does not exist.") await ctx.send("That rules does not exist.")
return 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) @utils.custom_perms(manage_server=True)
async def rules_add(self, ctx, *, rule: str): async def rules_add(self, ctx, *, rule: str):
"""Adds a rule to this server's rules """Adds a rule to this server's rules
@ -476,9 +455,9 @@ class Mod:
if not await utils.update_content('rules', update, r_filter): if not await utils.update_content('rules', update, r_filter):
await utils.add_content('rules', entry, 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) @utils.custom_perms(manage_server=True)
async def rules_delete(self, ctx, rule: int): async def rules_delete(self, ctx, rule: int):
"""Removes one of the rules from the list of this server's rules """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} r_filter = {'server_id': ctx.message.server.id}
update = {'rules': r.row['rules'].delete_at(rule - 1)} update = {'rules': r.row['rules'].delete_at(rule - 1)}
if not await utils.update_content('rules', update, r_filter): 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: 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): def setup(bot):