import asyncio import discord import re import os import random import string import json import time import html import codecs from random import shuffle from discord.ext import commands class CardsAgainstHumanity: # Init with the bot reference, and a reference to the deck file def __init__(self, bot, file = None): self.bot = bot self.games = [] self.maxBots = 5 # Max number of bots that can be added to a game - don't count toward max players self.maxPlayers = 10 # Max players for ranjom joins self.maxDeadTime = 3600 # Allow an hour of dead time before killing a game self.checkTime = 300 # 5 minutes between dead time checks self.winAfter = 10 # 10 wins for the game self.botWaitMin = 5 # Minimum number of seconds before the bot makes a decision (default 5) self.botWaitMax = 30 # Max number of seconds before a bot makes a decision (default 30) self.userTimeout = 300 # 5 minutes to timeout self.utCheck = 30 # Check timeout every 30 seconds self.utWarn = 60 # Warn the user if they have 60 seconds or less before being kicked self.charset = "1234567890" self.botName = 'Rando Cardrissian' self.minMembers = 3 self.loopsleep = 0.05 if file == None: file = "data/cah/deck.json" # Let's load our deck file # Can be found at http://www.crhallberg.com/cah/json if os.path.exists(file): f = open(file,'r') filedata = f.read() f.close() self.deck = json.loads(filedata) else: # File doesn't exist - create a placeholder self.deck = {} self.bot.loop.create_task(self.checkDead()) self.bot.loop.create_task(self.checkUserTimeout()) def cleanJson(self, json): json = html.unescape(json) # Clean out html formatting json = json.replace('_','[blank]') json = json.replace('
','\n') json = json.replace('
','\n') json = json.replace('', '*') json = json.replace('', '*') return json def displayname(self, member : discord.Member): # A helper function to return the member's display name nick = name = None try: nick = member.nick except AttributeError: pass try: name = member.name except AttributeError: pass if nick: return nick if name: return name return None def memberforname(self, name, server): # Check nick first - then name for member in server.members: if member.nick: if member.nick.lower() == name.lower(): return member for member in server.members: if member.name.lower() == name.lower(): return member # No member yet - try ID memID = ''.join(list(filter(str.isdigit, name))) newMem = memberForID(memID, server) if newMem: return newMem return None def getreadabletimebetween(first, last): # A helper function to make a readable string between two times timeBetween = int(last-first) weeks = int(timeBetween/604800) days = int((timeBetween-(weeks*604800))/86400) hours = int((timeBetween-(days*86400 + weeks*604800))/3600) minutes = int((timeBetween-(hours*3600 + days*86400 + weeks*604800))/60) seconds = int(timeBetween-(minutes*60 + hours*3600 + days*86400 + weeks*604800)) msg = "" if weeks > 0: if weeks == 1: msg = '{}{} week, '.format(msg, str(weeks)) else: msg = '{}{} weeks, '.format(msg, str(weeks)) if days > 0: if days == 1: msg = '{}{} day, '.format(msg, str(days)) else: msg = '{}{} days, '.format(msg, str(days)) if hours > 0: if hours == 1: msg = '{}{} hour, '.format(msg, str(hours)) else: msg = '{}{} hours, '.format(msg, str(hours)) if minutes > 0: if minutes == 1: msg = '{}{} minute, '.format(msg, str(minutes)) else: msg = '{}{} minutes, '.format(msg, str(minutes)) if seconds > 0: if seconds == 1: msg = '{}{} second, '.format(msg, str(seconds)) else: msg = '{}{} seconds, '.format(msg, str(seconds)) if not msg: return "0 seconds" else: return msg[:-2] async def checkUserTimeout(self): while not self.bot.is_closed: # Wait first - then check await asyncio.sleep(self.utCheck) for game in self.games: if not game['Timeout']: continue if len(game['Members']) >= self.minMembers: # Game is started for member in game['Members']: if member['IsBot']: continue if game['Judging']: if not member == game['Members'][game['Judge']]: # Not the judge - don't hold against the user member['Time'] = int(time.time()) continue else: # Not judging if member == game['Members'][game['Judge']]: # The judge - don't hold that against them member['Time'] = int(time.time()) continue currentTime = int(time.time()) userTime = member['Time'] downTime = currentTime - userTime # Check if downTime results in a kick if downTime >= self.userTimeout: # You gettin kicked, son. await self.removeMember(member['User']) self.checkGame(game) continue # Check if downTime is in warning time if downTime >= (self.userTimeout - self.utWarn): # Check if we're at warning phase if self.userTimeout - downTime >= (self.utWarn - self.utCheck): kickTime = self.userTimeout - downTime if kickTime % self.utCheck: # Kick time isn't exact time - round out to the next loop kickTime = kickTime-(kickTime % self.utCheck)+self.utCheck # Warning time! timeString = self.getreadabletimebetween(0, kickTime) msg = '**WARNING** - You will be kicked from the game if you do not make a move in *{}!*'.format(timeString) await self.bot.send_message(member['User'], msg) else: for member in game['Members']: # Reset timer member['Time'] = int(time.time()) async def checkDead(self): while not self.bot.is_closed: # Wait first - then check await asyncio.sleep(self.checkTime) for game in self.games: gameTime = game['Time'] currentTime = int(time.time()) timeRemain = currentTime - gameTime if timeRemain > self.maxDeadTime: # Game is dead - quit it and alert members for member in game['Members']: if member['IsBot']: # Clear pending tasks and set to None if not member['Task'] == None: task = member['Task'] if not task.done(): task.cancel() member['Task'] = None continue msg = "Game id: *{}* has been closed due to inactivity.".format(game['ID']) await self.bot.send_message(member['User'], msg) # Set running to false game['Running'] = False self.games.remove(game) async def checkPM(self, message): # Checks if we're talking in PM, and if not - outputs an error if message.channel.is_private: # PM return True else: # Not in PM await self.bot.send_message(message.channel, 'Cards Against Humanity commands must be run in PM.') return False def randomID(self, length = 8): # Create a random id that doesn't already exist while True: # Repeat until found newID = ''.join(random.choice(self.charset) for i in range(length)) exists = False for game in self.games: if game['ID'] == newID: exists = True break if not exists: break return newID def randomBotID(self, game, length = 4): # Returns a random id for a bot that doesn't already exist while True: # Repeat until found newID = ''.join(random.choice(self.charset) for i in range(length)) exists = False for member in game['Members']: if member['ID'] == newID: exists = True break if not exists: break return newID def userGame(self, user): # Returns the game the user is currently in if not type(user) is str: # Assume it's a discord.Member/User user = user.id for game in self.games: for member in game['Members']: if member['ID'] == user: # Found our user return game return None def gameForID(self, id): # Returns the game with the passed id for game in self.games: if game['ID'] == id: return game return None async def removeMember(self, user, game = None): if not type(user) is str: # Assume it's a discord.Member/User user = user.id outcome = False removed = None if not game: game = self.userGame(user) if game: for member in game['Members']: if member['ID'] == user: removed = member outcome = True judgeChanged = False # Reset judging flag to retrigger actions game['Judging'] = False # Get current Judge - only if game has started if len(game['Members']) >= self.minMembers: judge = game['Members'][game['Judge']] game['Members'].remove(member) # Check if we're removing the current judge if judge == member: # Judge will change judgeChanged = True # Find out if our member was the last in line if game['Judge'] >= len(game['Members']): game['Judge'] = 0 # Reset judge var judge = game['Members'][game['Judge']] else: # Judge didn't change - so let's reset judge index index = game['Members'].index(judge) game['Judge'] = index else: judge = None # Just remove the member game['Members'].remove(member) if member['Creator']: # We're losing the game creator - pick a new one for newCreator in game['Members']: if not newCreator['IsBot']: newCreator['Creator'] = True await self.bot.send_message(newCreator['User'], 'The creator of this game left. **YOU** are now the creator.') break # Remove submissions for sub in game['Submitted']: # Remove deleted member and new judge's submissions if sub['By'] == member or sub['By'] == judge: # Found it! game['Submitted'].remove(sub) break if member['IsBot']: if not member['Task'] == None: task = member['Task'] if not task.done(): task.cancel() member['Task'] = None else: msg = '**You were removed from game id:** ***{}.***'.format(game['ID']) await self.bot.send_message(member['User'], msg) # Removed, no need to finish the loop break if not outcome: return outcome # We removed someone - let's tell the world for member in game['Members']: if member['IsBot']: continue if removed['IsBot']: msg = '***{} ({})*** **left the game - reorganizing...**'.format(self.botName, removed['ID']) else: msg = '***{}*** **left the game - reorganizing...**'.format(self.displayname(removed['User'])) # Check if the judge changed if judgeChanged: # Judge changed newJudge = game['Members'][game['Judge']] if newJudge['IsBot']: msg += '\n\n***{} ({})*** **is now judging!**'.format(self.botName, newJudge['ID']) # Schedule judging task else: if newJudge == member: msg += '\n\n***YOU*** **are now judging!**' else: msg += '\n\n***{}*** **is now judging!**'.format(self.displayname(newJudge['User'])) await self.bot.send_message(member['User'], msg) return game def checkGame(self, game): for member in game['Members']: if not member['IsBot']: return True # If we got here - only bots, or empty game # Kill all bots' loops for member in game['Members']: if member['IsBot']: # Clear pending tasks and set to None if not member['Task'] == None: task = member['Task'] if not task.done(): task.cancel() member['Task'] = None # Set running to false game['Running'] = False self.games.remove(game) return False async def typing(self, game, typeTime = 5): # Allows us to show the bot typing waitTime = random.randint(self.botWaitMin, self.botWaitMax) preType = waitTime-typeTime if preType > 0: await asyncio.sleep(preType) for member in game['Members']: if member['IsBot']: continue # Show that we're typing await self.bot.send_typing(member['User']) await asyncio.sleep(self.loopsleep) await asyncio.sleep(typeTime) else: for member in game['Members']: if member['IsBot']: continue # Show that we're typing await self.bot.send_typing(member['User']) await asyncio.sleep(self.loopsleep) await asyncio.sleep(waitTime) async def botPick(self, ctx, bot, game): # Has the bot pick their card blackNum = game['BlackCard']['Pick'] if blackNum == 1: cardSpeak = 'card' else: cardSpeak = 'cards' i = 0 cards = [] while i < blackNum: randCard = random.randint(0, len(bot['Hand'])-1) cards.append(bot['Hand'].pop(randCard)['Text']) i += 1 await self.typing(game) # Make sure we haven't laid any cards if bot['Laid'] == False and game['Judging'] == False: newSubmission = { 'By': bot, 'Cards': cards } game['Submitted'].append(newSubmission) # Shuffle cards shuffle(game['Submitted']) bot['Laid'] = True game['Time'] = currentTime = int(time.time()) await self.checkSubmissions(ctx, game, bot) async def botPickWin(self, ctx, game): totalUsers = len(game['Members'])-1 submitted = len(game['Submitted']) if submitted >= totalUsers: # Judge is a bot - and all cards are in! await self.typing(game) # Pick a winner winner = random.randint(0, totalUsers-1) await self.winningCard(ctx, game, winner) async def checkSubmissions(self, ctx, game, user = None): totalUsers = len(game['Members'])-1 submitted = len(game['Submitted']) for member in game['Members']: msg = '' # Is the game running? if len(game['Members']) < self.minMembers: if member['IsBot']: # Clear pending tasks and set to None if not member['Task'] == None: task = member['Task'] if not task.done(): # Task isn't finished - we're on a new hand, cancel it task.cancel() member['Task'] = None continue # not enough members - send the embed stat_embed = discord.Embed(color=discord.Color.red()) stat_embed.set_author(name='Not enough players to continue! ({}/{})'.format(len(game['Members']), self.minMembers)) stat_embed.set_footer(text='Have other users join with: {}joincah {}'.format(ctx.prefix, game['ID'])) await self.bot.send_message(member['User'], embed=stat_embed) continue if member['IsBot'] == True: continue # Check if we have a user if user: blackNum = game['BlackCard']['Pick'] if blackNum == 1: card = 'card' else: card = 'cards' if user['IsBot']: msg = '*{} ({})* submitted their {}! '.format(self.botName, user['ID'], card) else: if not member == user: # Don't say this to the submitting user msg = '*{}* submitted their {}! '.format(self.displayname(user['User']), card) if submitted < totalUsers: msg += '{}/{} cards submitted...'.format(submitted, totalUsers) if len(msg): # We have something to say await self.bot.send_message(member['User'], msg) await asyncio.sleep(self.loopsleep) async def checkCards(self, ctx, game): while not self.bot.is_closed: if not game['Running']: break # wait for 1 second await asyncio.sleep(1) # Check for all cards if len(game['Members']) < self.minMembers: # Not enough members continue # Enough members - let's check if we're judging if game['Judging']: continue # Enough members, and not judging - let's check cards totalUsers = len(game['Members'])-1 submitted = len(game['Submitted']) if submitted >= totalUsers: game['Judging'] = True # We have enough cards for member in game['Members']: if member['IsBot']: continue msg = 'All cards have been submitted!' # if await self.bot.send_message(member['User'], msg) await self.showOptions(ctx, member['User']) await asyncio.sleep(self.loopsleep) # Check if a bot is the judge judge = game['Members'][game['Judge']] if not judge['IsBot']: continue # task = self.bot.loop.create_task(self.botPickWin(ctx, game)) task = asyncio.ensure_future(self.botPickWin(ctx, game)) judge['Task'] = task async def winningCard(self, ctx, game, card): # Let's pick our card and alert everyone winner = game['Submitted'][card] if winner['By']['IsBot']: winnerName = '{} ({})'.format(self.botName, winner['By']['ID']) winner['By']['Points'] += 1 winner['By']['Won'].append(game['BlackCard']['Text']) else: winnerName = self.displayname(winner['By']['User']) for member in game['Members']: if member['IsBot']: continue stat_embed = discord.Embed(color=discord.Color.gold()) stat_embed.set_footer(text='Cards Against Humanity - id: {}'.format(game['ID'])) index = game['Members'].index(member) if index == game['Judge']: stat_embed.set_author(name='You picked {}\'s card!'.format(winnerName)) elif member == winner['By']: stat_embed.set_author(name='YOU WON!!') member['Points'] += 1 member['Won'].append(game['BlackCard']['Text']) else: stat_embed.set_author(name='{} won!'.format(winnerName)) if len(winner['Cards']) == 1: msg = 'The **Winning** card was:\n\n{}'.format('{}'.format(' - '.join(winner['Cards']))) else: msg = 'The **Winning** cards were:\n\n{}'.format('{}'.format(' - '.join(winner['Cards']))) await self.bot.send_message(member['User'], embed=stat_embed) await self.bot.send_message(member['User'], msg) await asyncio.sleep(self.loopsleep) # await self.nextPlay(ctx, game) # Start the game loop event = game['NextHand'] self.bot.loop.call_soon_threadsafe(event.set) game['Time'] = currentTime = int(time.time()) async def gameCheckLoop(self, ctx, game): task = game['NextHand'] while True: if not game['Running']: break # Clear the pending task task.clear() # Queue up the next hand await self.nextPlay(ctx, game) # Wait until our next clear await task.wait() async def messagePlayers(self, ctx, message, game, judge = False): # Messages all the users on in a game for member in game['Members']: if member['IsBot']: continue # Not bots if member is game['Members'][game['Judge']]: # Is the judge if judge: await self.bot.send_message(member['User'], message) else: # Not the judge await self.bot.send_message(member['User'], message) ################################################ async def showPlay(self, ctx, user): # Creates an embed and displays the current game stats stat_embed = discord.Embed(color=discord.Color.blue()) game = self.userGame(user) if not game: return # Get the judge's name if game['Members'][game['Judge']]['User'] == user: judge = '**YOU** are' else: if game['Members'][game['Judge']]['IsBot']: # Bot judge = '*{} ({})* is'.format(self.botName, game['Members'][game['Judge']]['ID']) else: judge = '*{}* is'.format(self.displayname(game['Members'][game['Judge']]['User'])) # Get the Black Card try: blackCard = game['BlackCard']['Text'] blackNum = game['BlackCard']['Pick'] except Exception: blackCard = 'None.' blackNum = 0 msg = '{} the judge.\n\n'.format(judge) msg += '__Black Card:__\n\n**{}**\n\n'.format(blackCard) totalUsers = len(game['Members'])-1 submitted = len(game['Submitted']) if len(game['Members']) >= self.minMembers: if submitted < totalUsers: msg += '{}/{} cards submitted...'.format(submitted, totalUsers) else: msg += 'All cards have been submitted!' await self.showOptions(ctx, user) return if not judge == '**YOU** are': # Judge doesn't need to lay a card if blackNum == 1: # Singular msg += '\n\nLay a card with `{}lay [card number]`'.format(ctx.prefix) elif blackNum > 1: # Plural msg += '\n\nLay **{} cards** with `{}lay [card numbers separated by commas (1,2,3)]`'.format(blackNum, ctx.prefix) stat_embed.set_author(name='Current Play') stat_embed.set_footer(text='Cards Against Humanity - id: {}'.format(game['ID'])) await self.bot.send_message(user, embed=stat_embed) await self.bot.send_message(user, msg) async def showHand(self, ctx, user): # Shows the user's hand in an embed stat_embed = discord.Embed(color=discord.Color.green()) game = self.userGame(user) if not game: return i = 0 msg = '' points = '? points' for member in game['Members']: if member['ID'] == user.id: # Got our user if member['Points']==1: points = '1 point' else: points = '{} points'.format(member['Points']) for card in member['Hand']: i += 1 msg += '{}. {}\n'.format(i, card['Text']) try: blackCard = '**{}**'.format(game['BlackCard']['Text']) except Exception: blackCard = '**None.**' stat_embed.set_author(name='Your Hand - {}'.format(points)) stat_embed.set_footer(text='Cards Against Humanity - id: {}'.format(game['ID'])) await self.bot.send_message(user, embed=stat_embed) await self.bot.send_message(user, msg) async def showOptions(self, ctx, user): # Shows the judgement options stat_embed = discord.Embed(color=discord.Color.orange()) game = self.userGame(user) if not game: return # Add title stat_embed.set_author(name='JUDGEMENT TIME!!') stat_embed.set_footer(text='Cards Against Humanity - id: {}'.format(game['ID'])) await self.bot.send_message(user, embed=stat_embed) if game['Members'][game['Judge']]['User'] == user: judge = '**YOU** are' else: if game['Members'][game['Judge']]['IsBot']: # Bot judge = '*{} ({})* is'.format(self.botName, game['Members'][game['Judge']]['ID']) else: judge = '*{}* is'.format(self.displayname(game['Members'][game['Judge']]['User'])) blackCard = game['BlackCard']['Text'] msg = '{} judging.\n\n'.format(judge) msg += '__Black Card:__\n\n**{}**\n\n'.format(blackCard) msg += '__Submitted White Cards:__\n\n' i = 0 for sub in game['Submitted']: i+=1 msg += '{}. {}\n'.format(i, ' - '.join(sub['Cards'])) if judge == '**YOU** are': msg += '\nPick a winner with `{}pick [submission number]`.'.format(ctx.prefix) await self.bot.send_message(user, msg) async def drawCard(self, game): # Draws a random unused card and shuffles the deck if needed totalDiscard = len(game['Discard']) for member in game['Members']: totalDiscard += len(member['Hand']) if totalDiscard >= len(self.deck['whiteCards']): # Tell everyone the cards were shuffled for member in game['Members']: if member['IsBot']: continue user = member['User'] await self.bot.send_message(user, 'Shuffling white cards...') # Shuffle the cards self.shuffle(game) while True: # Random grab a unique card index = random.randint(0, len(self.deck['whiteCards'])-1) if not index in game['Discard']: game['Discard'].append(index) text = self.deck['whiteCards'][index] text = self.cleanJson(text) card = { 'Index': index, 'Text': text } return card def shuffle(self, game): # Adds discards back into the deck game['Discard'] = [] for member in game['Members']: for card in member['Hand']: game['Discard'].append(card['Index']) async def drawCards(self, user, cards = 10): if not type(user) is str: # Assume it's a discord.Member/User user = user.id # fills the user's hand up to number of cards game = self.userGame(user) for member in game['Members']: if member['ID'] == user: # Found our user - let's draw cards i = len(member['Hand']) while i < cards: # Draw unique cards until we fill our hand newCard = await self.drawCard(game) member['Hand'].append(newCard) i += 1 async def drawBCard(self, game): # Draws a random black card totalDiscard = len(game['BDiscard']) if totalDiscard >= len(self.deck['blackCards']): # Tell everyone the cards were shuffled for member in game['Members']: if member['IsBot']: continue user = member['User'] await self.bot.send_message(user, 'Shuffling black cards...') # Shuffle the cards game['BDiscard'] = [] while True: # Random grab a unique card index = random.randint(0, len(self.deck['blackCards'])-1) if not index in game['BDiscard']: game['BDiscard'].append(index) text = self.deck['blackCards'][index]['text'] text = self.cleanJson(text) game['BlackCard'] = { 'Text': text, 'Pick': self.deck['blackCards'][index]['pick'] } return game['BlackCard'] async def nextPlay(self, ctx, game): # Advances the game if len(game['Members']) < self.minMembers: stat_embed = discord.Embed(color=discord.Color.red()) stat_embed.set_author(name='Not enough players to continue! ({}/{})'.format(len(game['Members']), self.minMembers)) stat_embed.set_footer(text='Have other users join with: {}joincah {}'.format(ctx.prefix, game['ID'])) for member in game['Members']: if member['IsBot']: continue await self.bot.send_message(member['User'], embed=stat_embed) return # Find if we have a winner winner = False stat_embed = discord.Embed(color=discord.Color.lighter_grey()) for member in game['Members']: if member['IsBot']: # Clear pending tasks and set to None if not member['Task'] == None: task = member['Task'] if not task.done(): # Task isn't finished - we're on a new hand, cancel it task.cancel() member['Task'] = None if member['Points'] >= self.winAfter: # We have a winner! winner = True if member['IsBot']: stat_embed.set_author(name='{} ({}) is the WINNER!!'.format(self.botName, member['ID'])) else: stat_embed.set_author(name='{} is the WINNER!!'.format(self.displayname(member['User']))) stat_embed.set_footer(text='Congratulations!'.format(game['ID'])) break if winner: for member in game['Members']: if not member['IsBot']: await self.bot.send_message(member['User'], embed=stat_embed) # Reset all users member['Hand'] = [] member['Points'] = 0 member['Won'] = [] member['Laid'] = False member['Refreshed'] = False await asyncio.sleep(self.loopsleep) game['Judging'] = False # Clear submitted cards game['Submitted'] = [] # We have enough members if game['Judge'] == -1: # First game - randomize judge game['Judge'] = random.randint(0, len(game['Members'])-1) else: game['Judge']+=1 # Reset the judge if out of bounds if game['Judge'] >= len(game['Members']): game['Judge'] = 0 # Draw the next black card bCard = await self.drawBCard(game) # Draw cards for member in game['Members']: member['Laid'] = False await self.drawCards(member['ID']) # Show hands for member in game['Members']: if member['IsBot']: continue await self.showPlay(ctx, member['User']) index = game['Members'].index(member) if not index == game['Judge']: await self.showHand(ctx, member['User']) await asyncio.sleep(self.loopsleep) # Have the bots lay their cards for member in game['Members']: if not member['IsBot']: continue if member['ID'] == game['Members'][game['Judge']]['ID']: continue # Not a human player, and not the judge # task = self.bot.loop.create_task(self.botPick(ctx, member, game))\ task = asyncio.ensure_future(self.botPick(ctx, member, game)) member['Task'] = task # await self.botPick(ctx, member, game) @commands.command(pass_context=True) async def game(self, ctx, *, message = None): """Displays the game's current status.""" if not await self.checkPM(ctx.message): return userGame = self.userGame(ctx.message.author) if not userGame: msg = "You're not in a game - you can create one with `{}newcah` or join one with `{}joincah`.".format(ctx.prefix, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return await self.showPlay(ctx, ctx.message.author) @commands.command(pass_context=True) async def chat(self, ctx, *, message = None): """Broadcasts a message to the other players in your game.""" if not await self.checkPM(ctx.message): return userGame = self.userGame(ctx.message.author) if not userGame: msg = "You're not in a game - you can create one with `{}newcah` or join one with `{}joincah`.".format(ctx.prefix, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return userGame['Time'] = int(time.time()) if message == None: msg = "Ooookay, you say *nothing...*" await self.bot.send_message(ctx.message.author, msg) return msg = '*{}* says: {}'.format(ctx.message.author.name, message) for member in userGame['Members']: if member['IsBot']: continue # Tell them all!! if not member['User'] == ctx.message.author: # Don't tell yourself await self.bot.send_message(member['User'], msg) else: # Update member's time member['Time'] = int(time.time()) await self.bot.send_message(ctx.message.author, 'Message sent!') @commands.command(pass_context=True) async def lay(self, ctx, *, card = None): """Lays a card or cards from your hand. If multiple cards are needed, separate them by a comma (1,2,3).""" if not await self.checkPM(ctx.message): return userGame = self.userGame(ctx.message.author) if not userGame: msg = "You're not in a game - you can create one with `{}newcah` or join one with `{}joincah`.".format(ctx.prefix, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return userGame['Time'] = int(time.time()) for member in userGame['Members']: if member['User'] == ctx.message.author: member['Time'] = int(time.time()) user = member index = userGame['Members'].index(member) if index == userGame['Judge']: await self.bot.send_message(ctx.message.author, "You're the judge. You don't get to lay cards this round.") return for submit in userGame['Submitted']: if submit['By']['User'] == ctx.message.author: await self.bot.send_message(ctx.message.author, "You already made your submission this round.") return if card == None: await self.bot.send_message(ctx.message.author, 'You need you input *something.*') return card = card.strip() card = card.replace(" ", "") # Not the judge if len(userGame['Members']) < self.minMembers: stat_embed = discord.Embed(color=discord.Color.red()) stat_embed.set_author(name='Not enough players to continue! ({}/{})'.format(len(userGame['Members']), self.minMembers)) stat_embed.set_footer(text='Have other users join with: {}joincah {}'.format(ctx.prefix, userGame['ID'])) await self.bot.send_message(ctx.message.author, embed=stat_embed) return numberCards = userGame['BlackCard']['Pick'] cards = [] if numberCards > 1: cardSpeak = "cards" try: card = card.split(',') except Exception: card = [] if not len(card) == numberCards: msg = 'You need to lay **{} cards** (no duplicates) with `{}lay [card numbers separated by commas (1,2,3)]`'.format(numberCards, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) await self.showHand(ctx, ctx.message.author) return # Got something # Check for duplicates if not len(card) == len(set(card)): msg = 'You need to lay **{} cards** (no duplicates) with `{}lay [card numbers separated by commas (1,2,3)]`'.format(numberCards, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) await self.showHand(ctx, ctx.message.author) return # Works for c in card: try: c = int(c) except Exception: msg = 'You need to lay **{} cards** (no duplicates) with `{}lay [card numbers separated by commas (1,2,3)]`'.format(numberCards, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) await self.showHand(ctx, ctx.message.author) return if c < 1 or c > len(user['Hand']): msg = 'Card numbers must be between 1 and {}.'.format(len(user['Hand'])) await self.bot.send_message(ctx.message.author, msg) await self.showHand(ctx, ctx.message.author) return cards.append(user['Hand'][c-1]['Text']) # Remove from user's hand card = sorted(card, key=lambda card:int(card), reverse=True) for c in card: user['Hand'].pop(int(c)-1) # Valid cards newSubmission = { 'By': user, 'Cards': cards } else: cardSpeak = "card" try: card = int(card) except Exception: msg = 'You need to lay a valid card with `{}lay [card number]`'.format(ctx.prefix) await self.bot.send_message(ctx.message.author, msg) await self.showHand(ctx, ctx.message.author) return if card < 1 or card > len(user['Hand']): msg = 'Card numbers must be between 1 and {}.'.format(len(user['Hand'])) await self.bot.send_message(ctx.message.author, msg) await self.showHand(ctx, ctx.message.author) return # Valid card newSubmission = { 'By': user, 'Cards': [ user['Hand'].pop(card-1)['Text'] ] } userGame['Submitted'].append(newSubmission) # Shuffle cards shuffle(userGame['Submitted']) user['Laid'] = True await self.bot.send_message(ctx.message.author, 'You submitted your {}!'.format(cardSpeak)) await self.checkSubmissions(ctx, userGame, user) @commands.command(pass_context=True) async def pick(self, ctx, *, card = None): """As the judge - pick the winning card(s).""" if not await self.checkPM(ctx.message): return # Check if the user is already in game userGame = self.userGame(ctx.message.author) if not userGame: # Not in a game msg = "You're not in a game - you can create one with `{}newcah` or join one with `{}joincah`.".format(ctx.prefix, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return userGame['Time'] = int(time.time()) isJudge = False for member in userGame['Members']: if member['User'] == ctx.message.author: member['Time'] = int(time.time()) user = member index = userGame['Members'].index(member) if index == userGame['Judge']: isJudge = True if not isJudge: msg = "You're not the judge - I guess you'll have to wait your turn.".format(ctx.prefix, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return # Am judge totalUsers = len(userGame['Members'])-1 submitted = len(userGame['Submitted']) if submitted < totalUsers: if totalUsers - submitted == 1: msg = "Still waiting on 1 card..." else: msg = "Still waiting on {} cards...".format(totalUsers-submitted) await self.bot.send_message(ctx.message.author, msg) return try: card = int(card)-1 except Exception: card = -1 if card < 0 or card >= totalUsers: msg = "Your pick must be between 1 and {}.".format(totalUsers) await self.bot.send_message(ctx.message.author, msg) return # Pick is good! await self.winningCard(ctx, userGame, card) @commands.command(pass_context=True) async def hand(self, ctx): """Shows your hand.""" if not await self.checkPM(ctx.message): return # Check if the user is already in game userGame = self.userGame(ctx.message.author) if not userGame: # Not in a game msg = "You're not in a game - you can create one with `{}newcah` or join one with `{}joincah`.".format(ctx.prefix, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return await self.showHand(ctx, ctx.message.author) userGame['Time'] = currentTime = int(time.time()) @commands.command(pass_context=True) async def newcah(self, ctx): """Starts a new Cards Against Humanity game.""" #if not await self.checkPM(ctx.message): #return # Check if the user is already in game userGame = self.userGame(ctx.message.author) if userGame: # Already in a game msg = "You're already in a game (id: *{}*)\nType `{}leavecah` to leave that game.".format(userGame['ID'], ctx.prefix) await self.bot.send_message(ctx.message.channel, msg) return # Not in a game - create a new one gameID = self.randomID() currentTime = int(time.time()) newGame = { 'ID': gameID, 'Members': [], 'Discard': [], 'BDiscard': [], 'Judge': -1, 'Time': currentTime, 'BlackCard': None, 'Submitted': [], 'NextHand': asyncio.Event(), 'Judging': False, 'Timeout': True } member = { 'ID': ctx.message.author.id, 'User': ctx.message.author, 'Points': 0, 'Won': [], 'Hand': [], 'Laid': False, 'Refreshed': False, 'IsBot': False, 'Creator': True, 'Task': None, 'Time': currentTime } newGame['Members'].append(member) newGame['Running'] = True task = self.bot.loop.create_task(self.gameCheckLoop(ctx, newGame)) task = self.bot.loop.create_task(self.checkCards(ctx, newGame)) self.games.append(newGame) # Tell the user they created a new game and list its ID await self.bot.send_message(ctx.message.channel, 'You created game id: *{}*'.format(gameID)) await self.drawCards(ctx.message.author) # await self.showHand(ctx, ctx.message.author) # await self.nextPlay(ctx, newGame) @commands.command(pass_context=True) async def leavecah(self, ctx): """Leaves the current game you're in.""" removeCheck = await self.removeMember(ctx.message.author) if not removeCheck: msg = 'You are not in a game.' await self.bot.send_message(ctx.message.channel, msg) return if self.checkGame(removeCheck): # await self.nextPlay(ctx, removeCheck) """# Start the game loop event = removeCheck['NextHand'] self.bot.loop.call_soon_threadsafe(event.set)""" # Player was removed - try to handle it calmly... await self.checkSubmissions(ctx, removeCheck) @commands.command(pass_context=True) async def joincah(self, ctx, *, id = None): """Join a Cards Against Humanity game. If no id or user is passed, joins a random game.""" #if not await self.checkPM(ctx.message): #return # Check if the user is already in game userGame = self.userGame(ctx.message.author) isCreator = False if userGame: # Already in a game msg = "You're already in a game (id: *{}*)\nType `{}leavecah` to leave that game.".format(userGame['ID'], ctx.prefix) await self.bot.send_message(ctx.message.channel, msg) return if len(self.games): if id: game = self.gameForID(id) if game == None: # That id doesn't exist - or is possibly a user # If user, has to be joined from server chat if not ctx.message.server: msg = "I couldn't find a game attached to that id. If you are trying to join a user - run the `{}joincah [user]` command in a channel on a server you share with that user.".format(ctx.prefix) await self.bot.send_message(ctx.message.channel, msg) return else: # We have a server - let's try for a user member = self.memberforname(id, ctx.message.server) if not member: # Couldn't find user! msg = "I couldn't find a game attached to that id. If you are trying to join a user - run the `{}joincah [user]` command in a channel on a server you share with that user.".format(ctx.prefix) await self.bot.send_message(ctx.message.channel, msg) return # Have a user - check if they're in a game game = self.userGame(member) if not game: # That user is NOT in a game! msg = "That user doesn't appear to be playing." await self.bot.send_message(ctx.message.channel, msg) return else: game = random.choice(self.games) else: # No games - create a new one gameID = self.randomID() currentTime = int(time.time()) game = { 'ID': gameID, 'Members': [], 'Discard': [], 'BDiscard': [], 'Judge': -1, 'Time': currentTime, 'BlackCard': None, 'Submitted': [], 'NextHand': asyncio.Event(), 'Judging': False, 'Timeout': True } game['Running'] = True task = self.bot.loop.create_task(self.gameCheckLoop(ctx, game)) task = self.bot.loop.create_task(self.checkCards(ctx, game)) self.games.append(game) # Tell the user they created a new game and list its ID await self.bot.send_message(ctx.message.channel, '**You created game id:** ***{}***'.format(gameID)) isCreator = True # Tell everyone else you joined for member in game['Members']: if member['IsBot']: continue await self.bot.send_message(member['User'], '***{}*** **joined the game!**'.format(self.displayname(ctx.message.author))) # We got a user! currentTime = int(time.time()) member = { 'ID': ctx.message.author.id, 'User': ctx.message.author, 'Points': 0, 'Won': [], 'Hand': [], 'Laid': False, 'Refreshed': False, 'IsBot': False, 'Creator': isCreator, 'Task': None, 'Time': currentTime } game['Members'].append(member) await self.drawCards(ctx.message.author) if len(game['Members'])==1: # Just created the game await self.drawCards(ctx.message.author) else: msg = "**You've joined game id:** ***{}!***\n\nThere are *{} users* in this game.".format(game['ID'], len(game['Members'])) await self.bot.send_message(ctx.message.channel, msg) # Check if adding put us at minimum members if len(game['Members']) - 1 < self.minMembers: # It was - *actually* start a game event = game['NextHand'] self.bot.loop.call_soon_threadsafe(event.set) else: # It was not - just incorporate new players await self.checkSubmissions(ctx, game) # Reset judging flag to retrigger actions game['Judging'] = False # Show the user the current card and their hand await self.showPlay(ctx, member['User']) await self.showHand(ctx, member['User']) event = game['NextHand'] game['Time'] = int(time.time()) @commands.command(pass_context=True) async def joinbot(self, ctx): """Adds a bot to the game. Can only be done by the player who created the game.""" if not await self.checkPM(ctx.message): return # Check if the user is already in game userGame = self.userGame(ctx.message.author) if not userGame: # Not in a game msg = "You're not in a game - you can create one with `{}newcah` or join one with `{}joincah`.".format(ctx.prefix, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return botCount = 0 for member in userGame['Members']: if member['IsBot']: botCount += 1 continue if member['User'] == ctx.message.author: if not member['Creator']: # You didn't make this game msg = 'Only the player that created the game can add bots.' await self.bot.send_message(ctx.message.author, msg) return member['Time'] = int(time.time()) # We are the creator - let's check the number of bots if botCount >= self.maxBots: # Too many bots! msg = 'You already have enough bots (max is {}).'.format(self.maxBots) await self.bot.send_message(ctx.message.author, msg) return # We can get another bot! botID = self.randomBotID(userGame) lobot = { 'ID': botID, 'User': None, 'Points': 0, 'Won': [], 'Hand': [], 'Laid': False, 'Refreshed': False, 'IsBot': True, 'Creator': False, 'Task': None } userGame['Members'].append(lobot) await self.drawCards(lobot['ID']) msg = '***{} ({})*** **joined the game!**'.format(self.botName, botID) for member in userGame['Members']: if member['IsBot']: continue await self.bot.send_message(member['User'], msg) # await self.nextPlay(ctx, userGame) # Check if adding put us at minimum members if len(userGame['Members']) - 1 < self.minMembers: # It was - *actually* start a game event = userGame['NextHand'] self.bot.loop.call_soon_threadsafe(event.set) else: # It was not - just incorporate new players await self.checkSubmissions(ctx, userGame) # Reset judging flag to retrigger actions userGame['Judging'] = False # Schedule stuff task = asyncio.ensure_future(self.botPick(ctx, lobot, userGame)) lobot['Task'] = task @commands.command(pass_context=True) async def joinbots(self, ctx, number = None): """Adds bots to the game. Can only be done by the player who created the game.""" if not await self.checkPM(ctx.message): return # Check if the user is already in game userGame = self.userGame(ctx.message.author) if not userGame: # Not in a game msg = "You're not in a game - you can create one with `{}newcah` or join one with `{}joincah`.".format(ctx.prefix, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return botCount = 0 for member in userGame['Members']: if member['IsBot']: botCount += 1 continue if member['User'] == ctx.message.author: if not member['Creator']: # You didn't make this game msg = 'Only the player that created the game can add bots.' await self.bot.send_message(ctx.message.author, msg) return member['Time'] = int(time.time()) if number == None: # No number specified - let's add the max number of bots number = self.maxBots - botCount try: number = int(number) except Exception: msg = 'Number of bots to add must be an integer.' await self.bot.send_message(ctx.message.author, msg) return # We are the creator - let's check the number of bots if botCount >= self.maxBots: # Too many bots! msg = 'You already have enough bots (max is {}).'.format(self.maxBots) await self.bot.send_message(ctx.message.author, msg) return if number > (self.maxBots - botCount): number = self.maxBots - botCount if number == 1: msg = '**Adding {} bot:**\n\n'.format(number) else: msg = '**Adding {} bots:**\n\n'.format(number) newBots = [] for i in range(0, number): # We can get another bot! botID = self.randomBotID(userGame) lobot = { 'ID': botID, 'User': None, 'Points': 0, 'Won': [], 'Hand': [], 'Laid': False, 'Refreshed': False, 'IsBot': True, 'Creator': False, 'Task': None } userGame['Members'].append(lobot) newBots.append(lobot) await self.drawCards(lobot['ID']) msg += '***{} ({})*** **joined the game!**\n'.format(self.botName, botID) # await self.nextPlay(ctx, userGame) for member in userGame['Members']: if member['IsBot']: continue await self.bot.send_message(member['User'], msg) # Check if adding put us at minimum members if len(userGame['Members']) - number < self.minMembers: # It was - *actually* start a game event = userGame['NextHand'] self.bot.loop.call_soon_threadsafe(event.set) else: # It was not - just incorporate new players await self.checkSubmissions(ctx, userGame) # Reset judging flag to retrigger actions game['Judging'] = False for bot in newBots: # Schedule stuff task = asyncio.ensure_future(self.botPick(ctx, bot, userGame)) bot['Task'] = task @commands.command(pass_context=True) async def removebot(self, ctx, *, id = None): """Removes a bot from the game. Can only be done by the player who created the game.""" if not await self.checkPM(ctx.message): return # Check if the user is already in game userGame = self.userGame(ctx.message.author) if not userGame: # Not in a game msg = "You're not in a game - you can create one with `{}newcah` or join one with `{}joincah`.".format(ctx.prefix, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return botCount = 0 for member in userGame['Members']: if member['IsBot']: botCount += 1 continue if member['User'] == ctx.message.author: if not member['Creator']: # You didn't make this game msg = 'Only the player that created the game can remove bots.' await self.bot.send_message(ctx.message.author, msg) return member['Time'] = int(time.time()) # We are the creator - let's check the number of bots if id == None: # Just remove the first bot we find for member in userGame['Members']: if member['IsBot']: await self.removeMember(member['ID']) """# Start the game loop event = userGame['NextHand'] self.bot.loop.call_soon_threadsafe(event.set)""" # Bot was removed - try to handle it calmly... await self.checkSubmissions(ctx, userGame) return msg = 'No bots to remove!' await self.bot.send_message(ctx.message.author, msg) return else: # Remove a bot by id if not await self.removeMember(id): # not found msg = 'I couldn\'t locate that bot on this game. If you\'re trying to remove a player, try the `{}removeplayer [name]` command.'.format(ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return # await self.nextPlay(ctx, userGame) """# Start the game loop event = userGame['NextHand'] self.bot.loop.call_soon_threadsafe(event.set)""" # Bot was removed - let's try to handle it calmly... await self.checkSubmissions(ctx, userGame) @commands.command(pass_context=True) async def cahgames(self, ctx): """Displays up to 10 CAH games in progress.""" shuffledGames = list(self.games) random.shuffle(shuffledGames) if not len(shuffledGames): await self.bot.send_message(ctx.message.channel, 'No games being played currently.') return max = 10 if len(shuffledGames) < 10: max = len(shuffledGames) msg = '__Current CAH Games__:\n\n' for i in range(0, max): playerCount = 0 botCount = 0 gameID = shuffledGames[i]['ID'] for j in shuffledGames[i]['Members']: if j['IsBot']: botCount += 1 else: playerCount += 1 botText = '{} bot'.format(botCount) if not botCount == 1: botText += 's' playerText = '{} player'.format(playerCount) if not playerCount == 1: playerText += 's' msg += '{}. {} - {} | {}\n'.format(i+1, gameID, playerText, botText) await self.bot.send_message(ctx.message.channel, msg) @commands.command(pass_context=True) async def score(self, ctx): """Display the score of the current game.""" if not await self.checkPM(ctx.message): return # Check if the user is already in game userGame = self.userGame(ctx.message.author) if not userGame: # Not in a game msg = "You're not in a game - you can create one with `{}newcah` or join one with `{}joincah`.".format(ctx.prefix, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return stat_embed = discord.Embed(color=discord.Color.purple()) stat_embed.set_author(name='Current Score') stat_embed.set_footer(text='Cards Against Humanity - id: {}'.format(userGame['ID'])) await self.bot.send_message(ctx.message.author, embed=stat_embed) users = sorted(userGame['Members'], key=lambda card:int(card['Points']), reverse=True) msg = '' i = 0 if len(users) > 10: msg += '__10 of {} Players:__\n\n'.format(len(users)) else: msg += '__Players:__\n\n' for user in users: i += 1 if i > 10: break if user['Points'] == 1: if user['User']: # Person msg += '{}. *{}* - 1 point\n'.format(i, self.displayname(user['User'])) else: # Bot msg += '{}. *{} ({})* - 1 point\n'.format(i, self.botName, user['ID']) else: if user['User']: # Person msg += '{}. *{}* - {} points\n'.format(i, self.displayname(user['User']), user['Points']) else: # Bot msg += '{}. *{} ({})* - {} points\n'.format(i, self.botName, user['ID'], user['Points']) await self.bot.send_message(ctx.message.author, msg) @commands.command(pass_context=True) async def laid(self, ctx): """Shows who laid their cards and who hasn't.""" if not await self.checkPM(ctx.message): return # Check if the user is already in game userGame = self.userGame(ctx.message.author) if not userGame: # Not in a game msg = "You're not in a game - you can create one with `{}newcah` or join one with `{}joincah`.".format(ctx.prefix, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return stat_embed = discord.Embed(color=discord.Color.purple()) stat_embed.set_author(name='Card Check') stat_embed.set_footer(text='Cards Against Humanity - id: {}'.format(userGame['ID'])) await self.bot.send_message(ctx.message.author, embed=stat_embed) users = sorted(userGame['Members'], key=lambda card:int(card['Laid'])) msg = '' i = 0 if len(users) > 10: msg += '__10 of {} Players:__\n\n'.format(len(users)) else: msg += '__Players:__\n\n' for user in users: if len(userGame['Members']) >= self.minMembers: if user == userGame['Members'][userGame['Judge']]: continue i += 1 if i > 10: break if user['Laid']: if user['User']: # Person msg += '{}. *{}* - Cards are in.\n'.format(i, self.displayname(user['User'])) else: # Bot msg += '{}. *{} ({})* - Cards are in.\n'.format(i, self.botName, user['ID']) else: if user['User']: # Person msg += '{}. *{}* - Waiting for cards...\n'.format(i, self.displayname(user['User'])) else: # Bot msg += '{}. *{} ({})* - Waiting for cards...\n'.format(i, self.botName, user['ID']) await self.bot.send_message(ctx.message.author, msg) @commands.command(pass_context=True) async def removeplayer(self, ctx, *, name = None): """Removes a player from the game. Can only be done by the player who created the game.""" if not await self.checkPM(ctx.message): return # Check if the user is already in game userGame = self.userGame(ctx.message.author) if not userGame: # Not in a game msg = "You're not in a game - you can create one with `{}newcah` or join one with `{}joincah`.".format(ctx.prefix, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return botCount = 0 for member in userGame['Members']: if member['IsBot']: botCount += 1 continue if member['User'] == ctx.message.author: if not member['Creator']: # You didn't make this game msg = 'Only the player that created the game can remove players.' await self.bot.send_message(ctx.message.author, msg) return member['Time'] = int(time.time()) # We are the creator - let's check the number of bots if name == None: # Nobody named! msg = 'Okay, I removed... no one from the game...' await self.bot.send_message(ctx.message.author, msg) return # Let's get the person either by name, or by id nameID = ''.join(list(filter(str.isdigit, name))) for member in userGame['Members']: toRemove = False if member['IsBot']: continue if name.lower() == self.displayname(member['User']).lower(): # Got em! toRemove = True elif nameID == member['ID']: # Got em! toRemove = True if toRemove: await self.removeMember(member['ID']) break # await self.nextPlay(ctx, userGame) if toRemove: """# Start the game loop event = userGame['NextHand'] self.bot.loop.call_soon_threadsafe(event.set)""" # Player was removed - try to handle it calmly... await self.checkSubmissions(ctx, userGame) else: msg = 'I couldn\'t locate that player on this game. If you\'re trying to remove a bot, try the `{}removebot [id]` command.'.format(ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return @commands.command(pass_context=True) async def flushhand(self, ctx): """Flushes the cards in your hand - can only be done once per game.""" if not await self.checkPM(ctx.message): return # Check if the user is already in game userGame = self.userGame(ctx.message.author) if not userGame: # Not in a game msg = "You're not in a game - you can create one with `{}newcah` or join one with `{}joincah`.".format(ctx.prefix, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return if userGame['Judge'] == -1: msg = "The game hasn't started yet. Probably not worth it to flush your hand before you get it..." await self.bot.send_message(ctx.message.author, msg) return for member in userGame['Members']: if member['IsBot']: continue if member['User'] == ctx.message.author: member['Time'] = int(time.time()) # Found us! if member['Refreshed']: # Already flushed their hand msg = 'You have already flushed your hand this game.' await self.bot.send_message(ctx.message.author, msg) return else: member['Hand'] = [] await self.drawCards(member['ID']) member['Refreshed'] = True msg = 'Flushing your hand!' await self.bot.send_message(ctx.message.author, msg) await self.showHand(ctx, ctx.message.author) return @commands.command(pass_context=True) async def idlekick(self, ctx, *, setting = None): """Sets whether or not to kick members if idle for 5 minutes or more. Can only be done by the player who created the game.""" if not await self.checkPM(ctx.message): return # Check if the user is already in game userGame = self.userGame(ctx.message.author) if not userGame: # Not in a game msg = "You're not in a game - you can create one with `{}newcah` or join one with `{}joincah`.".format(ctx.prefix, ctx.prefix) await self.bot.send_message(ctx.message.author, msg) return botCount = 0 for member in userGame['Members']: if member['IsBot']: botCount += 1 continue if member['User'] == ctx.message.author: if not member['Creator']: # You didn't make this game msg = 'Only the player that created the game can remove bots.' await self.bot.send_message(ctx.message.author, msg) return # We are the creator - let's check the number of bots if setting == None: # Output idle kick status if userGame['Timeout']: await self.bot.send_message(ctx.message.channel, 'Idle kick is enabled.') else: await self.bot.send_message(ctx.message.channel, 'Idle kick is disabled.') return elif setting.lower() == "yes" or setting.lower() == "on" or setting.lower() == "true": setting = True elif setting.lower() == "no" or setting.lower() == "off" or setting.lower() == "false": setting = False else: setting = None if setting == True: if userGame['Timeout'] == True: msg = 'Idle kick remains enabled.' else: msg = 'Idle kick now enabled.' for member in userGame['Members']: member['Time'] = int(time.time()) else: if userGame['Timeout'] == False: msg = 'Idle kick remains disabled.' else: msg = 'Idle kick now disabled.' userGame['Timeout'] = setting await self.bot.send_message(ctx.message.channel, msg) @commands.command() async def cahcredits(self): """Code credits.""" message = await self._credit() await self.bot.say(message) async def _credit(self): message = "```This cog is made possible by CorpBot.\n" message+= "Please visit https://github.com/corpnewt/CorpBot.py for more information.```" return message def setup(bot): bot.add_cog(CardsAgainstHumanity(bot))