Compare commits
57 commits
refresh
...
ChaosChemn
Author | SHA1 | Date | |
---|---|---|---|
![]() |
358b415566 | ||
![]() |
3e1ea6ac4e | ||
![]() |
48b627ad4b | ||
![]() |
1f1ff649c9 | ||
8344fe7693 | |||
a6992d5d1a | |||
![]() |
21db4efd98 | ||
![]() |
8941d59dc2 | ||
09ce708709 | |||
![]() |
29cc95f0ad | ||
4a02f545ea | |||
![]() |
28176ad2ad | ||
![]() |
651d4a953e | ||
![]() |
80711e1278 | ||
a88d5ef0bd | |||
827c5c73e8 | |||
![]() |
580415ed76 | ||
c562a2c7ae | |||
![]() |
4b5e86c237 | ||
![]() |
11687a9ad0 | ||
296de07e14 | |||
dfbead6946 | |||
![]() |
e30eca5ebd | ||
![]() |
2a3c9f52dc | ||
![]() |
f88c3267d4 | ||
![]() |
2b18eaac5a | ||
0650046d18 | |||
![]() |
4e386c9008 | ||
![]() |
05bfb9099a | ||
![]() |
bfa3fb6e74 | ||
![]() |
d415d0fc69 | ||
![]() |
433d97d276 | ||
![]() |
121715115a | ||
![]() |
620de651ce | ||
![]() |
3f205eaafa | ||
![]() |
59cd8380d2 | ||
![]() |
7cce9bf27e | ||
![]() |
0ba2001b62 | ||
![]() |
63fc042027 | ||
![]() |
9421d8160d | ||
![]() |
4b4ac2d918 | ||
![]() |
05a68faf1d | ||
![]() |
40328cf24f | ||
![]() |
fb471bee17 | ||
![]() |
48ab7417b8 | ||
![]() |
97a3283eff | ||
![]() |
6d147e1677 | ||
![]() |
c99c44616c | ||
![]() |
1062e69e56 | ||
![]() |
5ca45fea4b | ||
![]() |
04af154c5b | ||
![]() |
f82041fc87 | ||
![]() |
a027bd780f | ||
![]() |
a611e0df45 | ||
![]() |
e49ec9a9c9 | ||
![]() |
4652ed90a3 | ||
![]() |
ff3ef576b7 |
129 changed files with 803 additions and 133 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,5 +1,6 @@
|
||||||
persist
|
persist
|
||||||
config
|
config
|
||||||
|
config.ssl
|
||||||
gitflow
|
gitflow
|
||||||
*.db
|
*.db
|
||||||
*.log
|
*.log
|
||||||
|
|
133
config.default
133
config.default
|
@ -1,64 +1,77 @@
|
||||||
{
|
{
|
||||||
"connections":
|
"connections": {
|
||||||
{
|
"hackint": {
|
||||||
"esper":
|
"server": "irc.hackint.eu",
|
||||||
{
|
"nick": "antibot",
|
||||||
"server": "irc.esper.net",
|
"user": "antibot",
|
||||||
"nick": "MyCloudBot",
|
"realname": "CloudBot - http://git.io/cloudbotirc",
|
||||||
"user": "cloudbot",
|
"mode": "",
|
||||||
"realname": "CloudBot - http://git.io/cloudbotirc",
|
"_nickserv_password": "",
|
||||||
"mode": "",
|
"-nickserv_user": "",
|
||||||
"nickserv_password": "",
|
"channels": [
|
||||||
"nickserv_user": "",
|
"#ChaosChemnitz",
|
||||||
"channels": ["#cloudbot", "#cloudbot2"],
|
"#logbot"
|
||||||
"invite_join": true,
|
],
|
||||||
"auto_rejoin": false,
|
"invite_join": true,
|
||||||
"command_prefix": "."
|
"auto_rejoin": false,
|
||||||
}
|
"command_prefix": "."
|
||||||
},
|
}
|
||||||
"disabled_plugins": [],
|
|
||||||
"disabled_commands": [],
|
|
||||||
"acls": {},
|
|
||||||
"api_keys":
|
|
||||||
{
|
|
||||||
"tvdb": "",
|
|
||||||
"wolframalpha": "",
|
|
||||||
"lastfm": "",
|
|
||||||
"rottentomatoes": "",
|
|
||||||
"soundcloud": "",
|
|
||||||
"twitter_consumer_key": "",
|
|
||||||
"twitter_consumer_secret": "",
|
|
||||||
"twitter_access_token": "",
|
|
||||||
"twitter_access_secret": "",
|
|
||||||
"wunderground": "",
|
|
||||||
"googletranslate": "",
|
|
||||||
"rdio_key": "",
|
|
||||||
"rdio_secret": ""
|
|
||||||
},
|
|
||||||
"permissions": {
|
|
||||||
"admins": {
|
|
||||||
"perms": ["adminonly", "addfactoid", "delfactoid", "ignore", "botcontrol", "permissions_users", "op"],
|
|
||||||
"users": ["examplea!user@example.com", "exampleb!user@example.com"]
|
|
||||||
},
|
},
|
||||||
"moderators": {
|
"disabled_plugins": [],
|
||||||
"perms": ["addfactoid", "delfactoid", "ignore"],
|
"disabled_commands": [],
|
||||||
"users": ["examplec!user@example.com"]
|
"acls": {},
|
||||||
}
|
"api_keys": {
|
||||||
},
|
"tvdb": "",
|
||||||
"plugins":
|
"wolframalpha": "",
|
||||||
{
|
"lastfm": "",
|
||||||
"factoids":
|
"rottentomatoes": "",
|
||||||
{
|
"soundcloud": "",
|
||||||
"prefix": false
|
"twitter_consumer_key": "",
|
||||||
|
"twitter_consumer_secret": "",
|
||||||
|
"twitter_access_token": "",
|
||||||
|
"twitter_access_secret": "",
|
||||||
|
"wunderground": "",
|
||||||
|
"googletranslate": "",
|
||||||
|
"rdio_key": "",
|
||||||
|
"rdio_secret": ""
|
||||||
},
|
},
|
||||||
"ignore":
|
"permissions": {
|
||||||
{
|
"admins": {
|
||||||
"ignored": []
|
"perms": [
|
||||||
}
|
"adminonly",
|
||||||
},
|
"addfactoid",
|
||||||
"censored_strings":
|
"delfactoid",
|
||||||
[
|
"ignore",
|
||||||
"mypass",
|
"botcontrol",
|
||||||
"mysecret"
|
"permissions_users",
|
||||||
]
|
"op"
|
||||||
|
],
|
||||||
|
"users": [
|
||||||
|
"examplea!user@example.com",
|
||||||
|
"exampleb!user@example.com"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"moderators": {
|
||||||
|
"perms": [
|
||||||
|
"addfactoid",
|
||||||
|
"delfactoid",
|
||||||
|
"ignore"
|
||||||
|
],
|
||||||
|
"users": [
|
||||||
|
"stummi!~Stummi@stummi.org"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"plugins": {
|
||||||
|
"factoids": {
|
||||||
|
"prefix": false
|
||||||
|
},
|
||||||
|
"ignore": {
|
||||||
|
"ignored": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"censored_strings": [
|
||||||
|
"mypass",
|
||||||
|
"mysecret"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
48
core/irc.py
48
core/irc.py
|
@ -44,7 +44,16 @@ class crlf_tcp(object):
|
||||||
return socket.socket(socket.AF_INET, socket.TCP_NODELAY)
|
return socket.socket(socket.AF_INET, socket.TCP_NODELAY)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.socket.connect((self.host, self.port))
|
noerror = 0
|
||||||
|
while 1:
|
||||||
|
try:
|
||||||
|
self.socket.connect((self.host, self.port))
|
||||||
|
break
|
||||||
|
except socket.gaierror as e:
|
||||||
|
time.sleep(5)
|
||||||
|
except socket.timeout as e:
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
thread.start_new_thread(self.recv_loop, ())
|
thread.start_new_thread(self.recv_loop, ())
|
||||||
thread.start_new_thread(self.send_loop, ())
|
thread.start_new_thread(self.send_loop, ())
|
||||||
|
|
||||||
|
@ -55,17 +64,25 @@ class crlf_tcp(object):
|
||||||
return socket.timeout
|
return socket.timeout
|
||||||
|
|
||||||
def handle_receive_exception(self, error, last_timestamp):
|
def handle_receive_exception(self, error, last_timestamp):
|
||||||
|
print("Receive exception: %s" % (error))
|
||||||
if time.time() - last_timestamp > self.timeout:
|
if time.time() - last_timestamp > self.timeout:
|
||||||
|
print("Receive timeout. Restart connection.")
|
||||||
self.iqueue.put(StopIteration)
|
self.iqueue.put(StopIteration)
|
||||||
self.socket.close()
|
self.socket.close()
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def handle_send_exception(self, error):
|
||||||
|
print("Send exception: %s" % (error))
|
||||||
|
self.iqueue.put(StopIteration)
|
||||||
|
self.socket.close()
|
||||||
|
return True
|
||||||
|
|
||||||
def recv_loop(self):
|
def recv_loop(self):
|
||||||
last_timestamp = time.time()
|
last_timestamp = time.time()
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
data = self.recv_from_socket(4096)
|
data = self.recv_from_socket(4096)
|
||||||
self.ibuffer += data
|
self.ibuffer += data
|
||||||
if data:
|
if data:
|
||||||
last_timestamp = time.time()
|
last_timestamp = time.time()
|
||||||
|
@ -79,6 +96,8 @@ class crlf_tcp(object):
|
||||||
if self.handle_receive_exception(e, last_timestamp):
|
if self.handle_receive_exception(e, last_timestamp):
|
||||||
return
|
return
|
||||||
continue
|
continue
|
||||||
|
except AttributeError:
|
||||||
|
return
|
||||||
|
|
||||||
while '\r\n' in self.ibuffer:
|
while '\r\n' in self.ibuffer:
|
||||||
line, self.ibuffer = self.ibuffer.split('\r\n', 1)
|
line, self.ibuffer = self.ibuffer.split('\r\n', 1)
|
||||||
|
@ -86,13 +105,19 @@ class crlf_tcp(object):
|
||||||
|
|
||||||
def send_loop(self):
|
def send_loop(self):
|
||||||
while True:
|
while True:
|
||||||
line = self.oqueue.get().splitlines()[0][:500]
|
try:
|
||||||
print ">>> %r" % line
|
line = self.oqueue.get().splitlines()[0][:500]
|
||||||
self.obuffer += line.encode('utf-8', 'replace') + '\r\n'
|
if line == StopIteration:
|
||||||
while self.obuffer:
|
return
|
||||||
sent = self.socket.send(self.obuffer)
|
print ">>> %r" % line
|
||||||
self.obuffer = self.obuffer[sent:]
|
self.obuffer += line.encode('utf-8', 'replace') + '\r\n'
|
||||||
|
while self.obuffer:
|
||||||
|
sent = self.socket.send(self.obuffer)
|
||||||
|
self.obuffer = self.obuffer[sent:]
|
||||||
|
|
||||||
|
except socket.error as e:
|
||||||
|
self.handle_send_exception(e)
|
||||||
|
return
|
||||||
|
|
||||||
class crlf_ssl_tcp(crlf_tcp):
|
class crlf_ssl_tcp(crlf_tcp):
|
||||||
"""Handles ssl tcp connetions that consist of utf-8 lines ending with crlf"""
|
"""Handles ssl tcp connetions that consist of utf-8 lines ending with crlf"""
|
||||||
|
@ -114,10 +139,13 @@ class crlf_ssl_tcp(crlf_tcp):
|
||||||
|
|
||||||
def handle_receive_exception(self, error, last_timestamp):
|
def handle_receive_exception(self, error, last_timestamp):
|
||||||
# this is terrible
|
# this is terrible
|
||||||
if not "timed out" in error.args[0]:
|
#if not "timed out" in error.args[0]:
|
||||||
raise
|
# raise
|
||||||
return crlf_tcp.handle_receive_exception(self, error, last_timestamp)
|
return crlf_tcp.handle_receive_exception(self, error, last_timestamp)
|
||||||
|
|
||||||
|
def handle_send_exception(self, error):
|
||||||
|
return crlf_tcp.handle_send_exception(self, error)
|
||||||
|
|
||||||
|
|
||||||
irc_prefix_rem = re.compile(r'(.*?) (.*?) (.*)').match
|
irc_prefix_rem = re.compile(r'(.*?) (.*?) (.*)').match
|
||||||
irc_noprefix_rem = re.compile(r'()(.*?) (.*)').match
|
irc_noprefix_rem = re.compile(r'()(.*?) (.*)').match
|
||||||
|
|
BIN
disabled_stuff/data/GeoLiteCity.dat
Normal file
BIN
disabled_stuff/data/GeoLiteCity.dat
Normal file
Binary file not shown.
|
@ -19,10 +19,10 @@ def define(inp):
|
||||||
'//div[@class="example"]')
|
'//div[@class="example"]')
|
||||||
|
|
||||||
if not definition:
|
if not definition:
|
||||||
return 'No results for ' + inp + ' :('
|
return u'No results for {} :('.format(inp)
|
||||||
|
|
||||||
def format_output(show_examples):
|
def format_output(show_examples):
|
||||||
result = '{}: '.format(h.xpath('//dt[@class="title-word"]/a/text()')[0])
|
result = u'{}: '.format(h.xpath('//dt[@class="title-word"]/a/text()')[0])
|
||||||
|
|
||||||
correction = h.xpath('//span[@class="correct-word"]/text()')
|
correction = h.xpath('//span[@class="correct-word"]/text()')
|
||||||
if correction:
|
if correction:
|
||||||
|
@ -77,7 +77,7 @@ def etymology(inp):
|
||||||
etym = h.xpath('//dl')
|
etym = h.xpath('//dl')
|
||||||
|
|
||||||
if not etym:
|
if not etym:
|
||||||
return 'No etymology found for {} :('.format(inp)
|
return u'No etymology found for {} :('.format(inp)
|
||||||
|
|
||||||
etym = etym[0].text_content()
|
etym = etym[0].text_content()
|
||||||
|
|
13
disabled_stuff/freddy.py
Normal file
13
disabled_stuff/freddy.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
from util import hook, http, web
|
||||||
|
from subprocess import check_output, CalledProcessError
|
||||||
|
|
||||||
|
@hook.command
|
||||||
|
def freddycode(inp):
|
||||||
|
"""freddycode <code> - Check if the Freddy Fresh code is correct."""
|
||||||
|
|
||||||
|
try:
|
||||||
|
return "Freddy: '%s' ist %s" % (inp, \
|
||||||
|
check_output(["/bin/freddycheck", inp]))
|
||||||
|
except CalledProcessError as err:
|
||||||
|
return "Freddy: Skript returned %s" % (str(err))
|
||||||
|
|
106
disabled_stuff/recipe.py
Normal file
106
disabled_stuff/recipe.py
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
import random
|
||||||
|
|
||||||
|
from util import hook, http, web
|
||||||
|
|
||||||
|
metadata_url = "http://omnidator.appspot.com/microdata/json/?url={}"
|
||||||
|
|
||||||
|
base_url = "http://www.cookstr.com"
|
||||||
|
search_url = base_url + "/searches"
|
||||||
|
random_url = search_url + "/surprise"
|
||||||
|
|
||||||
|
# set this to true to censor this plugin!
|
||||||
|
censor = True
|
||||||
|
phrases = [
|
||||||
|
u"EAT SOME FUCKING \x02{}\x02",
|
||||||
|
u"YOU WON'T NOT MAKE SOME FUCKING \x02{}\x02",
|
||||||
|
u"HOW ABOUT SOME FUCKING \x02{}?\x02",
|
||||||
|
u"WHY DON'T YOU EAT SOME FUCKING \x02{}?\x02",
|
||||||
|
u"MAKE SOME FUCKING \x02{}\x02",
|
||||||
|
u"INDUCE FOOD COMA WITH SOME FUCKING \x02{}\x02"
|
||||||
|
]
|
||||||
|
|
||||||
|
clean_key = lambda i: i.split("#")[1]
|
||||||
|
|
||||||
|
|
||||||
|
class ParseError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def get_data(url):
|
||||||
|
""" Uses the omnidator API to parse the metadata from the provided URL """
|
||||||
|
try:
|
||||||
|
omni = http.get_json(metadata_url.format(url))
|
||||||
|
except (http.HTTPError, http.URLError) as e:
|
||||||
|
raise ParseError(e)
|
||||||
|
schemas = omni["@"]
|
||||||
|
for d in schemas:
|
||||||
|
if d["a"] == "<http://schema.org/Recipe>":
|
||||||
|
data = {clean_key(key): value for (key, value) in d.iteritems()
|
||||||
|
if key.startswith("http://schema.org/Recipe")}
|
||||||
|
return data
|
||||||
|
raise ParseError("No recipe data found")
|
||||||
|
|
||||||
|
|
||||||
|
@hook.command(autohelp=False)
|
||||||
|
def recipe(inp):
|
||||||
|
"""recipe [term] - Gets a recipe for [term], or ets a random recipe if [term] is not provided"""
|
||||||
|
if inp:
|
||||||
|
# get the recipe URL by searching
|
||||||
|
try:
|
||||||
|
search = http.get_soup(search_url, query=inp.strip())
|
||||||
|
except (http.HTTPError, http.URLError) as e:
|
||||||
|
return "Could not get recipe: {}".format(e)
|
||||||
|
|
||||||
|
# find the list of results
|
||||||
|
result_list = search.find('div', {'class': 'found_results'})
|
||||||
|
|
||||||
|
if result_list:
|
||||||
|
results = result_list.find_all('div', {'class': 'recipe_result'})
|
||||||
|
else:
|
||||||
|
return "No results"
|
||||||
|
|
||||||
|
# pick a random front page result
|
||||||
|
result = random.choice(results)
|
||||||
|
|
||||||
|
# extract the URL from the result
|
||||||
|
url = base_url + result.find('div', {'class': 'image-wrapper'}).find('a')['href']
|
||||||
|
|
||||||
|
else:
|
||||||
|
# get a random recipe URL
|
||||||
|
try:
|
||||||
|
page = http.open(random_url)
|
||||||
|
except (http.HTTPError, http.URLError) as e:
|
||||||
|
return "Could not get recipe: {}".format(e)
|
||||||
|
url = page.geturl()
|
||||||
|
|
||||||
|
# use get_data() to get the recipe info from the URL
|
||||||
|
try:
|
||||||
|
data = get_data(url)
|
||||||
|
except ParseError as e:
|
||||||
|
return "Could not parse recipe: {}".format(e)
|
||||||
|
|
||||||
|
name = data["name"].strip()
|
||||||
|
return u"Try eating \x02{}!\x02 - {}".format(name, web.try_isgd(url))
|
||||||
|
|
||||||
|
|
||||||
|
@hook.command(autohelp=False)
|
||||||
|
def dinner(inp):
|
||||||
|
"""dinner - WTF IS FOR DINNER"""
|
||||||
|
try:
|
||||||
|
page = http.open(random_url)
|
||||||
|
except (http.HTTPError, http.URLError) as e:
|
||||||
|
return "Could not get recipe: {}".format(e)
|
||||||
|
url = page.geturl()
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = get_data(url)
|
||||||
|
except ParseError as e:
|
||||||
|
return "Could not parse recipe: {}".format(e)
|
||||||
|
|
||||||
|
name = data["name"].strip().upper()
|
||||||
|
text = random.choice(phrases).format(name)
|
||||||
|
|
||||||
|
if censor:
|
||||||
|
text = text.replace("FUCK", "F**K")
|
||||||
|
|
||||||
|
return u"{} - {}".format(text, web.try_isgd(url))
|
53
disabled_stuff/status.py
Normal file
53
disabled_stuff/status.py
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
from util import hook
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
from subprocess import check_output
|
||||||
|
|
||||||
|
def getstatus():
|
||||||
|
try:
|
||||||
|
return check_output("sudo /bin/chch-status", shell=True).strip("\n").decode("utf-8")
|
||||||
|
except:
|
||||||
|
return "unbekannt"
|
||||||
|
|
||||||
|
@hook.command("status", autohelp=False)
|
||||||
|
def cmd_status(inp, reply=None):
|
||||||
|
"""status - Return the door status"""
|
||||||
|
reply("Chaostreff Status: %s" % (getstatus()))
|
||||||
|
|
||||||
|
@hook.event("TOPIC")
|
||||||
|
def topic_update(info, conn=None, chan=None):
|
||||||
|
"""topic_update -- Update the topic on TOPIC command"""
|
||||||
|
status = getstatus()
|
||||||
|
|
||||||
|
topic = info[-1]
|
||||||
|
|
||||||
|
sstr = "Status: %s" % (status)
|
||||||
|
if sstr in topic:
|
||||||
|
return
|
||||||
|
|
||||||
|
if 'Status: ' in topic:
|
||||||
|
new_topic = re.sub("Status: [^ ]*", sstr, topic)
|
||||||
|
else:
|
||||||
|
new_topic = "%s | %s" % (topic.rstrip(' |'), sstr)
|
||||||
|
|
||||||
|
if new_topic != topic:
|
||||||
|
conn.send("TOPIC %s :%s" % (chan, new_topic))
|
||||||
|
|
||||||
|
@hook.event("332")
|
||||||
|
def e332_update(info, conn=None, chan=None):
|
||||||
|
"""e332_update -- run after current topic was requested"""
|
||||||
|
chan = info[1]
|
||||||
|
topic_update(info, conn=conn, chan=chan)
|
||||||
|
|
||||||
|
@hook.singlethread
|
||||||
|
@hook.event("353")
|
||||||
|
def e353_update(info, conn=None, chan=None):
|
||||||
|
"""e353_update -- runs after a channel was joined"""
|
||||||
|
chan = info[2]
|
||||||
|
if chan.lower() == "#chaoschemnitz":
|
||||||
|
conn.send("PRIVMSG Chanserv :op #chaoschemnitz")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
conn.send("TOPIC %s" % (chan))
|
||||||
|
time.sleep(60)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue