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

371
bot.py
View File

@ -13,222 +13,225 @@ import irc
home = os.getcwd()
def decode(bytes):
try: text = bytes.decode('utf-8')
except UnicodeDecodeError:
try: text = bytes.decode('iso-8859-1')
except UnicodeDecodeError:
text = bytes.decode('cp1252')
return text
if type(bytes) == str:
return bytes
try: text = bytes.decode('utf-8')
except UnicodeDecodeError:
try: text = bytes.decode('iso-8859-1')
except UnicodeDecodeError:
text = bytes.decode('cp1252')
return text
class Phenny(irc.Bot):
def __init__(self, config):
args = (config.nick, config.name, config.channels, config.password)
irc.Bot.__init__(self, *args)
self.config = config
self.doc = {}
self.stats = {}
self.setup()
def __init__(self, config):
args = (config.nick, config.name, config.channels, config.password)
irc.Bot.__init__(self, *args)
self.config = config
self.doc = {}
self.stats = {}
self.setup()
def setup(self):
self.variables = {}
def setup(self):
self.variables = {}
filenames = []
if not hasattr(self.config, 'enable'):
for fn in os.listdir(os.path.join(home, 'modules')):
if fn.endswith('.py') and not fn.startswith('_'):
filenames.append(os.path.join(home, 'modules', fn))
else:
for fn in self.config.enable:
filenames.append(os.path.join(home, 'modules', fn + '.py'))
filenames = []
if not hasattr(self.config, 'enable'):
for fn in os.listdir(os.path.join(home, 'modules')):
if fn.endswith('.py') and not fn.startswith('_'):
filenames.append(os.path.join(home, 'modules', fn))
else:
for fn in self.config.enable:
filenames.append(os.path.join(home, 'modules', fn + '.py'))
if hasattr(self.config, 'extra'):
for fn in self.config.extra:
if os.path.isfile(fn):
filenames.append(fn)
elif os.path.isdir(fn):
for n in os.listdir(fn):
if n.endswith('.py') and not n.startswith('_'):
filenames.append(os.path.join(fn, n))
if hasattr(self.config, 'extra'):
for fn in self.config.extra:
if os.path.isfile(fn):
filenames.append(fn)
elif os.path.isdir(fn):
for n in os.listdir(fn):
if n.endswith('.py') and not n.startswith('_'):
filenames.append(os.path.join(fn, n))
modules = []
excluded_modules = getattr(self.config, 'exclude', [])
for filename in filenames:
name = os.path.basename(filename)[:-3]
if name in excluded_modules: continue
# if name in sys.modules:
# del sys.modules[name]
try: module = imp.load_source(name, filename)
except Exception, e:
print >> sys.stderr, "Error loading %s: %s (in bot.py)" % (name, e)
else:
if hasattr(module, 'setup'):
module.setup(self)
self.register(vars(module))
modules.append(name)
modules = []
excluded_modules = getattr(self.config, 'exclude', [])
for filename in filenames:
name = os.path.basename(filename)[:-3]
if name in excluded_modules: continue
# if name in sys.modules:
# del sys.modules[name]
try: module = imp.load_source(name, filename)
except Exception as e:
print("Error loading %s: %s (in bot.py)" % (name, e), file=sys.stderr)
else:
if hasattr(module, 'setup'):
module.setup(self)
self.register(vars(module))
modules.append(name)
if modules:
print >> sys.stderr, 'Registered modules:', ', '.join(modules)
else: print >> sys.stderr, "Warning: Couldn't find any modules"
if modules:
print('Registered modules:', ', '.join(modules), file=sys.stderr)
else: print("Warning: Couldn't find any modules", file=sys.stderr)
self.bind_commands()
self.bind_commands()
def register(self, variables):
# This is used by reload.py, hence it being methodised
for name, obj in variables.iteritems():
if hasattr(obj, 'commands') or hasattr(obj, 'rule'):
self.variables[name] = obj
def register(self, variables):
# This is used by reload.py, hence it being methodised
for name, obj in variables.items():
if hasattr(obj, 'commands') or hasattr(obj, 'rule'):
self.variables[name] = obj
def bind_commands(self):
self.commands = {'high': {}, 'medium': {}, 'low': {}}
def bind(self, priority, regexp, func):
print priority, regexp.pattern.encode('utf-8'), func
# register documentation
if not hasattr(func, 'name'):
func.name = func.__name__
if func.__doc__:
if hasattr(func, 'example'):
example = func.example
example = example.replace('$nickname', self.nick)
else: example = None
self.doc[func.name] = (func.__doc__, example)
self.commands[priority].setdefault(regexp, []).append(func)
def bind_commands(self):
self.commands = {'high': {}, 'medium': {}, 'low': {}}
def bind(self, priority, regexp, func):
print(priority, regexp.pattern.encode('utf-8'), func)
# register documentation
if not hasattr(func, 'name'):
func.name = func.__name__
if func.__doc__:
if hasattr(func, 'example'):
example = func.example
example = example.replace('$nickname', self.nick)
else: example = None
self.doc[func.name] = (func.__doc__, example)
self.commands[priority].setdefault(regexp, []).append(func)
def sub(pattern, self=self):
# These replacements have significant order
pattern = pattern.replace('$nickname', re.escape(self.nick))
return pattern.replace('$nick', r'%s[,:] +' % re.escape(self.nick))
def sub(pattern, self=self):
# These replacements have significant order
pattern = pattern.replace('$nickname', re.escape(self.nick))
return pattern.replace('$nick', r'%s[,:] +' % re.escape(self.nick))
for name, func in self.variables.iteritems():
# print name, func
if not hasattr(func, 'priority'):
func.priority = 'medium'
for name, func in self.variables.items():
# print name, func
if not hasattr(func, 'priority'):
func.priority = 'medium'
if not hasattr(func, 'thread'):
func.thread = True
if not hasattr(func, 'thread'):
func.thread = True
if not hasattr(func, 'event'):
func.event = 'PRIVMSG'
else: func.event = func.event.upper()
if not hasattr(func, 'event'):
func.event = 'PRIVMSG'
else: func.event = func.event.upper()
if hasattr(func, 'rule'):
if isinstance(func.rule, str):
pattern = sub(func.rule)
regexp = re.compile(pattern)
bind(self, func.priority, regexp, func)
if hasattr(func, 'rule'):
if isinstance(func.rule, str):
pattern = sub(func.rule)
regexp = re.compile(pattern)
bind(self, func.priority, regexp, func)
if isinstance(func.rule, tuple):
# 1) e.g. ('$nick', '(.*)')
if len(func.rule) == 2 and isinstance(func.rule[0], str):
prefix, pattern = func.rule
prefix = sub(prefix)
regexp = re.compile(prefix + pattern)
bind(self, func.priority, regexp, func)
if isinstance(func.rule, tuple):
# 1) e.g. ('$nick', '(.*)')
if len(func.rule) == 2 and isinstance(func.rule[0], str):
prefix, pattern = func.rule
prefix = sub(prefix)
regexp = re.compile(prefix + pattern)
bind(self, func.priority, regexp, func)
# 2) e.g. (['p', 'q'], '(.*)')
elif len(func.rule) == 2 and isinstance(func.rule[0], list):
prefix = self.config.prefix
commands, pattern = func.rule
for command in commands:
command = r'(%s)\b(?: +(?:%s))?' % (command, pattern)
regexp = re.compile(prefix + command)
bind(self, func.priority, regexp, func)
# 2) e.g. (['p', 'q'], '(.*)')
elif len(func.rule) == 2 and isinstance(func.rule[0], list):
prefix = self.config.prefix
commands, pattern = func.rule
for command in commands:
command = r'(%s)\b(?: +(?:%s))?' % (command, pattern)
regexp = re.compile(prefix + command)
bind(self, func.priority, regexp, func)
# 3) e.g. ('$nick', ['p', 'q'], '(.*)')
elif len(func.rule) == 3:
prefix, commands, pattern = func.rule
prefix = sub(prefix)
for command in commands:
command = r'(%s) +' % command
regexp = re.compile(prefix + command + pattern)
bind(self, func.priority, regexp, func)
# 3) e.g. ('$nick', ['p', 'q'], '(.*)')
elif len(func.rule) == 3:
prefix, commands, pattern = func.rule
prefix = sub(prefix)
for command in commands:
command = r'(%s) +' % command
regexp = re.compile(prefix + command + pattern)
bind(self, func.priority, regexp, func)
if hasattr(func, 'commands'):
for command in func.commands:
template = r'^%s(%s)(?: +(.*))?$'
pattern = template % (self.config.prefix, command)
regexp = re.compile(pattern)
bind(self, func.priority, regexp, func)
if hasattr(func, 'commands'):
for command in func.commands:
template = r'^%s(%s)(?: +(.*))?$'
pattern = template % (self.config.prefix, command)
regexp = re.compile(pattern)
bind(self, func.priority, regexp, func)
def wrapped(self, origin, text, match):
class PhennyWrapper(object):
def __init__(self, phenny):
self.bot = phenny
def wrapped(self, origin, text, match):
class PhennyWrapper(object):
def __init__(self, phenny):
self.bot = phenny
def __getattr__(self, attr):
sender = origin.sender or text
if attr == 'reply':
return (lambda msg:
self.bot.msg(sender, origin.nick + ': ' + msg))
elif attr == 'say':
return lambda msg: self.bot.msg(sender, msg)
elif attr == 'do':
return lambda msg: self.bot.action(sender, msg)
return getattr(self.bot, attr)
def __getattr__(self, attr):
sender = origin.sender or text
if attr == 'reply':
return (lambda msg:
self.bot.msg(sender, origin.nick + ': ' + msg))
elif attr == 'say':
return lambda msg: self.bot.msg(sender, msg)
elif attr == 'do':
return lambda msg: self.bot.action(sender, msg)
return getattr(self.bot, attr)
return PhennyWrapper(self)
return PhennyWrapper(self)
def input(self, origin, text, bytes, match, event, args):
class CommandInput(unicode):
def __new__(cls, text, origin, bytes, match, event, args):
s = unicode.__new__(cls, text)
s.sender = origin.sender
s.nick = origin.nick
s.event = event
s.bytes = bytes
s.match = match
s.group = match.group
s.groups = match.groups
s.args = args
s.admin = origin.nick in self.config.admins
s.owner = origin.nick == self.config.owner
return s
def input(self, origin, text, bytes, match, event, args):
class CommandInput(str):
def __new__(cls, text, origin, bytes, match, event, args):
s = str.__new__(cls, text)
s.sender = decode(origin.sender)
s.nick = decode(origin.nick)
s.event = event
s.bytes = bytes
s.match = match
s.group = match.group
s.groups = match.groups
s.args = args
s.admin = self.nick in self.config.admins
s.owner = self.nick == self.config.owner
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):
try: func(phenny, input)
except Exception, e:
self.error(origin)
def call(self, func, origin, phenny, input):
try: func(phenny, input)
except Exception as e:
self.error(origin)
def limit(self, origin, func):
if origin.sender and origin.sender.startswith('#'):
if hasattr(self.config, 'limit'):
limits = self.config.limit.get(origin.sender)
if limits and (func.__module__ not in limits):
return True
return False
def limit(self, origin, func):
if origin.sender and origin.sender.startswith(b'#'):
if hasattr(self.config, 'limit'):
limits = self.config.limit.get(origin.sender)
if limits and (func.__module__ not in limits):
return True
return False
def dispatch(self, origin, args):
bytes, event, args = args[0], args[1], args[2:]
text = decode(bytes)
def dispatch(self, origin, args):
bytes, event, args = args[0], args[1], args[2:]
text = decode(bytes)
event = decode(event)
if origin.nick in self.config.ignore:
return
if origin.nick in self.config.ignore:
return
for priority in ('high', 'medium', 'low'):
items = self.commands[priority].items()
for regexp, funcs in items:
for func in funcs:
if event != func.event: continue
for priority in ('high', 'medium', 'low'):
items = list(self.commands[priority].items())
for regexp, funcs in items:
for func in funcs:
if event != func.event: continue
match = regexp.match(text)
if match:
if self.limit(origin, func): continue
match = regexp.match(text)
if match:
if self.limit(origin, func): continue
phenny = self.wrapped(origin, text, match)
input = self.input(origin, text, bytes, match, event, args)
phenny = self.wrapped(origin, text, match)
input = self.input(origin, text, bytes, match, event, args)
if func.thread:
targs = (func, origin, phenny, input)
t = threading.Thread(target=self.call, args=targs)
t.start()
else: self.call(func, origin, phenny, input)
if func.thread:
targs = (func, origin, phenny, input)
t = threading.Thread(target=self.call, args=targs)
t.start()
else: self.call(func, origin, phenny, input)
for source in [origin.sender, origin.nick]:
try: self.stats[(func.name, source)] += 1
except KeyError:
self.stats[(func.name, source)] = 1
for source in [origin.sender, origin.nick]:
try: self.stats[(func.name, source)] += 1
except KeyError:
self.stats[(func.name, source)] = 1
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 socket, asyncore, asynchat
import ssl
class Origin(object):
source = re.compile(r'([^!]*)!?([^@]*)@?(.*)')
source = re.compile(r'([^!]*)!?([^@]*)@?(.*)')
def __init__(self, bot, source, args):
match = Origin.source.match(source or '')
self.nick, self.user, self.host = match.groups()
def __init__(self, bot, source, args):
source = source.decode('utf-8')
match = Origin.source.match(source or '')
self.nick, self.user, self.host = match.groups()
if len(args) > 1:
target = args[1]
else: target = None
if len(args) > 1:
target = args[1]
else: target = None
mappings = {bot.nick: self.nick, None: None}
self.sender = mappings.get(target, target)
mappings = {bot.nick: self.nick, None: None}
self.sender = mappings.get(target, target)
class Bot(asynchat.async_chat):
def __init__(self, nick, name, channels, password=None):
asynchat.async_chat.__init__(self)
self.set_terminator('\n')
self.buffer = ''
def __init__(self, nick, name, channels, password=None):
asynchat.async_chat.__init__(self)
self.set_terminator(b'\n')
self.buffer = b''
self.nick = nick
self.user = nick
self.name = name
self.password = password
self.nick = nick
self.user = nick
self.name = name
self.password = password
self.verbose = True
self.channels = channels or []
self.stack = []
self.verbose = True
self.channels = channels or []
self.stack = []
import threading
self.sending = threading.RLock()
import threading
self.sending = threading.RLock()
# def push(self, *args, **kargs):
# asynchat.async_chat.push(self, *args, **kargs)
# def push(self, *args, **kargs):
# asynchat.async_chat.push(self, *args, **kargs)
def __write(self, args, text=None):
# print '%r %r %r' % (self, args, text)
try:
if text is not None:
self.push((' '.join(args) + ' :' + text)[:512] + '\r\n')
else: self.push(' '.join(args)[:512] + '\r\n')
except IndexError:
pass
def __write(self, args, text=None):
# print '%r %r %r' % (self, args, text)
try:
if text is not None:
self.push((b' '.join(args) + b' :' + text)[:512] + b'\r\n')
else:
self.push(b' '.join(args)[:512] + b'\r\n')
except IndexError:
pass
def write(self, args, text=None):
# This is a safe version of __write
def safe(input):
input = input.replace('\n', '')
input = input.replace('\r', '')
return input.encode('utf-8')
try:
args = [safe(arg) for arg in args]
if text is not None:
text = safe(text)
self.__write(args, text)
except Exception, e: pass
def write(self, args, text=None):
print(args, text)
# This is a safe version of __write
def safe(input):
input = input.replace('\n', '')
input = input.replace('\r', '')
return input.encode('utf-8')
try:
args = [safe(arg) for arg in args]
if text is not None:
text = safe(text)
self.__write(args, text)
except Exception as e:
pass
def run(self, host, port=6667, ssl=False, ipv6=False):
self.initiate_connect(host, port, ssl, ipv6)
def run(self, host, port=6667, ssl=False, ipv6=False):
self.initiate_connect(host, port, ssl, ipv6)
def initiate_connect(self, host, port, ssl, ipv6):
if self.verbose:
message = 'Connecting to %s:%s...' % (host, port)
print >> sys.stderr, message,
if ipv6 and socket.has_ipv6:
af = socket.AF_INET6
else:
af = socket.AF_INET
self.create_socket(af, socket.SOCK_STREAM)
self.connect((host, port))
if ssl:
import ssl
self.socket = ssl.wrap_socket(self.socket)
try: asyncore.loop()
except KeyboardInterrupt:
sys.exit()
def initiate_connect(self, host, port, use_ssl, ipv6):
if self.verbose:
message = 'Connecting to %s:%s...' % (host, port)
print(message, end=' ', file=sys.stderr)
if ipv6 and socket.has_ipv6:
af = socket.AF_INET6
else:
af = socket.AF_INET
self.create_socket(af, socket.SOCK_STREAM, use_ssl)
self.connect((host, port))
try: asyncore.loop()
except KeyboardInterrupt:
sys.exit()
def handle_connect(self):
if self.verbose:
print >> sys.stderr, 'connected!'
if self.password:
self.write(('PASS', self.password))
self.write(('NICK', self.nick))
self.write(('USER', self.user, '+iw', self.nick), self.name)
def create_socket(self, family, type, use_ssl=False):
self.family_and_type = family, type
sock = socket.socket(family, type)
if use_ssl:
sock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLSv1)
# FIXME: ssl module does not appear to work properly with nonblocking sockets
#sock.setblocking(0)
self.set_socket(sock)
def handle_close(self):
self.close()
print >> sys.stderr, 'Closed!'
def handle_connect(self):
if self.verbose:
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):
self.buffer += data
def handle_close(self):
self.close()
print('Closed!', file=sys.stderr)
def found_terminator(self):
line = self.buffer
if line.endswith('\r'):
line = line[:-1]
self.buffer = ''
def collect_incoming_data(self, data):
self.buffer += data
# print line
if line.startswith(':'):
source, line = line[1:].split(' ', 1)
else: source = None
def found_terminator(self):
line = self.buffer
if line.endswith(b'\r'):
line = line[:-1]
self.buffer = b''
if ' :' in line:
argstr, text = line.split(' :', 1)
else: argstr, text = line, ''
args = argstr.split()
# print line
if line.startswith(b':'):
source, line = line[1:].split(b' ', 1)
else: source = None
origin = Origin(self, source, args)
self.dispatch(origin, tuple([text] + args))
if b' :' in line:
argstr, text = line.split(b' :', 1)
else: argstr, text = line, b''
args = argstr.split()
if args[0] == 'PING':
self.write(('PONG', text))
origin = Origin(self, source, args)
self.dispatch(origin, tuple([text] + args))
def dispatch(self, origin, args):
pass
if args[0] == b'PING':
self.write(('PONG', text))
def msg(self, recipient, text):
self.sending.acquire()
def dispatch(self, origin, args):
pass
# Cf. http://swhack.com/logs/2006-03-01#T19-43-25
if isinstance(text, unicode):
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
def msg(self, recipient, text):
self.sending.acquire()
# No messages within the last 3 seconds? Go ahead!
# Otherwise, wait so it's been at least 0.8 seconds + penalty
if self.stack:
elapsed = time.time() - self.stack[-1][0]
if elapsed < 3:
penalty = float(max(0, len(text) - 50)) / 70
wait = 0.8 + penalty
if elapsed < wait:
time.sleep(wait - elapsed)
# Cf. http://swhack.com/logs/2006-03-01#T19-43-25
if isinstance(text, str):
try: text = text.encode('utf-8')
except UnicodeEncodeError as e:
text = e.__class__ + ': ' + str(e)
if isinstance(recipient, str):
try: recipient = recipient.encode('utf-8')
except UnicodeEncodeError as e:
return
# Loop detection
messages = [m[1] for m in self.stack[-8:]]
if messages.count(text) >= 5:
text = '...'
if messages.count('...') >= 3:
self.sending.release()
return
# No messages within the last 3 seconds? Go ahead!
# Otherwise, wait so it's been at least 0.8 seconds + penalty
if self.stack:
elapsed = time.time() - self.stack[-1][0]
if elapsed < 3:
penalty = float(max(0, len(text) - 50)) / 70
wait = 0.8 + penalty
if elapsed < wait:
time.sleep(wait - elapsed)
def safe(input):
input = input.replace('\n', '')
return input.replace('\r', '')
self.__write(('PRIVMSG', safe(recipient)), safe(text))
self.stack.append((time.time(), text))
self.stack = self.stack[-10:]
# Loop detection
messages = [m[1] for m in self.stack[-8:]]
if messages.count(text) >= 5:
text = '...'
if messages.count('...') >= 3:
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):
text = "ACTION %s" % text
textu = chr(1) + text + chr(1)
return self.msg(recipient, textu)
self.sending.release()
def notice(self, dest, text):
self.write(('NOTICE', dest), text)
def action(self, recipient, text):
text = "ACTION %s" % text
textu = chr(1) + text + chr(1)
return self.msg(recipient, textu)
def error(self, origin):
try:
import traceback
trace = traceback.format_exc()
print trace
lines = list(reversed(trace.splitlines()))
def notice(self, dest, text):
self.write((b'NOTICE', dest), text)
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')
def error(self, origin):
try:
import traceback
trace = traceback.format_exc()
print(trace)
lines = list(reversed(trace.splitlines()))
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):
def f_ping(self, origin, match, args):
delay = m.group(1)
if delay is not None:
import time
time.sleep(int(delay))
self.msg(origin.sender, 'pong (%s)' % delay)
else: self.msg(origin.sender, 'pong')
f_ping.rule = r'^\.ping(?:[ \t]+(\d+))?$'
def f_ping(self, origin, match, args):
delay = m.group(1)
if delay is not None:
import time
time.sleep(int(delay))
self.msg(origin.sender, 'pong (%s)' % delay)
else: self.msg(origin.sender, 'pong')
f_ping.rule = r'^\.ping(?:[ \t]+(\d+))?$'
def main():
# bot = TestBot('testbot', ['#d8uv.com'])
# bot.run('irc.freenode.net')
print __doc__
bot = TestBot('testbot007', 'testbot007', ['#wadsworth'])
bot.run('irc.freenode.net')
print(__doc__)
if __name__=="__main__":
main()
main()

