Port to python3, fix ssl support

master
mutantmonkey 2011-09-22 14:17:27 -04:00
parent 8d601d52bd
commit 50fe275870
41 changed files with 628 additions and 622 deletions

View File

@ -37,8 +37,8 @@ def run_phenny(config):
p.run(config.host, config.port, config.ssl, config.ipv6) p.run(config.host, config.port, config.ssl, config.ipv6)
try: Watcher() try: Watcher()
except Exception, e: except Exception as e:
print >> sys.stderr, 'Warning:', e, '(in __init__.py)' print('Warning:', e, '(in __init__.py)', file=sys.stderr)
while True: while True:
try: connect(config) try: connect(config)
@ -49,7 +49,7 @@ def run_phenny(config):
break break
warning = 'Warning: Disconnected. Reconnecting in %s seconds...' % delay warning = 'Warning: Disconnected. Reconnecting in %s seconds...' % delay
print >> sys.stderr, warning print(warning, file=sys.stderr)
time.sleep(delay) time.sleep(delay)
def run(config): def run(config):
@ -59,4 +59,4 @@ def run(config):
else: t.start() else: t.start()
if __name__ == '__main__': if __name__ == '__main__':
print __doc__ print(__doc__)

371
bot.py
View File

@ -13,222 +13,225 @@ import irc
home = os.getcwd() home = os.getcwd()
def decode(bytes): def decode(bytes):
try: text = bytes.decode('utf-8') if type(bytes) == str:
except UnicodeDecodeError: return bytes
try: text = bytes.decode('iso-8859-1') try: text = bytes.decode('utf-8')
except UnicodeDecodeError: except UnicodeDecodeError:
text = bytes.decode('cp1252') try: text = bytes.decode('iso-8859-1')
return text except UnicodeDecodeError:
text = bytes.decode('cp1252')
return text
class Phenny(irc.Bot): class Phenny(irc.Bot):
def __init__(self, config): def __init__(self, config):
args = (config.nick, config.name, config.channels, config.password) args = (config.nick, config.name, config.channels, config.password)
irc.Bot.__init__(self, *args) irc.Bot.__init__(self, *args)
self.config = config self.config = config
self.doc = {} self.doc = {}
self.stats = {} self.stats = {}
self.setup() self.setup()
def setup(self): def setup(self):
self.variables = {} self.variables = {}
filenames = [] filenames = []
if not hasattr(self.config, 'enable'): if not hasattr(self.config, 'enable'):
for fn in os.listdir(os.path.join(home, 'modules')): for fn in os.listdir(os.path.join(home, 'modules')):
if fn.endswith('.py') and not fn.startswith('_'): if fn.endswith('.py') and not fn.startswith('_'):
filenames.append(os.path.join(home, 'modules', fn)) filenames.append(os.path.join(home, 'modules', fn))
else: else:
for fn in self.config.enable: for fn in self.config.enable:
filenames.append(os.path.join(home, 'modules', fn + '.py')) filenames.append(os.path.join(home, 'modules', fn + '.py'))
if hasattr(self.config, 'extra'): if hasattr(self.config, 'extra'):
for fn in self.config.extra: for fn in self.config.extra:
if os.path.isfile(fn): if os.path.isfile(fn):
filenames.append(fn) filenames.append(fn)
elif os.path.isdir(fn): elif os.path.isdir(fn):
for n in os.listdir(fn): for n in os.listdir(fn):
if n.endswith('.py') and not n.startswith('_'): if n.endswith('.py') and not n.startswith('_'):
filenames.append(os.path.join(fn, n)) filenames.append(os.path.join(fn, n))
modules = [] modules = []
excluded_modules = getattr(self.config, 'exclude', []) excluded_modules = getattr(self.config, 'exclude', [])
for filename in filenames: for filename in filenames:
name = os.path.basename(filename)[:-3] name = os.path.basename(filename)[:-3]
if name in excluded_modules: continue if name in excluded_modules: continue
# if name in sys.modules: # if name in sys.modules:
# del sys.modules[name] # del sys.modules[name]
try: module = imp.load_source(name, filename) try: module = imp.load_source(name, filename)
except Exception, e: except Exception as e:
print >> sys.stderr, "Error loading %s: %s (in bot.py)" % (name, e) print("Error loading %s: %s (in bot.py)" % (name, e), file=sys.stderr)
else: else:
if hasattr(module, 'setup'): if hasattr(module, 'setup'):
module.setup(self) module.setup(self)
self.register(vars(module)) self.register(vars(module))
modules.append(name) modules.append(name)
if modules: if modules:
print >> sys.stderr, 'Registered modules:', ', '.join(modules) print('Registered modules:', ', '.join(modules), file=sys.stderr)
else: print >> sys.stderr, "Warning: Couldn't find any modules" else: print("Warning: Couldn't find any modules", file=sys.stderr)
self.bind_commands() self.bind_commands()
def register(self, variables): def register(self, variables):
# This is used by reload.py, hence it being methodised # This is used by reload.py, hence it being methodised
for name, obj in variables.iteritems(): for name, obj in variables.items():
if hasattr(obj, 'commands') or hasattr(obj, 'rule'): if hasattr(obj, 'commands') or hasattr(obj, 'rule'):
self.variables[name] = obj self.variables[name] = obj
def bind_commands(self): def bind_commands(self):
self.commands = {'high': {}, 'medium': {}, 'low': {}} self.commands = {'high': {}, 'medium': {}, 'low': {}}
def bind(self, priority, regexp, func): def bind(self, priority, regexp, func):
print priority, regexp.pattern.encode('utf-8'), func print(priority, regexp.pattern.encode('utf-8'), func)
# register documentation # register documentation
if not hasattr(func, 'name'): if not hasattr(func, 'name'):
func.name = func.__name__ func.name = func.__name__
if func.__doc__: if func.__doc__:
if hasattr(func, 'example'): if hasattr(func, 'example'):
example = func.example example = func.example
example = example.replace('$nickname', self.nick) example = example.replace('$nickname', self.nick)
else: example = None else: example = None
self.doc[func.name] = (func.__doc__, example) self.doc[func.name] = (func.__doc__, example)
self.commands[priority].setdefault(regexp, []).append(func) self.commands[priority].setdefault(regexp, []).append(func)
def sub(pattern, self=self): def sub(pattern, self=self):
# These replacements have significant order # These replacements have significant order
pattern = pattern.replace('$nickname', re.escape(self.nick)) pattern = pattern.replace('$nickname', re.escape(self.nick))
return pattern.replace('$nick', r'%s[,:] +' % re.escape(self.nick)) return pattern.replace('$nick', r'%s[,:] +' % re.escape(self.nick))
for name, func in self.variables.iteritems(): for name, func in self.variables.items():
# print name, func # print name, func
if not hasattr(func, 'priority'): if not hasattr(func, 'priority'):
func.priority = 'medium' func.priority = 'medium'
if not hasattr(func, 'thread'): if not hasattr(func, 'thread'):
func.thread = True func.thread = True
if not hasattr(func, 'event'): if not hasattr(func, 'event'):
func.event = 'PRIVMSG' func.event = 'PRIVMSG'
else: func.event = func.event.upper() else: func.event = func.event.upper()
if hasattr(func, 'rule'): if hasattr(func, 'rule'):
if isinstance(func.rule, str): if isinstance(func.rule, str):
pattern = sub(func.rule) pattern = sub(func.rule)
regexp = re.compile(pattern) regexp = re.compile(pattern)
bind(self, func.priority, regexp, func) bind(self, func.priority, regexp, func)
if isinstance(func.rule, tuple): if isinstance(func.rule, tuple):
# 1) e.g. ('$nick', '(.*)') # 1) e.g. ('$nick', '(.*)')
if len(func.rule) == 2 and isinstance(func.rule[0], str): if len(func.rule) == 2 and isinstance(func.rule[0], str):
prefix, pattern = func.rule prefix, pattern = func.rule
prefix = sub(prefix) prefix = sub(prefix)
regexp = re.compile(prefix + pattern) regexp = re.compile(prefix + pattern)
bind(self, func.priority, regexp, func) bind(self, func.priority, regexp, func)
# 2) e.g. (['p', 'q'], '(.*)') # 2) e.g. (['p', 'q'], '(.*)')
elif len(func.rule) == 2 and isinstance(func.rule[0], list): elif len(func.rule) == 2 and isinstance(func.rule[0], list):
prefix = self.config.prefix prefix = self.config.prefix
commands, pattern = func.rule commands, pattern = func.rule
for command in commands: for command in commands:
command = r'(%s)\b(?: +(?:%s))?' % (command, pattern) command = r'(%s)\b(?: +(?:%s))?' % (command, pattern)
regexp = re.compile(prefix + command) regexp = re.compile(prefix + command)
bind(self, func.priority, regexp, func) bind(self, func.priority, regexp, func)
# 3) e.g. ('$nick', ['p', 'q'], '(.*)') # 3) e.g. ('$nick', ['p', 'q'], '(.*)')
elif len(func.rule) == 3: elif len(func.rule) == 3:
prefix, commands, pattern = func.rule prefix, commands, pattern = func.rule
prefix = sub(prefix) prefix = sub(prefix)
for command in commands: for command in commands:
command = r'(%s) +' % command command = r'(%s) +' % command
regexp = re.compile(prefix + command + pattern) regexp = re.compile(prefix + command + pattern)
bind(self, func.priority, regexp, func) bind(self, func.priority, regexp, func)
if hasattr(func, 'commands'): if hasattr(func, 'commands'):
for command in func.commands: for command in func.commands:
template = r'^%s(%s)(?: +(.*))?$' template = r'^%s(%s)(?: +(.*))?$'
pattern = template % (self.config.prefix, command) pattern = template % (self.config.prefix, command)
regexp = re.compile(pattern) regexp = re.compile(pattern)
bind(self, func.priority, regexp, func) bind(self, func.priority, regexp, func)
def wrapped(self, origin, text, match): def wrapped(self, origin, text, match):
class PhennyWrapper(object): class PhennyWrapper(object):
def __init__(self, phenny): def __init__(self, phenny):
self.bot = phenny self.bot = phenny
def __getattr__(self, attr): def __getattr__(self, attr):
sender = origin.sender or text sender = origin.sender or text
if attr == 'reply': if attr == 'reply':
return (lambda msg: return (lambda msg:
self.bot.msg(sender, origin.nick + ': ' + msg)) self.bot.msg(sender, origin.nick + ': ' + msg))
elif attr == 'say': elif attr == 'say':
return lambda msg: self.bot.msg(sender, msg) return lambda msg: self.bot.msg(sender, msg)
elif attr == 'do': elif attr == 'do':
return lambda msg: self.bot.action(sender, msg) return lambda msg: self.bot.action(sender, msg)
return getattr(self.bot, attr) return getattr(self.bot, attr)
return PhennyWrapper(self) return PhennyWrapper(self)
def input(self, origin, text, bytes, match, event, args): def input(self, origin, text, bytes, match, event, args):
class CommandInput(unicode): class CommandInput(str):
def __new__(cls, text, origin, bytes, match, event, args): def __new__(cls, text, origin, bytes, match, event, args):
s = unicode.__new__(cls, text) s = str.__new__(cls, text)
s.sender = origin.sender s.sender = decode(origin.sender)
s.nick = origin.nick s.nick = decode(origin.nick)
s.event = event s.event = event
s.bytes = bytes s.bytes = bytes
s.match = match s.match = match
s.group = match.group s.group = match.group
s.groups = match.groups s.groups = match.groups
s.args = args s.args = args
s.admin = origin.nick in self.config.admins s.admin = self.nick in self.config.admins
s.owner = origin.nick == self.config.owner s.owner = self.nick == self.config.owner
return s return s
return CommandInput(text, origin, bytes, match, event, args) return CommandInput(text, origin, bytes, match, event, args)
def call(self, func, origin, phenny, input): def call(self, func, origin, phenny, input):
try: func(phenny, input) try: func(phenny, input)
except Exception, e: except Exception as e:
self.error(origin) self.error(origin)
def limit(self, origin, func): def limit(self, origin, func):
if origin.sender and origin.sender.startswith('#'): if origin.sender and origin.sender.startswith(b'#'):
if hasattr(self.config, 'limit'): if hasattr(self.config, 'limit'):
limits = self.config.limit.get(origin.sender) limits = self.config.limit.get(origin.sender)
if limits and (func.__module__ not in limits): if limits and (func.__module__ not in limits):
return True return True
return False return False
def dispatch(self, origin, args): def dispatch(self, origin, args):
bytes, event, args = args[0], args[1], args[2:] bytes, event, args = args[0], args[1], args[2:]
text = decode(bytes) text = decode(bytes)
event = decode(event)
if origin.nick in self.config.ignore: if origin.nick in self.config.ignore:
return return
for priority in ('high', 'medium', 'low'): for priority in ('high', 'medium', 'low'):
items = self.commands[priority].items() items = list(self.commands[priority].items())
for regexp, funcs in items: for regexp, funcs in items:
for func in funcs: for func in funcs:
if event != func.event: continue if event != func.event: continue
match = regexp.match(text) match = regexp.match(text)
if match: if match:
if self.limit(origin, func): continue if self.limit(origin, func): continue
phenny = self.wrapped(origin, text, match) phenny = self.wrapped(origin, text, match)
input = self.input(origin, text, bytes, match, event, args) input = self.input(origin, text, bytes, match, event, args)
if func.thread: if func.thread:
targs = (func, origin, phenny, input) targs = (func, origin, phenny, input)
t = threading.Thread(target=self.call, args=targs) t = threading.Thread(target=self.call, args=targs)
t.start() t.start()
else: self.call(func, origin, phenny, input) else: self.call(func, origin, phenny, input)
for source in [origin.sender, origin.nick]: for source in [origin.sender, origin.nick]:
try: self.stats[(func.name, source)] += 1 try: self.stats[(func.name, source)] += 1
except KeyError: except KeyError:
self.stats[(func.name, source)] = 1 self.stats[(func.name, source)] = 1
if __name__ == '__main__': if __name__ == '__main__':
print __doc__ print(__doc__)

