Add files I forgot

This commit is contained in:
Russell 2019-01-29 10:04:31 -05:00
parent 5f1bf146c3
commit 772995c0ff
29 changed files with 1807 additions and 0 deletions

64
Code/irc/bot_launcher.py Executable file
View File

@ -0,0 +1,64 @@
#!/usr/bin/python3
import argparse
from pinhook.bot import Bot
parser = argparse.ArgumentParser()
parser.add_argument(
"-s",
"--server",
dest="server",
default="127.0.0.1",
help="the server to connect to",
metavar="SERVER",
)
parser.add_argument(
"-p",
"--port",
dest="port",
type=int,
default=6667,
help="the port to connect to",
metavar="PORT",
)
parser.add_argument(
"-c",
"--channels",
dest="channels",
nargs="+",
default=["#bot_test"],
help="the channels to join",
metavar="CHANNELS",
)
parser.add_argument(
"-n",
"--nick",
dest="nick",
default="banterbot",
help="the nick to use",
metavar="NICK",
)
parser.add_argument(
"-o",
"--owner",
dest="owner",
default="krowbar",
help="the owner of this bot",
metavar="OWNER",
)
args = parser.parse_args()
print(args)
bot = Bot(
channels = args.channels,
nickname = args.nick,
ops = [ args.owner ],
plugin_dir = "{}_plugins".format(args.nick),
server = args.server,
port = args.port
)
if __name__ == "__main__":
bot.start()

1
Code/irc/madlibbot/util.py Symbolic link
View File

@ -0,0 +1 @@
../util.py

View File

@ -0,0 +1,7 @@
#!/usr/bin/python3
import pinhook.plugin
@pinhook.plugin.register('!rollcall')
def rollcall_plugin(msg):
return pinhook.plugin.message("tildebot reporting! I respond to !tilde !tildescore")

View File

@ -0,0 +1,41 @@
#!/usr/bin/python3
import pinhook.plugin
import util.tilde
@pinhook.plugin.register('!tildescore')
def tildescore_plugin(msg):
return pinhook.plugin.message(util.tilde.show_tildescore(msg.nick))
@pinhook.plugin.register('!jackpot')
def jackpot_plugin(msg):
return pinhook.plugin.message(util.tilde.show_jackpot())
# ADMIN PLUGIN
@pinhook.plugin.register('!debug')
def debug_plugin(msg):
if msg.nick not in msg.ops:
return
if msg.arg:
util.tilde.DEBUG = (msg.arg.lower == 'true' or msg.arg.lower == 't')
return pinhook.plugin.message("DEBUG set to '{}'".format(util.tilde.DEBUG))
# ADMIN PLUGIN
@pinhook.plugin.register('!tilde_requests')
def tilde_requests_plugin(msg):
if msg.nick not in msg.ops and not util.tilde.DEBUG:
return
return pinhook.plugin.message("Outstanding requests: {}".format(",".join(util.tilde.challenges) if util.tilde.challenges else "(none)"))
@pinhook.plugin.register('!tilde')
def tilde_plugin(msg):
if msg.channel != util.tilde.GOOD_CHAN and not util.tilde.DEBUG:
return pinhook.plugin.message("{} is a meanie and gets no tildes. **Tildebot now only gives out tildes in the {} channel.**".format(msg.nick, util.tilde.GOOD_CHAN))
if msg.nick not in util.tilde.challenges:
return pinhook.plugin.message(util.tilde.challenge(msg.channel, msg.nick, msg.timestamp))
@pinhook.plugin.listener('tilde_guess')
def tilde_guess_plugin(msg):
if msg.nick in util.tilde.challenges and (msg.channel == util.tilde.GOOD_CHAN or util.tilde.DEBUG):
return pinhook.plugin.message(util.tilde.challenge_response(msg.nick, msg.timestamp, msg.text))

View File

@ -0,0 +1,32 @@
#!/usr/bin/python3
import pinhook.plugin
from util import topic
import inflect
@pinhook.plugin.listener('topic')
def topic_listener(msg):
if msg.text.startswith("TOPIC"):
topic.count_topic(msg.channel, msg.nick, msg.time, msg.text)
@pinhook.plugin.register('!topic')
def topic_plugin(msg):
return pinhook.plugin.message(topic.get_topic(msg.channel, msg.nick, msg.time))
@pinhook.plugin.register('!settopic')
def set_topic_plugin(msg):
return pinhook.plugin.action("TOPIC {} {}".format(msg.channel, msg.arg))
@pinhook.plugin.register('!randomtopic')
def set_topic_plugin(msg):
return pinhook.plugin.message(topic.random_topic(msg.channel, msg.nick, msg.time, msg.nick == msg.owner))
@pinhook.plugin.register('!suggesttopic')
def suggest_topic_plugin(msg):
return pinhook.plugin.message(topic.random_topic(msg.channel, msg.nick, msg.time, False))
@pinhook.plugin.register('!thistory')
def topic_history_plugin(msg):
return pinhook.plugin.message(topic.topic_history(msg.channel, msg.nick, msg.arg))

View File

View File

@ -0,0 +1,99 @@
#!/usr/bin/python3
import requests
from bs4 import BeautifulSoup
import random
import string
dict = "/usr/share/dict/american-english"
(userId, token) = open("/home/krowbar/.secret/s4token").readline().rstrip().split(",")
def get_acros(word, silly, short):
acros = []
url = "http://www.stands4.com/services/v2/abbr.php?uid={}&tokenid={}&term={}".format(
userId, token, word
)
soup = BeautifulSoup(requests.get(url).content, "html5lib")
results = soup.find_all("result")
# there are lots of cases where the same definition is repeated multiple times under different categories. this is dumb so we should do a little more work
defs = []
for r in results:
rdef = r.find("definition").text
match = next((x for x in defs if x["definition"].lower() == rdef.lower()), None)
if match is not None:
# if we find a match, add the category to the existing categories and increase the score
match["categories"].append(
(
(r.find("parentcategoryname").text + "\\")
if r.find("parentcategoryname")
else ""
)
+ r.find("categoryname").text
)
match["score"] = str(float(match["score"]) + float(r.find("score").text))
else: # add a new item
defs.append(
{
"term": r.find("term").text,
"definition": r.find("definition").text,
"categories": [
(
(r.find("parentcategoryname").text + "\\")
if r.find("parentcategoryname")
else ""
)
+ r.find("categoryname").text
],
"score": r.find("score").text,
}
)
for d in sorted(defs, key=lambda x: float(x["score"]), reverse=True):
# print d;
if short is True:
acros.append('"%s"' % d["definition"])
else:
acros.append(
(
'{}: "{}" ({}, score: {})'.format(
d["term"],
d["definition"],
", ".join(d["categories"]),
d["score"],
)
)
)
if silly is True:
newDef = []
words = open(dict, "r").readlines()
try:
for idx, letter in enumerate(word):
newWord = random.choice(
list(filter(
lambda w: (idx is 0 or not w.strip().lower().endswith("'s"))
and w.lower().startswith(letter.lower()),
words,
))
).strip()
print(str(idx) + " -> " + newWord)
newDef.append(newWord)
newWord = string.capwords(" ".join(newDef))
if short is True:
acros.append('"%s"' % newWord)
else:
acros.append(
(
'{}: "{}" ({}, score: {})'.format(
word.upper(), newWord, "Tilde.town Original", "0"
)
)
)
except IndexError:
acros.append("Future hazy, try again later: Tilde.town Error")
if short is True:
shortList = acros[0:5]
if len(acros) > 5:
shortList.append(acros[-1])
return [word.upper() + ": " + ", ".join(shortList)]
else:
return acros

