2016-03-30 09:28:49 +02:00
|
|
|
"""
|
|
|
|
games.py: Create a bot that provides game functionality (dice, 8ball, etc).
|
|
|
|
"""
|
2016-04-07 15:32:45 +02:00
|
|
|
import random
|
2016-05-21 06:33:50 +02:00
|
|
|
import urllib.request
|
|
|
|
import urllib.error
|
|
|
|
from xml.etree import ElementTree
|
2016-05-01 02:09:06 +02:00
|
|
|
|
2016-06-21 03:18:54 +02:00
|
|
|
from pylinkirc import utils
|
|
|
|
from pylinkirc.log import log
|
2016-03-30 09:28:49 +02:00
|
|
|
|
2016-05-15 20:58:45 +02:00
|
|
|
gameclient = utils.registerService("Games", manipulatable=True)
|
2016-05-14 23:52:47 +02:00
|
|
|
reply = gameclient.reply # TODO find a better syntax for ServiceBot.reply()
|
2016-04-08 01:06:35 +02:00
|
|
|
|
|
|
|
# commands
|
2016-05-14 23:52:47 +02:00
|
|
|
def dice(irc, source, args):
|
|
|
|
"""<num>d<sides>
|
2016-04-07 15:32:45 +02:00
|
|
|
|
2016-05-14 23:52:47 +02:00
|
|
|
Rolls a die with <sides> sides <num> times.
|
|
|
|
"""
|
|
|
|
if not args:
|
|
|
|
reply(irc, "No string given.")
|
|
|
|
return
|
2016-04-07 15:32:45 +02:00
|
|
|
|
2016-05-14 23:52:47 +02:00
|
|
|
try:
|
|
|
|
# Split num and sides and convert them to int.
|
|
|
|
num, sides = map(int, args[0].split('d', 1))
|
|
|
|
except ValueError:
|
|
|
|
# Invalid syntax. Show the command help.
|
2016-05-15 01:19:29 +02:00
|
|
|
gameclient.help(irc, source, ['dice'])
|
2016-05-14 23:52:47 +02:00
|
|
|
return
|
2016-04-07 15:32:45 +02:00
|
|
|
|
2016-05-14 23:52:47 +02:00
|
|
|
assert 1 < sides <= 100, "Invalid side count (must be 2-100)."
|
|
|
|
assert 1 <= num <= 100, "Cannot roll more than 100 dice at once."
|
2016-04-07 15:32:45 +02:00
|
|
|
|
2016-05-14 23:52:47 +02:00
|
|
|
results = []
|
|
|
|
for _ in range(num):
|
|
|
|
results.append(random.randint(1, sides))
|
2016-04-07 15:09:56 +02:00
|
|
|
|
2016-05-14 23:52:47 +02:00
|
|
|
# Convert results to strings, join them, format, and reply.
|
|
|
|
s = 'You rolled %s: %s (total: %s)' % (args[0], ' '.join([str(x) for x in results]), sum(results))
|
|
|
|
reply(irc, s)
|
2016-04-07 15:09:56 +02:00
|
|
|
|
2016-05-14 23:52:47 +02:00
|
|
|
gameclient.add_cmd(dice, 'd')
|
|
|
|
gameclient.add_cmd(dice)
|
2016-04-07 15:09:56 +02:00
|
|
|
|
2016-05-21 06:13:39 +02:00
|
|
|
eightball_responses = ["It is certain.",
|
|
|
|
"It is decidedly so.",
|
|
|
|
"Without a doubt.",
|
|
|
|
"Yes, definitely.",
|
|
|
|
"You may rely on it.",
|
|
|
|
"As I see it, yes.",
|
|
|
|
"Most likely.",
|
|
|
|
"Outlook good.",
|
|
|
|
"Yes.",
|
|
|
|
"Signs point to yes.",
|
|
|
|
"Reply hazy, try again.",
|
|
|
|
"Ask again later.",
|
|
|
|
"Better not tell you now.",
|
|
|
|
"Cannot predict now.",
|
|
|
|
"Concentrate and ask again.",
|
|
|
|
"Don't count on it.",
|
|
|
|
"My reply is no.",
|
|
|
|
"My sources say no.",
|
|
|
|
"Outlook not so good.",
|
|
|
|
"Very doubtful."]
|
|
|
|
def eightball(irc, source, args):
|
|
|
|
"""[<question>]
|
|
|
|
|
|
|
|
Asks the Magic 8-ball a question.
|
|
|
|
"""
|
|
|
|
reply(irc, random.choice(eightball_responses))
|
|
|
|
gameclient.add_cmd(eightball)
|
|
|
|
gameclient.add_cmd(eightball, '8ball')
|
|
|
|
gameclient.add_cmd(eightball, '8b')
|
|
|
|
|
2016-05-21 06:33:50 +02:00
|
|
|
def fml(irc, source, args):
|
|
|
|
"""[<id>]
|
|
|
|
|
|
|
|
Displays an entry from fmylife.com. If <id>
|
|
|
|
is not given, fetch a random entry from the API."""
|
|
|
|
try:
|
|
|
|
query = args[0]
|
|
|
|
except IndexError:
|
|
|
|
# Get a random FML from the API.
|
|
|
|
query = 'random'
|
|
|
|
|
|
|
|
# TODO: configurable language?
|
|
|
|
url = ('http://api.betacie.com/view/%s/nocomment'
|
|
|
|
'?key=4be9c43fc03fe&language=en' % query)
|
|
|
|
try:
|
|
|
|
data = urllib.request.urlopen(url).read()
|
|
|
|
except urllib.error as e:
|
|
|
|
reply(irc, 'Error: %s' % e)
|
|
|
|
return
|
|
|
|
|
|
|
|
tree = ElementTree.fromstring(data.decode('utf-8'))
|
|
|
|
tree = tree.find('items/item')
|
|
|
|
|
|
|
|
try:
|
|
|
|
category = tree.find('category').text
|
|
|
|
text = tree.find('text').text
|
|
|
|
fmlid = tree.attrib['id']
|
|
|
|
url = tree.find('short_url').text
|
|
|
|
except AttributeError as e:
|
|
|
|
log.debug("games.FML: Error fetching FML %s from URL %s: %s",
|
|
|
|
query, url, e)
|
|
|
|
reply(irc, "Error: That FML does not exist or there was an error "
|
|
|
|
"fetching data from the API.")
|
|
|
|
return
|
|
|
|
|
|
|
|
if not fmlid:
|
|
|
|
reply(irc, "Error: That FML does not exist.")
|
|
|
|
return
|
|
|
|
|
|
|
|
# TODO: customizable formatting
|
|
|
|
votes = "\x02[Agreed: %s / Deserved: %s]\x02" % \
|
|
|
|
(tree.find('agree').text, tree.find('deserved').text)
|
|
|
|
s = '\x02#%s [%s]\x02: %s - %s \x02<\x0311%s\x03>\x02' % \
|
|
|
|
(fmlid, category, text, votes, url)
|
|
|
|
reply(irc, s)
|
|
|
|
gameclient.add_cmd(fml)
|
|
|
|
|
2016-05-14 23:52:47 +02:00
|
|
|
def die(irc):
|
|
|
|
utils.unregisterService('games')
|