332
irc.py
View File

@ -9,204 +9,216 @@ http://inamidst.com/phenny/
import sys, re, time, traceback import sys, re, time, traceback
import socket, asyncore, asynchat import socket, asyncore, asynchat
import ssl
class Origin(object): class Origin(object):
source = re.compile(r'([^!]*)!?([^@]*)@?(.*)') source = re.compile(r'([^!]*)!?([^@]*)@?(.*)')
def __init__(self, bot, source, args): def __init__(self, bot, source, args):
match = Origin.source.match(source or '') source = source.decode('utf-8')
self.nick, self.user, self.host = match.groups() match = Origin.source.match(source or '')
self.nick, self.user, self.host = match.groups()
if len(args) > 1: if len(args) > 1:
target = args[1] target = args[1]
else: target = None else: target = None
mappings = {bot.nick: self.nick, None: None} mappings = {bot.nick: self.nick, None: None}
self.sender = mappings.get(target, target) self.sender = mappings.get(target, target)
class Bot(asynchat.async_chat): class Bot(asynchat.async_chat):
def __init__(self, nick, name, channels, password=None): def __init__(self, nick, name, channels, password=None):
asynchat.async_chat.__init__(self) asynchat.async_chat.__init__(self)
self.set_terminator('\n') self.set_terminator(b'\n')
self.buffer = '' self.buffer = b''
self.nick = nick self.nick = nick
self.user = nick self.user = nick
self.name = name self.name = name
self.password = password self.password = password
self.verbose = True self.verbose = True
self.channels = channels or [] self.channels = channels or []
self.stack = [] self.stack = []
import threading import threading
self.sending = threading.RLock() self.sending = threading.RLock()
# def push(self, *args, **kargs): # def push(self, *args, **kargs):
# asynchat.async_chat.push(self, *args, **kargs) # asynchat.async_chat.push(self, *args, **kargs)
def __write(self, args, text=None): def __write(self, args, text=None):
# print '%r %r %r' % (self, args, text) # print '%r %r %r' % (self, args, text)
try: try:
if text is not None: if text is not None:
self.push((' '.join(args) + ' :' + text)[:512] + '\r\n') self.push((b' '.join(args) + b' :' + text)[:512] + b'\r\n')
else: self.push(' '.join(args)[:512] + '\r\n') else:
except IndexError: self.push(b' '.join(args)[:512] + b'\r\n')
pass except IndexError:
pass
def write(self, args, text=None): def write(self, args, text=None):
# This is a safe version of __write print(args, text)
def safe(input): # This is a safe version of __write
input = input.replace('\n', '') def safe(input):
input = input.replace('\r', '') input = input.replace('\n', '')
return input.encode('utf-8') input = input.replace('\r', '')
try: return input.encode('utf-8')
args = [safe(arg) for arg in args] try:
if text is not None: args = [safe(arg) for arg in args]
text = safe(text) if text is not None:
self.__write(args, text) text = safe(text)
except Exception, e: pass self.__write(args, text)
except Exception as e:
pass
def run(self, host, port=6667, ssl=False, ipv6=False): def run(self, host, port=6667, ssl=False, ipv6=False):
self.initiate_connect(host, port, ssl, ipv6) self.initiate_connect(host, port, ssl, ipv6)
def initiate_connect(self, host, port, ssl, ipv6): def initiate_connect(self, host, port, use_ssl, ipv6):
if self.verbose: if self.verbose:
message = 'Connecting to %s:%s...' % (host, port) message = 'Connecting to %s:%s...' % (host, port)
print >> sys.stderr, message, print(message, end=' ', file=sys.stderr)
if ipv6 and socket.has_ipv6: if ipv6 and socket.has_ipv6:
af = socket.AF_INET6 af = socket.AF_INET6
else: else:
af = socket.AF_INET af = socket.AF_INET
self.create_socket(af, socket.SOCK_STREAM) self.create_socket(af, socket.SOCK_STREAM, use_ssl)
self.connect((host, port)) self.connect((host, port))
if ssl: try: asyncore.loop()
import ssl except KeyboardInterrupt:
self.socket = ssl.wrap_socket(self.socket) sys.exit()
try: asyncore.loop()
except KeyboardInterrupt:
sys.exit()
def handle_connect(self): def create_socket(self, family, type, use_ssl=False):
if self.verbose: self.family_and_type = family, type
print >> sys.stderr, 'connected!' sock = socket.socket(family, type)
if self.password: if use_ssl:
self.write(('PASS', self.password)) sock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLSv1)
self.write(('NICK', self.nick)) # FIXME: ssl module does not appear to work properly with nonblocking sockets
self.write(('USER', self.user, '+iw', self.nick), self.name) #sock.setblocking(0)
self.set_socket(sock)
def handle_close(self): def handle_connect(self):
self.close() if self.verbose:
print >> sys.stderr, 'Closed!' print('connected!', file=sys.stderr)
if self.password:
self.write(('PASS', self.password))
self.write(('NICK', self.nick))
self.write(('USER', self.user, '+iw', self.nick), self.name)
def collect_incoming_data(self, data): def handle_close(self):
self.buffer += data self.close()
print('Closed!', file=sys.stderr)
def found_terminator(self): def collect_incoming_data(self, data):
line = self.buffer self.buffer += data
if line.endswith('\r'):
line = line[:-1]
self.buffer = ''
# print line def found_terminator(self):
if line.startswith(':'): line = self.buffer
source, line = line[1:].split(' ', 1) if line.endswith(b'\r'):
else: source = None line = line[:-1]
self.buffer = b''
if ' :' in line: # print line
argstr, text = line.split(' :', 1) if line.startswith(b':'):
else: argstr, text = line, '' source, line = line[1:].split(b' ', 1)
args = argstr.split() else: source = None
origin = Origin(self, source, args) if b' :' in line:
self.dispatch(origin, tuple([text] + args)) argstr, text = line.split(b' :', 1)
else: argstr, text = line, b''
args = argstr.split()
if args[0] == 'PING': origin = Origin(self, source, args)
self.write(('PONG', text)) self.dispatch(origin, tuple([text] + args))
def dispatch(self, origin, args): if args[0] == b'PING':
pass self.write(('PONG', text))
def msg(self, recipient, text): def dispatch(self, origin, args):
self.sending.acquire() pass
# Cf. http://swhack.com/logs/2006-03-01#T19-43-25 def msg(self, recipient, text):
if isinstance(text, unicode): self.sending.acquire()
try: text = text.encode('utf-8')
except UnicodeEncodeError, e:
text = e.__class__ + ': ' + str(e)
if isinstance(recipient, unicode):
try: recipient = recipient.encode('utf-8')
except UnicodeEncodeError, e:
return
# No messages within the last 3 seconds? Go ahead! # Cf. http://swhack.com/logs/2006-03-01#T19-43-25
# Otherwise, wait so it's been at least 0.8 seconds + penalty if isinstance(text, str):
if self.stack: try: text = text.encode('utf-8')
elapsed = time.time() - self.stack[-1][0] except UnicodeEncodeError as e:
if elapsed < 3: text = e.__class__ + ': ' + str(e)
penalty = float(max(0, len(text) - 50)) / 70 if isinstance(recipient, str):
wait = 0.8 + penalty try: recipient = recipient.encode('utf-8')
if elapsed < wait: except UnicodeEncodeError as e:
time.sleep(wait - elapsed) return
# Loop detection # No messages within the last 3 seconds? Go ahead!
messages = [m[1] for m in self.stack[-8:]] # Otherwise, wait so it's been at least 0.8 seconds + penalty
if messages.count(text) >= 5: if self.stack:
text = '...' elapsed = time.time() - self.stack[-1][0]
if messages.count('...') >= 3: if elapsed < 3:
self.sending.release() penalty = float(max(0, len(text) - 50)) / 70
return wait = 0.8 + penalty
if elapsed < wait:
time.sleep(wait - elapsed)
def safe(input): # Loop detection
input = input.replace('\n', '') messages = [m[1] for m in self.stack[-8:]]
return input.replace('\r', '') if messages.count(text) >= 5:
self.__write(('PRIVMSG', safe(recipient)), safe(text)) text = '...'
self.stack.append((time.time(), text)) if messages.count('...') >= 3:
self.stack = self.stack[-10:] self.sending.release()
return
self.sending.release() def safe(input):
input = input.replace(b'\n', b'')
return input.replace(b'\r', b'')
self.__write((b'PRIVMSG', safe(recipient)), safe(text))
self.stack.append((time.time(), text))
self.stack = self.stack[-10:]
def action(self, recipient, text): self.sending.release()
text = "ACTION %s" % text
textu = chr(1) + text + chr(1)
return self.msg(recipient, textu)
def notice(self, dest, text): def action(self, recipient, text):
self.write(('NOTICE', dest), text) text = "ACTION %s" % text
textu = chr(1) + text + chr(1)
return self.msg(recipient, textu)
def error(self, origin): def notice(self, dest, text):
try: self.write((b'NOTICE', dest), text)
import traceback
trace = traceback.format_exc()
print trace
lines = list(reversed(trace.splitlines()))
report = [lines[0].strip()] def error(self, origin):
for line in lines: try:
line = line.strip() import traceback
if line.startswith('File "/'): trace = traceback.format_exc()
report.append(line[0].lower() + line[1:]) print(trace)
break lines = list(reversed(trace.splitlines()))
else: report.append('source unknown')
report = [lines[0].strip()]
for line in lines:
line = line.strip()
if line.startswith('File "/'):
report.append(line[0].lower() + line[1:])
break
else: report.append('source unknown')
self.msg(origin.sender, report[0] + ' (' + report[1] + ')')
except: self.msg(origin.sender, "Got an error.")
self.msg(origin.sender, report[0] + ' (' + report[1] + ')')
except: self.msg(origin.sender, "Got an error.")
class TestBot(Bot): class TestBot(Bot):
def f_ping(self, origin, match, args): def f_ping(self, origin, match, args):
delay = m.group(1) delay = m.group(1)
if delay is not None: if delay is not None:
import time import time
time.sleep(int(delay)) time.sleep(int(delay))
self.msg(origin.sender, 'pong (%s)' % delay) self.msg(origin.sender, 'pong (%s)' % delay)
else: self.msg(origin.sender, 'pong') else: self.msg(origin.sender, 'pong')
f_ping.rule = r'^\.ping(?:[ \t]+(\d+))?$' f_ping.rule = r'^\.ping(?:[ \t]+(\d+))?$'
def main(): def main():
# bot = TestBot('testbot', ['#d8uv.com']) bot = TestBot('testbot007', 'testbot007', ['#wadsworth'])
# bot.run('irc.freenode.net') bot.run('irc.freenode.net')
print __doc__ print(__doc__)
if __name__=="__main__": if __name__=="__main__":
main() main()

View File

@ -48,5 +48,5 @@ def eightball(phenny, input):
eightball.commands = ['8ball'] eightball.commands = ['8ball']
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -60,4 +60,4 @@ me.rule = (['me'], r'(#?\S+) (.*)')
me.priority = 'low' me.priority = 'low'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -10,7 +10,7 @@ modified from Wikipedia module
author: mutantmonkey <mutantmonkey@gmail.com> author: mutantmonkey <mutantmonkey@gmail.com>
""" """
import re, urllib import re, urllib.request, urllib.parse, urllib.error
import web import web
import json import json
@ -65,9 +65,9 @@ def awik(phenny, input):
origterm = input.groups()[1] origterm = input.groups()[1]
if not origterm: if not origterm:
return phenny.say('Perhaps you meant ".awik dwm"?') return phenny.say('Perhaps you meant ".awik dwm"?')
origterm = origterm.encode('utf-8') origterm = origterm
term = urllib.unquote(origterm) term = urllib.parse.unquote(origterm)
term = term[0].upper() + term[1:] term = term[0].upper() + term[1:]
term = term.replace(' ', '_') term = term.replace(' ', '_')
@ -84,4 +84,4 @@ awik.commands = ['awik']
awik.priority = 'high' awik.priority = 'high'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -22,5 +22,5 @@ bothug.commands = ['bothug']
bothug.priority = 'low' bothug.priority = 'low'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -44,12 +44,12 @@ def botsnack(phenny, input):
# ignore this invocation. Else reset to the default state # ignore this invocation. Else reset to the default state
if botsnack.coolingdown: if botsnack.coolingdown:
if now - botsnack.coolingstarted > botsnack.coolingperiod: if now - botsnack.coolingstarted > botsnack.coolingperiod:
print "cooling down over, reseting" print("cooling down over, reseting")
botsnack.coolingdown = False botsnack.coolingdown = False
botsnack.hunger = 50.0 botsnack.hunger = 50.0
botsnack.last_tick = now botsnack.last_tick = now
else: else:
print "cooling down! %s < %s" %(now - botsnack.coolingstarted, botsnack.coolingperiod) print("cooling down! %s < %s" %(now - botsnack.coolingstarted, botsnack.coolingperiod))
return # ignore! return # ignore!
# 1. Time has has passed, so the bot has gotten # 1. Time has has passed, so the bot has gotten
@ -60,7 +60,7 @@ def botsnack(phenny, input):
botsnack.hunger = increase_hunger(old_hunger, delta) botsnack.hunger = increase_hunger(old_hunger, delta)
print "hunger was %s, increased to %s" %(old_hunger, botsnack.hunger) print("hunger was %s, increased to %s" %(old_hunger, botsnack.hunger))
botsnack.last_tick = now botsnack.last_tick = now
@ -68,7 +68,7 @@ def botsnack(phenny, input):
old_hunger = botsnack.hunger old_hunger = botsnack.hunger
botsnack.hunger = decrease_hunger(old_hunger, random.uniform(1,5)) botsnack.hunger = decrease_hunger(old_hunger, random.uniform(1,5))
print "hunger was %s, decreased to %s" %(old_hunger, botsnack.hunger) print("hunger was %s, decreased to %s" %(old_hunger, botsnack.hunger))
if botsnack.hunger > 95: # special case to prevent abuse if botsnack.hunger > 95: # special case to prevent abuse
phenny.say("Too much food!") phenny.say("Too much food!")
@ -106,5 +106,5 @@ botsnack.last_tick = time.time()
botsnack.coolingdown = False botsnack.coolingdown = False
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -17,8 +17,8 @@ r_tag = re.compile(r'<\S+.*?>')
subs = [ subs = [
(' in ', ' -> '), (' in ', ' -> '),
(' over ', ' / '), (' over ', ' / '),
(u'£', 'GBP '), ('£', 'GBP '),
(u'', 'EUR '), ('', 'EUR '),
('\$', 'USD '), ('\$', 'USD '),
(r'\bKB\b', 'kilobytes'), (r'\bKB\b', 'kilobytes'),
(r'\bMB\b', 'megabytes'), (r'\bMB\b', 'megabytes'),
@ -41,7 +41,7 @@ def calc(phenny, input):
precision = 5 precision = 5
if query[-3:] in ('GBP', 'USD', 'EUR', 'NOK'): if query[-3:] in ('GBP', 'USD', 'EUR', 'NOK'):
precision = 2 precision = 2
query = web.urllib.quote(query.encode('utf-8')) query = web.quote(query)
uri = 'http://futureboy.us/fsp/frink.fsp?fromVal=' uri = 'http://futureboy.us/fsp/frink.fsp?fromVal='
bytes = web.get(uri + query) bytes = web.get(uri + query)
@ -71,18 +71,18 @@ def c(phenny, input):
"""Google calculator.""" """Google calculator."""
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('utf-8') q = input.group(2)
q = q.replace('\xcf\x95', 'phi') # utf-8 U+03D5 q = q.replace('\xcf\x95', 'phi') # utf-8 U+03D5
q = q.replace('\xcf\x80', 'pi') # utf-8 U+03C0 q = q.replace('\xcf\x80', 'pi') # utf-8 U+03C0
uri = 'http://www.google.com/ig/calculator?q=' uri = 'http://www.google.com/ig/calculator?q='
bytes = web.get(uri + web.urllib.quote(q)) bytes = web.get(uri + web.quote(q))
parts = bytes.split('",') parts = bytes.split('",')
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 = ''.join(chr(ord(c)) for c in answer)
answer = answer.decode('utf-8') answer = answer.decode('utf-8')
answer = answer.replace(u'\xc2\xa0', ',') answer = answer.replace('\xc2\xa0', ',')
answer = answer.replace('<sup>', '^(') answer = answer.replace('<sup>', '^(')
answer = answer.replace('</sup>', ')') answer = answer.replace('</sup>', ')')
answer = web.decode(answer) answer = web.decode(answer)
@ -92,9 +92,9 @@ c.commands = ['c']
c.example = '.c 5 + 3' c.example = '.c 5 + 3'
def py(phenny, input): def py(phenny, input):
query = input.group(2).encode('utf-8') query = input.group(2)
uri = 'http://tumbolia.appspot.com/py/' uri = 'http://tumbolia.appspot.com/py/'
answer = web.get(uri + web.urllib.quote(query)) answer = web.get(uri + web.quote(query))
if answer: if answer:
phenny.say(answer) phenny.say(answer)
else: phenny.reply('Sorry, no result.') else: phenny.reply('Sorry, no result.')
@ -103,13 +103,13 @@ py.commands = ['py']
def wa(phenny, input): def wa(phenny, input):
if not input.group(2): if not input.group(2):
return phenny.reply("No search term.") return phenny.reply("No search term.")
query = input.group(2).encode('utf-8') query = input.group(2)
uri = 'http://tumbolia.appspot.com/wa/' uri = 'http://tumbolia.appspot.com/wa/'
answer = web.get(uri + web.urllib.quote(query.replace('+', '%2B'))) answer = web.get(uri + web.quote(query.replace('+', '%2B')))
if answer: if answer:
phenny.say(answer) phenny.say(answer)
else: phenny.reply('Sorry, no result.') else: phenny.reply('Sorry, no result.')
wa.commands = ['wa'] wa.commands = ['wa']
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -131,4 +131,4 @@ chill.commands = ['chill']
chill.priority = 'low' chill.priority = 'low'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -7,7 +7,7 @@ Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/ http://inamidst.com/phenny/
""" """
import re, math, time, urllib, locale, socket, struct, datetime import re, math, time, urllib.request, urllib.parse, urllib.error, locale, socket, struct, datetime
from decimal import Decimal as dec from decimal import Decimal as dec
from tools import deprecated from tools import deprecated
@ -203,9 +203,9 @@ def f_time(self, origin, match, args):
People = self.config.timezones People = self.config.timezones
else: People = {} else: People = {}
if People.has_key(tz): if tz in People:
tz = People[tz] tz = People[tz]
elif (not match.group(2)) and People.has_key(origin.nick): elif (not match.group(2)) and origin.nick in People:
tz = People[origin.nick] tz = People[origin.nick]
TZ = tz.upper() TZ = tz.upper()
@ -218,7 +218,7 @@ def f_time(self, origin, match, args):
locale.setlocale(locale.LC_TIME, (tz[1:-1], 'UTF-8')) locale.setlocale(locale.LC_TIME, (tz[1:-1], 'UTF-8'))
msg = time.strftime("%A, %d %B %Y %H:%M:%SZ", time.gmtime()) msg = time.strftime("%A, %d %B %Y %H:%M:%SZ", time.gmtime())
self.msg(origin.sender, msg) self.msg(origin.sender, msg)
elif TimeZones.has_key(TZ): elif TZ in TimeZones:
offset = TimeZones[TZ] * 3600 offset = TimeZones[TZ] * 3600
timenow = time.gmtime(time.time() + offset) timenow = time.gmtime(time.time() + offset)
msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(TZ), timenow) msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(TZ), timenow)
@ -273,7 +273,7 @@ yi.priority = 'low'
def tock(phenny, input): def tock(phenny, input):
"""Shows the time from the USNO's atomic clock.""" """Shows the time from the USNO's atomic clock."""
u = urllib.urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl') u = urllib.request.urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl')
info = u.info() info = u.info()
u.close() u.close()
phenny.say('"' + info['Date'] + '" - tycho.usno.navy.mil') phenny.say('"' + info['Date'] + '" - tycho.usno.navy.mil')
@ -290,7 +290,7 @@ def npl(phenny, input):
d = dec('0.0') d = dec('0.0')
for i in range(8): for i in range(8):
d += dec(buf[32 + i]) * dec(str(math.pow(2, (3 - i) * 8))) d += dec(buf[32 + i]) * dec(str(math.pow(2, (3 - i) * 8)))
d -= dec(2208988800L) d -= dec(2208988800)
a, b = str(d).split('.') a, b = str(d).split('.')
f = '%Y-%m-%d %H:%M:%S' f = '%Y-%m-%d %H:%M:%S'
result = datetime.datetime.fromtimestamp(d).strftime(f) + '.' + b[:6] result = datetime.datetime.fromtimestamp(d).strftime(f) + '.' + b[:6]
@ -300,4 +300,4 @@ npl.commands = ['npl']
npl.priority = 'high' npl.priority = 'high'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -21,7 +21,7 @@ def about(u, cp=None, name=None):
if not unicodedata.combining(u): if not unicodedata.combining(u):
template = 'U+%04X %s (%s)' template = 'U+%04X %s (%s)'
else: template = 'U+%04X %s (\xe2\x97\x8c%s)' else: template = 'U+%04X %s (\xe2\x97\x8c%s)'
return template % (cp, name, u.encode('utf-8')) return template % (cp, name, u)
def codepoint_simple(arg): def codepoint_simple(arg):
arg = arg.upper() arg = arg.upper()
@ -29,8 +29,8 @@ def codepoint_simple(arg):
r_label = re.compile('\\b' + arg.replace(' ', '.*\\b') + '\\b') r_label = re.compile('\\b' + arg.replace(' ', '.*\\b') + '\\b')
results = [] results = []
for cp in xrange(0xFFFF): for cp in range(0xFFFF):
u = unichr(cp) u = chr(cp)
try: name = unicodedata.name(u) try: name = unicodedata.name(u)
except ValueError: continue except ValueError: continue
@ -38,8 +38,8 @@ def codepoint_simple(arg):
results.append((len(name), u, cp, name)) results.append((len(name), u, cp, name))
if not results: if not results:
r_label = re.compile('\\b' + arg.replace(' ', '.*\\b')) r_label = re.compile('\\b' + arg.replace(' ', '.*\\b'))
for cp in xrange(0xFFFF): for cp in range(0xFFFF):
u = unichr(cp) u = chr(cp)
try: name = unicodedata.name(u) try: name = unicodedata.name(u)
except ValueError: continue except ValueError: continue
@ -57,8 +57,8 @@ def codepoint_extended(arg):
try: r_search = re.compile(arg) try: r_search = re.compile(arg)
except: raise ValueError('Broken regexp: %r' % arg) except: raise ValueError('Broken regexp: %r' % arg)
for cp in xrange(1, 0x10FFFF): for cp in range(1, 0x10FFFF):
u = unichr(cp) u = chr(cp)
name = unicodedata.name(u, '-') name = unicodedata.name(u, '-')
if r_search.search(name): if r_search.search(name):
@ -90,7 +90,7 @@ def u(phenny, input):
break break
if len(arg) == 4: if len(arg) == 4:
try: u = unichr(int(arg, 16)) try: u = chr(int(arg, 16))
except ValueError: pass except ValueError: pass
else: return phenny.say(about(u)) else: return phenny.say(about(u))
@ -131,4 +131,4 @@ bytes.commands = ['bytes']
bytes.example = '.bytes \xe3\x8b\xa1' bytes.example = '.bytes \xe3\x8b\xa1'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -59,8 +59,7 @@ def etymology(word):
sentence = m.group(0) sentence = m.group(0)
try: try:
sentence = unicode(sentence, 'iso-8859-1') sentence = str(sentence, 'iso-8859-1')
sentence = sentence.encode('utf-8')
except: pass except: pass
maxlength = 275 maxlength = 275
@ -98,4 +97,4 @@ f_etymology.priority = 'high'
if __name__=="__main__": if __name__=="__main__":
import sys import sys
print etymology(sys.argv[1]) print(etymology(sys.argv[1]))