View File

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

View File

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

View File

@ -10,7 +10,7 @@ modified from Wikipedia module
author: mutantmonkey <mutantmonkey@gmail.com>
"""
import re, urllib
import re, urllib.request, urllib.parse, urllib.error
import web
import json
@ -65,9 +65,9 @@ def awik(phenny, input):
origterm = input.groups()[1]
if not origterm:
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.replace(' ', '_')
@ -84,4 +84,4 @@ awik.commands = ['awik']
awik.priority = 'high'
if __name__ == '__main__':
print __doc__.strip()
print(__doc__.strip())

View File

@ -22,5 +22,5 @@ bothug.commands = ['bothug']
bothug.priority = 'low'
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
if botsnack.coolingdown:
if now - botsnack.coolingstarted > botsnack.coolingperiod:
print "cooling down over, reseting"
print("cooling down over, reseting")
botsnack.coolingdown = False
botsnack.hunger = 50.0
botsnack.last_tick = now
else:
print "cooling down! %s < %s" %(now - botsnack.coolingstarted, botsnack.coolingperiod)
print("cooling down! %s < %s" %(now - botsnack.coolingstarted, botsnack.coolingperiod))
return # ignore!
# 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)
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
@ -68,7 +68,7 @@ def botsnack(phenny, input):
old_hunger = botsnack.hunger
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
phenny.say("Too much food!")
@ -106,5 +106,5 @@ botsnack.last_tick = time.time()
botsnack.coolingdown = False
if __name__ == '__main__':
print __doc__.strip()
print(__doc__.strip())

View File

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

View File

@ -131,4 +131,4 @@ chill.commands = ['chill']
chill.priority = 'low'
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/
"""
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 tools import deprecated
@ -203,9 +203,9 @@ def f_time(self, origin, match, args):
People = self.config.timezones
else: People = {}
if People.has_key(tz):
if tz in People:
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 = tz.upper()
@ -218,7 +218,7 @@ def f_time(self, origin, match, args):
locale.setlocale(locale.LC_TIME, (tz[1:-1], 'UTF-8'))
msg = time.strftime("%A, %d %B %Y %H:%M:%SZ", time.gmtime())
self.msg(origin.sender, msg)
elif TimeZones.has_key(TZ):
elif TZ in TimeZones:
offset = TimeZones[TZ] * 3600
timenow = time.gmtime(time.time() + offset)
msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(TZ), timenow)
@ -273,7 +273,7 @@ yi.priority = 'low'
def tock(phenny, input):
"""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()
u.close()
phenny.say('"' + info['Date'] + '" - tycho.usno.navy.mil')
@ -290,7 +290,7 @@ def npl(phenny, input):
d = dec('0.0')
for i in range(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('.')
f = '%Y-%m-%d %H:%M:%S'
result = datetime.datetime.fromtimestamp(d).strftime(f) + '.' + b[:6]
@ -300,4 +300,4 @@ npl.commands = ['npl']
npl.priority = 'high'
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):
template = 'U+%04X %s (%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):
arg = arg.upper()
@ -29,8 +29,8 @@ def codepoint_simple(arg):
r_label = re.compile('\\b' + arg.replace(' ', '.*\\b') + '\\b')
results = []
for cp in xrange(0xFFFF):
u = unichr(cp)
for cp in range(0xFFFF):
u = chr(cp)
try: name = unicodedata.name(u)
except ValueError: continue
@ -38,8 +38,8 @@ def codepoint_simple(arg):
results.append((len(name), u, cp, name))
if not results:
r_label = re.compile('\\b' + arg.replace(' ', '.*\\b'))
for cp in xrange(0xFFFF):
u = unichr(cp)
for cp in range(0xFFFF):
u = chr(cp)
try: name = unicodedata.name(u)
except ValueError: continue
@ -57,8 +57,8 @@ def codepoint_extended(arg):
try: r_search = re.compile(arg)
except: raise ValueError('Broken regexp: %r' % arg)
for cp in xrange(1, 0x10FFFF):
u = unichr(cp)
for cp in range(1, 0x10FFFF):
u = chr(cp)
name = unicodedata.name(u, '-')
if r_search.search(name):
@ -90,7 +90,7 @@ def u(phenny, input):
break
if len(arg) == 4:
try: u = unichr(int(arg, 16))
try: u = chr(int(arg, 16))
except ValueError: pass
else: return phenny.say(about(u))
@ -131,4 +131,4 @@ bytes.commands = ['bytes']
bytes.example = '.bytes \xe3\x8b\xa1'
if __name__ == '__main__':
print __doc__.strip()
print(__doc__.strip())

View File

@ -59,8 +59,7 @@ def etymology(word):
sentence = m.group(0)
try:
sentence = unicode(sentence, 'iso-8859-1')
sentence = sentence.encode('utf-8')
sentence = str(sentence, 'iso-8859-1')
except: pass
maxlength = 275
@ -98,4 +97,4 @@ f_etymology.priority = 'high'
if __name__=="__main__":
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/
"""
import re, urllib, urllib2, httplib, urlparse, time, cookielib
from htmlentitydefs import name2codepoint
import re, urllib.request, urllib.parse, urllib.error, urllib.request, urllib.error, urllib.parse, http.client, urllib.parse, time, http.cookiejar
from html.entities import name2codepoint
from string import join
import web
from tools import deprecated
cj = cookielib.LWPCookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
urllib2.install_opener(opener)
cj = http.cookiejar.LWPCookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
urllib.request.install_opener(opener)
def head(phenny, input):
"""Provide HTTP HEAD information."""
uri = input.group(2)
uri = (uri or '').encode('utf-8')
uri = (uri or '')
if ' ' in uri:
uri, header = uri.rsplit(' ', 1)
else: uri, header = uri, None
@ -35,7 +35,7 @@ def head(phenny, input):
try: info = web.head(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):
try: info = dict(info)
@ -49,20 +49,20 @@ def head(phenny, input):
if header is None:
data = []
if info.has_key('Status'):
if 'Status' in info:
data.append(info['Status'])
if info.has_key('content-type'):
if 'content-type' in info:
data.append(info['content-type'].replace('; charset=', ', '))
if info.has_key('last-modified'):
if 'last-modified' in info:
modified = info['last-modified']
modified = time.strptime(modified, '%a, %d %b %Y %H:%M:%S %Z')
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')
phenny.reply(', '.join(data))
else:
headerlower = header.lower()
if info.has_key(headerlower):
if headerlower in info:
phenny.say(header + ': ' + info.get(headerlower))
else:
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):
""".title <URI> - Return the title of URI."""
uri = match.group(2)
uri = (uri or '').encode('utf-8')
uri = (uri or '')
if not uri and hasattr(self, 'last_seen_uri'):
uri = self.last_seen_uri.get(origin.sender)
@ -90,7 +90,7 @@ def f_title(self, origin, match, args):
f_title.commands = ['title']
def noteuri(phenny, input):
uri = input.group(1).encode('utf-8')
uri = input.group(1)
if not hasattr(phenny.bot, 'last_seen_uri'):
phenny.bot.last_seen_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):
if re.match(r'(?i)' + phenny.config.prefix + titlecommands, input.group()):
return
uri = input.group(1).encode('utf-8')
uri = input.group(1)
title = gettitle(uri)
if title:
phenny.msg(input.sender, '[ ' + title + ' ]')
@ -137,7 +137,7 @@ def gettitle(uri):
status = str(info[1])
info = info[0]
if status.startswith('3'):
uri = urlparse.urljoin(uri, info['Location'])
uri = urllib.parse.urljoin(uri, info['Location'])
else: break
redirects += 1
@ -173,20 +173,20 @@ def gettitle(uri):
entity = m.group(0)
if entity.startswith('&#x'):
cp = int(entity[3:-1], 16)
return unichr(cp).encode('utf-8')
return chr(cp)
elif entity.startswith('&#'):
cp = int(entity[2:-1])
return unichr(cp).encode('utf-8')
return chr(cp)
else:
char = name2codepoint[entity[1:-1]]
return unichr(char).encode('utf-8')
return chr(char)
title = r_entity.sub(e, title)
if title:
try: title.decode('utf-8')
except:
try: title = title.decode('iso-8859-1').encode('utf-8')
except: title = title.decode('cp1252').encode('utf-8')
try: title = title.decode('iso-8859-1')
except: title = title.decode('cp1252')
else: pass
title = title.replace('\n', '')
title = title.replace('\r', '')
@ -194,4 +194,4 @@ def gettitle(uri):
return title
if __name__ == '__main__':
print __doc__.strip()
print(__doc__.strip())