60
Code/irc/util/banter.py Normal file
View File

@ -0,0 +1,60 @@
#!/usr/bin/python3
import random
import re
banter_file = "/home/krowbar/Code/irc/data/banterscores.txt"
def score_banter(nick, messageText):
print(re)
score = 5
with open(banter_file, "r") as banterfile:
bantz = banterfile.readlines()
words = messageText.strip("\n").split(" ")
for word in words:
for bant in bantz:
bword = bant.strip("\n").split("|")
if re.sub("[^a-z0-9]+", "", word.lower()) == bword[0]:
score += int(bword[1])
score += messageText.count("!") * 2 # hype is banter
score -= messageText.count("!!!") * 6 # too much hype is not banter
score += messageText.count("#") * 3 # hashs are mad bantz
score -= messageText.count("##") * 6 # but too many is garbage
names = ["mate", "lad", "my best boy"]
compliment = [
"top-drawer",
"top-shelf",
"bangin'",
"legendary",
"smashing",
"incredible",
"impeccable",
"stunning",
]
msg = ""
if score > 100:
msg = "Truely {}, {}! That was some #banter! You earned a {} for that!".format(
random.choice(compliment).capitalize(), random.choice(names), score
)
elif score > 50:
msg = "{} #banter! You get a {} from me!".format(
random.choice(compliment).capitalize(), score
)
elif score > 10:
msg = "{} #banter. You get a {}".format(
random.choice(["acceptible", "reasonable", "passable"]).capitalize(), score
)
else:
msg = "That {} #banter, {}. I'll give you a {}. Maybe try again?".format(
random.choice(
["was hardly", "was barely", "wasn't", "won't pass for", "was awful"]
),
random.choice(["lad", "lah", "boy", "son"]),
score,
)
return msg

View File

@ -0,0 +1,34 @@
#!/usr/bin/python3
import requests
from bs4 import BeautifulSoup
import random
def define(word):
defs = []
url = "http://www.merriam-webster.com/dictionary/{}".format(word)
soup = BeautifulSoup(requests.get(url).content, "html.parser")
head = soup.find("div", id="headword")
if head:
for p in head.find_all("p"):
defs.append(p.text)
return defs
key = open("/home/krowbar/.secret/key").readline().rstrip()
def defWord(word, short=True):
defs = []
url = "http://www.dictionaryapi.com/api/v1/references/collegiate/xml/{}?key={}".format(
word, key
)
soup = BeautifulSoup(requests.get(url).content, "html5lib")
entry = soup.find("entry")
if entry:
for d in entry.find_all("dt"):
defs.append(d.text)
if short:
return " ".join(defs)
else:
return defs

View File

@ -0,0 +1,53 @@
#!/usr/bin/python
import random
import inflect
p = inflect.engine()
dictionary = "/usr/share/dict/american-english-small"
BAD_WORDS_FILE = "/home/krowbar/Code/irc/data/badwords.txt"
def gen_wordlist():
# I feel weird calling this "get_wordlist" when it's a generator without calling out that I do in fact realise it's weird - ~deltawitch
# how about gen_wordlist
with open(BAD_WORDS_FILE, "r") as fp:
bad_words = set(fp)
for word in open(dictionary).readlines():
if "'" not in word and word not in bad_words:
yield word.rstrip()
def get_puzzle():
dict_words = list(gen_wordlist())
words = random.sample(dict_words, 3)
key = random.randrange(0, 3) # get values 1-3
puzzle = "When alphebetized, what is the {} in {}?".format(
p.ordinal(p.number_to_words(key + 1)), ", ".join(words)
)
words.sort()
answer = words[key]
return [answer, puzzle]
def get_anagram(maxlen=6):
dict_words = [
word for word in gen_wordlist() if len(word) > 2 and len(word) < maxlen + 1
]
word = random.choice(dict_words)
anagram = list(word)
random.shuffle(anagram)
anagram = "".join(anagram)
# Anagrams can have multiple answers, so we provide a check function that accepts all possibilities
def answer_checker(guess):
# Check for exact match
if guess == word:
return True
# Bail out early if they didn't even use all the same letters
if sorted(guess) != sorted(word):
return False
# Ok, gotta actually check if it's a word now
return any(guess == item for item in gen_wordlist())
return [answer_checker, "Unscramble the following word: '{}'".format(anagram)]

198
Code/irc/util/duckduckgo.py Executable file
View File