View File

@ -7,20 +7,20 @@ Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/ http://inamidst.com/phenny/
""" """
import re, urllib, urllib2, httplib, urlparse, time, cookielib import re, urllib.request, urllib.parse, urllib.error, urllib.request, urllib.error, urllib.parse, http.client, urllib.parse, time, http.cookiejar
from htmlentitydefs import name2codepoint from html.entities import name2codepoint
from string import join from string import join
import web import web
from tools import deprecated from tools import deprecated
cj = cookielib.LWPCookieJar() cj = http.cookiejar.LWPCookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
urllib2.install_opener(opener) urllib.request.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)
uri = (uri or '').encode('utf-8') uri = (uri or '')
if ' ' in uri: if ' ' in uri:
uri, header = uri.rsplit(' ', 1) uri, header = uri.rsplit(' ', 1)
else: uri, header = uri, None else: uri, header = uri, None
@ -35,7 +35,7 @@ def head(phenny, input):
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)
except httplib.InvalidURL: return phenny.say("Not a valid URI, sorry.") except http.client.InvalidURL: return phenny.say("Not a valid URI, sorry.")
if not isinstance(info, list): if not isinstance(info, list):
try: info = dict(info) try: info = dict(info)
@ -49,20 +49,20 @@ def head(phenny, input):
if header is None: if header is None:
data = [] data = []
if info.has_key('Status'): if 'Status' in info:
data.append(info['Status']) data.append(info['Status'])
if info.has_key('content-type'): if 'content-type' in info:
data.append(info['content-type'].replace('; charset=', ', ')) data.append(info['content-type'].replace('; charset=', ', '))
if info.has_key('last-modified'): if 'last-modified' in info:
modified = info['last-modified'] modified = info['last-modified']
modified = time.strptime(modified, '%a, %d %b %Y %H:%M:%S %Z') modified = time.strptime(modified, '%a, %d %b %Y %H:%M:%S %Z')
data.append(time.strftime('%Y-%m-%d %H:%M:%S UTC', modified)) data.append(time.strftime('%Y-%m-%d %H:%M:%S UTC', modified))
if info.has_key('content-length'): if 'content-length' in info:
data.append(info['content-length'] + ' bytes') data.append(info['content-length'] + ' bytes')
phenny.reply(', '.join(data)) phenny.reply(', '.join(data))
else: else:
headerlower = header.lower() headerlower = header.lower()
if info.has_key(headerlower): if headerlower in info:
phenny.say(header + ': ' + info.get(headerlower)) phenny.say(header + ': ' + info.get(headerlower))
else: else:
msg = 'There was no %s header in the response.' % header msg = 'There was no %s header in the response.' % header
@ -77,7 +77,7 @@ r_entity = re.compile(r'&[A-Za-z0-9#]+;')
def f_title(self, origin, match, args): def f_title(self, origin, match, args):
""".title <URI> - Return the title of URI.""" """.title <URI> - Return the title of URI."""
uri = match.group(2) uri = match.group(2)
uri = (uri or '').encode('utf-8') uri = (uri or '')
if not uri and hasattr(self, 'last_seen_uri'): if not uri and hasattr(self, 'last_seen_uri'):
uri = self.last_seen_uri.get(origin.sender) uri = self.last_seen_uri.get(origin.sender)
@ -90,7 +90,7 @@ def f_title(self, origin, match, args):
f_title.commands = ['title'] f_title.commands = ['title']
def noteuri(phenny, input): def noteuri(phenny, input):
uri = input.group(1).encode('utf-8') uri = input.group(1)
if not hasattr(phenny.bot, 'last_seen_uri'): if not hasattr(phenny.bot, 'last_seen_uri'):
phenny.bot.last_seen_uri = {} phenny.bot.last_seen_uri = {}
phenny.bot.last_seen_uri[input.sender] = uri phenny.bot.last_seen_uri[input.sender] = uri
@ -101,7 +101,7 @@ titlecommands = r'(?:' + join(f_title.commands, r'|') + r')'
def snarfuri(phenny, input): def snarfuri(phenny, input):
if re.match(r'(?i)' + phenny.config.prefix + titlecommands, input.group()): if re.match(r'(?i)' + phenny.config.prefix + titlecommands, input.group()):
return return
uri = input.group(1).encode('utf-8') uri = input.group(1)
title = gettitle(uri) title = gettitle(uri)
if title: if title:
phenny.msg(input.sender, '[ ' + title + ' ]') phenny.msg(input.sender, '[ ' + title + ' ]')
@ -137,7 +137,7 @@ def gettitle(uri):
status = str(info[1]) status = str(info[1])
info = info[0] info = info[0]
if status.startswith('3'): if status.startswith('3'):
uri = urlparse.urljoin(uri, info['Location']) uri = urllib.parse.urljoin(uri, info['Location'])
else: break else: break
redirects += 1 redirects += 1
@ -173,20 +173,20 @@ def gettitle(uri):
entity = m.group(0) entity = m.group(0)
if entity.startswith('&#x'): if entity.startswith('&#x'):
cp = int(entity[3:-1], 16) cp = int(entity[3:-1], 16)
return unichr(cp).encode('utf-8') return chr(cp)
elif entity.startswith('&#'): elif entity.startswith('&#'):
cp = int(entity[2:-1]) cp = int(entity[2:-1])
return unichr(cp).encode('utf-8') return chr(cp)
else: else:
char = name2codepoint[entity[1:-1]] char = name2codepoint[entity[1:-1]]
return unichr(char).encode('utf-8') return chr(char)
title = r_entity.sub(e, title) title = r_entity.sub(e, title)
if title: if title:
try: title.decode('utf-8') try: title.decode('utf-8')
except: except:
try: title = title.decode('iso-8859-1').encode('utf-8') try: title = title.decode('iso-8859-1')
except: title = title.decode('cp1252').encode('utf-8') except: title = title.decode('cp1252')
else: pass else: pass
title = title.replace('\n', '') title = title.replace('\n', '')
title = title.replace('\r', '') title = title.replace('\r', '')
@ -194,4 +194,4 @@ def gettitle(uri):
return title return title
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -5,7 +5,7 @@ author: mutantmonkey <mutantmonkey@mutantmonkey.in>
""" """
import ldap import ldap
from urllib import quote as urlquote from urllib.parse import quote as urlquote
LDAP_URI = "ldap://directory.vt.edu" LDAP_URI = "ldap://directory.vt.edu"
RESULTS_URL = "http://search.vt.edu/search/people.html?q={0}" RESULTS_URL = "http://search.vt.edu/search/people.html?q={0}"
@ -56,5 +56,5 @@ def hs(phenny, input):
hs.rule = (['hs'], r'(.*)') hs.rule = (['hs'], r'(.*)')
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -12,7 +12,7 @@ def doc(phenny, input):
name = input.group(1) name = input.group(1)
name = name.lower() name = name.lower()
if phenny.doc.has_key(name): if name in phenny.doc:
phenny.reply(phenny.doc[name][0]) phenny.reply(phenny.doc[name][0])
if phenny.doc[name][1]: if phenny.doc[name][1]:
phenny.say('e.g. ' + phenny.doc[name][1]) phenny.say('e.g. ' + phenny.doc[name][1])
@ -23,7 +23,7 @@ doc.priority = 'low'
def commands(phenny, input): def commands(phenny, input):
# This function only works in private message # This function only works in private message
if input.sender.startswith('#'): return if input.sender.startswith('#'): return
names = ', '.join(sorted(phenny.doc.iterkeys())) names = ', '.join(sorted(phenny.doc.keys()))
phenny.say('Commands I recognise: ' + names + '.') phenny.say('Commands I recognise: ' + names + '.')
phenny.say(("For help, do '%s: help example?' where example is the " + phenny.say(("For help, do '%s: help example?' where example is the " +
"name of the command you want help for.") % phenny.nick) "name of the command you want help for.") % phenny.nick)
@ -49,7 +49,7 @@ def stats(phenny, input):
channels = {} channels = {}
ignore = set(['f_note', 'startup', 'message', 'noteuri']) ignore = set(['f_note', 'startup', 'message', 'noteuri'])
for (name, user), count in phenny.stats.items(): for (name, user), count in list(phenny.stats.items()):
if name in ignore: continue if name in ignore: continue
if not user: continue if not user: continue
@ -63,9 +63,9 @@ def stats(phenny, input):
try: channels[user] += count try: channels[user] += count
except KeyError: channels[user] = count except KeyError: channels[user] = count
comrank = sorted([(b, a) for (a, b) in commands.iteritems()], reverse=True) comrank = sorted([(b, a) for (a, b) in commands.items()], reverse=True)
userank = sorted([(b, a) for (a, b) in users.iteritems()], reverse=True) userank = sorted([(b, a) for (a, b) in users.items()], reverse=True)
charank = sorted([(b, a) for (a, b) in channels.iteritems()], reverse=True) charank = sorted([(b, a) for (a, b) in channels.items()], reverse=True)
# most heavily used commands # most heavily used commands
creply = 'most used commands: ' creply = 'most used commands: '
@ -88,4 +88,4 @@ stats.commands = ['stats']
stats.priority = 'low' stats.priority = 'low'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -7,9 +7,10 @@ author: Casey Link <unnamedrambler@gmail.com>
import random import random
import ConfigParser, os import configparser, os
from urllib import quote as urlquote from urllib.parse import quote as urlquote
from urllib2 import urlopen, HTTPError from urllib.request import urlopen
from urllib.error import HTTPError
from lxml import etree from lxml import etree
from datetime import datetime from datetime import datetime
@ -17,7 +18,7 @@ APIKEY = "b25b959554ed76058ac220b7b2e0a026"
APIURL = "http://ws.audioscrobbler.com/2.0/?api_key="+APIKEY+"&" APIURL = "http://ws.audioscrobbler.com/2.0/?api_key="+APIKEY+"&"
AEPURL = "http://www.davethemoonman.com/lastfm/aep.php?format=txt&username=" AEPURL = "http://www.davethemoonman.com/lastfm/aep.php?format=txt&username="
config = ConfigParser.RawConfigParser() config = configparser.RawConfigParser()
config.optionxform = str config.optionxform = str
config_filename = "" config_filename = ""
@ -84,7 +85,7 @@ def now_playing(phenny, input):
user = user.strip() user = user.strip()
try: try:
req = urlopen("%smethod=user.getrecenttracks&user=%s" % (APIURL, urlquote(user))) req = urlopen("%smethod=user.getrecenttracks&user=%s" % (APIURL, urlquote(user)))
except HTTPError, e: except HTTPError as e:
if e.code == 400: if e.code == 400:
phenny.say("%s doesn't exist on last.fm, perhaps they need to set user" % (user)) phenny.say("%s doesn't exist on last.fm, perhaps they need to set user" % (user))
return return
@ -151,7 +152,7 @@ def aep(phenny, input):
user = user.strip() user = user.strip()
try: try:
req = urlopen("%s%s" % (AEPURL, urlquote(user))) req = urlopen("%s%s" % (AEPURL, urlquote(user)))
except HTTPError, e: except HTTPError as e:
phenny.say("uhoh. try again later, mmkay?") phenny.say("uhoh. try again later, mmkay?")
return return
result = req.read() result = req.read()
@ -182,7 +183,7 @@ def tasteometer(phenny, input):
user2 = input.nick user2 = input.nick
try: try:
req = urlopen("%smethod=tasteometer.compare&type1=user&type2=user&value1=%s&value2=%s" % (APIURL, urlquote(user1), urlquote(user2))) req = urlopen("%smethod=tasteometer.compare&type1=user&type2=user&value1=%s&value2=%s" % (APIURL, urlquote(user1), urlquote(user2)))
except HTTPError, e: except HTTPError as e:
if e.code == 400: if e.code == 400:
phenny.say("uhoh, someone doesn't exist on last.fm, perhaps they need to set user") phenny.say("uhoh, someone doesn't exist on last.fm, perhaps they need to set user")
return return
@ -217,7 +218,7 @@ def tasteometer(phenny, input):
if len(artists) == 0: if len(artists) == 0:
common_artists = ". they don't have any artists in common." common_artists = ". they don't have any artists in common."
else: else:
map(lambda a: names.append(a.text) ,artists) list(map(lambda a: names.append(a.text) ,artists))
common_artists = "and music they have in common includes: %s" % ", ".join(names) common_artists = "and music they have in common includes: %s" % ", ".join(names)
phenny.say("%s's and %s's musical compatibility rating is %s %s" % (user1, user2, rating, common_artists)) phenny.say("%s's and %s's musical compatibility rating is %s %s" % (user1, user2, rating, common_artists))
@ -294,4 +295,4 @@ def pretty_date(time=False):
return str(day_diff/365) + " years ago" return str(day_diff/365) + " years ago"
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -7,8 +7,7 @@ author: mutantmonkey <mutantmonkey@mutantmonkey.in>
import random import random
from urllib import quote as urlquote from urllib.error import HTTPError
from urllib2 import HTTPError
import web import web
import lxml.html import lxml.html
@ -16,7 +15,7 @@ def fml(phenny, input):
""".fml""" """.fml"""
try: try:
req = web.get("http://www.fmylife.com/random") req = web.get("http://www.fmylife.com/random")
except HTTPError, IOError: except (HTTPError, IOError):
phenny.say("I tried to use .fml, but it was broken. FML") phenny.say("I tried to use .fml, but it was broken. FML")
return return
@ -29,7 +28,7 @@ def mlia(phenny, input):
""".mlia - My life is average.""" """.mlia - My life is average."""
try: try:
req = web.get("http://mylifeisaverage.com/") req = web.get("http://mylifeisaverage.com/")
except HTTPError, IOError: except (HTTPError, IOError):
phenny.say("I tried to use .mlia, but it wasn't loading. MLIA") phenny.say("I tried to use .mlia, but it wasn't loading. MLIA")
return return
@ -43,7 +42,7 @@ def mliarab(phenny, input):
""".mliarab - My life is Arabic.""" """.mliarab - My life is Arabic."""
try: try:
req = web.get("http://mylifeisarabic.com/random/") req = web.get("http://mylifeisarabic.com/random/")
except HTTPError, IOError: except (HTTPError, IOError):
phenny.say("The site you requested, mylifeisarabic.com, has been banned \ phenny.say("The site you requested, mylifeisarabic.com, has been banned \
in the UAE. You will be reported to appropriate authorities") in the UAE. You will be reported to appropriate authorities")
return return
@ -59,7 +58,7 @@ def mlib(phenny, input):
""".mlib - My life is bro.""" """.mlib - My life is bro."""
try: try:
req = web.get("http://mylifeisbro.com/random") req = web.get("http://mylifeisbro.com/random")
except HTTPError, IOError: except (HTTPError, IOError):
phenny.say("MLIB is out getting a case of Natty. It's chill.") phenny.say("MLIB is out getting a case of Natty. It's chill.")
return return
@ -72,7 +71,7 @@ def mlic(phenny, input):
""".mlic - My life is creepy.""" """.mlic - My life is creepy."""
try: try:
req = web.get("http://mylifeiscreepy.com/random") req = web.get("http://mylifeiscreepy.com/random")
except HTTPError, IOError: except (HTTPError, IOError):
phenny.say("Error: Have you checked behind you?") phenny.say("Error: Have you checked behind you?")
return return
@ -86,7 +85,7 @@ def mlid(phenny, input):
""".mlib - My life is Desi.""" """.mlib - My life is Desi."""
try: try:
req = web.get("http://www.mylifeisdesi.com/random") req = web.get("http://www.mylifeisdesi.com/random")
except HTTPError, IOError: except (HTTPError, IOError):
phenny.say("MLID is busy at the hookah lounge, be back soon.") phenny.say("MLID is busy at the hookah lounge, be back soon.")
return return
@ -99,7 +98,7 @@ def mlig(phenny, input):
""".mlig - My life is ginger.""" """.mlig - My life is ginger."""
try: try:
req = web.get("http://www.mylifeisginger.org/random") req = web.get("http://www.mylifeisginger.org/random")
except HTTPError, IOError: except (HTTPError, IOError):
phenny.say("Busy eating your soul. Be back soon.") phenny.say("Busy eating your soul. Be back soon.")
return return
@ -112,7 +111,7 @@ def mlih(phenny, input):
""".mlih - My life is ho.""" """.mlih - My life is ho."""
try: try:
req = web.get("http://mylifeisho.com/random") req = web.get("http://mylifeisho.com/random")
except HTTPError, IOError: except (HTTPError, IOError):
phenny.say("MLIH is giving some dome to some lax bros.") phenny.say("MLIH is giving some dome to some lax bros.")
return return
@ -125,7 +124,7 @@ def mlihp(phenny, input):
""".mlihp - My life is Harry Potter.""" """.mlihp - My life is Harry Potter."""
try: try:
req = web.get("http://www.mylifeishp.com/random") req = web.get("http://www.mylifeishp.com/random")
except HTTPError, IOError: except (HTTPError, IOError):
phenny.say("This service is not available to Muggles.") phenny.say("This service is not available to Muggles.")
return return
@ -138,7 +137,7 @@ def mlit(phenny, input):
""".mlit - My life is Twilight.""" """.mlit - My life is Twilight."""
try: try:
req = web.get("http://mylifeistwilight.com/random") req = web.get("http://mylifeistwilight.com/random")
except HTTPError, IOError: except (HTTPError, IOError):
phenny.say("Error: Your life is too Twilight. Go outside.") phenny.say("Error: Your life is too Twilight. Go outside.")
return return
@ -148,5 +147,5 @@ def mlit(phenny, input):
mlit.commands = ['mlit'] mlit.commands = ['mlit']
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -14,5 +14,5 @@ def nsfw(phenny, input):
nsfw.rule = (['nsfw'], r'(.*)') nsfw.rule = (['nsfw'], r'(.*)')
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -7,7 +7,7 @@ Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/ http://inamidst.com/phenny/
""" """
import re, urllib import re, urllib.request, urllib.parse, urllib.error
import web import web
definitions = 'https://github.com/nslater/oblique/wiki' definitions = 'https://github.com/nslater/oblique/wiki'
@ -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.parse.quote(args, ''))
template = template.replace('${nick}', urllib.quote(input.nick, '')) template = template.replace('${nick}', urllib.parse.quote(input.nick, ''))
uri = template.replace('${sender}', urllib.quote(input.sender, '')) uri = template.replace('${sender}', urllib.parse.quote(input.sender, ''))
info = web.head(uri) info = web.head(uri)
if isinstance(info, list): if isinstance(info, list):
@ -80,7 +80,7 @@ def o(phenny, input):
msg = o.services.get(args, 'No such service!') msg = o.services.get(args, 'No such service!')
return phenny.reply(msg) return phenny.reply(msg)
if not o.services.has_key(command): if command not in o.services:
return phenny.reply('Service not found in %s' % o.serviceURI) return phenny.reply('Service not found in %s' % o.serviceURI)
if hasattr(phenny.config, 'external'): if hasattr(phenny.config, 'external'):
@ -102,7 +102,7 @@ def snippet(phenny, input):
if not o.services: if not o.services:
refresh(phenny) refresh(phenny)
search = urllib.quote(input.group(2).encode('utf-8')) search = urllib.parse.quote(input.group(2))
py = "BeautifulSoup.BeautifulSoup(re.sub('<.*?>|(?<= ) +', '', " + \ py = "BeautifulSoup.BeautifulSoup(re.sub('<.*?>|(?<= ) +', '', " + \
"''.join(chr(ord(c)) for c in " + \ "''.join(chr(ord(c)) for c in " + \
"eval(urllib.urlopen('http://ajax.googleapis.com/ajax/serv" + \ "eval(urllib.urlopen('http://ajax.googleapis.com/ajax/serv" + \
@ -114,4 +114,4 @@ def snippet(phenny, input):
snippet.commands = ['snippet'] snippet.commands = ['snippet']
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -20,4 +20,4 @@ interjection.priority = 'high'
interjection.thread = False interjection.thread = False
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -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 name not 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
@ -52,4 +52,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())

