flake8 + autopep8 (whitespace fixes)

This commit is contained in:
Ryan Hitchman 2014-01-14 13:12:37 -08:00
parent c065aaa59a
commit cb8c437772
38 changed files with 212 additions and 189 deletions

8
bot.py
View File

@ -20,7 +20,7 @@ print 'Loading plugins'
# bootstrap the reloader # bootstrap the reloader
eval(compile(open(os.path.join('core', 'reload.py'), 'U').read(), eval(compile(open(os.path.join('core', 'reload.py'), 'U').read(),
os.path.join('core', 'reload.py'), 'exec')) os.path.join('core', 'reload.py'), 'exec'))
reload(init=True) reload(init=True)
config() config()
@ -35,11 +35,11 @@ try:
for name, conf in bot.config['connections'].iteritems(): for name, conf in bot.config['connections'].iteritems():
if conf.get('ssl'): if conf.get('ssl'):
bot.conns[name] = SSLIRC(conf['server'], conf['nick'], conf=conf, bot.conns[name] = SSLIRC(conf['server'], conf['nick'], conf=conf,
port=conf.get('port', 6667), channels=conf['channels'], port=conf.get('port', 6667), channels=conf['channels'],
ignore_certificate_errors=conf.get('ignore_cert', True)) ignore_certificate_errors=conf.get('ignore_cert', True))
else: else:
bot.conns[name] = IRC(conf['server'], conf['nick'], conf=conf, bot.conns[name] = IRC(conf['server'], conf['nick'], conf=conf,
port=conf.get('port', 6667), channels=conf['channels']) port=conf.get('port', 6667), channels=conf['channels'])
except Exception, e: except Exception, e:
print 'ERROR: malformed config file', e print 'ERROR: malformed config file', e
sys.exit() sys.exit()

View File

@ -27,6 +27,7 @@ def censor(text):
class crlf_tcp(object): class crlf_tcp(object):
"Handles tcp connections that consist of utf-8 lines ending with crlf" "Handles tcp connections that consist of utf-8 lines ending with crlf"
def __init__(self, host, port, timeout=300): def __init__(self, host, port, timeout=300):
@ -94,15 +95,17 @@ class crlf_tcp(object):
class crlf_ssl_tcp(crlf_tcp): class crlf_ssl_tcp(crlf_tcp):
"Handles ssl tcp connetions that consist of utf-8 lines ending with crlf" "Handles ssl tcp connetions that consist of utf-8 lines ending with crlf"
def __init__(self, host, port, ignore_cert_errors, timeout=300): def __init__(self, host, port, ignore_cert_errors, timeout=300):
self.ignore_cert_errors = ignore_cert_errors self.ignore_cert_errors = ignore_cert_errors
crlf_tcp.__init__(self, host, port, timeout) crlf_tcp.__init__(self, host, port, timeout)
def create_socket(self): def create_socket(self):
return wrap_socket(crlf_tcp.create_socket(self), server_side=False, return wrap_socket(crlf_tcp.create_socket(self), server_side=False,
cert_reqs=CERT_NONE if self.ignore_cert_errors else cert_reqs=CERT_NONE if self.ignore_cert_errors else
CERT_REQUIRED) CERT_REQUIRED)
def recv_from_socket(self, nbytes): def recv_from_socket(self, nbytes):
return self.socket.read(nbytes) return self.socket.read(nbytes)
@ -123,8 +126,10 @@ irc_param_ref = re.compile(r'(?:^|(?<= ))(:.*|[^ ]+)').findall
class IRC(object): class IRC(object):
"handles the IRC protocol" "handles the IRC protocol"
#see the docs/ folder for more information on the protocol # see the docs/ folder for more information on the protocol
def __init__(self, server, nick, port=6667, channels=[], conf={}): def __init__(self, server, nick, port=6667, channels=[], conf={}):
self.channels = channels self.channels = channels
self.conf = conf self.conf = conf
@ -148,8 +153,8 @@ class IRC(object):
self.set_pass(self.conf.get('server_password')) self.set_pass(self.conf.get('server_password'))
self.set_nick(self.nick) self.set_nick(self.nick)
self.cmd("USER", self.cmd("USER",
[conf.get('user', 'skybot'), "3", "*", conf.get('realname', [conf.get('user', 'skybot'), "3", "*", conf.get('realname',
'Python bot - http://github.com/rmmh/skybot')]) 'Python bot - http://github.com/rmmh/skybot')])
def parse_loop(self): def parse_loop(self):
while True: while True:
@ -171,7 +176,7 @@ class IRC(object):
paramlist[-1] = paramlist[-1][1:] paramlist[-1] = paramlist[-1][1:]
lastparam = paramlist[-1] lastparam = paramlist[-1]
self.out.put([msg, prefix, command, params, nick, user, host, self.out.put([msg, prefix, command, params, nick, user, host,
paramlist, lastparam]) paramlist, lastparam])
if command == "PING": if command == "PING":
self.cmd("PONG", paramlist) self.cmd("PONG", paramlist)
@ -200,6 +205,7 @@ class IRC(object):
class FakeIRC(IRC): class FakeIRC(IRC):
def __init__(self, server, nick, port=6667, channels=[], conf={}, fn=""): def __init__(self, server, nick, port=6667, channels=[], conf={}, fn=""):
self.channels = channels self.channels = channels
self.conf = conf self.conf = conf
@ -233,7 +239,7 @@ class FakeIRC(IRC):
paramlist[-1] = paramlist[-1][1:] paramlist[-1] = paramlist[-1][1:]
lastparam = paramlist[-1] lastparam = paramlist[-1]
self.out.put([msg, prefix, command, params, nick, user, host, self.out.put([msg, prefix, command, params, nick, user, host,
paramlist, lastparam]) paramlist, lastparam])
if command == "PING": if command == "PING":
self.cmd("PONG", [params]) self.cmd("PONG", [params])
@ -242,6 +248,7 @@ class FakeIRC(IRC):
class SSLIRC(IRC): class SSLIRC(IRC):
def __init__(self, server, nick, port=6667, channels=[], conf={}, def __init__(self, server, nick, port=6667, channels=[], conf={},
ignore_certificate_errors=True): ignore_certificate_errors=True):
self.ignore_cert_errors = ignore_certificate_errors self.ignore_cert_errors = ignore_certificate_errors

View File

@ -6,8 +6,9 @@ thread.stack_size(1024 * 512) # reduce vm size
class Input(dict): class Input(dict):
def __init__(self, conn, raw, prefix, command, params, def __init__(self, conn, raw, prefix, command, params,
nick, user, host, paraml, msg): nick, user, host, paraml, msg):
chan = paraml[0].lower() chan = paraml[0].lower()
if chan == conn.nick.lower(): # is a PM if chan == conn.nick.lower(): # is a PM
@ -35,10 +36,10 @@ class Input(dict):
conn.cmd('NOTICE', [nick, msg]) conn.cmd('NOTICE', [nick, msg])
dict.__init__(self, conn=conn, raw=raw, prefix=prefix, command=command, dict.__init__(self, conn=conn, raw=raw, prefix=prefix, command=command,
params=params, nick=nick, user=user, host=host, params=params, nick=nick, user=user, host=host,
paraml=paraml, msg=msg, server=conn.server, chan=chan, paraml=paraml, msg=msg, server=conn.server, chan=chan,
notice=notice, say=say, reply=reply, pm=pm, bot=bot, notice=notice, say=say, reply=reply, pm=pm, bot=bot,
me=me, set_nick=set_nick, lastparam=paraml[-1]) me=me, set_nick=set_nick, lastparam=paraml[-1])
# make dict keys accessible as attributes # make dict keys accessible as attributes
def __getattr__(self, key): def __getattr__(self, key):
@ -80,7 +81,9 @@ def do_sieve(sieve, bot, input, func, type, args):
class Handler(object): class Handler(object):
'''Runs plugins in their own threads (ensures order)''' '''Runs plugins in their own threads (ensures order)'''
def __init__(self, func): def __init__(self, func):
self.func = func self.func = func
self.input_queue = Queue.Queue() self.input_queue = Queue.Queue()
@ -121,7 +124,7 @@ def dispatch(input, kind, func, args, autohelp=False):
return return
if autohelp and args.get('autohelp', True) and not input.inp \ if autohelp and args.get('autohelp', True) and not input.inp \
and func.__doc__ is not None: and func.__doc__ is not None:
input.reply(func.__doc__) input.reply(func.__doc__)
return return