@ -0,0 +1,198 @@
import requests
import urllib
import json as j
import sys
__version__ = 0.242
def query(
query,
useragent="python-duckduckgo " + str(__version__),
safesearch=True,
html=False,
meanings=True,
**kwargs
):
"""
Query DuckDuckGo, returning a Results object.
Here's a query that's unlikely to change:
>>> result = query('1 + 1')
>>> result.type
'nothing'
>>> result.answer.text
'1 + 1 = 2'
>>> result.answer.type
'calc'
Keword arguments:
useragent: UserAgent to use while querying. Default: "python-duckduckgo %d" (str)
safesearch: True for on, False for off. Default: True (bool)
html: True to allow HTML in output. Default: False (bool)
meanings: True to include disambiguations in results (bool)
Any other keyword arguments are passed directly to DuckDuckGo as URL params.
""" % __version__
safesearch = "1" if safesearch else "-1"
html = "0" if html else "1"
meanings = "0" if meanings else "1"
params = {
"q": query,
"o": "json",
"kp": safesearch,
"no_redirect": "1",
"no_html": html,
"d": meanings,
}
params.update(kwargs)
encparams = urllib.parse.urlencode(params)
url = "http://api.duckduckgo.com/?" + encparams
request = requests.get(url, headers={"User-Agent": useragent})
return Results(request.json())
class Results(object):
def __init__(self, json):
self.type = {
"A": "answer",
"D": "disambiguation",
"C": "category",
"N": "name",
"E": "exclusive",
"": "nothing",
}.get(json.get("Type", ""), "")
self.json = json
self.api_version = None # compat
self.heading = json.get("Heading", "")
self.results = [Result(elem) for elem in json.get("Results", [])]
self.related = [Result(elem) for elem in json.get("RelatedTopics", [])]
self.abstract = Abstract(json)
self.redirect = Redirect(json)
self.definition = Definition(json)
self.answer = Answer(json)
self.image = Image({"Result": json.get("Image", "")})
class Abstract(object):
def __init__(self, json):
self.html = json.get("Abstract", "")
self.text = json.get("AbstractText", "")
self.url = json.get("AbstractURL", "")
self.source = json.get("AbstractSource")
class Redirect(object):
def __init__(self, json):
self.url = json.get("Redirect", "")
class Result(object):
def __init__(self, json):
self.topics = json.get("Topics", [])
if self.topics:
self.topics = [Result(t) for t in self.topics]
return
self.html = json.get("Result")
self.text = json.get("Text")
self.url = json.get("FirstURL")
icon_json = json.get("Icon")
if icon_json is not None:
self.icon = Image(icon_json)
else:
self.icon = None
class Image(object):
def __init__(self, json):
self.url = json.get("Result")
self.height = json.get("Height", None)
self.width = json.get("Width", None)
class Answer(object):
def __init__(self, json):
self.text = json.get("Answer")
self.type = json.get("AnswerType", "")
class Definition(object):
def __init__(self, json):
self.text = json.get("Definition", "")
self.url = json.get("DefinitionURL")
self.source = json.get("DefinitionSource")
def get_zci(
q,
web_fallback=True,
priority=["answer", "abstract", "related.0", "definition"],
urls=True,
**kwargs
):
"""A helper method to get a single (and hopefully the best) ZCI result.
priority=list can be used to set the order in which fields will be checked for answers.
Use web_fallback=True to fall back to grabbing the first web result.
passed to query. This method will fall back to 'Sorry, no results.'
if it cannot find anything."""
ddg = query("\\" + q, **kwargs)
response = ""
for p in priority:
ps = p.split(".")
type = ps[0]
index = int(ps[1]) if len(ps) > 1 else None
result = getattr(ddg, type)
if index is not None:
if not hasattr(result, "__getitem__"):
raise TypeError("%s field is not indexable" % type)
result = result[index] if len(result) > index else None
if not result:
continue
if result.text:
response = result.text
if result.text and hasattr(result, "url") and urls:
if result.url:
response += " (%s)" % result.url
if response:
break
# if there still isn't anything, try to get the first web result
if not response and web_fallback:
if ddg.redirect.url:
response = ddg.redirect.url
# final fallback
if not response:
response = "Sorry, no results."
return response
def main():
if len(sys.argv) > 1:
q = query(" ".join(sys.argv[1:]))
keys = q.json.keys()
keys.sort()
for key in keys:
sys.stdout.write(key)
if type(q.json[key]) in [str, unicode]:
print(":", q.json[key])
else:
sys.stdout.write("\n")
for i in q.json[key]:
print("\t", i)
else:
print("Usage: %s [query]" % sys.argv[0])

6
Code/irc/util/evil.py Normal file
View File

@ -0,0 +1,6 @@
import random
evil_file = "/home/krowbar/logs/evildata.txt"
def get_thing():
return "If I Ever Become an Evil Overlord: {}".format(random.choice(list(open(evil_file))).rstrip())

27
Code/irc/util/nameFix.py Normal file
View File

@ -0,0 +1,27 @@
#!/usr/bin/python3
import json
names = {
"jumblesal": "jumblesale",
"hardmath1": "kc",
"hardmath123": "kc",
"bendorphan": "endorphant",
"endorphan": "endorphant",
"synergian": "synergiance",
}
def fixName(name):
return names[name] if name in names else name
def get_name(name):
names_file = "/home/jumblesale/Code/canonical_names/canonical_names.json"
try:
with open(names_file) as names_data:
names = json.load(names_data)
try:
return names[name]["userName"]
except KeyError:
return name
except IOError:
return name # if we didn't already

View File

@ -0,0 +1,55 @@
#!/usr/bin/python3
import random
import re
dictDir = "/usr/share/dict/"
def getBanter(morphWord="bant", dictName="words"):
with open(dictDir + dictName, "r") as dict:
# get rid of all the words with apostrophes
words = list(filter(lambda word: re.search(r"^[^']*$", word), dict.readlines()))
head = getBanterHead(words, morphWord)
tail = getBanterTail(words, morphWord)
if head == "" and tail == "":
return "" # dang, we just failed
else:
# pick randomly between non-empty strings
return random.choice([w for w in [head, tail] if w != ""])
def getBanterHead(words, morphWord):
morphHead = morphWord[0:-1]
morphLast = morphWord[-1]
filtered = list(filter(lambda word: re.search(morphHead, word), words))
if len(filtered) == 0:
return "" # nothing applicable found
word = random.choice(filtered).strip("\n")
end = word.find(morphHead) + len(morphHead)
if end == len(word):
return word + morphLast
else:
if "aeiou".find(word[end]) > -1: # just append 't'
return word[:end] + morphLast + word[end:]
else: # replace the letter with 'b'
return word[:end] + morphLast + word[end + 1 :]
def getBanterTail(words, morphWord):
morphTail = morphWord[1:]
morphFirst = morphWord[0]
filtered = list(filter(lambda word: re.search(morphTail, word), words))
if len(filtered) == 0:
return "" # nothing applicable found
word = random.choice(filtered).strip("\n")
start = word.find(morphTail)
if start == 0:
return morphFirst + word
else:
if "aeiou".find(word[start]) > -1: # just append a 'b'
return word[:start] + morphFirst + word[start:]
else: # replace the letter with 'b'
return word[: start - 1] + morphFirst + word[start:]

191
Code/irc/util/numberwang.py Normal file
View File