View File

@ -16,7 +16,7 @@ def filename(self):
def load_database(name): def load_database(name):
data = {} data = {}
if os.path.isfile(name): if os.path.isfile(name):
f = open(name, 'rb') f = open(name, 'r')
for line in f: for line in f:
unixtime, channel, nick, message = line.split('\t') unixtime, channel, nick, message = line.split('\t')
message = message.rstrip('\n') message = message.rstrip('\n')
@ -28,8 +28,8 @@ def load_database(name):
return data return data
def dump_database(name, data): def dump_database(name, data):
f = open(name, 'wb') f = open(name, 'w')
for unixtime, reminders in data.iteritems(): for unixtime, reminders in data.items():
for channel, nick, message in reminders: for channel, nick, message in reminders:
f.write('%s\t%s\t%s\t%s\n' % (unixtime, channel, nick, message)) f.write('%s\t%s\t%s\t%s\n' % (unixtime, channel, nick, message))
f.close() f.close()
@ -97,12 +97,12 @@ scaling = {
's': 1 's': 1
} }
periods = '|'.join(scaling.keys()) periods = '|'.join(list(scaling.keys()))
p_command = r'\.in ([0-9]+(?:\.[0-9]+)?)\s?((?:%s)\b)?:?\s?(.*)' % periods p_command = r'\.in ([0-9]+(?:\.[0-9]+)?)\s?((?:%s)\b)?:?\s?(.*)' % periods
r_command = re.compile(p_command) r_command = re.compile(p_command)
def remind(phenny, input): def remind(phenny, input):
m = r_command.match(input.bytes) m = r_command.match(input.bytes.decode('utf-8'))
if not m: if not m:
return phenny.reply("Sorry, didn't understand the input.") return phenny.reply("Sorry, didn't understand the input.")
length, scale, message = m.groups() length, scale, message = m.groups()
@ -133,4 +133,4 @@ def remind(phenny, input):
remind.commands = ['in'] remind.commands = ['in']
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -33,14 +33,14 @@ def google_search(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 print(results)
return False return False
def google_count(query): def google_count(query):
results = google_ajax(query) results = google_ajax(query)
if not results.has_key('responseData'): return '0' if 'responseData' not in results: return '0'
if not results['responseData'].has_key('cursor'): return '0' if 'cursor' not in results['responseData']: return '0'
if not results['responseData']['cursor'].has_key('estimatedResultCount'): if 'estimatedResultCount' not in results['responseData']['cursor']:
return '0' return '0'
return results['responseData']['cursor']['estimatedResultCount'] return results['responseData']['cursor']['estimatedResultCount']
@ -56,7 +56,6 @@ def g(phenny, 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')
uri = google_search(query) uri = google_search(query)
if uri: if uri:
phenny.reply(uri) phenny.reply(uri)
@ -74,7 +73,6 @@ def gc(phenny, input):
query = input.group(2) query = input.group(2)
if not query: if not query:
return phenny.reply('.gc what?') return phenny.reply('.gc what?')
query = query.encode('utf-8')
num = formatnumber(google_count(query)) num = formatnumber(google_count(query))
phenny.say(query + ': ' + num) phenny.say(query + ': ' + num)
gc.commands = ['gc'] gc.commands = ['gc']
@ -95,7 +93,6 @@ def gcs(phenny, input):
results = [] results = []
for i, query in enumerate(queries): for i, query in enumerate(queries):
query = query.strip('[]') query = query.strip('[]')
query = query.encode('utf-8')
n = int((formatnumber(google_count(query)) or '0').replace(',', '')) n = int((formatnumber(google_count(query)) or '0').replace(',', ''))
results.append((n, query)) results.append((n, query))
if i >= 2: __import__('time').sleep(0.25) if i >= 2: __import__('time').sleep(0.25)
@ -125,7 +122,6 @@ def bing(phenny, input):
if not query: if not query:
return phenny.reply('.bing what?') return phenny.reply('.bing what?')
query = query.encode('utf-8')
uri = bing_search(query, lang) uri = bing_search(query, lang)
if uri: if uri:
phenny.reply(uri) phenny.reply(uri)
@ -150,7 +146,6 @@ def duck(phenny, input):
query = input.group(2) query = input.group(2)
if not query: return phenny.reply('.ddg what?') if not query: return phenny.reply('.ddg what?')
query = query.encode('utf-8')
uri = duck_search(query) uri = duck_search(query)
if uri: if uri:
phenny.reply(uri) phenny.reply(uri)
@ -163,7 +158,7 @@ duck.commands = ['duck', 'ddg']
def search(phenny, input): def search(phenny, input):
if not input.group(2): if not input.group(2):
return phenny.reply('.search for what?') return phenny.reply('.search for what?')
query = input.group(2).encode('utf-8') query = input.group(2)
gu = google_search(query) or '-' gu = google_search(query) or '-'
bu = bing_search(query) or '-' bu = bing_search(query) or '-'
du = duck_search(query) or '-' du = duck_search(query) or '-'
@ -188,7 +183,7 @@ search.commands = ['search']
def suggest(phenny, input): def suggest(phenny, input):
if not input.group(2): if not input.group(2):
return phenny.reply("No query term.") return phenny.reply("No query term.")
query = input.group(2).encode('utf-8') query = input.group(2)
uri = 'http://websitedev.de/temp-bin/suggest.pl?q=' uri = 'http://websitedev.de/temp-bin/suggest.pl?q='
answer = web.get(uri + web.urllib.quote(query).replace('+', '%2B')) answer = web.get(uri + web.urllib.quote(query).replace('+', '%2B'))
if answer: if answer:
@ -197,4 +192,4 @@ def suggest(phenny, input):
suggest.commands = ['suggest'] suggest.commands = ['suggest']
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -17,7 +17,7 @@ def f_seen(self, origin, match, args):
nick = match.group(2).lower() nick = match.group(2).lower()
if not hasattr(self, 'seen'): if not hasattr(self, 'seen'):
return self.msg(origin.sender, '?') return self.msg(origin.sender, '?')
if self.seen.has_key(nick): if nick in self.seen:
channel, t = self.seen[nick] channel, t = self.seen[nick]
t = time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime(t)) t = time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime(t))
@ -41,9 +41,9 @@ def f_note(self, origin, match, args):
# self.chanspeak[args[2]] = args[0] # self.chanspeak[args[2]] = args[0]
try: note(self, origin, match, args) try: note(self, origin, match, args)
except Exception, e: print e except Exception as e: print(e)
f_note.rule = r'(.*)' f_note.rule = r'(.*)'
f_note.priority = 'low' f_note.priority = 'low'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -12,7 +12,7 @@ import web
uri = 'http://www.sloganizer.net/en/outbound.php?slogan=%s' uri = 'http://www.sloganizer.net/en/outbound.php?slogan=%s'
def sloganize(word): def sloganize(word):
bytes = web.get(uri % web.urllib.quote(word.encode('utf-8'))) bytes = web.get(uri % web.quote(word))
return bytes return bytes
def slogan(phenny, input): def slogan(phenny, input):
@ -37,4 +37,4 @@ slogan.commands = ['slogan']
slogan.example = '.slogan Granola' slogan.example = '.slogan Granola'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -23,4 +23,4 @@ startup.event = '251'
startup.priority = 'low' startup.priority = 'low'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -37,7 +37,7 @@ def loadReminders(fn):
def dumpReminders(fn, data): def dumpReminders(fn, data):
f = open(fn, 'w') f = open(fn, 'w')
for tellee in data.iterkeys(): for tellee in data.keys():
for remindon in data[tellee]: for remindon in data[tellee]:
line = '\t'.join((tellee,) + remindon) line = '\t'.join((tellee,) + remindon)
try: f.write(line + '\n') try: f.write(line + '\n')
@ -62,9 +62,9 @@ def f_remind(phenny, input):
# @@ Multiple comma-separated tellees? Cf. Terje, #swhack, 2006-04-15 # @@ Multiple comma-separated tellees? Cf. Terje, #swhack, 2006-04-15
verb, tellee, msg = input.groups() verb, tellee, msg = input.groups()
verb = verb.encode('utf-8') verb = verb
tellee = tellee.encode('utf-8') tellee = tellee
msg = msg.encode('utf-8') msg = msg
tellee_original = tellee.rstrip('.,:;') tellee_original = tellee.rstrip('.,:;')
tellee = tellee_original.lower() tellee = tellee_original.lower()
@ -79,7 +79,7 @@ def f_remind(phenny, input):
if not tellee in (teller.lower(), phenny.nick, 'me'): # @@ if not tellee in (teller.lower(), phenny.nick, 'me'): # @@
# @@ <deltab> and year, if necessary # @@ <deltab> and year, if necessary
warn = False warn = False
if not phenny.reminders.has_key(tellee): if tellee not in phenny.reminders:
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:
@ -144,14 +144,14 @@ def message(phenny, input):
for line in reminders[maximum:]: for line in reminders[maximum:]:
phenny.msg(tellee, line) phenny.msg(tellee, line)
if len(phenny.reminders.keys()) != remkeys: if len(list(phenny.reminders.keys())) != remkeys:
dumpReminders(phenny.tell_filename, phenny.reminders) # @@ tell dumpReminders(phenny.tell_filename, phenny.reminders) # @@ tell
message.rule = r'(.*)' message.rule = r'(.*)'
message.priority = 'low' message.priority = 'low'
message.thread = False message.thread = False
def messageAlert(phenny, input): def messageAlert(phenny, input):
if (input.nick.lower() in phenny.reminders.keys()): if (input.nick.lower() in list(phenny.reminders.keys())):
phenny.say(input.nick + ': You have messages.') phenny.say(input.nick + ': You have messages.')
messageAlert.event = 'JOIN' messageAlert.event = 'JOIN'
messageAlert.rule = r'.*' messageAlert.rule = r'.*'
@ -159,4 +159,4 @@ messageAlert.priority = 'low'
messageAlert.thread = False messageAlert.thread = False
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -4,8 +4,8 @@ tfw.py - the fucking weather module
author: mutantmonkey <mutantmonkey@gmail.com> author: mutantmonkey <mutantmonkey@gmail.com>
""" """
from urllib import quote as urlquote from urllib.parse import quote as urlquote
from urllib2 import HTTPError from urllib.error import HTTPError
import web import web
import lxml.html import lxml.html
@ -24,7 +24,7 @@ def tfw(phenny, input, fahrenheit=False, celsius=False):
try: try:
req = web.get("http://thefuckingweather.com/?zipcode=%s%s" % (urlquote(zipcode), celsius_param)) req = web.get("http://thefuckingweather.com/?zipcode=%s%s" % (urlquote(zipcode), celsius_param))
except HTTPError: except (HTTPError, IOError):
phenny.say("THE INTERNET IS FUCKING BROKEN. Please try again later.") phenny.say("THE INTERNET IS FUCKING BROKEN. Please try again later.")
return return
@ -46,7 +46,7 @@ def tfw(phenny, input, fahrenheit=False, celsius=False):
if c.isdigit(): if c.isdigit():
tempt += c tempt += c
temp = int(tempt) temp = int(tempt)
deg = unichr(176).encode('latin-1') deg = chr(176)
# add units and convert if necessary # add units and convert if necessary
if fahrenheit: if fahrenheit:
@ -82,5 +82,5 @@ def tfwc(phenny, input):
tfwc.rule = (['tfwc'], r'(.*)') tfwc.rule = (['tfwc'], r'(.*)')
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -8,12 +8,12 @@ Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/ http://inamidst.com/phenny/
""" """
import re, urllib import re, urllib.request, urllib.parse, urllib.error
import web import web
def detect(text): def detect(text):
uri = 'http://ajax.googleapis.com/ajax/services/language/detect' uri = 'http://ajax.googleapis.com/ajax/services/language/detect'
q = urllib.quote(text) q = urllib.parse.quote(text)
bytes = web.get(uri + '?q=' + q + '&v=1.0') bytes = web.get(uri + '?q=' + q + '&v=1.0')
result = web.json(bytes) result = web.json(bytes)
try: return result['responseData']['language'] try: return result['responseData']['language']
@ -21,7 +21,7 @@ def detect(text):
def translate(text, input, output): def translate(text, input, output):
uri = 'http://ajax.googleapis.com/ajax/services/language/translate' uri = 'http://ajax.googleapis.com/ajax/services/language/translate'
q = urllib.quote(text) q = urllib.parse.quote(text)
pair = input + '%7C' + output pair = input + '%7C' + output
bytes = web.get(uri + '?q=' + q + '&v=1.0&langpair=' + pair) bytes = web.get(uri + '?q=' + q + '&v=1.0&langpair=' + pair)
result = web.json(bytes) result = web.json(bytes)
@ -32,7 +32,7 @@ def tr(phenny, context):
"""Translates a phrase, with an optional language hint.""" """Translates a phrase, with an optional language hint."""
input, output, phrase = context.groups() input, output, phrase = context.groups()
phrase = phrase.encode('utf-8') phrase = phrase
if (len(phrase) > 350) and (not context.admin): if (len(phrase) > 350) and (not context.admin):
return phenny.reply('Phrase must be under 350 characters.') return phenny.reply('Phrase must be under 350 characters.')
@ -41,8 +41,7 @@ def tr(phenny, context):
if not input: if not input:
err = 'Unable to guess your crazy moon language, sorry.' err = 'Unable to guess your crazy moon language, sorry.'
return phenny.reply(err) return phenny.reply(err)
input = input.encode('utf-8') output = (output or 'en')
output = (output or 'en').encode('utf-8')
if input != output: if input != output:
msg = translate(phrase, input, output) msg = translate(phrase, input, output)
@ -56,12 +55,12 @@ def tr(phenny, context):
phenny.reply(msg) phenny.reply(msg)
else: phenny.reply('Language guessing failed, so try suggesting one!') else: phenny.reply('Language guessing failed, so try suggesting one!')
tr.rule = ('$nick', ur'(?:([a-z]{2}) +)?(?:([a-z]{2}) +)?["“](.+?)["”]\? *$') tr.rule = ('$nick', r'(?:([a-z]{2}) +)?(?:([a-z]{2}) +)?["“](.+?)["”]\? *$')
tr.example = '$nickname: "mon chien"? or $nickname: fr "mon chien"?' tr.example = '$nickname: "mon chien"? or $nickname: fr "mon chien"?'
tr.priority = 'low' tr.priority = 'low'
def mangle(phenny, input): def mangle(phenny, input):
phrase = input.group(2).encode('utf-8') phrase = input.group(2)
for lang in ['fr', 'de', 'es', 'it', 'ja']: for lang in ['fr', 'de', 'es', 'it', 'ja']:
backup = phrase backup = phrase
phrase = translate(phrase, 'en', lang) phrase = translate(phrase, 'en', lang)
@ -81,4 +80,4 @@ def mangle(phenny, input):
mangle.commands = ['mangle'] mangle.commands = ['mangle']
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -10,7 +10,7 @@ modified from Wikipedia module
author: mutantmonkey <mutantmonkey@gmail.com> author: mutantmonkey <mutantmonkey@gmail.com>
""" """
import re, urllib import re, urllib.request, urllib.parse, urllib.error
import web import web
wikiuri = 'http://uncyclopedia.wikia.com/wiki/%s' wikiuri = 'http://uncyclopedia.wikia.com/wiki/%s'
@ -46,14 +46,13 @@ def text(html):
return unescape(html).strip() return unescape(html).strip()
def search(term): def search(term):
try: import search try: from . import search
except ImportError, e: except ImportError as e:
print e print(e)
return term return term
if isinstance(term, unicode): if not isinstance(term, str):
term = term.encode('utf-8') term = term.decode('utf-8')
else: term = term.decode('utf-8')
term = term.replace('_', ' ') term = term.replace('_', ' ')
try: uri = search.result('site:uncyclopedia.wikia.com %s' % term) try: uri = search.result('site:uncyclopedia.wikia.com %s' % term)
@ -65,10 +64,10 @@ def search(term):
def uncyclopedia(term, last=False): def uncyclopedia(term, last=False):
global wikiuri global wikiuri
if not '%' in term: if not '%' in term:
if isinstance(term, unicode): if isinstance(term, str):
t = term.encode('utf-8') t = term
else: t = term else: t = term
q = urllib.quote(t) q = urllib.parse.quote(t)
u = wikiuri % q u = wikiuri % q
bytes = web.get(u) bytes = web.get(u)
else: bytes = web.get(wikiuri % term) else: bytes = web.get(wikiuri % term)
@ -77,7 +76,7 @@ def uncyclopedia(term, last=False):
if not last: if not last:
r = r_redirect.search(bytes[:4096]) r = r_redirect.search(bytes[:4096])
if r: if r:
term = urllib.unquote(r.group(1)) term = urllib.parse.unquote(r.group(1))
return uncyclopedia(term, last=True) return uncyclopedia(term, last=True)
paragraphs = r_paragraph.findall(bytes) paragraphs = r_paragraph.findall(bytes)
@ -138,18 +137,15 @@ def uncyclopedia(term, last=False):
return None return None
sentence = '"' + sentence.replace('"', "'") + '"' 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) return sentence + ' - ' + (wikiuri % term)
def uncyc(phenny, input): def uncyc(phenny, input):
origterm = input.groups()[1] origterm = input.groups()[1]
if not origterm: if not origterm:
return phenny.say('Perhaps you meant ".uncyc Zen"?') return phenny.say('Perhaps you meant ".uncyc Zen"?')
origterm = origterm.encode('utf-8') origterm = origterm
term = urllib.unquote(origterm) term = urllib.parse.unquote(origterm)
term = term[0].upper() + term[1:] term = term[0].upper() + term[1:]
term = term.replace(' ', '_') term = term.replace(' ', '_')
@ -166,4 +162,4 @@ uncyc.commands = ['uncyc']
uncyc.priority = 'high' uncyc.priority = 'high'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -25,10 +25,10 @@ def val(phenny, input):
if isinstance(info, list): if isinstance(info, list):
return phenny.say('Got HTTP response %s' % info[1]) return phenny.say('Got HTTP response %s' % info[1])
if info.has_key('X-W3C-Validator-Status'): if 'X-W3C-Validator-Status' in info:
result += str(info['X-W3C-Validator-Status']) result += str(info['X-W3C-Validator-Status'])
if info['X-W3C-Validator-Status'] != 'Valid': if info['X-W3C-Validator-Status'] != 'Valid':
if info.has_key('X-W3C-Validator-Errors'): if 'X-W3C-Validator-Errors' in info:
n = int(info['X-W3C-Validator-Errors'].split(' ')[0]) n = int(info['X-W3C-Validator-Errors'].split(' ')[0])
if n != 1: if n != 1:
result += ' (%s errors)' % n result += ' (%s errors)' % n
@ -40,4 +40,4 @@ val.rule = (['val'], r'(?i)(\S+)')
val.example = '.val http://www.w3.org/' val.example = '.val http://www.w3.org/'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -10,7 +10,7 @@ modified from Wikipedia module
author: mutantmonkey <mutantmonkey@gmail.com> author: mutantmonkey <mutantmonkey@gmail.com>
""" """
import re, urllib import re, urllib.request, urllib.parse, urllib.error
import web import web
import json import json
@ -64,9 +64,9 @@ def vtluug(phenny, input):
origterm = input.groups()[1] origterm = input.groups()[1]
if not origterm: if not origterm:
return phenny.say('Perhaps you meant ".vtluug Zen"?') return phenny.say('Perhaps you meant ".vtluug Zen"?')
origterm = origterm.encode('utf-8') origterm = origterm
term = urllib.unquote(origterm) term = urllib.parse.unquote(origterm)
term = term[0].upper() + term[1:] term = term[0].upper() + term[1:]
term = term.replace(' ', '_') term = term.replace(' ', '_')
@ -83,4 +83,4 @@ vtluug.commands = ['vtluug']
vtluug.priority = 'high' vtluug.priority = 'high'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -8,9 +8,10 @@ author: Casey Link <unnamedrambler@gmail.com>
import random import random
import ConfigParser, os import configparser, os
from urllib import quote as urlquote from urllib.parse import quote as urlquote
from urllib2 import urlopen, HTTPError from urllib.request import urlopen
from urllib.error import HTTPError
from lxml import etree from lxml import etree
from lxml import objectify from lxml import objectify
from datetime import datetime from datetime import datetime
@ -25,7 +26,7 @@ class server(object):
self.players = [] self.players = []
def __str__(self): def __str__(self):
s = "%s - %d players: " %(self.name, len(self.players)) s = "%s - %d players: " %(self.name, len(self.players))
s += ", ".join(map(lambda p: str(p), self.players)) s += ", ".join([str(p) for p in self.players])
return s return s
class player(object): class player(object):
@ -79,7 +80,7 @@ def wargame(phenny, input):
return return
try: try:
req = urlopen(APIURL) req = urlopen(APIURL)
except HTTPError, e: except HTTPError as e:
phenny.say("uhoh. try again later, mmkay?") phenny.say("uhoh. try again later, mmkay?")
return return
root = objectify.parse(req).getroot() root = objectify.parse(req).getroot()
@ -90,11 +91,11 @@ def wargame(phenny, input):
for server_e in root.servers.server: for server_e in root.servers.server:
servers.append( parse_server( server_e ) ) servers.append( parse_server( server_e ) )
phenny.say( "wargame network is %s. last updated %s. available targets: %s" % ( "ONLINE" if online else "OFFLINE", updated, ", ".join(map(lambda s: s.name, servers))) ) phenny.say( "wargame network is %s. last updated %s. available targets: %s" % ( "ONLINE" if online else "OFFLINE", updated, ", ".join([s.name for s in servers])) )
def wargame_scores(phenny, s_name): def wargame_scores(phenny, s_name):
try: try:
req = urlopen(APIURL) req = urlopen(APIURL)
except HTTPError, e: except HTTPError as e:
phenny.say("uhoh. try again later, mmkay?") phenny.say("uhoh. try again later, mmkay?")
return return
root = objectify.parse(req).getroot() root = objectify.parse(req).getroot()

