81ddab81 by Barry

Finished refactor and added threading for all calls.

1 parent 4264acb8
No preview for this file type
......@@ -8,6 +8,7 @@ import time
import re
import pickle
import logging
import thread
import traceback
import sys
......@@ -27,7 +28,7 @@ import sqlite3
from blackjack import Blackjack
import data
VERSION = 2.0
VERSION = 2.2
conn = sqlite3.connect('db.sqlite3')
......@@ -37,9 +38,9 @@ muted_until = datetime.datetime.now()
client = discord.Client()
wolf = {}
logging.basicConfig(filename='hellsbot.log',level=logging.WARNING)
logging.basicConfig(filename='hellsbot.log', level=logging.WARNING)
registered_commands = {'!help': 'do_help', '!commands': 'do_help',
registered_commands = {'!help': 'do_help', '!commands': 'do_help',
'!shutup': 'do_shutup',
'!roll': 'do_roll',
'!lastseen': 'do_lastseen',
......@@ -70,18 +71,24 @@ registered_commands = {'!help': 'do_help', '!commands': 'do_help',
'!question': 'do_question',
'!addjoke': 'do_addjoke',
'!joke': 'do_joke',
'!secret': 'do_secret',
'!bemyirlwaifu': 'do_waifu',
'HILLARY 2016': 'do_hillary',
'!squid': 'do_squid',
'!stars': 'do_stars',
}
#####################
## Utility Functions
# Utility Functions
#####################
def log(message):
try:
logging.warning("{} - {}".format(datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S'), message))
except:
pass
def format_exception(e):
exception_list = traceback.format_stack()
exception_list = exception_list[:-2]
......@@ -95,12 +102,14 @@ def format_exception(e):
return exception_str
def leaders(xs, top=20):
counts = defaultdict(int)
for x in xs:
counts[x] += 1
return sorted(counts.items(), reverse=True, key=lambda tup: tup[1])[:top]
def byteify(input):
if isinstance(input, dict):
return {byteify(key): byteify(value) for key, value in input.iteritems()}
......@@ -111,18 +120,20 @@ def byteify(input):
else:
return input
def search_youtube(query):
query_string = {"search_query" : query}
query_string = {"search_query": query}
r = requests.get("http://www.youtube.com/results", params=query_string)
search_results = re.findall(r'href=\"\/watch\?v=(.{11})', r.content)
log("http://www.youtube.com/watch?v=" + search_results[0])
return "http://www.youtube.com/watch?v=" + search_results[0]
def search_google_images(query, animated=False):
headers = {'User-Agent': "Mozilla/5.0 (X11; FreeBSD amd64; rv:12.0) Gecko/20100101 Firefox/12.0"}
query_string = {"safe": "off", "tbm": "isch", "q" : query}
query_string = {"safe": "off", "tbm": "isch", "q": query}
if animated:
query_string = {"safe": "off", "tbm": "isch", "q" : query, 'tbs': 'itp:animated'}
query_string = {"safe": "off", "tbm": "isch", "q": query, 'tbs': 'itp:animated'}
r = requests.get("http://www.google.com/search", params=query_string, headers=headers)
......@@ -139,24 +150,23 @@ def search_google_images(query, animated=False):
#################
## Client Events
# Client Events
#################
@client.event
def on_socket_raw_send(payload, binary=False):
check_msg_queue()
@client.event
def on_status(member):
for member in client.get_all_members():
try:
db_member = data.db_get_member(member.id)
#log(db_member)
if not db_member:
log("Creating new member: {}".format(member) )
log("Creating new member: {}".format(member))
data.db_create_member(member)
else:
#log("Updating member: {}".format(member) )
data.db_update_member(member, db_member)
check_msg_queue()
......@@ -164,8 +174,8 @@ def on_status(member):
log("Exception: {}".format(format_exception(e)))
pass
def check_msg_queue():
#log("checking messages")
messages = data.db_get_messages()
if messages:
for message in messages:
......@@ -181,6 +191,7 @@ def check_msg_queue():
log("{}\nFailed to send message: {}".format(format_exception(e), message['message_id'],))
return
def do_roll(client, message_parts, message):
request = message_parts[0]
count = 1
......@@ -201,36 +212,36 @@ def do_roll(client, message_parts, message):
return
roll_results = []
for i in range(count):
roll_results.append(random.randint(1,dice))
roll_results.append(random.randint(1, dice))
out_string = '{} your roll {}d{}: {} = {}'.format(message.author.mention(), count, dice, '+'.join(str(r) for r in roll_results), sum(roll_results))
client.send_message(message.channel, out_string)
return
def do_lastseen(client, message_parts, message):
username = ' '.join(message_parts).replace('@', '').lower()
member = data.db_get_member(username=username)
#log(member)
if member:
out_string = ''
if member['is_afk'] == 1:
out_string = 'Went AFK at: {}\n'.format(member['afk_at'])
elif member['status'] == 'offline':
out_string = 'Currently Offline\n'
out_string = 'Currently Offline\n'
else:
out_string = 'Currently Online\n'
out_string += 'Last Status: {} at {} which was {}\nPrevious Status: {}\n'.format(member['status'],
member['status_change_at'],
member['status_change_at'],
human(datetime.datetime.strptime(member['status_change_at'], '%Y/%m/%d %H:%M:%S')),
member['prev_status'])
client.send_message(message.channel, 'Last Information on {}:\n{}'.format(byteify(username), out_string))
else:
client.send_message(message.channel, 'I don\'t have any data on {} yet {}'.format(byteify(username), message.author.mention()))
return
return
def do_help(client, message_parts, message):
client.send_message(message.channel,
"""{} Available Commands:
client.send_message(message.channel, """{} Available Commands:
You can ask compound or questions and I will choose. Example: HellsBot Rui is a Faggot or Rui is a faggot?
User Info:
......@@ -272,29 +283,35 @@ Stuff:
!shutup - disables all image / gif / youtube spam for 5 minutes
!bemyirlwaifu""".format(message.author.mention()))
def do_shutup(client, message_parts, message):
global muted_until
muted_until = datetime.datetime.now() + datetime.timedelta(minutes=5)
client.send_message(message.channel, 'All image / gif / youtube spam disabled for 5 minutes')
return
def do_youtube(client, message_parts, message):
if datetime.datetime.now() < muted_until:
return
client.send_message(message.channel, search_youtube(' '.join(message_parts)))
return
def do_image(client, message_parts, message):
if datetime.datetime.now() < muted_until:
return
client.send_message(message.channel, search_google_images(' '.join(message_parts)))
return
def do_gif(client, message_parts, message):
if datetime.datetime.now() < muted_until:
return
client.send_message(message.channel, search_google_images(' '.join(message_parts), True))
return
def do_gameslist(client, message_parts, message):
limit = 20
if len(message_parts) > 0 and message_parts[0].isdigit():
......@@ -310,6 +327,7 @@ def do_gameslist(client, message_parts, message):
out_string = out_string[1900:]
return
def do_alias(client, message_parts, message):
if len(message_parts) > 0:
username = ' '.join(message_parts).replace('@', '').lower()
......@@ -324,9 +342,10 @@ def do_alias(client, message_parts, message):
else:
client.send_message(message.channel, 'No known alises for {} yet {}'.format(byteify(username), message.author.mention()))
else:
client.send_message(message.channel, 'I don\'t know who you are speaking of {}!'.format(message.author.mention()))
client.send_message(message.channel, 'I don\'t know who you are speaking of {}!'.format(message.author.mention()))
return
def do_addalias(client, message_parts, message):
alias = ' '.join(message_parts)
username = message.author.name.lower()
......@@ -338,6 +357,7 @@ def do_addalias(client, message_parts, message):
client.send_message(message.channel, 'Something horrible happened and it is all your fault, try logging out / on again or play a game. (or fuck off i dunno i\'m just an error message. Who am I to tell you how to run your life...)')
return
def do_games(client, message_parts, message):
if len(message_parts) > 0:
username = ' '.join(message_parts).replace('@', '').lower()
......@@ -352,12 +372,14 @@ def do_games(client, message_parts, message):
else:
client.send_message(message.channel, 'I don\'t have any data on {} yet {}'.format(byteify(username), message.author.mention()))
def do_reload(client, message_parts, message):
if message.author.id != '78767557628133376':
client.send_message(message.channel, "You shouldn't be calling this. You are clearly looking to piss Hellsbreath off.")
return
call(["service", "hellsbot", "restart"])
def do_whoplayed(client, message_parts, message):
game_name = ' '.join(message_parts)
member_list = data.db_get_whoplayed(game_name)
......@@ -373,6 +395,7 @@ def do_whoplayed(client, message_parts, message):
out_string = out_string[1900:]
return
def do_gimmecredits(client, message_parts, message):
member = data.db_get_member(message.author.id)
if not member:
......@@ -387,6 +410,7 @@ def do_gimmecredits(client, message_parts, message):
client.send_message(message.author, "You already have credits. Stop begging.")
return
def do_grantcredits(clients, message_parts, message):
if message.author.id != '78767557628133376':
client.send_message(message.channel, "You are not Hellsbreath. Use !gimmecredits to get a few extra if you run out.")
......@@ -402,6 +426,7 @@ def do_grantcredits(clients, message_parts, message):
client.send_message(message.channel, "{} has been given {} credits.".format(member['member_name'], 100))
return
def do_ticketrank(clients, message_parts, message):
members = data.db_get_all_members()
if len(members) < 0:
......@@ -410,13 +435,11 @@ def do_ticketrank(clients, message_parts, message):
ticket_count = 0
for member in members:
if member['discord_id'] != '78767557628133376':
#log(member)
ticket_count += member['tickets']
if ticket_count == 0:
client.send_message(message.channel, "No Tickets have been sold for this raffle.")
return
#log("Ticket Count: {}".format(ticket_count))
out_string = ""
for member in members:
if member['tickets'] > 0 and member['discord_id'] != '78767557628133376':
......@@ -426,6 +449,7 @@ def do_ticketrank(clients, message_parts, message):
client.send_message(message.channel, out_string)
return
def do_startraffle(client, message_parts, message):
if message.author.id != '78767557628133376':
client.send_message(message.channel, "You are not Hellsbreath. Go die in an especially hot fire.")
......@@ -437,13 +461,11 @@ def do_startraffle(client, message_parts, message):
ticket_count = 0
for member in members:
if member['discord_id'] != '78767557628133376':
#log(member)
ticket_count += member['tickets']
if ticket_count == 0:
client.send_message(message.channel, "No Tickets have been sold for this raffle.")
return
#log("Ticket Count: {}".format(ticket_count))
out_string = "The final standings are as follows: \n\n"
ticket_reel = []
for member in members:
......@@ -461,12 +483,13 @@ def do_startraffle(client, message_parts, message):
while second in ticket_reel:
ticket_reel.remove(second)
time.sleep(0.5)
client.send_message(message.channel, "\n\n*2nd Place:* {}".format(byteify(winner)))
client.send_message(message.channel, "\n\n*2nd Place:* {}".format(byteify(second)))
if len(ticket_reel) > 0:
third = random.choice(ticket_reel)
time.sleep(0.5)
client.send_message(message.channel, "\n*3rd Place:* {}".format(byteify(winner)))
return
client.send_message(message.channel, "\n*3rd Place:* {}".format(byteify(third)))
return
def do_raffle(client, message_parts, message):
client.send_message(message.channel, """Current Raffle Item:
......@@ -474,7 +497,7 @@ def do_raffle(client, message_parts, message):
**1st Place**
Game: **Lightning Returns**
Description:
Description:
*Lightning Returns is the concluding chapter of the Final Fantasy XIII saga and series heroine Lightning's final battle. The grand finale of the trilogy brings a world reborn as well as free character customization and stunning action based battles.*
http://store.steampowered.com/app/345350/
......@@ -496,6 +519,7 @@ You can get extra credits by playing !slots <amount> and !bet <amount> on BlackJ
""")
return
def do_buyticket(client, message_parts, message):
member = data.db_get_member(message.author.id)
if not member:
......@@ -510,6 +534,7 @@ def do_buyticket(client, message_parts, message):
client.send_message(message.author, "Raffle ticket purchased. Tickets: {} Credits: {}".format(response, credits))
return
def do_balance(client, message_parts, message):
member = data.db_get_member(message.author.id)
if not member:
......@@ -518,6 +543,7 @@ def do_balance(client, message_parts, message):
client.send_message(message.author, "Credits: {}\nTickets: {}".format(member['credits'], member['tickets']))
return
def do_slotsrules(client, message_parts, message):
client.send_message(message.channel, """Paying Combinations:
......@@ -538,6 +564,7 @@ Max Bet: 10 credits
To Play: !slots <bet>""")
return
def do_slots(client, message_parts, message):
member = data.db_get_member(message.author.id)
if not member:
......@@ -571,6 +598,7 @@ def do_slots(client, message_parts, message):
diamonds = reels.count(":diamonds:")
bells = reels.count(":bell:")
moneybags = reels.count(":moneybag:")
out_string = ""
if moneybags == 3:
out_string += "JACKPOT!!"
winnings = 250
......@@ -604,7 +632,8 @@ def do_slots(client, message_parts, message):
out_string += "\nCredits: {}".format(credits)
client.send_message(message.author, out_string)
return
return
def do_bj_hit(client, message_parts, message):
member = data.db_get_member(message.author.id)
......@@ -643,6 +672,7 @@ def do_bj_hit(client, message_parts, message):
client.send_message(message.author, "You must start a game with !bet before you can ask for a new card.")
return
def do_bj_stay(client, message_parts, message):
member = data.db_get_member(message.author.id)
if not member:
......@@ -669,6 +699,7 @@ def do_bj_stay(client, message_parts, message):
client.send_message(message.author, out_string)
return
def do_bj_bet(client, message_parts, message):
member = data.db_get_member(message.author.id)
if not member:
......@@ -739,10 +770,10 @@ def do_bj_bet(client, message_parts, message):
client.send_message(message.author, out_string)
return
def do_msg(client, message_parts, message):
channel = message.channel
author = message.author
#author = message.author.name
username = ''
try:
# TODO: Switch message_bits with message_parts
......@@ -768,19 +799,18 @@ def do_msg(client, message_parts, message):
msg_idx = 4
except ValueError:
client.send_message(channel, 'Your shitty message has been rejected {}. Next time learn how to date...MM\\DD\\YYYY'.format(message.author.mention()))
return
return
username = message_bits[1]
user_mention = ''
# TODO: have it look in the database. Do this AFTER on startup we add all users.
for member in client.get_all_members():
#log("MEMBER: {}".format(byteify(member)))
if username.lower() == member.name.lower():
user_mention = member.mention()
user_id = member.id
if user_mention == '':
client.send_message(channel, 'Your shitty message has been rejected {}. That user does not exist.'.format(message.author.name))
return
client.send_message(channel, 'Your shitty message has been rejected {}. That user does not exist.'.format(message.author.name))
return
msg_text = byteify(' '.join(message_bits[msg_idx:]))
message = {'user_id': user_id, 'channel': channel.id, 'delivery_time': msg_datetime.strftime('%Y/%m/%d %H:%M:%S'), 'message': msg_text}
......@@ -790,14 +820,15 @@ def do_msg(client, message_parts, message):
#test_ch = Object(channel.id)
#client.send_message(test_ch, 'Test Message {}.'.format(author))
except Exception as e:
client.send_message(channel, 'Your shitty message has been rejected {}. {}'.format(author.name, format_exception(e)))
return
client.send_message(channel, 'Your shitty message has been rejected {}. {}'.format(author.name, format_exception(e)))
return
if msg_datetime < datetime.datetime.now():
client.send_message(channel, '{} your message will be delivered to {} as soon as they are available.'.format(author.name, user_mention))
else:
client.send_message(channel, '{} your message will be delivered to {} {}.'.format(author.name, user_mention, human(msg_datetime)))
check_msg_queue()
return
return
def do_addfortune(client, message_parts, message):
try:
......@@ -813,9 +844,10 @@ def do_addfortune(client, message_parts, message):
except Exception as e:
log(e.message)
client.send_message(message.channel, 'Your shitty fortune has been rejected {}.'.format(message.author.mention()))
return
return
client.send_message(message.channel, 'Your shitty fortune has been added {}.'.format(message.author.mention()))
return
return
def do_fortune(client, message_parts, message):
fortune = None
......@@ -833,11 +865,12 @@ def do_fortune(client, message_parts, message):
client.send_message(message.channel, '{} Your fortune is... {}'.format(message.author.mention(), byteify(fortune)))
return
def do_question(client, message_parts, message):
question = message.content[10:]
if "is it gay" in question:
client.send_message(message.channel, 'Yes {}, it is gay.'.format(message.author.mention()))
return
return
res = wolf.query(question)
try:
if len(res.pods):
......@@ -862,13 +895,13 @@ def do_question(client, message_parts, message):
client.send_message(message.channel, 'I don\'t know {}.'.format(message.author.mention()))
return
def do_addjoke(client, message_parts, message):
try:
joke = message.content[9:]
if 'aa737a5846' in joke:
client.send_message(message.channel, '{} you stop it, you are a pedofile, stop looking at little girls.'.format(message.author.mention()))
return
date_added = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')
c = conn.cursor()
c.execute("INSERT INTO jokes (joke) VALUES (?)", (joke,))
conn.commit()
......@@ -876,9 +909,10 @@ def do_addjoke(client, message_parts, message):
except Exception as e:
log(e.message)
client.send_message(message.channel, 'Your shitty joke has been rejected {}.'.format(message.author.mention()))
return
return
client.send_message(message.channel, 'Your shitty joke has been added {}.'.format(message.author.mention()))
return
return
def do_joke(client, message_parts, message):
joke = None
......@@ -895,12 +929,37 @@ def do_joke(client, message_parts, message):
client.send_message(message.channel, '{} {}'.format(message.author.mention(), byteify(joke)))
return
def do_secret(client, message_parts, message):
client.send_message(message.channel, 'git gud {}! My source is here: http://git.savsoul.com/barry/discordbot\nVersion: {}'.format(message.author.mention(), VERSION))
return
def do_waifu(client, message_parts, message):
client.send_message(message.channel, 'http://orig13.deviantart.net/b25e/f/2014/175/3/d/no_waifu_no_laifu_by_imtheonenexttome-d7nsx3b.gif {}!'.format(message.author.mention()))
return
def do_hillary(client, message_parts, message):
client.send_message(message.channel, ':bomb: Ohhhhhh, now you done it...:bomb:'.format(message.author.mention()))
return
def do_squid(client, message_parts, message):
client.send_message(message.channel, 'くコ:彡 くコ:彡 くコ:彡 くコ:彡')
return
def do_stars(client, message_parts, message):
client.send_message(message.channel, '✮═━┈  ✰═━┈  ✮═━┈  ✰═━┈  ✮═━┈  ✰═━┈  ✮═━┈  ✰═━┈  ✮═━┈  ✰═━┈ ✰═━┈┈ ✰═━┈┈')
return
@client.event
def on_message(message):
#print message.content
#print message.author
#print client.user
global muted_until
# we do not want the bot to reply to itself
if message.author == client.user:
return
......@@ -909,7 +968,7 @@ def on_message(message):
for command, method in registered_commands.iteritems():
if message_parts[0] == command:
try:
globals()[method](client, message_parts[1:], message)
thread.start_new_thread(globals()[method], (client, message_parts[1:], message))
except Exception as e:
log("{} - {}".format(format_exception(e), e.message))
return
......@@ -918,31 +977,7 @@ def on_message(message):
log('Someone is talking to %s' % (client.user.name.lower(),))
if ' or ' in message.content:
questions = message.content[len(client.user.name)+1:].replace('?', '').split(' or ')
client.send_message(message.channel, '{} I choose: {}'.format(message.author.mention(), random.choice(questions).encode('utf-8',errors='ignore')))
if message.content.startswith('!secret'):
client.send_message(message.channel, 'git gud {}! My source is here: http://git.savsoul.com/barry/discordbot\nVersion: {}'.format(message.author.mention(), VERSION))
return
if message.content.startswith('!bemyirlwaifu'):
client.send_message(message.channel, 'http://orig13.deviantart.net/b25e/f/2014/175/3/d/no_waifu_no_laifu_by_imtheonenexttome-d7nsx3b.gif {}!'.format(message.author.mention()))
return
if message.content.startswith('HILLARY 2016'):
client.send_message(message.channel, ':bomb: Ohhhhhh, now you done it...:bomb:'.format(message.author.mention()))
return
if message.content.startswith('!squid'):
client.send_message(message.channel, 'くコ:彡 くコ:彡 くコ:彡 くコ:彡')
return
if message.content.startswith('!stars'):
client.send_message(message.channel, '✮═━┈  ✰═━┈  ✮═━┈  ✰═━┈  ✮═━┈  ✰═━┈  ✮═━┈  ✰═━┈  ✮═━┈  ✰═━┈ ✰═━┈┈ ✰═━┈┈')
return
if message.content.startswith('!hello'):
client.send_message(message.channel, 'Hello {}!'.format(message.author.mention()))
return
client.send_message(message.channel, '{} I choose: {}'.format(message.author.mention(), random.choice(questions).encode('utf-8', errors='ignore')))
@client.event
......@@ -959,7 +994,7 @@ def on_ready():
retries = 0
while retries < 1000:
try:
json_data=open(credentials).read()
json_data = open(credentials).read()
creds = json.loads(json_data)
wolf = wolframalpha.Client(creds['wolframkey'])
client.login(creds['username'], creds['password'])
......
......@@ -86,7 +86,7 @@ Families = {
'aspir': False,
'drain': False,
'temperament_attitude': {
'initial_value': 4,
'initial_value': 4,
'actions': {
4: {'use_tp_chance': 100, 'ws': ['Sinker Drill'], 'side_attack_chance': 0, 'range_chance': 0},
3: {'use_tp_chance': 75, 'ws': ['Eyes On Me'], 'side_attack_chance': 70, 'range_chance': 10},
......@@ -95,7 +95,7 @@ Families = {
}
},
'temperament_posture': {
'initial_value': 4,
'initial_value': 4,
'actions': {
4: {'use_tp_chance': 100, 'ws': ['Eyes On Me'], 'side_attack_chance': 0, 'range_chance': 0},
3: {'use_tp_chance': 75, 'ws': ['Eyes On Me'], 'side_attack_chance': 70, 'range_chance': 10},
......@@ -117,7 +117,7 @@ Families = {
'aspir': True,
'drain': True,
'temperament_attitude': {
'initial_value': 4,
'initial_value': 4,
'actions': {
4: {'use_tp_chance': 100, 'ws': ['Eyes On Me'], 'side_attack_chance': 0, 'range_chance': 0},
3: {'use_tp_chance': 75, 'ws': ['Eyes On Me'], 'side_attack_chance': 70, 'range_chance': 10},
......@@ -126,7 +126,7 @@ Families = {
}
},
'temperament_posture': {
'initial_value': 4,
'initial_value': 4,
'actions': {
4: {'use_tp_chance': 100, 'ws': ['Eyes On Me'], 'side_attack_chance': 0, 'range_chance': 0},
3: {'use_tp_chance': 75, 'ws': ['Eyes On Me'], 'side_attack_chance': 70, 'range_chance': 10},
......@@ -192,7 +192,7 @@ class Pankration:
dicipline_level = 1
monster = Monster(family, level, main_job, support_job, feral_skills,
[], dicipline_level)
[], dicipline_level)
return HuntResponse(HuntResponse.SUCCESS, "You captured the monster!",
monster)
else:
......