View File

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

View File

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

View File

@ -7,9 +7,10 @@ author: Casey Link <unnamedrambler@gmail.com>
import random
import ConfigParser, os
from urllib import quote as urlquote
from urllib2 import urlopen, HTTPError
import configparser, os
from urllib.parse import quote as urlquote
from urllib.request import urlopen
from urllib.error import HTTPError
from lxml import etree
from datetime import datetime
@ -17,7 +18,7 @@ APIKEY = "b25b959554ed76058ac220b7b2e0a026"
APIURL = "http://ws.audioscrobbler.com/2.0/?api_key="+APIKEY+"&"
AEPURL = "http://www.davethemoonman.com/lastfm/aep.php?format=txt&username="
config = ConfigParser.RawConfigParser()
config = configparser.RawConfigParser()
config.optionxform = str
config_filename = ""
@ -84,7 +85,7 @@ def now_playing(phenny, input):
user = user.strip()
try:
req = urlopen("%smethod=user.getrecenttracks&user=%s" % (APIURL, urlquote(user)))
except HTTPError, e:
except HTTPError as e:
if e.code == 400:
phenny.say("%s doesn't exist on last.fm, perhaps they need to set user" % (user))
return
@ -151,7 +152,7 @@ def aep(phenny, input):
user = user.strip()
try:
req = urlopen("%s%s" % (AEPURL, urlquote(user)))
except HTTPError, e:
except HTTPError as e:
phenny.say("uhoh. try again later, mmkay?")
return
result = req.read()
@ -182,7 +183,7 @@ def tasteometer(phenny, input):
user2 = input.nick
try:
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:
phenny.say("uhoh, someone doesn't exist on last.fm, perhaps they need to set user")
return
@ -217,7 +218,7 @@ def tasteometer(phenny, input):
if len(artists) == 0:
common_artists = ". they don't have any artists in common."
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)
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"
if __name__ == '__main__':
print __doc__.strip()
print(__doc__.strip())