View File

@ -7,16 +7,16 @@ Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/ http://inamidst.com/phenny/
""" """
import re, urllib import re, urllib.request, urllib.parse, urllib.error
import web import web
from tools import deprecated from tools import deprecated
r_from = re.compile(r'(?i)([+-]\d+):00 from') r_from = re.compile(r'(?i)([+-]\d+):00 from')
def location(name): def location(name):
name = urllib.quote(name.encode('utf-8')) name = urllib.parse.quote(name)
uri = 'http://ws.geonames.org/searchJSON?q=%s&maxRows=1' % name uri = 'http://ws.geonames.org/searchJSON?q=%s&maxRows=1' % name
for i in xrange(10): for i in range(10):
bytes = web.get(uri) bytes = web.get(uri)
if bytes is not None: break if bytes is not None: break
@ -220,25 +220,25 @@ def f_weather(self, origin, match, args):
description = 'Violent storm' description = 'Violent storm'
else: description = 'Hurricane' else: description = 'Hurricane'
degrees = wind[0:3] degrees = float(wind[0:3]
if degrees == 'VRB': if degrees == 'VRB':
degrees = u'\u21BB'.encode('utf-8') degrees = '\u21BB'
elif (degrees <= 22.5) or (degrees > 337.5): elif (degrees <= 22.5) or (degrees > 337.5):
degrees = u'\u2191'.encode('utf-8') degrees = '\u2191'
elif (degrees > 22.5) and (degrees <= 67.5): elif (degrees > 22.5) and (degrees <= 67.5):
degrees = u'\u2197'.encode('utf-8') degrees = '\u2197'
elif (degrees > 67.5) and (degrees <= 112.5): elif (degrees > 67.5) and (degrees <= 112.5):
degrees = u'\u2192'.encode('utf-8') degrees = '\u2192'
elif (degrees > 112.5) and (degrees <= 157.5): elif (degrees > 112.5) and (degrees <= 157.5):
degrees = u'\u2198'.encode('utf-8') degrees = '\u2198'
elif (degrees > 157.5) and (degrees <= 202.5): elif (degrees > 157.5) and (degrees <= 202.5):
degrees = u'\u2193'.encode('utf-8') degrees = '\u2193'
elif (degrees > 202.5) and (degrees <= 247.5): elif (degrees > 202.5) and (degrees <= 247.5):
degrees = u'\u2199'.encode('utf-8') degrees = '\u2199'
elif (degrees > 247.5) and (degrees <= 292.5): elif (degrees > 247.5) and (degrees <= 292.5):
degrees = u'\u2190'.encode('utf-8') degrees = '\u2190'
elif (degrees > 292.5) and (degrees <= 337.5): elif (degrees > 292.5) and (degrees <= 337.5):
degrees = u'\u2196'.encode('utf-8') degrees = '\u2196'
if not icao_code.startswith('EN') and not icao_code.startswith('ED'): if not icao_code.startswith('EN') and not icao_code.startswith('ED'):
wind = '%s %skt (%s)' % (description, speed, degrees) wind = '%s %skt (%s)' % (description, speed, degrees)
@ -274,13 +274,13 @@ def f_weather(self, origin, match, args):
level = 0 level = 0
if level == 8: if level == 8:
cover = u'Overcast \u2601'.encode('utf-8') cover = 'Overcast \u2601'
elif level == 5: elif level == 5:
cover = 'Cloudy' cover = 'Cloudy'
elif level == 3: elif level == 3:
cover = 'Scattered' cover = 'Scattered'
elif (level == 1) or (level == 0): elif (level == 1) or (level == 0):
cover = u'Clear \u263C'.encode('utf-8') cover = 'Clear \u263C'
else: cover = 'Cover Unknown' else: cover = 'Cover Unknown'
else: cover = 'Cover Unknown' else: cover = 'Cover Unknown'
@ -310,10 +310,10 @@ def f_weather(self, origin, match, args):
if isinstance(temp, int): if isinstance(temp, int):
f = round((temp * 1.8) + 32, 2) f = round((temp * 1.8) + 32, 2)
temp = u'%s\u2109 (%s\u2103)'.encode('utf-8') % (f, temp) temp = '%s\u2109 (%s\u2103)' % (f, temp)
else: pressure = '?mb' else: pressure = '?mb'
if isinstance(temp, int): if isinstance(temp, int):
temp = u'%s\u2103'.encode('utf-8') % temp temp = '%s\u2103' % temp
if cond: if cond:
conds = cond conds = cond
@ -397,14 +397,14 @@ def f_weather(self, origin, match, args):
# args = (icao, time, cover, temp, pressure, cond, wind) # args = (icao, time, cover, temp, pressure, cond, wind)
if not cond: if not cond:
format = u'%s, %s, %s, %s - %s %s' format = '%s, %s, %s, %s - %s %s'
args = (cover, temp, pressure, wind, str(icao_code), time) args = (cover, temp, pressure, wind, str(icao_code), time)
else: else:
format = u'%s, %s, %s, %s, %s - %s, %s' format = '%s, %s, %s, %s, %s - %s, %s'
args = (cover, temp, pressure, cond, wind, str(icao_code), time) args = (cover, temp, pressure, cond, wind, str(icao_code), time)
self.msg(origin.sender, format.encode('utf-8') % args) self.msg(origin.sender, format % args)
f_weather.rule = (['weather'], r'(.*)') f_weather.rule = (['weather'], r'(.*)')
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -7,7 +7,7 @@ Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/ http://inamidst.com/phenny/
""" """
import re, urllib, gzip, StringIO import re, urllib.request, urllib.parse, urllib.error, gzip, io
import web import web
import json import json
@ -61,9 +61,9 @@ def wik(phenny, input):
origterm = input.groups()[1] origterm = input.groups()[1]
if not origterm: if not origterm:
return phenny.say('Perhaps you meant ".wik Zen"?') return phenny.say('Perhaps you meant ".wik Zen"?')
origterm = origterm.encode('utf-8') origterm = origterm
term = urllib.unquote(origterm) term = urllib.parse.unquote(origterm)
term = term[0].upper() + term[1:] term = term[0].upper() + term[1:]
term = term.replace(' ', '_') term = term.replace(' ', '_')
@ -80,4 +80,4 @@ wik.commands = ['wik']
wik.priority = 'high' wik.priority = 'high'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -23,7 +23,7 @@ def text(html):
return text return text
def wiktionary(word): def wiktionary(word):
bytes = web.get(uri % web.urllib.quote(word.encode('utf-8'))) bytes = web.get(uri % web.urllib.quote(word))
bytes = r_ul.sub('', bytes) bytes = r_ul.sub('', bytes)
mode = None mode = None
@ -62,11 +62,11 @@ parts = ('preposition', 'particle', 'noun', 'verb',
'adjective', 'adverb', 'interjection') 'adjective', 'adverb', 'interjection')
def format(word, definitions, number=2): def format(word, definitions, number=2):
result = '%s' % word.encode('utf-8') result = '%s' % word
for part in parts: for part in parts:
if definitions.has_key(part): if part in definitions:
defs = definitions[part][:number] defs = definitions[part][:number]
result += u' \u2014 '.encode('utf-8') + ('%s: ' % part) result += ' \u2014 ' + ('%s: ' % part)
n = ['%s. %s' % (i + 1, e.strip(' .')) for i, e in enumerate(defs)] n = ['%s. %s' % (i + 1, e.strip(' .')) for i, e in enumerate(defs)]
result += ', '.join(n) result += ', '.join(n)
return result.strip(' .,') return result.strip(' .,')
@ -97,4 +97,4 @@ def encarta(phenny, input):
encarta.commands = ['dict'] encarta.commands = ['dict']
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

