mutantmonkey 2011-04-04 16:46:46 -04:00
commit f249e43ba4
7 changed files with 206 additions and 66 deletions

View File

@ -78,6 +78,8 @@ def c(phenny, input):
answer = [p for p in parts if p.startswith('rhs: "')][0][6:] answer = [p for p in parts if p.startswith('rhs: "')][0][6:]
if answer: if answer:
answer = answer.decode('unicode-escape') answer = answer.decode('unicode-escape')
answer = ''.join(chr(ord(c)) for c in answer)
answer = answer.decode('utf-8')
answer = answer.replace(u'\xc2\xa0', ',') answer = answer.replace(u'\xc2\xa0', ',')
answer = answer.replace('<sup>', '^(') answer = answer.replace('<sup>', '^(')
answer = answer.replace('</sup>', ')') answer = answer.replace('</sup>', ')')
@ -97,7 +99,7 @@ def py(phenny, input):
py.commands = ['py'] py.commands = ['py']
def wa(phenny, input): def wa(phenny, input):
query = input.group(2) query = input.group(2).encode('utf-8')
uri = 'http://tumbolia.appspot.com/wa/' uri = 'http://tumbolia.appspot.com/wa/'
answer = web.get(uri + web.urllib.quote(query)) answer = web.get(uri + web.urllib.quote(query))
if answer: if answer:

View File

@ -7,11 +7,16 @@ Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/ http://inamidst.com/phenny/
""" """
import re, urllib, urllib2, httplib, urlparse, time import re, urllib, urllib2, httplib, urlparse, time, cookielib
from htmlentitydefs import name2codepoint from htmlentitydefs import name2codepoint
from string import join
import web import web
from tools import deprecated from tools import deprecated
cj = cookielib.LWPCookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
urllib2.install_opener(opener)
def head(phenny, input): def head(phenny, input):
"""Provide HTTP HEAD information.""" """Provide HTTP HEAD information."""
uri = input.group(2) uri = input.group(2)
@ -26,6 +31,7 @@ def head(phenny, input):
if not uri.startswith('htt'): if not uri.startswith('htt'):
uri = 'http://' + uri uri = 'http://' + uri
# uri = uri.replace('#!', '?_escaped_fragment_=')
try: info = web.head(uri) try: info = web.head(uri)
except IOError: return phenny.say("Can't connect to %s" % uri) except IOError: return phenny.say("Can't connect to %s" % uri)
@ -77,9 +83,35 @@ def f_title(self, origin, match, args):
uri = self.last_seen_uri.get(origin.sender) uri = self.last_seen_uri.get(origin.sender)
if not uri: if not uri:
return self.msg(origin.sender, 'I need a URI to give the title of...') return self.msg(origin.sender, 'I need a URI to give the title of...')
title = gettitle(uri)
if title:
self.msg(origin.sender, origin.nick + ': ' + title)
else: self.msg(origin.sender, origin.nick + ': No title found')
f_title.commands = ['title']
def noteuri(phenny, input):
uri = input.group(1).encode('utf-8')
if not hasattr(phenny.bot, 'last_seen_uri'):
phenny.bot.last_seen_uri = {}
phenny.bot.last_seen_uri[input.sender] = uri
noteuri.rule = r'.*(http[s]?://[^<> "\x01]+)[,.]?'
noteuri.priority = 'low'
titlecommands = r'(?:' + join(f_title.commands, r'|') + r')'
def snarfuri(phenny, input):
if re.match(r'(?i)' + phenny.config.prefix + titlecommands, input.group()):
return
uri = input.group(1).encode('utf-8')
title = gettitle(uri)
if title:
phenny.msg(input.sender, '[ ' + title + ' ]')
snarfuri.rule = r'.*(http[s]?://[^<> "\x01]+)[,.]?'
snarfuri.priority = 'low'
def gettitle(uri):
if not ':' in uri: if not ':' in uri:
uri = 'http://' + uri uri = 'http://' + uri
uri = uri.replace('#!', '?_escaped_fragment_=')
try: try:
redirects = 0 redirects = 0
@ -92,7 +124,6 @@ def f_title(self, origin, match, args):
u = urllib2.urlopen(req) u = urllib2.urlopen(req)
info = u.info() info = u.info()
u.close() u.close()
# info = web.head(uri)
if not isinstance(info, list): if not isinstance(info, list):
status = '200' status = '200'
@ -105,23 +136,19 @@ def f_title(self, origin, match, args):
redirects += 1 redirects += 1
if redirects >= 25: if redirects >= 25:
self.msg(origin.sender, origin.nick + ": Too many redirects") return None
return
try: mtype = info['content-type'] try: mtype = info['content-type']
except: except:
err = ": Couldn't get the Content-Type, sorry" return None
return self.msg(origin.sender, origin.nick + err) if not (('/html' in mtype) or ('/xhtml' in mtype)):
if not (('/html' in mtype) or ('/xhtml' in mtype)): return None
self.msg(origin.sender, origin.nick + ": Document isn't HTML")
return
u = urllib2.urlopen(req) u = urllib2.urlopen(req)
bytes = u.read(262144) bytes = u.read(262144)
u.close() u.close()
except IOError: except IOError:
self.msg(origin.sender, "Can't connect to %s" % uri)
return return
m = r_title.search(bytes) m = r_title.search(bytes)
@ -155,21 +182,10 @@ def f_title(self, origin, match, args):
try: title = title.decode('iso-8859-1').encode('utf-8') try: title = title.decode('iso-8859-1').encode('utf-8')
except: title = title.decode('cp1252').encode('utf-8') except: title = title.decode('cp1252').encode('utf-8')
else: pass else: pass
else: title = '[The title is empty.]' title = title.replace('\n', '')
title = title.replace('\r', '')
title = title.replace('\n', '') else: title = None
title = title.replace('\r', '') return title
self.msg(origin.sender, origin.nick + ': ' + title)
else: self.msg(origin.sender, origin.nick + ': No title found')
f_title.commands = ['title']
def noteuri(phenny, input):
uri = input.group(1).encode('utf-8')
if not hasattr(phenny.bot, 'last_seen_uri'):
phenny.bot.last_seen_uri = {}
phenny.bot.last_seen_uri[input.sender] = uri
noteuri.rule = r'.*(http[s]?://[^<> "\x01]+)[,.]?'
noteuri.priority = 'low'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print __doc__.strip()