@ -0,0 +1,191 @@
#!/usr/bin/python3
import inflect
import random
p = inflect.engine()
LIMIT_GUESSING = True
MIN_ROUNDS = 5
MAX_ROUNDS = 12
SCORE_FILE = "/home/krowbar/Code/irc/data/numberwangscores.txt"
SHOW_TOP_NUM = 5
GOOD_CHAN = "#bots"
roundsLeft = 0
bonusRound = 0
guesses = 0
lastGuesser = ""
currentScores = {}
def resetGlobals():
global roundsLeft
global bonusRound
global guesses
global lastGuesser
global currentScores
roundsLeft = 0
bonusRound = 0
guesses = 0
lastGuesser = ""
currentScores.clear()
# returns a number of lines to be printed out. Numbers represent time to sleep
# between prints
def start_numberwang(channel, user):
if channel != GOOD_CHAN:
return [ "Numberwang has been disabled in {} due to spamminess. Please join {} to start a game.".format(channel, GOOD_CHAN) ]
message = [ "{} started a game".format(user) ]
resetGlobals()
message.append("It's time for Numberwang!")
message.append(1)
message.append("Here's how to play:")
message.append("1. There are 10 rounds")
message.append("2. Each round lasts 10 seconds. You're up against the clock!")
message.append("3. Play your numbers, as long as they're between 0 and 99.")
message.append("4. That's Numberwang!")
message.append(2)
message.append("Let's get started!")
global roundsLeft
global bonusRound
roundsLeft = random.randint(MIN_ROUNDS, MAX_ROUNDS)
bonusRound = random.randint(2, roundsLeft - 1)
# debug print
print(
"There will be {} rounds with the bonus on round {}".format(
str(roundsLeft), str(roundsLeft - bonusRound + 1)
)
)
def print_scores():
scoreStrs = []
first = True
for name in currentScores:
scoreStrs.append(
"{} is {} on {}".format(
name,
("also " if not first and random.randint(1, 3) == 3 else ""),
currentScores[name],
)
)
first = False
return p.join(scoreStrs)
def guess_numberwang(user, messageText):
global guesses
global lastGuesser
global currentScores
global roundsLeft
# print(user + " guessed '" + messageText + "'")
guess = re.sub(
"[^0-9]", "", messageText.split()[0]
) # must have a number in the first 'word'
messages = []
if guess:
if LIMIT_GUESSING and user == lastGuesser:
messages.appen("{}, you just guessed! Give another player a try!".format(user))
else:
guesses += 1
lastGuesser = user
###CORRECT GUESS###
if (
random.randint(0, 10) > 10 - guesses
): # the more guesses, the higher the probability
guesses = 0
lastGuesser = ""
message = "{}: THAT'S NUMBERWANG!".format(user)
points = random.randint(2, 10) * (
random.randint(2, 4) if roundsLeft == bonusRound else 1
)
if user in currentScores.keys():
currentScores[user] += points
else:
currentScores[user] = points
roundsLeft -= 1
message.append(2)
if roundsLeft == 0:
messages.append("Numberwang is now over. Thank you for playing!")
messages.append("Final scores:")
messages.extend(print_scores())
save_scores()
else:
messages.extend(print_scores())
newRoundStr = ""
if roundsLeft == 1:
newRoundStr += "The last round is Wangernumb!"
elif roundsLeft == bonusRound:
newRoundStr += "**Bonus Round!**"
else:
newRoundStr += "New Round!"
if random.randint(1, 10) > 8:
newRoundStr += " Let's rotate the board!"
messages.append("{} Start guessing!".format(newRoundStr))
###INCORRECT GUESS###
else:
messages.append("{}, {}, {} Numberwang!".format(
random.choice(["Sorry", "I'm sorry", "No", "Nope"]),
user,
random.choice(
[
"that's not",
"that is not",
"that isn't",
"that is not",
"that won't make",
"that will not make",
]
),
))
return messages
def stop_numberwang(user):
# print(user + " stopped a game")
resetGlobals()
return ["Numberwang has been stopped. No points have been awarded. {} is such a party pooper!".format(user)]
def save_scores():
with open(SCORE_FILE, "r+") as scorefile:
scores = scorefile.readlines()
scorefile.seek(0)
scorefile.truncate()
for line in scores:
for name in currentScores:
score = line.strip("\n").split("&^%")
if score[0] == name:
line = "{}&^%{}\n".format(
score[0], int(score[1]) + currentScores[name]
)
del currentScores[name]
break
scorefile.write(line)
for name in currentScores: # new wangers
scorefile.write("{}&^%{}\n".format(name, currentScores[name]))
def show_highscores():
with open(SCORE_FILE, "r") as scorefile:
scores = []
for line in scorefile.readlines():
sline = line.strip("\n").split("&^%")
scores.append((int(sline[1]), sline[0]))
scores = sorted(scores, reverse=True)[:SHOW_TOP_NUM]
return ["====TOP WANGERS===="] + [" :== ~{} ({} points!) ==".format(score[1], score[0]) for score in scores]
def show_user_score(user):
with open(SCORE_FILE, "r") as scorefile:
for line in scorefile.readlines():
score = line.strip("\n").split("&^%")
if user == score[0]:
return ["{}: Your global numberwang score is {}!".format(user, score[1])]
# if we don't find a score line
return ["{}: You haven't scored any points yet!".format(user)]

187
Code/irc/util/puzzle.py Normal file
View File