View File

@ -35,4 +35,4 @@ replaced.commands = [
replaced.priority = 'low' replaced.priority = 'low'
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

30
phenny
View File

@ -19,12 +19,12 @@ dotdir = os.path.expanduser('~/.phenny')
def check_python_version(): def check_python_version():
if sys.version_info < (2, 4): if sys.version_info < (2, 4):
error = 'Error: Requires Python 2.4 or later, from www.python.org' error = 'Error: Requires Python 2.4 or later, from www.python.org'
print >> sys.stderr, error print(error, file=sys.stderr)
sys.exit(1) sys.exit(1)
def create_default_config(fn): def create_default_config(fn):
f = open(fn, 'w') f = open(fn, 'w')
print >> f, trim("""\ print(trim("""\
nick = 'phenny' nick = 'phenny'
host = 'irc.example.net' host = 'irc.example.net'
port = 6667 port = 6667
@ -61,23 +61,23 @@ def create_default_config(fn):
} }
# EOF # EOF
""") """), file=f)
f.close() f.close()
def create_dotdir(dotdir): def create_dotdir(dotdir):
print 'Creating a config directory at ~/.phenny...' print('Creating a config directory at ~/.phenny...')
try: os.mkdir(dotdir) try: os.mkdir(dotdir)
except Exception, e: except Exception as e:
print >> sys.stderr, 'There was a problem creating %s:' % dotdir print('There was a problem creating %s:' % dotdir, file=sys.stderr)
print >> sys.stderr, e.__class__, str(e) print(e.__class__, str(e), file=sys.stderr)
print >> sys.stderr, 'Please fix this and then run phenny again.' print('Please fix this and then run phenny again.', file=sys.stderr)
sys.exit(1) sys.exit(1)
print 'Creating a default config file at ~/.phenny/default.py...' print('Creating a default config file at ~/.phenny/default.py...')
default = os.path.join(dotdir, 'default.py') default = os.path.join(dotdir, 'default.py')
create_default_config(default) create_default_config(default)
print 'Done; now you can edit default.py, and run phenny! Enjoy.' print('Done; now you can edit default.py, and run phenny! Enjoy.')
sys.exit(0) sys.exit(0)
def check_dotdir(): def check_dotdir():
@ -107,8 +107,8 @@ def config_names(config):
if os.path.isdir(there): if os.path.isdir(there):
return files(there) return files(there)
print >> sys.stderr, "Error: Couldn't find a config file!" print("Error: Couldn't find a config file!", file=sys.stderr)
print >> sys.stderr, 'What happened to ~/.phenny/default.py?' print('What happened to ~/.phenny/default.py?', file=sys.stderr)
sys.exit(1) sys.exit(1)
def main(argv=None): def main(argv=None):
@ -118,7 +118,7 @@ def main(argv=None):
parser.add_option('-c', '--config', metavar='fn', parser.add_option('-c', '--config', metavar='fn',
help='use this configuration file or directory') help='use this configuration file or directory')
opts, args = parser.parse_args(argv) opts, args = parser.parse_args(argv)
if args: print >> sys.stderr, 'Warning: ignoring spurious arguments' if args: print('Warning: ignoring spurious arguments', file=sys.stderr)
# Step Two: Check Dependencies # Step Two: Check Dependencies
@ -154,7 +154,7 @@ def main(argv=None):
if module.host == 'irc.example.net': if module.host == 'irc.example.net':
error = ('Error: you must edit the config file first!\n' + error = ('Error: you must edit the config file first!\n' +
"You're currently using %s" % module.filename) "You're currently using %s" % module.filename)
print >> sys.stderr, error print(error, file=sys.stderr)
sys.exit(1) sys.exit(1)
config_modules.append(module) config_modules.append(module)
@ -165,7 +165,7 @@ def main(argv=None):
except ImportError: except ImportError:
try: from phenny import run try: from phenny import run
except ImportError: except ImportError:
print >> sys.stderr, "Error: Couldn't find phenny to import" print("Error: Couldn't find phenny to import", file=sys.stderr)
sys.exit(1) sys.exit(1)
# Step Five: Initialise And Run The Phennies # Step Five: Initialise And Run The Phennies