View File

@ -49,7 +49,7 @@ def reload(init=False):
try: try:
eval(compile(open(filename, 'U').read(), filename, 'exec'), eval(compile(open(filename, 'U').read(), filename, 'exec'),
globals()) globals())
except Exception: except Exception:
traceback.print_exc() traceback.print_exc()
if init: # stop if there's an error (syntax?) in a core if init: # stop if there's an error (syntax?) in a core
@ -111,7 +111,7 @@ def reload(init=False):
if not init: if not init:
print '### new plugin (type: %s) loaded:' % \ print '### new plugin (type: %s) loaded:' % \
type, format_plug(data) type, format_plug(data)
if changed: if changed:
bot.commands = {} bot.commands = {}
@ -119,7 +119,7 @@ def reload(init=False):
name = plug[1]['name'].lower() name = plug[1]['name'].lower()
if not re.match(r'^\w+$', name): if not re.match(r'^\w+$', name):
print '### ERROR: invalid command name "%s" (%s)' % (name, print '### ERROR: invalid command name "%s" (%s)' % (name,
format_plug(plug)) format_plug(plug))
continue continue
if name in bot.commands: if name in bot.commands:
print "### ERROR: command '%s' already registered (%s, %s)" % \ print "### ERROR: command '%s' already registered (%s, %s)" % \

View File

@ -44,7 +44,7 @@ def bf(inp):
# the main program loop: # the main program loop:
while ip < len(program): while ip < len(program):
c = program[ip] c = program[ip]
if c == '+': if c == '+':
memory[mp] = memory[mp] + 1 % 256 memory[mp] = memory[mp] + 1 % 256
elif c == '-': elif c == '-':
memory[mp] = memory[mp] - 1 % 256 memory[mp] = memory[mp] - 1 % 256

View File

@ -23,13 +23,13 @@ def nrolls(count, n):
if count < 5000: if count < 5000:
return [random.randint(0, 1) for x in xrange(count)] return [random.randint(0, 1) for x in xrange(count)]
else: # fake it else: # fake it
return [int(random.normalvariate(.5*count, (.75*count)**.5))] return [int(random.normalvariate(.5 * count, (.75 * count) ** .5))]
else: else:
if count < 5000: if count < 5000:
return [random.randint(1, n) for x in xrange(count)] return [random.randint(1, n) for x in xrange(count)]
else: # fake it else: # fake it
return [int(random.normalvariate(.5*(1+n)*count, return [int(random.normalvariate(.5 * (1 + n) * count,
(((n+1)*(2*n+1)/6.-(.5*(1+n))**2)*count)**.5))] (((n + 1) * (2 * n + 1) / 6. - (.5 * (1 + n)) ** 2) * count) ** .5))]
@hook.command('roll') @hook.command('roll')

View File

@ -15,7 +15,7 @@ def urban(inp):
if page['result_type'] == 'no_results': if page['result_type'] == 'no_results':
return 'not found.' return 'not found.'
out = defs[0]['word'] + ': ' + defs[0]['definition'].replace('\r\n',' ') out = defs[0]['word'] + ': ' + defs[0]['definition'].replace('\r\n', ' ')
if len(out) > 400: if len(out) > 400:
out = out[:out.rfind(' ', 0, 400)] + '...' out = out[:out.rfind(' ', 0, 400)] + '...'
@ -61,7 +61,7 @@ def define(inp):
result += article[0] result += article[0]
if len(article) > 2: if len(article) > 2:
result += ' '.join('%d. %s' % (n + 1, section) result += ' '.join('%d. %s' % (n + 1, section)
for n, section in enumerate(article[1:])) for n, section in enumerate(article[1:]))
else: else:
result += article[1] + ' ' result += article[1] + ' '

View File

@ -11,7 +11,7 @@ ed_url = "http://encyclopediadramatica.se/"
@hook.command @hook.command
def drama(inp): def drama(inp):
'''.drama <phrase> -- gets first paragraph of Encyclopedia Dramatica ''' \ '''.drama <phrase> -- gets first paragraph of Encyclopedia Dramatica ''' \
'''article on <phrase>''' '''article on <phrase>'''
j = http.get_json(api_url, search=inp) j = http.get_json(api_url, search=inp)
if not j[1]: if not j[1]:

View File

@ -5,7 +5,7 @@ from util import hook, http
def api_get(query, key, is_image=None, num=1): def api_get(query, key, is_image=None, num=1):
url = ('https://www.googleapis.com/customsearch/v1?cx=007629729846476161907:ud5nlxktgcw' url = ('https://www.googleapis.com/customsearch/v1?cx=007629729846476161907:ud5nlxktgcw'
'&fields=items(title,link,snippet)&safe=off' + ('&searchType=image' if is_image else '')) '&fields=items(title,link,snippet)&safe=off' + ('&searchType=image' if is_image else ''))
return http.get_json(url, key=key, q=query, num=num) return http.get_json(url, key=key, q=query, num=num)

View File

@ -17,4 +17,4 @@ def sha1(inp):
def hash(inp): def hash(inp):
".hash <text> -- returns hashes of <text>" ".hash <text> -- returns hashes of <text>"
return ', '.join(x + ": " + getattr(hashlib, x)(inp).hexdigest() return ', '.join(x + ": " + getattr(hashlib, x)(inp).hexdigest()
for x in 'md5 sha1 sha256'.split()) for x in 'md5 sha1 sha256'.split())

View File

@ -7,6 +7,7 @@ from util import hook, http
api_url = "http://ws.audioscrobbler.com/2.0/?format=json" api_url = "http://ws.audioscrobbler.com/2.0/?format=json"
@hook.api_key('lastfm') @hook.api_key('lastfm')
@hook.command(autohelp=False) @hook.command(autohelp=False)
def lastfm(inp, nick='', say=None, api_key=None): def lastfm(inp, nick='', say=None, api_key=None):

View File