View File

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

View File

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

View File

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

View File

@ -24,7 +24,7 @@ def f_reload(phenny, input):
phenny.setup()
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)
# Thanks to moot for prodding me on this
@ -52,4 +52,4 @@ f_reload.priority = 'low'
f_reload.thread = False
if __name__ == '__main__':
print __doc__.strip()
print(__doc__.strip())

View File

@ -16,7 +16,7 @@ def filename(self):
def load_database(name):
data = {}
if os.path.isfile(name):
f = open(name, 'rb')
f = open(name, 'r')
for line in f:
unixtime, channel, nick, message = line.split('\t')
message = message.rstrip('\n')
@ -28,8 +28,8 @@ def load_database(name):
return data
def dump_database(name, data):
f = open(name, 'wb')
for unixtime, reminders in data.iteritems():
f = open(name, 'w')
for unixtime, reminders in data.items():
for channel, nick, message in reminders:
f.write('%s\t%s\t%s\t%s\n' % (unixtime, channel, nick, message))
f.close()
@ -97,12 +97,12 @@ scaling = {
's': 1
}
periods = '|'.join(scaling.keys())
periods = '|'.join(list(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)
m = r_command.match(input.bytes.decode('utf-8'))
if not m:
return phenny.reply("Sorry, didn't understand the input.")
length, scale, message = m.groups()
@ -133,4 +133,4 @@ def remind(phenny, input):
remind.commands = ['in']
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']
except IndexError: return None
except TypeError:
print results
print(results)
return False
def google_count(query):
results = google_ajax(query)
if not results.has_key('responseData'): return '0'
if not results['responseData'].has_key('cursor'): return '0'
if not results['responseData']['cursor'].has_key('estimatedResultCount'):
if 'responseData' not in results: return '0'
if 'cursor' not in results['responseData']: return '0'
if 'estimatedResultCount' not in results['responseData']['cursor']:
return '0'
return results['responseData']['cursor']['estimatedResultCount']
@ -56,7 +56,6 @@ def g(phenny, input):
query = input.group(2)
if not query:
return phenny.reply('.g what?')
query = query.encode('utf-8')
uri = google_search(query)
if uri:
phenny.reply(uri)
@ -74,7 +73,6 @@ def gc(phenny, input):
query = input.group(2)
if not query:
return phenny.reply('.gc what?')
query = query.encode('utf-8')
num = formatnumber(google_count(query))
phenny.say(query + ': ' + num)
gc.commands = ['gc']
@ -95,7 +93,6 @@ def gcs(phenny, input):
results = []
for i, query in enumerate(queries):
query = query.strip('[]')
query = query.encode('utf-8')
n = int((formatnumber(google_count(query)) or '0').replace(',', ''))
results.append((n, query))
if i >= 2: __import__('time').sleep(0.25)
@ -125,7 +122,6 @@ def bing(phenny, input):
if not query:
return phenny.reply('.bing what?')
query = query.encode('utf-8')
uri = bing_search(query, lang)
if uri:
phenny.reply(uri)
@ -150,7 +146,6 @@ def duck(phenny, input):
query = input.group(2)
if not query: return phenny.reply('.ddg what?')
query = query.encode('utf-8')
uri = duck_search(query)
if uri:
phenny.reply(uri)
@ -163,7 +158,7 @@ duck.commands = ['duck', 'ddg']
def search(phenny, input):
if not input.group(2):
return phenny.reply('.search for what?')
query = input.group(2).encode('utf-8')
query = input.group(2)
gu = google_search(query) or '-'
bu = bing_search(query) or '-'
du = duck_search(query) or '-'
@ -188,7 +183,7 @@ search.commands = ['search']
def suggest(phenny, input):
if not input.group(2):
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='
answer = web.get(uri + web.urllib.quote(query).replace('+', '%2B'))
if answer:
@ -197,4 +192,4 @@ def suggest(phenny, input):
suggest.commands = ['suggest']
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()
if not hasattr(self, 'seen'):
return self.msg(origin.sender, '?')
if self.seen.has_key(nick):
if nick in self.seen:
channel, t = self.seen[nick]
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]
try: note(self, origin, match, args)
except Exception, e: print e
except Exception as e: print(e)
f_note.rule = r'(.*)'
f_note.priority = 'low'
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'
def sloganize(word):
bytes = web.get(uri % web.urllib.quote(word.encode('utf-8')))
bytes = web.get(uri % web.quote(word))
return bytes
def slogan(phenny, input):
@ -37,4 +37,4 @@ slogan.commands = ['slogan']
slogan.example = '.slogan Granola'
if __name__ == '__main__':
print __doc__.strip()
print(__doc__.strip())