@ -0,0 +1,187 @@
#!/usr/bin/python3
import random
import hashlib
import inflect
import util.quote_puzzle
import util.dict_puzzle
import util.textcaptcha
p = inflect.engine()
primes = [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]
fuzz_amount = 3
def make_puzzle(obfuscate=True, roll=None):
answer = 0
bonus = 0
puzzle = random.choice(
[
"Prove you're not a robot: ",
"Are you a robot?: ",
"Anti-bot check: ",
"Counter-cnd0rphant measures: ",
"Cosn0k countermeasures: ",
"Anti-tilde7hief precautions: ",
"Pro-l0gin challenge: ",
"Riddle me this: ",
"Would you like to play a game? ",
"How about this? "
]
)
puzzle += random.choice(
[
"What is",
"What do you get from",
"What do you get with",
"What is the value of",
"Can you answer",
"Can you tell me",
"Ask wiz3bot what is",
"Does anybody know",
"Who knows",
"Guess what",
"Calculate",
"Find out"
]
)
puzzle += " "
roll = roll or random.randrange(0, 21)
var1 = random.randrange(1, 10)
var2 = random.randrange(1, 10)
var3 = random.randrange(1, 20)
var4 = random.randrange(1, 20)
let1_ord = random.randrange(ord("a"), ord("z") + 1)
if roll == 0:
answer = var1 + var2
puzzle += "{} {} {}".format(
p.number_to_words(var1),
random.choice(["and", "plus", "sum", "add"]),
p.number_to_words(var2),
)
elif roll == 1:
answer = var1 * var2
puzzle += "{} {} {}".format(
p.number_to_words(var1),
random.choice(["times", "multiply", "multiplied by", "product"]),
p.number_to_words(var2),
)
elif roll == 2:
if var2 > var1:
var1, var2 = var2, var1
answer = var1 - var2
puzzle += "{} {} {}".format(
p.number_to_words(var1),
random.choice(["minus", "subtract", "take away", "less"]),
p.number_to_words(var2),
)
elif roll == 3:
if var2 > var1:
var1, var2 = var2, var1
answer = var1 * 2 / var2
puzzle += "{} {} {} (no remainder)".format(
p.number_to_words(var1 * 2),
random.choice(["divided by", "over"]),
p.number_to_words(var2),
)
elif roll == 4:
answer = var1 ** var2
puzzle += "{} to the {} power".format(
p.number_to_words(var1), p.ordinal(p.number_to_words(var2))
)
elif roll == 5:
p1 = random.choice(primes)
p2 = random.choice(primes)
def answer(guess):
# Check the the numbers entered are correct, regardless of order
# or surrounding whitespace.
attempt = sorted(word.strip() for word in guess.split(","))
correct = sorted([str(p1), str(p2)])
return attempt == correct
bonus = 1
puzzle += "{} when factored into its two primes (answer in the form of the two primes with a comma between)".format(
p.number_to_words(p1 * p2)
)
elif roll == 6:
prime = random.choice(primes)
answer = prime % var1
puzzle += p.number_to_words(prime) + " modulus " + p.number_to_words(var1)
elif roll == 7:
if let1_ord + var1 > ord("z"):
let1_ord -= var1
answer = chr(let1_ord + var1)
puzzle += "letter comes {} letters after '{}'".format(
p.number_to_words(var1), chr(let1_ord)
)
obfuscate = False
elif roll == 8:
if let1_ord - var1 < ord("a"):
let1_ord += var1
answer = chr(let1_ord - var1)
puzzle += "letter comes {} letters before '{}'".format(
p.number_to_words(var1), chr(let1_ord)
)
obfuscate = False
elif roll == 9:
answer, puzzle = util.quote_puzzle.get_quote()
obfuscate = False
elif roll == 10:
answer = str(min(var1, var2, var3, var4))
puzzle += "the {} of {}, {}, {}, and {}".format(
random.choice(["smallest", "lowest"]),
p.number_to_words(var1),
p.number_to_words(var2),
p.number_to_words(var3),
p.number_to_words(var4),
)
elif roll == 11:
answer = str(max(var1, var2, var3, var4))
puzzle += "the {} of {}, {}, {}, and {}".format(
random.choice(["biggest", "largest"]),
p.number_to_words(var1),
p.number_to_words(var2),
p.number_to_words(var3),
p.number_to_words(var4),
)
elif roll <= 14: # 12-14
answer, puzzle = util.dict_puzzle.get_puzzle()
obfuscate = False
elif roll <= 17: # 15-17
answer, puzzle = util.dict_puzzle.get_anagram()
obfuscate = False
elif roll == 18:
answer, puzzle = util.quote_puzzle.get_chuck()
obfuscate = False
elif roll <= 20: #19-20
captcha = util.textcaptcha.get_captcha()
puzzle = captcha['q'] # the question part of the captcha
# print(captcha)
answer = lambda a : hashlib.md5(a.encode()).hexdigest() in captcha['a'] # check if the answer is correct
obfuscate = False
bonus = 1
# Add a question mark on the end of the question
if puzzle[-1] != "?":
puzzle += "?"
if obfuscate == True:
for _ in range(fuzz_amount):
idx = random.randrange(len(puzzle) - 2) # get between 0 and string length (except the ? mark)
puzzle = "".join(
[puzzle[0:idx], chr(random.randint(33, 126)), puzzle[idx + 1 :]]
)
return [puzzle, answer, bonus]

View File

@ -0,0 +1,27 @@
#!/usr/bin/python3
import json
import requests
import random
import re
quotefile = "/home/karlen/irc/quotes.txt"
chuckfile = "/home/krowbar/Code/irc/data/chuck.txt"
chuckApi = "https://api.icndb.com/jokes/random"
def get_quote():
quotes = open(quotefile, "r").read().split("---")
quote, attr = random.choice(quotes).strip().splitlines()
quote = quote[:200] # get only the first 200 chars
word = random.choice([q for q in quote.split(" ") if len(q) > 1])
quote = quote.replace(word, re.sub(r"[a-zA-Z]", "_", word))
return [word, 'Fill in the blank: "' + quote + '" ' + attr]
def get_chuck():
#chucks = open(chuckfile, "r").readlines()
#chuck = random.choice(chucks).rstrip()[:200] # get only the first 200 chars
# ha ha! let's see if we can confus login
chuck = json.loads(requests.get(chuckApi).content.decode())['value']['joke'][:200]
word = random.choice([w for w in chuck.split(" ") if len(w) > 1 and w.lower() != "chuck" and w.lower() != "norris"])
chuck = chuck.replace(word, re.sub(r"[a-zA-Z]", "_", word)).replace("&quot;", "\"")
return [word, 'Fill in the blank: "{}"'.format(chuck)]

View File

@ -0,0 +1,40 @@
#!/usr/bin/python3
import requests
# from lxml.html import fromstring
from bs4 import BeautifulSoup
import random
def getRhymes(word):
words = []
url = "http://www.rhymer.com/RhymingDictionaryLast/%s.html" % word
soup = BeautifulSoup(requests.get(url).content, "html.parser")
for t in soup.find_all("table", "table"):
words.append(
random.choice(
[
w
for w in t.text.split("\n")
if w not in [u"", u"\xa0"] and "-" not in w
]
)
)
return words
def rhymeZone(word):
words = []
url = (
"http://rhymezone.com/r/rhyme.cgi?Word=%s&typeofrhyme=perfect&org1=syl&org2=l&org3=y"
% word
)
soup = BeautifulSoup(requests.get(url).content, "html.parser")
for t in soup.find_all("a", "d"):
w = t.text.rstrip()
if w not in [u"", u"\xa0"] and "?" not in t:
words.append(w)
random.shuffle(words)
return words[0:5]

View File

@ -0,0 +1,11 @@
#!/usr/bin/python3
import hashlib
import json
import requests
url = "http://api.textcaptcha.com/krowbar@tilde.town.json"
def get_captcha():
return json.loads(requests.get(url).content.decode())

282
Code/irc/util/tilde.py Executable file
View File