@ -15,15 +15,15 @@ log_fds = {} # '%(net)s %(chan)s' : (filename, fd)
timestamp_format = '%H:%M:%S' timestamp_format = '%H:%M:%S'
formats = {'PRIVMSG': '<%(nick)s> %(msg)s', formats = {'PRIVMSG': '<%(nick)s> %(msg)s',
'PART': '-!- %(nick)s [%(user)s@%(host)s] has left %(chan)s', 'PART': '-!- %(nick)s [%(user)s@%(host)s] has left %(chan)s',
'JOIN': '-!- %(nick)s [%(user)s@%(host)s] has joined %(param0)s', 'JOIN': '-!- %(nick)s [%(user)s@%(host)s] has joined %(param0)s',
'MODE': '-!- mode/%(chan)s [%(param_tail)s] by %(nick)s', 'MODE': '-!- mode/%(chan)s [%(param_tail)s] by %(nick)s',
'KICK': '-!- %(param1)s was kicked from %(chan)s by %(nick)s [%(msg)s]', 'KICK': '-!- %(param1)s was kicked from %(chan)s by %(nick)s [%(msg)s]',
'TOPIC': '-!- %(nick)s changed the topic of %(chan)s to: %(msg)s', 'TOPIC': '-!- %(nick)s changed the topic of %(chan)s to: %(msg)s',
'QUIT': '-!- %(nick)s has quit [%(msg)s]', 'QUIT': '-!- %(nick)s has quit [%(msg)s]',
'PING': '', 'PING': '',
'NOTICE': '' 'NOTICE': ''
} }
ctcp_formats = {'ACTION': '* %(nick)s %(ctcpmsg)s'} ctcp_formats = {'ACTION': '* %(nick)s %(ctcpmsg)s'}
@ -32,7 +32,7 @@ irc_color_re = re.compile(r'(\x03(\d+,\d+|\d)|[\x0f\x02\x16\x1f])')
def get_log_filename(dir, server, chan): def get_log_filename(dir, server, chan):
return os.path.join(dir, 'log', gmtime('%Y'), server, return os.path.join(dir, 'log', gmtime('%Y'), server,
(gmtime('%%s.%m-%d.log') % chan).lower()) (gmtime('%%s.%m-%d.log') % chan).lower())
def gmtime(format): def gmtime(format):
@ -57,8 +57,8 @@ def beautify(input):
ctcp += [''] ctcp += ['']
args['ctcpcmd'], args['ctcpmsg'] = ctcp args['ctcpcmd'], args['ctcpmsg'] = ctcp
format = ctcp_formats.get(args['ctcpcmd'], format = ctcp_formats.get(args['ctcpcmd'],
'%(nick)s [%(user)s@%(host)s] requested unknown CTCP ' '%(nick)s [%(user)s@%(host)s] requested unknown CTCP '
'%(ctcpcmd)s from %(chan)s: %(ctcpmsg)s') '%(ctcpcmd)s from %(chan)s: %(ctcpmsg)s')
return format % args return format % args

View File

@ -9,7 +9,7 @@ from util import hook, http
@hook.command('mc') @hook.command('mc')
def metacritic(inp): def metacritic(inp):
'.mc [all|movie|tv|album|x360|ps3|pc|ds|3ds|wii|psv] <title> -- gets rating for'\ '.mc [all|movie|tv|album|x360|ps3|pc|ds|3ds|wii|psv] <title> -- gets rating for'\
' <title> from metacritic on the specified medium' ' <title> from metacritic on the specified medium'
# if the results suck, it's metacritic's fault # if the results suck, it's metacritic's fault
@ -130,6 +130,6 @@ def metacritic(inp):
score = None score = None
return '[%s] %s - %s, %s -- %s' % (plat.upper(), name, return '[%s] %s - %s, %s -- %s' % (plat.upper(), name,
score or 'no score', score or 'no score',
'release: %s' % release if release else 'unreleased', 'release: %s' % release if release else 'unreleased',
link) link)

View File

@ -1,4 +1,3 @@
import re
import socket import socket
import subprocess import subprocess
import time import time
@ -18,12 +17,12 @@ def get_version():
shorthash = stdout.split(None, 1)[0] shorthash = stdout.split(None, 1)[0]
http.ua_skybot = 'Skybot/r%d %s (http://github.com/rmmh/skybot)' \ http.ua_skybot = 'Skybot/r%d %s (http://github.com/rmmh/skybot)' \
% (revnumber, shorthash) % (revnumber, shorthash)
return shorthash, revnumber return shorthash, revnumber
#autorejoin channels # autorejoin channels
@hook.event('KICK') @hook.event('KICK')
def rejoin(paraml, conn=None): def rejoin(paraml, conn=None):
if paraml[1] == conn.nick: if paraml[1] == conn.nick:
@ -31,7 +30,7 @@ def rejoin(paraml, conn=None):
conn.join(paraml[0]) conn.join(paraml[0])
#join channels when invited # join channels when invited
@hook.event('INVITE') @hook.event('INVITE')
def invite(paraml, conn=None): def invite(paraml, conn=None):
conn.join(paraml[-1]) conn.join(paraml[-1])

View File

@ -33,7 +33,7 @@ def mtg(inp):
printing_out = ', '.join('%s (%s)' % (set_abbrevs.get(x[0], x[0]), printing_out = ', '.join('%s (%s)' % (set_abbrevs.get(x[0], x[0]),
rarity_abbrevs.get(x[1], x[1])) rarity_abbrevs.get(x[1], x[1]))
for x in printings) for x in printings)
name.make_links_absolute(base_url=url) name.make_links_absolute(base_url=url)
link = name.attrib['href'] link = name.attrib['href']

View File

@ -8,4 +8,4 @@ def profile(inp):
".profile <username> -- links to <username>'s profile on SA" ".profile <username> -- links to <username>'s profile on SA"
return 'http://forums.somethingawful.com/member.php?action=getinfo' + \ return 'http://forums.somethingawful.com/member.php?action=getinfo' + \
'&username=' + '+'.join(inp.split()) '&username=' + '+'.join(inp.split())

View File

@ -8,7 +8,7 @@ from util import hook
def add_quote(db, chan, nick, add_nick, msg): def add_quote(db, chan, nick, add_nick, msg):
db.execute('''insert or fail into quote (chan, nick, add_nick, db.execute('''insert or fail into quote (chan, nick, add_nick,
msg, time) values(?,?,?,?,?)''', msg, time) values(?,?,?,?,?)''',
(chan, nick, add_nick, msg, time.time())) (chan, nick, add_nick, msg, time.time()))
db.commit() db.commit()
@ -20,19 +20,19 @@ def del_quote(db, chan, nick, add_nick, msg):
def get_quotes_by_nick(db, chan, nick): def get_quotes_by_nick(db, chan, nick):
return db.execute("select time, nick, msg from quote where deleted!=1 " return db.execute("select time, nick, msg from quote where deleted!=1 "
"and chan=? and lower(nick)=lower(?) order by time", "and chan=? and lower(nick)=lower(?) order by time",
(chan, nick)).fetchall() (chan, nick)).fetchall()
def get_quotes_by_chan(db, chan): def get_quotes_by_chan(db, chan):
return db.execute("select time, nick, msg from quote where deleted!=1 " return db.execute("select time, nick, msg from quote where deleted!=1 "
"and chan=? order by time", (chan,)).fetchall() "and chan=? order by time", (chan,)).fetchall()
def format_quote(q, num, n_quotes): def format_quote(q, num, n_quotes):
ctime, nick, msg = q ctime, nick, msg = q
return "[%d/%d] %s <%s> %s" % (num, n_quotes, return "[%d/%d] %s <%s> %s" % (num, n_quotes,
time.strftime("%Y-%m-%d", time.gmtime(ctime)), nick, msg) time.strftime("%Y-%m-%d", time.gmtime(ctime)), nick, msg)
@hook.command('q') @hook.command('q')
@ -42,8 +42,8 @@ def quote(inp, nick='', chan='', db=None):
"random or [#n]th quote by <nick> or from <#chan>/adds quote" "random or [#n]th quote by <nick> or from <#chan>/adds quote"
db.execute("create table if not exists quote" db.execute("create table if not exists quote"
"(chan, nick, add_nick, msg, time real, deleted default 0, " "(chan, nick, add_nick, msg, time real, deleted default 0, "
"primary key (chan, nick, msg))") "primary key (chan, nick, msg))")
db.commit() db.commit()
add = re.match(r"add[^\w@]+(\S+?)>?\s+(.*)", inp, re.I) add = re.match(r"add[^\w@]+(\S+?)>?\s+(.*)", inp, re.I)
@ -61,9 +61,7 @@ def quote(inp, nick='', chan='', db=None):
elif retrieve: elif retrieve:
select, num = retrieve.groups() select, num = retrieve.groups()
by_chan = False
if select.startswith('#'): if select.startswith('#'):
by_chan = True
quotes = get_quotes_by_chan(db, select) quotes = get_quotes_by_chan(db, select)
else: else:
quotes = get_quotes_by_nick(db, chan, select) quotes = get_quotes_by_nick(db, chan, select)
@ -85,7 +83,7 @@ def quote(inp, nick='', chan='', db=None):
if num: if num:
if num > n_quotes or (num < 0 and num < -n_quotes): if num > n_quotes or (num < 0 and num < -n_quotes):
return "I only have %d quote%s for %s" % (n_quotes, return "I only have %d quote%s for %s" % (n_quotes,
('s', '')[n_quotes == 1], select) ('s', '')[n_quotes == 1], select)
elif num < 0: elif num < 0:
selected_quote = quotes[num] selected_quote = quotes[num]
num = n_quotes + num + 1 num = n_quotes + num + 1