View File

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

View File

@ -37,7 +37,7 @@ def loadReminders(fn):
def dumpReminders(fn, data):
f = open(fn, 'w')
for tellee in data.iterkeys():
for tellee in data.keys():
for remindon in data[tellee]:
line = '\t'.join((tellee,) + remindon)
try: f.write(line + '\n')
@ -62,9 +62,9 @@ def f_remind(phenny, input):
# @@ Multiple comma-separated tellees? Cf. Terje, #swhack, 2006-04-15
verb, tellee, msg = input.groups()
verb = verb.encode('utf-8')
tellee = tellee.encode('utf-8')
msg = msg.encode('utf-8')
verb = verb
tellee = tellee
msg = msg
tellee_original = tellee.rstrip('.,:;')
tellee = tellee_original.lower()
@ -79,7 +79,7 @@ def f_remind(phenny, input):
if not tellee in (teller.lower(), phenny.nick, 'me'): # @@
# @@ <deltab> and year, if necessary
warn = False
if not phenny.reminders.has_key(tellee):
if tellee not in phenny.reminders:
phenny.reminders[tellee] = [(teller, verb, timenow, msg)]
else:
# if len(phenny.reminders[tellee]) >= maximum:
@ -144,14 +144,14 @@ def message(phenny, input):
for line in reminders[maximum:]:
phenny.msg(tellee, line)
if len(phenny.reminders.keys()) != remkeys:
if len(list(phenny.reminders.keys())) != remkeys:
dumpReminders(phenny.tell_filename, phenny.reminders) # @@ tell
message.rule = r'(.*)'
message.priority = 'low'
message.thread = False
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.')
messageAlert.event = 'JOIN'
messageAlert.rule = r'.*'
@ -159,4 +159,4 @@ messageAlert.priority = 'low'
messageAlert.thread = False
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>
"""
from urllib import quote as urlquote
from urllib2 import HTTPError
from urllib.parse import quote as urlquote
from urllib.error import HTTPError
import web
import lxml.html
@ -24,7 +24,7 @@ def tfw(phenny, input, fahrenheit=False, celsius=False):
try:
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.")
return
@ -46,7 +46,7 @@ def tfw(phenny, input, fahrenheit=False, celsius=False):
if c.isdigit():
tempt += c
temp = int(tempt)
deg = unichr(176).encode('latin-1')
deg = chr(176)
# add units and convert if necessary
if fahrenheit:
@ -82,5 +82,5 @@ def tfwc(phenny, input):
tfwc.rule = (['tfwc'], r'(.*)')
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/
"""
import re, urllib
import re, urllib.request, urllib.parse, urllib.error
import web
def detect(text):
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')
result = web.json(bytes)
try: return result['responseData']['language']
@ -21,7 +21,7 @@ def detect(text):
def translate(text, input, output):
uri = 'http://ajax.googleapis.com/ajax/services/language/translate'
q = urllib.quote(text)
q = urllib.parse.quote(text)
pair = input + '%7C' + output
bytes = web.get(uri + '?q=' + q + '&v=1.0&langpair=' + pair)
result = web.json(bytes)
@ -32,7 +32,7 @@ def tr(phenny, context):
"""Translates a phrase, with an optional language hint."""
input, output, phrase = context.groups()
phrase = phrase.encode('utf-8')
phrase = phrase
if (len(phrase) > 350) and (not context.admin):
return phenny.reply('Phrase must be under 350 characters.')
@ -41,8 +41,7 @@ def tr(phenny, context):
if not input:
err = 'Unable to guess your crazy moon language, sorry.'
return phenny.reply(err)
input = input.encode('utf-8')
output = (output or 'en').encode('utf-8')
output = (output or 'en')
if input != output:
msg = translate(phrase, input, output)
@ -56,12 +55,12 @@ def tr(phenny, context):
phenny.reply(msg)
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.priority = 'low'
def mangle(phenny, input):
phrase = input.group(2).encode('utf-8')
phrase = input.group(2)
for lang in ['fr', 'de', 'es', 'it', 'ja']:
backup = phrase
phrase = translate(phrase, 'en', lang)
@ -81,4 +80,4 @@ def mangle(phenny, input):
mangle.commands = ['mangle']
if __name__ == '__main__':
print __doc__.strip()
print(__doc__.strip())