@ -0,0 +1,282 @@
#!/usr/bin/python3
# Import some necessary libraries.
import random
import inflect
import util.puzzle
p = inflect.engine()
challenges = {}
SCORE_FILE = "/home/krowbar/Code/irc/data/tildescores.txt"
JACKPOT_FILE = "/home/krowbar/Code/irc/data/tildejackpot.txt"
JACKPOT_MIN = 3
DEBUG = False
GOOD_CHAN = "#bots" # The name of the "good" channel that the bot is allowed to run in
def too_recent(time1, time2):
return int(float(time1)) - int(float(time2)) < 60 * 60
def get_positive():
return random.choice(
[
"Yes",
"Yep",
"Yeppers",
"Correct",
"You got it",
"Yeah",
"Right on",
"Uh-huh",
"Positive",
"Totally right",
"Close enough",
"That's it",
"Winner, winner",
"Bingo",
"Affirmative",
]
)
def get_negative():
return random.choice(
[
"No",
"Nope",
"Sorry",
"Wrong",
"Nuh-uh",
"Negatory",
"Incorrect",
"Not today",
"Try again",
"Maybe later",
"Maybe next time",
"Probably not",
"Answer hazy",
"Not quite",
"Not even close",
"Not for you",
"I think not"
]
)
def get_superlative(score):
if score > 4:
return random.choice(
[
"super cool",
"totally rad",
"extraordinary",
"dynomite",
"#topdrawer",
"a #TopLad",
"the cat's meow",
"a tilde town hero",
"my favorite person",
"incredibly lucky",
"unbelievable",
"a tilde town hunk",
"could bring all the boys to the yard",
"worth twice their weight in gold",
"the hero we need",
"no ordinary townie",
]
)
elif score > 2:
return random.choice(
[
"really cool",
"pretty neat",
"rather nice",
"a dynamic doggo",
"radical",
"intense",
"pretty lucky",
"knows the territory",
"has what it takes",
"has mad skillz",
"going the distance",
"a hard worker",
"my sunshine",
"ready to rumble",
]
)
else:
return random.choice(
[
"cool",
"nice",
"acceptible",
"good enough",
"a promising pupper",
"better than a horse",
"swell",
"a little lucky",
"just credible",
"my friend",
"probably not a robot",
"valuable to the team",
"now trending",
]
)
def get_bad_thing():
return random.choice(
[
"is a meanie",
"mugs me right off",
"miffed me off",
"is worse than a horse",
"smells like a ghost",
"probably didn't bathe today",
"probably shakes babies",
"didn't guess hard enough",
"isn't lucky",
"smells of elderberries",
"should reconsider their life choices",
"did't believe in the heart of the tilde",
"came to the wrong side of town",
"should have stopped while they were ahead",
"requires annotations from an authoratative source",
"could have been a contender",
"spreads vicious rumors",
"drank my milkshake",
"is probably cheating",
"is trying too hard",
"didn't really try",
"should try harder",
"caught me in a bad mood",
"should have gone with their first choice",
"did not receive IFR clearance from tower",
"was tardy for class",
"is on double secret probation",
"forgot their keys",
"forgot to bribe me",
"forgot to close the door",
"waited too long",
"doesn't call me on my cellphone",
"isn't wearing a seatbelt",
"didn't courtesy flush",
"asked a bot for answers",
"was right but I didn't feel like it",
"is right on opposite day",
"actually answered the last question",
"has their pants on backwards",
"forgot their own name",
]
)
def get_prize(user, isHuman, bonus=0):
prizes = [1] * 8 + [2] * 4 + [3] * 2 + [5] * isHuman # no 5pt prize for non-humans
prize = random.choice(prizes) + bonus
if (
random.randint(1, 10) > 6 - 4 * isHuman
): # 80% of the time it's a normal prize (40% for not humans)
return [
prize,
"{}: {}! You are {} and get {} tildes!".format(
user,
(get_positive() if isHuman else get_negative()),
get_superlative(prize),
p.number_to_words(prize),
),
]
else: # 20% of the time its a jackpot situation
with open(JACKPOT_FILE, "r+") as jackpotfile:
jackpot = int(jackpotfile.readline().strip("\n"))
jackpotfile.seek(0)
jackpotfile.truncate()
if (
random.randint(1, 10) > 1 or not isHuman
): # 90% of the time it's a non-prize. non-humans never win jackpot
new_jackpot = jackpot + max(1, prize)
jackpotfile.write(
str(new_jackpot)
) # increase the jackpot by the prize size
return [
0,
"{} {} and gets no tildes! (Jackpot is now {} tildes)".format(
user, get_bad_thing(), new_jackpot
),
]
else: # hit jackpot!
jackpotfile.write(str(JACKPOT_MIN))
return [
jackpot,
"{} hit the jackpot and won **{}** tildes!".format(
user, p.number_to_words(jackpot)
),
]
def show_jackpot():
with open(JACKPOT_FILE, "r") as jackpotfile:
jackpot = int(jackpotfile.readline().strip("\n"))
return "The jackpot is currently {} tildes!".format(p.number_to_words(jackpot))
def give_tilde(user, time, human, bonus=0):
found = False
with open(SCORE_FILE, "r+") as scorefile:
scores = scorefile.readlines()
scorefile.seek(0)
scorefile.truncate()
message = ""
for score in scores:
name, score_on_file, timestamp = score.strip("\n").split("&^%")
if name == user:
found = True
if too_recent(time, timestamp) and not DEBUG:
message = "{} asked for a tilde too recently and {}. Try again later.".format(user, get_bad_thing())
else:
prizevalue, prizetext = get_prize(user, human, bonus)
score = "{}&^%{}&^%{}\n".format(
user, str(int(score_on_file) + prizevalue), time
)
message = prizetext
scorefile.write(score)
if not found:
prizevalue, prizetext = get_prize(user, True, bonus)
scorefile.write("{}&^%{}&^%{}\n".format(user, str(prizevalue + 1), time))
message = "Welcome to the tilde game, {}! Here's {} free tildes to start you off.".format(user, p.number_to_words(prizevalue + 1))
return message
def show_tildescore(user):
with open(SCORE_FILE, "r") as scorefile:
for _idx, score in enumerate(scorefile):
record = score.strip("\n").split("&^%")
if record[0] == user:
return "{} has {} tildes!".format(user, p.number_to_words(record[1]))
# person has not played yet
return "{} has no tildes yet!".format(user)
def challenge(channel, user, time):
global challenges
challenge = util.puzzle.make_puzzle()
challenges[user] = challenge[1:]
return "{}: {}".format(user, challenge[0])
def challenge_response(user, time, msg):
global challenges
# print(msg)
response = ""
if user in challenges:
answer, bonus = challenges[user]
if (callable(answer) and answer(msg.lower())) or (
msg.lower() == str(answer).lower() or msg == p.number_to_words(answer)
):
response = give_tilde(user, time, True, bonus)
else:
response = give_tilde(user, time, False, 0)
del challenges[user]
# delete the user from challenges either way
return response

95
Code/irc/util/topic.py Normal file
View File