View File

@ -7,11 +7,11 @@ def bible(inp):
".bible <passage> -- gets <passage> from the Bible (ESV)" ".bible <passage> -- gets <passage> from the Bible (ESV)"
base_url = ('http://www.esvapi.org/v2/rest/passageQuery?key=IP&' base_url = ('http://www.esvapi.org/v2/rest/passageQuery?key=IP&'
'output-format=plain-text&include-heading-horizontal-lines&' 'output-format=plain-text&include-heading-horizontal-lines&'
'include-headings=false&include-passage-horizontal-lines=false&' 'include-headings=false&include-passage-horizontal-lines=false&'
'include-passage-references=false&include-short-copyright=false&' 'include-passage-references=false&include-short-copyright=false&'
'include-footnotes=false&line-length=0&' 'include-footnotes=false&line-length=0&'
'include-heading-horizontal-lines=false') 'include-heading-horizontal-lines=false')
text = http.get(base_url, passage=inp) text = http.get(base_url, passage=inp)

View File

@ -13,7 +13,7 @@ def db_init(db):
def get_memory(db, chan, word): def get_memory(db, chan, word):
row = db.execute("select data from memory where chan=? and word=lower(?)", row = db.execute("select data from memory where chan=? and word=lower(?)",
(chan, word)).fetchone() (chan, word)).fetchone()
if row: if row:
return row[0] return row[0]
else: else:
@ -56,7 +56,7 @@ def remember(inp, nick='', chan='', db=None):
return "appending %s to %s" % (new, data.replace('"', "''")) return "appending %s to %s" % (new, data.replace('"', "''"))
else: else:
return 'forgetting "%s", remembering this instead.' % \ return 'forgetting "%s", remembering this instead.' % \
data.replace('"', "''") data.replace('"', "''")
else: else:
return 'done.' return 'done.'

View File

@ -25,11 +25,13 @@ def rottentomatoes(inp, api_key=None):
if critics_score == -1: if critics_score == -1:
return return
reviews = http.get_json(movie_reviews_url % id, apikey=api_key, review_type='all') reviews = http.get_json(movie_reviews_url %
id, apikey=api_key, review_type='all')
review_count = reviews['total'] review_count = reviews['total']
fresh = critics_score * review_count / 100 fresh = critics_score * review_count / 100
rotten = review_count - fresh rotten = review_count - fresh
return u"%s - critics: \x02%d%%\x02 (%d\u2191%d\u2193)" \ return u"%s - critics: \x02%d%%\x02 (%d\u2191%d\u2193)" \
" audience: \x02%d%%\x02 - %s" % (title, critics_score, fresh, rotten, audience_score, url) " audience: \x02%d%%\x02 - %s" % (title, critics_score,
fresh, rotten, audience_score, url)

View File

@ -8,7 +8,7 @@ from util import hook, timesince
def db_init(db): def db_init(db):
"check to see that our db has the the seen table and return a connection." "check to see that our db has the the seen table and return a connection."
db.execute("create table if not exists seen(name, time, quote, chan, " db.execute("create table if not exists seen(name, time, quote, chan, "
"primary key(name, chan))") "primary key(name, chan))")
db.commit() db.commit()
@ -17,8 +17,8 @@ def db_init(db):
def seeninput(paraml, input=None, db=None, bot=None): def seeninput(paraml, input=None, db=None, bot=None):
db_init(db) db_init(db)
db.execute("insert or replace into seen(name, time, quote, chan)" db.execute("insert or replace into seen(name, time, quote, chan)"
"values(?,?,?,?)", (input.nick.lower(), time.time(), input.msg, "values(?,?,?,?)", (input.nick.lower(), time.time(), input.msg,
input.chan)) input.chan))
db.commit() db.commit()
@ -44,11 +44,11 @@ def seen(inp, nick='', chan='', db=None, input=None):
reltime = timesince.timesince(last_seen[1]) reltime = timesince.timesince(last_seen[1])
if last_seen[0] != inp.lower(): # for glob matching if last_seen[0] != inp.lower(): # for glob matching
inp = last_seen[0] inp = last_seen[0]
if last_seen[2][0:1]=="\x01": if last_seen[2][0:1] == "\x01":
return '%s was last seen %s ago: *%s %s*' % \ return '%s was last seen %s ago: *%s %s*' % \
(inp, reltime, inp, last_seen[2][8:-1]) (inp, reltime, inp, last_seen[2][8:-1])
else: else:
return '%s was last seen %s ago saying: %s' % \ return '%s was last seen %s ago saying: %s' % \
(inp, reltime, last_seen[2]) (inp, reltime, last_seen[2])
else: else:
return "I've never seen %s" % inp return "I've never seen %s" % inp

View File

@ -26,7 +26,7 @@ def snopes(inp):
status = status.group(0).strip() status = status.group(0).strip()
else: # new-style statuses else: # new-style statuses
status = "Status: %s." % re.search(r"FALSE|TRUE|MIXTURE|UNDETERMINED", status = "Status: %s." % re.search(r"FALSE|TRUE|MIXTURE|UNDETERMINED",
snopes_text).group(0).title() snopes_text).group(0).title()
claim = re.sub(r"[\s\xa0]+", " ", claim) # compress whitespace claim = re.sub(r"[\s\xa0]+", " ", claim) # compress whitespace
status = re.sub(r"[\s\xa0]+", " ", status) status = re.sub(r"[\s\xa0]+", " ", status)

View File

@ -16,7 +16,7 @@ def login(user, password):
user = http.quote(user) user = http.quote(user)
password = http.quote(password) password = http.quote(password)
http.get("http://forums.somethingawful.com/account.php", cookies=True, http.get("http://forums.somethingawful.com/account.php", cookies=True,
post_data="action=login&username=%s&password=%s" % (user, password)) post_data="action=login&username=%s&password=%s" % (user, password))
@hook.api_key('somethingawful') @hook.api_key('somethingawful')
@ -49,8 +49,8 @@ def forum_link(inp, api_key=None):
num_posts = int(num_posts[0].rsplit('=', 1)[1]) num_posts = int(num_posts[0].rsplit('=', 1)[1])
return '\x02%s\x02 > \x02%s\x02 by \x02%s\x02, %s post%s' % ( return '\x02%s\x02 > \x02%s\x02 by \x02%s\x02, %s post%s' % (
forum_title, thread_title, poster, num_posts, forum_title, thread_title, poster, num_posts,
's' if num_posts > 1 else '') 's' if num_posts > 1 else '')
forum_abbrevs = { forum_abbrevs = {

View File

@ -1,5 +1,3 @@
import random
from util import hook, http from util import hook, http

View File

@ -19,7 +19,8 @@ def suggest(inp, inp_unstripped=''):
else: else:
num = 0 num = 0
page = http.get('http://google.com/complete/search', output='json', client='hp', q=inp) page = http.get('http://google.com/complete/search',
output='json', client='hp', q=inp)
page_json = page.split('(', 1)[1][:-1] page_json = page.split('(', 1)[1][:-1]
suggestions = json.loads(page_json)[1] suggestions = json.loads(page_json)[1]
if not suggestions: if not suggestions:

View File

@ -20,7 +20,9 @@ def munge(inp, munge_count=0):
break break
return inp return inp
class PaginatingWinnower(object): class PaginatingWinnower(object):
def __init__(self): def __init__(self):
self.lock = threading.Lock() self.lock = threading.Lock()
self.last_input = [] self.last_input = []
@ -48,7 +50,8 @@ class PaginatingWinnower(object):
if inp in inputs: if inp in inputs:
inputs.remove(inp) inputs.remove(inp)
else: else:
inputs.remove(random.choice([inp for inp in inputs if inp in self.recent])) inputs.remove(
random.choice([inp for inp in inputs if inp in self.recent]))
else: else:
if ordered: if ordered:
inputs.pop() inputs.pop()
@ -61,6 +64,7 @@ class PaginatingWinnower(object):
winnow = PaginatingWinnower().winnow winnow = PaginatingWinnower().winnow
def add_tag(db, chan, nick, subject): def add_tag(db, chan, nick, subject):
match = db.execute('select * from tag where lower(nick)=lower(?) and' match = db.execute('select * from tag where lower(nick)=lower(?) and'
' chan=? and lower(subject)=lower(?)', ' chan=? and lower(subject)=lower(?)',
@ -95,7 +99,6 @@ def get_tag_counts_by_chan(db, chan):
tags.sort(key=lambda x: x[1], reverse=True) tags.sort(key=lambda x: x[1], reverse=True)
if not tags: if not tags:
return 'no tags in %s' % chan return 'no tags in %s' % chan
ret = '%s tags: ' % chan
return winnow(['%s (%d)' % row for row in tags], ordered=True) return winnow(['%s (%d)' % row for row in tags], ordered=True)
@ -105,7 +108,7 @@ def get_tags_by_nick(db, chan, nick):
" order by lower(subject)", (nick, chan)).fetchall() " order by lower(subject)", (nick, chan)).fetchall()
if tags: if tags:
return 'tags for "%s": ' % munge(nick, 1) + winnow([ return 'tags for "%s": ' % munge(nick, 1) + winnow([
tag[0] for tag in tags]) tag[0] for tag in tags])
else: else:
return '' return ''
@ -151,6 +154,7 @@ def tag(inp, chan='', db=None):
else: else:
return tag.__doc__ return tag.__doc__
@hook.command @hook.command
def untag(inp, chan='', db=None): def untag(inp, chan='', db=None):
'.untag <nick> <tag> -- unmarks <nick> as <tag> {related: .tag, .tags, .tagged}' '.untag <nick> <tag> -- unmarks <nick> as <tag> {related: .tag, .tags, .tagged}'
@ -163,6 +167,7 @@ def untag(inp, chan='', db=None):
else: else:
return untag.__doc__ return untag.__doc__
@hook.command @hook.command
def tags(inp, chan='', db=None): def tags(inp, chan='', db=None):
'.tags <nick>/list -- get list of tags for <nick>, or a list of tags {related: .tag, .untag, .tagged}' '.tags <nick>/list -- get list of tags for <nick>, or a list of tags {related: .tag, .untag, .tagged}'
@ -182,6 +187,7 @@ def tagged(inp, chan='', db=None):
return get_nicks_by_tagset(db, chan, inp) return get_nicks_by_tagset(db, chan, inp)
def distance(lat1, lon1, lat2, lon2): def distance(lat1, lon1, lat2, lon2):
deg_to_rad = math.pi / 180 deg_to_rad = math.pi / 180
lat1 *= deg_to_rad lat1 *= deg_to_rad
@ -189,17 +195,18 @@ def distance(lat1, lon1, lat2, lon2):
lon1 *= deg_to_rad lon1 *= deg_to_rad
lon2 *= deg_to_rad lon2 *= deg_to_rad
R = 6371 # km R = 6371 # km
d = math.acos(math.sin(lat1)*math.sin(lat2) + d = math.acos(math.sin(lat1) * math.sin(lat2) +
math.cos(lat1)*math.cos(lat2) * math.cos(lat1) * math.cos(lat2) *
math.cos(lon2-lon1)) * R math.cos(lon2 - lon1)) * R
return d return d
@hook.command(autohelp=False) @hook.command(autohelp=False)
def near(inp, nick='', chan='', db=None): def near(inp, nick='', chan='', db=None):
try: try:
loc = db.execute("select lat, lon from location where chan=? and nick=lower(?)", (chan, nick)).fetchone() loc = db.execute("select lat, lon from location where chan=? and nick=lower(?)",
(chan, nick)).fetchone()
except db.OperationError: except db.OperationError:
loc = None loc = None
@ -210,10 +217,9 @@ def near(inp, nick='', chan='', db=None):
db.create_function('distance', 4, distance) db.create_function('distance', 4, distance)
nearby = db.execute("select nick, distance(lat, lon, ?, ?) as dist from location where chan=?" nearby = db.execute("select nick, distance(lat, lon, ?, ?) as dist from location where chan=?"
" and nick != lower(?) order by dist limit 20", (lat, lon, chan, nick)).fetchall() " and nick != lower(?) order by dist limit 20", (lat, lon, chan, nick)).fetchall()
out = '(km) ' out = '(km) '
last_dist = 10
while nearby and len(out) < 200: while nearby and len(out) < 200:
nick, dist = nearby.pop(0) nick, dist = nearby.pop(0)
out += '%s:%.0f ' % (munge(nick, 1), dist) out += '%s:%.0f ' % (munge(nick, 1), dist)

View File

@ -9,8 +9,8 @@ from util import hook, timesince
def db_init(db): def db_init(db):
"check to see that our db has the tell table and return a dbection." "check to see that our db has the tell table and return a dbection."
db.execute("create table if not exists tell" db.execute("create table if not exists tell"
"(user_to, user_from, message, chan, time," "(user_to, user_from, message, chan, time,"
"primary key(user_to, message))") "primary key(user_to, message))")
db.commit() db.commit()
return db return db
@ -18,8 +18,8 @@ def db_init(db):
def get_tells(db, user_to): def get_tells(db, user_to):
return db.execute("select user_from, message, time, chan from tell where" return db.execute("select user_from, message, time, chan from tell where"
" user_to=lower(?) order by time", " user_to=lower(?) order by time",
(user_to.lower(),)).fetchall() (user_to.lower(),)).fetchall()
@hook.singlethread @hook.singlethread
@ -42,7 +42,7 @@ def tellinput(paraml, input=None, db=None, bot=None):
reply += " (+%d more, .showtells to view)" % (len(tells) - 1) reply += " (+%d more, .showtells to view)" % (len(tells) - 1)
db.execute("delete from tell where user_to=lower(?) and message=?", db.execute("delete from tell where user_to=lower(?) and message=?",
(input.nick, message)) (input.nick, message))
db.commit() db.commit()
input.notice(reply) input.notice(reply)
@ -65,7 +65,7 @@ def showtells(inp, nick='', chan='', notice=None, db=None):
notice("%s said %s ago in %s: %s" % (user_from, past, chan, message)) notice("%s said %s ago in %s: %s" % (user_from, past, chan, message))
db.execute("delete from tell where user_to=lower(?)", db.execute("delete from tell where user_to=lower(?)",
(nick,)) (nick,))
db.commit() db.commit()
@ -91,13 +91,13 @@ def tell(inp, nick='', chan='', db=None):
db_init(db) db_init(db)
if db.execute("select count() from tell where user_to=?", if db.execute("select count() from tell where user_to=?",
(user_to,)).fetchone()[0] >= 5: (user_to,)).fetchone()[0] >= 5:
return "That person has too many things queued." return "That person has too many things queued."
try: try:
db.execute("insert into tell(user_to, user_from, message, chan," db.execute("insert into tell(user_to, user_from, message, chan,"
"time) values(?,?,?,?,?)", (user_to, user_from, message, "time) values(?,?,?,?,?)", (user_to, user_from, message,
chan, time.time())) chan, time.time()))
db.commit() db.commit()
except db.IntegrityError: except db.IntegrityError:
return "Message has already been queued." return "Message has already been queued."

View File

@ -40,13 +40,14 @@ def unescape(text):
def goog_trans(text, slang, tlang): def goog_trans(text, slang, tlang):
url = 'https://www.googleapis.com/language/translate/v2' url = 'https://www.googleapis.com/language/translate/v2'
parsed = http.get_json(url, key=api_key, q=text, source=slang, target=tlang) parsed = http.get_json(
url, key=api_key, q=text, source=slang, target=tlang)
if not 200 <= parsed['responseStatus'] < 300: if not 200 <= parsed['responseStatus'] < 300:
raise IOError('error with the translation server: %d: %s' % ( raise IOError('error with the translation server: %d: %s' % (
parsed['responseStatus'], parsed['responseDetails'])) parsed['responseStatus'], parsed['responseDetails']))
if not slang: if not slang:
return unescape('(%(detectedSourceLanguage)s) %(translatedText)s' % return unescape('(%(detectedSourceLanguage)s) %(translatedText)s' %
(parsed['responseData']['data']['translations'][0])) (parsed['responseData']['data']['translations'][0]))
return unescape('%(translatedText)s' % parsed['responseData']['data']['translations'][0]) return unescape('%(translatedText)s' % parsed['responseData']['data']['translations'][0])
@ -66,8 +67,8 @@ def match_language(fragment):
@hook.command @hook.command
def translate(inp, bot=None): def translate(inp, bot=None):
'.translate [source language [target language]] <sentence> -- translates' \ '.translate [source language [target language]] <sentence> -- translates' \
' <sentence> from source language (default autodetect) to target' \ ' <sentence> from source language (default autodetect) to target' \
' language (default English) using Google Translate' ' language (default English) using Google Translate'
if not hasapikey(bot): if not hasapikey(bot):
return None return None
@ -141,6 +142,7 @@ def babelext(inp, bot=None):
return out return out
def hasapikey(bot): def hasapikey(bot):
api_key = bot.config.get("api_keys", {}).get("googletranslate", None) api_key = bot.config.get("api_keys", {}).get("googletranslate", None)
return api_key return api_key

View File

@ -5,7 +5,6 @@ modified by rmmh 2010, 2013
import datetime import datetime
from lxml import etree
from util import hook, http, timesince from util import hook, http, timesince
@ -31,7 +30,8 @@ def get_episodes_for_series(seriesname):
series_id = series_id[0] series_id = series_id[0]
try: try:
series = http.get_xml(base_url + '%s/series/%s/all/en.xml' % (api_key, series_id)) series = http.get_xml(base_url + '%s/series/%s/all/en.xml' %
(api_key, series_id))
except http.URLError: except http.URLError:
res["error"] = "error contacting thetvdb.com" res["error"] = "error contacting thetvdb.com"
return res return res
@ -97,12 +97,13 @@ def tv_next(inp):
(episode_air_date, airdate, episode_desc) = ep_info (episode_air_date, airdate, episode_desc) = ep_info
if airdate > today: if airdate > today:
next_eps = ['%s (%s) (%s)' % (episode_air_date, timesince.timeuntil(datetime.datetime.strptime(episode_air_date, "%Y-%m-%d")), episode_desc)] next_eps = ['%s (%s) (%s)' % (episode_air_date, timesince.timeuntil(
datetime.datetime.strptime(episode_air_date, "%Y-%m-%d")), episode_desc)]
elif airdate == today: elif airdate == today:
next_eps = ['Today (%s)' % episode_desc] + next_eps next_eps = ['Today (%s)' % episode_desc] + next_eps
else: else:
#we're iterating in reverse order with newest episodes last # we're iterating in reverse order with newest episodes last
#so, as soon as we're past today, break out of loop # so, as soon as we're past today, break out of loop
break break
if not next_eps: if not next_eps:
@ -140,8 +141,8 @@ def tv_last(inp):
(episode_air_date, airdate, episode_desc) = ep_info (episode_air_date, airdate, episode_desc) = ep_info
if airdate < today: if airdate < today:
#iterating in reverse order, so the first episode encountered # iterating in reverse order, so the first episode encountered
#before today was the most recently aired # before today was the most recently aired
prev_ep = '%s (%s)' % (episode_air_date, episode_desc) prev_ep = '%s (%s)' % (episode_air_date, episode_desc)
break break

View File

@ -5,14 +5,15 @@ from urllib import quote
from util import hook, http from util import hook, http
@hook.api_key('twitter') @hook.api_key('twitter')
@hook.command @hook.command
def twitter(inp, api_key=None): def twitter(inp, api_key=None):
".twitter <user>/<user> <n>/<id>/#<search>/#<search> <n> -- " \ ".twitter <user>/<user> <n>/<id>/#<search>/#<search> <n> -- " \
"get <user>'s last/<n>th tweet/get tweet <id>/do <search>/get <n>th <search> result" "get <user>'s last/<n>th tweet/get tweet <id>/do <search>/get <n>th <search> result"
if not isinstance(api_key, dict) or any(key not in api_key for key in if not isinstance(api_key, dict) or any(key not in api_key for key in
('consumer', 'consumer_secret', 'access', 'access_secret')): ('consumer', 'consumer_secret', 'access', 'access_secret')):
return "error: api keys not set" return "error: api keys not set"
getting_id = False getting_id = False
@ -44,13 +45,13 @@ def twitter(inp, api_key=None):
tweet = http.get_json(request_url, oauth=True, oauth_keys=api_key) tweet = http.get_json(request_url, oauth=True, oauth_keys=api_key)
except http.HTTPError, e: except http.HTTPError, e:
errors = {400: 'bad request (ratelimited?)', errors = {400: 'bad request (ratelimited?)',
401: 'unauthorized', 401: 'unauthorized',
403: 'forbidden', 403: 'forbidden',
404: 'invalid user/id', 404: 'invalid user/id',
500: 'twitter is broken', 500: 'twitter is broken',
502: 'twitter is down ("getting upgraded")', 502: 'twitter is down ("getting upgraded")',
503: 'twitter is overloaded (lol, RoR)', 503: 'twitter is overloaded (lol, RoR)',
410: 'twitter shut off api v1.' } 410: 'twitter shut off api v1.'}
if e.code == 404: if e.code == 404:
return 'error: invalid ' + ['username', 'tweet id'][getting_id] return 'error: invalid ' + ['username', 'tweet id'][getting_id]
if e.code in errors: if e.code in errors:
@ -75,11 +76,13 @@ def twitter(inp, api_key=None):
screen_name = tweet["user"]["screen_name"] screen_name = tweet["user"]["screen_name"]
time = tweet["created_at"] time = tweet["created_at"]
time = strftime('%Y-%m-%d %H:%M:%S', strptime(time, '%a %b %d %H:%M:%S +0000 %Y')) time = strftime('%Y-%m-%d %H:%M:%S',
strptime(time, '%a %b %d %H:%M:%S +0000 %Y'))
return "%s \x02%s\x02: %s" % (time, screen_name, text) return "%s \x02%s\x02: %s" % (time, screen_name, text)
@hook.api_key('twitter') @hook.api_key('twitter')
@hook.regex(r'https?://twitter.com/(#!/)?([_0-9a-zA-Z]+)/status/(\d+)') @hook.regex(r'https?://twitter.com/(#!/)?([_0-9a-zA-Z]+)/status/(\d+)')
def show_tweet(match, api_key=None): def show_tweet(match, api_key=None):
return twitter(match.group(3),api_key) return twitter(match.group(3), api_key)

View File

@ -1,5 +1,4 @@
import math import math
import re
import time import time
from util import hook, urlnorm, timesince from util import hook, urlnorm, timesince
@ -12,22 +11,21 @@ ignored_urls = [urlnorm.normalize("http://google.com")]
def db_init(db): def db_init(db):
db.execute("create table if not exists urlhistory" db.execute("create table if not exists urlhistory"
"(chan, url, nick, time)") "(chan, url, nick, time)")
db.commit() db.commit()
def insert_history(db, chan, url, nick): def insert_history(db, chan, url, nick):
now = time.time()
db.execute("insert into urlhistory(chan, url, nick, time) " db.execute("insert into urlhistory(chan, url, nick, time) "
"values(?,?,?,?)", (chan, url, nick, time.time())) "values(?,?,?,?)", (chan, url, nick, time.time()))
db.commit() db.commit()
def get_history(db, chan, url): def get_history(db, chan, url):
db.execute("delete from urlhistory where time < ?", db.execute("delete from urlhistory where time < ?",
(time.time() - expiration_period,)) (time.time() - expiration_period,))
return db.execute("select nick, time from urlhistory where " return db.execute("select nick, time from urlhistory where "
"chan=? and url=? order by time desc", (chan, url)).fetchall() "chan=? and url=? order by time desc", (chan, url)).fetchall()
def nicklist(nicks): def nicklist(nicks):
@ -60,7 +58,7 @@ def format_reply(history):
last = "last linked by %s %s ago" % (last_nick, last_time) last = "last linked by %s %s ago" % (last_nick, last_time)
return "that url has been posted %s in the past %s by %s (%s)." % (ordinal, return "that url has been posted %s in the past %s by %s (%s)." % (ordinal,
hour_span, nicklist(history), last) hour_span, nicklist(history), last)
@hook.regex(r'([a-zA-Z]+://|www\.)[^ ]+') @hook.regex(r'([a-zA-Z]+://|www\.)[^ ]+')

View File

@ -22,7 +22,7 @@ def _hook_add(func, add, name=''):
n_args -= 1 n_args -= 1
if n_args != 1: if n_args != 1:
err = '%ss must take 1 non-keyword argument (%s)' % (name, err = '%ss must take 1 non-keyword argument (%s)' % (name,
func.__name__) func.__name__)
raise ValueError(err) raise ValueError(err)
args = [] args = []
@ -41,7 +41,7 @@ def _hook_add(func, add, name=''):
def sieve(func): def sieve(func):
if func.func_code.co_argcount != 5: if func.func_code.co_argcount != 5:
raise ValueError( raise ValueError(
'sieves must take 5 arguments: (bot, input, func, type, args)') 'sieves must take 5 arguments: (bot, input, func, type, args)')
_hook_add(func, ['sieve', (func,)]) _hook_add(func, ['sieve', (func,)])
return func return func

View File

@ -10,7 +10,7 @@ import urllib
import urllib2 import urllib2
import urlparse import urlparse
from hashlib import sha1 from hashlib import sha1
from urllib import quote, quote_plus as _quote_plus from urllib import quote, quote_plus as _quote_plus
from urllib2 import HTTPError, URLError from urllib2 import HTTPError, URLError
@ -69,14 +69,16 @@ def open(url, query_params=None, user_agent=None, referer=None, post_data=None,
nonce = oauth_nonce() nonce = oauth_nonce()
timestamp = oauth_timestamp() timestamp = oauth_timestamp()
api_url, req_data = string.split(url, "?") api_url, req_data = string.split(url, "?")
unsigned_request = oauth_unsigned_request(nonce, timestamp, req_data, oauth_keys['consumer'], oauth_keys['access']) unsigned_request = oauth_unsigned_request(
nonce, timestamp, req_data, oauth_keys['consumer'], oauth_keys['access'])
signature = oauth_sign_request("GET", api_url, req_data, unsigned_request, oauth_keys['consumer_secret'], oauth_keys['access_secret'])
signature = oauth_sign_request("GET", api_url, req_data, unsigned_request, oauth_keys[
header = oauth_build_header(nonce, signature, timestamp, oauth_keys['consumer'], oauth_keys['access']) 'consumer_secret'], oauth_keys['access_secret'])
header = oauth_build_header(
nonce, signature, timestamp, oauth_keys['consumer'], oauth_keys['access'])
request.add_header('Authorization', header) request.add_header('Authorization', header)
if cookies: if cookies:
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(jar)) opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(jar))
else: else:
@ -91,7 +93,7 @@ def prepare_url(url, queries):
query = dict(urlparse.parse_qsl(query)) query = dict(urlparse.parse_qsl(query))
query.update(queries) query.update(queries)
query = urllib.urlencode(dict((to_utf8(key), to_utf8(value)) query = urllib.urlencode(dict((to_utf8(key), to_utf8(value))
for key, value in query.iteritems())) for key, value in query.iteritems()))
url = urlparse.urlunsplit((scheme, netloc, path, query, fragment)) url = urlparse.urlunsplit((scheme, netloc, path, query, fragment))
@ -108,48 +110,53 @@ def to_utf8(s):
def quote_plus(s): def quote_plus(s):
return _quote_plus(to_utf8(s)) return _quote_plus(to_utf8(s))
def oauth_nonce(): def oauth_nonce():
return ''.join([str(random.randint(0, 9)) for i in range(8)]) return ''.join([str(random.randint(0, 9)) for i in range(8)])
def oauth_timestamp(): def oauth_timestamp():
return str(int(time.time())) return str(int(time.time()))
def oauth_unsigned_request(nonce, timestamp, req, consumer, token):
d = { 'oauth_consumer_key':consumer,
'oauth_nonce':nonce,
'oauth_signature_method':'HMAC-SHA1',
'oauth_timestamp':timestamp,
'oauth_token':token,
'oauth_version':'1.0' }
k,v = string.split(req, "=") def oauth_unsigned_request(nonce, timestamp, req, consumer, token):
d = {'oauth_consumer_key': consumer,
'oauth_nonce': nonce,
'oauth_signature_method': 'HMAC-SHA1',
'oauth_timestamp': timestamp,
'oauth_token': token,
'oauth_version': '1.0'}
k, v = string.split(req, "=")
d[k] = v d[k] = v
unsigned_req = '' unsigned_req = ''
for x in sorted(d, key=lambda key: key): for x in sorted(d, key=lambda key: key):
unsigned_req += x + "=" + d[x] + "&" unsigned_req += x + "=" + d[x] + "&"
unsigned_req = quote(unsigned_req[:-1]) unsigned_req = quote(unsigned_req[:-1])
return unsigned_req return unsigned_req
def oauth_build_header(nonce, signature, timestamp, consumer, token):
d = { 'oauth_consumer_key':consumer,
'oauth_nonce':nonce,
'oauth_signature':signature,
'oauth_signature_method':'HMAC-SHA1',
'oauth_timestamp':timestamp,
'oauth_token':token,
'oauth_version':'1.0' }
header='OAuth ' def oauth_build_header(nonce, signature, timestamp, consumer, token):
d = {'oauth_consumer_key': consumer,
'oauth_nonce': nonce,
'oauth_signature': signature,
'oauth_signature_method': 'HMAC-SHA1',
'oauth_timestamp': timestamp,
'oauth_token': token,
'oauth_version': '1.0'}
header = 'OAuth '
for x in sorted(d, key=lambda key: key): for x in sorted(d, key=lambda key: key):
header += x + '="' + d[x] + '", ' header += x + '="' + d[x] + '", '
return header[:-1] return header[:-1]
def oauth_sign_request(method, url, params, unsigned_request, consumer_secret, token_secret): def oauth_sign_request(method, url, params, unsigned_request, consumer_secret, token_secret):
key = consumer_secret + "&" + token_secret key = consumer_secret + "&" + token_secret
@ -158,9 +165,10 @@ def oauth_sign_request(method, url, params, unsigned_request, consumer_secret, t
hash = hmac.new(key, base, sha1) hash = hmac.new(key, base, sha1)
signature = quote(binascii.b2a_base64(hash.digest())[:-1]) signature = quote(binascii.b2a_base64(hash.digest())[:-1])
return signature return signature
def unescape(s): def unescape(s):
if not s.strip(): if not s.strip():
return s return s

View File

@ -22,4 +22,4 @@ def validate(inp):
errorcount = info['x-w3c-validator-errors'] errorcount = info['x-w3c-validator-errors']
warningcount = info['x-w3c-validator-warnings'] warningcount = info['x-w3c-validator-warnings']
return "%s was found to be %s with %s errors and %s warnings." \ return "%s was found to be %s with %s errors and %s warnings." \
" see: %s" % (inp, status, errorcount, warningcount, url) " see: %s" % (inp, status, errorcount, warningcount, url)

View File

@ -1,23 +1,21 @@
"weather, thanks to wunderground" "weather, thanks to wunderground"
import math
from util import hook, http from util import hook, http
@hook.api_key('wunderground') @hook.api_key('wunderground')
@hook.command(autohelp=False) @hook.command(autohelp=False)
def weather(inp, chan='', nick='', reply=None, db=None, api_key=None): def weather(inp, chan='', nick='', reply=None, db=None, api_key=None):
".weather <location> [dontsave] -- gets weather data from Wunderground "\ ".weather <location> [dontsave] -- gets weather data from Wunderground "\
"http://wunderground.com/weather/api" "http://wunderground.com/weather/api"
if not api_key: if not api_key:
return None return None
# this database is used by other plugins interested in user's locations, # this database is used by other plugins interested in user's locations,
# like .near in tag.py # like .near in tag.py
db.execute("create table if not exists location(chan, nick, loc, lat, lon, primary key(chan, nick))") db.execute(
"create table if not exists location(chan, nick, loc, lat, lon, primary key(chan, nick))")
loc = inp loc = inp
@ -25,10 +23,10 @@ def weather(inp, chan='', nick='', reply=None, db=None, api_key=None):
if dontsave: if dontsave:
loc = loc[:-9].strip().lower() loc = loc[:-9].strip().lower()
if not loc: # blank line if not loc: # blank line
loc = db.execute("select loc from location where chan=? and nick=lower(?)", loc = db.execute(
(chan, nick)).fetchone() "select loc from location where chan=? and nick=lower(?)",
(chan, nick)).fetchone()
if not loc: if not loc:
try: try:
# grab from old-style weather database # grab from old-style weather database
@ -104,10 +102,10 @@ def weather(inp, chan='', nick='', reply=None, db=None, api_key=None):
info['l_c'] = sf['low']['celsius'] info['l_c'] = sf['low']['celsius']
info['humid'] = obs['relative_humidity'] info['humid'] = obs['relative_humidity']
info['wind'] = 'Wind: {mph}mph/{kph}kph' \ info['wind'] = 'Wind: {mph}mph/{kph}kph' \
.format(mph=obs['wind_mph'], kph=obs['wind_kph']) .format(mph=obs['wind_mph'], kph=obs['wind_kph'])
reply('{city}: {weather}, {t_f}F/{t_c}C' \ reply('{city}: {weather}, {t_f}F/{t_c}C'
'(H:{h_f}F/{h_c}C L:{l_f}F/{l_c}C)' \ '(H:{h_f}F/{h_c}C L:{l_f}F/{l_c}C)'
', Humidity: {humid}, {wind}'.format(**info)) ', Humidity: {humid}, {wind}'.format(**info))
lat = float(obs['display_location']['latitude']) lat = float(obs['display_location']['latitude'])
lon = float(obs['display_location']['longitude']) lon = float(obs['display_location']['longitude'])
@ -116,5 +114,3 @@ def weather(inp, chan='', nick='', reply=None, db=None, api_key=None):
db.execute("insert or replace into location(chan, nick, loc, lat, lon) " db.execute("insert or replace into location(chan, nick, loc, lat, lon) "
"values (?, ?, ?, ?,?)", (chan, nick.lower(), inp, lat, lon)) "values (?, ?, ?, ?,?)", (chan, nick.lower(), inp, lat, lon))
db.commit() db.commit()

View File

@ -16,7 +16,7 @@ paren_re = re.compile('\s*\(.*\)$')
@hook.command @hook.command
def wiki(inp): def wiki(inp):
'''.w/.wiki <phrase> -- gets first sentence of wikipedia ''' \ '''.w/.wiki <phrase> -- gets first sentence of wikipedia ''' \
'''article on <phrase>''' '''article on <phrase>'''
x = http.get_xml(search_url, search=inp) x = http.get_xml(search_url, search=inp)
@ -31,7 +31,7 @@ def wiki(inp):
def extract(item): def extract(item):
return [item.find(ns + x).text for x in return [item.find(ns + x).text for x in
('Text', 'Description', 'Url')] ('Text', 'Description', 'Url')]
title, desc, url = extract(items[0]) title, desc, url = extract(items[0])

View File

@ -1,6 +1,7 @@
from util import hook, http from util import hook, http
from random import choice from random import choice
@hook.api_key('yahoo') @hook.api_key('yahoo')
@hook.command @hook.command
def answer(inp, api_key=None): def answer(inp, api_key=None):
@ -9,10 +10,10 @@ def answer(inp, api_key=None):
url = "http://answers.yahooapis.com/AnswersService/V1/questionSearch" url = "http://answers.yahooapis.com/AnswersService/V1/questionSearch"
result = http.get_json(url, result = http.get_json(url,
query=inp, query=inp,
search_in="question", search_in="question",
output="json", output="json",
appid=api_key) appid=api_key)
questions = result.get("all", {}).get("questions", []) questions = result.get("all", {}).get("questions", [])
answered = filter(lambda x: x.get("ChosenAnswer", ""), questions) answered = filter(lambda x: x.get("ChosenAnswer", ""), questions)
@ -25,4 +26,3 @@ def answer(inp, api_key=None):
response = "%s -- %s" % (link, answer) response = "%s -- %s" % (link, answer)
return " ".join(response.split()) return " ".join(response.split())

View File

@ -39,17 +39,17 @@ def get_video_description(vid_id):
if 'rating' in j: if 'rating' in j:
out += ' - rated \x02%.2f/5.0\x02 (%d)' % (j['rating'], out += ' - rated \x02%.2f/5.0\x02 (%d)' % (j['rating'],
j['ratingCount']) j['ratingCount'])
# The use of str.decode() prevents UnicodeDecodeError with some locales # The use of str.decode() prevents UnicodeDecodeError with some locales
# See http://stackoverflow.com/questions/4082645/ # See http://stackoverflow.com/questions/4082645/
if 'viewCount' in j: if 'viewCount' in j:
out += ' - \x02%s\x02 views' % locale.format('%d', out += ' - \x02%s\x02 views' % locale.format('%d',
j['viewCount'], 1).decode(locale.getlocale()[1]) j['viewCount'], 1).decode(locale.getlocale()[1])
upload_time = time.strptime(j['uploaded'], "%Y-%m-%dT%H:%M:%S.000Z") upload_time = time.strptime(j['uploaded'], "%Y-%m-%dT%H:%M:%S.000Z")
out += ' - \x02%s\x02 on \x02%s\x02' % (j['uploader'], out += ' - \x02%s\x02 on \x02%s\x02' % (j['uploader'],
time.strftime("%Y.%m.%d", upload_time)) time.strftime("%Y.%m.%d", upload_time))
if 'contentRating' in j: if 'contentRating' in j:
out += ' - \x034NSFW\x02' out += ' - \x034NSFW\x02'