diff --git a/README.md b/README.md
index 410a67a..109d208 100644
--- a/README.md
+++ b/README.md
@@ -1,36 +1,6 @@
# aikaterna-cogs
-Cogs for Red-DiscordBot by Twentysix26.
+v3 Cogs for Red-DiscordBot by Twentysix26.
-autoeconomy - New users that join the server will be automatically given a bank account.
-
-away - By Paddolicious#8880. Set and unset a user as being "away".
-
-cah - Cards Against Humanity. A port of CorpBot's module: https://github.com/corpnewt/CorpBot.py
-
-chatchart - Generates a pie chart to display chat activity over the last 5000 messages. Requested by violetnyte.
-
-forwarding - Forwards DMs sent to the bot to the owner of the bot. A port of the forwarding module from: https://github.com/jacobcheatley/dankbot
-
-hunting - By Paddolicious#8880. It hunts birds... and things that fly.
-
-imgwelcome - Welcome users to your server with a customized image.
-
-otherbot - Have multiple Red instances and want to know when one goes offline? Edit this cog and load it on your watcher bot.
-
-pug - Warcraft pug checker. A port of PugBot's module: https://github.com/reznok/PugBot
-
-radio - A hidden unpublished gem from Paddo, with a couple edits. Plays http audio streams like icecast and mp3 streams.
-
-riot - an old Fredboat command, requested by Mewleficent.
-
-seen - By Paddolicious#8880. Check when the user was last active on a server.
-
-serverlimit - Limit the bot to joining servers with over 25 members.
-
-
-The chatterbot cog that was previously on this repo has been removed in favor of: https://github.com/Nobleasskicker/GrandeCogs/tree/master/chat
-
-Q: Why do you have some of Paddo's cogs on your repo?
-A: He recently made an announcement about finding a new home for a few cogs. I've picked up a couple and I welcome PRs or feature requests. I'm also intending to port these for Red v3 as I can.
+away - Originally by Paddo, written for v3 by Axas, final tests by aikaterna. Set and unset a user as being "away".
Feel free to join the server for these cogs if you'd like. https://discord.gg/th6eS3T
diff --git a/autoeconomy/autoeconomy.py b/autoeconomy/autoeconomy.py
deleted file mode 100644
index 6c03e6a..0000000
--- a/autoeconomy/autoeconomy.py
+++ /dev/null
@@ -1,129 +0,0 @@
-import asyncio
-import discord
-import os
-from __main__ import send_cmd_help
-from cogs.utils import checks
-from cogs.utils.dataIO import dataIO
-from copy import deepcopy
-from discord.ext import commands
-
-default_settings = {"CHANNEL": None,
- "DEBUG": False,
- "TOGGLE": False,
- }
-
-
-class AutoEconomy:
- """Auto-registers new users to the bank. Must have Economy loaded."""
-
- def __init__(self, bot):
- self.bot = bot
- self.settings = dataIO.load_json('data/autoeconomy/settings.json')
- self.banksettings = dataIO.load_json('data/economy/settings.json')
- self.version = "0.1.1b"
-
- async def save_settings(self):
- dataIO.save_json('data/autoeconomy/settings.json', self.settings)
-
- async def _data_check(self, ctx):
- server = ctx.message.server
- if server.id not in self.settings:
- self.settings[server.id] = deepcopy(default_settings)
- self.settings[server.id]["CHANNEL"] = ctx.message.channel.id
- await self.save_settings()
- econ_cog = self.bot.get_cog('Economy')
- if not econ_cog:
- await self.bot.say("You must have Economy loaded to use this cog. \nAny settings saved will not work until the cog is loaded.")
- return
-
- @checks.admin_or_permissions(manage_server=True)
- @commands.group(pass_context=True)
- async def autoeconomy(self, ctx):
- """Configuration options for auto-registering Economy accounts."""
- if ctx.invoked_subcommand is None:
- await send_cmd_help(ctx)
- return
-
- @autoeconomy.command(pass_context=True, name="debug", no_pm=True)
- async def autoeconomy_debug(self, ctx):
- """Toggle autoeconomy debug messages."""
- server = ctx.message.server
- await self._data_check(ctx)
- self.settings[server.id]["DEBUG"] = not self.settings[server.id]["DEBUG"]
- if self.settings[server.id]["DEBUG"]:
- await self.bot.say("Debug messages on.")
- else:
- await self.bot.say("Debug messages off.")
- await self.save_settings()
-
- @autoeconomy.command(pass_context=True, name="channel", no_pm=True)
- async def autoeconomy_channel(self, ctx, channel: discord.Channel):
- """Set a channel for the debug messages."""
- server = ctx.message.server
- await self._data_check(ctx)
- if not server.me.permissions_in(channel).send_messages:
- await self.bot.say("No permissions to speak in that channel.")
- return
- self.settings[server.id]["CHANNEL"] = channel.id
- await self.save_settings()
- await self.bot.send_message(channel, "This channel will be used for debug messages.")
-
- @autoeconomy.command(pass_context=True, name="toggle", no_pm=True)
- async def autoeconomy_toggle(self, ctx):
- """Toggle autoeconomy on the server."""
- server = ctx.message.server
- await self._data_check(ctx)
- self.settings[server.id]["TOGGLE"] = not self.settings[server.id]["TOGGLE"]
- if self.settings[server.id]["TOGGLE"]:
- await self.bot.say("New users will automatically be registered for a bank account.")
- else:
- await self.bot.say("No longer auto-registering new users.")
- await self.save_settings()
-
- @autoeconomy.command(name="version", pass_context=True, hidden=True)
- async def autoeconomy_version(self):
- """Displays the autoeconomy version."""
- await self.bot.say("autoeconomy version {}.".format(self.version))
-
- async def on_member_join(self, member):
- server = member.server
- if server.id not in self.settings:
- self.settings[server.id] = deepcopy(default_settings)
- await self.save_settings()
- if not self.settings[server.id]["TOGGLE"]:
- return
- channel = self.settings[server.id]["CHANNEL"]
- channel_object = self.bot.get_channel(channel)
- econ_cog = self.bot.get_cog('Economy')
- if not econ_cog:
- return
- bank = self.bot.get_cog('Economy').bank
- try:
- bank.create_account(member)
- except Exception:
- if self.settings[server.id]["DEBUG"]:
- await self.bot.send_message(channel_object, "Economy account already exists for {}.".format(member.name))
- return
- if self.banksettings[server.id]["REGISTER_CREDITS"]:
- reg_credits = self.banksettings[server.id]["REGISTER_CREDITS"]
- bank.deposit_credits(member, reg_credits)
- if self.settings[server.id]["DEBUG"]:
- await self.bot.send_message(channel_object, "Bank account opened for {} and initial credits given.".format(member.name))
- return
-
-
-def check_folders():
- if not os.path.exists('data/autoeconomy/'):
- os.mkdir('data/autoeconomy/')
-
-
-def check_files():
- if not dataIO.is_valid_json('data/autoeconomy/settings.json'):
- defaults = {}
- dataIO.save_json('data/autoeconomy/settings.json', defaults)
-
-
-def setup(bot):
- check_folders()
- check_files()
- bot.add_cog(AutoEconomy(bot))
diff --git a/autoeconomy/info.json b/autoeconomy/info.json
deleted file mode 100644
index 17e01bc..0000000
--- a/autoeconomy/info.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "AUTHOR" : "aikaterna",
- "INSTALL_MSG" : "Use [p]autoeconomy to change settings.",
- "NAME" : "autoeconomy",
- "SHORT" : "Autoregister new users to the bot bank on server join.",
- "DESCRIPTION" : "Auto-registers new users to the bot bank on server join. You must have the Economy cog loaded for this cog to work.",
- "TAGS": ["bank", "economy", "register"]
-}
diff --git a/away/away.py b/away/away.py
deleted file mode 100644
index 10937ad..0000000
--- a/away/away.py
+++ /dev/null
@@ -1,88 +0,0 @@
-import os
-import discord
-from .utils import checks
-from discord.ext import commands
-from cogs.utils.dataIO import dataIO
-
-
-class Away:
- """Le away cog"""
- def __init__(self, bot):
- self.bot = bot
- self.data = dataIO.load_json('data/away/away.json')
-
- async def listener(self, message):
- tmp = {}
- server = message.server
- if server.id not in self.data:
- for mention in message.mentions:
- tmp[mention] = True
- if message.author.id != self.bot.user.id:
- for author in tmp:
- if author.id in self.data:
- try:
- avatar = author.avatar_url if author.avatar else author.default_avatar_url
- if self.data[author.id]['MESSAGE']:
- em = discord.Embed(description=self.data[author.id]['MESSAGE'], color=discord.Color.blue())
- em.set_author(name='{} is currently away'.format(author.display_name), icon_url=avatar)
- else:
- em = discord.Embed(color=discord.Color.blue())
- em.set_author(name='{} is currently away'.format(author.display_name), icon_url=avatar)
- await self.bot.send_message(message.channel, embed=em)
- except:
- if self.data[author.id]['MESSAGE']:
- msg = '{} is currently away and has set the following message: `{}`'.format(author.display_name, self.data[author.id]['MESSAGE'])
- else:
- msg = '{} is currently away'.format(author.display_name)
- await self.bot.send_message(message.channel, msg)
-
- @commands.command(pass_context=True, name="away")
- async def _away(self, context, *message: str):
- """Tell the bot you're away or back."""
- author = context.message.author
- if author.id in self.data:
- del self.data[author.id]
- msg = 'You\'re now back.'
- else:
- self.data[context.message.author.id] = {}
- if len(str(message)) < 256:
- self.data[context.message.author.id]['MESSAGE'] = ' '.join(context.message.clean_content.split()[1:])
- else:
- self.data[context.message.author.id]['MESSAGE'] = True
- msg = 'You\'re now set as away.'
- dataIO.save_json('data/away/away.json', self.data)
- await self.bot.say(msg)
-
- @commands.command(pass_context=True, name="toggleaway")
- @checks.mod_or_permissions(administrator=True)
- async def _ignore(self, context):
- server = context.message.server
- if server.id in self.data:
- del self.data[server.id]
- message = 'Not ignoring this server anymore.'
- else:
- self.data[server.id] = True
- message = 'Ignoring this server.'
- dataIO.save_json('data/away/away.json', self.data)
- await self.bot.say(message)
-
-
-def check_folder():
- if not os.path.exists('data/away'):
- print('Creating data/away folder...')
- os.makedirs('data/away')
-
-
-def check_file():
- f = 'data/away/away.json'
- if not dataIO.is_valid_json(f):
- dataIO.save_json(f, {})
- print('Creating default away.json...')
-
-
-def setup(bot):
- check_folder()
- check_file()
- n = Away(bot)
- bot.add_listener(n.listener, 'on_message')
- bot.add_cog(n)
diff --git a/away/info.json b/away/info.json
deleted file mode 100644
index af9161c..0000000
--- a/away/info.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "AUTHOR" : "Paddolicious#8880",
- "NAME" : "Away",
- "SHORT" : "Sets and unsets a user away.",
- "DESCRIPTION" : "Sets the user as away. When someone mentions the users the bot replies with either its own message or a message set by the user that the user is away.",
- "TAGS": ["away", "member", "tool"]
-}
diff --git a/cah/cah.py b/cah/cah.py
deleted file mode 100644
index 59418ad..0000000
--- a/cah/cah.py
+++ /dev/null
@@ -1,1690 +0,0 @@
-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))
diff --git a/cah/data/deck.json b/cah/data/deck.json
deleted file mode 100644
index 208bf32..0000000
--- a/cah/data/deck.json
+++ /dev/null
@@ -1,2434 +0,0 @@
-{
- "blackCards":[
- {
- "text":"Why can't I sleep at night?",
- "pick":1
- },
- {
- "text":"I got 99 problems but _ ain't one.",
- "pick":1
- },
- {
- "text":"What's a girl's best friend?",
- "pick":1
- },
- {
- "text":"What's that smell?",
- "pick":1
- },
- {
- "text":"This is the way the world ends \/ This is the way the world ends \/ Not with a bang but with _.",
- "pick":1
- },
- {
- "text":"What is Batman's guilty pleasure?",
- "pick":1
- },
- {
- "text":"TSA guidelines now prohibit _ on airplanes.",
- "pick":1
- },
- {
- "text":"What ended my last relationship?",
- "pick":1
- },
- {
- "text":"MTV's new reality show features eight washed-up celebrities living with _.",
- "pick":1
- },
- {
- "text":"I drink to forget _.",
- "pick":1
- },
- {
- "text":"I'm sorry, Professor, but I couldn't complete my homework because of _.",
- "pick":1
- },
- {
- "text":"Alternative medicine is now embracing the curative powers of _.",
- "pick":1
- },
- {
- "text":"What's that sound?",
- "pick":1
- },
- {
- "text":"What's the next Happy Meal toy?",
- "pick":1
- },
- {
- "text":"It's a pity that kids these days are all getting involved with _.",
- "pick":1
- },
- {
- "text":"In the new Disney Channel Original Movie, Hannah Montana struggles with _ for the first time.",
- "pick":1
- },
- {
- "text":"_. That's how I want to die.",
- "pick":1
- },
- {
- "text":"What does Dick Cheney prefer?",
- "pick":1
- },
- {
- "text":"What's the most emo?",
- "pick":1
- },
- {
- "text":"Instead of coal, Santa now gives the bad children _.",
- "pick":1
- },
- {
- "text":"Next from J.K. Rowling: Harry Potter and the Chamber of _.",
- "pick":1
- },
- {
- "text":"A romantic, candlelit dinner would be incomplete without _.",
- "pick":1
- },
- {
- "text":"White people like _.",
- "pick":1
- },
- {
- "text":"_. Betcha can't have just one!",
- "pick":1
- },
- {
- "text":"War! What is it good for?",
- "pick":1
- },
- {
- "text":"BILLY MAYS HERE FOR _.",
- "pick":1
- },
- {
- "text":"_. High five, bro.",
- "pick":1
- },
- {
- "text":"During sex, I like to think about _.",
- "pick":1
- },
- {
- "text":"What did I bring back from Mexico?",
- "pick":1
- },
- {
- "text":"What are my parents hiding from me?",
- "pick":1
- },
- {
- "text":"What will always get you laid?",
- "pick":1
- },
- {
- "text":"What would grandma find disturbing, yet oddly charming?",
- "pick":1
- },
- {
- "text":"What did the U.S. airdrop to the children of Afghanistan?",
- "pick":1
- },
- {
- "text":"What helps Obama unwind?",
- "pick":1
- },
- {
- "text":"What's there a ton of in heaven?",
- "pick":1
- },
- {
- "text":"Major League Baseball has banned _ for giving players an unfair advantage.",
- "pick":1
- },
- {
- "text":"When I am a billionaire, I shall erect a 50-foot statue to commemorate _.",
- "pick":1
- },
- {
- "text":"What's the new fad diet?",
- "pick":1
- },
- {
- "text":"When I am the President of the United States, I will create the Department of _.",
- "pick":1
- },
- {
- "text":"_. It's a trap!",
- "pick":1
- },
- {
- "text":"How am I maintaining my relationship status?",
- "pick":1
- },
- {
- "text":"What will I bring back in time to convince people that I am a powerful wizard?",
- "pick":1
- },
- {
- "text":"While the United States raced the Soviet Union to the moon, the Mexican government funneled millions of pesos into research on _.",
- "pick":1
- },
- {
- "text":"Coming to Broadway this season, _: The Musical.",
- "pick":1
- },
- {
- "text":"What's my secret power?",
- "pick":1
- },
- {
- "text":"What gives me uncontrollable gas?",
- "pick":1
- },
- {
- "text":"But before I kill you, Mr. Bond, I must show you _.",
- "pick":1
- },
- {
- "text":"What never fails to liven up the party?",
- "pick":1
- },
- {
- "text":"What am I giving up for Lent?",
- "pick":1
- },
- {
- "text":"What do old people smell like? ",
- "pick":1
- },
- {
- "text":"The class field trip was completely ruined by _.",
- "pick":1
- },
- {
- "text":"When Pharaoh remained unmoved, Moses called down a plague of _.",
- "pick":1
- },
- {
- "text":"I do not know with which weapons World War III will be fought, but World War IV will be fought with _.",
- "pick":1
- },
- {
- "text":"What's Teach for America using to inspire inner city students to succeed?",
- "pick":1
- },
- {
- "text":"In Michael Jackson's final moments, he thought about _.",
- "pick":1
- },
- {
- "text":"Why do I hurt all over?",
- "pick":1
- },
- {
- "text":"Studies show that lab rats navigate mazes 50% faster after being exposed to _.",
- "pick":1
- },
- {
- "text":"Why am I sticky?",
- "pick":1
- },
- {
- "text":"What's my anti-drug?",
- "pick":1
- },
- {
- "text":"And the Academy Award for _ goes to _.",
- "pick":2
- },
- {
- "text":"For my next trick, I will pull _ out of _.",
- "pick":2
- },
- {
- "text":"_: Good to the last drop.",
- "pick":1
- },
- {
- "text":"What did Vin Diesel eat for dinner?",
- "pick":1
- },
- {
- "text":"_: kid-tested, mother-approved.",
- "pick":1
- },
- {
- "text":"What gets better with age?",
- "pick":1
- },
- {
- "text":"I never truly understood _ until I encountered _.",
- "pick":2
- },
- {
- "text":"Rumor has it that Vladimir Putin's favorite delicacy is _ stuffed with _.",
- "pick":2
- },
- {
- "text":"Lifetime presents _, the story of _.",
- "pick":2
- },
- {
- "text":"Make a haiku.",
- "pick":3
- },
- {
- "text":"In M. Night Shyamalan's new movie, Bruce Willis discovers that _ had really been _ all along.",
- "pick":2
- },
- {
- "text":"_ is a slippery slope that leads to _.",
- "pick":2
- },
- {
- "text":"In a world ravaged by _, our only solace is _.",
- "pick":2
- },
- {
- "text":"That's right, I killed _. How, you ask? _.",
- "pick":2
- },
- {
- "text":"When I was tripping on acid, _ turned into _.",
- "pick":2
- },
- {
- "text":"_ + _ = _.",
- "pick":3
- },
- {
- "text":"What's the next superhero\/sidekick duo?",
- "pick":2
- },
- {
- "text":"Dear Abby, I'm having some trouble with _ and would like your advice.",
- "pick":1
- },
- {
- "text":"After the earthquake, Sean Penn brought _ to the people of Haiti.",
- "pick":1
- },
- {
- "text":"In L.A. County Jail, word is you can trade 200 cigarettes for _.",
- "pick":1
- },
- {
- "text":"Maybe she's born with it. Maybe it's _.",
- "pick":1
- },
- {
- "text":"Life for American Indians was forever changed when the White Man introduced them to _.",
- "pick":1
- },
- {
- "text":"Next on ESPN2, the World Series of _.",
- "pick":1
- },
- {
- "text":"Step 1: _. Step 2: _. Step 3: Profit.",
- "pick":2
- },
- {
- "text":"Here is the church... Here is the steeple... Open the doors... And there is _.",
- "pick":1
- },
- {
- "text":"How did I lose my virginity?",
- "pick":1
- },
- {
- "text":"During his childhood, Salvador Dali produced hundreds of paintings of _.",
- "pick":1
- },
- {
- "text":"In 1,000 years, when paper money is a distant memory, how will we pay for goods and services?",
- "pick":1
- },
- {
- "text":"What don't you want to find in your Kung Pao chicken?",
- "pick":1
- },
- {
- "text":"The Smithsonian Museum of Natural History has just opened an exhibit on _.",
- "pick":1
- },
- {
- "text":"Daddy, why is Mommy crying?",
- "pick":1
- },
- {
- "text":"An international tribunal has found _ guilty of _.",
- "pick":2
- },
- {
- "text":"And I would have gotten away with it, too, if it hadn't been for _!",
- "pick":1
- },
- {
- "text":"Dear Sir or Madam, We regret to inform you that the Office of _ has denied your request for _.",
- "pick":2
- },
- {
- "text":"He who controls _ controls the world.",
- "pick":1
- },
- {
- "text":"I learned the hard way that you can't cheer up a grieving friend with _.",
- "pick":1
- },
- {
- "text":"In a pinch, _ can be a suitable substitute for _.",
- "pick":2
- },
- {
- "text":"In his new self-produced album, Kanye West raps over the sounds of _.",
- "pick":1
- },
- {
- "text":"In its new tourism campaign, Detroit proudly proclaims that it has finally eliminated _.",
- "pick":1
- },
- {
- "text":"In Rome, there are whisperings that the Vatican has a secret room devoted to _.",
- "pick":1
- },
- {
- "text":"In the distant future, historians will agree that _ marked the beginning of America's decline.",
- "pick":1
- },
- {
- "text":"Michael Bay's new three-hour action epic pits _ against _.",
- "pick":2
- },
- {
- "text":"My plan for world domination begins with _.",
- "pick":1
- },
- {
- "text":"Next season on Man vs, Wild, Bear Grylls must survive the depths of the Amazon with only _ and his wits.",
- "pick":1
- },
- {
- "text":"Science will never explain _.",
- "pick":1
- },
- {
- "text":"Science will never explain the origin of _.",
- "pick":1
- },
- {
- "text":"The CIA now interrogates enemy agents by repeatedly subjecting them to _.",
- "pick":1
- },
- {
- "text":"The secret to a lasting marriage is communication, communication, and _.",
- "pick":1
- },
- {
- "text":"The socialist governments of Scandinavia have declared that access to _ is a basic human right.",
- "pick":1
- },
- {
- "text":"This season on Man vs. Wild, Bear Grylls must survive in the depths of the",
- "pick":1
- },
- {
- "text":"Amazon with only _ and his wits.",
- "pick":1
- },
- {
- "text":"What brought the orgy to a grinding halt?",
- "pick":1
- },
- {
- "text":"What has been making life difficult at the nudist colony?",
- "pick":1
- },
- {
- "text":"What's the gift that keeps on giving?",
- "pick":1
- },
- {
- "text":"When all else fails, I can always masturbate to _.",
- "pick":1
- },
- {
- "text":"When I pooped, what came out of my butt?",
- "pick":1
- },
- {
- "text":"_ would be woefully incomplete without _.",
- "pick":2
- },
- {
- "text":"After months of debate, the Occupy Wall Street General Assembly could only agree on \"More _!\"",
- "pick":1
- },
- {
- "text":"Before _, all we had was _.",
- "pick":2
- },
- {
- "text":"Before I run for president, I must destroy all evidence of my involvement with _.",
- "pick":1
- },
- {
- "text":"Charades was ruined for me forever when my mom had to act out _.",
- "pick":1
- },
- {
- "text":"During his midlife crisis, my dad got really into _.",
- "pick":1
- },
- {
- "text":"Everyone down on the ground! We don't want to hurt anyone. We're just here for _.",
- "pick":1
- },
- {
- "text":"I spent my whole life working toward _, only to have it ruined by _.",
- "pick":2
- },
- {
- "text":"I went from _ to _, all thanks to _.",
- "pick":3
- },
- {
- "text":"If God didn't want us to enjoy _, he wouldn't have given us _.",
- "pick":2
- },
- {
- "text":"In his newest and most difficult stunt, David Blaine must escape from _.",
- "pick":1
- },
- {
- "text":"Little Miss Muffet Sat on a tuffet, Eating her curds and _.",
- "pick":1
- },
- {
- "text":"Members of New York's social elite are paying thousands of dollars just to experience _.",
- "pick":1
- },
- {
- "text":"My country, 'tis of thee, sweet land of _.",
- "pick":1
- },
- {
- "text":"My mom freaked out when she looked at my browser history and found _.com\/_.",
- "pick":2
- },
- {
- "text":"My new favorite porn star is Joey \"_\" McGee.",
- "pick":1
- },
- {
- "text":"Next time on Dr. Phil: How to talk to your child about _.",
- "pick":1
- },
- {
- "text":"Only two things in life are certain: death and _.",
- "pick":1
- },
- {
- "text":"The Five Stages of Grief: denial, anger, bargaining, _, acceptance.",
- "pick":1
- },
- {
- "text":"The healing process began when I joined a support group for victims of _.",
- "pick":1
- },
- {
- "text":"The votes are in, and the new high school mascot is _.",
- "pick":1
- },
- {
- "text":"This is your captain speaking. Fasten your seatbelts and prepare for _.",
- "pick":1
- },
- {
- "text":"This month's Cosmo: \"Spice up your sex life by bringing _ into the bedroom.\"",
- "pick":1
- },
- {
- "text":"Tonight on 20\/20: What you don't know about _ could kill you.",
- "pick":1
- },
- {
- "text":"You haven't truly lived until you've experienced _ and _ at the same time.",
- "pick":2
- },
- {
- "text":"A remarkable new study has shown that chimps have evolved their own primitive version of _.",
- "pick":1
- },
- {
- "text":"What's harshing my mellow, man?",
- "pick":1
- },
- {
- "text":"Your persistence is admirable, my dear Prince. But you cannot win my heart with _ alone.",
- "pick":1
- },
- {
- "text":"In the seventh circle of Hell, sinners must endure _ for all eternity.",
- "pick":1
- },
- {
- "text":"A successful job interview begins with a firm handshake and ends with _.",
- "pick":1
- },
- {
- "text":"Lovin' you is easy 'cause you're _.",
- "pick":1
- },
- {
- "text":"My life is ruled by a vicious cycle of _ and _.",
- "pick":2
- },
- {
- "text":"The blind date was going horribly until we discovered our shared interest in _.",
- "pick":1
- },
- {
- "text":"_. Awesome in theory, kind of a mess in practice.",
- "pick":1
- },
- {
- "text":"I'm not like the rest of you. I'm too rich and busy for _.",
- "pick":1
- },
- {
- "text":"_: Hours of fun. Easy to use. Perfect for _!",
- "pick":2
- },
- {
- "text":"What left this stain on my couch?",
- "pick":1
- },
- {
- "text":"Call the law offices of Goldstein & Goldstein, because no one should have to tolerate _ in the workplace.",
- "pick":1
- },
- {
- "text":"When you get right down to it, _ is just _.",
- "pick":2
- },
- {
- "text":"Turns out that _-Man was neither the hero we needed nor wanted.",
- "pick":1
- },
- {
- "text":"As part of his daily regimen, Anderson Cooper sets aside 15 minutes for _.",
- "pick":1
- },
- {
- "text":"Money can't buy me love, but it can buy me _.",
- "pick":1
- },
- {
- "text":"With enough time and pressure, _ will turn into _.",
- "pick":2
- },
- {
- "text":"And what did you bring for show and tell?",
- "pick":1
- },
- {
- "text":"During high school I never really fit in until I found _ club.",
- "pick":1
- },
- {
- "text":"Hey baby, come back to my place and I'll show you _.",
- "pick":1
- },
- {
- "text":"After months of practice with _, I think I'm finally ready for _.",
- "pick":2
- },
- {
- "text":"To prepare for his upcoming role, Daniel Day-Lewis immersed himself in the world of _.",
- "pick":1
- },
- {
- "text":"Finally! A service that delivers _ right to your door.",
- "pick":1
- },
- {
- "text":"My gym teacher got fired for adding _ to the obstacle course.",
- "pick":1
- },
- {
- "text":"Having problems with _? Try _!",
- "pick":2
- },
- {
- "text":"As part of his contract, Prince won't perform without _ in his dressing room.",
- "pick":1
- },
- {
- "text":"Listen, son. If you want to get involved with _, I won't stop you. Just steer clear of _.",
- "pick":2
- },
- {
- "text":"What's fun until it gets weird?",
- "pick":1
- },
- {
- "text":"In the beginning, there was _. And the Lord said, \"Let there be _.\"",
- "pick":2
- },
- {
- "text":"Wes Anderson's new film tells the story of a precocious child coming to terms with _.",
- "pick":1
- },
- {
- "text":"_ will never be the same after _.",
- "pick":2
- },
- {
- "text":"I'm sorry, sir, but we don't allow _ at the country club.",
- "pick":1
- },
- {
- "text":"How am I compensating for my tiny penis?",
- "pick":1
- },
- {
- "text":"You've seen the bearded lady! You've seen the ring of fire! Now, ladies and gentlemen, feast your eyes upon _!",
- "pick":1
- },
- {
- "text":"We never did find _, but along the way we sure learned a lot about _.",
- "pick":2
- },
- {
- "text":"She's up all night for good fun. I'm up all night for _.",
- "pick":1
- },
- {
- "text":"_ may pass, but _ will last forever.",
- "pick":2
- },
- {
- "text":"Dear Leader Kim Jong-un, our village praises your",
- "pick":1
- },
- {
- "text":"infinite wisdom with a humble offering of _.",
- "pick":1
- },
- {
- "text":"Man, this is bullshit. Fuck _.",
- "pick":1
- },
- {
- "text":"You guys, I saw this crazy movie last night. It opens on _, and then there's some stuff about _, and then it ends with _.",
- "pick":3
- },
- {
- "text":"In return for my soul, the Devil promised me _, but all I got was _.",
- "pick":2
- },
- {
- "text":"The Japanese have developed a smaller, more efficient version of _.",
- "pick":1
- },
- {
- "text":"Alright, bros. Our frat house is condemned, and all the hot slampieces are over at Gamma Phi. That time has come to commence Operation _.",
- "pick":1
- },
- {
- "text":"This is the prime of my life. I'm young, hot, and full of _.",
- "pick":1
- },
- {
- "text":"I'm pretty sure I'm high right now, because I'm absolutely mesmerized by _.",
- "pick":1
- },
- {
- "text":"It lurks in the night. It hungers for flesh. This summer, no one is safe from _.",
- "pick":1
- },
- {
- "text":"If you can't handle _, you'd better stay away from _.",
- "pick":2
- },
- {
- "text":"Forget everything you know about _, because now we've supercharged it with _!",
- "pick":2
- },
- {
- "text":"Honey, I have a new role-play I want to try tonight!",
- "pick":1
- },
- {
- "text":"You can be _, and I'll be _.",
- "pick":2
- },
- {
- "text":"This year's hottest album is \"_\" by _.",
- "pick":2
- },
- {
- "text":"Every step towards _ gets me a little bit closer to _.",
- "pick":2
- },
- {
- "text":"Oprah's book of the month is \"_ For _: A Story of Hope.\"",
- "pick":2
- },
- {
- "text":"Do not fuck with me! I am literally _ right now.",
- "pick":1
- },
- {
- "text":"2 AM in the city that never sleeps. The door swings open and she walks in, legs up to here. Something in her eyes tells me she's looking for _.",
- "pick":1
- },
- {
- "text":"As king, how will I keep the peasants in line?",
- "pick":1
- },
- {
- "text":"Adventure. Romance. _. From Paramount Pictures, \"_.\"",
- "pick":2
- },
- {
- "text":"I am become _, destroyer of _!",
- "pick":2
- },
- {
- "text":"And today's soup is Cream of _.",
- "pick":1
- },
- {
- "text":"Armani suit: $1,000. Dinner for two at that swanky restaurant: $300. The look on her face when you surprise her with _: priceless.",
- "pick":1
- },
- {
- "text":"Do the Dew with our most extreme flavor yet! Get ready for Mountain Dew _!",
- "pick":1
- },
- {
- "text":"Do you lack energy? Does it sometimes feel like the whole world is _ ? Zoloft.",
- "pick":1
- },
- {
- "text":"Don't forget! Beginning this week, Casual Friday will officially become \"_ Friday.\"",
- "pick":1
- },
- {
- "text":"Get ready for the movie of the summer! One cop plays by the book. The other's only interested in one thing: _.",
- "pick":1
- },
- {
- "text":"Having the worst day EVER. #_",
- "pick":1
- },
- {
- "text":"Heed my voice, mortals! I am the god of _ , and I will not tolerate _!",
- "pick":2
- },
- {
- "text":"Help me doctor, I've got _ in my butt!",
- "pick":1
- },
- {
- "text":"Here at the Academy for Gifted Children, we all students to explore _ at their own pace.",
- "pick":1
- },
- {
- "text":"Hi MTV! My name is Kendra, I live in Malibu, I'm into _, and I love to have a good time.",
- "pick":1
- },
- {
- "text":"Hi, this is Jim from accounting. We noticed a $1,200 charge labeled \"_.\" Can you explain?",
- "pick":1
- },
- {
- "text":"I don't mean to brag, but they call me the Micheal Jordan of _.",
- "pick":1
- },
- {
- "text":"In his farewell address, George Washington famously warned Americans about the dangers of _.",
- "pick":1
- },
- {
- "text":"In his new action comedy, Jackie Chan must fend off ninjas while also dealing with _.",
- "pick":1
- },
- {
- "text":"Life's pretty tough in the fast lane. That's why I never leave the house without _.",
- "pick":1
- },
- {
- "text":"Now in bookstores: \"The Audacity of _\" by Barack Obama.",
- "pick":1
- },
- {
- "text":"Patient presents with _ . Likely a result of _ .",
- "pick":2
- },
- {
- "text":"Well if _ is good enough for _, it's good enough for me.",
- "pick":2
- },
- {
- "text":"Well what do you have to say for yourself, Casey? This is the third time you've been sent to the principal's office for _.",
- "pick":1
- },
- {
- "text":"What killed my boner?",
- "pick":1
- },
- {
- "text":"What's making things awkward in the sauna?",
- "pick":1
- },
- {
- "text":"WHOOO! God damn I love _!",
- "pick":1
- },
- {
- "text":"Why am I broke?",
- "pick":1
- },
- {
- "text":"Yo' mama's so fat she _!",
- "pick":1
- },
- {
- "text":"I work my ass off all day for this family, and this what I come home to? _!?",
- "pick":1
- },
- {
- "text":"I have a strict policy. First date, dinner. Second date, kiss. Third date, _.",
- "pick":1
- },
- {
- "text":"When I was a kid we used to play Cowboys and _.",
- "pick":1
- },
- {
- "text":"This is America. If you don't work hard, you don't succeed. I don't care if you're black, white, purple, or _.",
- "pick":1
- },
- {
- "text":"You Won't Believe These 15 Hilarious _ Bloopers!",
- "pick":1
- },
- {
- "text":"James is a lonely boy. But when he discovers a secret door in his attic, he meets a magical new friend: _.",
- "pick":1
- },
- {
- "text":"Don't worry, kid. It gets better. I've been living with _ for 20 years.",
- "pick":1
- },
- {
- "text":"My grandfather worked his way up from nothing.",
- "pick":1
- },
- {
- "text":"When he came to this country, all he had was the shoes on his feet and _.",
- "pick":1
- },
- {
- "text":"Behind every powerful man is _.",
- "pick":1
- },
- {
- "text":"You are not alone. Millions of Americans struggle with _ every day.",
- "pick":1
- },
- {
- "text":"Come to Dubai, where you can relax in our world-famous spas, experience the nightlife, or simply enjoy _ by the poolside.",
- "pick":1
- },
- {
- "text":"'This is madness!' 'No. THIS IS _!'",
- "pick":1
- },
- {
- "text":"Listen, Gary, I like you. But if you want that corner office, you're going to have to show me _.",
- "pick":1
- },
- {
- "text":"I went to the desert and ate of the peyote cactus.",
- "pick":1
- },
- {
- "text":"Turns out my spirit animal is _.",
- "pick":1
- },
- {
- "text":"And would you like those buffalo wings mild, hot, or _?",
- "pick":1
- },
- {
- "text":"The six things I could never do without: oxygen, facebook, chocolate, netflix, friends, and _ LOL!",
- "pick":1
- },
- {
- "text":"Why won't you make love to me anymore? Is it _?",
- "pick":1
- },
- {
- "text":"Puberty is a time of change. You might notice hair growing in new places. You might develop an interest in _. This is normal.",
- "pick":1
- },
- {
- "text":"I'm sorry, Mrs. Chen, but there was nothing we could do. At 4:15 this morning, your son succumbed to _.",
- "pick":1
- },
- {
- "text":"I'm Miss Tennessee, and if I could make the world better by changing one thing, I would get rid of _.",
- "pick":1
- },
- {
- "text":"Tonight, we will have sex. And afterwards, if you'd like, a little bit of _.",
- "pick":1
- },
- {
- "text":"Everybody join hands and close your eyes. Do you sense that? That's the presence of _ in this room.",
- "pick":1
- },
- {
- "text":"To become a true Yanomamo warrior, you must prove that you can withstand _ without crying out.",
- "pick":1
- },
- {
- "text":"Y'all ready to get this thing started? I'm Nick Cannon, and this is America's Got _.",
- "pick":1
- },
- {
- "text":"If you had to describe me, the Card Czar, using only one of the cards in your hand, which one would it be?",
- "pick":1
- },
- {
- "text":"I may not be much to look at, but I fuck like _.",
- "pick":1
- },
- {
- "text":"Errbody in the club _.",
- "pick":1
- },
- {
- "text":"The top Google auto-complete results for \"Barack Obama\": Barack Obama Height. Barack Obama net worth. Barack Obama _.",
- "pick":1
- },
- {
- "text":"Barack Obama Height.",
- "pick":1
- },
- {
- "text":"Barack Obama net worth.",
- "pick":1
- },
- {
- "text":"Barack Obama ___.",
- "pick":1
- },
- {
- "text":"Son, take it from someone who's been around the block a few times. Nothin' puts her in the mood like _.",
- "pick":1
- },
- {
- "text":"Art isn't just a painting in a stuffy museum. Art is alive. Art is _.",
- "pick":1
- },
- {
- "text":"You won't believe what's in my pussy. It's _.",
- "pick":1
- },
- {
- "text":"What's the most problematic?",
- "pick":1
- },
- {
- "text":"Feeling so grateful! #amazing #mylife #_.",
- "pick":1
- },
- {
- "text":"What's a total waste of Hillary Clinton's time?",
- "pick":1
- },
- {
- "text":"What's the gayest?",
- "pick":1
- },
- {
- "text":"_ be all like _.",
- "pick":2
- },
- {
- "text":"Girls just wanna have _.",
- "pick":1
- },
- {
- "text":"One more thing. Watch out for Big Mike. They say he killed a man with _.",
- "pick":1
- },
- {
- "text":"Well, shit. My eyes ain't so good, but I'll eat my own boot if that ain't _!",
- "pick":1
- },
- {
- "text":"If at first you don't succeed, try _.",
- "pick":1
- },
- {
- "text":"What will end racism once and for all?",
- "pick":1
- },
- {
- "text":"I'll take the BBQ bacon burger with friend egg and fuck it how about _.",
- "pick":1
- },
- {
- "text":"Well if _ is a crime, then lock me up!",
- "pick":1
- },
- {
- "text":"We do not shake with our left hands in this country. That is the hand we use for _.",
- "pick":1
- },
- {
- "text":"You know who else liked _? Hitler.",
- "pick":1
- },
- {
- "text":"Poor Brandon, still living in his parent's basement. I heard he never got over _.",
- "pick":1
- },
- {
- "text":"What totally destroyed my asshole?",
- "pick":1
- },
- {
- "text":"I don't believe in God. I believe in _.",
- "pick":1
- },
- {
- "text":"Then the princess kissed the frog, and all of a sudden the frog was _!",
- "pick":1
- },
- {
- "text":"I got rhythm, I've got music, I've got _. Who could ask for anything more?",
- "pick":1
- },
- {
- "text":"No, no, no, no, no, no, NO! I will NOT let _ ruin this wedding.",
- "pick":1
- },
- {
- "text":"Coming to Red Lobster this month, _.",
- "pick":1
- },
- {
- "text":"Ooo, daddy like _.",
- "pick":1
- },
- {
- "text":"Best you go back where you came from, now. We don't take too kindly to _ in these parts.",
- "pick":1
- },
- {
- "text":"Summer lovin', had me a blast. _, happened so fast.",
- "pick":1
- },
- {
- "text":"LSD + _ = really bad time.",
- "pick":1
- },
- {
- "text":"What are all those whales singing about?",
- "pick":1
- },
- {
- "text":"As Teddy Roosevelt said, the four manly virtues are honor, temperance, industry, and _.",
- "pick":1
- },
- {
- "text":"I tell you, it was a non-stop fuckfest. When it was over, my asshole looked like _.",
- "pick":1
- },
- {
- "text":"What turned me into a Republican?",
- "pick":1
- },
- {
- "text":"I'm sorry, sir, but your insurance plan doesn't cover injuries caused by _.",
- "pick":1
- },
- {
- "text":"Run, run, as fast as you can! You can't catch me, I'm _!",
- "pick":1
- },
- {
- "text":"There is no God. It's just _ and then you die.",
- "pick":1
- },
- {
- "text":"She's just one of the guys, you know? She likes beer, and football, and _.",
- "pick":1
- },
- {
- "text":"This Friday at the Liquid Lunge, it's _ Night! Ladies drink free.",
- "pick":1
- },
- {
- "text":"What sucks balls?",
- "pick":1
- },
- {
- "text":"I've had a horrible vision, father. I saw mountains crumbling, stars falling from the sky. I saw _.",
- "pick":1
- },
- {
- "text":"Oh no! Siri, how do I fix _?",
- "pick":1
- },
- {
- "text":"Dance like there's nobody watching, love like you'll never be hurt, and live like you're _.",
- "pick":1
- },
- {
- "text":"Mom's to-do list: Buy Groceries Clean up ___. Soccer Practice.",
- "pick":1
- },
- {
- "text":"Why am I laughing and crying and taking off my clothes?",
- "pick":1
- },
- {
- "text":"She's a lady in the streets, _ in the sheets.",
- "pick":1
- },
- {
- "text":"What's about to take dance floor to the next level?",
- "pick":1
- },
- {
- "text":"CNN breaking news! Scientists discover _.",
- "pick":1
- },
- {
- "text":"Most Americans would not vote for a candidate who is openly _.",
- "pick":1
- },
- {
- "text":"Congratulations! You have been selected for our summer internship program. While we are unable to offer a salary, we can offer you _.",
- "pick":1
- },
- {
- "text":"In the 1950s, psychologists prescribed _ as a cure for homosexually.",
- "pick":1
- },
- {
- "text":"As reparations for slavery, all African Americans will receive _.",
- "pick":1
- },
- {
- "text":"With a one-time gift of just $10, you can save this child from _.",
- "pick":1
- },
- {
- "text":"Google Calendar alert: _ in 10 minutes.",
- "pick":1
- }
- ],
- "whiteCards":[
- "Coat hanger abortions.",
- "Man meat.",
- "Autocannibalism.",
- "Vigorous jazz hands.",
- "Flightless birds.",
- "Pictures of boobs.",
- "Doing the right thing.",
- "The violation of our most basic human rights.",
- "Viagra.",
- "Self-loathing.",
- "Spectacular abs.",
- "A balanced breakfast.",
- "Roofies.",
- "Concealing a boner.",
- "Amputees.",
- "The Big Bang.",
- "Former President George W. Bush.",
- "The Rev. Dr. Martin Luther King, Jr.",
- "Smegma.",
- "Being marginalized.",
- "Cuddling.",
- "Laying an egg.",
- "The Pope.",
- "Aaron Burr.",
- "Genital piercings.",
- "Fingering.",
- "A bleached asshole.",
- "Horse meat.",
- "Fear itself.",
- "Science.",
- "Elderly Japanese men.",
- "Stranger danger.",
- "The terrorists.",
- "Praying the gay away.",
- "Same-sex ice dancing.",
- "Ethnic cleansing.",
- "Cheating in the Special Olympics.",
- "German dungeon porn.",
- "Bingeing and purging.",
- "Making a pouty face.",
- "William Shatner.",
- "Heteronormativity.",
- "Nickelback.",
- "Tom Cruise.",
- "The profoundly handicapped.",
- "The placenta.",
- "Chainsaws for hands.",
- "Arnold Schwarzenegger.",
- "An icepick lobotomy.",
- "Goblins.",
- "Object permanence.",
- "Dying.",
- "Foreskin.",
- "A falcon with a cap on its head.",
- "Hormone injections.",
- "Dying of dysentery.",
- "Sexy pillow fights.",
- "The invisible hand.",
- "A really cool hat.",
- "Sean Penn.",
- "Heartwarming orphans.",
- "The clitoris.",
- "The Three-Fifths compromise.",
- "A sad handjob.",
- "Men.",
- "Historically black colleges.",
- "A micropenis.",
- "Raptor attacks.",
- "Agriculture.",
- "Vikings.",
- "Pretending to care.",
- "The Underground Railroad.",
- "My humps.",
- "Being a dick to children.",
- "Geese.",
- "Bling.",
- "Sniffing glue.",
- "The South.",
- "An Oedipus complex.",
- "Eating all of the cookies before the AIDS bake-sale.",
- "Sexting.",
- "YOU MUST CONSTRUCT ADDITIONAL PYLONS.",
- "Mutually-assured destruction.",
- "Sunshine and rainbows.",
- "Count Chocula.",
- "Sharing needles.",
- "Being rich.",
- "Skeletor.",
- "A sausage festival.",
- "Michael Jackson.",
- "Emotions.",
- "Farting and walking away.",
- "The Chinese gymnastics team.",
- "Necrophilia.",
- "Spontaneous human combustion.",
- "Yeast.",
- "Leaving an awkward voicemail.",
- "Dick Cheney.",
- "White people.",
- "Penis envy.",
- "Teaching a robot to love.",
- "Sperm whales.",
- "Scrubbing under the folds.",
- "Panda sex.",
- "Whipping it out.",
- "Catapults.",
- "Masturbation.",
- "Natural selection.",
- "Opposable thumbs.",
- "A sassy black woman.",
- "AIDS.",
- "The KKK.",
- "Figgy pudding.",
- "Seppuku.",
- "Gandhi.",
- "Preteens.",
- "Toni Morrison's vagina.",
- "Five-Dollar Footlongs.",
- "Land mines.",
- "A sea of troubles.",
- "A zesty breakfast burrito.",
- "Christopher Walken.",
- "Friction.",
- "Balls.",
- "Dental dams.",
- "A can of whoop-ass.",
- "A tiny horse.",
- "Waiting 'til marriage.",
- "Authentic Mexican cuisine.",
- "Genghis Khan.",
- "Old-people smell.",
- "Feeding Rosie O'Donnell.",
- "Pixelated bukkake.",
- "Friends with benefits.",
- "The token minority.",
- "The Tempur-Pedic Swedish Sleep System.",
- "A thermonuclear detonation.",
- "Take-backsies.",
- "The Rapture.",
- "A cooler full of organs.",
- "Sweet, sweet vengeance.",
- "RoboCop.",
- "Keanu Reeves.",
- "Drinking alone.",
- "Giving 110%.",
- "Flesh-eating bacteria.",
- "The American Dream.",
- "Taking off your shirt.",
- "Me time.",
- "A murder most foul.",
- "The inevitable heat death of the universe.",
- "The folly of man.",
- "That thing that electrocutes your abs.",
- "Cards Against Humanity.",
- "Fiery poops.",
- "Poor people.",
- "Edible underpants.",
- "Britney Spears at 55.",
- "All-you-can-eat shrimp for $4.99.",
- "Pooping back and forth. Forever.",
- "Fancy Feast.",
- "Jewish fraternities.",
- "Being a motherfucking sorcerer.",
- "Pulling out.",
- "Picking up girls at the abortion clinic.",
- "The homosexual agenda.",
- "The Holy Bible.",
- "Passive-agression.",
- "Ronald Reagan.",
- "Vehicular manslaughter.",
- "Nipple blades.",
- "Assless chaps.",
- "Full frontal nudity.",
- "Hulk Hogan.",
- "Daddy issues.",
- "The hardworking Mexican.",
- "Natalie Portman.",
- "Waking up half-naked in a Denny's parking lot.",
- "God.",
- "Sean Connery.",
- "Saxophone solos.",
- "Gloryholes.",
- "The World of Warcraft.",
- "Homeless people.",
- "Scalping.",
- "Darth Vader.",
- "Eating the last known bison.",
- "Guys who don't call.",
- "Hot Pockets.",
- "A time travel paradox.",
- "The milk man.",
- "Testicular torsion.",
- "Dropping a chandelier on your enemies and riding the rope up.",
- "World peace.",
- "A salty surprise.",
- "Poorly-timed Holocaust jokes.",
- "Smallpox blankets.",
- "Licking things to claim them as your own.",
- "The heart of a child.",
- "Robert Downey, Jr.",
- "Lockjaw.",
- "Eugenics.",
- "A good sniff.",
- "Friendly fire.",
- "The taint; the grundle; the fleshy fun-bridge.",
- "Wearing underwear inside-out to avoid doing laundry.",
- "Hurricane Katrina.",
- "Free samples.",
- "Jerking off into a pool of children's tears.",
- "A foul mouth.",
- "The glass ceiling.",
- "Republicans.",
- "Explosions.",
- "Michelle Obama's arms.",
- "Getting really high.",
- "Attitude.",
- "Sarah Palin.",
- "The Ubermensch.",
- "Altar boys.",
- "My soul.",
- "My sex life.",
- "Pedophiles.",
- "72 virgins.",
- "Pabst Blue Ribbon.",
- "Domino's Oreo Dessert Pizza.",
- "A snapping turtle biting the tip of your penis.",
- "The Blood of Christ.",
- "Half-assed foreplay.",
- "My collection of high-tech sex toys.",
- "A middle-aged man on roller skates.",
- "Bitches.",
- "Bill Nye the Science Guy.",
- "Italians.",
- "A windmill full of corpses.",
- "Adderall.",
- "Crippling debt.",
- "A stray pube.",
- "Prancing.",
- "Passing a kidney stone.",
- "A brain tumor.",
- "Leprosy.",
- "Puppies!",
- "Bees?",
- "Frolicking.",
- "Repression.",
- "Road head.",
- "A bag of magic beans.",
- "An asymmetric boob job.",
- "Dead parents.",
- "Public ridicule.",
- "A mating display.",
- "A mime having a stroke.",
- "Stephen Hawking talking dirty.",
- "African children.",
- "Mouth herpes.",
- "Overcompensation.",
- "Riding off into the sunset.",
- "Being on fire.",
- "Tangled Slinkys.",
- "Civilian casualties.",
- "Auschwitz.",
- "My genitals.",
- "Not reciprocating oral sex.",
- "Lactation.",
- "Being fabulous.",
- "Shaquille O'Neal's acting career.",
- "My relationship status.",
- "Asians who aren't good at math.",
- "Alcoholism.",
- "Incest.",
- "Grave robbing.",
- "Hope.",
- "8 oz. of sweet Mexican black-tar heroin.",
- "Kids with ass cancer.",
- "Winking at old people.",
- "The Jews.",
- "Justin Bieber.",
- "Doin' it in the butt.",
- "A lifetime of sadness.",
- "The Hamburglar.",
- "Swooping.",
- "Classist undertones.",
- "New Age music.",
- "Not giving a shit about the Third World.",
- "The Kool-Aid Man.",
- "A hot mess.",
- "Tentacle porn.",
- "Lumberjack fantasies.",
- "The gays.",
- "Scientology.",
- "Estrogen.",
- "GoGurt.",
- "Judge Judy.",
- "Dick fingers.",
- "Racism.",
- "Surprise sex!",
- "Police brutality.",
- "Passable transvestites.",
- "The Virginia Tech Massacre.",
- "When you fart and a little bit comes out.",
- "Oompa-Loompas.",
- "A fetus.",
- "Obesity.",
- "Tasteful sideboob.",
- "Hot people.",
- "BATMAN!!!",
- "Black people.",
- "A gassy antelope.",
- "Sexual tension.",
- "Third base.",
- "Racially-biased SAT questions.",
- "Porn stars.",
- "A Super Soaker full of cat pee.",
- "Muhammed (Praise Be Unto Him).",
- "Puberty.",
- "A disappointing birthday party.",
- "An erection that lasts longer than four hours.",
- "White privilege.",
- "Getting so angry that you pop a boner.",
- "Wifely duties.",
- "Two midgets shitting into a bucket.",
- "Queefing.",
- "Wiping her butt.",
- "Golden showers.",
- "Barack Obama.",
- "Nazis.",
- "A robust mongoloid.",
- "An M. Night Shyamalan plot twist.",
- "Getting drunk on mouthwash.",
- "Lunchables.",
- "Women in yogurt commercials.",
- "John Wilkes Booth.",
- "Powerful thighs.",
- "Mr. Clean, right behind you.",
- "Multiple stab wounds.",
- "Cybernetic enhancements.",
- "Serfdom.",
- "Kanye West.",
- "Women's suffrage.",
- "Children on leashes.",
- "Harry Potter erotica.",
- "The Dance of the Sugar Plum Fairy.",
- "Lance Armstrong's missing testicle.",
- "Parting the Red Sea.",
- "The Amish.",
- "Dead babies.",
- "Child beauty pageants.",
- "AXE Body Spray.",
- "Centaurs.",
- "Copping a feel.",
- "Grandma.",
- "Famine.",
- "The Trail of Tears.",
- "The miracle of childbirth.",
- "Finger painting.",
- "A monkey smoking a cigar.",
- "The Make-A-Wish Foundation.",
- "Anal beads.",
- "The Force.",
- "Kamikaze pilots.",
- "Dry heaving.",
- "Active listening.",
- "Ghosts.",
- "The Hustle.",
- "Peeing a little bit.",
- "Another goddamn vampire movie.",
- "Shapeshifters.",
- "The Care Bear Stare.",
- "Hot cheese.",
- "A mopey zoo lion.",
- "A defective condom.",
- "Teenage pregnancy.",
- "A Bop It.",
- "Expecting a burp and vomiting on the floor.",
- "Horrifying laser hair removal accidents.",
- "Boogers.",
- "Unfathomable stupidity.",
- "Breaking out into song and dance.",
- "Soup that is too hot.",
- "Morgan Freeman's voice.",
- "Getting naked and watching Nickelodeon.",
- "MechaHitler.",
- "Flying sex snakes.",
- "The true meaning of Christmas.",
- "My inner demons.",
- "Pac-Man uncontrollably guzzling cum.",
- "My vagina.",
- "A homoerotic volleyball montage.",
- "Actually taking candy from a baby.",
- "Crystal meth.",
- "Exactly what you'd expect.",
- "Natural male enhancement.",
- "Passive-aggressive Post-it notes.",
- "Inappropriate yodeling.",
- "Lady Gaga.",
- "The Little Engine That Could.",
- "Vigilante justice.",
- "A death ray.",
- "Poor life choices.",
- "A gentle caress of the inner thigh.",
- "Embryonic stem cells.",
- "Nicolas Cage.",
- "Firing a rifle into the air while balls deep in a squealing hog.",
- "Switching to Geico.",
- "The chronic.",
- "Erectile dysfunction.",
- "Home video of Oprah sobbing into a Lean Cuisine.",
- "A bucket of fish heads.",
- "50,000 volts straight to the nipples.",
- "Being fat and stupid.",
- "Hospice care.",
- "A pyramid of severed heads.",
- "Getting married, having a few kids, buying some stuff, retiring to Florida, and dying.",
- "A subscription to Men's Fitness.",
- "Crucifixion.",
- "A micropig wearing a tiny raincoat and booties.",
- "Some god-damn peace and quiet.",
- "Used panties.",
- "A tribe of warrior women.",
- "The penny whistle solo from \"My Heart Will Go On.\"",
- "An oversized lollipop.",
- "Helplessly giggling at the mention of Hutus and Tutsis.",
- "Not wearing pants.",
- "Consensual sex.",
- "Her Majesty, Queen Elizabeth II.",
- "Funky fresh rhymes.",
- "The art of seduction.",
- "The Devil himself.",
- "Advice from a wise, old black man.",
- "Destroying the evidence.",
- "The light of a billion suns.",
- "Wet dreams.",
- "Synergistic management solutions.",
- "Growing a pair.",
- "Silence.",
- "An M16 assault rifle.",
- "Poopy diapers.",
- "A live studio audience.",
- "The Great Depression.",
- "A spastic nerd.",
- "Rush Limbaugh's soft, shitty body.",
- "Tickling Sean Hannity, even after he tells you to stop.",
- "Stalin.",
- "Brown people.",
- "Rehab.",
- "Capturing Newt Gingrich and forcing him to dance in a monkey suit.",
- "Battlefield amputations.",
- "An uppercut.",
- "Shiny objects.",
- "An ugly face.",
- "Menstrual rage.",
- "A bitch slap.",
- "One trillion dollars.",
- "Chunks of dead prostitute.",
- "The entire Mormon Tabernacle Choir.",
- "The female orgasm.",
- "Extremely tight pants.",
- "The Boy Scouts of America.",
- "Stormtroopers.",
- "Throwing a virgin into a volcano.",
- "24-hour media coverage",
- "A beached whale.",
- "A big black dick.",
- "A bloody pacifier.",
- "A crappy little hand.",
- "A fat bald man from the internet.",
- "A low standard of living.",
- "A nuanced critique.",
- "A panty raid.",
- "A passionate Latino lover.",
- "A plunger to the face.",
- "A rival dojo.",
- "A smiling black man, a latina businesswoman, a cool asian, and some whites.",
- "A web of lies.",
- "A woman scorned.",
- "An atomic wedgie.",
- "An Etsy steampunk strap-on.",
- "An evil man in evil clothes.",
- "AndrÈ the Giant's enormous, leathery scrotum.",
- "Apologizing.",
- "Appreciative snapping.",
- "Ashton Kutcher.",
- "Beating your wives.",
- "Being a busy adult with many important things to do.",
- "Being a dinosaur.",
- "Blaxploitation.",
- "Bosnian chicken farmers.",
- "Breaking nip slip news.",
- "Carnies.",
- "Clams.",
- "Clenched butt cheeks.",
- "Coughing into a vagina.",
- "Cutting.",
- "Dancing with a broom.",
- "Deflowering a princess.",
- "Deflowering the princess.",
- "Dorito breath.",
- "Eating an albino.",
- "Enormous Scandinavian women.",
- "Fabricating statistics.",
- "Finding a skeleton.",
- "Gandalf.",
- "Genetically engineered super-soldiers.",
- "George Clooney's musk.",
- "Getting abducted by Peter Pan.",
- "Getting in her pants, politely.",
- "Gladiatorial combat.",
- "Good grammar.",
- "having a penis",
- "Hipsters.",
- "Historical revisionism.",
- "Insatiable bloodlust.",
- "Jafar.",
- "Jean-Claude Van Damme in slow motion.",
- "Jean-Claude Van Damme.",
- "Just the tip.",
- "Leveling up.",
- "Literally eating shit.",
- "Mad hacky-sack skills.",
- "Making the penises kiss.",
- "Media coverage.",
- "Medieval Times Dinner & Tournament.",
- "Mom.",
- "Moral ambiguity.",
- "My machete.",
- "Neil Patrick Harris.",
- "NOOOOOOOOO!!!",
- "Nubile slave boys.",
- "Ominous background music.",
- "One thousand Slim Jims.",
- "Overpowering your father.",
- "Panty raids.",
- "Pistol-whipping a hostage.",
- "Quiche.",
- "Quivering jowls.",
- "Revenge fucking.",
- "Ripping into a man's chest and pulling out his still-beating heart.",
- "Ryan Gosling riding in on a white horse.",
- "Salvia.",
- "Sanding off a man's nose.",
- "Santa Claus.",
- "Savagely beating a mascot",
- "Scrotum tickling.",
- "Sexual humiliation.",
- "Sexy Siamese twins.",
- "Shaft.",
- "Slow motion.",
- "Space muffins.",
- "Statistically validated stereotypes.",
- "Stockholm syndrome",
- "Sudden Poop Explosion Disease.",
- "Suicidal thoughts.",
- "Syphilitic insanity",
- "The boners of the elderly.",
- "The economy.",
- "The Fanta girls.",
- "The four arms of Vishnu.",
- "The gulags.",
- "The harsh light of day.",
- "The hiccups.",
- "The ooze",
- "The shambling corpse of Larry King.",
- "This guy!",
- "Tripping balls.",
- "Walking in on Dad peeing into Mom's mouth.",
- "Words, words, words.",
- "Zeus's sexual appetites.",
- "A 55-gallon drum of lube.",
- "A bigger, blacker dick.",
- "A Burmese tiger pit.",
- "A dollop of sour cream.",
- "A fortuitous turnip harvest.",
- "A magic hippie love cloud.",
- "A man in yoga pants with a ponytail and feather earrings.",
- "A piÒata full of scorpions",
- "A sad fat dragon with no friends.",
- "A slightly shittier parallel universe.",
- "A sofa that says \"I have style, but I like to be comfortable.\"",
- "A soulful rendition of \"Ol' Man River.\"",
- "A squadron of moles wearing aviator goggles.",
- "A sweaty, panting leather daddy.",
- "A sweet spaceship.",
- "All of this blood.",
- "An army of skeletons.",
- "An ether-soaked rag.",
- "An unhinged ferris wheel rolling toward the sea.",
- "Another shot of morphine.",
- "Basic human decency.",
- "Beefin' over turf.",
- "Being awesome at sex.",
- "Boris the Soviet Love Hammer.",
- "Bullshit.",
- "Catastrophic urethral trauma.",
- "Crushing Mr. Peanut's brittle body.",
- "Daddy's belt.",
- "Death by Steven Seagal.",
- "Dennis the Menace.",
- "Dining with cardboard cutouts of the cast of \"Friends.\"",
- "Double penetration.",
- "Existing.",
- "Fetal alcohol syndrome.",
- "Finding Waldo.",
- "Fuck Mountain.",
- "Getting hilariously gang-banged by the Blue Man Group.",
- "Grandpa's ashes.",
- "Graphic violence, adult language, and some sexual content.",
- "Hillary Clinton's death stare.",
- "Intimacy problems.",
- "Jeff Goldblum.",
- "Living in a trashcan.",
- "Loki, the trickster god.",
- "Making a friend.",
- "Maximal insertion.",
- "Me.",
- "Mild autism.",
- "Mooing.",
- "My first kill.",
- "Nunchuck moves.",
- "Oncoming traffic.",
- "One Ring to rule them all.",
- "Power",
- "Pretty Pretty Princess Board Game.",
- "Pumping out a baby every nine months.",
- "Rising from the grave.",
- "Scrotal frostbite.",
- "Some really fucked-up shit.",
- "Special musical guest, Cher.",
- "Spring break!",
- "Subduing a grizzly bear and making her your wife.",
- "Survivor's guilt.",
- "Swiftly achieving orgasm.",
- "Taking a man's eyes and balls out and putting his eyes where his balls go and then his balls in the eye holes.",
- "The black Power Ranger",
- "The corporations.",
- "The day the birds attacked.",
- "The Google.",
- "The grey nutrient broth that sustains Mitt Romney.",
- "The human body.",
- "The mere concept of Applebee's.",
- "The mixing of the races.",
- "The new Radiohead album.",
- "Tiny nipples.",
- "Tongue.",
- "Upgrading homeless people to mobile hotspots.",
- "Weapons-grade plutonium.",
- "Wearing an octopus for a hat.",
- "Whining like a little bitch.",
- "Whipping a disobedient slave.",
- "That ass.",
- "Nothing.",
- "Shutting the fuck up.",
- "The primal, ball-slapping sex your parents are having right now.",
- "A cat video so cute that your eyes roll back and your spine slides out of your anus.",
- "Cock.",
- "A cop who is also a dog.",
- "Dying alone and in pain.",
- "Gay aliens.",
- "The way white people is.",
- "Reverse cowgirl.",
- "The Quesadilla Explosion Salad from Chili's.",
- "Actually getting shot, for real.",
- "Not having sex.",
- "Vietnam flashbacks.",
- "Running naked through a mall, pissing and shitting everywhere.",
- "Warm, velvety muppet sex.",
- "Self-flagellation.",
- "The systematic destruction of an entire people and their way of life.",
- "Samuel L. Jackson.",
- "A boo-boo.",
- "Going around punching people.",
- "The entire Internet.",
- "Some kind of bird-man.",
- "Chugging a lava lamp.",
- "Having sex on top of a pizza.",
- "Indescribable loneliness.",
- "An ass disaster.",
- "All my friends dying.",
- "Putting an entire peanut butter and jelly sandwich into the VCR.",
- "Spending lots of money.",
- "Some douche with an acoustic guitar.",
- "Flying robots that kill people.",
- "A greased-up Matthew McConaughey.",
- "An unstoppable wave of fire ants.",
- "Not contributing to society in any meaningful way.",
- "An all-midget production of Shakespeare's Richard III.",
- "Screaming like a maniac.",
- "The moist, demanding chasm of his mouth.",
- "Filling every orifice with butterscotch pudding.",
- "Unlimited soup, salad, and breadsticks.",
- "Crying into the pages of Sylvia Plath.",
- "Velcro.",
- "A PowerPoint presentation.",
- "A surprising amount of hair.",
- "Eating Tom Selleck's mustache to gain his powers.",
- "Roland the Farter, flatulist to the king.",
- "A pile of squirming bodies.",
- "Buying the right pants to be, cool.",
- "Blood farts.",
- "Three months in the hole.",
- "A botched circumcision.",
- "The Land of Chocolate.",
- "Slapping a racist old lady.",
- "A lamprey swimming up the toilet and latching onto your taint.",
- "Jumping out at people.",
- "A black male in his early 20s, last seen wearing a hoodie.",
- "Mufasa's death scene.",
- "Bill Clinton, naked on a bearskin rug with a saxophone.",
- "Demonic possession.",
- "The Harlem Globetrotters.",
- "Vomiting mid-blowjob.",
- "My manservant, Claude.",
- "Having shotguns for legs.",
- "Letting everyone down.",
- "A spontaneous conga line.",
- "A vagina that leads to another dimension.",
- "Disco fever.",
- "Getting your dick stuck in a Chinese finger trap with another dick.",
- "Fisting.",
- "The thin veneer of situational causality that underlies porn.",
- "Girls that always be textin'.",
- "Blowing some dudes in an alley.",
- "Drinking ten 5-hour ENERGYs to get fifty continuous hours of energy.",
- "Sneezing, farting, and coming at the same time.",
- "A bunch of idiots playing a card game instead of interacting like normal humans.",
- "A sex goblin with a carnival penis.",
- "Lots and lots of abortions.",
- "Injecting speed into one arm and horse tranquilizer into the other.",
- "Sharks with legs.",
- "A sex comet from Neptune that plunges the Earth into eternal sexiness.",
- "How awesome I am.",
- "Smoking crack, for instance.",
- "A dance move that's just sex.",
- "A hopeless amount of spiders.",
- "Drinking responsibly.",
- "Angelheaded hipsters burning for the ancient heavenly connection to the starry dynamo in the machinery of the night.",
- "Bouncing up and down.",
- "A shiny rock that proves I love you.",
- "Crazy opium eyes.",
- "Moderate-to-severe joint pain.",
- "Actual mutants with medical conditions and no superpowers.",
- "The complex geopolitical quagmire that is the Middle East.",
- "Finally finishing off the Indians.",
- "Neil Diamond's Greatest Hits.",
- "No clothes on, penis in vagina.",
- "Whispering all sexy.",
- "A horse with no legs.",
- "Depression.",
- "Almost giving money to a homeless person.",
- "Interspecies marriage.",
- "Blackula.",
- "What Jesus would do.",
- "A manhole.",
- "My dad's dumb fucking face.",
- "A Ugandan warlord.",
- "My worthless son.",
- "A Native American who solves crimes by going into the spirit world.",
- "A kiss on the lips.",
- "A fart.",
- "The peaceful and nonthreatening rise of China.",
- "Snorting coke off a clown's boner.",
- "Three consecutive seconds of happiness.",
- "Falling into the toilet.",
- "Ass to mouth.",
- "Some sort of Asian.",
- "The size of my penis.",
- "The safe word.",
- "Party Mexicans.",
- "Ambiguous sarcasm.",
- "Jizz.",
- "An interracial handshake.",
- "Incredible Facts About the Anus.",
- "The secret formula for ultimate female satisfaction.",
- "Sugar madness.",
- "Calculating every mannerism so as not to suggest homosexuality.",
- "Fucking a corpse back to life.",
- "All the single ladies.",
- "Whatever a McRib is made of.",
- "Africa.",
- "The euphoric rush of strangling a drifter.",
- "Khakis.",
- "A gender identity that can only be conveyed through slam poetry.",
- "Stuffing a child's face with Fun Dip until he starts having fun.",
- "A for-real lizard that spits blood from its eyes.",
- "The tiniest shred of evidence that God is real.",
- "Prince Ali, fabulous he, Ali Ababwa.",
- "Dem titties.",
- "Exploding pigeons.",
- "My sex dungeon.",
- "Child Protective Services.",
- "Doo-doo.",
- "Sports.",
- "Unquestioning obedience.",
- "Grammar nazis who are also regular Nazis.",
- "40 acres and a mule.",
- "A crazy little thing called love.",
- "A disappointing salad.",
- "A face full of horse cum.",
- "A giant powdery manbaby.",
- "A mouthful of potato salad.",
- "A one-way ticket to Gary, Indiana.",
- "A powered exoskeleton.",
- "A reason not to commit suicide.",
- "A team of lawyers.",
- "A whole new kind of porn.",
- "A zero-risk way to make $2,000 from home.",
- "AIDS monkeys.",
- "All these decorative pillows.",
- "An unforgettable quinceanera.",
- "An uninterrupted history of imperialism and exploitation.",
- "Anal fissures like you wouldn't believe.",
- "Ancient Athenian boy-fucking.",
- "Backwards knees.",
- "Being nine years old.",
- "Being paralyzed from the neck down.",
- "Being worshiped as the one true God.",
- "Blackface.",
- "Blowjobs for everyone.",
- "Boring Vaginal sex.",
- "Butt stuff.",
- "Changing a person's mind with logic and facts.",
- "Child support payments.",
- "Cutting off a flamingo's legs with garden shears.",
- "Daddy's credit card.",
- "Deez nuts.",
- "Denzel.",
- "Doing the right stuff to her nipples.",
- "Ejaculating live bees and the bees are angry.",
- "Ennui.",
- "Figuring out how to have sex with a dolphin.",
- "Free ice cream, yo.",
- "Genghis Khan's DNA.",
- "Getting caught by the police and going to jail.",
- "Getting drive-by shot.",
- "Getting eaten alive by Guy Fieri.",
- "Giant sperm from outer space.",
- "Going to a high school reunion on ketamine.",
- "Having been dead a while.",
- "Mom's new boyfriend.",
- "My boyfriends stupid penis.",
- "My dead son's baseball glove.",
- "My first period.",
- "Not believing in giraffes.",
- "Oil!",
- "Out-of-this-world bazongas.",
- "P.F. Chang himself.",
- "Russian super-tuberculosis.",
- "Seeing my village burned and my family slaughtered before my eyes.",
- "Seeing things from Hitler's perspective.",
- "September 11th, 2001.",
- "Slowly easing down onto a cucumber.",
- "Social justice warriors with flamethrowers of compassion.",
- "Some shit-hot guitar licks.",
- "The Abercrombie & Fitch lifestyle.",
- "The basic suffering that pervades all of existence.",
- "The eight gay warlocks who dictate the rules of fashion.",
- "The ghost of Marlon Brando.",
- "The inability to form meaningful relationships.",
- "The passage of time.",
- "The swim team, all at once.",
- "The tiger that killed my father.",
- "The unbelievable world of mushrooms.",
- "The black half of Barack Obama.",
- "The white half of Barack Obama.",
- "Too much cocaine.",
- "Unrelenting genital punishment.",
- "Vegetarian options.",
- "Wearing glasses and sounding smart.",
- "Western standards of beauty.",
- "A bass drop so huge it tears the starry vault asunder to reveal the face of God.",
- "Growing up chained to a radiator in perpetual darkness.",
- "Shitting all over the floor like a bad, bad girl.",
- "A buttload of candy.",
- "Sucking all the milk out of a yak.",
- "Bullets.",
- "A man who is so cool that he rides on a motorcycle.",
- "Sudden penis loss.",
- "Getting all offended.",
- "Crying and shitting and eating spaghetti.",
- "One unforgettable night of passion.",
- "Being popular and good at sports.",
- "Filling a man's anus with concrete.",
- "Two whales fucking the shit out of each other.",
- "Cool, relatable cancer teens.",
- "The amount of gay I am.",
- "A possible Muslim.",
- "Unsheathing my massive horse cock.",
- "A bowl of gourds.",
- "The male gaze.",
- "The power of the Dark Side.",
- "Ripping a dog in half.",
- "A constant need for validation.",
- "Meaningless sex.",
- "Such a big boy.",
- "Throwing stones at a man until he dies.",
- "Cancer.",
- "Like a million alligators.",
- "Eating together like a god damn family for once.",
- "Cute boys.",
- "Pussy.",
- "Being a terrible mother.",
- "Never having sex again.",
- "A pizza guy who fucked up.",
- "A whole lotta woman.",
- "The all-new Nissan Pathfinder with 0.9% APR financing!",
- "A peyote-fueled vision quest.",
- "Kale.",
- "Breastfeeding a ten year old.",
- "Crippling social anxiety.",
- "Immortality cream.",
- "Texas.",
- "Teaching a girl how to handjob the penis.",
- "A turd.",
- "Shapes and colors.",
- "Whatever you wish, mother.",
- "The haunting stare of an Iraqi child.",
- "Robots who just want to party.",
- "A self-microwaving burrito.",
- "Forgetting grandma's first name.",
- "Our new Buffalo Chicken Dippers!",
- "Treasures beyond your wildest dreams.",
- "Getting shot out of a cannon.",
- "The sweet song of sword against sword and the braying of mighty war beasts.",
- "Walking into a glass door.",
- "The color \"puce.\"",
- "Every ounce of charisma left in Mick Jagger's tired body.",
- "The eighth graders.",
- "Setting my balls on fire and cartwheeling to Ohio.",
- "The dentist.",
- "Gwyneth Paltrow's opinions.",
- "Turning the rivers red with the blood of infidels.",
- "Rabies.",
- "Important news about Taylor Swift.",
- "Ejaculating inside another man's wife.",
- "Owls, the perfect predator.",
- "Being John Malkovich.",
- "Bathing in moonsblood and dancing around the ancient oak.",
- "An oppressed people with a vibrant culture.",
- "An overwhelming variety of cheeses.",
- "Reading the entire End-User License Agreement.",
- "Morpheus.",
- "Peeing into a girl's butt to make a baby.",
- "Generally having no idea what's going on.",
- "No longer finding any Cards Against Humanity card funny.",
- "Content.",
- "Fucking me good and taking me to Red Lobster.",
- "Self-identifying as a DJ.",
- "Getting high with mom.",
- "Beyonce.",
- "Gazpacho.",
- "Discovering that what I really want in life is to kill people and have sex with their corpses.",
- "A man with the head of a goat and the body of a goat.",
- "How good lead paint taste.",
- "Dropping dead in a Sbarro's bathroom and not being found for 72 hours.",
- "Eating too many Cinnabons and then vomiting and then eating the vomit.",
- "Some of that good dick.",
- "Two shitty kids and a garbage husband.",
- "Pooping in the potty.",
- "Bad emotions I don't want.",
- "Mixing M&Ms and Skittles like some kind of psychopath.",
- "Fucking my therapist.",
- "The best, deepest quotes from The Dark Knight.",
- "Meatloaf, the man.",
- "Meatloaf, the food.",
- "My huge penis and substantial fortune.",
- "Hot lettuce.",
- "It being too late to stop having sex with a horse.",
- "Becoming the President of the United States.",
- "Microaggressions.",
- "Getting the Dorito crumbs out of my purse.",
- "The sweet, forbidden meat of the monkey.",
- "Consensual, nonreproductive incest.",
- "Grunting for ten minutes and then peeing sand.",
- "Prematurely ejaculating like a total loser.",
- "Jazz.",
- "Straight blazin' 24/7.",
- "Having sex with a beautiful person.",
- "Going around pulling people's tampons out.",
- "Reaching an age where barbecue chips are better than sex.",
- "Daddy going away forever.",
- "Three hours of nonstop penetration.",
- "Holding the proper political beliefs of my time to attract a mate.",
- "Scissoring, if that's a thing.",
- "Creamy slices of real, California avocado.",
- "ISIS.",
- "A weird guy who says weird stuff and weirds me out.",
- "Rubbing my bush all over your bald head.",
- "Farting all over my face with your tight little asshole.",
- "Quinoa.",
- "How sad it will be when Morgan Freeman dies.",
- "A cheerfulness that belies a deep-seated self-loathing.",
- "Farting a huge shit out of my pussy.",
- "Defeating a gorilla in single combat.",
- "A big ol' plate of fettuccine alfredo.",
- "Brunch.",
- "Anal.",
- "A women's perspective.",
- "A long business meeting with no obvious purpose.",
- "Thinking about what eating even is.",
- "Doing a somersault and barfing.",
- "Trees.",
- "Hating Jews.",
- "Whooping your ass at Mario Kart.",
- "A massive collection of child pornography.",
- "Systems and policies designed to preserve centuries-old power structures.",
- "Having an awesome time drinking and driving.",
- "Muchin' puss.",
- "Moon people.",
- "Picking up a glass of water and taking a sip and being the president.",
- "Critical thinking.",
- "Showing all the boys my pussy.",
- "Homework.",
- "China.",
- "Putting more black people in jail.",
- "The ol' penis-in-the-popcorn surprise.",
- "One of them big-city Jew lawyers.",
- "Informing you that I am a registered sex offender.",
- "Rolling so hard.",
- "Who really did 9\/11.",
- "Being turned into sausages.",
- "Eating ass.",
- "A dolphin that learns to talk and becomes the Dead of Harvard Law School.",
- "Gay thoughts.",
- "My dog dying.",
- "Dominating a man by peeing on his eldest son.",
- "Dis bitch.",
- "A strong horse and enough rations for thirty days.",
- "Feminism.",
- "A cold and indifferent universe.",
- "An incurable homosexual.",
- "The amount of baby carrots I can fit up my ass.",
- "Huge big balls full of jizz.",
- "Gregor, my largest son.",
- "Esmeralda, my most beautiful daughter.",
- "Trevor, the world's greatest boyfriend.",
- "Jason, the teen mayor.",
- "That bitch, Stacy.",
- "Gayle from HR.",
- "Gary.",
- "Just now finding out about the Armenian Genocide.",
- "Opening your mouth to talk and a big penis fops out.",
- "Twisting my cock and balls into a balloon poodle.",
- "The wind.",
- "A gun that shoots cobras.",
- "Out-of-control teenage blowjob parties.",
- "A black friend.",
- "The body of a 46-year-old man.",
- "Art.",
- "Water.",
- "Doritos and a Fruit Roll-Up.",
- "Sucking each other's penises for hours on end.",
- "10,000 shrieking teenage girls.",
- "Whomsoever let the dogs out.",
- "The chicken from Popeyes.",
- "Assassinating the president.",
- "Having sex with a man and then eating his head.",
- "A burrito that's just sour cream.",
- "An arrangement wherein I give a person money they have sex with me.",
- "Facilitating dialogue and deconstructing binaries.",
- "Taking the form of a falcon.",
- "Watching you die.",
- "An X-Man whose power is that he has sex with dogs and children.",
- "Loud, scary thunder.",
- "Every man's ultimate fantasy: a perfectly cylindrical vagina.",
- "Tiny, rancid girl farts.",
- "Math.",
- "Founding a major world religion.",
- "Plowing that ass like a New England corn farmer.",
- "Period poops.",
- "The feeling of going to McDonald's as a 6-year-old.",
- "Misogyny.",
- "Tables.",
- "Feeling the emotion of anger.",
- "One of those \"blow jobs\" I've been hearing so much about.",
- "A creepy child singing a nursery rhyme.",
- "Blossoming into a beautiful young woman.",
- "The secret to truly resilient hair.",
- "Rock-hard tits and a huge vagina.",
- "The lived experience of African Americans.",
- "Mental illness.",
- "Getting eaten out by a dog.",
- "10 football players with erections barreling towards you at full speed.",
- "Starting a shitty podcast.",
- "Overthrowing the democratically-elected government of Chile.",
- "Guns.",
- "A hug.",
- "Getting aborted.",
- "Crazy anal orgasms.",
- "Getting this party started!",
- "Being sexually attracted to children.",
- "Antidepressants.",
- "Getting trapped in a conversation about Ayn Rand.",
- "Swearing praise upon the Sultan's hideous daughters.",
- "Turning 32.",
- "Sudden and unwanted slam poetry.",
- "A negative body image that is totally justified.",
- "Exploring each other's buttholes.",
- "You.",
- "Quacking like a duck in lieu of a cogent argument.",
- "Catching a live salmon in your mouth.",
- "Eating people.",
- "Our baby.",
- "Breastfeeding in public like a radiant earth goddess.",
- "Big, smart money boys tap-tapping on their keyboards.",
- "Finding a nice elevator to poop in.",
- "The mysterious fog rolling into town.",
- "Two beautiful pig sisters.",
- "Condoleezza Rice.",
- "The full force of the American military.",
- "A woman's right to choose.",
- "A terrified fat child who won't come out of the bushes.",
- "A medium horchata.",
- "How great my ass looks in these jeans.",
- "Raising three kids on minimum wage.",
- "The bond between a woman and her horse.",
- "Slamming a dunk.",
- "Chris Hemsworth.",
- "Ejaculating at the apex of a cartwheel.",
- "Child labor.",
- "An older man.",
- "Crushing the patriarchy.",
- "Denying the Holocaust.",
- "Falling into a pit of waffles.",
- "Objectifying women.",
- "Everything.",
- "A creature made of penises that must constantly arouse itself to survive.",
- "Getting blasted in the face by a t-shirt cannon.",
- "Onions.",
- "Dumpster juice.",
- "Forty-five minutes of finger blasting.",
- "Film roles for actresses over 40.",
- "Having sex with your mom.",
- "Having a vagina.",
- "Regurgitating a half-digested sparrow.",
- "The hottest MILF in Dallas.",
- "Some real spicy shrimps.",
- "The Rwandan Genocide.",
- "The LGBT community.",
- "Twenty bucks.",
- "The full blown marginalization of ugly people.",
- "A finger up the butt.",
- "A big, beautiful mouth packed to the brim with sparkling teeth.",
- "Getting laid like all the time.",
- "Happy daddies with happy sandals.",
- "Libertarians.",
- "Late-stage dementia.",
- "How strange it is to be anything at all.",
- "Pooping in a leotard and hoping no one notices.",
- "Restoring Germany to its former glory.",
- "Participating.",
- "Going to bed at a reasonable hour.",
- "Smashing my balls at the moment of climax.",
- "Making out and stuff.",
- "Menopause.",
- "The government.",
- "The graceful path of an autumn leaf as it falls to its earthen cradle.",
- "Tender chunks of all-white-meat chicken.",
- "Twenty cheerleaders laughing at your tiny penis.",
- "Mommy and daddy fighting all the time.",
- "Playing my asshole like a trumpet.",
- "Getting naked too soon.",
- "A slowly encroaching circle of wolves.",
- "A man in a suit with perfect hair who tells you beautiful lies.",
- "Seizing control of the means of production.",
- "Comprehensive immigration reform.",
- "Awesome pictures of planets and stuff.",
- "Aborting the shit out of a fetus.",
- "A genetic predisposition for alcoholism.",
- "The flaming wreckage of the International Space Station.",
- "Waking up inside of a tornado.",
- "When the big truck goes \"Toot! Toot!\"",
- "The fear and hatred in men's hearts.",
- "Getting killed and dragged up a tree by a leopard.",
- "Eternal screaming madness.",
- "My brother's hot friends.",
- "Salsa Night at Dave's Cantina.",
- "The clown that followed me home from the grocery store.",
- "Watching a hot person eat.",
- "Pretending to be one of the guys but actually being the spider god.",
- "Getting pegged.",
- "An empowered woman.",
- "An old dog full of tumors.",
- "A duffel bag full of lizards.",
- "All these people I've killed.",
- "Working so hard to have muscles and then having them.",
- "Political correctness.",
- "A tiny fireman who puts out tiny fires.",
- "Albert Einstein but if he had a huge muscles and a rhinoceros cock.",
- "Chipotle."
- ]
-}
diff --git a/cah/info.json b/cah/info.json
deleted file mode 100644
index 9e1351f..0000000
--- a/cah/info.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "AUTHOR" : "aikaterna",
- "INSTALL_MSG" : "Thanks for installing Cards Against Humanity. I highly advise only playing this game with 3-4 people on one server, on a private bot, because of the high amount of DM's this game generates.",
- "NAME" : "cah",
- "SHORT" : "Cards Against Humanity.",
- "DESCRIPTION" : "This cog was made possible by CorpBot: https://github.com/corpnewt/CorpBot.py"
-}
diff --git a/chatchart/chatchart.py b/chatchart/chatchart.py
deleted file mode 100644
index d337892..0000000
--- a/chatchart/chatchart.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# Lines 54 through 68 are influenced heavily by cacobot's stats module:
-# https://github.com/Orangestar12/cacobot/blob/master/cacobot/stats.py
-# Big thanks to Redjumpman for changing the beta version from
-# Imagemagick/cairosvg to matplotlib.
-# Thanks to violetnyte for suggesting this cog.
-import discord
-import heapq
-import os
-from io import BytesIO
-import matplotlib
-matplotlib.use('agg')
-import matplotlib.pyplot as plt
-plt.switch_backend('agg')
-from discord.ext import commands
-
-
-class ChatChart:
- """Show activity."""
-
- def __init__(self, bot):
- self.bot = bot
-
- def create_chart(self, top, others):
- plt.clf()
- sizes = [x[1] for x in top]
- labels = ["{} {:g}%".format(x[0], x[1]) for x in top]
- if len(top) >= 10:
- sizes = sizes + [others]
- labels = labels + ["Others {:g}%".format(others)]
-
- title = plt.title('User activity in the last 5000 messages')
- title.set_va("top")
- title.set_ha("left")
- plt.gca().axis("equal")
- colors = ['r', 'darkorange', 'gold', 'y', 'olivedrab', 'green', 'darkcyan', 'mediumblue', 'darkblue', 'blueviolet', 'indigo']
- pie = plt.pie(sizes, colors=colors, startangle=0)
- plt.legend(pie[0], labels, bbox_to_anchor=(0.7, 0.5), loc="center", fontsize=10,
- bbox_transform=plt.gcf().transFigure)
- plt.subplots_adjust(left=0.0, bottom=0.1, right=0.45)
- image_object = BytesIO()
- plt.savefig(image_object, format='PNG')
- image_object.seek(0)
- return image_object
-
- @commands.command(pass_context=True)
- @commands.cooldown(1, 10, commands.BucketType.channel)
- async def chatchart(self, ctx):
- """
- Generates a pie chart, representing the last 5000 messages in this channel.
- """
- channel = ctx.message.channel
- e = discord.Embed(description="Loading...", colour=0x00ccff)
- e.set_thumbnail(url="https://i.imgur.com/vSp4xRk.gif")
- em = await self.bot.say(embed=e)
-
- history = []
- async for msg in self.bot.logs_from(channel, 5000):
- history.append(msg)
- msg_data = {'total count': 0, 'users': {}}
-
- for msg in history:
- if msg.author.bot:
- pass
- elif msg.author.name in msg_data['users']:
- msg_data['users'][msg.author.name]['msgcount'] += 1
- msg_data['total count'] += 1
- else:
- msg_data['users'][msg.author.name] = {}
- msg_data['users'][msg.author.name]['msgcount'] = 1
- msg_data['total count'] += 1
-
- for usr in msg_data['users']:
- pd = float(msg_data['users'][usr]['msgcount']) / float(msg_data['total count'])
- msg_data['users'][usr]['percent'] = round(pd * 100, 1)
-
- top_ten = heapq.nlargest(10, [(x, msg_data['users'][x][y])
- for x in msg_data['users']
- for y in msg_data['users'][x]
- if y == 'percent'], key=lambda x: x[1])
- others = 100 - sum(x[1] for x in top_ten)
- img = self.create_chart(top_ten, others)
- await self.bot.delete_message(em)
- await self.bot.send_file(channel, img, filename="chart.png")
-
-
-def check_folders():
- if not os.path.exists("data/chatchart"):
- print("Creating data/chatchart folder...")
- os.makedirs("data/chatchart")
-
-
-def setup(bot):
- check_folders()
- bot.add_cog(ChatChart(bot))
diff --git a/chatchart/info.json b/chatchart/info.json
deleted file mode 100644
index 1e380b9..0000000
--- a/chatchart/info.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "AUTHOR" : "aikaterna and Redjumpman",
- "INSTALL_MSG" : "Use [p]chatchart to generate a chart for that channel.",
- "NAME" : "chatchart",
- "SHORT" : "Generate a pie chart from the last 5000 messages.",
- "DESCRIPTION" : "Generate a pie chart from the last 5000 messages in a channel to see who's been talking the most.",
- "REQUIREMENTS": ["matplotlib"],
- "TAGS": ["data", "chart", "activity"]
-}
diff --git a/forwarding/forwarding.py b/forwarding/forwarding.py
deleted file mode 100644
index 1239dff..0000000
--- a/forwarding/forwarding.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# forwarding.py is ported from another bot:
-# https://github.com/jacobcheatley/dankbot
-
-import discord
-from discord.ext import commands
-from .utils.dataIO import dataIO
-from .utils import checks
-
-
-class Forwarding:
- def __init__(self, bot: commands.Bot):
- self.bot = bot
- self.owner = self.get_owner()
-
- def get_owner(self):
- owner_id = dataIO.load_json("data/red/settings.json")["OWNER"]
- return discord.utils.find(lambda m: m.id == owner_id, self.bot.get_all_members())
-
- async def send_to_owner(self, **kwargs):
- if self.owner is None:
- self.owner = self.get_owner()
- await self.bot.send_message(self.owner, **kwargs)
-
- async def on_message(self, message: discord.Message):
- if self.owner is None:
- self.owner = self.get_owner()
- if not message.channel.is_private or message.channel.user.id == self.owner.id:
- return
-
- embed = discord.Embed()
- if message.author == self.bot.user:
- embed.title = 'Sent PM to {}#{} ({}).'.format(message.channel.user.name, message.channel.user.discriminator, message.channel.user.id)
- else:
- embed.set_author(name=message.author, icon_url=message.author.avatar_url or message.author.default_avatar_url)
- embed.title = '{} messaged me:'.format(message.channel.user.id)
- embed.description = message.content
- embed.timestamp = message.timestamp
-
- await self.send_to_owner(embed=embed)
-
- @commands.command()
- @checks.is_owner()
- async def pm(self, user: discord.User, *, content: str):
- """PMs a person."""
- await self.bot.send_message(user, content)
-
-
-def setup(bot):
- bot.add_cog(Forwarding(bot))
diff --git a/forwarding/info.json b/forwarding/info.json
deleted file mode 100644
index b040c7d..0000000
--- a/forwarding/info.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "AUTHOR" : "aikaterna",
- "NAME" : "forwarding",
- "SHORT" : "Forwards DMs sent to the bot to the owner.",
- "DESCRIPTION" : "Forwards DMs sent to the bot to the owner.",
- "TAGS": ["message", "dm"]
-}
diff --git a/hunting/hunting.py b/hunting/hunting.py
deleted file mode 100644
index ae38cc8..0000000
--- a/hunting/hunting.py
+++ /dev/null
@@ -1,240 +0,0 @@
-from __main__ import send_cmd_help
-from .utils.dataIO import dataIO
-from discord.ext import commands
-from .utils import checks
-import datetime
-import asyncio
-import discord
-import random
-import time
-import os
-
-# TODO
-# Show error when timing intervals are the same
-
-
-class Hunting:
- def __init__(self, bot):
- self.bot = bot
- self.scores = dataIO.load_json('data/hunting/scores.json')
- self.subscriptions = dataIO.load_json('data/hunting/subscriptions.json')
- self.settings = dataIO.load_json('data/hunting/settings.json')
- self.animals = {'duck': ':duck: **_Quack!_**', 'penguin': ':penguin: **_Noot!_**', 'chicken': ':rooster: **_Bah-gawk!_**', 'pigeon': ':dove: **_Coo!_**'}
- self.in_game = []
- self.paused_games = []
- self._latest_message_check_message_limit = 5
- self._latest_message_check_wait_limit = self.settings['hunt_interval_maximum'] * 2
- self.next = None
-
- async def _save_scores(self):
- dataIO.save_json('data/hunting/scores.json', self.scores)
-
- async def _save_subscriptions(self):
- dataIO.save_json('data/hunting/subscriptions.json', self.subscriptions)
-
- async def _save_settings(self):
- dataIO.save_json('data/hunting/settings.json', self.settings)
-
- @commands.group(pass_context=True, no_pm=True, name='hunting')
- async def _hunting(self, context):
- """Hunting, it hunts birds... and things that fly"""
- if context.invoked_subcommand is None:
- await send_cmd_help(context)
-
- @_hunting.command(pass_context=True, no_pm=True, name='start')
- async def _start(self, context):
- """Start the hunt"""
- server = context.message.server
- channel = context.message.channel
- if server.id in self.subscriptions:
- message = '**We\'re already hunting!**'
- else:
- self.subscriptions[server.id] = channel.id
- message = '**The hunt has started. Good luck to all.**'
- await self._save_subscriptions()
- await self.bot.say(message)
-
- @_hunting.command(pass_context=True, no_pm=True, name='stop')
- async def _stop(self, context):
- """Stop the hunt"""
- server = context.message.server
- if server.id not in self.subscriptions:
- message = '**We\'re not hunting!**'
- else:
- del self.subscriptions[server.id]
- message = '**The hunt has stopped.**'
- await self._save_subscriptions()
- await self.bot.say(message)
-
- @_hunting.command(no_pm=True, name='timing')
- @checks.is_owner()
- async def _timing(self, interval_min: int, interval_max: int, bang_timeout: int):
- """Change the timing"""
- if interval_min > interval_max:
- message = '**`interval_min` needs to be lower than `interval_max`**'
- elif interval_min < 0 and interval_max < 0 and bang_timeout < 0:
- message = '**Please no negative numbers!**'
- elif interval_min == interval_max:
- message = '**`interval_min` and `interval_max` cannot be the same**'
- else:
- self.settings['hunt_interval_minimum'] = interval_min
- self.settings['hunt_interval_maximum'] = interval_max
- self.settings['wait_for_bang_timeout'] = bang_timeout
- await self._save_settings()
- message = '**Timing has been set.**'
- await self.bot.say(message)
-
- @_hunting.command(pass_context=True, no_pm=True, name='next')
- @checks.is_owner()
- async def _next(self, context):
- """When will the next occurance happen?"""
- if self.next:
- time = abs(datetime.datetime.utcnow() - self.next)
- total_seconds = int(time.total_seconds())
- hours, remainder = divmod(total_seconds, 60*60)
- minutes, seconds = divmod(remainder, 60)
- message = '**The next occurance will be in {} hours and {} minutes.**'.format(hours, minutes)
- else:
- message = '**There is currently no hunt.**'
- await self.bot.say(message)
-
- @_hunting.command(pass_context=True, no_pm=True, name='score')
- async def _score(self, context, member: discord.Member):
- """This will show the score of a hunter"""
- server = context.message.server
- if server.id in self.scores:
- if member.id in self.scores[server.id]:
- message = '**{} shot a total of {} animals ({})**'.format(member.mention, self.scores[server.id][member.id]['total'], ', '.join([str(self.scores[server.id][member.id]['score'][x]) + ' ' + x.capitalize() + 's' for x in self.scores[server.id][member.id]['score']])) # (', '.join([str(self.scores[server.id][member.id]['score'][x]) + ' ' + x.capitalize() + 's' for x in self.scores[server.id][member.id]['score']]))
- else:
- message = '**Please shoot something before you can brag about it.**'
- else:
- message = '**Please shoot something before you can brag about it.**'
- await self.bot.say(message)
-
- @_hunting.command(pass_context=True, no_pm=True, name='clearscore')
- @checks.serverowner()
- async def _clearscore(self, context):
- """Clear the leaderboard"""
- server = context.message.server
- if server.id in self.scores:
- self.scores[server.id] = {}
- await self._save_scores()
- message = 'Leaderboard is cleared'
- else:
- message = 'There\'s nothing to clear'
- await self.bot.say(message)
-
- @_hunting.command(pass_context=True, no_pm=True, name='leaderboard', aliases=['scores'])
- async def _huntingboard(self, context):
- """This will show the top hunters on this server"""
- server = context.message.server
- if server.id in self.scores:
- p = self.scores[server.id]
- scores = sorted(p, key=lambda x: (p[x]['total']), reverse=True)
- message = '```\n{:<4}{:<8}{}\n\n'.format('#', 'TOTAL', 'USERNAME')
- for i, hunter in enumerate(scores, 1):
- if i > 10:
- break
- message += '{:<4}{:<8}{} ({})\n'.format(i, p[hunter]['total'], p[hunter]['author_name'], ', '.join([str(p[hunter]['score'][x]) + ' ' + x.capitalize() + 's' for x in p[hunter]['score']]))
- message += '```'
- else:
- message = '**Please shoot something before you can brag about it.**'
- await self.bot.say(message)
-
- async def add_score(self, server, author, avian):
- if server.id not in self.scores:
- self.scores[server.id] = {}
- if author.id not in self.scores[server.id]:
- self.scores[server.id][author.id] = {}
- self.scores[server.id][author.id]['score'] = {}
- self.scores[server.id][author.id]['total'] = 0
- self.scores[server.id][author.id]['author_name'] = ''
- for a in list(self.animals.keys()):
- self.scores[server.id][author.id]['score'][a] = 0
- if avian not in self.scores[server.id][author.id]['score']:
- self.scores[server.id][author.id]['score'][avian] = 0
- self.scores[server.id][author.id]['author_name'] = author.display_name
- self.scores[server.id][author.id]['score'][avian] += 1
- self.scores[server.id][author.id]['total'] += 1
- await self._save_scores()
-
- async def _wait_for_bang(self, server, channel):
- def check(message):
- return message.content.lower().split(' ')[0] == 'bang' or message.content.lower() == 'b' if message.content else False
-
- animal = random.choice(list(self.animals.keys()))
- await self.bot.send_message(channel, self.animals[animal])
- message = await self.bot.wait_for_message(channel=channel, timeout=self.settings['wait_for_bang_timeout'], check=check)
- if message:
- author = message.author
- if random.randrange(0, 17) > 1:
- await self.add_score(server, author, animal)
- msg = '**{} shot a {}!**'.format(author.mention, animal)
- else:
- msg = '**{} missed the shot and the {} got away!**'.format(author.mention, animal)
- else:
- msg = '**The {} got away!** :confused:'.format(animal)
- self.in_game.remove(channel.id)
- await self.bot.send_message(channel, msg)
-
- async def _latest_message_check(self, channel):
- async for message in self.bot.logs_from(channel, limit=self._latest_message_check_message_limit, reverse=True):
- delta = datetime.datetime.utcnow() - message.timestamp
- if delta.total_seconds() < self._latest_message_check_wait_limit and message.author.id != self.bot.user.id:
- if channel.id in self.paused_games:
- self.paused_games.remove(channel.id)
- return True
- if channel.id not in self.paused_games:
- self.paused_games.append(channel.id)
- await self.bot.send_message(channel, '**It seems there are no hunters here. The hunt will be resumed when someone treads here again.**')
- return False
-
- async def _hunting_loop(self):
- while self == self.bot.get_cog('Hunting'):
- wait_time = random.randrange(self.settings['hunt_interval_minimum'], self.settings['hunt_interval_maximum'])
- self.next = datetime.datetime.fromtimestamp(int(time.mktime(datetime.datetime.utcnow().timetuple())) + wait_time)
- await asyncio.sleep(wait_time)
- for server in self.subscriptions:
- if self.subscriptions[server] not in self.in_game:
- channel = self.bot.get_channel(self.subscriptions[server])
- server = self.bot.get_server(server)
- if await self._latest_message_check(channel):
- self.in_game.append(self.subscriptions[server.id])
- self.bot.loop = asyncio.get_event_loop()
- self.bot.loop.create_task(self._wait_for_bang(server, channel))
-
-
-def check_folder():
- if not os.path.exists('data/hunting'):
- print('Creating data/hunting folder...')
- os.makedirs('data/hunting')
-
-
-def check_files():
- f = 'data/hunting/settings.json'
- if not dataIO.is_valid_json(f):
- print('Creating empty settings.json...')
- data = {}
- data['hunt_interval_minimum'] = 300
- data['hunt_interval_maximum'] = 600
- data['wait_for_bang_timeout'] = 30
- dataIO.save_json(f, data)
-
- f = 'data/hunting/subscriptions.json'
- if not dataIO.is_valid_json(f):
- print('Creating empty subscriptions.json...')
- dataIO.save_json(f, {})
-
- f = 'data/hunting/scores.json'
- if not dataIO.is_valid_json(f):
- print('Creating empty scores.json...')
- dataIO.save_json(f, {})
-
-
-def setup(bot):
- check_folder()
- check_files()
- cog = Hunting(bot)
- loop = asyncio.get_event_loop()
- loop.create_task(cog._hunting_loop())
- bot.add_cog(cog)
diff --git a/hunting/info.json b/hunting/info.json
deleted file mode 100644
index 32d2ee7..0000000
--- a/hunting/info.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "AUTHOR" : "Paddolicious#8880",
- "NAME" : "Hunting",
- "SHORT" : "Hunting, it hunts birds... and things that fly",
- "DESCRIPTION" : "Hunting, it hunts birds... and things that fly",
- "TAGS": ["Hunting", "hunt", "birds", "paddo"]
-}
diff --git a/imgwelcome/data/fonts/UniSansHeavy.otf b/imgwelcome/data/fonts/UniSansHeavy.otf
deleted file mode 100644
index facd333..0000000
Binary files a/imgwelcome/data/fonts/UniSansHeavy.otf and /dev/null differ
diff --git a/imgwelcome/data/noimage.png b/imgwelcome/data/noimage.png
deleted file mode 100644
index 77e494f..0000000
Binary files a/imgwelcome/data/noimage.png and /dev/null differ
diff --git a/imgwelcome/data/transparent.png b/imgwelcome/data/transparent.png
deleted file mode 100644
index bf2672c..0000000
Binary files a/imgwelcome/data/transparent.png and /dev/null differ
diff --git a/imgwelcome/imgwelcome.py b/imgwelcome/imgwelcome.py
deleted file mode 100644
index 52751cf..0000000
--- a/imgwelcome/imgwelcome.py
+++ /dev/null
@@ -1,615 +0,0 @@
-# _is_hex, _hex_to_rgb, _rgb_to_hex are from Stevy's leveler.py
-# Also thanks to Stevy for nice, smooth circles.
-# https://github.com/AznStevy/Maybe-Useful-Cogs
-# imgwelcomeset_upload is based on code in orels' drawing.py
-# https://github.com/orels1/ORELS-Cogs
-# Parts of _create_welcome and on_member_join are from the Welcomer bot:
-# https://discordbots.org/bot/330416853971107840
-# Font switcher, font outline, and bonus text announcement toggles
-# thanks to Sitryk.
-# Font listing from FlapJack + aikaterna's yet unpublished wordcloud cog.
-import asyncio
-import aiohttp
-import datetime
-import discord
-import os
-import re
-import time
-from __main__ import send_cmd_help
-from cogs.utils.dataIO import dataIO
-from cogs.utils import checks
-from copy import deepcopy
-from discord.ext import commands
-from io import BytesIO
-from PIL import Image, ImageFont, ImageOps, ImageDraw
-
-
-default_settings = {"ANNOUNCE": False,
- "BACKGROUND": "data/imgwelcome/transparent.png",
- "BONUSES": {"ACCOUNT_WARNINGS": True,
- "SPECIAL_USERS": True
- },
- "BORDER": [255, 255, 255, 230],
- "CHANNEL": None,
- "OUTLINE": [0, 0, 0, 255],
- "SERVERTEXT": [255, 255, 255, 230],
- "TEXT": [255, 255, 255, 230],
- "FONT": {"WELCOME_FONT": {"PATH": "data/imgwelcome/fonts/UniSansHeavy.otf",
- "SIZE": 50},
- "SERVER_FONT": {"PATH": "data/imgwelcome/fonts/UniSansHeavy.otf",
- "SIZE": 20},
- "NAME_FONT": {"PATH": "data/imgwelcome/fonts/UniSansHeavy.otf",
- "SIZE": {"NORMAL": 30,
- "MEDIUM": 22,
- "SMALL": 18,
- "SMALLEST": 12
- }
- }
- }
- }
-
-
-class ImgWelcome:
- """Welcomes a user to the server with an image."""
-
- def __init__(self, bot):
- self.bot = bot
- self.settings = dataIO.load_json('data/imgwelcome/settings.json')
- self.version = "0.1.6"
-
- async def save_settings(self):
- dataIO.save_json('data/imgwelcome/settings.json', self.settings)
-
- async def _create_welcome(self, member, url, test_member_number: int = None):
- server = member.server
- wfont = self.settings[server.id]["FONT"]["WELCOME_FONT"]
- sfont = self.settings[server.id]["FONT"]["SERVER_FONT"]
- nfont = self.settings[server.id]["FONT"]["NAME_FONT"]
- welcome_font = ImageFont.truetype(wfont["PATH"], wfont["SIZE"])
- server_font = ImageFont.truetype(sfont["PATH"], sfont["SIZE"])
-
- name_font = ImageFont.truetype(nfont["PATH"], nfont["SIZE"]["NORMAL"])
- name_font_medium = ImageFont.truetype(nfont["PATH"], nfont["SIZE"]["MEDIUM"])
- name_font_small = ImageFont.truetype(nfont["PATH"], nfont["SIZE"]["SMALL"])
- name_font_smallest = ImageFont.truetype(nfont["PATH"], nfont["SIZE"]["SMALLEST"])
- background = Image.open(self.settings[server.id]["BACKGROUND"]).convert('RGBA')
- no_profile_picture = Image.open("data/imgwelcome/noimage.png")
-
- global welcome_picture
- welcome_picture = Image.new("RGBA", (500, 150))
- welcome_picture = ImageOps.fit(background, (500, 150), centering=(0.5, 0.5))
- welcome_picture.paste(background)
- welcome_picture = welcome_picture.resize((500, 150), Image.NEAREST)
-
- profile_area = Image.new("L", (512, 512), 0)
- draw = ImageDraw.Draw(profile_area)
- draw.ellipse(((0, 0), (512, 512)), fill=255)
- circle_img_size = tuple(self.settings[member.server.id]["CIRCLE"])
- profile_area = profile_area.resize((circle_img_size), Image.ANTIALIAS)
- try:
- url = url.replace('webp?size=1024', 'png')
- url = url.replace('gif?size=1024', 'png')
- await self._get_profile(url)
- profile_picture = Image.open('data/imgwelcome/profilepic.png')
- except:
- profile_picture = no_profile_picture
- profile_area_output = ImageOps.fit(profile_picture, (circle_img_size), centering=(0, 0))
- profile_area_output.putalpha(profile_area)
-
- bordercolor = tuple(self.settings[member.server.id]["BORDER"])
- fontcolor = tuple(self.settings[member.server.id]["TEXT"])
- servercolor = tuple(self.settings[member.server.id]["SERVERTEXT"])
- textoutline = tuple(self.settings[server.id]["OUTLINE"])
-
- mask = Image.new('L', (512, 512), 0)
- draw_thumb = ImageDraw.Draw(mask)
- draw_thumb.ellipse((0, 0) + (512, 512), fill=255, outline=0)
- circle = Image.new("RGBA", (512, 512))
- draw_circle = ImageDraw.Draw(circle)
- draw_circle.ellipse([0, 0, 512, 512], fill=(bordercolor[0], bordercolor[1], bordercolor[2], 180), outline=(255, 255, 255, 250))
- circle_border_size = await self._circle_border(circle_img_size)
- circle = circle.resize((circle_border_size), Image.ANTIALIAS)
- circle_mask = mask.resize((circle_border_size), Image.ANTIALIAS)
- circle_pos = (7 + int((136 - circle_border_size[0]) / 2))
- border_pos = (11 + int((136 - circle_border_size[0]) / 2))
- drawtwo = ImageDraw.Draw(welcome_picture)
- welcome_picture.paste(circle, (circle_pos, circle_pos), circle_mask)
- welcome_picture.paste(profile_area_output, (border_pos, border_pos), profile_area_output)
-
- uname = (str(member.name) + "#" + str(member.discriminator))
-
- def _outline(original_position: tuple, text: str, pixel_displacement: int, font, textoutline):
- op = original_position
- pd = pixel_displacement
-
- left = (op[0] - pd, op[1])
- right = (op[0] + pd, op[1])
- up = (op[0], op[1] - pd)
- down = (op[0], op[1] + pd)
-
- drawtwo.text(left, text, font=font, fill=(textoutline))
- drawtwo.text(right, text, font=font, fill=(textoutline))
- drawtwo.text(up, text, font=font, fill=(textoutline))
- drawtwo.text(down, text, font=font, fill=(textoutline))
-
- drawtwo.text(op, text, font=font, fill=(textoutline))
-
- _outline((150, 16), "Welcome", 1, welcome_font, (textoutline))
- drawtwo.text((150, 16), "Welcome", font=welcome_font, fill=(fontcolor))
-
- if len(uname) <= 17:
- _outline((152, 63), uname, 1, name_font, (textoutline))
- drawtwo.text((152, 63), uname, font=name_font, fill=(fontcolor))
-
- if len(uname) > 17:
- if len(uname) <= 23:
- _outline((152, 66), uname, 1, name_font_medium, (textoutline))
- drawtwo.text((152, 66), uname, font=name_font_medium, fill=(fontcolor))
-
- if len(uname) >= 24:
- if len(uname) <= 32:
- _outline((152, 70), uname, 1, name_font_small, (textoutline))
- drawtwo.text((152, 70), uname, font=name_font_small, fill=(fontcolor))
-
- if len(uname) >= 33:
- drawtwo.text((152, 73), uname, 1, name_font_smallest, (textoutline))
- drawtwo.text((152, 73), uname, font=name_font_smallest, fill=(fontcolor))
-
- if test_member_number is None:
- members = sorted(server.members,
- key=lambda m: m.joined_at).index(member) + 1
- else:
- members = test_member_number
-
- member_number = str(members) + self._get_suffix(members)
- sname = str(member.server.name) + '!' if len(str(member.server.name)) <= 28 else str(member.server.name)[:23] + '...'
-
- _outline((152, 96), "You are the " + str(member_number) + " member", 1, server_font, (textoutline))
- drawtwo.text((152, 96), "You are the " + str(member_number) + " member", font=server_font, fill=(servercolor))
- _outline((152, 116), 'of ' + sname, 1, server_font, (textoutline))
- drawtwo.text((152, 116), 'of ' + sname, font=server_font, fill=(servercolor))
-
- image_object = BytesIO()
- welcome_picture.save(image_object, format="PNG")
- image_object.seek(0)
- return image_object
-
- async def _circle_border(self, circle_img_size: tuple):
- border_size = []
- for i in range(len(circle_img_size)):
- border_size.append(circle_img_size[0] + 8)
- return tuple(border_size)
-
- async def _data_check(self, ctx):
- server = ctx.message.server
- if server.id not in self.settings:
- self.settings[server.id] = deepcopy(default_settings)
- self.settings[server.id]["CHANNEL"] = ctx.message.channel.id
- await self.save_settings()
-
- if "BONUSES" not in self.settings[server.id].keys():
- self.settings[server.id]["BONUSES"] = {"ACCOUNT_WARNINGS": True,
- "SPECIAL_USERS": True
- }
- await self.save_settings()
-
- if "CIRCLE" not in self.settings[server.id].keys():
- self.settings[server.id]["CIRCLE"] = [128, 128]
- await self.save_settings()
-
- if "CHANNEL" not in self.settings[server.id].keys():
- self.settings[server.id]["CHANNEL"] = ctx.message.channel.id
- await self.save_settings()
-
- if "FONT" not in self.settings[server.id].keys():
- self.settings[server.id]["FONT"] = {"WELCOME_FONT": {"PATH": "data/imgwelcome/fonts/UniSansHeavy.otf",
- "SIZE": 50},
- "SERVER_FONT": {"PATH": "data/imgwelcome/fonts/UniSansHeavy.otf",
- "SIZE": 20},
- "NAME_FONT": {"PATH": "data/imgwelcome/fonts/UniSansHeavy.otf",
- "SIZE": {"NORMAL": 30,
- "MEDIUM": 22,
- "SMALL": 18,
- "SMALLEST": 12
- }
- }
- }
-
- if "OUTLINE" not in self.settings[server.id].keys():
- self.settings[server.id]["OUTLINE"] = [0, 0, 0, 255]
- await self.save_settings()
-
- async def _get_profile(self, url):
- async with aiohttp.get(url) as r:
- image = await r.content.read()
- with open('data/imgwelcome/profilepic.png', 'wb') as f:
- f.write(image)
-
- def _get_suffix(self, num):
- suffixes = {1: 'st', 2: 'nd', 3: 'rd'}
- if 10 <= num % 100 <= 20:
- suffix = 'th'
- else:
- suffix = suffixes.get(num % 10, 'th')
- return suffix
-
- def _hex_to_rgb(self, hex_num: str, a: int):
- h = hex_num.lstrip('#')
-
- # if only 3 characters are given
- if len(str(h)) == 3:
- expand = ''.join([x*2 for x in str(h)])
- h = expand
-
- colors = [int(h[i:i+2], 16) for i in (0, 2, 4)]
- colors.append(a)
- return tuple(colors)
-
- def _is_hex(self, color: str):
- if color is not None and len(color) != 4 and len(color) != 7:
- return False
-
- reg_ex = r'^#(?:[0-9a-fA-F]{3}){1,2}$'
- return re.search(reg_ex, str(color))
-
- def _rgb_to_hex(self, rgb):
- rgb = tuple(rgb[:3])
- return '#%02x%02x%02x' % rgb
-
- @checks.admin_or_permissions(manage_server=True)
- @commands.group(pass_context=True)
- async def imgwelcome(self, ctx):
- """Configuration options for the welcome image."""
- if ctx.invoked_subcommand is None:
- await send_cmd_help(ctx)
- return
-
- @imgwelcome.command(pass_context=True, name="border", no_pm=True)
- async def imgwelcome_border(self, ctx, bordercolor=None):
- """Set the profile image border color.
- Use hex codes for colors and ‘clear’ for transparent."""
- server = ctx.message.server
- await self._data_check(ctx)
- default_a = 230
- valid = True
-
- if bordercolor == "clear":
- self.settings[server.id]["BORDER"] = [0, 0, 0, 0]
- elif self._is_hex(bordercolor):
- self.settings[server.id]["BORDER"] = self._hex_to_rgb(bordercolor, default_a)
- else:
- await self.bot.say('Border color is invalid. Use #000000 as a format.')
- valid = False
-
- if valid:
- await self.bot.say('The profile border color has been set.')
- await self.save_settings()
-
- @imgwelcome.command(pass_context=True, name="channel", no_pm=True)
- async def imgwelcome_channel(self, ctx, channel: discord.Channel):
- """Set the announcement channel."""
- server = ctx.message.server
- if not server.me.permissions_in(channel).send_messages:
- await self.bot.say("No permissions to speak in that channel.")
- return
- await self._data_check(ctx)
- self.settings[server.id]["CHANNEL"] = channel.id
- await self.save_settings()
- await self.bot.send_message(channel, "This channel will be used for welcome messages.")
-
- @imgwelcome.command(name='clear', pass_context=True, no_pm=True)
- async def imgwelcome_clear(self, ctx):
- """Set the background to transparent."""
- server = ctx.message.server
- await self._data_check(ctx)
- self.settings[server.id]['BACKGROUND'] = 'data/imgwelcome/transparent.png'
- await self.save_settings()
- await self.bot.say('Welcome image background is now transparent.')
-
- @imgwelcome.command(pass_context=True, name="outline", no_pm=True)
- async def imgwelcome_outline(self, ctx, outline=None):
- """Set the text outline. White or black."""
- server = ctx.message.server
- await self._data_check(ctx)
- valid = True
- if outline == "white":
- self.settings[server.id]["OUTLINE"] = [255, 255, 255, 255]
- await self.save_settings()
- elif outline == "black":
- self.settings[server.id]["OUTLINE"] = [0, 0, 0, 255]
- await self.save_settings()
- else:
- await self.bot.say('Outline color is invalid. Use white or black.')
- valid = False
-
- if valid:
- await self.bot.say('The text outline has been set.')
-
- @imgwelcome.command(name="preview", pass_context=True, no_pm=True)
- async def imagewelcome_preview(self, ctx, member: discord.Member=None, number: int=None):
- """Show a welcome image with the current settings."""
- server = ctx.message.server
- channel = ctx.message.channel
- if member is None:
- member = ctx.message.author
- await self._data_check(ctx)
- channel_object = self.bot.get_channel(channel.id)
- await self.bot.send_typing(channel_object)
- image_object = await self._create_welcome(member, member.avatar_url, number)
- await self.bot.send_file(channel_object, image_object, filename="welcome.png")
-
- @imgwelcome.command(pass_context=True, name="size", no_pm=True)
- async def imgwelcome_profilesize(self, ctx, profilesize: int):
- """Set the profile size in pixels. Use one number, 128 is recommended."""
- server = ctx.message.server
- await self._data_check(ctx)
- if profilesize is 0:
- await self.bot.say("Profile picture size must be larger than 0.")
- return
- else:
- self.settings[server.id]["CIRCLE"] = [profilesize, profilesize]
- await self.save_settings()
- await self.bot.say('The profile picture size has been set.')
-
- @imgwelcome.command(pass_context=True, name="text", no_pm=True)
- async def imgwelcome_text(self, ctx, textcolor: str, servercolor: str):
- """Set text colors. Use hex code for colors."""
- server = ctx.message.server
- await self._data_check(ctx)
- default_a = 230
- valid = True
-
- if self._is_hex(textcolor):
- self.settings[server.id]["TEXT"] = self._hex_to_rgb(textcolor, default_a)
- else:
- await self.bot.say('Welcome text color is invalid. Use #000000 as a format.')
- valid = False
-
- if self._is_hex(servercolor):
- self.settings[server.id]["SERVERTEXT"] = self._hex_to_rgb(servercolor, default_a)
- else:
- await self.bot.say('Server text color is invalid. Use #000000 as a format.')
- valid = False
-
- if valid:
- await self.bot.say('The text colors have been set.')
- await self.save_settings()
-
- @imgwelcome.command(pass_context=True, name="toggle", no_pm=True)
- async def imgwelcome_toggle(self, ctx):
- """Toggle welcome messages on the server."""
- server = ctx.message.server
- await self._data_check(ctx)
- self.settings[server.id]["ANNOUNCE"] = not self.settings[server.id]["ANNOUNCE"]
- if self.settings[server.id]["ANNOUNCE"]:
- await self.bot.say("Now welcoming new users.")
- else:
- await self.bot.say("No longer welcoming new users.")
- await self.save_settings()
-
- @imgwelcome.command(name='upload', pass_context=True, no_pm=True)
- async def imgwelcome_upload(self, ctx, default=None):
- """Upload a background through Discord. 500px x 150px.
- This must be an image file and not a url."""
- server = ctx.message.server
- await self._data_check(ctx)
- await self.bot.say("Please send the file to use as a background. File must be 500px x 150px.")
- answer = await self.bot.wait_for_message(timeout=30, author=ctx.message.author)
-
- try:
- bg_url = answer.attachments[0]["url"]
- success = True
- except Exception as e:
- success = False
- print(e)
-
- serverimage = Image
-
- if success:
- try:
- async with aiohttp.get(bg_url) as r:
- image = await r.content.read()
- if not os.path.exists('data/imgwelcome/{}'.format(server.id)):
- os.makedirs('data/imgwelcome/{}'.format(server.id))
- serverbg = 'data/imgwelcome/{}/serverbg.png'.format(server.id)
- with open(serverbg, 'wb') as f:
- f.write(image)
- serverimage = Image.open(serverbg).convert('RGBA')
- success = True
-
- except Exception as e:
- success = False
- print(e)
- if success:
- if serverimage.size == (500, 150):
- self.settings[server.id]['BACKGROUND'] = "data/imgwelcome/" + ctx.message.server.id + "/serverbg.png"
- await self.save_settings()
- else:
- await self.bot.say("Image needs to be 500x150.")
- return
- background_img = ('data/imgwelcome/{}/serverbg.png'.format(server.id))
- self.settings[server.id]['BACKGROUND'] = (background_img)
- await self.save_settings()
- await self.bot.say('Welcome image for this server set to uploaded file.')
- else:
- await self.bot.say("Couldn't get the image from Discord.")
- else:
- await self.bot.say("Couldn't get the image.")
-
- @imgwelcome.group(pass_context=True, name='bonus', no_pm=True)
- async def imgwelcome_bonus(self, ctx):
- """Toggle display of additional text welcome messages when a user joins the server."""
- if ctx.invoked_subcommand is None or isinstance(ctx.invoked_subcommand, commands.Group):
- await send_cmd_help(ctx)
- return
-
- @imgwelcome_bonus.command(pass_context=True, name='user', no_pm=True)
- async def bonus_user(self, ctx):
- """Toggle text announcement when a user is x 100th to join or #1337."""
- server = ctx.message.server
- await self._data_check(ctx)
- self.settings[server.id]["BONUSES"]["SPECIAL_USERS"] = not self.settings[server.id]["BONUSES"]["SPECIAL_USERS"]
- await self.save_settings()
- if self.settings[server.id]["BONUSES"]["SPECIAL_USERS"]:
- msg = "I will now announce when special users join."
- else:
- msg = "I will no longer announce when special users join."
- await self.bot.say(msg)
-
- @imgwelcome_bonus.command(pass_context=True, name='warn', no_pm=True)
- async def bonus_warn(self, ctx):
- """Toggle text announcement when a new user's account is <7d old."""
- server = ctx.message.server
- await self._data_check(ctx)
- self.settings[server.id]["BONUSES"]["ACCOUNT_WARNINGS"] = not self.settings[server.id]["BONUSES"]["ACCOUNT_WARNINGS"]
- await self.save_settings()
- if self.settings[server.id]["BONUSES"]["ACCOUNT_WARNINGS"]:
- msg = "I will now announce when new accounts join."
- else:
- msg = "I will no longer announce when new accounts join."
- await self.bot.say(msg)
-
- @imgwelcome.group(pass_context=True, name='font', no_pm=True)
- async def imgwelcome_font(self, ctx):
- """Place your font files in the data/imgwelcome/fonts/ directory.
- Valid font areas to change are: welcome, server and name.
- """
- if ctx.invoked_subcommand is None or isinstance(ctx.invoked_subcommand, commands.Group):
- await send_cmd_help(ctx)
- return
-
- @imgwelcome_font.command(pass_context=True, name='list', no_pm=True)
- async def fontg_list(self, ctx):
- """List fonts in the directory."""
- channel = ctx.message.channel
- directory = "data/imgwelcome/fonts/"
- fonts = sorted(os.listdir(directory))
-
- if len(fonts) == 0:
- await self.bot.send_message(channel, "No fonts found. Place "
- "fonts in /data/imgwelcome/fonts/.")
- return
-
- pager = commands.formatter.Paginator(prefix='```', suffix='```', max_size=2000)
- pager.add_line('Current fonts:')
- for font_name in fonts:
- pager.add_line(font_name)
- for page in pager.pages:
- await self.bot.send_message(channel, page)
-
- @imgwelcome_font.command(pass_context=True, name='name', no_pm=True)
- async def fontg_name(self, ctx, font_name: str, size: int=None):
- """Change the name text font.
- e.g. [p]imgwelcome font name "UniSansHeavy.otf"
- """
- await self._data_check(ctx)
- server = ctx.message.server
-
- directory = "data/imgwelcome/fonts/"
- if size is None:
- size = self.settings[server.id]["FONT"]["NAME_FONT"]["SIZE"]["NORMAL"]
-
- try:
- ImageFont.truetype(directory + font_name, size)
- except:
- await self.bot.say("I could not find that font file.")
- return
-
- self.settings[server.id]["FONT"]["NAME_FONT"]["PATH"] = directory + font_name
- self.settings[server.id]["FONT"]["NAME_FONT"]["SIZE"]["NORMAL"] = size
- self.settings[server.id]["FONT"]["NAME_FONT"]["SIZE"]["MEDIUM"] = size - 8
- self.settings[server.id]["FONT"]["NAME_FONT"]["SIZE"]["SMALL"] = size - 12
- self.settings[server.id]["FONT"]["NAME_FONT"]["SIZE"]["SMALLEST"] = size - 18
- await self.save_settings()
- await self.bot.say("Name font changed to: {}".format(font_name[:-4]))
-
- @imgwelcome_font.command(pass_context=True, name='server', no_pm=True)
- async def fontg_server(self, ctx, font_name: str, size: int=None):
- """Change the server text font."""
- await self._data_check(ctx)
- server = ctx.message.server
-
- directory = "data/imgwelcome/fonts/"
- if size is None:
- size = self.settings[server.id]["FONT"]["SERVER_FONT"]["SIZE"]
-
- try:
- ImageFont.truetype(directory + font_name, size)
- except:
- await self.bot.say("I could not find that font file.")
- return
-
- self.settings[server.id]["FONT"]["SERVER_FONT"]["PATH"] = directory + font_name
- self.settings[server.id]["FONT"]["SERVER_FONT"]["SIZE"] = size
- await self.save_settings()
- await self.bot.say("Server text font changed to: {}".format(font_name[:-4]))
- pass
-
- @imgwelcome_font.command(pass_context=True, name='welcome', no_pm=True)
- async def fontg_welcome(self, ctx, font_name: str, size: int=None):
- """Change the welcome text font."""
- # try open file_name, if fail tell user
- # if opens change settings, tell user success
- # if file_name doesn't exist, list available fonts
- await self._data_check(ctx)
- server = ctx.message.server
-
- directory = "data/imgwelcome/fonts/"
- if size is None:
- size = self.settings[server.id]["FONT"]["WELCOME_FONT"]["SIZE"]
-
- try:
- ImageFont.truetype(directory + font_name, size)
- except:
- await self.bot.say("I could not find that font file.")
- return
-
- self.settings[server.id]["FONT"]["WELCOME_FONT"]["PATH"] = directory + font_name
- self.settings[server.id]["FONT"]["WELCOME_FONT"]["SIZE"] = size
- await self.save_settings()
- await self.bot.say("Welcome font changed to: {}".format(font_name[:-4]))
- pass
-
- @imgwelcome.command(name="version", pass_context=True, hidden=True)
- async def imagewelcomeset_version(self):
- """Displays the imgwelcome version."""
- await self.bot.say("imgwelcome version {}.".format(self.version))
-
- async def on_member_join(self, member):
- server = member.server
- if server.id not in self.settings:
- self.settings[server.id] = deepcopy(default_settings)
- await self.save_settings()
- if not self.settings[server.id]["ANNOUNCE"]:
- return
- channelid = self.settings[server.id]["CHANNEL"]
- channel_object = self.bot.get_channel(channelid)
- await self.bot.send_typing(channel_object)
- image_object = await self._create_welcome(member, member.avatar_url)
- await self.bot.send_file(channel_object, image_object, filename="welcome.png")
- if (len(member.server.members) % 100) == 0 or (len(member.server.members) == 1337) and self.settings[server.id]["SPECIAL_USERS"]:
- msg = "\N{PARTY POPPER} Thanks <@" + member.id + ">, you're the ***" + str(len(member.server.members)) + "*** th user on this server! \N{PARTY POPPER}"
- await self.bot.send_message(channel_object, msg)
- date_join = datetime.datetime.strptime(str(member.created_at), "%Y-%m-%d %H:%M:%S.%f")
- date_now = datetime.datetime.now(datetime.timezone.utc)
- date_now = date_now.replace(tzinfo=None)
- since_join = date_now - date_join
- if since_join.days < 7 and self.settings[server.id]["ACCOUNT_WARNINGS"]:
- await self.bot.send_message(channel_object, "\N{WARNING SIGN} This account was created less than a week ago (" + str(since_join.days) + " days ago)")
-
-
-def check_folders():
- if not os.path.exists('data/imgwelcome/'):
- os.mkdir('data/imgwelcome/')
-
-
-def check_files():
- if not dataIO.is_valid_json('data/imgwelcome/settings.json'):
- defaults = {}
- dataIO.save_json('data/imgwelcome/settings.json', defaults)
-
-
-def setup(bot):
- check_folders()
- check_files()
- bot.add_cog(ImgWelcome(bot))
diff --git a/imgwelcome/info.json b/imgwelcome/info.json
deleted file mode 100644
index c608df4..0000000
--- a/imgwelcome/info.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "AUTHOR" : "aikaterna",
- "INSTALL_MSG" : "Use [p]imgwelcome to change settings.",
- "NAME" : "imgwelcome",
- "SHORT" : "Welcome users to your server with an image.",
- "DESCRIPTION" : "Welcome users to your server with an image.",
- "REQUIREMENTS": ["Pillow"],
- "TAGS": ["welcome", "welcome image", "images"]
-}
diff --git a/otherbot/otherbot.py b/otherbot/otherbot.py
deleted file mode 100644
index b5225eb..0000000
--- a/otherbot/otherbot.py
+++ /dev/null
@@ -1,17 +0,0 @@
-import discord
-
-class OtherbotStatus:
- def __init__(self, bot):
- self.bot = bot
-
- async def on_member_update(self, before, after):
- if after.status == discord.Status.offline and after.id == "000000000000000000": # this is the bot id that you want to watch
- channel_object = self.bot.get_channel("000000000000000000") # this is the channel id for the watcher bot to scream in
- await self.bot.send_message(channel_object, "<@000000000000000000>, the bot is offline.") # this is the person to ping and the message
- else:
- pass
-
-
-def setup(bot):
- n = OtherbotStatus(bot)
- bot.add_cog(n)
diff --git a/picwelcome/data/default.png b/picwelcome/data/default.png
deleted file mode 100644
index cedc576..0000000
Binary files a/picwelcome/data/default.png and /dev/null differ
diff --git a/picwelcome/info.json b/picwelcome/info.json
deleted file mode 100644
index 05647f5..0000000
--- a/picwelcome/info.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "AUTHOR" : "aikaterna",
- "INSTALL_MSG" : "Use [p]picwelcome to change settings.",
- "NAME" : "picwelcome",
- "SHORT" : "Welcome users to your server with a picture.",
- "DESCRIPTION" : "Welcome users to your server with a picture.",
- "REQUIREMENTS": ["Pillow"],
- "TAGS": ["welcome", "welcome image", "images"]
-}
diff --git a/picwelcome/picwelcome.py b/picwelcome/picwelcome.py
deleted file mode 100644
index c2de3d3..0000000
--- a/picwelcome/picwelcome.py
+++ /dev/null
@@ -1,170 +0,0 @@
-# picwelcomeset_upload is based on code in orels' drawing.py
-# https://github.com/orels1/ORELS-Cogs
-
-import asyncio
-import aiohttp
-import datetime
-import discord
-import os
-from __main__ import send_cmd_help
-from cogs.utils.dataIO import dataIO
-from cogs.utils import checks
-from copy import deepcopy
-from discord.ext import commands
-from PIL import Image
-
-
-default_settings = {"ANNOUNCE": False,
- "PICTURE": "data/picwelcome/default.png",
- "CHANNEL": None,
- }
-
-
-class PicWelcome:
- """Welcome new users with a static image."""
-
- def __init__(self, bot):
- self.bot = bot
- self.settings = dataIO.load_json('data/picwelcome/settings.json')
- self.version = "0.0.1"
-
- async def save_settings(self):
- dataIO.save_json('data/picwelcome/settings.json', self.settings)
-
- async def _data_check(self, ctx):
- server = ctx.message.server
- if server.id not in self.settings:
- self.settings[server.id] = deepcopy(default_settings)
- self.settings[server.id]["CHANNEL"] = ctx.message.channel.id
- await self.save_settings()
-
- @checks.admin_or_permissions(manage_server=True)
- @commands.group(pass_context=True)
- async def picwelcome(self, ctx):
- """Configuration options for a welcome picture."""
- if ctx.invoked_subcommand is None:
- await send_cmd_help(ctx)
- return
-
- @picwelcome.command(pass_context=True, name="channel", no_pm=True)
- async def picwelcome_channel(self, ctx, channel: discord.Channel):
- """Set the announcement channel."""
- server = ctx.message.server
- if not server.me.permissions_in(channel).send_messages:
- await self.bot.say("No permissions to speak in that channel.")
- return
- await self._data_check(ctx)
- self.settings[server.id]["CHANNEL"] = channel.id
- await self.save_settings()
- await self.bot.send_message(channel, "This channel will be used for welcome pictures.")
-
- @picwelcome.command(name='reset', pass_context=True, no_pm=True)
- async def picwelcome_reset(self, ctx):
- """Set the welcome picture back to the default."""
- server = ctx.message.server
- await self._data_check(ctx)
- self.settings[server.id]['PICTURE'] = 'data/picwelcome/default.png'
- await self.save_settings()
- await self.bot.say('Welcome picture reset to default.')
-
- @picwelcome.command(name="preview", pass_context=True, no_pm=True)
- async def picwelcome_preview(self, ctx, member: discord.Member=None, number: int=None):
- """Show a the welcome picture with the current settings."""
- server = ctx.message.server
- channel = ctx.message.channel
- if member is None:
- member = ctx.message.author
- await self._data_check(ctx)
- channel_object = self.bot.get_channel(channel.id)
- await self.bot.send_typing(channel_object)
- serverpicture = self.settings[server.id]["PICTURE"]
- await self.bot.send_file(channel_object, serverpicture)
-
- @picwelcome.command(pass_context=True, name="toggle", no_pm=True)
- async def picwelcome_toggle(self, ctx):
- """Toggle welcome pictures on the server."""
- server = ctx.message.server
- await self._data_check(ctx)
- self.settings[server.id]["ANNOUNCE"] = not self.settings[server.id]["ANNOUNCE"]
- if self.settings[server.id]["ANNOUNCE"]:
- await self.bot.say("Now welcoming new users with a picture.")
- else:
- await self.bot.say("No longer welcoming new users with a picture.")
- await self.save_settings()
-
- @picwelcome.command(name='upload', pass_context=True, no_pm=True)
- async def picwelcome_upload(self, ctx, default=None):
- """Upload a picture through Discord.
- This must be an image file and not a url."""
- server = ctx.message.server
- await self._data_check(ctx)
- await self.bot.say("Please send the file to use as a welcome picture.")
- answer = await self.bot.wait_for_message(timeout=30, author=ctx.message.author)
-
- try:
- bg_url = answer.attachments[0]["url"]
- success = True
- except Exception as e:
- success = False
- print(e)
-
- serverimage = Image
-
- if success:
- try:
- async with aiohttp.get(bg_url) as r:
- image = await r.content.read()
- if not os.path.exists('data/picwelcome/{}'.format(server.id)):
- os.makedirs('data/picwelcome/{}'.format(server.id))
- serverbg = 'data/picwelcome/{}/serverpic.png'.format(server.id)
- with open(serverbg, 'wb') as f:
- f.write(image)
- serverimage = Image.open(serverbg).convert('RGBA')
- success = True
-
- except Exception as e:
- success = False
- print(e)
- if success:
- self.settings[server.id]['PICTURE'] = "data/picwelcome/" + ctx.message.server.id + "/serverpic.png"
- await self.save_settings()
- await self.bot.say('Welcome image for this server set to uploaded file.')
- else:
- await self.bot.say("Couldn't get the image from Discord.")
- else:
- await self.bot.say("Couldn't get the image.")
-
- @picwelcome.command(name="version", pass_context=True, hidden=True)
- async def picwelcome_version(self):
- """Displays the picwelcome version."""
- await self.bot.say("picwelcome version {}.".format(self.version))
-
- async def on_member_join(self, member):
- server = member.server
- if server.id not in self.settings:
- self.settings[server.id] = deepcopy(default_settings)
- await self.save_settings()
- if not self.settings[server.id]["ANNOUNCE"]:
- return
- channelid = self.settings[server.id]["CHANNEL"]
- channel_object = self.bot.get_channel(channelid)
- await self.bot.send_typing(channel_object)
- serverpicture = self.settings[server.id]["PICTURE"]
- await self.bot.send_file(channel_object, serverpicture)
-
-
-def check_folders():
- if not os.path.exists('data/picwelcome/'):
- os.mkdir('data/picwelcome/')
-
-
-def check_files():
- if not dataIO.is_valid_json('data/picwelcome/settings.json'):
- defaults = {}
- dataIO.save_json('data/picwelcome/settings.json', defaults)
-
-
-def setup(bot):
- check_folders()
- check_files()
- bot.add_cog(PicWelcome(bot))
diff --git a/pug/info.json b/pug/info.json
deleted file mode 100644
index 562239b..0000000
--- a/pug/info.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "AUTHOR" : "aikaterna",
- "INSTALL_MSG" : "Thanks for installing Pug. Now you can check out your Warcraft pugs for raid-readiness through Discord.",
- "NAME" : "Pug",
- "SHORT" : "Warcraft character lookup.",
- "DESCRIPTION" : "This tool lets you check potential group pugs for enchants, gems, and raid completion. It was made possible by PugBot: https://github.com/reznok/PugBot",
- "TAGS" : ["warcraft", "raiding", "raid"]
-}
diff --git a/pug/pug.py b/pug/pug.py
deleted file mode 100644
index 44b609c..0000000
--- a/pug/pug.py
+++ /dev/null
@@ -1,313 +0,0 @@
-import json
-import os
-import requests
-from .utils.dataIO import dataIO
-from __main__ import send_cmd_help
-from discord.ext import commands
-from .utils import checks
-
-
-class Pug:
-
- def __init__(self, bot):
- self.bot = bot
- self.settings = dataIO.load_json("data/pug/config.json")
- self.fp = "data/pug/config.json"
- API_KEY = self.settings["blizzard_api_key"]
- default_region = self.settings["default_region"]
-
- LEG_WITH_SOCKET = [
- 132369, 132410, 137044, 132444, 132449, 132452, 132460, 133973, 133974, 137037, 137038, 137039, 137040, 137041,
- 137042, 137043, 132378, 137045, 137046, 137047, 137048, 137049, 137050, 137051, 137052, 137054, 137055, 137220,
- 137223, 137276, 137382, 138854
- ]
-
- ENCHANTABLE_SLOTS = ["neck", "back", "finger1", "finger2"]
-
- region_locale = {
- 'us': ['us', 'en_US', 'en'],
- 'eu': ['eu', 'en_GB', 'en']
- # 'kr': ['kr', 'ko_KR', 'ko'],
- # 'tw': ['tw', 'zh_TW', 'zh'],
- # 'es': ['es', 'es_MX', 'es'], es lookup is broken until the armory site is migrated to the new format
- }
-
- def get_sockets(self, player_dictionary):
- """
- Return dict with total sockets and count of equipped gems and slots that are missing
-
- :param player_dictionary: Retrieved player dict from API
- :return: dict()
- """
- sockets = 0
- equipped_gems = 0
-
- for item in player_dictionary["items"]:
- if item in "averageItemLevel" or item in "averageItemLevelEquipped":
- continue
-
- if int(player_dictionary["items"][item]["id"]) in self.LEG_WITH_SOCKET:
- sockets += 1
-
- for bonus in player_dictionary["items"][item]["bonusLists"]:
- if bonus == 1808: # 1808 is Legion prismatic socket bonus
- sockets += 1
-
- if item in ["neck", "finger1", "finger2"]:
- if player_dictionary["items"][item]["context"] == "trade-skill":
- sockets += 1
-
- for ttip in player_dictionary["items"][item]["tooltipParams"]:
- if item in "mainHand" or item in "offHand": # Ignore Relic
- continue
- if "gem" in ttip: # Equipped gems are listed as gem0, gem1, etc...
- equipped_gems += 1
-
- return {"total_sockets": sockets,
- "equipped_gems": equipped_gems}
-
- def get_enchants(self, player_dictionary):
- """
- Get count of enchants missing and slots that are missing
- :param player_dictionary:
- :return: dict()
- """
- self.missing_enchant_slots = []
- for slot in self.ENCHANTABLE_SLOTS:
- if "enchant" not in player_dictionary["items"][slot]["tooltipParams"]:
- self.missing_enchant_slots.append(slot)
-
- return {
- "enchantable_slots": len(self.ENCHANTABLE_SLOTS),
- "missing_slots": self.missing_enchant_slots,
- "total_missing": len(self.missing_enchant_slots)
- }
-
- def get_raid_progression(self, player_dictionary, raid):
- r = [x for x in player_dictionary["progression"]
- ["raids"] if x["name"] in raid][0]
- normal = 0
- heroic = 0
- mythic = 0
-
- for boss in r["bosses"]:
- if boss["normalKills"] > 0:
- normal += 1
- if boss["heroicKills"] > 0:
- heroic += 1
- if boss["mythicKills"] > 0:
- mythic += 1
-
- return {"normal": normal,
- "heroic": heroic,
- "mythic": mythic,
- "total_bosses": len(r["bosses"])}
-
- def get_mythic_progression(self, player_dictionary):
- achievements = player_dictionary["achievements"]
- plus_two = 0
- plus_five = 0
- plus_ten = 0
-
- if 33096 in achievements["criteria"]:
- index = achievements["criteria"].index(33096)
- plus_two = achievements["criteriaQuantity"][index]
-
- if 33097 in achievements["criteria"]:
- index = achievements["criteria"].index(33097)
- plus_five = achievements["criteriaQuantity"][index]
-
- if 33098 in achievements["criteria"]:
- index = achievements["criteria"].index(33098)
- plus_ten = achievements["criteriaQuantity"][index]
-
- return {
- "plus_two": plus_two,
- "plus_five": plus_five,
- "plus_ten": plus_ten
- }
-
- def get_char(self, name, server, target_region):
- self.settings = dataIO.load_json("data/pug/config.json") # Load Configs
- API_KEY = self.settings["blizzard_api_key"]
- r = requests.get("https://%s.api.battle.net/wow/character/%s/%s?fields=items+progression+achievements&locale=%s&apikey=%s" % (
- self.region_locale[target_region][0], server, name, self.region_locale[target_region][1], API_KEY))
-
- if r.status_code != 200:
- raise Exception("Could not find character (No 200 from API).")
-
- player_dict = json.loads(r.text)
-
- r = requests.get(
- "https://%s.api.battle.net/wow/data/character/classes?locale=%s&apikey=%s" % (
- self.region_locale[target_region][0], self.region_locale[target_region][1], API_KEY))
- if r.status_code != 200:
- raise Exception("Could Not Find Character Classes (No 200 From API)")
- class_dict = json.loads(r.text)
- class_dict = {c['id']: c['name'] for c in class_dict["classes"]}
-
- r = requests.get("https://%s.api.battle.net/wow/character/%s/%s?fields=stats&locale=%s&apikey=%s" % (
- self.region_locale[target_region][0], server, name, self.region_locale[target_region][1], API_KEY))
- if r.status_code != 200:
- raise Exception("Could not find character stats (No 200 From API).")
- stats_dict = json.loads(r.text)
-
- health = stats_dict["stats"]["health"]
- power = stats_dict["stats"]["power"]
- powertype = stats_dict["stats"]["powerType"]
- powertypeproper = powertype.title()
- strength = stats_dict["stats"]["str"]
- agi = stats_dict["stats"]["agi"]
- int = stats_dict["stats"]["int"]
- sta = stats_dict["stats"]["sta"]
- crit = stats_dict["stats"]["critRating"]
- critrating = stats_dict["stats"]["crit"]
- haste = stats_dict["stats"]["hasteRating"]
- hasterating = stats_dict["stats"]["haste"]
- mastery = stats_dict["stats"]["masteryRating"]
- masteryrating = stats_dict["stats"]["mastery"]
- vers = stats_dict["stats"]["versatility"]
- versrating = stats_dict["stats"]["versatilityDamageDoneBonus"]
- equipped_ivl = player_dict["items"]["averageItemLevelEquipped"]
- sockets = self.get_sockets(player_dict)
- enchants = self.get_enchants(player_dict)
- tov_progress = self.get_raid_progression(player_dict, "Trial of Valor")
- en_progress = self.get_raid_progression(player_dict, "The Emerald Nightmare")
- nh_progress = self.get_raid_progression(player_dict, "The Nighthold")
- tos_progress = self.get_raid_progression(player_dict, "Tomb of Sargeras")
- ant_progress = self.get_raid_progression(player_dict, "Antorus, the Burning Throne")
- mythic_progress = self.get_mythic_progression(player_dict)
-
- armory_url = 'http://{}.battle.net/wow/{}/character/{}/{}/advanced'.format(
- self.region_locale[target_region][0], self.region_locale[target_region][2], server, name)
-
- return_string = ''
- return_string += "**%s** - **%s** - **%s %s**\n" % (
- name.title(), server.title(), player_dict['level'], class_dict[player_dict['class']])
- return_string += '<{}>\n'.format(armory_url)
- return_string += '```ini\n' # start Markdown
-
- # iLvL
- return_string += "[Equipped Item Level]: %s\n" % equipped_ivl
-
- # Mythic Progression
- return_string += "[Mythics]: +2: %s, +5: %s, +10: %s\n" % (mythic_progress["plus_two"],
- mythic_progress["plus_five"],
- mythic_progress["plus_ten"])
-
- # Raid Progression
- return_string += "[EN]: {1}/{0} (N), {2}/{0} (H), {3}/{0} (M)\n".format(en_progress["total_bosses"],
- en_progress["normal"],
- en_progress["heroic"],
- en_progress["mythic"])
- return_string += "[TOV]: {1}/{0} (N), {2}/{0} (H), {3}/{0} (M)\n".format(tov_progress["total_bosses"],
- tov_progress["normal"],
- tov_progress["heroic"],
- tov_progress["mythic"])
- return_string += "[NH]: {1}/{0} (N), {2}/{0} (H), {3}/{0} (M)\n".format(nh_progress["total_bosses"],
- nh_progress["normal"],
- nh_progress["heroic"],
- nh_progress["mythic"])
- return_string += "[TOS]: {1}/{0} (N), {2}/{0} (H), {3}/{0} (M)\n".format(tos_progress["total_bosses"],
- tos_progress["normal"],
- tos_progress["heroic"],
- tos_progress["mythic"])
- return_string += "[ANT]: {1}/{0} (N), {2}/{0} (H), {3}/{0} (M)\n".format(ant_progress["total_bosses"],
- ant_progress["normal"],
- ant_progress["heroic"],
- ant_progress["mythic"])
- # Gems
- return_string += "[Gems Equipped]: %s/%s\n" % (
- sockets["equipped_gems"], sockets["total_sockets"])
-
- # Enchants
- return_string += "[Enchants]: %s/%s\n" % (enchants["enchantable_slots"] - enchants["total_missing"],
- enchants["enchantable_slots"])
- if enchants["total_missing"] > 0:
- return_string += "[Missing Enchants]: {0}".format(
- ", ".join(enchants["missing_slots"]))
-
- # Stats
- return_string += "\n"
- return_string += "[Health]: {} [{}]: {}\n".format(health, powertypeproper, power)
- return_string += "[Str]: {} [Agi]: {}\n".format(strength, agi, int, sta)
- return_string += "[Int]: {} [Sta]: {}\n".format(int, sta)
- return_string += "[Crit]: {}, {}% [Haste]: {}, {}%\n".format(crit, critrating, haste, hasterating,)
- return_string += "[Mastery]: {}, {}% [Vers]: {}, {}% bonus damage\n".format(mastery, masteryrating, vers, versrating)
-
- return_string += '```' # end Markdown
- return return_string
-
- @commands.command(name="pug", pass_context=True, no_pm=True)
- async def _pug(self, ctx, *, message):
- """A Warcraft Armory character lookup tool.
- Use: !pug
- Hyphenate two-word servers (Ex: Twisting-Nether)."""
- self.settings = dataIO.load_json("data/pug/config.json") # Load Configs
- default_region = self.settings["default_region"]
- target_region = default_region
- channel = ctx.message.channel
- try:
- i = str(ctx.message.content).split(' ')
- name = i[1]
- server = i[2]
- if len(i) == 4 and i[3].lower() in self.region_locale.keys():
- target_region = i[3].lower()
- character_info = self.get_char(name, server, target_region)
- await self.bot.send_message(ctx.message.channel, character_info)
- except Exception as e:
- print(e)
- await self.bot.send_message(ctx.message.channel, "Error with character name or server.")
-
- @commands.command(pass_context=True, name='pugtoken')
- @checks.is_owner()
- async def _pugtoken(self, context, key: str):
- """Sets the token for the Blizzard API.
- You can use this command in a private message to the bot.
-
- Get an API token at: https://dev.battle.net/member/register"""
- settings = dataIO.load_json(self.fp)
- settings['blizzard_api_key'] = key
- dataIO.save_json(self.fp, settings)
- await self.bot.say("API key set.")
-
- @commands.command(pass_context=True, name='pugregion')
- @checks.is_owner()
- async def _pugregion(self, context, key: str):
- """Sets the default region."""
- settings = dataIO.load_json(self.fp)
- settings['default_region'] = key
- dataIO.save_json(self.fp, settings)
- await self.bot.say("Default region set.")
-
- @commands.command()
- async def pugcredits(self):
- """Code credits."""
- message = await self._credit()
- await self.bot.say(message)
-
- async def _credit(self):
- message = "```This cog is made possible by Pugbot.\n"
- message+= "Please visit https://github.com/reznok/PugBot for more information.\n"
- message+= "```"
- return message
-
-
-def check_folders():
- if not os.path.exists("data/pug"):
- print("Creating data/pug folder...")
- os.mkdir("data/pug")
-
-
-def check_files():
- fp = "data/pug/config.json"
- if not dataIO.is_valid_json(fp):
- print("Creating config.json...")
- dataIO.save_json(fp, {"blizzard_api_key": "", "default_region": "us"})
-
-
-def setup(bot):
- check_folders()
- check_files()
- n = Pug(bot)
- bot.add_cog(n)
diff --git a/radio/info.json b/radio/info.json
deleted file mode 100644
index 9acd0a0..0000000
--- a/radio/info.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "AUTHOR" : "Paddo, with edits by aikaterna",
- "NAME" : "radio",
- "SHORT" : "Plays http streams like icecast or mp3 streams.",
- "DESCRIPTION" : "This cog can only be used with audio unloaded. To play m3u or pls files, extract the http stream url they contain and use that - this cog can remember urls for later playback.",
- "TAGS": ["radio", "stream", "icecast"]
-}
diff --git a/radio/radio.py b/radio/radio.py
deleted file mode 100644
index 64fd054..0000000
--- a/radio/radio.py
+++ /dev/null
@@ -1,161 +0,0 @@
-import os
-import discord
-import asyncio
-from discord.ext import commands
-from __main__ import send_cmd_help
-from cogs.utils.dataIO import dataIO
-
-
-class Radio:
- def __init__(self, bot):
- self.bot = bot
- self.players = {}
- self.memory_path = 'data/radio/memory.json'
- self.memory = dataIO.load_json(self.memory_path)
-
- @commands.group(pass_context=True, no_pm=True, name='radio')
- async def _radio(self, ctx):
- """Streaming audio commands."""
- audio_cog = self.bot.get_cog('Audio')
- if audio_cog:
- return await self.bot.say("Please unload the audio cog before using this cog.")
- if ctx.invoked_subcommand is None:
- await send_cmd_help(ctx)
-
- @_radio.command(pass_context=True, no_pm=True, name='stop')
- async def _leave(self, ctx):
- """Stops playback."""
- server = ctx.message.server
- voice_client = await self.voice_client(server)
- await self.stop_playing(server)
- if voice_client:
- await voice_client.disconnect()
-
- @_radio.command(no_pm=True, pass_context=True, name='play')
- async def _play(self, ctx, url: str):
- """Play a http stream."""
- server = ctx.message.server
- if server.id in self.players:
- await self.stop_playing(server)
- await self.play_stream(ctx, url)
- await self.bot.say("Now playing: <{}>".format(url))
-
- @_radio.command(no_pm=True, pass_context=True, name='list')
- async def _list(self, ctx):
- """List saved stream URLs."""
- server = ctx.message.server
- message = '```\n'
- message += '{:<30}{}\n\n'.format('NAME', 'URL')
- if server.id in self.memory:
- for stream in self.memory[server.id]:
- message += '{:<30}{}\n'.format(stream, self.memory[server.id][stream])
- message += '```'
- await self.bot.say(message)
-
- @_radio.command(no_pm=True, pass_context=True, name='add')
- async def _add(self, ctx, name: str, url: str):
- """Add a url to save for radio playback."""
- server = ctx.message.server
- await self.add_to_memory(server, name, url)
- await self.bot.say('Added to memory')
-
- @_radio.command(no_pm=True, pass_context=True, name='load')
- async def _load(self, ctx, name: str):
- """Load a saved url for radio playback."""
- server = ctx.message.server
- if server.id in self.memory:
- if name.lower() in self.memory[server.id]:
- url = self.memory[server.id][name.lower()]
- if server.id in self.players:
- await self.stop_playing(server)
- await self.play_stream(ctx, url)
- await self.bot.say("Now playing: <{}>".format(url))
- else:
- await self.bot.say('"{}" is not in memory.'.format(name.lower()))
- else:
- await self.bot.say('Nothing in memory yet')
-
- async def save_memory(self):
- dataIO.save_json(self.memory_path, self.memory)
-
- async def add_to_memory(self, server, name, url):
- if server.id not in self.memory:
- self.memory[server.id] = {}
- self.memory[server.id][name.lower()] = url
- await self.save_memory()
-
- async def join_voice_channel(self, channel):
- try:
- await self.bot.join_voice_channel(channel)
- return True
- except discord.InvalidArgument:
- await self.bot.say('You need to be in a voice channel yourself.')
- except discord.Forbidden:
- await self.bot.say('I don\'t have permissions to join this channel.')
- return False
-
- async def leave_voice_channel(self, server):
- voice_client = await self.voice_client(server)
- if server.id in self.players:
- self.players[server.id].stop()
- del self.players[server.id]
- await self.stop_playing(server)
- await voice_client.disconnect()
-
- async def voice_connected(self, server):
- return self.bot.is_voice_connected(server)
-
- async def voice_client(self, server):
- return self.bot.voice_client_in(server)
-
- async def stop_playing(self, server):
- if server.id in self.players:
- self.players[server.id].stop()
- del self.players[server.id]
-
- async def start_playing(self, server, url):
- if server.id not in self.players:
- voice_client = await self.voice_client(server)
- audio_player = voice_client.create_ffmpeg_player(url)
- self.players[server.id] = audio_player
- self.players[server.id].start()
-
- async def play_stream(self, ctx, url):
- server = ctx.message.server
- channel = ctx.message.author.voice_channel
- if not ctx.message.channel.is_private:
- check = True
- if not await self.voice_connected(server):
- check = await self.join_voice_channel(channel)
- if check:
- await self.start_playing(server, url)
-
- async def _playing_check(self):
- while self == self.bot.get_cog('Radio'):
- for player in self.players:
- if not self.players[player].is_playing():
- server = self.bot.get_server(player)
- await self.leave_voice_channel(server)
- break
- await asyncio.sleep(30)
-
-
-def check_folder():
- if not os.path.exists('data/radio'):
- print('Creating data/radio folder...')
- os.makedirs('data/radio')
-
-
-def check_file():
- if not dataIO.is_valid_json('data/radio/memory.json'):
- print('Creating memory.json...')
- dataIO.save_json('data/radio/memory.json', {})
-
-
-def setup(bot):
- check_folder()
- check_file()
- cog = Radio(bot)
- loop = asyncio.get_event_loop()
- loop.create_task(cog._playing_check())
- bot.add_cog(cog)
diff --git a/riot/info.json b/riot/info.json
deleted file mode 100644
index b0a2efe..0000000
--- a/riot/info.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "AUTHOR" : "aikaterna",
- "INSTALL_MSG" : "Thanks for installing riot.",
- "NAME" : "Riot",
- "SHORT" : "RIOT!",
- "DESCRIPTION" : "Riot was a feature on the now-extinct Fredboat, requested by Mewleficent.",
- "TAGS" : ["riot"]
-}
diff --git a/riot/riot.py b/riot/riot.py
deleted file mode 100644
index 3c748c9..0000000
--- a/riot/riot.py
+++ /dev/null
@@ -1,17 +0,0 @@
-import discord
-from discord.ext import commands
-
-
-class Riot:
-
- def __init__(self, bot):
- self.bot = bot
-
- @commands.command(pass_context=True, no_pm=True)
- async def riot(self, ctx, *, text: str):
- """RIOT!"""
- await self.bot.say('ヽ༼ຈل͜ຈ༽ノ **' + str(text) + '** ヽ༼ຈل͜ຈ༽ノ')
-
-
-def setup(bot):
- bot.add_cog(Riot(bot))
diff --git a/seen/info.json b/seen/info.json
deleted file mode 100644
index f582db7..0000000
--- a/seen/info.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "AUTHOR" : "Paddolicious#8880",
- "NAME" : "Seen",
- "SHORT" : "Check when the user was last active on a server.",
- "DESCRIPTION" : "Check when the user was last active on a server.",
- "TAGS": ["Seen", "member", "tools"]
-}
diff --git a/seen/seen.py b/seen/seen.py
deleted file mode 100644
index 8aace8c..0000000
--- a/seen/seen.py
+++ /dev/null
@@ -1,119 +0,0 @@
-from discord.ext import commands
-from cogs.utils.dataIO import dataIO
-import discord
-import os
-import asyncio
-from datetime import datetime
-
-
-DB_VERSION = 2
-
-
-class Seen:
- '''Check when someone was last seen.'''
- def __init__(self, bot):
- self.bot = bot
- self.seen = dataIO.load_json('data/seen/seen.json')
- self.new_data = False
-
- async def data_writer(self):
- while self == self.bot.get_cog('Seen'):
- if self.new_data:
- dataIO.save_json('data/seen/seen.json', self.seen)
- self.new_data = False
- await asyncio.sleep(60)
- else:
- await asyncio.sleep(30)
-
- @commands.command(pass_context=True, no_pm=True, name='seen')
- async def _seen(self, context, username: discord.Member):
- '''seen <@username>'''
- server = context.message.server
- author = username
- timestamp_now = context.message.timestamp
- if server.id in self.seen:
- if author.id in self.seen[server.id]:
- data = self.seen[server.id][author.id]
- timestamp_then = datetime.fromtimestamp(data['TIMESTAMP'])
- timestamp = timestamp_now - timestamp_then
- days = timestamp.days
- seconds = timestamp.seconds
- hours = seconds // 3600
- seconds = seconds - (hours * 3600)
- minutes = seconds // 60
- if sum([days, hours, minutes]) < 1:
- ts = 'just now'
- else:
- ts = ''
- if days == 1:
- ts += '{} day, '.format(days)
- elif days > 1:
- ts += '{} days, '.format(days)
- if hours == 1:
- ts += '{} hour, '.format(hours)
- elif hours > 1:
- ts += '{} hours, '.format(hours)
- if minutes == 1:
- ts += '{} minute ago'.format(minutes)
- elif minutes > 1:
- ts += '{} minutes ago'.format(minutes)
- em = discord.Embed(color=discord.Color.green())
- avatar = author.avatar_url if author.avatar else author.default_avatar_url
- em.set_author(name='{} was seen {}'.format(author.display_name, ts), icon_url=avatar)
- await self.bot.say(embed=em)
- else:
- message = 'I haven\'t seen {} yet.'.format(author.display_name)
- await self.bot.say('{}'.format(message))
- else:
- message = 'I haven\'t seen {} yet.'.format(author.display_name)
- await self.bot.say('{}'.format(message))
-
- async def on_message(self, message):
- if not message.channel.is_private and self.bot.user.id != message.author.id:
- if not any(message.content.startswith(n) for n in self.bot.settings.prefixes):
- server = message.server
- author = message.author
- ts = message.timestamp.timestamp()
- data = {}
- data['TIMESTAMP'] = ts
- if server.id not in self.seen:
- self.seen[server.id] = {}
- self.seen[server.id][author.id] = data
- self.new_data = True
-
-
-def check_folder():
- if not os.path.exists('data/seen'):
- print('Creating data/seen folder...')
- os.makedirs('data/seen')
-
-
-def check_file():
- data = {}
- data['db_version'] = DB_VERSION
- f = 'data/seen/seen.json'
- if not dataIO.is_valid_json(f):
- print('Creating seen.json...')
- dataIO.save_json(f, data)
- else:
- check = dataIO.load_json(f)
- if 'db_version' in check:
- if check['db_version'] < DB_VERSION:
- data = {}
- data['db_version'] = DB_VERSION
- dataIO.save_json(f, data)
- print('SEEN: Database version too old, resetting!')
- else:
- data = {}
- data['db_version'] = DB_VERSION
- dataIO.save_json(f, data)
- print('SEEN: Database version too old, resetting!')
-
-
-def setup(bot):
- check_folder()
- check_file()
- n = Seen(bot)
- loop = asyncio.get_event_loop()
- loop.create_task(n.data_writer())
- bot.add_cog(n)
diff --git a/serverlimit/info.json b/serverlimit/info.json
deleted file mode 100644
index 890730f..0000000
--- a/serverlimit/info.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "AUTHOR" : "aikaterna",
- "INSTALL_MSG" : "No settings, when loaded the bot will leave servers with under 25 members on join.",
- "NAME" : "serverlimit",
- "SHORT" : "Serverlimit",
- "DESCRIPTION" : "Limits the bot joining servers that have under 25 members.",
- "TAGS": []
-}
diff --git a/serverlimit/serverlimit.py b/serverlimit/serverlimit.py
deleted file mode 100644
index 496e047..0000000
--- a/serverlimit/serverlimit.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# get_default_channel_or_other is from Squid's Admin cog:
-# https://github.com/tekulvw/Squid-Plugins
-
-import discord
-import traceback
-
-
-class ServerLimit:
- def __init__(self, bot):
- self.bot = bot
-
- async def _message(self, server):
- server_owner = server.owner
- notice_msg = "Hi, I tried to make an announcement in your "\
- + "server, " + server.name + ", but I don't have "\
- + "permissions to send messages in the default "\
- + "channel there!"
- await self.bot.send_message(server_owner, notice_msg)
- await self.bot.leave_server(server)
-
- async def on_server_join(self, server):
- chan = self.get_default_channel_or_other(server,
- discord.ChannelType.text,
- send_messages=True)
- me = server.me
- server_owner = server.owner
- msg = "I can only join servers which have more than 25 members. "\
- + "Please try again later when the server is larger."
- if len(server.members) <= 25:
- if chan is not None:
- if chan.permissions_for(me).send_messages:
- await self.bot.send_message(chan, msg)
- await self.bot.leave_server(server)
- else:
- await self._message(server)
- await self.bot.send_message(server_owner, msg)
- else:
- await self._message(server)
- await self.bot.send_message(server_owner, msg)
-
- def get_default_channel_or_other(self, server,
- ctype: discord.ChannelType=None,
- **perms_required):
-
- perms = discord.Permissions.none()
- perms.update(**perms_required)
- if ctype is None:
- types = [discord.ChannelType.text, discord.ChannelType.voice]
- elif ctype == discord.ChannelType.text:
- types = [discord.ChannelType.text]
- else:
- types = [discord.ChannelType.voice]
- try:
- channel = server.default_channel
- except Exception:
- channel = None
- if channel is not None:
- if channel.permissions_for(server.me).is_superset(perms):
- return channel
-
- chan_list = [c for c in sorted(server.channels,
- key=lambda ch: ch.position)
- if c.type in types]
- for ch in chan_list:
- if ch.permissions_for(server.me).is_superset(perms):
- return ch
- return None
-
-
-def setup(bot):
- bot.add_cog(ServerLimit(bot))