mirror of
https://github.com/RussellChamp/tilde-projects.git
synced 2026-10-28 00:22:34 +00:00
Add files I forgot
This commit is contained in:
1 parent
5f1bf146c3
commit
772995c0ff
29 files changed
+1807
No files matched your search
Executable
+64
@@ -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()
|
||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
../util.py
|
||||||
@@ -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")
|
||||||
Executable
+41
@@ -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))
|
||||||
|
|
||||||
@@ -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))
|
||||||
|
|
||||||
Whitespace-only changes.
@@ -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
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -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)]
|
||||||
Executable
+198
@@ -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])
|
||||||
@@ -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())
|
||||||
@@ -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
|
||||||
@@ -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:]
|
||||||
@@ -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)]
|
||||||
@@ -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]
|
||||||
@@ -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(""", "\"")
|
||||||
|
return [word, 'Fill in the blank: "{}"'.format(chuck)]
|
||||||
@@ -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]
|
||||||
@@ -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())
|
||||||
|
|
||||||
Executable
+282
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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()
|
||||||
|
)
|
||||||
@@ -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}
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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))
|
||||||
@@ -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?)
|
||||||
@@ -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}}
|
||||||
Reference in new issue
Block a user