@ -0,0 +1,95 @@
#!/usr/bin/python3
import inflect
import random
scores_file = "/home/krowbar/Code/irc/data/topicscores.txt"
channel_topics = "/home/krowbar/Code/irc/data/topics_{}.txt"
random_topics = "/home/krowbar/Code/irc/data/randomtopics.txt"
p = inflect.engine()
def get_topic(channel, user, time):
# topic scores are saved as <USER>&^%<GETS SCORE>&^%<SETS SCORE>
with open(scores_file, "r") as scorefile:
scores = scorefile.readlines()
userscore = 1
found = False
with open(scores_file, "w") as scorefile:
for idx, score in enumerate(scores):
data = score.strip("\n").split("&^%")
if data[0] == user:
found = True
userscore = int(data[1]) + 1
scores[idx] = data[0] + "&^%" + str(userscore) + "&^%" + data[2] + "\n"
scorefile.writelines(scores)
if not found:
scorefile.write(user + "&^%1&^%0\n")
with open(channel_topics.format(channel), "r") as topics:
topic = topics.readlines()[-1].strip("\n").split("&^%", 3)
byuser = util.get_name(topic[1])
return "I've told you {} times! It's \"{}\" (set by {} {})".format(
p.number_to_words(userscore),
topic[2],
byuser,
util.pretty_date(int(topic[0])),
)
def count_topic(channel, user, time, msg):
with open(channel_topic.format(channel), "a") as topics:
topics.write(time + "&^%" + user + "&^%" + msg + "\n")
with open(scores_file, "r") as scorefile:
scores = scorefile.readlines()
userscore = 1
found = False
with open(scores_file, "w") as scorefile:
for idx, score in enumerate(scores):
data = score.strip("\n").split("&^%")
if data[0] == user:
found = True
userscore = int(data[2]) + 1
scores[idx] = data[0] + "&^%" + data[1] + "&^%" + str(userscore) + "\n"
scorefile.writelines(scores)
if not found:
scorefile.write(user + "&^%0&^%1")
return "{} has changed the topic {} times!".format(user, p.number_to_words(userscore))
def set_topic(channel, user, time, msg):
ircsock.send("TOPIC " + channel + " :" + msg + "\n")
return count_topic(channel, user, time, msg)
def random_topic(channel, user, time, setTopic=False):
with open(random_topics) as rtopics:
msg = random.choice(rtopics.readlines()).strip("\n")
if setTopic:
set_topic(channel, user, time, msg)
else:
return "Suggested Topic: {}".format(msg)
def rollcall(channel):
return "topicbot reporting! I respond to !topic !settopic !suggesttopic !thistory"
def topic_history(channel, user, count):
try:
iCount = int(count.split()[1])
except (ValueError, IndexError):
iCount = 3
if iCount > 10:
iCount = 10
if iCount < 1:
iCount = 3
with open(channel_topics.format(channel), "r") as topicsfile:
message = "Ok, here are the last {} topics".format(p.number_to_words(iCount))
for idx, topic in enumerate(reversed(topicsfile.readlines()[-iCount:])):
topic = topic.strip("\n").split("&^%", 3)
byuser = util.get_name(topic[1])
message += "\n{}: {} (set by {} {})".format( str(idx + 1), topic[2], byuser, util.pretty_date(int(topic[0])) )
return message

49
Code/irc/util/tumblr.py Normal file
View File

@ -0,0 +1,49 @@
#!/usr/bin/python3
from bs4 import BeautifulSoup
import random
import re
import requests
def tumble(url):
# Find the max pages
soup = BeautifulSoup(requests.get(url).content, "html.parser")
pages = soup.findAll("span", "page-numbers")[0].text.split("/")[
1
] # this could totally fail several ways
tries = 3
while True:
try:
page = random.randrange(1, int(pages) + 1)
# Parse a page
soup = BeautifulSoup(
requests.get("{}/page/{}".format(url, page)).content, "html.parser"
)
article = random.choice(soup.findAll("article"))
quote = article.find("blockquote").text.replace("\n", "")
if len(article.find("footer").findAll("ul")) > 1:
quote += re.sub(
"\n+", " ", article.find("footer").findAll("ul")[0].text
)
# the hash tags
quote += (
"("
+ re.sub("\n+", " ", article.find("footer").findAll("ul")[1].text)
+ ")"
)
# and the date and notes
else:
quote += (
"("
+ re.sub("\n+", " ", article.find("footer").findAll("ul")[0].text)
+ ")"
)
# just the date and notes
return quote
except: # sometimes we fail. let's retry a few times
if tries == 0:
return ""
else:
tries -= 1
break

10
Code/irc/util/welch.py Normal file
View File

@ -0,0 +1,10 @@
import random
def get_thing():
file = "/home/krowbar/logs/welchdata.txt"
thing = ""
return (
"Thing Mr. Welch can no longer do in a RPG #"
+ random.choice(list(open(file))).rstrip()
)

61
Code/irc/util/whoSaid.py Normal file
View File

@ -0,0 +1,61 @@
#!/usr/bin/python3
import datetime
import fileinput
import time
import calendar
import re
import operator
from util import nameFix
MAX_NODES = 5
logfile = "/home/archangelic/irc/log"
timeCutoff = calendar.timegm(time.gmtime()) - (3 * 7 * 24 * 60 * 60) # 3 weeks
def whoSaid(text):
if not text:
return "No text given :("
else:
result = whoSaid_data(text)
date = datetime.date.fromtimestamp(result["timecutoff"])
dateStr = date.strftime("%B %d")
if not result["data"]:
msg = "Nobody said '%s' since %s" % (text, dateStr)
else:
msg = "Since %s, %s said '%s' %d times" % (
dateStr,
result["data"][0][0],
text,
result["data"][0][1],
)
if len(result["data"]) > 1:
msg += " and %s said it %d times" % (
result["data"][1][0],
result["data"][1][1],
)
return msg
def whoSaid_data(word):
word = word.lower()
userData = (
{}
) # hash keyed by "user" that contains a hash of mentioned other users with count
# Get a list of all user names by checking the logs for people who have said things
with open(logfile, "r") as log:
for line in log:
try:
time, user, message = line.split("\t", 3)
time = int(time)
user = nameFix.fixName(user).lower()
except ValueError:
continue # There are some bad lines in the log file that we'll ignore if we can't parse
if time > timeCutoff and message[0] is not "!" and word in message.lower():
if user in userData:
userData[user] += 1
else:
userData[user] = 1
userData = sorted(userData.items(), key=operator.itemgetter(1), reverse=True)
return {"timecutoff": timeCutoff, "data": userData}

View File

@ -0,0 +1,87 @@
#!/usr/bin/python3
from bs4 import BeautifulSoup
import random
import requests
def get_philosophy(word, max_steps=20):
step_words = [word]
steps = 0
url = "https://en.wikipedia.org/wiki/%s" % word
while steps < max_steps:
print("url: {}".format(url))
soup = BeautifulSoup(requests.get(url).content, "html.parser")
title = soup.find("h1", id="firstHeading")
content = soup.find("div", id="mw-content-text")
if not content:
break
item = [
item
for item in content.find_all("a")
if not item.get("class")
and not item.get("target")
and item.get("title")
and not "Wikipedia:" in item.get("title")
and not "Category:" in item.get("title")
and not "Help:" in item.get("title")
and not "Portal:" in item.get("title")
and not "Special:" in item.get("title")
and not "Talk:" in item.get("title")
and not "Template:" in item.get("title")
and not "File:" in item.get("title")
and "Edit section:" not in item.get("title")
and "Commons:" not in item.get("title")
and not item.get("title") in step_words
][0]
step_words.append(item.get("title"))
# print item.get('title') + "\n"
url = "https://en.wikipedia.org{}".format(item.get("href"))
steps += 1
return step_words
def containsAny(str, set):
return 1 in [c in str for c in set]
def get_philosophy_lower(word, max_steps=20):
step_words = [word]
steps = 0
url = "https://en.wikipedia.org/wiki/{}".format(word.replace(" ", "%20"))
while steps < max_steps:
print("url: {}".format(url))
soup = BeautifulSoup(requests.get(url).content, "html.parser")
if soup.find(id="noarticletext"):
step_words.append("(not found)")
break
title = soup.find("h1", id="firstHeading")
content = soup.find("div", id="mw-content-text")
if not content:
break
links = [
item
for item in content.find_all("a")
if not item.get("class")
and item.text
and item.text[0].islower()
and not containsAny(item.text, ":()")
and item.get("title")
and not containsAny(item.get("title"), ":()")
and not item.get("title") in step_words
]
if not links:
step_words.append("(dead end)")
break
item = links[0] # grab the first good link item
# print "Checking %s %s" % (item.get('title'), item.text)
step_words.append(item.get("title"))
if item.get("title") == "Philosophy":
break
# print item.get('title') + "\n"
url = "https://en.wikipedia.org%s" % item.get("href")
steps += 1
return step_words

View File

@ -0,0 +1,31 @@
#!/usr/bin/python3
import requests
from bs4 import BeautifulSoup
import util.duckduckgo
def xkcd(query):
res = util.duckduckgo.get_zci("site:xkcd.com " + query)
title = ""
try: # ddg returns a url for these searches. i want a title as well
title = BeautifulSoup(requests.get(res).content, "html.parser").title.text
except:
pass # just swallow the error. maybe the result wasn't a url or something else bad happened
return [(((title + " - ") if title else "") + res)]
# never mind, blocked by ddg
# def xkcd_links(query):
# url = "https://duckduckgo.com/html/?q=site%3Axkcd.com+" + query.replace(' ', '+')
# soup = BeautifulSoup(requests.get(url).content, 'html.parser')
# items = soup.find_all("a", class_="result__a")
# print items
# items = list(filter(lambda i: i[0:8] == 'xkcd.com',
# [i.find(class_="result__title").text.strip() for i in items]))
# print items
# def pretty_link(item):
# url = item.find(class_="result__url").text.strip()
# title = item.find(class_="result__title").text.strip()
# return (title + ' - ' + url) if title else url
#
# links = map(lambda url: pretty_link(url), items)
# return links

View File

@ -0,0 +1,43 @@
#!/usr/bin/python3
import pinhook.plugin
import time
from util import numberwang
@pinhook.plugin.register('!rollcall')
def rollcall_plugin(msg):
return pinhook.plugin.message("Is it time for Numberwang? It might be! Start a new game with !numberwang or stop a current game with !wangernumb Get your score with !myscore and the list of top wangers with !topwangers")
# the numberwang lib returns message lists that may contain numbers.
# if we get one of those, sleep for that long
def print_messages(msg, messages):
for line in messages:
if isinstance(line, int) or isinstance(line, float):
time.sleep(line)
else:
msg.privmsg(msg.channel, line)
@pinhook.plugin.register('!numberwang')
def numberwang_plugin(msg):
if numberwang.roundsLeft == 0:
print_messages(msg, numberwang.start_numberwang(msg.channel, msg.nick))
@pinhook.plugin.register('!wangernumb')
def wangernumb_plugin(msg):
if numberwang.roundsLeft > 0:
print_messages(msg, numberwang.stop_numberwang(msg.nick))
@pinhook.plugin.register('!topwangers')
def top_plugin(msg):
print_messages(msg, numberwang.show_highscores())
@pinhook.plugin.register('!myscore')
def my_score_plugin(msg):
print_messages(msg, numberwang.show_user_score(msg.nick))
@pinhook.plugin.listener('numberwang')
def numberwang_listener(msg):
if msg.text.split()[0] in ['!numberwang', '!wangernumb', '!topwangers', '!myscore'] or numberwang.roundsLeft is 0 or msg.channel != numberwang.GOOD_CHAN:
return
print_messages(msg, numberwang.guess_numberwang(msg.channel, msg.user, msg.arg))

13
madlibs/baseball.madlib Normal file
View File

@ -0,0 +1,13 @@
It was the bottom of the {{an ordinal number, ending in -th or -rd}} and the {{a city}} {{an animal, plural}} were down {{a number}} points against their rivals, the {{a city}} {{an occupation}}.
Young {{a male name}} Jackson was up to the plate. He'd have to {{a verb}} this pitch if his team any chance of winning the game.
The pitch came in {{an adjective}}, the batter swung but was too {{another adjective}}! Strike one!
The second pitch, but {{a noun}} got in the batter's {{a body part}}! Strike two!
"{{an encouraging aphorism}}" somebody shouted from the stands.
The pitcher wound up and threw a {{a shape}}. The batter hit the ball but it went wide! "{{an adjective}} ball!" The umpire yelled.
The batter was feeling very {{an emotion}}, {{a liquid}} was pouring down his face.
"You'll never be able to hit this one!" the pitcher {{a verb, past tense}} before letting loose!
The batter closed his eyes, wished on his lucky {{an astrological body, plural}}, and swung.
"{{a loud sound effect}}!"
The ball flew over the {{a direction}} field wall! Home run!
After he ran the bases, his teammates cheered and slapped him on the {{a body part}}!
The game was tied up, but it still wasn't over... (To be continued?)

View File

@ -0,0 +1,3 @@
Here is a number {{a number#}} ordinal {{a number#|ordinal}}, numeric {{a number#|numeric}}
Here is a word {{a word#1}} upper {{a word#1|upper}} lower {{a word#1|lower}}
Here is another word {{a word#2}} title {{a word#2|title}}