View File

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

View File

@ -25,10 +25,10 @@ def val(phenny, input):
if isinstance(info, list):
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'])
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])
if n != 1:
result += ' (%s errors)' % n
@ -40,4 +40,4 @@ val.rule = (['val'], r'(?i)(\S+)')
val.example = '.val http://www.w3.org/'
if __name__ == '__main__':
print __doc__.strip()
print(__doc__.strip())

View File

@ -10,7 +10,7 @@ modified from Wikipedia module
author: mutantmonkey <mutantmonkey@gmail.com>
"""
import re, urllib
import re, urllib.request, urllib.parse, urllib.error
import web
import json
@ -64,9 +64,9 @@ def vtluug(phenny, input):
origterm = input.groups()[1]
if not origterm:
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.replace(' ', '_')
@ -83,4 +83,4 @@ vtluug.commands = ['vtluug']
vtluug.priority = 'high'
if __name__ == '__main__':
print __doc__.strip()
print(__doc__.strip())

View File

@ -8,9 +8,10 @@ author: Casey Link <unnamedrambler@gmail.com>
import random
import ConfigParser, os
from urllib import quote as urlquote
from urllib2 import urlopen, HTTPError
import configparser, os
from urllib.parse import quote as urlquote
from urllib.request import urlopen
from urllib.error import HTTPError
from lxml import etree
from lxml import objectify
from datetime import datetime
@ -25,7 +26,7 @@ class server(object):
self.players = []
def __str__(self):
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
class player(object):
@ -79,7 +80,7 @@ def wargame(phenny, input):
return
try:
req = urlopen(APIURL)
except HTTPError, e:
except HTTPError as e:
phenny.say("uhoh. try again later, mmkay?")
return
root = objectify.parse(req).getroot()
@ -90,11 +91,11 @@ def wargame(phenny, input):
for server_e in root.servers.server:
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):
try:
req = urlopen(APIURL)
except HTTPError, e:
except HTTPError as e:
phenny.say("uhoh. try again later, mmkay?")
return
root = objectify.parse(req).getroot()

View File

@ -7,16 +7,16 @@ Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/
"""
import re, urllib
import re, urllib.request, urllib.parse, urllib.error
import web
from tools import deprecated
r_from = re.compile(r'(?i)([+-]\d+):00 from')
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
for i in xrange(10):
for i in range(10):
bytes = web.get(uri)
if bytes is not None: break
@ -220,25 +220,25 @@ def f_weather(self, origin, match, args):
description = 'Violent storm'
else: description = 'Hurricane'
degrees = wind[0:3]
degrees = float(wind[0:3]
if degrees == 'VRB':
degrees = u'\u21BB'.encode('utf-8')
degrees = '\u21BB'
elif (degrees <= 22.5) or (degrees > 337.5):
degrees = u'\u2191'.encode('utf-8')
degrees = '\u2191'
elif (degrees > 22.5) and (degrees <= 67.5):
degrees = u'\u2197'.encode('utf-8')
degrees = '\u2197'
elif (degrees > 67.5) and (degrees <= 112.5):
degrees = u'\u2192'.encode('utf-8')
degrees = '\u2192'
elif (degrees > 112.5) and (degrees <= 157.5):
degrees = u'\u2198'.encode('utf-8')
degrees = '\u2198'
elif (degrees > 157.5) and (degrees <= 202.5):
degrees = u'\u2193'.encode('utf-8')
degrees = '\u2193'
elif (degrees > 202.5) and (degrees <= 247.5):
degrees = u'\u2199'.encode('utf-8')
degrees = '\u2199'
elif (degrees > 247.5) and (degrees <= 292.5):
degrees = u'\u2190'.encode('utf-8')
degrees = '\u2190'
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'):
wind = '%s %skt (%s)' % (description, speed, degrees)
@ -274,13 +274,13 @@ def f_weather(self, origin, match, args):
level = 0
if level == 8:
cover = u'Overcast \u2601'.encode('utf-8')
cover = 'Overcast \u2601'
elif level == 5:
cover = 'Cloudy'
elif level == 3:
cover = 'Scattered'
elif (level == 1) or (level == 0):
cover = u'Clear \u263C'.encode('utf-8')
cover = 'Clear \u263C'
else: cover = 'Cover Unknown'
else: cover = 'Cover Unknown'
@ -310,10 +310,10 @@ def f_weather(self, origin, match, args):
if isinstance(temp, int):
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'
if isinstance(temp, int):
temp = u'%s\u2103'.encode('utf-8') % temp
temp = '%s\u2103' % temp
if cond:
conds = cond
@ -397,14 +397,14 @@ def f_weather(self, origin, match, args):
# args = (icao, time, cover, temp, pressure, cond, wind)
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)
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)
self.msg(origin.sender, format.encode('utf-8') % args)
self.msg(origin.sender, format % args)
f_weather.rule = (['weather'], r'(.*)')
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/
"""
import re, urllib, gzip, StringIO
import re, urllib.request, urllib.parse, urllib.error, gzip, io
import web
import json
@ -61,9 +61,9 @@ def wik(phenny, input):
origterm = input.groups()[1]
if not origterm:
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.replace(' ', '_')
@ -80,4 +80,4 @@ wik.commands = ['wik']
wik.priority = 'high'
if __name__ == '__main__':
print __doc__.strip()
print(__doc__.strip())

View File

@ -23,7 +23,7 @@ def text(html):
return text
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)
mode = None
@ -62,11 +62,11 @@ parts = ('preposition', 'particle', 'noun', 'verb',
'adjective', 'adverb', 'interjection')
def format(word, definitions, number=2):
result = '%s' % word.encode('utf-8')
result = '%s' % word
for part in parts:
if definitions.has_key(part):
if part in definitions:
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)]
result += ', '.join(n)
return result.strip(' .,')
@ -97,4 +97,4 @@ def encarta(phenny, input):
encarta.commands = ['dict']
if __name__ == '__main__':
print __doc__.strip()
print(__doc__.strip())

View File

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

View File

@ -23,4 +23,4 @@ def deprecated(old):
return new
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/
"""
import re, urllib
from htmlentitydefs import name2codepoint
import re, urllib.request, urllib.parse, urllib.error
from html.entities import name2codepoint
import json as jsonlib
class Grab(urllib.URLopener):
def __init__(self, *args):
self.version = 'Mozilla/5.0 (Phenny)'
urllib.URLopener.__init__(self, *args)
def http_error_default(self, url, fp, errcode, errmsg, headers):
return urllib.addinfourl(fp, [headers, errcode], "http:" + url)
urllib._urlopener = Grab()
class Grab(urllib.request.URLopener):
def __init__(self, *args):
self.version = 'Mozilla/5.0 (Phenny)'
urllib.request.URLopener.__init__(self, *args)
def http_error_default(self, url, fp, errcode, errmsg, headers):
return urllib.addinfourl(fp, [headers, errcode], "http:" + url)
urllib.request._urlopener = Grab()
def get(uri):
if not uri.startswith('http'):
return
u = urllib.urlopen(uri)
bytes = u.read()
u.close()
return bytes
if not uri.startswith('http'):
return
u = urllib.request.urlopen(uri)
bytes = u.read().decode('utf-8')
u.close()
return bytes
def head(uri):
if not uri.startswith('http'):
return
u = urllib.urlopen(uri)
info = u.info()
u.close()
return info
if not uri.startswith('http'):
return
u = urllib.request.urlopen(uri)
info = u.info()
u.close()
return info
def post(uri, query):
if not uri.startswith('http'):
return
data = urllib.urlencode(query)
u = urllib.urlopen(uri, data)
bytes = u.read()
u.close()
return bytes
if not uri.startswith('http'):
return
data = urllib.parse.urlencode(query)
u = urllib.request.urlopen(uri, data)
bytes = u.read().decode('utf-8')
u.close()
return bytes
r_entity = re.compile(r'&([^;\s]+);')
def entity(match):
value = match.group(1).lower()
if value.startswith('#x'):
return unichr(int(value[2:], 16))
elif value.startswith('#'):
return unichr(int(value[1:]))
elif name2codepoint.has_key(value):
return unichr(name2codepoint[value])
return '[' + value + ']'
value = match.group(1).lower()
if value.startswith('#x'):
return chr(int(value[2:], 16))
elif value.startswith('#'):
return chr(int(value[1:]))
elif value in name2codepoint:
return chr(name2codepoint[value])
return '[' + value + ']'
def quote(text):
return urllib.parse.quote(text)
def decode(html):
return r_entity.sub(entity, html)
return r_entity.sub(entity, html)
r_string = re.compile(r'("(\\.|[^"\\])*")')
r_json = re.compile(r'^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]+$')
env = {'__builtins__': None, 'null': None, 'true': True, 'false': False}
def json(text):
"""Evaluate JSON text safely (we hope)."""
if r_json.match(r_string.sub('', 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.')
"""Evaluate JSON text safely (we hope)."""
return jsonlib.loads(text)
if __name__=="__main__":
main()
main()