View File

@ -30,9 +30,9 @@ def mappings(uri):
def service(phenny, input, command, args): def service(phenny, input, command, args):
t = o.services[command] t = o.services[command]
template = t.replace('${args}', urllib.quote(args.encode('utf-8'))) template = t.replace('${args}', urllib.quote(args.encode('utf-8'), ''))
template = template.replace('${nick}', urllib.quote(input.nick)) template = template.replace('${nick}', urllib.quote(input.nick, ''))
uri = template.replace('${sender}', urllib.quote(input.sender)) uri = template.replace('${sender}', urllib.quote(input.sender, ''))
info = web.head(uri) info = web.head(uri)
if isinstance(info, list): if isinstance(info, list):

View File

@ -7,6 +7,7 @@ Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/ http://inamidst.com/phenny/
""" """
import sys, os.path, time, imp
import irc import irc
def f_reload(phenny, input): def f_reload(phenny, input):
@ -21,18 +22,23 @@ def f_reload(phenny, input):
phenny.setup() phenny.setup()
return phenny.reply('done') return phenny.reply('done')
try: module = getattr(__import__('modules.' + name), name) if not sys.modules.has_key(name):
except ImportError: return phenny.reply('%s: no such module!' % name)
module = getattr(__import__('opt.' + name), name)
reload(module) # Thanks to moot for prodding me on this
path = sys.modules[name].__file__
if path.endswith('.pyc') or path.endswith('.pyo'):
path = path[:-1]
if not os.path.isfile(path):
return phenny.reply('Found %s, but not the source file' % name)
module = imp.load_source(name, path)
sys.modules[name] = module
if hasattr(module, 'setup'): if hasattr(module, 'setup'):
module.setup(phenny) module.setup(phenny)
if hasattr(module, '__file__'): mtime = os.path.getmtime(module.__file__)
import os.path, time modified = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(mtime))
mtime = os.path.getmtime(module.__file__)
modified = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(mtime))
else: modified = 'unknown'
phenny.register(vars(module)) phenny.register(vars(module))
phenny.bind_commands() phenny.bind_commands()

136
modules/remind.py Executable file
View File

@ -0,0 +1,136 @@
#!/usr/bin/env python
"""
remind.py - Phenny Reminder Module
Copyright 2011, Sean B. Palmer, inamidst.com
Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/
"""
import os, re, time, threading
def filename(self):
name = self.nick + '-' + self.config.host + '.reminders.db'
return os.path.join(os.path.expanduser('~/.phenny'), name)
def load_database(name):
data = {}
if os.path.isfile(name):
f = open(name, 'rb')
for line in f:
unixtime, channel, nick, message = line.split('\t')
message = message.rstrip('\n')
t = int(unixtime)
reminder = (channel, nick, message)
try: data[t].append(reminder)
except KeyError: data[t] = [reminder]
f.close()
return data
def dump_database(name, data):
f = open(name, 'wb')
for unixtime, reminders in data.iteritems():
for channel, nick, message in reminders:
f.write('%s\t%s\t%s\t%s\n' % (unixtime, channel, nick, message))
f.close()
def setup(phenny):
phenny.rfn = filename(phenny)
phenny.rdb = load_database(phenny.rfn)
def monitor(phenny):
time.sleep(5)
while True:
now = int(time.time())
unixtimes = [int(key) for key in phenny.rdb]
oldtimes = [t for t in unixtimes if t <= now]
if oldtimes:
for oldtime in oldtimes:
for (channel, nick, message) in phenny.rdb[oldtime]:
if message:
phenny.msg(channel, nick + ': ' + message)
else: phenny.msg(channel, nick + '!')
del phenny.rdb[oldtime]
dump_database(phenny.rfn, phenny.rdb)
time.sleep(2.5)
targs = (phenny,)
t = threading.Thread(target=monitor, args=targs)
t.start()
scaling = {
'years': 365.25 * 24 * 3600,
'year': 365.25 * 24 * 3600,
'yrs': 365.25 * 24 * 3600,
'y': 365.25 * 24 * 3600,
'months': 29.53059 * 24 * 3600,
'month': 29.53059 * 24 * 3600,
'mo': 29.53059 * 24 * 3600,
'weeks': 7 * 24 * 3600,
'week': 7 * 24 * 3600,
'wks': 7 * 24 * 3600,
'wk': 7 * 24 * 3600,
'w': 7 * 24 * 3600,
'days': 24 * 3600,
'day': 24 * 3600,
'd': 24 * 3600,
'hours': 3600,
'hour': 3600,
'hrs': 3600,
'hr': 3600,
'h': 3600,
'minutes': 60,
'minute': 60,
'mins': 60,
'min': 60,
'm': 60,
'seconds': 1,
'second': 1,
'secs': 1,
'sec': 1,
's': 1
}
periods = '|'.join(scaling.keys())
p_command = r'\.in ([0-9]+(?:\.[0-9]+)?)\s?((?:%s)\b)?:?\s?(.*)' % periods
r_command = re.compile(p_command)
def remind(phenny, input):
m = r_command.match(input.bytes)
if not m:
return phenny.reply("Sorry, didn't understand the input.")
length, scale, message = m.groups()
length = float(length)
factor = scaling.get(scale, 60)
duration = length * factor
if duration % 1:
duration = int(duration) + 1
else: duration = int(duration)
t = int(time.time()) + duration
reminder = (input.sender, input.nick, message)
try: phenny.rdb[t].append(reminder)
except KeyError: phenny.rdb[t] = [reminder]
dump_database(phenny.rfn, phenny.rdb)
if duration >= 60:
w = ''
if duration >= 3600 * 12:
w += time.strftime(' on %d %b %Y', time.gmtime(t))
w += time.strftime(' at %H:%MZ', time.gmtime(t))
phenny.reply('Okay, will remind%s' % w)
else: phenny.reply('Okay, will remind in %s secs' % duration)
remind.commands = ['in']
if __name__ == '__main__':
print __doc__.strip()

View File

@ -82,13 +82,13 @@ def f_remind(phenny, input):
if not phenny.reminders.has_key(tellee): if not phenny.reminders.has_key(tellee):
phenny.reminders[tellee] = [(teller, verb, timenow, msg)] phenny.reminders[tellee] = [(teller, verb, timenow, msg)]
else: else:
if len(phenny.reminders[tellee]) >= maximum: # if len(phenny.reminders[tellee]) >= maximum:
warn = True # warn = True
phenny.reminders[tellee].append((teller, verb, timenow, msg)) phenny.reminders[tellee].append((teller, verb, timenow, msg))
# @@ Stephanie's augmentation # @@ Stephanie's augmentation
response = "I'll pass that on when %s is around." % tellee_original response = "I'll pass that on when %s is around." % tellee_original
if warn: response += (" I'll have to use a pastebin, though, so " + # if warn: response += (" I'll have to use a pastebin, though, so " +
"your message may get lost.") # "your message may get lost.")
rand = random.random() rand = random.random()
if rand > 0.9999: response = "yeah, yeah" if rand > 0.9999: response = "yeah, yeah"
@ -138,29 +138,9 @@ def message(phenny, input):
phenny.say(line) phenny.say(line)
if reminders[maximum:]: if reminders[maximum:]:
try: phenny.say('Further messages sent privately')
if origin.sender in lispchannels: for line in reminders[maximum:]:
chan = origin.sender phenny.msg(tellee, line)
else: chan = 'None'
result = web.post('http://paste.lisp.org/submit',
{'channel': chan,
'username': phenny.nick,
'title': 'Further Messages for %s' % tellee,
'colorize': 'None',
'text': '\n'.join(reminders[maximum:]) + '\n',
'captcha': 'lisp',
'captchaid': 'bdf447484f62a3e8b23816f9acee79d9'
}
)
uris = re.findall('http://paste.lisp.org/display/\d+', result)
uri = list(reversed(uris)).pop()
if not origin.sender in lispchannels:
message = '%s: see %s for further messages' % (tellee, uri)
phenny.say(message)
except:
error = '[Sorry, some messages were elided and lost...]'
phenny.say(error)
if len(phenny.reminders.keys()) != remkeys: if len(phenny.reminders.keys()) != remkeys:
dumpReminders(phenny.tell_filename, phenny.reminders) # @@ tell dumpReminders(phenny.tell_filename, phenny.reminders) # @@ tell

View File

@ -24,7 +24,7 @@ r_redirect = re.compile(
abbrs = ['etc', 'ca', 'cf', 'Co', 'Ltd', 'Inc', 'Mt', 'Mr', 'Mrs', abbrs = ['etc', 'ca', 'cf', 'Co', 'Ltd', 'Inc', 'Mt', 'Mr', 'Mrs',
'Dr', 'Ms', 'Rev', 'Fr', 'St', 'Sgt', 'pron', 'approx', 'lit', 'Dr', 'Ms', 'Rev', 'Fr', 'St', 'Sgt', 'pron', 'approx', 'lit',
'syn', 'transl', 'sess', 'fl', 'Op'] \ 'syn', 'transl', 'sess', 'fl', 'Op', 'Dec'] \
+ list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') \ + list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') \
+ list('abcdefghijklmnopqrstuvwxyz') + list('abcdefghijklmnopqrstuvwxyz')
t_sentence = r'^.{5,}?(?<!\b%s)(?:\.(?=[\[ ][A-Z0-9]|\Z)|\Z)' t_sentence = r'^.{5,}?(?<!\b%s)(?:\.(?=[\[ ][A-Z0-9]|\Z)|\Z)'