↪ Python 3
parent
3f9b3d9807
commit
daabc5f39a
|
@ -1,2 +1,3 @@
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
*~
|
*~
|
||||||
|
__pycache__
|
||||||
|
|
|
@ -45,9 +45,7 @@ Required arguments are enclosed in { and }, optional arguments are enclosed in [
|
||||||
<tr> <td>!b32d {string}</td> <td>Base32-decode a string</td> <td>Anyone</td> </tr>
|
<tr> <td>!b32d {string}</td> <td>Base32-decode a string</td> <td>Anyone</td> </tr>
|
||||||
<tr> <td>!b16e {string}</td> <td>Base16-encode a string</td> <td>Anyone</td> </tr>
|
<tr> <td>!b16e {string}</td> <td>Base16-encode a string</td> <td>Anyone</td> </tr>
|
||||||
<tr> <td>!b16d {string}</td> <td>Base16-decode a string</td> <td>Anyone</td> </tr>
|
<tr> <td>!b16d {string}</td> <td>Base16-decode a string</td> <td>Anyone</td> </tr>
|
||||||
<tr> <td>!crc32 {string}</td> <td>Hash a string using crc32</td> <td>Anyone</td> </tr>
|
<tr> <td>!hash {hashtype} {string}</td> <td>Hash a string, supports various hash functions</td> <td>Anyone</td> </tr>
|
||||||
<tr> <td>!hash {hashtype} {string}</td> <td>Hash a string using various hash functions</td> <td>Anyone</td> </tr>
|
|
||||||
<tr> <td>!re {regex}<i>`</i>{string}</td> <td>check if regex matches, if it does print groups</td> <td>Anyone</td> </tr>
|
|
||||||
<tr> <td>!rand [min] {max}</td> <td>Says a random number between(incl.) min and max</td> <td>Anyone</td> </tr>
|
<tr> <td>!rand [min] {max}</td> <td>Says a random number between(incl.) min and max</td> <td>Anyone</td> </tr>
|
||||||
<tr> <td><b>search.py</b></td> <td></td> <td></td> </tr>
|
<tr> <td><b>search.py</b></td> <td></td> <td></td> </tr>
|
||||||
<tr> <td>!g {string}</td> <td>Output first Google result for string</td> <td>Anyone</td> </tr>
|
<tr> <td>!g {string}</td> <td>Output first Google result for string</td> <td>Anyone</td> </tr>
|
||||||
|
@ -74,9 +72,6 @@ Required arguments are enclosed in { and }, optional arguments are enclosed in [
|
||||||
<tr> <td><b>serverup.py</b></td> <td></td> <td></td> </tr>
|
<tr> <td><b>serverup.py</b></td> <td></td> <td></td> </tr>
|
||||||
<tr> <td>!up {IP/hostname} [port]</td> <td>Check if server at IP/hostname is up</td> <td>Anyone</td> </tr>
|
<tr> <td>!up {IP/hostname} [port]</td> <td>Check if server at IP/hostname is up</td> <td>Anyone</td> </tr>
|
||||||
<tr> <td></td> <td>Supports multiple Ports e.g. 123-456,999</td> <td></td> </tr>
|
<tr> <td></td> <td>Supports multiple Ports e.g. 123-456,999</td> <td></td> </tr>
|
||||||
<tr> <td><b>shorten.py</b></td> <td></td> <td></td> </tr>
|
|
||||||
<tr> <td>!sh {service} {url}</td> <td>Shortens URL</td> <td>Anyone</td> </tr>
|
|
||||||
<tr> <td></td> <td>Currently supports: is.gd, v.gd</td> <td></td> </tr>
|
|
||||||
<tr> <td><b>title.py</b></td> <td></td> <td></td> </tr>
|
<tr> <td><b>title.py</b></td> <td></td> <td></td> </tr>
|
||||||
<tr> <td>!title [link]</td> <td>Query Page Title</td> <td>Anyone</td> </tr>
|
<tr> <td>!title [link]</td> <td>Query Page Title</td> <td>Anyone</td> </tr>
|
||||||
<tr> <td><b>twitter.py</b></td> <td></td> <td></td> </tr>
|
<tr> <td><b>twitter.py</b></td> <td></td> <td></td> </tr>
|
||||||
|
|
2
admin.py
2
admin.py
|
@ -80,4 +80,4 @@ py.commands = ['py']
|
||||||
py.priority = 'high'
|
py.priority = 'high'
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__.strip()
|
print(__doc__.strip())
|
||||||
|
|
29
calc.py
29
calc.py
|
@ -14,13 +14,24 @@ class SomeObject(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
env = {
|
env = {
|
||||||
"bin": bin, "abs": abs, "oct": oct, "int": int, "sum": sum,
|
"abs": abs, "all": all, "any": any,
|
||||||
"tuple": tuple, "divmod": divmod, "hash": hash, "hex": hex,
|
"ascii": ascii, "bin": bin, "bool": bool,
|
||||||
"len": len, "list": list, "long": long, "max": max,
|
"bytearray": bytearray, "bytes": bytes,
|
||||||
"range": range, "round": round, "min": min, "map": map,
|
"callable": callable, "chr": chr,
|
||||||
"zip": zip, "xrange": xrange, "unicode": unicode,
|
"complex": complex, "dict": dict,
|
||||||
"unichr": unichr, "type": type, "slice": slice, "ord": ord,
|
"divmod": divmod,
|
||||||
"chr": chr, "str": str, "float": float
|
"enumerate": enumerate, "filter": filter,
|
||||||
|
"float": format, "hex": hex, "int": int,
|
||||||
|
"iter": iter, "len": len, "list": list,
|
||||||
|
"map": map, "max": max, "min": min,
|
||||||
|
"next": next, "object": object,
|
||||||
|
"oct": oct, "ord": ord, "pow": pow,
|
||||||
|
"range": range, "repr": repr,
|
||||||
|
"reversed": reversed, "round": round,
|
||||||
|
"set": set, "slice": slice,
|
||||||
|
"sorted": sorted, "str": str,
|
||||||
|
"sum": sum, "tuple": tuple,
|
||||||
|
"type": type, "zip": zip,
|
||||||
}
|
}
|
||||||
|
|
||||||
libs = [
|
libs = [
|
||||||
|
@ -37,7 +48,7 @@ for lib in libs:
|
||||||
def c(phenny, input):
|
def c(phenny, input):
|
||||||
if not input.group(2):
|
if not input.group(2):
|
||||||
return phenny.reply("Nothing to calculate.")
|
return phenny.reply("Nothing to calculate.")
|
||||||
q = input.group(2).encode('ascii', 'ignore')
|
q = input.group(2)
|
||||||
if '__' in q:
|
if '__' in q:
|
||||||
return phenny.reply("Sorry, but no double underscores.")
|
return phenny.reply("Sorry, but no double underscores.")
|
||||||
log.log("event", "%s calculated '%s'" % (log.fmt_user(input), q), phenny)
|
log.log("event", "%s calculated '%s'" % (log.fmt_user(input), q), phenny)
|
||||||
|
@ -67,4 +78,4 @@ c.commands = ['c']
|
||||||
c.example = '.c 5 + 3'
|
c.example = '.c 5 + 3'
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__.strip()
|
print(__doc__.strip())
|
||||||
|
|
190
devwiki.py
190
devwiki.py
|
@ -1,164 +1,56 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
"""
|
"""
|
||||||
devwiki.py - Phenny Wiki Module
|
wiki.py - Phenny Wiki Module
|
||||||
Copyright 2008-9, Sean B. Palmer, inamidst.com
|
Copyright 2014, sfan5
|
||||||
Modified by Sfan5 2013
|
|
||||||
Licensed under the Eiffel Forum License 2.
|
|
||||||
|
|
||||||
http://inamidst.com/phenny/
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re, urllib, gzip, StringIO
|
import re
|
||||||
import web
|
import web
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
devwikiuri = 'http://dev.minetest.net/%s'
|
wikiuri_g = 'http://dev.minetest.net/index.php?title=%s&printable=yes'
|
||||||
|
wikiuri_r = 'http://dev.minetest.net/index.php?title=%s'
|
||||||
|
|
||||||
r_tr = re.compile(r'(?ims)<tr[^>]*>.*?</tr>')
|
r_content = re.compile(r'(?i)<div[^>]+class=.mw-content-ltr.>')
|
||||||
r_paragraph = re.compile(r'(?ims)<p[^>]*>.*?</p>|<li(?!n)[^>]*>.*?</li>')
|
r_paragraph = re.compile(r'(?ims)<p>(.+?)</p>')
|
||||||
r_tag = re.compile(r'<(?!!)[^>]+>')
|
r_sentenceend = re.compile(r'\.[^\.]')
|
||||||
r_whitespace = re.compile(r'[\t\r\n ]+')
|
transforms = [
|
||||||
r_redirect = re.compile(
|
re.compile(r'(?i)<a [^>]+>(.+?)</a>'),
|
||||||
r'(?ims)class=.redirectText.>\s*<a\s*href=./wiki/([^"/]+)'
|
re.compile(r'(?i)<b>(.+?)</b>'),
|
||||||
)
|
re.compile(r'(?i)<i>(.+?)</i>'),
|
||||||
|
]
|
||||||
|
|
||||||
abbrs = ['etc', 'ca', 'cf', 'Co', 'Ltd', 'Inc', 'Mt', 'Mr', 'Mrs',
|
def wiki(phenny, input):
|
||||||
'Dr', 'Ms', 'Rev', 'Fr', 'St', 'Sgt', 'pron', 'approx', 'lit',
|
term = input.group(2)
|
||||||
'syn', 'transl', 'sess', 'fl', 'Op', 'Dec', 'Brig', 'Gen'] \
|
if not term:
|
||||||
+ list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') \
|
return
|
||||||
+ list('abcdefghijklmnopqrstuvwxyz')
|
|
||||||
t_sentence = r'^.{5,}?(?<!\b%s)(?:\.(?=[\[ ][A-Z0-9]|\Z)|\Z)'
|
|
||||||
r_sentence = re.compile(t_sentence % r')(?<!\b'.join(abbrs))
|
|
||||||
|
|
||||||
def unescape(s):
|
log.log("event", "%s queried Developer Wiki for '%s'" % (log.fmt_user(input), term), phenny)
|
||||||
s = s.replace('>', '>')
|
term = web.urlencode(term)
|
||||||
s = s.replace('<', '<')
|
|
||||||
s = s.replace('&', '&')
|
|
||||||
s = s.replace(' ', ' ')
|
|
||||||
return s
|
|
||||||
|
|
||||||
def text(html):
|
data, scode = web.get(wikiuri_g % term)
|
||||||
html = r_tag.sub('', html)
|
if scode == 404:
|
||||||
html = r_whitespace.sub(' ', html)
|
return phenny.say("No such page.")
|
||||||
return unescape(html).strip()
|
data = str(data, "utf-8")
|
||||||
|
|
||||||
def devwikipedia(term, language='en', last=False):
|
m = re.search(r_content, data)
|
||||||
global devwikiuri
|
if not m:
|
||||||
if not '%' in term:
|
return phenny.say("Sorry, did not find anything.")
|
||||||
if isinstance(term, unicode):
|
data = data[m.span()[1]:]
|
||||||
t = term.encode('utf-8')
|
|
||||||
else: t = term
|
|
||||||
q = urllib.quote(t)
|
|
||||||
u = devwikiuri % (q)
|
|
||||||
bytes = web.get(u)
|
|
||||||
else: bytes = web.get(devwikiuri % (term))
|
|
||||||
|
|
||||||
if bytes.startswith('\x1f\x8b\x08\x00\x00\x00\x00\x00'):
|
m = re.search(r_paragraph, data)
|
||||||
f = StringIO.StringIO(bytes)
|
if not m:
|
||||||
f.seek(0)
|
return phenny.say("Sorry, did not find anything.")
|
||||||
gzip_file = gzip.GzipFile(fileobj=f)
|
data = m.group(1)
|
||||||
bytes = gzip_file.read()
|
for transform in transforms:
|
||||||
gzip_file.close()
|
data = re.sub(transform, '\g<1>', data)
|
||||||
f.close()
|
m = re.search(r_sentenceend, data)
|
||||||
|
if m:
|
||||||
|
data = data[:m.span()[1]-1]
|
||||||
|
phenny.say('"%s" - %s ' % (web.decode(data), wikiuri_r % term))
|
||||||
|
|
||||||
bytes = r_tr.sub('', bytes)
|
wiki.commands = ['devwik', 'devwiki']
|
||||||
|
wiki.priority = 'high'
|
||||||
if not last:
|
|
||||||
r = r_redirect.search(bytes[:4096])
|
|
||||||
if r:
|
|
||||||
term = urllib.unquote(r.group(1))
|
|
||||||
return devwikipedia(term, language=language, last=True)
|
|
||||||
|
|
||||||
paragraphs = r_paragraph.findall(bytes)
|
|
||||||
|
|
||||||
if not paragraphs:
|
|
||||||
if not last:
|
|
||||||
term = search(term)
|
|
||||||
return devwikipedia(term, language=language, last=True)
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Pre-process
|
|
||||||
paragraphs = [para for para in paragraphs
|
|
||||||
if (para and 'technical limitations' not in para
|
|
||||||
and 'window.showTocToggle' not in para
|
|
||||||
and 'Deletion_policy' not in para
|
|
||||||
and 'Template:AfD_footer' not in para
|
|
||||||
and not (para.startswith('<p><i>') and
|
|
||||||
para.endswith('</i></p>'))
|
|
||||||
and not 'disambiguation)"' in para)
|
|
||||||
and not '(images and media)' in para
|
|
||||||
and not 'This article contains a' in para
|
|
||||||
and not 'id="coordinates"' in para
|
|
||||||
and not 'class="thumb' in para]
|
|
||||||
# and not 'style="display:none"' in para]
|
|
||||||
|
|
||||||
for i, para in enumerate(paragraphs):
|
|
||||||
para = para.replace('<sup>', '|')
|
|
||||||
para = para.replace('</sup>', '|')
|
|
||||||
paragraphs[i] = text(para).strip()
|
|
||||||
|
|
||||||
# Post-process
|
|
||||||
paragraphs = [para for para in paragraphs if
|
|
||||||
(para and not (para.endswith(':') and len(para) < 150))]
|
|
||||||
|
|
||||||
para = text(paragraphs[0])
|
|
||||||
m = r_sentence.match(para)
|
|
||||||
|
|
||||||
if not m:
|
|
||||||
if not last:
|
|
||||||
term = search(term)
|
|
||||||
return devwikipedia(term, language=language, last=True)
|
|
||||||
return None
|
|
||||||
sentence = m.group(0)
|
|
||||||
|
|
||||||
maxlength = 275
|
|
||||||
if len(sentence) > maxlength:
|
|
||||||
sentence = sentence[:maxlength]
|
|
||||||
words = sentence[:-5].split(' ')
|
|
||||||
words.pop()
|
|
||||||
sentence = ' '.join(words) + ' [...]'
|
|
||||||
|
|
||||||
if (('using the Article Wizard if you wish' in sentence)
|
|
||||||
or ('or add a request for it' in sentence)
|
|
||||||
or ('in existing articles' in sentence)):
|
|
||||||
if not last:
|
|
||||||
term = search(term)
|
|
||||||
return devwikipedia(term, language=language, last=True)
|
|
||||||
return None
|
|
||||||
|
|
||||||
sentence = '"' + sentence.replace('"', "'") + '"'
|
|
||||||
sentence = sentence.decode('utf-8').encode('utf-8')
|
|
||||||
devwikiuri = devwikiuri.decode('utf-8').encode('utf-8')
|
|
||||||
term = term.decode('utf-8').encode('utf-8')
|
|
||||||
return sentence + ' - ' + (devwikiuri % (term))
|
|
||||||
|
|
||||||
def devwik(phenny, input):
|
|
||||||
origterm = input.groups()[1]
|
|
||||||
if not origterm:
|
|
||||||
return phenny.say('Perhaps you meant "!devwik Zen"?')
|
|
||||||
origterm = origterm.encode('utf-8')
|
|
||||||
log.log("event", "%s queried Devwiki for '%s'" % (log.fmt_user(input), origterm), phenny)
|
|
||||||
|
|
||||||
term = urllib.unquote(origterm)
|
|
||||||
language = 'en'
|
|
||||||
if term.startswith(':') and (' ' in term):
|
|
||||||
a, b = term.split(' ', 1)
|
|
||||||
a = a.lstrip(':')
|
|
||||||
if a.isalpha():
|
|
||||||
language, term = a, b
|
|
||||||
term = term.replace(' ', '_')
|
|
||||||
|
|
||||||
try: result = devwikipedia(term, language)
|
|
||||||
except IOError:
|
|
||||||
args = (language, devwikiuri % (term))
|
|
||||||
error = "Can't connect to dev.minetest.net (%s)" % args
|
|
||||||
return phenny.say(error)
|
|
||||||
|
|
||||||
if result is not None:
|
|
||||||
phenny.say(result)
|
|
||||||
else: phenny.say('Can\'t find anything in Dev Wiki for "%s".' % origterm)
|
|
||||||
|
|
||||||
devwik.commands = ['dev', 'devwik', 'devwiki']
|
|
||||||
devwik.priority = 'high'
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__.strip()
|
print(__doc__.strip())
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
"""
|
"""
|
||||||
forumutils.py - Phenny Minetest Forum Module
|
forumutils.py - Phenny Minetest Forum Module
|
||||||
Copyright 2012, Sfan5
|
Copyright 2012, sfan5
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import web
|
import web
|
||||||
|
@ -137,4 +137,4 @@ search_forumuser_limit.commands = ['searchforumuserlimit', 'sfulimit']
|
||||||
search_forumuser_limit.priority = 'low'
|
search_forumuser_limit.priority = 'low'
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__
|
print(__doc__)
|
||||||
|
|
|
@ -7,36 +7,36 @@ Copyright 2014, sfan5
|
||||||
import time
|
import time
|
||||||
|
|
||||||
loglevels = {
|
loglevels = {
|
||||||
'TEXT': 'TXT', # TEXT: purely informal message that appears in masses e.g. a command being executed
|
'TEXT': 'TXT', # TEXT: purely informal message that appears in masses e.g. a command being executed
|
||||||
'EVENT': 'EVT', # EVENT: like TEXT events but more likely someone wants to see those
|
'EVENT': 'EVT', # EVENT: like TEXT events but more likely someone wants to see those
|
||||||
'ACTION': 'ACT', # ACTION: something the bot decided on doing automatically, requires attention
|
'ACTION': 'ACT', # ACTION: something the bot decided on doing automatically, requires attention
|
||||||
'WARNING': 'WRN', # WARNING: a warning
|
'WARNING': 'WRN', # WARNING: a warning
|
||||||
}
|
}
|
||||||
|
|
||||||
actionchannel = "##minetestbot"
|
actionchannel = "##minetestbot"
|
||||||
actionhighlight = "sfan5"
|
actionhighlight = "sfan5"
|
||||||
|
|
||||||
def log(level, text, phenny):
|
def log(level, text, phenny):
|
||||||
level = level.upper()
|
level = level.upper()
|
||||||
f = open("bot.log", "ab")
|
f = open("bot.log", "a")
|
||||||
f.write(time.strftime("%F %H:%M:%S %z") + "\t" + loglevels[level] + "\t" + text.encode('utf-8') + "\n")
|
f.write(time.strftime("%F %H:%M:%S %z") + "\t" + loglevels[level] + "\t" + text + "\n")
|
||||||
f.close()
|
f.close()
|
||||||
if level == 'ACTION':
|
if level == 'ACTION':
|
||||||
phenny.write(['PRIVMSG', actionchannel], actionhighlight + ": " + text)
|
phenny.write(['PRIVMSG', actionchannel], actionhighlight + ": " + text)
|
||||||
print(level + " " + text)
|
print(level + " " + text)
|
||||||
|
|
||||||
def fmt_user(input):
|
def fmt_user(input):
|
||||||
return "%s(%s)" % (input.nick, input.hostmask)
|
return "%s(%s)" % (input.nick, input.hostmask)
|
||||||
|
|
||||||
class SomeObject(object):
|
class SomeObject(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
log_api = SomeObject()
|
log_api = SomeObject()
|
||||||
log_api.log = log
|
log_api.log = log
|
||||||
log_api.fmt_user = fmt_user
|
log_api.fmt_user = fmt_user
|
||||||
|
|
||||||
_export = {
|
_export = {
|
||||||
'log': log_api,
|
'log': log_api,
|
||||||
}
|
}
|
||||||
|
|
||||||
def log_text(phenny, input, func):
|
def log_text(phenny, input, func):
|
||||||
|
|
4
ping.py
4
ping.py
|
@ -20,8 +20,8 @@ interjection.priority = 'high'
|
||||||
|
|
||||||
def l3(phenny, input):
|
def l3(phenny, input):
|
||||||
phenny.say('<3 ' + input.nick)
|
phenny.say('<3 ' + input.nick)
|
||||||
l3.rule = r'<3 $nickname'
|
l3.rule = r'<3 $nickname\s*'
|
||||||
l3.priority = 'low'
|
l3.priority = 'low'
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__.strip()
|
print(__doc__.strip())
|
||||||
|
|
|
@ -24,7 +24,7 @@ def f_reload(phenny, input):
|
||||||
phenny.setup()
|
phenny.setup()
|
||||||
return phenny.reply('done')
|
return phenny.reply('done')
|
||||||
|
|
||||||
if not sys.modules.has_key(name):
|
if not name in sys.modules:
|
||||||
return phenny.reply('%s: no such module!' % name)
|
return phenny.reply('%s: no such module!' % name)
|
||||||
|
|
||||||
# Thanks to moot for prodding me on this
|
# Thanks to moot for prodding me on this
|
||||||
|
@ -53,4 +53,4 @@ f_reload.priority = 'low'
|
||||||
f_reload.thread = False
|
f_reload.thread = False
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__.strip()
|
print(__doc__.strip())
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
"""
|
"""
|
||||||
rssnotify.py - Phenny RssNotify Module
|
rssnotify.py - Phenny RssNotify Module
|
||||||
Copyright 2013, Sfan5
|
Copyright 2013, sfan5
|
||||||
"""
|
"""
|
||||||
import time, urllib, re
|
import time, urllib, re
|
||||||
import feedparser # sudo pip install feedparser
|
import feedparser # sudo pip install feedparser
|
||||||
|
@ -51,7 +51,7 @@ def rsscheck(phenny, input):
|
||||||
('https://github.com/Uberi/MineTest-WorldEdit/commits/master.atom', allchans),
|
('https://github.com/Uberi/MineTest-WorldEdit/commits/master.atom', allchans),
|
||||||
('https://github.com/Jeija/minetest-mod-mesecons/commits/master.atom', allchans),
|
('https://github.com/Jeija/minetest-mod-mesecons/commits/master.atom', allchans),
|
||||||
]
|
]
|
||||||
for v in xrange(0, len(feeds)):
|
for v in range(0, len(feeds)):
|
||||||
url = feeds[v][0]
|
url = feeds[v][0]
|
||||||
feednum = v
|
feednum = v
|
||||||
options = {
|
options = {
|
||||||
|
@ -111,7 +111,7 @@ def rsscheck(phenny, input):
|
||||||
phenny.write(['PRIVMSG', ch],"GIT: %s commited to %s: %s %s %s %s" % (commiter, reponame, feed_entry.title, commit_hash, commit_time, commit_link))
|
phenny.write(['PRIVMSG', ch],"GIT: %s commited to %s: %s %s %s %s" % (commiter, reponame, feed_entry.title, commit_hash, commit_time, commit_link))
|
||||||
if len(feed.entries) > 0:
|
if len(feed.entries) > 0:
|
||||||
m = -1
|
m = -1
|
||||||
for i in xrange(0, len(feed.entries)):
|
for i in range(0, len(feed.entries)):
|
||||||
if to_unix_time(feed.entries[i].updated) > m:
|
if to_unix_time(feed.entries[i].updated) > m:
|
||||||
m = to_unix_time(feed.entries[i].updated)
|
m = to_unix_time(feed.entries[i].updated)
|
||||||
rssnotify["last_updated_feeds"][feednum] = m
|
rssnotify["last_updated_feeds"][feednum] = m
|
||||||
|
@ -128,4 +128,4 @@ rsscheck.event = '*'
|
||||||
rsscheck.nohook = True
|
rsscheck.nohook = True
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__.strip()
|
print(__doc__.strip())
|
||||||
|
|
50
rutils.py
50
rutils.py
|
@ -12,7 +12,7 @@ def rev(phenny, input):
|
||||||
"""reverse string"""
|
"""reverse string"""
|
||||||
if not input.group(2):
|
if not input.group(2):
|
||||||
return phenny.reply("Nothing to reverse.")
|
return phenny.reply("Nothing to reverse.")
|
||||||
q = input.group(2).encode('utf-8')
|
q = input.group(2)
|
||||||
s = ""
|
s = ""
|
||||||
for i in range(1,len(q)):
|
for i in range(1,len(q)):
|
||||||
s += q[-i]
|
s += q[-i]
|
||||||
|
@ -27,7 +27,7 @@ def make_thing(cmds, func):
|
||||||
if not input.group(2): return
|
if not input.group(2): return
|
||||||
q = input.group(2).encode('utf-8')
|
q = input.group(2).encode('utf-8')
|
||||||
try:
|
try:
|
||||||
phenny.say(rs(func(q)))
|
phenny.say(rs(func(q).decode('utf-8')))
|
||||||
except BaseException as e:
|
except BaseException as e:
|
||||||
phenny.reply("Failed to handle data")
|
phenny.reply("Failed to handle data")
|
||||||
m.commands = cmds
|
m.commands = cmds
|
||||||
|
@ -41,17 +41,6 @@ b32d = make_thing(['b32d','base32decode'], base64.b32decode)
|
||||||
b16e = make_thing(['b16e','base16encode'], base64.b16encode)
|
b16e = make_thing(['b16e','base16encode'], base64.b16encode)
|
||||||
b16d = make_thing(['b16d','base16decode'], base64.b16decode)
|
b16d = make_thing(['b16d','base16decode'], base64.b16decode)
|
||||||
|
|
||||||
def crc32(phenny, input):
|
|
||||||
"""crc32 hash"""
|
|
||||||
if not input.group(2):
|
|
||||||
return phenny.reply("Nothing to hash.")
|
|
||||||
q = input.group(2).encode('utf-8')
|
|
||||||
h = binascii.crc32(q)
|
|
||||||
return phenny.say(rs(str(h) + "(" + hex(h) + ")"))
|
|
||||||
|
|
||||||
crc32.commands = ['crc32']
|
|
||||||
crc32.priority = 'low'
|
|
||||||
|
|
||||||
def hash_(phenny, input):
|
def hash_(phenny, input):
|
||||||
if not input.group(2):
|
if not input.group(2):
|
||||||
return phenny.reply("Usage: hash <hash function> <text> | Get available hash funcs with ?")
|
return phenny.reply("Usage: hash <hash function> <text> | Get available hash funcs with ?")
|
||||||
|
@ -74,39 +63,6 @@ def hash_(phenny, input):
|
||||||
hash_.commands = ['hash']
|
hash_.commands = ['hash']
|
||||||
hash_.priority = 'low'
|
hash_.priority = 'low'
|
||||||
|
|
||||||
def regex(phenny, input):
|
|
||||||
"""regex"""
|
|
||||||
if not input.group(2):
|
|
||||||
return phenny.reply("Give me a regex and a message seperated by `")
|
|
||||||
q = input.group(2).encode('utf-8')
|
|
||||||
rgx = q[:q.find("`")]
|
|
||||||
txt = q[q.find("`")+1:]
|
|
||||||
if rgx == "" or txt == "":
|
|
||||||
return phenny.reply("Give me a regex and a message seperated by `")
|
|
||||||
try:
|
|
||||||
r = re.compile(rgx)
|
|
||||||
except BaseException as e:
|
|
||||||
return phenny.reply("Failed to compile regex: " + e.message)
|
|
||||||
q = multiprocessing.Queue()
|
|
||||||
def compute(q, re, rgx, txt):
|
|
||||||
q.put(list(e.groups()[0] for e in list(re.finditer(rgx, txt))))
|
|
||||||
t = multiprocessing.Process(target=compute, args=(q,re,rgx,txt))
|
|
||||||
t.start()
|
|
||||||
t.join(3.0)
|
|
||||||
if t.is_alive():
|
|
||||||
t.terminate()
|
|
||||||
phenny.reply("Regex took to long to compute")
|
|
||||||
return
|
|
||||||
m = q.get()
|
|
||||||
if m == []:
|
|
||||||
return phenny.say("false")
|
|
||||||
else:
|
|
||||||
return phenny.say("true groups=[" + ', '.join((repr(e) for e in m)) + "]")
|
|
||||||
|
|
||||||
regex.commands = ['re','regex']
|
|
||||||
regex.priority = 'low'
|
|
||||||
regex.thread = True
|
|
||||||
|
|
||||||
def rand(phenny, input):
|
def rand(phenny, input):
|
||||||
"""Returns a random number"""
|
"""Returns a random number"""
|
||||||
if not input.group(2):
|
if not input.group(2):
|
||||||
|
@ -138,4 +94,4 @@ rand.commands = ['rand', 'random']
|
||||||
rand.priority = 'low'
|
rand.priority = 'low'
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__.strip()
|
print(__doc__.strip())
|
||||||
|
|
60
search.py
60
search.py
|
@ -8,59 +8,30 @@ Licensed under the Eiffel Forum License 2.
|
||||||
http://inamidst.com/phenny/
|
http://inamidst.com/phenny/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import web, re
|
import web
|
||||||
|
import re
|
||||||
class Grab(web.urllib.URLopener):
|
|
||||||
def __init__(self, *args):
|
|
||||||
self.version = 'Mozilla/5.0 (MinetestBot)'
|
|
||||||
web.urllib.URLopener.__init__(self, *args)
|
|
||||||
self.addheader('Referer', 'http://minetest.net')
|
|
||||||
def http_error_default(self, url, fp, errcode, errmsg, headers):
|
|
||||||
return web.urllib.addinfourl(fp, [headers, errcode], "http:" + url)
|
|
||||||
|
|
||||||
def google_ajax(query):
|
def google_ajax(query):
|
||||||
"""Search using AjaxSearch, and return its JSON."""
|
"""Search using AjaxSearch, and return its JSON."""
|
||||||
if isinstance(query, unicode):
|
|
||||||
query = query.encode('utf-8')
|
|
||||||
uri = 'http://ajax.googleapis.com/ajax/services/search/web'
|
uri = 'http://ajax.googleapis.com/ajax/services/search/web'
|
||||||
args = '?v=1.0&safe=off&q=' + web.urllib.quote(query)
|
args = '?v=1.0&safe=off&q=' + web.urlencode(query)
|
||||||
handler = web.urllib._urlopener
|
data, sc = web.get(uri + args)
|
||||||
web.urllib._urlopener = Grab()
|
data = str(data, 'utf-8')
|
||||||
bytes = web.get(uri + args)
|
return web.json(data)
|
||||||
web.urllib._urlopener = handler
|
|
||||||
return web.json(bytes)
|
|
||||||
|
|
||||||
def google_search(query):
|
def google_search(query):
|
||||||
results = google_ajax(query)
|
results = google_ajax(query)
|
||||||
try: return results['responseData']['results'][0]['unescapedUrl']
|
try: return results['responseData']['results'][0]['unescapedUrl']
|
||||||
except IndexError: return None
|
except IndexError: return None
|
||||||
except TypeError:
|
except TypeError:
|
||||||
print results
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def google_count(query):
|
|
||||||
results = google_ajax(query)
|
|
||||||
if not results.has_key('responseData'): return '0'
|
|
||||||
if not results['responseData'].has_key('cursor'): return '0'
|
|
||||||
if not results['responseData']['cursor'].has_key('estimatedResultCount'):
|
|
||||||
return '0'
|
|
||||||
return results['responseData']['cursor']['estimatedResultCount']
|
|
||||||
|
|
||||||
def formatnumber(n):
|
|
||||||
"""Format a number with beautiful commas."""
|
|
||||||
parts = list(str(n))
|
|
||||||
for i in range((len(parts) - 3), 0, -3):
|
|
||||||
parts.insert(i, ',')
|
|
||||||
return ''.join(parts)
|
|
||||||
|
|
||||||
|
|
||||||
def g(phenny, input):
|
def g(phenny, input):
|
||||||
"""Queries Google for the specified input."""
|
"""Queries Google for the specified input."""
|
||||||
query = input.group(2)
|
query = input.group(2)
|
||||||
if not query:
|
if not query:
|
||||||
return phenny.reply('.g what?')
|
return phenny.reply('.g what?')
|
||||||
query = query.encode('utf-8')
|
log.log("event", "%s searched Google for '%s'" % (log.fmt_user(input), query), phenny)
|
||||||
log.log("%s searched Google for '%s'" % (log.fmt_user(input), query))
|
|
||||||
uri = google_search(query)
|
uri = google_search(query)
|
||||||
if uri:
|
if uri:
|
||||||
phenny.reply(uri)
|
phenny.reply(uri)
|
||||||
|
@ -72,10 +43,10 @@ g.priority = 'high'
|
||||||
g.example = '.g minetest'
|
g.example = '.g minetest'
|
||||||
|
|
||||||
def gc(phenny, input):
|
def gc(phenny, input):
|
||||||
if not input.group(2):
|
query = input.group(2)
|
||||||
|
if not query:
|
||||||
return phenny.reply("No query term.")
|
return phenny.reply("No query term.")
|
||||||
query = input.group(2).encode('utf-8')
|
log.log("event", "%s searched Google for '%s'" % (log.fmt_user(input), query), phenny)
|
||||||
log.log("%s searched Google for '%s'" % (log.fmt_user(input), query))
|
|
||||||
result = new_gc(query)
|
result = new_gc(query)
|
||||||
if result:
|
if result:
|
||||||
phenny.say(query + ": " + result)
|
phenny.say(query + ": " + result)
|
||||||
|
@ -83,12 +54,13 @@ def gc(phenny, input):
|
||||||
|
|
||||||
def new_gc(query):
|
def new_gc(query):
|
||||||
uri = 'https://www.google.com/search?hl=en&q='
|
uri = 'https://www.google.com/search?hl=en&q='
|
||||||
uri = uri + web.urllib.quote(query).replace('+', '%2B')
|
uri = uri + web.urlencode(query).replace('+', '%2B')
|
||||||
if '"' in query: uri += '&tbs=li:1'
|
if '"' in query: uri += '&tbs=li:1'
|
||||||
bytes = web.get(uri)
|
data, sc = web.get(uri)
|
||||||
if "did not match any documents" in bytes:
|
data = str(data, 'utf-8')
|
||||||
|
if "did not match any documents" in data:
|
||||||
return "0"
|
return "0"
|
||||||
for result in re.compile(r'(?ims)([0-9,]+) results?').findall(bytes):
|
for result in re.compile(r'(?ims)([0-9,]+) results?').findall(data):
|
||||||
return result
|
return result
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -97,4 +69,4 @@ gc.priority = 'high'
|
||||||
gc.example = '.gc minetest'
|
gc.example = '.gc minetest'
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__.strip()
|
print(__doc__.strip())
|
||||||
|
|
12
seen.py
12
seen.py
|
@ -9,13 +9,12 @@ http://inamidst.com/phenny/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import time
|
import time
|
||||||
from tools import deprecated
|
from threading import Thread, Lock
|
||||||
from thread import start_new_thread, allocate_lock
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
updates = list()
|
updates = list()
|
||||||
update_l = allocate_lock()
|
update_l = Lock()
|
||||||
dblock = allocate_lock()
|
dblock = Lock()
|
||||||
|
|
||||||
def opendb():
|
def opendb():
|
||||||
db = sqlite3.connect("seen.sqlite")
|
db = sqlite3.connect("seen.sqlite")
|
||||||
|
@ -130,7 +129,8 @@ c.execute('''CREATE TABLE IF NOT EXISTS seen (nick text, channel text, time int)
|
||||||
c.close()
|
c.close()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
start_new_thread(updatethread, ())
|
t = Thread(target=updatethread, name="seen.py database thread")
|
||||||
|
t.start()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__.strip()
|
print(__doc__.strip())
|
||||||
|
|
|
@ -148,4 +148,4 @@ def server(phenny, input):
|
||||||
server.commands = ['sv', 'server']
|
server.commands = ['sv', 'server']
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__
|
print(__doc__)
|
||||||
|
|
|
@ -80,4 +80,4 @@ serverup.commands = ['up']
|
||||||
serverup.thread = True
|
serverup.thread = True
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__
|
print(__doc__)
|
||||||
|
|
38
shorten.py
38
shorten.py
|
@ -1,38 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
"""
|
|
||||||
shorten.py - URL Shorten Module
|
|
||||||
Copyright 2013, sfan5
|
|
||||||
"""
|
|
||||||
import urllib
|
|
||||||
|
|
||||||
def shorten(phenny, input):
|
|
||||||
arg = input.group(2)
|
|
||||||
if not arg:
|
|
||||||
arg = "" # Function continues and prints Help Message
|
|
||||||
arg = arg.split(' ')
|
|
||||||
if len(arg) < 2:
|
|
||||||
phenny.reply("Give me an url shorten service and an address")
|
|
||||||
return phenny.reply("Supported Services: is.gd, v.gd")
|
|
||||||
else:
|
|
||||||
if arg[0].lower() == "is.gd":
|
|
||||||
p = urllib.urlencode({'format' :"simple", 'url': arg[1]})
|
|
||||||
try:
|
|
||||||
u = urllib.urlopen("http://is.gd/create.php?%s" % p)
|
|
||||||
return phenny.reply(u.read())
|
|
||||||
except:
|
|
||||||
return phenny.reply("Problems accessing is.gd, please try a different Service")
|
|
||||||
if arg[0].lower() == "v.gd":
|
|
||||||
p = urllib.urlencode({'format' :"simple", 'url': arg[1]})
|
|
||||||
try:
|
|
||||||
u = urllib.urlopen("http://v.gd/create.php?%s" % p)
|
|
||||||
return phenny.reply(u.read())
|
|
||||||
except:
|
|
||||||
return phenny.reply("Problems accessing v.gd, please try a different Service")
|
|
||||||
return phenny.reply("Unknown Service")
|
|
||||||
|
|
||||||
|
|
||||||
shorten.commands = ['shorten','sh']
|
|
||||||
shorten.thread = True
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
print __doc__
|
|
|
@ -10,8 +10,7 @@ http://inamidst.com/phenny/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import random
|
import random
|
||||||
import urllib2
|
import web
|
||||||
import json
|
|
||||||
|
|
||||||
def make_cmd(cmd, txt):
|
def make_cmd(cmd, txt):
|
||||||
def m(phenny, input):
|
def m(phenny, input):
|
||||||
|
@ -41,10 +40,8 @@ next.commands = ['next']
|
||||||
def doge(phenny, input):
|
def doge(phenny, input):
|
||||||
"""much wow, very function, such programming"""
|
"""much wow, very function, such programming"""
|
||||||
if random.randint(0, 1) == 0:
|
if random.randint(0, 1) == 0:
|
||||||
f = urllib2.urlopen('http://pubapi.cryptsy.com/api.php?method=singlemarketdata&marketid=132')
|
data = web.get('http://pubapi.cryptsy.com/api.php?method=singlemarketdata&marketid=132')
|
||||||
data = f.read()
|
data = web.json(data)
|
||||||
f.close()
|
|
||||||
data = json.loads(data)
|
|
||||||
phenny.say("DOGE is at " + data['return']['markets']['DOGE']['lasttradeprice'] + " BTC")
|
phenny.say("DOGE is at " + data['return']['markets']['DOGE']['lasttradeprice'] + " BTC")
|
||||||
else:
|
else:
|
||||||
links = [
|
links = [
|
||||||
|
|
18
startup.py
18
startup.py
|
@ -9,7 +9,7 @@ http://inamidst.com/phenny/
|
||||||
|
|
||||||
import threading, time
|
import threading, time
|
||||||
|
|
||||||
def setup(phenny):
|
def setup(phenny):
|
||||||
print("Setting up phenny")
|
print("Setting up phenny")
|
||||||
# by clsn
|
# by clsn
|
||||||
phenny.data = {}
|
phenny.data = {}
|
||||||
|
@ -20,9 +20,9 @@ def setup(phenny):
|
||||||
except: pass
|
except: pass
|
||||||
|
|
||||||
def close():
|
def close():
|
||||||
print "Nobody PONGed our PING, restarting"
|
print("Nobody PONGed our PING, restarting")
|
||||||
phenny.handle_close()
|
phenny.handle_close()
|
||||||
|
|
||||||
def pingloop():
|
def pingloop():
|
||||||
timer = threading.Timer(refresh_delay, close, ())
|
timer = threading.Timer(refresh_delay, close, ())
|
||||||
phenny.data['startup.setup.timer'] = timer
|
phenny.data['startup.setup.timer'] = timer
|
||||||
|
@ -43,27 +43,27 @@ def setup(phenny):
|
||||||
pong.rule = r'.*'
|
pong.rule = r'.*'
|
||||||
phenny.variables['pong'] = pong
|
phenny.variables['pong'] = pong
|
||||||
|
|
||||||
def startup(phenny, input):
|
def startup(phenny, input):
|
||||||
import time
|
import time
|
||||||
|
|
||||||
# Start the ping loop. Has to be done after USER on e.g. quakenet
|
# Start the ping loop. Has to be done after USER on e.g. quakenet
|
||||||
if phenny.data.get('startup.setup.pingloop'):
|
if phenny.data.get('startup.setup.pingloop'):
|
||||||
phenny.data['startup.setup.pingloop']()
|
phenny.data['startup.setup.pingloop']()
|
||||||
|
|
||||||
if hasattr(phenny.config, 'serverpass'):
|
if hasattr(phenny.config, 'serverpass'):
|
||||||
phenny.write(('PASS', phenny.config.serverpass))
|
phenny.write(('PASS', phenny.config.serverpass))
|
||||||
|
|
||||||
if hasattr(phenny.config, 'password'):
|
if hasattr(phenny.config, 'password'):
|
||||||
phenny.msg('NickServ', 'IDENTIFY %s' % phenny.config.password)
|
phenny.msg('NickServ', 'IDENTIFY %s' % phenny.config.password)
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
|
|
||||||
# Cf. http://swhack.com/logs/2005-12-05#T19-32-36
|
# Cf. http://swhack.com/logs/2005-12-05#T19-32-36
|
||||||
for channel in phenny.channels:
|
for channel in phenny.channels:
|
||||||
phenny.write(('JOIN', channel))
|
phenny.write(('JOIN', channel))
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
startup.rule = r'(.*)'
|
startup.rule = r'(.*)'
|
||||||
startup.event = '251'
|
startup.event = '251'
|
||||||
startup.priority = 'low'
|
startup.priority = 'low'
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__.strip()
|
print(__doc__.strip())
|
||||||
|
|
3
tell.py
3
tell.py
|
@ -5,7 +5,6 @@ Copyright 2013, sfan5
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import random
|
import random
|
||||||
from thread import start_new_thread, allocate_lock
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import time
|
import time
|
||||||
import hashlib
|
import hashlib
|
||||||
|
@ -118,4 +117,4 @@ db.commit()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__.strip()
|
print(__doc__.strip())
|
||||||
|
|
112
title.py
112
title.py
|
@ -1,100 +1,46 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
"""
|
"""
|
||||||
title.py - Phenny URL Title Module
|
title.py - Phenny URL Title Module
|
||||||
Copyright 2008, Sean B. Palmer, inamidst.com
|
Copyright 2014, sfan5
|
||||||
Modified by sfan5, 2013
|
|
||||||
Licensed under the Eiffel Forum License 2.
|
|
||||||
|
|
||||||
http://inamidst.com/phenny/
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re, urllib2, urlparse
|
import re
|
||||||
|
import web
|
||||||
|
|
||||||
r_title = re.compile(r'(?ims)<title[^>]*>(.*?)</title\s*>')
|
r_title = re.compile(r'(?ims)<\s*title[^>]*>(.*?)<\s*/\s*title\s*>')
|
||||||
|
|
||||||
def f_title(phenny, input):
|
|
||||||
uri = input.group(2)
|
|
||||||
uri = (uri or '').encode('utf-8')
|
|
||||||
|
|
||||||
if not uri and hasattr(phenny.bot, 'last_seen_uri'):
|
|
||||||
uri = phenny.bot.last_seen_uri
|
|
||||||
if not uri:
|
|
||||||
return phenny.reply('I need a URI to give the title of...')
|
|
||||||
|
|
||||||
if not ':' in uri:
|
|
||||||
uri = 'http://' + uri
|
|
||||||
|
|
||||||
|
def title(phenny, input):
|
||||||
|
uri = input.group(2).strip()
|
||||||
|
if uri:
|
||||||
|
pass
|
||||||
|
elif hasattr(phenny.bot, 'last_seen_uri'):
|
||||||
|
uri = phenny.bot.last_seen_uri
|
||||||
|
else:
|
||||||
|
return phenny.reply("Give me an URI..")
|
||||||
|
data, sc = web.get(uri, 4096)
|
||||||
|
if sc != 200:
|
||||||
|
return phenny.say("HTTP error %d" % sc)
|
||||||
try:
|
try:
|
||||||
redirects = 0
|
data = str(data, 'utf-8')
|
||||||
while True:
|
except UnicodeDecodeError:
|
||||||
headers = {
|
return phenny.say("Doesn't seem to be HTML..")
|
||||||
'Accept': 'text/html',
|
m = re.search(r_title, data)
|
||||||
'User-Agent': 'Mozilla/5.0 (MinetestBot)'
|
if not m:
|
||||||
}
|
return phenny.say("No title found.")
|
||||||
req = urllib2.Request(uri, headers=headers)
|
title = m.group(1).strip()
|
||||||
u = urllib2.urlopen(req)
|
if len(title) > 75:
|
||||||
info = u.info()
|
title = title[:75] + "[...]"
|
||||||
u.close()
|
phenny.reply(title)
|
||||||
|
|
||||||
if not isinstance(info, list):
|
title.commands = ['title']
|
||||||
status = '200'
|
|
||||||
else:
|
|
||||||
status = str(info[1])
|
|
||||||
info = info[0]
|
|
||||||
if status.startswith('3'):
|
|
||||||
uri = urlparse.urljoin(uri, info['Location'])
|
|
||||||
else: break
|
|
||||||
|
|
||||||
redirects += 1
|
|
||||||
if redirects >= 20:
|
|
||||||
return phenny.reply("Too many redirects")
|
|
||||||
|
|
||||||
try: mtype = info['content-type']
|
|
||||||
except:
|
|
||||||
return phenny.reply("Couldn't get the Content-Type, sorry")
|
|
||||||
if not (('/html' in mtype) or ('/xhtml' in mtype)):
|
|
||||||
return phenny.reply("Document isn't HTML")
|
|
||||||
|
|
||||||
u = urllib2.urlopen(req)
|
|
||||||
bytes = u.read(262144)
|
|
||||||
u.close()
|
|
||||||
|
|
||||||
except IOError:
|
|
||||||
return phenny.reply("Can't connect to %s" % uri)
|
|
||||||
|
|
||||||
m = r_title.search(bytes)
|
|
||||||
if m:
|
|
||||||
title = m.group(1)
|
|
||||||
title = title.strip()
|
|
||||||
title = title.replace('\n', ' ')
|
|
||||||
title = title.replace('\r', ' ')
|
|
||||||
while ' ' in title:
|
|
||||||
title = title.replace(' ', ' ')
|
|
||||||
if len(title) > 100:
|
|
||||||
title = title[:100] + '[...]'
|
|
||||||
|
|
||||||
if title:
|
|
||||||
try: title.decode('utf-8')
|
|
||||||
except:
|
|
||||||
try: title = title.decode('iso-8859-1').encode('utf-8')
|
|
||||||
except: title = title.decode('cp1252').encode('utf-8')
|
|
||||||
else: pass
|
|
||||||
else: title = '[The title is empty.]'
|
|
||||||
|
|
||||||
title = title.replace('\n', '')
|
|
||||||
title = title.replace('\r', '')
|
|
||||||
return phenny.reply(title)
|
|
||||||
else: return phenny.reply('No title found')
|
|
||||||
|
|
||||||
f_title.commands = ['title']
|
|
||||||
|
|
||||||
def noteuri(phenny, input):
|
def noteuri(phenny, input):
|
||||||
uri = input.group(1).encode('utf-8')
|
uri = input.group(1)
|
||||||
phenny.bot.last_seen_uri = uri
|
phenny.bot.last_seen_uri = uri
|
||||||
|
|
||||||
noteuri.rule = r'.*(https?://[^<> "\x01]+).*'
|
noteuri.rule = r'(https?://[^<> "\x01]+)'
|
||||||
noteuri.priority = 'low'
|
noteuri.priority = 'low'
|
||||||
noteuri.nohook = True
|
noteuri.nohook = True
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__.strip()
|
print(__doc__.strip())
|
||||||
|
|
19
twitter.py
19
twitter.py
|
@ -21,7 +21,7 @@ r_whiteline = re.compile(r'(?ims)[ \t]+[\r\n]+')
|
||||||
r_breaks = re.compile(r'(?ims)[\r\n]+')
|
r_breaks = re.compile(r'(?ims)[\r\n]+')
|
||||||
|
|
||||||
def entity(*args, **kargs):
|
def entity(*args, **kargs):
|
||||||
return web.entity(*args, **kargs).encode('utf-8')
|
return web.entity(*args, **kargs)
|
||||||
|
|
||||||
def decode(html):
|
def decode(html):
|
||||||
return web.r_entity.sub(entity, html)
|
return web.r_entity.sub(entity, html)
|
||||||
|
@ -35,7 +35,8 @@ def expand(tweet):
|
||||||
return r_anchor.sub(replacement, tweet)
|
return r_anchor.sub(replacement, tweet)
|
||||||
|
|
||||||
def read_tweet(url):
|
def read_tweet(url):
|
||||||
bytes = web.get(url)
|
bytes, sc = web.get(url)
|
||||||
|
bytes = str(bytes, 'utf-8')
|
||||||
shim = '<div class="content clearfix">'
|
shim = '<div class="content clearfix">'
|
||||||
if shim in bytes:
|
if shim in bytes:
|
||||||
bytes = bytes.split(shim, 1).pop()
|
bytes = bytes.split(shim, 1).pop()
|
||||||
|
@ -58,11 +59,11 @@ def user_tweet(username):
|
||||||
|
|
||||||
def id_tweet(tid):
|
def id_tweet(tid):
|
||||||
link = 'https://twitter.com/twitter/status/' + tid
|
link = 'https://twitter.com/twitter/status/' + tid
|
||||||
data = web.head(link)
|
headers, status = web.head(link)
|
||||||
message, status = tuple(data)
|
|
||||||
if status == 301:
|
if status == 301:
|
||||||
url = message.get("Location")
|
if not "Location" in headers:
|
||||||
if not url: return "Sorry, couldn't get a tweet from %s" % link
|
return "Sorry, couldn't get a tweet from %s" % link
|
||||||
|
url = headers["Location"]
|
||||||
username = url.split('/')[3]
|
username = url.split('/')[3]
|
||||||
tweet = read_tweet(url)
|
tweet = read_tweet(url)
|
||||||
return format(tweet, username)
|
return format(tweet, username)
|
||||||
|
@ -74,9 +75,7 @@ def twitter(phenny, input):
|
||||||
return phenny.reply("Give me a link, a @username, or a tweet id")
|
return phenny.reply("Give me a link, a @username, or a tweet id")
|
||||||
|
|
||||||
arg = arg.strip()
|
arg = arg.strip()
|
||||||
if isinstance(arg, unicode):
|
log.log("event", "%s queried Twitter for '%s'" % (log.fmt_user(input), arg), phenny)
|
||||||
arg = arg.encode('utf-8')
|
|
||||||
log.log("%s queried Twitter for '%s'" % (log.fmt_user(input), arg))
|
|
||||||
if arg.isdigit():
|
if arg.isdigit():
|
||||||
phenny.say(id_tweet(arg))
|
phenny.say(id_tweet(arg))
|
||||||
elif r_username.match(arg):
|
elif r_username.match(arg):
|
||||||
|
@ -91,4 +90,4 @@ twitter.commands = ['tw', 'twitter']
|
||||||
twitter.thread = True
|
twitter.thread = True
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__
|
print(__doc__)
|
||||||
|
|
190
wiki.py
190
wiki.py
|
@ -1,166 +1,56 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
"""
|
"""
|
||||||
wiki.py - Phenny Wiki Module
|
wiki.py - Phenny Wiki Module
|
||||||
Copyright 2008-9, Sean B. Palmer, inamidst.com
|
Copyright 2014, sfan5
|
||||||
Modified by sfan5 2013
|
|
||||||
Licensed under the Eiffel Forum License 2.
|
|
||||||
|
|
||||||
http://inamidst.com/phenny/
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re, urllib, gzip, StringIO
|
import re
|
||||||
import web
|
import web
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
wikiuri = 'http://wiki.minetest.net/%s'
|
wikiuri_g = 'http://wiki.minetest.net/%s?printable=yes'
|
||||||
|
wikiuri_r = 'http://wiki.minetest.net/%s'
|
||||||
|
|
||||||
r_tr = re.compile(r'(?ims)<tr[^>]*>.*?</tr>')
|
r_content = re.compile(r'(?i)<div[^>]+class=.mw-content-ltr.>')
|
||||||
r_paragraph = re.compile(r'(?ims)<p[^>]*>.*?</p>|<li(?!n)[^>]*>.*?</li>')
|
r_paragraph = re.compile(r'(?ims)<p>(.+?)</p>')
|
||||||
r_tag = re.compile(r'<(?!!)[^>]+>')
|
r_sentenceend = re.compile(r'\.[^\.]')
|
||||||
r_whitespace = re.compile(r'[\t\r\n ]+')
|
transforms = [
|
||||||
r_redirect = re.compile(
|
re.compile(r'(?i)<a [^>]+>(.+?)</a>'),
|
||||||
r'(?ims)class=.redirectText.>\s*<a\s*href=./wiki/([^"/]+)'
|
re.compile(r'(?i)<b>(.+?)</b>'),
|
||||||
)
|
re.compile(r'(?i)<i>(.+?)</i>'),
|
||||||
|
]
|
||||||
|
|
||||||
abbrs = ['etc', 'ca', 'cf', 'Co', 'Ltd', 'Inc', 'Mt', 'Mr', 'Mrs',
|
def wiki(phenny, input):
|
||||||
'Dr', 'Ms', 'Rev', 'Fr', 'St', 'Sgt', 'pron', 'approx', 'lit',
|
term = input.group(2)
|
||||||
'syn', 'transl', 'sess', 'fl', 'Op', 'Dec', 'Brig', 'Gen'] \
|
if not term:
|
||||||
+ list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') \
|
return
|
||||||
+ list('abcdefghijklmnopqrstuvwxyz')
|
|
||||||
t_sentence = r'^.{5,}?(?<!\b%s)(?:\.(?=[\[ ][A-Z0-9]|\Z)|\Z)'
|
|
||||||
r_sentence = re.compile(t_sentence % r')(?<!\b'.join(abbrs))
|
|
||||||
|
|
||||||
def unescape(s):
|
log.log("event", "%s queried Wiki for '%s'" % (log.fmt_user(input), term), phenny)
|
||||||
s = s.replace('>', '>')
|
term = web.urlencode(term)
|
||||||
s = s.replace('<', '<')
|
|
||||||
s = s.replace('&', '&')
|
|
||||||
s = s.replace(' ', ' ')
|
|
||||||
return s
|
|
||||||
|
|
||||||
def text(html):
|
data, scode = web.get(wikiuri_g % term)
|
||||||
html = r_tag.sub('', html)
|
if scode == 404:
|
||||||
html = r_whitespace.sub(' ', html)
|
return phenny.say("No such page.")
|
||||||
return unescape(html).strip()
|
data = str(data, "utf-8")
|
||||||
|
|
||||||
def wikipedia(term, language='en', last=False):
|
m = re.search(r_content, data)
|
||||||
global wikiuri
|
if not m:
|
||||||
if not '%' in term:
|
return phenny.say("Sorry, did not find anything.")
|
||||||
if isinstance(term, unicode):
|
data = data[m.span()[1]:]
|
||||||
t = term.encode('utf-8')
|
|
||||||
else: t = term
|
|
||||||
q = urllib.quote(t)
|
|
||||||
u = wikiuri % (q)
|
|
||||||
bytes = web.get(u)
|
|
||||||
else: bytes = web.get(wikiuri % (term))
|
|
||||||
|
|
||||||
if bytes.startswith('\x1f\x8b\x08\x00\x00\x00\x00\x00'):
|
m = re.search(r_paragraph, data)
|
||||||
f = StringIO.StringIO(bytes)
|
if not m:
|
||||||
f.seek(0)
|
return phenny.say("Sorry, did not find anything.")
|
||||||
gzip_file = gzip.GzipFile(fileobj=f)
|
data = m.group(1)
|
||||||
bytes = gzip_file.read()
|
for transform in transforms:
|
||||||
gzip_file.close()
|
data = re.sub(transform, '\g<1>', data)
|
||||||
f.close()
|
m = re.search(r_sentenceend, data)
|
||||||
|
if m:
|
||||||
|
data = data[:m.span()[1]-1]
|
||||||
|
phenny.say('"%s" - %s ' % (web.decode(data), wikiuri_r % term))
|
||||||
|
|
||||||
bytes = r_tr.sub('', bytes)
|
wiki.commands = ['wik', 'wiki']
|
||||||
|
wiki.priority = 'high'
|
||||||
if not last:
|
|
||||||
r = r_redirect.search(bytes[:4096])
|
|
||||||
if r:
|
|
||||||
term = urllib.unquote(r.group(1))
|
|
||||||
return wikipedia(term, language=language, last=True)
|
|
||||||
|
|
||||||
paragraphs = r_paragraph.findall(bytes)
|
|
||||||
|
|
||||||
if not paragraphs:
|
|
||||||
if not last:
|
|
||||||
term = search(term)
|
|
||||||
return wikipedia(term, language=language, last=True)
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Pre-process
|
|
||||||
paragraphs = [para for para in paragraphs
|
|
||||||
if (para and 'technical limitations' not in para
|
|
||||||
and 'window.showTocToggle' not in para
|
|
||||||
and 'Deletion_policy' not in para
|
|
||||||
and 'Template:AfD_footer' not in para
|
|
||||||
and not (para.startswith('<p><i>') and
|
|
||||||
para.endswith('</i></p>'))
|
|
||||||
and not 'disambiguation)"' in para)
|
|
||||||
and not '(images and media)' in para
|
|
||||||
and not 'This article contains a' in para
|
|
||||||
and not 'id="coordinates"' in para
|
|
||||||
and not 'class="thumb' in para]
|
|
||||||
# and not 'style="display:none"' in para]
|
|
||||||
|
|
||||||
for i, para in enumerate(paragraphs):
|
|
||||||
para = para.replace('<sup>', '|')
|
|
||||||
para = para.replace('</sup>', '|')
|
|
||||||
paragraphs[i] = text(para).strip()
|
|
||||||
|
|
||||||
# Post-process
|
|
||||||
paragraphs = [para for para in paragraphs if
|
|
||||||
(para and not (para.endswith(':') and len(para) < 150))]
|
|
||||||
|
|
||||||
para = text(paragraphs[0])
|
|
||||||
m = r_sentence.match(para)
|
|
||||||
|
|
||||||
if not m:
|
|
||||||
if not last:
|
|
||||||
term = search(term)
|
|
||||||
return wikipedia(term, language=language, last=True)
|
|
||||||
return None
|
|
||||||
sentence = m.group(0)
|
|
||||||
|
|
||||||
maxlength = 275
|
|
||||||
if len(sentence) > maxlength:
|
|
||||||
sentence = sentence[:maxlength]
|
|
||||||
words = sentence[:-5].split(' ')
|
|
||||||
words.pop()
|
|
||||||
sentence = ' '.join(words) + ' [...]'
|
|
||||||
|
|
||||||
if (('using the Article Wizard if you wish' in sentence)
|
|
||||||
or ('or add a request for it' in sentence)
|
|
||||||
or ('in existing articles' in sentence)):
|
|
||||||
if not last:
|
|
||||||
term = search(term)
|
|
||||||
return wikipedia(term, language=language, last=True)
|
|
||||||
return None
|
|
||||||
|
|
||||||
sentence = '"' + sentence.replace('"', "'") + '"'
|
|
||||||
sentence = sentence.decode('utf-8').encode('utf-8')
|
|
||||||
wikiuri = wikiuri.decode('utf-8').encode('utf-8')
|
|
||||||
term = term.decode('utf-8').encode('utf-8')
|
|
||||||
return sentence + ' - ' + (wikiuri % (term))
|
|
||||||
|
|
||||||
def wik(phenny, input):
|
|
||||||
origterm = input.groups()[1]
|
|
||||||
if not origterm:
|
|
||||||
return phenny.say('Perhaps you meant "!wik Zen"?')
|
|
||||||
origterm = origterm.encode('utf-8')
|
|
||||||
|
|
||||||
log.log("event", "%s queried Wiki for '%s'" % (log.fmt_user(input), origterm), phenny)
|
|
||||||
|
|
||||||
term = urllib.unquote(origterm)
|
|
||||||
language = 'en'
|
|
||||||
if term.startswith(':') and (' ' in term):
|
|
||||||
a, b = term.split(' ', 1)
|
|
||||||
a = a.lstrip(':')
|
|
||||||
if a.isalpha():
|
|
||||||
language, term = a, b
|
|
||||||
term = term[0].upper() + term[1:]
|
|
||||||
term = term.replace(' ', '_')
|
|
||||||
|
|
||||||
try: result = wikipedia(term, language)
|
|
||||||
except IOError:
|
|
||||||
args = (language, wikiuri % (term))
|
|
||||||
error = "Can't connect to wiki.minetest.com (%s)" % args
|
|
||||||
return phenny.say(error)
|
|
||||||
|
|
||||||
if result is not None:
|
|
||||||
phenny.say(result)
|
|
||||||
else: phenny.say('Can\'t find anything in Wiki for "%s".' % origterm)
|
|
||||||
|
|
||||||
wik.commands = ['wik', 'wiki']
|
|
||||||
wik.priority = 'high'
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__.strip()
|
print(__doc__.strip())
|
||||||
|
|
Loading…
Reference in New Issue