View File

@ -23,4 +23,4 @@ def deprecated(old):
return new return new
if __name__ == '__main__': if __name__ == '__main__':
print __doc__.strip() print(__doc__.strip())

87
web.py
View File

@ -5,67 +5,68 @@ Author: Sean B. Palmer, inamidst.com
About: http://inamidst.com/phenny/ About: http://inamidst.com/phenny/
""" """
import re, urllib import re, urllib.request, urllib.parse, urllib.error
from htmlentitydefs import name2codepoint from html.entities import name2codepoint
import json as jsonlib
class Grab(urllib.URLopener): class Grab(urllib.request.URLopener):
def __init__(self, *args): def __init__(self, *args):
self.version = 'Mozilla/5.0 (Phenny)' self.version = 'Mozilla/5.0 (Phenny)'
urllib.URLopener.__init__(self, *args) urllib.request.URLopener.__init__(self, *args)
def http_error_default(self, url, fp, errcode, errmsg, headers): def http_error_default(self, url, fp, errcode, errmsg, headers):
return urllib.addinfourl(fp, [headers, errcode], "http:" + url) return urllib.addinfourl(fp, [headers, errcode], "http:" + url)
urllib._urlopener = Grab() urllib.request._urlopener = Grab()
def get(uri): def get(uri):
if not uri.startswith('http'): if not uri.startswith('http'):
return return
u = urllib.urlopen(uri) u = urllib.request.urlopen(uri)
bytes = u.read() bytes = u.read().decode('utf-8')
u.close() u.close()
return bytes return bytes
def head(uri): def head(uri):
if not uri.startswith('http'): if not uri.startswith('http'):
return return
u = urllib.urlopen(uri) u = urllib.request.urlopen(uri)
info = u.info() info = u.info()
u.close() u.close()
return info return info
def post(uri, query): def post(uri, query):
if not uri.startswith('http'): if not uri.startswith('http'):
return return
data = urllib.urlencode(query) data = urllib.parse.urlencode(query)
u = urllib.urlopen(uri, data) u = urllib.request.urlopen(uri, data)
bytes = u.read() bytes = u.read().decode('utf-8')
u.close() u.close()
return bytes return bytes
r_entity = re.compile(r'&([^;\s]+);') r_entity = re.compile(r'&([^;\s]+);')
def entity(match): def entity(match):
value = match.group(1).lower() value = match.group(1).lower()
if value.startswith('#x'): if value.startswith('#x'):
return unichr(int(value[2:], 16)) return chr(int(value[2:], 16))
elif value.startswith('#'): elif value.startswith('#'):
return unichr(int(value[1:])) return chr(int(value[1:]))
elif name2codepoint.has_key(value): elif value in name2codepoint:
return unichr(name2codepoint[value]) return chr(name2codepoint[value])
return '[' + value + ']' return '[' + value + ']'
def quote(text):
return urllib.parse.quote(text)
def decode(html): def decode(html):
return r_entity.sub(entity, html) return r_entity.sub(entity, html)
r_string = re.compile(r'("(\\.|[^"\\])*")') r_string = re.compile(r'("(\\.|[^"\\])*")')
r_json = re.compile(r'^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]+$') r_json = re.compile(r'^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]+$')
env = {'__builtins__': None, 'null': None, 'true': True, 'false': False} env = {'__builtins__': None, 'null': None, 'true': True, 'false': False}
def json(text): def json(text):
"""Evaluate JSON text safely (we hope).""" """Evaluate JSON text safely (we hope)."""
if r_json.match(r_string.sub('', text)): return jsonlib.loads(text)
text = r_string.sub(lambda m: 'u' + m.group(1), text)
return eval(text.strip(' \t\r\n'), env, {})
raise ValueError('Input must be serialised JSON.')
if __name__=="__main__": if __name__=="__main__":
main() main()