Fixed formatting.

This commit is contained in:
Fletcher Boyd 2013-09-04 18:30:04 +08:00
parent 146ae3c279
commit 4069dd21a3
89 changed files with 615 additions and 496 deletions

View file

@ -24,5 +24,4 @@ def config():
print 'error: malformed config', e
bot._config_mtime = 0
bot._config_mtime = 0

View file

@ -6,7 +6,7 @@ threaddbs = {}
def get_db_connection(conn, name=''):
"returns an sqlite3 connection to a persistent database"
"""returns an sqlite3 connection to a persistent database"""
if not name:
name = '{}.db'.format(conn.name)

View file

@ -28,7 +28,7 @@ def censor(text):
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):
self.ibuffer = ""
@ -95,15 +95,16 @@ class crlf_tcp(object):
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):
self.ignore_cert_errors = ignore_cert_errors
crlf_tcp.__init__(self, host, port, timeout)
def create_socket(self):
return wrap_socket(crlf_tcp.create_socket(self), server_side=False,
cert_reqs=CERT_NONE if self.ignore_cert_errors else
CERT_REQUIRED)
cert_reqs=CERT_NONE if self.ignore_cert_errors else
CERT_REQUIRED)
def recv_from_socket(self, nbytes):
return self.socket.read(nbytes)
@ -117,6 +118,7 @@ class crlf_ssl_tcp(crlf_tcp):
raise
return crlf_tcp.handle_receive_exception(self, error, last_timestamp)
irc_prefix_rem = re.compile(r'(.*?) (.*?) (.*)').match
irc_noprefix_rem = re.compile(r'()(.*?) (.*)').match
irc_netmask_rem = re.compile(r':?([^!@]*)!?([^@]*)@?(.*)').match
@ -124,7 +126,8 @@ irc_param_ref = re.compile(r'(?:^|(?<= ))(:.*|[^ ]+)').findall
class IRC(object):
"handles the IRC protocol"
"""handles the IRC protocol"""
def __init__(self, name, server, nick, port=6667, channels=[], conf={}):
self.name = name
self.channels = channels
@ -150,8 +153,8 @@ class IRC(object):
self.set_pass(self.conf.get('server_password'))
self.set_nick(self.nick)
self.cmd("USER",
[conf.get('user', 'cloudbot'), "3", "*", conf.get('realname',
'CloudBot - http://git.io/cloudbot')])
[conf.get('user', 'cloudbot'), "3", "*", conf.get('realname',
'CloudBot - http://git.io/cloudbot')])
def parse_loop(self):
while True:
@ -175,9 +178,9 @@ class IRC(object):
if paramlist[-1].startswith(':'):
paramlist[-1] = paramlist[-1][1:]
lastparam = paramlist[-1]
# put the parsed message in the response queue
# put the parsed message in the response queue
self.out.put([msg, prefix, command, params, nick, user, host,
mask, paramlist, lastparam])
mask, paramlist, lastparam])
# if the server pings us, pong them back
if command == "PING":
self.cmd("PONG", paramlist)

View file

@ -7,7 +7,7 @@ thread.stack_size(1024 * 512) # reduce vm size
class Input(dict):
def __init__(self, conn, raw, prefix, command, params,
nick, user, host, mask, paraml, msg):
nick, user, host, mask, paraml, msg):
chan = paraml[0].lower()
if chan == conn.nick.lower(): # is a PM
@ -32,10 +32,10 @@ class Input(dict):
conn.cmd('NOTICE', [nick, msg])
dict.__init__(self, conn=conn, raw=raw, prefix=prefix, command=command,
params=params, nick=nick, user=user, host=host, mask=mask,
paraml=paraml, msg=msg, server=conn.server, chan=chan,
notice=notice, say=say, reply=reply, pm=pm, bot=bot,
me=me, lastparam=paraml[-1])
params=params, nick=nick, user=user, host=host, mask=mask,
paraml=paraml, msg=msg, server=conn.server, chan=chan,
notice=notice, say=say, reply=reply, pm=pm, bot=bot,
me=me, lastparam=paraml[-1])
# make dict keys accessible as attributes
def __getattr__(self, key):
@ -77,7 +77,8 @@ def do_sieve(sieve, bot, input, func, type, args):
class Handler(object):
'''Runs plugins in their own threads (ensures order)'''
"""Runs plugins in their own threads (ensures order)"""
def __init__(self, func):
self.func = func
self.input_queue = Queue.Queue()
@ -103,6 +104,7 @@ class Handler(object):
run(self.func, input)
except:
import traceback
traceback.print_exc()
def stop(self):
@ -115,11 +117,10 @@ class Handler(object):
def dispatch(input, kind, func, args, autohelp=False):
for sieve, in bot.plugs['sieve']:
input = do_sieve(sieve, bot, input, func, kind, args)
if input == None:
if input is None:
return
if autohelp and args.get('autohelp', True) and not input.inp \
and func.__doc__ is not None:
if not (not autohelp or not args.get('autohelp', True) or input.inp or not (func.__doc__ is not None)):
input.notice(input.conn.conf["command_prefix"] + func.__doc__)
return
@ -169,7 +170,7 @@ def main(conn, out):
if isinstance(command, list): # multiple potential matches
input = Input(conn, *out)
input.notice("Did you mean %s or %s?" %
(', '.join(command[:-1]), command[-1]))
(', '.join(command[:-1]), command[-1]))
elif command in bot.commands:
input = Input(conn, *out)
input.trigger = trigger

View file

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

View file

@ -28,7 +28,7 @@ with open("plugins/data/flirts.txt") as f:
@hook.command
def slap(inp, me=None, nick=None, conn=None, notice=None):
"slap <user> -- Makes the bot slap <user>."
"""slap <user> -- Makes the bot slap <user>."""
target = inp.strip()
if " " in target:
@ -48,7 +48,7 @@ def slap(inp, me=None, nick=None, conn=None, notice=None):
@hook.command
def lart(inp, me=None, nick=None, conn=None, notice=None):
"lart <user> -- LARTs <user>."
"""lart <user> -- LARTs <user>."""
target = inp.strip()
if " " in target:
@ -68,7 +68,7 @@ def lart(inp, me=None, nick=None, conn=None, notice=None):
@hook.command
def kill(inp, me=None, nick=None, conn=None, notice=None):
"kill <user> -- Makes the bot kill <user>."
"""kill <user> -- Makes the bot kill <user>."""
target = inp.strip()
if " " in target:
@ -88,7 +88,7 @@ def kill(inp, me=None, nick=None, conn=None, notice=None):
@hook.command
def insult(inp, nick=None, me=None, conn=None, notice=None):
"insult <user> -- Makes the bot insult <user>."
"""insult <user> -- Makes the bot insult <user>."""
target = inp.strip()
if " " in target:
@ -105,8 +105,8 @@ def insult(inp, nick=None, me=None, conn=None, notice=None):
@hook.command
def flirt(inp, nick=None, me=None, conn=None, notice=None):
"flirt <user> -- Make the bot flirt with <user>."
def flirt(inp, me=None, conn=None, notice=None):
"""flirt <user> -- Make the bot flirt with <user>."""
target = inp.strip()
if " " in target:

View file

@ -3,7 +3,7 @@ from util import http, hook
@hook.command(autohelp=False)
def bitcoin(inp, say=None):
"bitcoin -- gets current exchange rate for bitcoins from mtgox"
"""bitcoin -- gets current exchange rate for bitcoins from mtgox"""
data = http.get_json("https://data.mtgox.com/api/2/BTCUSD/money/ticker")
data = data['data']
ticker = {

View file

@ -14,7 +14,7 @@ MAX_STEPS = 1000000
@hook.command('brainfuck')
@hook.command
def bf(inp):
"bf <prog> -- Executes <prog> as Brainfuck code."
"""bf <prog> -- Executes <prog> as Brainfuck code."""
program = re.sub('[^][<>+-.,]', '', inp)
@ -45,10 +45,10 @@ def bf(inp):
# the main program loop:
while ip < len(program):
c = program[ip]
if c == '+':
memory[mp] = memory[mp] + 1 % 256
if c == '+':
memory[mp] += 1 % 256
elif c == '-':
memory[mp] = memory[mp] - 1 % 256
memory[mp] -= 1 % 256
elif c == '>':
mp += 1
if mp > rightmost:
@ -57,7 +57,7 @@ def bf(inp):
# no restriction on memory growth!
memory.extend([0] * BUFFER_SIZE)
elif c == '<':
mp = mp - 1 % len(memory)
mp -= 1 % len(memory)
elif c == '.':
output += chr(memory[mp])
if len(output) > 500:

View file

@ -6,8 +6,8 @@ from util import hook
@hook.command
def choose(inp):
"choose <choice1>, [choice2], [choice3], [choice4], ... -- " \
"Randomly picks one of the given choices."
"""choose <choice1>, [choice2], [choice3] ... [choiceN]
Randomly picks one of the given choices."""
c = re.findall(r'([^,]+)', inp)
if len(c) == 1:

View file

@ -15,7 +15,7 @@ always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'
'abcdefghijklmnopqrstuvwxyz'
'0123456789' '_.-')
headers = {'X-Moz': 'prefetch', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
headers = {'X-Moz': 'prefetch', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0.1)Gecko/20100101 Firefox/7.0',
'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'Referer': 'http://www.cleverbot.com',
'Pragma': 'no-cache', 'Cache-Control': 'no-cache, no-cache', 'Accept-Language': 'en-us;q=0.8,en;q=0.5'}
@ -28,6 +28,7 @@ keylist = ['stimulus', 'start', 'sessionid', 'vText8', 'vText7', 'vText6',
MsgList = list()
def quote(s, safe='/'): # quote('abc def') -> 'abc%20def'
s = s.encode('utf-8')
s = s.decode('utf-8')
@ -46,6 +47,7 @@ def quote(s, safe='/'): # quote('abc def') -> 'abc%20def'
print "res= " + ''.join(res)
return ''.join(res)
def encode(keylist, arglist):
text = str()
for i in range(len(keylist)):
@ -55,6 +57,7 @@ def encode(keylist, arglist):
text = text[1:]
return text
def Send():
data = encode(keylist, arglist)
digest_txt = data[9:29]
@ -67,6 +70,7 @@ def Send():
reply = f.read()
return reply
def parseAnswers(text):
d = dict()
keys = ['text', 'sessionid', 'logurl', 'vText8', 'vText7', 'vText6',
@ -81,6 +85,7 @@ def parseAnswers(text):
i += 1
return d
def ask(inp):
arglist[keylist.index('stimulus')] = inp
if MsgList:
@ -99,10 +104,12 @@ def ask(inp):
MsgList.append(text)
return text
@hook.command("cb")
def cleverbot(inp, reply=None):
reply(ask(inp))
''' # TODO: add in command to control extra verbose per channel
@hook.event('PRIVMSG')
def cbevent(inp, reply=None):

View file

@ -4,7 +4,7 @@ import random
@hook.command(autohelp=False)
def coin(inp, me=None):
"coin [amount] -- Flips [amount] of coins."
"""coin [amount] -- Flips [amount] of coins."""
if inp:
try:
@ -21,5 +21,5 @@ def coin(inp, me=None):
else:
heads = int(random.normalvariate(.5 * amount, (.75 * amount) ** .5))
tails = amount - heads
me("flips %i coins and gets " \
"%i heads and %i tails." % (amount, heads, tails))
me("flips %i coins and gets "
"%i heads and %i tails." % (amount, heads, tails))

View file

@ -1,8 +1,8 @@
'''
"""
Plugin which (de)cyphers a string
Doesn't cypher non-alphanumeric strings yet.
by instanceoftom
'''
"""
from util import hook
chars = "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ "
@ -11,7 +11,7 @@ len_chars = len(chars)
@hook.command
def cypher(inp):
"cypher <pass> <string> -- Cyphers <string> with <password>."
"""cypher <pass> <string> -- Cyphers <string> with <password>."""
passwd = inp.split(" ")[0]
len_passwd = len(passwd)
@ -38,7 +38,7 @@ def cypher(inp):
@hook.command
def decypher(inp):
"decypher <pass> <string> -- Decyphers <string> with <password>."
"""decypher <pass> <string> -- Decyphers <string> with <password>."""
passwd = inp.split(" ")[0]
len_passwd = len(passwd)
@ -52,7 +52,7 @@ def decypher(inp):
except ValueError:
continue
passwd_index = passwd_index - 1
passwd_index -= 1
reversed_message = inp[::-1]
out = ""

View file

@ -15,7 +15,7 @@ split_re = re.compile(r'([\d+-]*)d?(F|\d*)', re.I)
def nrolls(count, n):
"roll an n-sided die count times"
"""roll an n-sided die count times"""
if n == "F":
return [random.randint(-1, 1) for x in xrange(min(count, 100))]
if n < 2: # it's a coin
@ -28,16 +28,16 @@ def nrolls(count, n):
return [random.randint(1, n) for x in xrange(count)]
else: # fake it
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.regex(valid_diceroll, re.I)
@hook.command
def dice(inp):
"dice <diceroll> -- Simulates dicerolls. Example of <diceroll>:" \
" 'dice 2d20-d5+4 roll 2'. D20s, subtract 1D5, add 4"
"""dice <diceroll> -- Simulates dicerolls. Example of <diceroll>:
'dice 2d20-d5+4 roll 2'. D20s, subtract 1D5, add 4"""
try: # if inp is a re.match object...
(inp, desc) = inp.groups()
@ -84,6 +84,6 @@ def dice(inp):
return "Thanks for overflowing a float, jerk >:["
if desc:
return "%s: %d (%s)" % (desc.strip(), total, ", ".join(rolls))
return "%s: %d (%s)" % (desc.strip(), total, ", ".join(rolls))
else:
return "%d (%s)" % (total, ", ".join(rolls))

View file

@ -7,7 +7,7 @@ from util import http
@hook.command('dictionary')
@hook.command
def define(inp):
"define <word> -- Fetches definition of <word>."
"""define <word> -- Fetches definition of <word>."""
url = 'http://ninjawords.com/'
@ -67,7 +67,7 @@ def define(inp):
@hook.command('e')
@hook.command
def etymology(inp):
"etymology <word> -- Retrieves the etymology of <word>."
"""etymology <word> -- Retrieves the etymology of <word>."""
url = 'http://www.etymonline.com/index.php'

View file

@ -1,15 +1,18 @@
from util import hook, http
@hook.command
def domainr(inp):
"""domainr <domain> - Use domain.nr's API to search for a domain, and similar domains."""
try:
data = http.get_json('http://domai.nr/api/json/search?q=' + inp);
data = http.get_json('http://domai.nr/api/json/search?q=' + inp)
except (http.URLError, http.HTTPError) as e:
return "Unable to get data for some reason. Try again later."
if data['query'] == "":
return "An error occurrred: {status} - {message}".format(**data['error'])
domains = "";
domains = ""
for domain in data['results']:
domains += ("\x034" if domain['availability'] == "taken" else ("\x033" if domain['availability'] == "available" else "\x031")) + domain['domain'] + "\x0f" + domain['path'] + ", "
domains += ("\x034" if domain['availability'] == "taken" else (
"\x033" if domain['availability'] == "available" else "\x031")) + domain['domain'] + "\x0f" + domain[
'path'] + ", "
return "Domains: " + domains

View file

@ -5,7 +5,7 @@ from util import hook, http
@hook.command
def down(inp):
"down <url> -- Checks if the site at <url> is up or down."
"""down <url> -- Checks if the site at <url> is up or down."""
if 'http://' not in inp:
inp = 'http://' + inp

View file

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

View file

@ -1,5 +1,5 @@
from util import hook, text
import random
from util import hook, text
color_codes = {
"<r>": "\x02\x0305",
@ -9,14 +9,13 @@ color_codes = {
with open("plugins/data/8ball_responses.txt") as f:
responses = [line.strip() for line in
f.readlines()if not line.startswith("//")]
f.readlines() if not line.startswith("//")]
@hook.command('8ball')
def eightball(input, me=None):
"8ball <question> -- The all knowing magic eight ball, " \
"in electronic form. Ask and it shall be answered!"
"""8ball <question> -- The all knowing magic eight ball,
in electronic form. Ask and it shall be answered!"""
# here we use voodoo magic to tell the future
magic = text.multiword_replace(random.choice(responses), color_codes)
me("shakes the magic 8 ball... %s" % magic)

View file

@ -3,7 +3,7 @@ from util import hook, http, web
@hook.command(autohelp=False)
def fact(inp, say=False, nick=False):
"fact -- Gets a random fact from OMGFACTS."
"""fact -- Gets a random fact from OMGFACTS."""
attempts = 0

View file

@ -1,19 +1,18 @@
# Written by Scaevolus 2010
from util import hook, http, text, execute
import string
import sqlite3
import re
re_lineends = re.compile(r'[\r\n]*')
# some simple "shortcodes" for formatting purposes
shortcodes = {
'[b]': '\x02',
'[/b]': '\x02',
'[u]': '\x1F',
'[/u]': '\x1F',
'[i]': '\x16',
'[/i]': '\x16'}
'[b]': '\x02',
'[/b]': '\x02',
'[u]': '\x1F',
'[/u]': '\x1F',
'[i]': '\x16',
'[/i]': '\x16'}
def db_init(db):
@ -23,7 +22,6 @@ def db_init(db):
def get_memory(db, word):
row = db.execute("select data from mem where word=lower(?)",
[word]).fetchone()
if row:
@ -34,9 +32,9 @@ def get_memory(db, word):
@hook.command("r", permissions=["addfactoid"])
@hook.command(permissions=["addfactoid"])
def remember(inp, nick='', db=None, say=None, input=None, notice=None):
"remember <word> [+]<data> -- Remembers <data> with <word>. Add +"
" to <data> to append."
def remember(inp, nick='', db=None, notice=None):
"""remember <word> [+]<data> -- Remembers <data> with <word>. Add +
to <data> to append."""
db_init(db)
append = False
@ -67,17 +65,17 @@ def remember(inp, nick='', db=None, say=None, input=None, notice=None):
notice("Appending \x02%s\x02 to \x02%s\x02" % (new_data, old_data))
else:
notice('Remembering \x02%s\x02 for \x02%s\x02. Type ?%s to see it.'
% (data, word, word))
% (data, word, word))
notice('Previous data was \x02%s\x02' % old_data)
else:
notice('Remembering \x02%s\x02 for \x02%s\x02. Type ?%s to see it.'
% (data, word, word))
% (data, word, word))
@hook.command("f", permissions=["delfactoid"])
@hook.command(permissions=["delfactoid"])
def forget(inp, db=None, input=None, notice=None):
"forget <word> -- Forgets a remembered <word>."
def forget(inp, db=None, notice=None):
"""forget <word> -- Forgets a remembered <word>."""
db_init(db)
data = get_memory(db, inp)
@ -95,7 +93,7 @@ def forget(inp, db=None, input=None, notice=None):
@hook.command
def info(inp, notice=None, db=None):
"info <factoid> -- Shows the source of a factoid."
"""info <factoid> -- Shows the source of a factoid."""
db_init(db)
@ -134,7 +132,8 @@ def factoid(inp, say=None, db=None, bot=None, me=None, conn=None, input=None):
if data.startswith("<py>"):
code = data[4:].strip()
variables = 'input="""%s"""; nick="%s"; chan="%s"; bot_nick="%s";' % (arguments.replace('"', '\\"'),
input.nick, input.chan, input.conn.nick)
input.nick, input.chan,
input.conn.nick)
result = execute.eval_py(variables + code)
else:
result = data

View file

@ -7,7 +7,7 @@ api_url = "http://api.fishbans.com/stats/{}/"
@hook.command("bans")
@hook.command
def fishbans(inp):
"fishbans <user> -- Gets information on <user>s minecraft bans from fishbans"
"""fishbans <user> -- Gets information on <user>s minecraft bans from fishbans"""
user = inp.strip()
try:
@ -15,7 +15,7 @@ def fishbans(inp):
except (http.HTTPError, http.URLError) as e:
return "Could not fetch ban data from the Fishbans API: {}".format(e)
if request["success"] == False:
if not request["success"]:
return "Could not fetch ban data for {}.".format(user)
user_url = "http://fishbans.com/u/{}/".format(user)
@ -27,7 +27,7 @@ def fishbans(inp):
@hook.command
def bancount(inp):
"bancount <user> -- Gets a count of <user>s minecraft bans from fishbans"
"""bancount <user> -- Gets a count of <user>s minecraft bans from fishbans"""
user = inp.strip()
try:
@ -35,7 +35,7 @@ def bancount(inp):
except (http.HTTPError, http.URLError) as e:
return "Could not fetch ban data from the Fishbans API: {}".format(e)
if request["success"] == False:
if not request["success"]:
return "Could not fetch ban data for {}.".format(user)
user_url = "http://fishbans.com/u/{}/".format(user)

View file

@ -18,7 +18,7 @@ refresh_cache()
@hook.command(autohelp=False)
def fml(inp, reply=None):
"fml -- Gets a random quote from fmyfife.com."
"""fml -- Gets a random quote from fmyfife.com."""
# grab the last item in the fml cache and remove it
id, text = fml_cache.pop()

View file

@ -8,5 +8,5 @@ with open("plugins/data/fortunes.txt") as f:
@hook.command(autohelp=False)
def fortune(inp):
"fortune -- Fortune cookies on demand."
"""fortune -- Fortune cookies on demand."""
return random.choice(fortunes)

View file

@ -1,9 +1,10 @@
from util import hook, http
@hook.command("math")
@hook.command
def calc(inp):
"calc <term> -- Calculate <term> with Google Calc."
"""calc <term> -- Calculate <term> with Google Calc."""
soup = http.get_soup('http://www.google.com/search', q=inp)

View file

@ -18,7 +18,7 @@ else:
string_io = StringIO(download)
geoip_file = gzip.GzipFile(fileobj=string_io, mode='rb')
output = open(os.path.abspath("./plugins/data/GeoLiteCity.dat"),'wb')
output = open(os.path.abspath("./plugins/data/GeoLiteCity.dat"), 'wb')
output.write(geoip_file.read())
output.close()
@ -27,7 +27,7 @@ else:
@hook.command
def geoip(inp):
"geoip <host/ip> -- Gets the location of <host/ip>"
"""geoip <host/ip> -- Gets the location of <host/ip>"""
try:
record = geo.record_by_name(inp)

View file

@ -4,58 +4,59 @@ import urllib2
shortcuts = {"cloudbot": "ClouDev/CloudBot"}
def truncate(msg):
nmsg = msg.split(" ")
out = None
x = 0
for i in nmsg:
if x <= 7:
if out:
out = out + " " + nmsg[x]
else:
out = nmsg[x]
x = x + 1
if x <= 7:
if out:
out = out + " " + nmsg[x]
else:
out = nmsg[x]
x += 1
if x <= 7:
return out
return out
else:
return out + "..."
return out + "..."
@hook.command
def ghissues(inp):
"""ghissues username/repo [number] - Get specified issue summary, or open issue count """
args = inp.split(" ")
try:
if args[0] in shortcuts:
repo = shortcuts[args[0]]
else:
repo = args[0]
url = "https://api.github.com/repos/%s/issues" % repo
if args[0] in shortcuts:
repo = shortcuts[args[0]]
else:
repo = args[0]
url = "https://api.github.com/repos/%s/issues" % repo
except IndexError:
return "Invalid syntax. .github issues username/repo [number]"
return "Invalid syntax. .github issues username/repo [number]"
try:
url = url + "/%s" % args[1]
number = True
url += "/%s" % args[1]
number = True
except IndexError:
number = False
number = False
try:
data = json.loads(http.open(url).read())
print url
if not number:
try:
data = data[0]
except IndexError:
print data
return "Repo has no open issues"
data = json.loads(http.open(url).read())
print url
if not number:
try:
data = data[0]
except IndexError:
print data
return "Repo has no open issues"
except ValueError:
return "Invalid data returned. Check arguments (.github issues username/repo [number]"
fmt = "Issue: #%s (%s) by %s: %s | %s %s" # (number, state, user.login, title, truncate(body), gitio.gitio(data.url))
fmt1 = "Issue: #%s (%s) by %s: %s %s" # (number, state, user.login, title, gitio.gitio(data.url))
return "Invalid data returned. Check arguments (.github issues username/repo [number]"
fmt = "Issue: #%s (%s) by %s: %s | %s %s" # (number, state, user.login, title, truncate(body), gitio.gitio(data.url))
fmt1 = "Issue: #%s (%s) by %s: %s %s" # (number, state, user.login, title, gitio.gitio(data.url))
number = data["number"]
if data["state"] == "open":
state = u"\x033\x02OPEN\x02\x0f"
closedby = None
state = u"\x033\x02OPEN\x02\x0f"
else:
state = u"\x034\x02CLOSED\x02\x0f by %s" % data["closed_by"]["login"]
state = u"\x034\x02CLOSED\x02\x0f by %s" % data["closed_by"]["login"]
user = data["user"]["login"]
title = data["title"]
summary = truncate(data["body"])
@ -63,15 +64,15 @@ def ghissues(inp):
if "Failed to get URL" in gitiourl:
gitiourl = gitio(data["html_url"] + " " + repo.split("/")[1] + number)
if summary == "":
return fmt1 % (number, state, user, title, gitiourl)
return fmt1 % (number, state, user, title, gitiourl)
else:
return fmt % (number, state, user, title, summary, gitiourl)
return fmt % (number, state, user, title, summary, gitiourl)
@hook.command
def gitio(inp):
"gitio <url> [code] -- Shorten Github URLs with git.io. [code] is" \
" a optional custom short code."
"""gitio <url> [code] -- Shorten Github URLs with git.io. [code] is
a optional custom short code."""
split = inp.split(" ")
url = split[0]

View file

@ -13,28 +13,28 @@ def api_get(kind, query):
@hook.command('gis')
@hook.command
def googleimage(inp):
"gis <query> -- Returns first Google Image result for <query>."
"""gis <query> -- Returns first Google Image result for <query>."""
parsed = api_get('images', inp)
if not 200 <= parsed['responseStatus'] < 300:
raise IOError('error searching for images: %d: %s' % ( \
parsed['responseStatus'], ''))
raise IOError('error searching for images: %d: %s' % (
parsed['responseStatus'], ''))
if not parsed['responseData']['results']:
return 'no images found'
return random.choice(parsed['responseData']['results'][:10]) \
['unescapedUrl']
['unescapedUrl']
@hook.command('search')
@hook.command('g')
@hook.command
def google(inp):
"google <query> -- Returns first google search result for <query>."
"""google <query> -- Returns first google search result for <query>."""
parsed = api_get('web', inp)
if not 200 <= parsed['responseStatus'] < 300:
raise IOError('error searching for pages: %d: %s' % (
parsed['responseStatus'], ''))
parsed['responseStatus'], ''))
if not parsed['responseData']['results']:
return 'No results found.'

View file

@ -1,7 +1,7 @@
'''
"""
A Google API key is required and retrieved from the bot config file.
Since December 1, 2011, the Google Translate API is a paid service only.
'''
"""
import htmlentitydefs
import re
@ -50,12 +50,12 @@ def goog_trans(api_key, text, slang, tlang):
else:
parsed = http.get_json(url, key=api_key, q=text, target=tlang, format="text")
#if not 200 <= parsed['responseStatus'] < 300:
# raise IOError('error with the translation server: %d: %s' % (
# parsed['responseStatus'], parsed['responseDetails']))
#if not 200 <= parsed['responseStatus'] < 300:
# raise IOError('error with the translation server: %d: %s' % (
# parsed['responseStatus'], parsed['responseDetails']))
if not slang:
return unescape('(%(detectedSourceLanguage)s) %(translatedText)s' %
(parsed['data']['translations'][0]))
(parsed['data']['translations'][0]))
return unescape('%(translatedText)s' % parsed['data']['translations'][0])
@ -73,10 +73,10 @@ def match_language(fragment):
@hook.command
def translate(inp, bot=None, say=None):
'translate [source language [target language]] <sentence> -- translates' \
' <sentence> from source language (default autodetect) to target' \
' language (default English) using Google Translate'
def translate(inp, bot=None):
"""translate [source language [target language]] <sentence> -- translates
<sentence> from source language (default autodetect) to target
language (default English) using Google Translate"""
api_key = bot.config.get("api_keys", {}).get("googletranslate", None)
if not api_key:
@ -102,6 +102,7 @@ def translate(inp, bot=None, say=None):
except IOError, e:
return e
lang_pairs = [
("no", "Norwegian"),
("it", "Italian"),

View file

@ -4,6 +4,6 @@ from util import hook
@hook.command
def hash(inp):
"hash <text> -- Returns hashes of <text>."
"""hash <text> -- Returns hashes of <text>."""
return ', '.join(x + ": " + getattr(hashlib, x)(inp).hexdigest()
for x in ['md5', 'sha1', 'sha256'])
for x in ['md5', 'sha1', 'sha256'])

View file

@ -3,8 +3,8 @@ from util import hook
@hook.command(autohelp=False)
def help(inp, say=None, notice=None, input=None, conn=None, bot=None):
"help -- Gives a list of commands/help for a command."
def help(inp, notice=None, input=None, conn=None, bot=None):
"""help -- Gives a list of commands/help for a command."""
funcs = {}
disabled = bot.config.get('disabled_plugins', [])
@ -37,7 +37,7 @@ def help(inp, say=None, notice=None, input=None, conn=None, bot=None):
notice("Commands I recognise: " + out[0][1:])
if out[1]:
notice(out[1][1:])
notice("For detailed help, do '%shelp <example>' where <example> "\
notice("For detailed help, do '%shelp <example>' where <example> "
"is the name of the command you want help for." % conn.conf["command_prefix"])
else:

View file

@ -6,7 +6,7 @@ db_ready = False
def db_init(db):
"check to see that our db has the horoscope table and return a connection."
"""check to see that our db has the horoscope table and return a connection."""
db.execute("create table if not exists horoscope(nick primary key, sign)")
db.commit()
db_ready = True
@ -14,7 +14,7 @@ def db_init(db):
@hook.command(autohelp=False)
def horoscope(inp, db=None, notice=None, nick=None):
"horoscope <sign> -- Get your horoscope."
"""horoscope <sign> -- Get your horoscope."""
if not db_ready:
db_init(db)

View file

@ -16,11 +16,13 @@ def hulu_url(match):
@hook.command('hulu')
def hulu_search(inp):
"""hulu <search> - Search Hulu"""
result = http.get_soup("http://m.hulu.com/search?dp_identifier=hulu&{}&items_per_page=1&page=1".format(urlencode({'query': inp})))
result = http.get_soup(
"http://m.hulu.com/search?dp_identifier=hulu&{}&items_per_page=1&page=1".format(urlencode({'query': inp})))
data = result.find('results').find('videos').find('video')
showname = data.find('show').find('name').text
title = data.find('title').text
duration = timeformat.timeformat(int(float(data.find('duration').text)))
description = data.find('description').text
rating = data.find('content-rating').text
return "{}: {} - {} - {} ({}) {}".format(showname, title, description, duration, rating, "http://www.hulu.com/watch/" + str(data.find('id').text))
return "{}: {} - {} - {} ({}) {}".format(showname, title, description, duration, rating,
"http://www.hulu.com/watch/" + str(data.find('id').text))

View file

@ -31,7 +31,7 @@ def ignore_sieve(bot, input, func, type, args):
@hook.command(autohelp=False)
def ignored(inp, notice=None, bot=None):
"ignored -- Lists ignored channels/users."
"""ignored -- Lists ignored channels/users."""
ignorelist = bot.config["plugins"]["ignore"]["ignored"]
if ignorelist:
notice("Ignored channels/users are: %s" % ", ".join(ignorelist))
@ -42,7 +42,7 @@ def ignored(inp, notice=None, bot=None):
@hook.command(permissions=["ignore"])
def ignore(inp, notice=None, bot=None, config=None):
"ignore <channel|nick|host> -- Makes the bot ignore <channel|user>."
"""ignore <channel|nick|host> -- Makes the bot ignore <channel|user>."""
target = inp.lower()
ignorelist = bot.config["plugins"]["ignore"]["ignored"]
if target in ignorelist:
@ -57,8 +57,8 @@ def ignore(inp, notice=None, bot=None, config=None):
@hook.command(permissions=["ignore"])
def unignore(inp, notice=None, bot=None, config=None):
"unignore <channel|user> -- Makes the bot listen to"\
" <channel|user>."
"""unignore <channel|user> -- Makes the bot listen to
<channel|user>."""
target = inp.lower()
ignorelist = bot.config["plugins"]["ignore"]["ignored"]
if target in ignorelist:

View file

@ -9,7 +9,7 @@ imdb_re = (r'(.*:)//(imdb.com|www.imdb.com)(:[0-9]+)?(.*)', re.I)
@hook.command
def imdb(inp):
"imdb <movie> -- Gets information about <movie> from IMDb."
"""imdb <movie> -- Gets information about <movie> from IMDb."""
strip = inp.strip()

View file

@ -1,6 +1,7 @@
from util import hook, http
import re
@hook.command(autohelp=False)
def kernel(inp, reply=None):
contents = http.get("https://www.kernel.org/finger_banner")

View file

@ -6,9 +6,9 @@ api_url = "http://ws.audioscrobbler.com/2.0/?format=json"
@hook.command('l', autohelp=False)
@hook.command(autohelp=False)
def lastfm(inp, nick='', say=None, db=None, bot=None, notice=None):
"lastfm [user] [dontsave] -- Displays the now playing (or last played)" \
" track of LastFM user [user]."
def lastfm(inp, nick='', db=None, bot=None, notice=None):
"""lastfm [user] [dontsave] -- Displays the now playing (or last played)
track of LastFM user [user]."""
api_key = bot.config.get("api_keys", {}).get("lastfm")
if not api_key:
return "error: no api key set"

View file

@ -3,5 +3,5 @@ from util import hook
@hook.command
def length(inp):
"length <message> -- gets the length of <message>"
"""length <message> -- gets the length of <message>"""
return "The length of that message is {} characters.".format(len(inp))

View file

@ -3,8 +3,8 @@ from util import hook, web, http
@hook.command('gfy')
@hook.command
def lmgtfy(inp, bot=None):
"lmgtfy [phrase] - Posts a google link for the specified phrase"
def lmgtfy(inp):
"""lmgtfy [phrase] - Posts a google link for the specified phrase"""
link = "http://lmgtfy.com/?q=%s" % http.quote_plus(inp)

View file

@ -27,11 +27,11 @@ formats = {
}
ctcp_formats = {
'ACTION': '* %(nick)s %(ctcpmsg)s',
'VERSION': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s',
'PING': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s',
'TIME': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s',
'FINGER': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s'
'ACTION': '* %(nick)s %(ctcpmsg)s',
'VERSION': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s',
'PING': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s',
'TIME': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s',
'FINGER': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s'
}
irc_color_re = re.compile(r'(\x03(\d+,\d+|\d)|[\x0f\x02\x16\x1f])')
@ -39,7 +39,7 @@ irc_color_re = re.compile(r'(\x03(\d+,\d+|\d)|[\x0f\x02\x16\x1f])')
def get_log_filename(dir, server, chan):
return os.path.join(dir, 'log', gmtime('%Y'), server, chan,
(gmtime('%%s.%m-%d.log') % chan).lower())
(gmtime('%%s.%m-%d.log') % chan).lower())
def gmtime(format):
@ -64,8 +64,8 @@ def beautify(input):
ctcp += ['']
args['ctcpcmd'], args['ctcpmsg'] = ctcp
format = ctcp_formats.get(args['ctcpcmd'],
'%(nick)s [%(user)s@%(host)s] requested unknown CTCP '
'%(ctcpcmd)s from %(chan)s: %(ctcpmsg)s')
'%(nick)s [%(user)s@%(host)s] requested unknown CTCP '
'%(ctcpcmd)s from %(chan)s: %(ctcpmsg)s')
return format % args
@ -90,7 +90,7 @@ def get_log_fd(dir, server, chan):
@hook.singlethread
@hook.event('*')
def log(paraml, input=None, bot=None):
def log(input=None, bot=None):
timestamp = gmtime(timestamp_format)
fd = get_log_fd(bot.persist_dir, input.server, 'raw')

View file

@ -9,7 +9,8 @@ from util import hook, http
@hook.command('mc')
@hook.command
def metacritic(inp):
"mc [all|movie|tv|album|x360|ps3|wii|pc|ds|3ds|vita] <title> -- Gets rating for <title> from metacritic on the specified medium."
"""mc [all|movie|tv|album|x360|ps3|wii|pc|ds|3ds|vita] <title>
Gets rating for <title> from metacritic on the specified medium."""
# if the results suck, it's metacritic's fault
@ -118,7 +119,7 @@ def metacritic(inp):
link = 'http://metacritic.com' + product_title.find('a').attrib['href']
try:
release = result.find_class('release_date')[0].\
release = result.find_class('release_date')[0]. \
find_class('data')[0].text_content()
# strip extra spaces out of the release date
@ -132,6 +133,6 @@ def metacritic(inp):
score = None
return '[%s] %s - \x02%s/100\x02, %s - %s' % (plat.upper(), name,
score or 'no score',
'release: \x02%s\x02' % release if release else 'unreleased',
link)
score or 'no score',
'release: \x02%s\x02' % release if release else 'unreleased',
link)

View file

@ -4,7 +4,7 @@ import json
@hook.command(autohelp=False)
def mcstatus(inp, say=None):
"mcstatus -- Checks the status of various Mojang (the creators of Minecraft) servers."
"""mcstatus -- Checks the status of various Mojang (the creators of Minecraft) servers."""
try:
request = http.get("http://status.mojang.com/check")
@ -28,7 +28,7 @@ def mcstatus(inp, say=None):
@hook.command("haspaid")
@hook.command
def mcpaid(inp):
"mcpaid <username> -- Checks if <username> has a premium Minecraft account."
"""mcpaid <username> -- Checks if <username> has a premium Minecraft account."""
user = inp.strip()

View file

@ -7,8 +7,8 @@ mc_url = "http://minecraftwiki.net/wiki/"
@hook.command
def mcwiki(inp):
"mcwiki <phrase> -- Gets the first paragraph of" \
" the Minecraft Wiki article on <phrase>."
"""mcwiki <phrase> -- Gets the first paragraph of
the Minecraft Wiki article on <phrase>."""
j = http.get_json(api_url, search=inp)

View file

@ -1,13 +1,14 @@
# Plugin by Infinity - <https://github.com/infinitylabs/UguuBot>
from util import hook, http
import random
from util import hook, http
mlia_cache = []
def refresh_cache():
"gets a page of random MLIAs and puts them into a dictionary "
"""gets a page of random MLIAs and puts them into a dictionary """
url = 'http://mylifeisaverage.com/%s' % random.randint(1, 11000)
soup = http.get_soup(url)

View file

@ -3,5 +3,5 @@ from util import hook, text
@hook.command
def munge(inp):
"munge <text> -- Munges up <text>."
"""munge <text> -- Munges up <text>."""
return text.munge(inp)

View file

@ -1,7 +1,11 @@
# Plugin by Lukeroge
import json
import random
import re
import os
from util import hook
from util.text import get_text_list
import json, random, re, os
TEMPLATE_RE = re.compile(r"\{(.+?)\}")
GEN_DIR = "./plugins/data/name_files/"
@ -10,7 +14,7 @@ GEN_DIR = "./plugins/data/name_files/"
def get_generator(_json):
data = json.loads(_json)
return NameGenerator(data["name"], data["templates"],
data["default_templates"], data["parts"])
data["default_templates"], data["parts"])
class NameGenerator(object):
@ -36,7 +40,7 @@ class NameGenerator(object):
return name
def generate_names(self, amount, template=None):
def generate_names(self, amount):
names = []
for i in xrange(amount):
names.append(self.generate_name())
@ -48,8 +52,8 @@ class NameGenerator(object):
@hook.command(autohelp=False)
def namegen(inp, notice=None):
"namegen [generator] -- Generates some names using the chosen generator. " \
"'namegen list' will display a list of all generators."
"""namegen [generator] -- Generates some names using the chosen generator.
'namegen list' will display a list of all generators."""
# clean up the input
inp = inp.strip().lower()

View file

@ -29,13 +29,14 @@ def newgrounds_url(match):
# get rating
try:
rating_info = soup.find('dd', {'class': 'star-variable'})['title'].split("Stars &ndash;")[0].strip()
rating = u" - rated \x02{}\x02/\x025.0\x02".format(rating_info)
rating = u" - rated \x02{}\x02/\x025.0\x02".format(rating_info)
except:
rating = ""
# get amount of ratings
try:
ratings_info = soup.find('dd', {'class': 'star-variable'})['title'].split("Stars &ndash;")[1].replace("Votes", "").strip()
ratings_info = soup.find('dd', {'class': 'star-variable'})['title'].split("Stars &ndash;")[1].replace("Votes",
"").strip()
numofratings = " ({})".format(ratings_info)
except:
numofratings = ""

View file

@ -15,73 +15,74 @@ def mode_cmd(mode, text, inp, chan, conn, notice):
notice("Attempting to {} {} in {}...".format(text, target, channel))
conn.send("MODE {} {} {}".format(channel, mode, target))
@hook.command(permissions=["op_ban", "op"])
def ban(inp, conn=None, chan=None, notice=None):
"ban [channel] <user> -- Makes the bot ban <user> in [channel]. "\
"If [channel] is blank the bot will ban <user> in "\
"the channel the command was used in."
"""ban [channel] <user> -- Makes the bot ban <user> in [channel].
If [channel] is blank the bot will ban <user> in
the channel the command was used in."""
mode_cmd("+b", "ban", inp, chan, conn, notice)
@hook.command(permissions=["op_ban", "op"])
def unban(inp, conn=None, chan=None, notice=None):
"unban [channel] <user> -- Makes the bot unban <user> in [channel]. "\
"If [channel] is blank the bot will unban <user> in "\
"the channel the command was used in."
"""unban [channel] <user> -- Makes the bot unban <user> in [channel].
If [channel] is blank the bot will unban <user> in
the channel the command was used in."""
mode_cmd("-b", "unban", inp, chan, conn, notice)
@hook.command(permissions=["op_quiet", "op"])
def quiet(inp, conn=None, chan=None, notice=None):
"quiet [channel] <user> -- Makes the bot quiet <user> in [channel]. "\
"If [channel] is blank the bot will quiet <user> in "\
"the channel the command was used in."
"""quiet [channel] <user> -- Makes the bot quiet <user> in [channel].
If [channel] is blank the bot will quiet <user> in
the channel the command was used in."""
mode_cmd("+q", "quiet", inp, chan, conn, notice)
@hook.command(permissions=["op_quiet", "op"])
def unquiet(inp, conn=None, chan=None, notice=None):
"unquiet [channel] <user> -- Makes the bot unquiet <user> in [channel]. "\
"If [channel] is blank the bot will unquiet <user> in "\
"the channel the command was used in."
"""unquiet [channel] <user> -- Makes the bot unquiet <user> in [channel].
If [channel] is blank the bot will unquiet <user> in
the channel the command was used in."""
mode_cmd("-q", "unquiet", inp, chan, conn, notice)
@hook.command(permissions=["op_voice", "op"])
def voice(inp, conn=None, chan=None, notice=None):
"voice [channel] <user> -- Makes the bot voice <user> in [channel]. "\
"If [channel] is blank the bot will voice <user> in "\
"the channel the command was used in."
"""voice [channel] <user> -- Makes the bot voice <user> in [channel].
If [channel] is blank the bot will voice <user> in
the channel the command was used in."""
mode_cmd("+v", "voice", inp, chan, conn, notice)
@hook.command(permissions=["op_voice", "op"])
def devoice(inp, conn=None, chan=None, notice=None):
"devoice [channel] <user> -- Makes the bot devoice <user> in [channel]. "\
"If [channel] is blank the bot will devoice <user> in "\
"the channel the command was used in."
"""devoice [channel] <user> -- Makes the bot devoice <user> in [channel].
If [channel] is blank the bot will devoice <user> in
the channel the command was used in."""
mode_cmd("-v", "devoice", inp, chan, conn, notice)
@hook.command(permissions=["op_op", "op"])
def op(inp, conn=None, chan=None, notice=None):
"op [channel] <user> -- Makes the bot op <user> in [channel]. "\
"If [channel] is blank the bot will op <user> in "\
"the channel the command was used in."
"""op [channel] <user> -- Makes the bot op <user> in [channel].
If [channel] is blank the bot will op <user> in
the channel the command was used in."""
mode_cmd("+o", "op", inp, chan, conn, notice)
@hook.command(permissions=["op_op", "op"])
def deop(inp, conn=None, chan=None, notice=None):
"deop [channel] <user> -- Makes the bot deop <user> in [channel]. "\
"If [channel] is blank the bot will deop <user> in "\
"the channel the command was used in."
"""deop [channel] <user> -- Makes the bot deop <user> in [channel].
If [channel] is blank the bot will deop <user> in
the channel the command was used in."""
mode_cmd("-o", "deop", inp, chan, conn, notice)
@hook.command(permissions=["op_topic", "op"])
def topic(inp, conn=None, chan=None):
"topic [channel] <topic> -- Change the topic of a channel."
"""topic [channel] <topic> -- Change the topic of a channel."""
split = inp.split(" ")
if split[0].startswith("#"):
message = " ".join(split[1:])
@ -95,9 +96,9 @@ def topic(inp, conn=None, chan=None):
@hook.command(permissions=["op_kick", "op"])
def kick(inp, chan=None, conn=None, notice=None):
"kick [channel] <user> [reason] -- Makes the bot kick <user> in [channel] "\
"If [channel] is blank the bot will kick the <user> in "\
"the channel the command was used in."
"""kick [channel] <user> [reason] -- Makes the bot kick <user> in [channel]
If [channel] is blank the bot will kick the <user> in
the channel the command was used in."""
split = inp.split(" ")
if split[0].startswith("#"):
@ -120,9 +121,10 @@ def kick(inp, chan=None, conn=None, notice=None):
notice("Attempting to kick {} from {}...".format(target, channel))
conn.send(out)
@hook.command(permissions=["op_rem", "op"])
def remove(inp, chan=None, conn=None, notice=None):
"remove [channel] [user] -- Force a user to part from a channel."
def remove(inp, chan=None, conn=None):
"""remove [channel] [user] -- Force a user to part from a channel."""
split = inp.split(" ")
if split[0].startswith("#"):
message = " ".join(split[1:])

View file

@ -6,7 +6,8 @@ import random
@hook.command
def password(inp, notice=None):
"password <length> [types] -- Generates a password of <length> (default 10). [types] can include 'alpha', 'no caps', 'numeric', 'symbols' or any combination of the inp, eg. 'numbers symbols'"
"""password <length> [types] -- Generates a password of <length> (default 10).
[types] can include 'alpha', 'no caps', 'numeric', 'symbols' or any combination of the inp, eg. 'numbers symbols'"""
okay = []
# find the length needed for the password
@ -30,7 +31,8 @@ def password(inp, notice=None):
# add symbols
if "symbol" in inp:
sym = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '=', '_', '+', '[', ']', '{', '}', '\\', '|', ';', ':', "'", '.', '>', ',', '<', '/', '?', '`', '~', '"']
sym = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '=', '_', '+', '[', ']', '{', '}', '\\', '|', ';',
':', "'", '.', '>', ',', '<', '/', '?', '`', '~', '"']
okay += okay + sym
# defaults to lowercase alpha password if the okay list is empty

View file

@ -9,7 +9,7 @@ ping_regex = re.compile(r"(\d+.\d+)/(\d+.\d+)/(\d+.\d+)/(\d+.\d+)")
@hook.command
def ping(inp, reply=None):
"ping <host> [count] -- Pings <host> [count] times."
"""ping <host> [count] -- Pings <host> [count] times."""
if os.name == "nt":
return "Sorry, this command is not supported on Windows systems."
@ -39,4 +39,4 @@ def ping(inp, reply=None):
else:
m = re.search(ping_regex, pingcmd)
return "min: %sms, max: %sms, average: %sms, range: %sms, count: %s" \
% (m.group(1), m.group(3), m.group(2), m.group(4), count)
% (m.group(1), m.group(3), m.group(2), m.group(4), count)

View file

@ -1,13 +1,44 @@
# coding=utf-8
from util import hook
import re
import random
potatoes = ['AC Belmont', 'AC Blue Pride', 'AC Brador', 'AC Chaleur', 'AC Domino', 'AC Dubuc', 'AC Glacier Chip', 'AC Maple Gold', 'AC Novachip', 'AC Peregrine Red', 'AC Ptarmigan', 'AC Red Island', 'AC Saguenor', 'AC Stampede Russet', 'AC Sunbury', 'Abeille', 'Abnaki', 'Acadia', 'Acadia Russet', 'Accent', 'Adirondack Blue', 'Adirondack Red', 'Adora', 'Agria', 'All Blue', 'All Red', 'Alpha', 'Alta Russet', 'Alturas Russet', 'Amandine', 'Amisk', 'Andover', 'Anoka', 'Anson', 'Aquilon', 'Arran Consul', 'Asterix', 'Atlantic', 'Austrian Crescent', 'Avalanche', 'Banana', 'Bannock Russet', 'Batoche', 'BeRus', 'Belle De Fonteney', 'Belleisle', 'Bintje', 'Blossom', 'Blue Christie', 'Blue Mac', 'Brigus', 'Brise du Nord', 'Butte', 'Butterfinger', 'Caesar', 'CalWhite', 'CalRed', 'Caribe', 'Carlingford', 'Carlton', 'Carola', 'Cascade', 'Castile', 'Centennial Russet', 'Century Russet', 'Charlotte', 'Cherie', 'Cherokee', 'Cherry Red', 'Chieftain', 'Chipeta', 'Coastal Russet', 'Colorado Rose', 'Concurrent', 'Conestoga', 'Cowhorn', 'Crestone Russet', 'Crispin', 'Cupids', 'Daisy Gold', 'Dakota Pearl', 'Defender', 'Delikat', 'Denali', 'Desiree', 'Divina', 'Dundrod', 'Durango Red', 'Early Rose', 'Elba', 'Envol', 'Epicure', 'Eramosa', 'Estima', 'Eva', 'Fabula', 'Fambo', 'Fremont Russet', 'French Fingerling', 'Frontier Russet', 'Fundy', 'Garnet Chile', 'Gem Russet', 'GemStar Russet', 'Gemchip', 'German Butterball', 'Gigant', 'Goldrush', 'Granola', 'Green Mountain', 'Haida', 'Hertha', 'Hilite Russet', 'Huckleberry', 'Hunter', 'Huron', 'IdaRose', 'Innovator', 'Irish Cobbler', 'Island Sunshine', 'Ivory Crisp', 'Jacqueline Lee', 'Jemseg', 'Kanona', 'Katahdin', 'Kennebec', "Kerr's Pink", 'Keswick', 'Keuka Gold', 'Keystone Russet', 'King Edward VII', 'Kipfel', 'Klamath Russet', 'Krantz', 'LaRatte', 'Lady Rosetta', 'Latona', 'Lemhi Russet', 'Liberator', 'Lili', 'MaineChip', 'Marfona', 'Maris Bard', 'Maris Piper', 'Matilda', 'Mazama', 'McIntyre', 'Michigan Purple', 'Millenium Russet', 'Mirton Pearl', 'Modoc', 'Mondial', 'Monona', 'Morene', 'Morning Gold', 'Mouraska', 'Navan', 'Nicola', 'Nipigon', 'Niska', 'Nooksack', 'NorValley', 'Norchip', 'Nordonna', 'Norgold Russet', 'Norking Russet', 'Norland', 'Norwis', 'Obelix', 'Ozette', 'Peanut', 'Penta', 'Peribonka', 'Peruvian Purple', 'Pike', 'Pink Pearl', 'Prospect', 'Pungo', 'Purple Majesty', 'Purple Viking', 'Ranger Russet', 'Reba', 'Red Cloud', 'Red Gold', 'Red La Soda', 'Red Pontiac', 'Red Ruby', 'Red Thumb', 'Redsen', 'Rocket', 'Rose Finn Apple', 'Rose Gold', 'Roselys', 'Rote Erstling', 'Ruby Crescent', 'Russet Burbank', 'Russet Legend', 'Russet Norkotah', 'Russet Nugget', 'Russian Banana', 'Saginaw Gold', 'Sangre', 'Sant<EFBFBD>', 'Satina', 'Saxon', 'Sebago', 'Shepody', 'Sierra', 'Silverton Russet', 'Simcoe', 'Snowden', 'Spunta', "St. John's", 'Summit Russet', 'Sunrise', 'Superior', 'Symfonia', 'Tolaas', 'Trent', 'True Blue', 'Ulla', 'Umatilla Russet', 'Valisa', 'Van Gogh', 'Viking', 'Wallowa Russet', 'Warba', 'Western Russet', 'White Rose', 'Willamette', 'Winema', 'Yellow Finn', 'Yukon Gold']
potatoes = ['AC Belmont', 'AC Blue Pride', 'AC Brador', 'AC Chaleur', 'AC Domino', 'AC Dubuc', 'AC Glacier Chip',
'AC Maple Gold', 'AC Novachip', 'AC Peregrine Red', 'AC Ptarmigan', 'AC Red Island', 'AC Saguenor',
'AC Stampede Russet', 'AC Sunbury', 'Abeille', 'Abnaki', 'Acadia', 'Acadia Russet', 'Accent',
'Adirondack Blue', 'Adirondack Red', 'Adora', 'Agria', 'All Blue', 'All Red', 'Alpha', 'Alta Russet',
'Alturas Russet', 'Amandine', 'Amisk', 'Andover', 'Anoka', 'Anson', 'Aquilon', 'Arran Consul', 'Asterix',
'Atlantic', 'Austrian Crescent', 'Avalanche', 'Banana', 'Bannock Russet', 'Batoche', 'BeRus',
'Belle De Fonteney', 'Belleisle', 'Bintje', 'Blossom', 'Blue Christie', 'Blue Mac', 'Brigus',
'Brise du Nord', 'Butte', 'Butterfinger', 'Caesar', 'CalWhite', 'CalRed', 'Caribe', 'Carlingford',
'Carlton', 'Carola', 'Cascade', 'Castile', 'Centennial Russet', 'Century Russet', 'Charlotte', 'Cherie',
'Cherokee', 'Cherry Red', 'Chieftain', 'Chipeta', 'Coastal Russet', 'Colorado Rose', 'Concurrent',
'Conestoga', 'Cowhorn', 'Crestone Russet', 'Crispin', 'Cupids', 'Daisy Gold', 'Dakota Pearl', 'Defender',
'Delikat', 'Denali', 'Desiree', 'Divina', 'Dundrod', 'Durango Red', 'Early Rose', 'Elba', 'Envol',
'Epicure', 'Eramosa', 'Estima', 'Eva', 'Fabula', 'Fambo', 'Fremont Russet', 'French Fingerling',
'Frontier Russet', 'Fundy', 'Garnet Chile', 'Gem Russet', 'GemStar Russet', 'Gemchip', 'German Butterball',
'Gigant', 'Goldrush', 'Granola', 'Green Mountain', 'Haida', 'Hertha', 'Hilite Russet', 'Huckleberry',
'Hunter', 'Huron', 'IdaRose', 'Innovator', 'Irish Cobbler', 'Island Sunshine', 'Ivory Crisp',
'Jacqueline Lee', 'Jemseg', 'Kanona', 'Katahdin', 'Kennebec', "Kerr's Pink", 'Keswick', 'Keuka Gold',
'Keystone Russet', 'King Edward VII', 'Kipfel', 'Klamath Russet', 'Krantz', 'LaRatte', 'Lady Rosetta',
'Latona', 'Lemhi Russet', 'Liberator', 'Lili', 'MaineChip', 'Marfona', 'Maris Bard', 'Maris Piper',
'Matilda', 'Mazama', 'McIntyre', 'Michigan Purple', 'Millenium Russet', 'Mirton Pearl', 'Modoc', 'Mondial',
'Monona', 'Morene', 'Morning Gold', 'Mouraska', 'Navan', 'Nicola', 'Nipigon', 'Niska', 'Nooksack',
'NorValley', 'Norchip', 'Nordonna', 'Norgold Russet', 'Norking Russet', 'Norland', 'Norwis', 'Obelix',
'Ozette', 'Peanut', 'Penta', 'Peribonka', 'Peruvian Purple', 'Pike', 'Pink Pearl', 'Prospect', 'Pungo',
'Purple Majesty', 'Purple Viking', 'Ranger Russet', 'Reba', 'Red Cloud', 'Red Gold', 'Red La Soda',
'Red Pontiac', 'Red Ruby', 'Red Thumb', 'Redsen', 'Rocket', 'Rose Finn Apple', 'Rose Gold', 'Roselys',
'Rote Erstling', 'Ruby Crescent', 'Russet Burbank', 'Russet Legend', 'Russet Norkotah', 'Russet Nugget',
'Russian Banana', 'Saginaw Gold', 'Sangre', 'Sant<EFBFBD>', 'Satina', 'Saxon', 'Sebago', 'Shepody', 'Sierra',
'Silverton Russet', 'Simcoe', 'Snowden', 'Spunta', "St. John's", 'Summit Russet', 'Sunrise', 'Superior',
'Symfonia', 'Tolaas', 'Trent', 'True Blue', 'Ulla', 'Umatilla Russet', 'Valisa', 'Van Gogh', 'Viking',
'Wallowa Russet', 'Warba', 'Western Russet', 'White Rose', 'Willamette', 'Winema', 'Yellow Finn',
'Yukon Gold']
@hook.command
def potato(inp, me=None, input=None):
"potato <user> - Makes <user> a tasty little potato."
"""potato <user> - Makes <user> a tasty little potato."""
inp = inp.strip()
if not re.match("^[A-Za-z0-9_|.-\]\[]*$", inp.lower()):
@ -19,4 +50,5 @@ def potato(inp, me=None, input=None):
method = random.choice(['bakes', 'fries', 'boils', 'roasts'])
side_dish = random.choice(['side salad', 'dollop of sour cream', 'piece of chicken', 'bowl of shredded bacon'])
me("%s a %s %s %s potato for %s and serves it with a small %s!" % (method, flavor, size, potato_type, inp, side_dish))
me("%s a %s %s %s potato for %s and serves it with a small %s!" % (
method, flavor, size, potato_type, inp, side_dish))

View file

@ -4,17 +4,15 @@ from util import hook, web, http
@hook.command('qr')
@hook.command
def qrcode(inp, bot=None):
"qrcode [link] returns a link for a QR code."
def qrcode(inp):
"""qrcode [link] returns a link for a QR code."""
args = {
"cht": "qr", # chart type
"chs": "200x200", # dimensions
"chl": inp
"cht": "qr", # chart type
"chs": "200x200", # dimensions
"chl": inp
}
link = http.prepare_url("http://chart.googleapis.com/chart", args)
return web.try_isgd(link)

View file

@ -9,14 +9,14 @@ def format_quote(q, num, n_quotes):
"""Returns a formatted string of a quote"""
ctime, nick, msg = q
return "[%d/%d] <%s> %s" % (num, n_quotes,
nick, msg)
nick, msg)
def create_table_if_not_exists(db):
"""Creates an empty quote table if one does not already exist"""
db.execute("create table if not exists quote"
"(chan, nick, add_nick, msg, time real, deleted default 0, "
"primary key (chan, nick, msg))")
"(chan, nick, add_nick, msg, time real, deleted default 0, "
"primary key (chan, nick, msg))")
db.commit()
@ -49,8 +49,8 @@ def get_quote_num(num, count, name):
if num and num < 0: # Count back if possible
num = count + num + 1 if num + count > -1 else count + 1
if num and num > count: # If there are not enough quotes, raise an error
raise Exception("I only have %d quote%s for %s."\
% (count, ('s', '')[count == 1], name))
raise Exception("I only have %d quote%s for %s."
% (count, ('s', '')[count == 1], name))
if num and num == 0: # If the number is zero, set it to one
num = 1
if not num: # If a number is not given, select a random one
@ -124,8 +124,8 @@ def get_quote_by_chan(db, chan, num=False):
@hook.command('q')
@hook.command
def quote(inp, nick='', chan='', db=None, notice=None):
"quote [#chan] [nick] [#n]/.quote add <nick> <msg> -- Gets " \
"random or [#n]th quote by <nick> or from <#chan>/adds quote."
"""quote [#chan] [nick] [#n]/.quote add <nick> <msg>
Gets random or [#n]th quote by <nick> or from <#chan>/adds quote."""
create_table_if_not_exists(db)
add = re.match(r"add[^\w@]+(\S+?)>?\s+(.*)", inp, re.I)

View file

@ -1,120 +1,130 @@
import urllib
import json
import re
from util import hook
import oauth2 as oauth
import urllib, json
CONSUMER_KEY = "KEY"
CONSUMER_SECRET = "SECRET"
def getdata(inp, types):
consumer = oauth.Consumer(CONSUMER_KEY, CONSUMER_SECRET)
client = oauth.Client(consumer)
response = client.request('http://api.rdio.com/1/', 'POST', urllib.urlencode({'method': 'search', 'query': inp, 'types': types, 'count': '1'}))
data = json.loads(response[1])
return data
consumer = oauth.Consumer(CONSUMER_KEY, CONSUMER_SECRET)
client = oauth.Client(consumer)
response = client.request('http://api.rdio.com/1/', 'POST',
urllib.urlencode({'method': 'search', 'query': inp, 'types': types, 'count': '1'}))
data = json.loads(response[1])
return data
def checkkeys():
if CONSUMER_KEY == "KEY" or CONSUMER_SECRET == "SECRET":
return True
else:
return False
if CONSUMER_KEY == "KEY" or CONSUMER_SECRET == "SECRET":
return True
else:
return False
@hook.command
def rdio(inp):
""" rdio <search term> - alternatives: .rdiot (track), .rdioar (artist), .rdioal (album) """
if checkkeys():
return "This command requires an API key, please enter one in the config"
data = getdata(inp, "Track,Album,Artist")
try:
info = data['result']['results'][0]
except IndexError:
return "No results."
if 'name' in info:
if 'artist' in info and 'album' in info: #Track
name = info['name']
artist = info['artist']
album = info['album']
url = info['shortUrl']
return u"\x02{}\x02 by \x02{}\x02 - {} {}".format(name, artist, album, url)
elif 'artist' in info and not 'album' in info: #Album
name = info['name']
artist = info['artist']
url = info['shortUrl']
return u"\x02{}\x02 by \x02{}\x02 - {}".format(name, artist, url)
else: #Artist
name = info['name']
url = info['shortUrl']
return u"\x02{}\x02 {}".format(name, url)
""" rdio <search term> - alternatives: .rdiot (track), .rdioar (artist), .rdioal (album) """
if checkkeys():
return "This command requires an API key, please enter one in the config"
data = getdata(inp, "Track,Album,Artist")
try:
info = data['result']['results'][0]
except IndexError:
return "No results."
if 'name' in info:
if 'artist' in info and 'album' in info: #Track
name = info['name']
artist = info['artist']
album = info['album']
url = info['shortUrl']
return u"\x02{}\x02 by \x02{}\x02 - {} {}".format(name, artist, album, url)
elif 'artist' in info and not 'album' in info: #Album
name = info['name']
artist = info['artist']
url = info['shortUrl']
return u"\x02{}\x02 by \x02{}\x02 - {}".format(name, artist, url)
else: #Artist
name = info['name']
url = info['shortUrl']
return u"\x02{}\x02 {}".format(name, url)
@hook.command
def rdiot(inp):
""" rdiot <search term> - Search for tracks on rdio """
if checkkeys():
return "This command requires an API key, please enter one in the config"
data = getdata(inp, "Track")
try:
info = data['result']['results'][0]
except IndexError:
return "No results."
name = info['name']
artist = info['artist']
album = info['album']
url = info['shortUrl']
return u"\x02{}\x02 by \x02{}\x02 - {} {}".format(name, artist, album, url)
""" rdiot <search term> - Search for tracks on rdio """
if checkkeys():
return "This command requires an API key, please enter one in the config"
data = getdata(inp, "Track")
try:
info = data['result']['results'][0]
except IndexError:
return "No results."
name = info['name']
artist = info['artist']
album = info['album']
url = info['shortUrl']
return u"\x02{}\x02 by \x02{}\x02 - {} {}".format(name, artist, album, url)
@hook.command
def rdioar(inp):
""" rdioar <search term> - Search for artists on rdio """
if checkkeys():
return "This command requires an API key, please enter one in the config"
data = getdata(inp, "Artist")
try:
info = data['result']['results'][0]
except IndexError:
return "No results."
name = info['name']
url = info['shortUrl']
return u"\x02{}\x02 {}".format(name, url)
""" rdioar <search term> - Search for artists on rdio """
if checkkeys():
return "This command requires an API key, please enter one in the config"
data = getdata(inp, "Artist")
try:
info = data['result']['results'][0]
except IndexError:
return "No results."
name = info['name']
url = info['shortUrl']
return u"\x02{}\x02 {}".format(name, url)
@hook.command
def rdioal(inp):
""" rdioal <search term> - Search for albums on rdio """
if checkkeys():
return "This command requires an API key, please enter one in the config"
data = getdata(inp, "Album")
try:
info = data['result']['results'][0]
except IndexError:
return "No results."
name = info['name']
artist = info['artist']
url = info['shortUrl']
return u"\x02{}\x02 by \x02{}\x02 - {}".format(name, artist, url)
""" rdioal <search term> - Search for albums on rdio """
if checkkeys():
return "This command requires an API key, please enter one in the config"
data = getdata(inp, "Album")
try:
info = data['result']['results'][0]
except IndexError:
return "No results."
name = info['name']
artist = info['artist']
url = info['shortUrl']
return u"\x02{}\x02 by \x02{}\x02 - {}".format(name, artist, url)
import re
import urllib2
rdio_re = (r'(.*:)//(rd.io|www.rdio.com|rdio.com)(:[0-9]+)?(.*)', re.I)
@hook.regex(*rdio_re)
def rdio_url(match):
if checkkeys():
return None
return None
url = match.group(1) + "//" + match.group(2) + match.group(4)
consumer = oauth.Consumer(CONSUMER_KEY, CONSUMER_SECRET)
client = oauth.Client(consumer)
response = client.request('http://api.rdio.com/1/', 'POST', urllib.urlencode({'method': 'getObjectFromUrl', 'url': url}))
response = client.request('http://api.rdio.com/1/', 'POST',
urllib.urlencode({'method': 'getObjectFromUrl', 'url': url}))
data = json.loads(response[1])
info = data['result']
if 'name' in info:
if 'artist' in info and 'album' in info: #Track
name = info['name']
artist = info['artist']
album = info['album']
return u"Rdio track: \x02{}\x02 by \x02{}\x02 - {}".format(name, artist, album)
elif 'artist' in info and not 'album' in info: #Album
name = info['name']
artist = info['artist']
return u"Rdio album: \x02{}\x02 by \x02{}\x02".format(name, artist)
else: #Artist
name = info['name']
return u"Rdio artist: \x02{}\x02".format(name)
if 'artist' in info and 'album' in info: #Track
name = info['name']
artist = info['artist']
album = info['album']
return u"Rdio track: \x02{}\x02 by \x02{}\x02 - {}".format(name, artist, album)
elif 'artist' in info and not 'album' in info: #Album
name = info['name']
artist = info['artist']
return u"Rdio album: \x02{}\x02 by \x02{}\x02".format(name, artist)
else: #Artist
name = info['name']
return u"Rdio artist: \x02{}\x02".format(name)

View file

@ -3,9 +3,9 @@ import re
reddit_re = (r'.*((www\.)?reddit\.com/r[^ ]+)', re.I)
@hook.regex(*reddit_re)
def reddit_url(match):
thread = http.get_html(match.group(0))
title = thread.xpath('//title/text()')[0]
@ -16,4 +16,4 @@ def reddit_url(match):
comments = thread.xpath("//div[@id='siteTable']//a[@class='comments']/text()")[0]
return '\x02%s\x02 - posted by \x02%s\x02 %s ago - %s upvotes, %s downvotes - %s' % (
title, author, timeago, upvotes, downvotes, comments)
title, author, timeago, upvotes, downvotes, comments)

View file

@ -7,7 +7,7 @@ movie_reviews_url = api_root + 'movies/%s/reviews.json'
@hook.command('rt')
def rottentomatoes(inp, bot=None):
'rt <title> -- gets ratings for <title> from Rotten Tomatoes'
"""rt <title> -- gets ratings for <title> from Rotten Tomatoes"""
api_key = bot.config.get("api_keys", {}).get("rottentomatoes", None)
if not api_key:

View file

@ -4,7 +4,7 @@ from util import hook, http, web, text
@hook.command("feed")
@hook.command
def rss(inp, say=None):
"rss <feed> -- Gets the first three items from the RSS feed <feed>."
"""rss <feed> -- Gets the first three items from the RSS feed <feed>."""
limit = 3
# preset news feeds
@ -36,5 +36,5 @@ def rss(inp, say=None):
@hook.command(autohelp=False)
def rb(inp, say=None):
"rb -- Shows the latest Craftbukkit recommended build"
"""rb -- Shows the latest Craftbukkit recommended build"""
rss("bukkit", say)

View file

@ -1,4 +1,4 @@
" seen.py: written by sklnd in about two beers July 2009"
"""seen.py: written by sklnd in about two beers July 2009"""
import time
import re
@ -9,29 +9,29 @@ db_ready = False
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_user(name, time, quote, chan, host, "
"primary key(name, chan))")
"primary key(name, chan))")
db.commit()
db_ready = True
@hook.singlethread
@hook.event('PRIVMSG', ignorebots=False)
def seen_sieve(paraml, input=None, db=None, bot=None):
def seen_sieve(input=None, db=None):
if not db_ready:
db_init(db)
# keep private messages private
# keep private messages private
if input.chan[:1] == "#" and not re.findall('^s/.*/.*/$', input.msg.lower()):
db.execute("insert or replace into seen_user(name, time, quote, chan, host)"
"values(?,?,?,?,?)", (input.nick.lower(), time.time(), input.msg,
input.chan, input.mask))
"values(?,?,?,?,?)", (input.nick.lower(), time.time(), input.msg,
input.chan, input.mask))
db.commit()
@hook.command
def seen(inp, nick='', chan='', db=None, input=None):
"seen <nick> -- Tell when a nickname was last in active in one of this bot's channels."
"""seen <nick> -- Tell when a nickname was last in active in one of this bot's channels."""
if input.conn.nick.lower() == inp.lower():
return "You need to get your eyes checked."
@ -52,7 +52,7 @@ def seen(inp, nick='', chan='', db=None, input=None):
reltime = timesince.timesince(last_seen[1])
if last_seen[0] != inp.lower(): # for glob matching
inp = last_seen[0]
if last_seen[2][0:1]=="\x01":
if last_seen[2][0:1] == "\x01":
return '{} was last seen {} ago: * {} {}'.format(inp, reltime, inp,
last_seen[2][8:-1])
else:

View file

@ -3,7 +3,7 @@ from util import hook, http, web
@hook.command
def shorten(inp):
"shorten <url> - Makes an is.gd shortlink to the url provided."
"""shorten <url> - Makes an is.gd shortlink to the url provided."""
try:
return web.isgd(inp)

View file

@ -9,7 +9,7 @@ with open("plugins/data/slogans.txt") as f:
@hook.command
def slogan(inp):
"slogan <word> -- Makes a slogan for <word>."
"""slogan <word> -- Makes a slogan for <word>."""
out = random.choice(slogans)
if inp.lower() and out.startswith("<text>"):
inp = text.capitalize_first(inp)

View file

@ -8,7 +8,7 @@ search_url = "http://search.atomz.com/search/?sp_a=00062d45-sp00000000"
@hook.command
def snopes(inp):
"snopes <topic> -- Searches snopes for an urban legend about <topic>."
"""snopes <topic> -- Searches snopes for an urban legend about <topic>."""
search_page = http.get_html(search_url, sp_q=inp, sp_c="1")
result_urls = search_page.xpath("//a[@target='_self']/@href")
@ -26,7 +26,7 @@ def snopes(inp):
status = status.group(0).strip()
else: # new-style statuses
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
status = re.sub(r"[\s\xa0]+", " ", status)

View file

@ -21,7 +21,9 @@ def soundcloud(url, api_key):
url = web.try_isgd(data['permalink_url'])
return u"SoundCloud track: \x02{}\x02 by \x02{}user\x02 {}{}- {} plays, {} downloads, {} comments - \x02{}\x02".format(data['title'], data['user']['username'], desc, genre, data['playback_count'], data['download_count'], data['comment_count'], url)
return u"SoundCloud track: \x02{}\x02 by \x02{}user\x02 {}{}- {} plays, {} downloads, {} comments - \x02{}\x02".format(
data['title'], data['user']['username'], desc, genre, data['playback_count'], data['download_count'],
data['comment_count'], url)
@hook.regex(*sc_re)
@ -30,7 +32,8 @@ def soundcloud_url(match, bot=None):
if not api_key:
print "Error: no api key set"
return None
url = match.group(1).split(' ')[-1] + "//" + (match.group(2) if match.group(2) else "") + match.group(3) + match.group(4).split(' ')[0]
url = match.group(1).split(' ')[-1] + "//" + (match.group(2) if match.group(2) else "") + match.group(3) + \
match.group(4).split(' ')[0]
return soundcloud(url, api_key)
@ -40,5 +43,6 @@ def sndsc_url(match, bot=None):
if not api_key:
print "Error: no api key set"
return None
url = match.group(1).split(' ')[-1] + "//" + (match.group(2) if match.group(2) else "") + match.group(3) + match.group(4).split(' ')[0]
url = match.group(1).split(' ')[-1] + "//" + (match.group(2) if match.group(2) else "") + match.group(3) + \
match.group(4).split(' ')[0]
return soundcloud(http.open(url).url, api_key)

View file

@ -6,7 +6,7 @@ locale = "en_US"
@hook.command
def spell(inp):
"spell <word> -- Check spelling of <word>."
"""spell <word> -- Check spelling of <word>."""
if ' ' in inp:
return "This command only supports one word at a time."

View file

@ -10,10 +10,12 @@ spotify_re = (r'(spotify:(track|album|artist|user):([a-zA-Z0-9]+))', re.I)
http_re = (r'(open\.spotify\.com\/(track|album|artist|user)\/'
'([a-zA-Z0-9]+))', re.I)
def sptfy(inp, sptfy=False):
if sptfy:
shortenurl = "http://sptfy.com/index.php"
data = urlencode({'longUrl': inp, 'shortUrlDomain': 1, 'submitted': 1, "shortUrlFolder": 6, "customUrl": "", "shortUrlPassword": "", "shortUrlExpiryDate": "", "shortUrlUses": 0, "shortUrlType": 0})
data = urlencode({'longUrl': inp, 'shortUrlDomain': 1, 'submitted': 1, "shortUrlFolder": 6, "customUrl": "",
"shortUrlPassword": "", "shortUrlExpiryDate": "", "shortUrlUses": 0, "shortUrlType": 0})
try:
soup = http.get_soup(shortenurl, post_data=data, cookies=True)
except:
@ -22,7 +24,8 @@ def sptfy(inp, sptfy=False):
link = soup.find('div', {'class': 'resultLink'}).text.strip()
return link
except:
message = "Unable to shorten URL: %s" % soup.find('div', {'class': 'messagebox_text'}).find('p').text.split("<br/>")[0]
message = "Unable to shorten URL: %s" % \
soup.find('div', {'class': 'messagebox_text'}).find('p').text.split("<br/>")[0]
return message
else:
return web.try_isgd(inp)
@ -31,9 +34,9 @@ def sptfy(inp, sptfy=False):
@hook.command('sptrack')
@hook.command
def spotify(inp):
"spotify <song> -- Search Spotify for <song>"
"""spotify <song> -- Search Spotify for <song>"""
try:
data = http.get_json("http://ws.spotify.com/search/1/track.json", q=inp.strip())
data = http.get_json("http://ws.spotify.com/search/1/track.json", q=inp.strip())
except Exception as e:
return "Could not get track information: {}".format(e)
@ -42,13 +45,15 @@ def spotify(inp):
except IndexError:
return "Could not find track."
url = sptfy(gateway.format(type, id))
return u"\x02{}\x02 by \x02{}\x02 - \x02{}\x02".format(data["tracks"][0]["name"], data["tracks"][0]["artists"][0]["name"], url)
return u"\x02{}\x02 by \x02{}\x02 - \x02{}\x02".format(data["tracks"][0]["name"],
data["tracks"][0]["artists"][0]["name"], url)
@hook.command
def spalbum(inp):
"spalbum <album> -- Search Spotify for <album>"
"""spalbum <album> -- Search Spotify for <album>"""
try:
data = http.get_json("http://ws.spotify.com/search/1/album.json", q=inp.strip())
data = http.get_json("http://ws.spotify.com/search/1/album.json", q=inp.strip())
except Exception as e:
return "Could not get album information: {}".format(e)
@ -57,13 +62,15 @@ def spalbum(inp):
except IndexError:
return "Could not find album."
url = sptfy(gateway.format(type, id))
return u"\x02{}\x02 by \x02{}\x02 - \x02{}\x02".format(data["albums"][0]["name"], data["albums"][0]["artists"][0]["name"], url)
return u"\x02{}\x02 by \x02{}\x02 - \x02{}\x02".format(data["albums"][0]["name"],
data["albums"][0]["artists"][0]["name"], url)
@hook.command
def spartist(inp):
"spartist <artist> -- Search Spotify for <artist>"
"""spartist <artist> -- Search Spotify for <artist>"""
try:
data = http.get_json("http://ws.spotify.com/search/1/artist.json", q=inp.strip())
data = http.get_json("http://ws.spotify.com/search/1/artist.json", q=inp.strip())
except Exception as e:
return "Could not get artist information: {}".format(e)
@ -74,6 +81,7 @@ def spartist(inp):
url = sptfy(gateway.format(type, id))
return u"\x02{}\x02 - \x02{}\x02".format(data["artists"][0]["name"], url)
@hook.regex(*http_re)
@hook.regex(*spotify_re)
def spotify_url(match):
@ -86,8 +94,13 @@ def spotify_url(match):
name = data["track"]["name"]
artist = data["track"]["artists"][0]["name"]
album = data["track"]["album"]["name"]
return u"Spotify Track: \x02{}\x02 by \x02{}\x02 from the album \x02{}\x02 - \x02{}\x02".format(name, artist, album, sptfy(gateway.format(type, spotify_id)))
return u"Spotify Track: \x02{}\x02 by \x02{}\x02 from the album \x02{}\x02 - \x02{}\x02".format(name, artist,
album, sptfy(
gateway.format(type, spotify_id)))
elif type == "artist":
return u"Spotify Artist: \x02{}\x02 - \x02{}\x02".format(data["artist"]["name"], sptfy(gateway.format(type, spotify_id)))
return u"Spotify Artist: \x02{}\x02 - \x02{}\x02".format(data["artist"]["name"],
sptfy(gateway.format(type, spotify_id)))
elif type == "album":
return u"Spotify Album: \x02{}\x02 - \x02{}\x02 - \x02{}\x02".format(data["album"]["artist"], data["album"]["name"], sptfy(gateway.format(type, spotify_id)))
return u"Spotify Album: \x02{}\x02 - \x02{}\x02 - \x02{}\x02".format(data["album"]["artist"],
data["album"]["name"],
sptfy(gateway.format(type, spotify_id)))

View file

@ -1,5 +1,4 @@
from util import hook, http, web, text, timesince
from datetime import datetime
from util import hook, http, web, text
from bs4 import BeautifulSoup
import re
@ -54,7 +53,8 @@ def steamcalc(inp, nick='', db=None):
if inp.split(" ")[2] == "dontsave":
dontsave = True
url = http.prepare_url("http://steamdb.info/calculator/", {"player": inp, "currency": currency if currency else "us"})
url = http.prepare_url("http://steamdb.info/calculator/",
{"player": inp, "currency": currency if currency else "us"})
soup = http.get_soup(url)
out = u""
@ -64,7 +64,8 @@ def steamcalc(inp, nick='', db=None):
except Exception as e:
print e
return u"\x02Unable to retrieve info for %s!\x02 Is it a valid SteamCommunity profile username (%s)? " \
"Check if your profile is private, or go here to search: %s" % (inp, web.try_isgd("http://steamcommunity.com/id/%s" % inp), web.try_isgd(url))
"Check if your profile is private, or go here to search: %s" % (
inp, web.try_isgd("http://steamcommunity.com/id/%s" % inp), web.try_isgd(url))
nextone = False
status = "Unknown"
@ -73,7 +74,7 @@ def steamcalc(inp, nick='', db=None):
status = i.text
break
elif i.text == "Status":
nextone=True
nextone = True
if status == "Online":
status = "\x033\x02Online\x02\x0f"
elif status == "Offline":
@ -96,7 +97,8 @@ def steamcalc(inp, nick='', db=None):
nppercent = data[3].text.split(" ")[-1]
time = data[4].text.split(" ")[-1].replace("h", "hours")
out += " This account is worth \x02%s\x02, and they've spent \x02%s\x02 playing games! " % (money, time)
out += " They have \x02%s games\x02, but \x02%s of them haven't been touched\x02! That's \x02%s\x02! " % (totalgames, notplayed, nppercent)
out += " They have \x02%s games\x02, but \x02%s of them haven't been touched\x02! That's \x02%s\x02! " % (
totalgames, notplayed, nppercent)
if not dontsave:
db.execute("insert or replace into steam(nick, acc) values (?,?)", (nick.lower(), inp))

View file

@ -4,9 +4,10 @@ import json
url = 'http://www.google.com/ig/api'
@hook.command
def stock(inp):
"stock <symbol> -- Gets information about stock symbol <symbol>."
"""stock <symbol> -- Gets information about stock symbol <symbol>."""
parsed = http.get_xml(url, stock=inp)
@ -19,25 +20,26 @@ def stock(inp):
# if we dont get a company name back, the symbol doesn't match a company
if not "company" in results:
guess_data = json.loads(http.get("http://d.yimg.com/autoc.finance.yahoo.com/autoc", query=inp, callback="YAHOO.Finance.SymbolSuggest.ssCallback")[39:-1])
guess_data = json.loads(http.get("http://d.yimg.com/autoc.finance.yahoo.com/autoc", query=inp,
callback="YAHOO.Finance.SymbolSuggest.ssCallback")[39:-1])
guess = guess_data['ResultSet']['Result']
if len(guess) > 0:
guess = guess[0]["symbol"]
return stock(guess)
else:
return "error: unable to get stock info for '%s'" % inp
if results['last'] == '0.00':
return "%(company)s - last known stock value was 0.00 %(currency)s" \
" as of %(trade_timestamp)s" % (results)
" as of %(trade_timestamp)s" % results
if results['change'][0] == '-':
results['color'] = "5"
else:
results['color'] = "3"
ret = "%(company)s - %(last)s %(currency)s " \
"\x03%(color)s%(change)s (%(perc_change)s%%)\x03 " \
ret = "%(company)s - %(last)s %(currency)s " \
"\x03%(color)s%(change)s (%(perc_change)s%%)\x03 " \
"as of %(trade_timestamp)s" % results
if results['delay'] != '0':

View file

@ -17,7 +17,7 @@ def convert_kilobytes(kilobytes):
@hook.command(autohelp=False)
def system(inp):
"system -- Retrieves information about the host system."
"""system -- Retrieves information about the host system."""
hostname = platform.node()
os = platform.platform()
python_imp = platform.python_implementation()
@ -31,7 +31,7 @@ def system(inp):
@hook.command(autohelp=False)
def memory(inp):
"memory -- Displays the bot's current memory usage."
"""memory -- Displays the bot's current memory usage."""
if os.name == "posix":
# get process info
status_file = open('/proc/self/status').read()
@ -63,7 +63,7 @@ def memory(inp):
@hook.command(autohelp=False)
def uptime(inp, bot=None):
"uptime -- Shows the bot's uptime."
"""uptime -- Shows the bot's uptime."""
uptime_raw = round(time.time() - bot.start_time)
uptime = timedelta(seconds=uptime_raw)
return "Uptime: \x02%s\x02" % uptime
@ -71,5 +71,5 @@ def uptime(inp, bot=None):
@hook.command(autohelp=False)
def pid(inp):
"pid -- Prints the bot's PID."
"""pid -- Prints the bot's PID."""
return "PID: \x02%s\x02" % os.getpid()

View file

@ -1,5 +1,5 @@
" tell.py: written by sklnd in July 2009"
" 2010.01.25 - modified by Scaevolus"
""" tell.py: written by sklnd in July 2009
2010.01.25 - modified by Scaevolus"""
import time
import re
@ -8,10 +8,10 @@ from util import hook, timesince
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"
"(user_to, user_from, message, chan, time,"
"primary key(user_to, message))")
"(user_to, user_from, message, chan, time,"
"primary key(user_to, message))")
db.commit()
return db
@ -19,8 +19,8 @@ def db_init(db):
def get_tells(db, user_to):
return db.execute("select user_from, message, time, chan from tell where"
" user_to=lower(?) order by time",
(user_to.lower(),)).fetchall()
" user_to=lower(?) order by time",
(user_to.lower(),)).fetchall()
@hook.singlethread
@ -38,12 +38,12 @@ def tellinput(paraml, input=None, notice=None, db=None, bot=None, nick=None, con
reltime = timesince.timesince(time)
reply = "%s sent you a message %s ago from %s: %s" % (user_from, reltime, chan,
message)
message)
if len(tells) > 1:
reply += " (+%d more, %sshowtells to view)" % (len(tells) - 1, conn.conf["command_prefix"])
db.execute("delete from tell where user_to=lower(?) and message=?",
(nick, message))
(nick, message))
db.commit()
notice(reply)
@ -66,13 +66,13 @@ def showtells(inp, nick='', chan='', notice=None, db=None):
notice("%s sent you a message %s ago from %s: %s" % (user_from, past, chan, message))
db.execute("delete from tell where user_to=lower(?)",
(nick,))
(nick,))
db.commit()
@hook.command
def tell(inp, nick='', chan='', db=None, input=None, notice=None):
"tell <nick> <message> -- Relay <message> to <nick> when <nick> is around."
"""tell <nick> <message> -- Relay <message> to <nick> when <nick> is around."""
query = inp.split(' ', 1)
if len(query) != 2:
@ -102,14 +102,14 @@ def tell(inp, nick='', chan='', db=None, input=None, notice=None):
db_init(db)
if db.execute("select count() from tell where user_to=?",
(user_to,)).fetchone()[0] >= 10:
(user_to,)).fetchone()[0] >= 10:
notice("That person has too many messages queued.")
return
try:
db.execute("insert into tell(user_to, user_from, message, chan,"
"time) values(?,?,?,?,?)", (user_to, user_from, message,
chan, time.time()))
"time) values(?,?,?,?,?)", (user_to, user_from, message,
chan, time.time()))
db.commit()
except db.IntegrityError:
notice("Message has already been queued.")

View file

@ -7,7 +7,7 @@ api_url = 'http://api.wolframalpha.com/v2/query?format=plaintext'
@hook.command("time")
def time_command(inp, bot=None):
"time <area> -- Gets the time in <area>"
"""time <area> -- Gets the time in <area>"""
query = "current time in %s" % inp
@ -16,8 +16,7 @@ def time_command(inp, bot=None):
return "error: no wolfram alpha api key set"
request = http.get_xml(api_url, input=query, appid=api_key)
time = " ".join(request.xpath("//pod[@title='Result']/subpod/plain" \
"text/text()"))
time = " ".join(request.xpath("//pod[@title='Result']/subpod/plaintext/text()"))
time = time.replace(" | ", ", ")
if time:
@ -25,8 +24,9 @@ def time_command(inp, bot=None):
if inp.lower() == "unix":
place = "Unix Epoch"
else:
place = capitalize_first(" ".join(request.xpath("//pod[@" \
"title='Input interpretation']/subpod/plaintext/text()"))[16:])
place = capitalize_first(" ".join(request.xpath("//pod[@"
"title='Input interpretation']/subpod/plaintext/text()"))[
16:])
return "%s - \x02%s\x02" % (time, place)
else:
return "Could not get the time for '%s'." % inp
@ -34,15 +34,15 @@ def time_command(inp, bot=None):
@hook.command(autohelp=False)
def beats(inp):
"beats -- Gets the current time in .beats (Swatch Internet Time). "
"""beats -- Gets the current time in .beats (Swatch Internet Time). """
if inp.lower() == "wut":
return "Instead of hours and minutes, the mean solar day is divided " \
"up into 1000 parts called \".beats\". Each .beat lasts 1 minute and" \
" 26.4 seconds. Times are notated as a 3-digit number out of 1000 af" \
"ter midnight. So, @248 would indicate a time 248 .beats after midni" \
"ght representing 248/1000 of a day, just over 5 hours and 57 minute" \
"s. There are no timezones."
"up into 1000 parts called \".beats\". Each .beat lasts 1 minute and" \
" 26.4 seconds. Times are notated as a 3-digit number out of 1000 af" \
"ter midnight. So, @248 would indicate a time 248 .beats after midni" \
"ght representing 248/1000 of a day, just over 5 hours and 57 minute" \
"s. There are no timezones."
elif inp.lower() == "guide":
return "1 day = 1000 .beats, 1 hour = 41.666 .beats, 1 min = 0.6944 .beats, 1 second = 0.01157 .beats"

View file

@ -4,7 +4,7 @@ from bs4 import BeautifulSoup
@hook.command
def title(inp):
"title <url> -- gets the title of a web page"
"""title <url> -- gets the title of a web page"""
url = urlnorm.normalize(inp.encode('utf-8'), assume_scheme="http")
try:

View file

@ -64,8 +64,8 @@ def db_del(db, nick, limit='all'):
limit ?
offset ?)
""", (nick,
-1 if limit == 'all' else 1,
0 if limit == 'all' else limit))
-1 if limit == 'all' else 1,
0 if limit == 'all' else limit))
db.commit()
return row

View file

@ -79,13 +79,13 @@ def get_episode_info(episode, api_key):
episode_desc = '%s' % episode_num
if episode_name:
episode_desc += ' - %s' % episode_name
return (first_aired, airdate, episode_desc)
return first_aired, airdate, episode_desc
@hook.command
@hook.command('tv')
def tv_next(inp, bot=None):
"tv <series> -- Get the next episode of <series>."
"""tv <series> -- Get the next episode of <series>."""
api_key = bot.config.get("api_keys", {}).get("tvdb", None)
if api_key is None:
@ -135,7 +135,7 @@ def tv_next(inp, bot=None):
@hook.command
@hook.command('tv_prev')
def tv_last(inp, bot=None):
"tv_last <series> -- Gets the most recently aired episode of <series>."
"""tv_last <series> -- Gets the most recently aired episode of <series>."""
api_key = bot.config.get("api_keys", {}).get("tvdb", None)
if api_key is None:

View file

@ -21,7 +21,7 @@ def truncate(msg):
out = out + " " + nmsg[x]
else:
out = nmsg[x]
x = x + 1
x += 1
if x <= 7:
return out
else:
@ -44,7 +44,7 @@ def multitwitch_url(match):
@hook.regex(*twitch_re)
def twitch_url(match, chan=''):
def twitch_url(match):
bit = match.group(4).split("#")[0]
location = "/".join(bit.split("/")[1:])
if not test(location):
@ -68,16 +68,16 @@ def twitch_lookup(location):
locsplit = location.split("/")
if len(locsplit) > 1 and len(locsplit) == 3:
channel = locsplit[0]
type = locsplit[1] # should be b or c
type = locsplit[1] # should be b or c
id = locsplit[2]
else:
channel = locsplit[0]
type = None
id = None
h = HTMLParser()
fmt = "{}: {} playing {} ({})" # Title: nickname playing Game (x views)
fmt = "{}: {} playing {} ({})" # Title: nickname playing Game (x views)
if type and id:
if type == "b": # I haven't found an API to retrieve broadcast info
if type == "b": # I haven't found an API to retrieve broadcast info
soup = http.get_soup("http://twitch.tv/" + location)
title = soup.find('span', {'class': 'real_title js-title'}).text
playing = soup.find('a', {'class': 'game js-game'}).text

View file

@ -8,7 +8,7 @@ from datetime import datetime
@hook.command("tw")
@hook.command("twatter")
@hook.command
def twitter(inp, bot=None, say=None):
def twitter(inp, bot=None):
"twitter <user> [n] -- Gets last/[n]th tweet from <user>"
consumer_key = bot.config.get("api_keys", {}).get("twitter_consumer_key")
@ -100,7 +100,7 @@ def twitter(inp, bot=None, say=None):
@hook.command("twinfo")
@hook.command
def twuser(inp, bot=None):
"twuser <user> -- Get info on the Twitter user <user>"
"""twuser <user> -- Get info on the Twitter user <user>"""
consumer_key = bot.config.get("api_keys", {}).get("twitter_consumer_key")
consumer_secret = bot.config.get("api_keys", {}).get("twitter_consumer_secret")
@ -131,4 +131,5 @@ def twuser(inp, bot=None):
prefix = ""
return u"{}@\x02{}\x02 ({}) is located in \x02{}\x02 and has \x02{:,}\x02 tweets and \x02{:,}\x02 followers. The users description is \"{}\" " \
"".format(prefix, user.screen_name, user.name, user.location, user.statuses_count, user.followers_count, user.description)
"".format(prefix, user.screen_name, user.name, user.location, user.statuses_count, user.followers_count,
user.description)

View file

@ -1,4 +1,4 @@
from util import hook, http, text, web
from util import hook, http, text
import re
base_url = 'http://www.urbandictionary.com/iphone/search/define'
@ -7,7 +7,7 @@ base_url = 'http://www.urbandictionary.com/iphone/search/define'
@hook.command('u')
@hook.command
def urban(inp):
"urban <phrase> [id] -- Looks up <phrase> on urbandictionary.com."
"""urban <phrase> [id] -- Looks up <phrase> on urbandictionary.com."""
# clean and split the input
input = inp.lower().strip()
@ -22,7 +22,6 @@ def urban(inp):
else:
id = 1
# fetch the definitions
page = http.get_json(base_url, term=input, referer="http://m.urbandictionary.com")
defs = page['list']
@ -35,13 +34,13 @@ def urban(inp):
try:
definition = defs[id - 1]['definition'].replace('\r\n', ' ')
definition = re.sub('\s+', ' ', definition).strip() # remove excess spaces
definition = text.truncate_str(definition, 200)
definition = text.truncate_str(definition, 200)
except IndexError:
return 'Not found.'
url = defs[id - 1]['permalink']
output = u"[%i/%i] %s :: %s" % \
(id, len(defs), definition, url)
(id, len(defs), definition, url)
return output

View file

@ -9,6 +9,7 @@ control = {'bold': '\x02', 'color': '\x03', 'italic': '\x09',
'strikethrough': '\x13', 'reset': '\x0f', 'underline': '\x15',
'underline2': '\x1f', 'reverse': '\x16'}
def color(color):
return control['color'] + colors[color]

View file

@ -22,14 +22,14 @@ def _hook_add(func, add, name=''):
n_args -= 1
if n_args != 1:
err = '%ss must take 1 non-keyword argument (%s)' % (name,
func.__name__)
func.__name__)
raise ValueError(err)
args = []
if argspec.defaults:
end = bool(argspec.keywords) + bool(argspec.varargs)
args.extend(argspec.args[-len(argspec.defaults):
end if end else None])
end if end else None])
if argspec.keywords:
args.append(0) # means kwargs present
func._args = args
@ -41,7 +41,7 @@ def _hook_add(func, add, name=''):
def sieve(func):
if func.func_code.co_argcount != 5:
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,)])
return func

View file

@ -22,7 +22,7 @@ ua_cloudbot = 'Cloudbot/DEV http://github.com/CloudDev/CloudBot'
ua_firefox = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/17.0' \
' Firefox/17.0'
ua_old_firefox = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; ' \
'rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6'
'rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6'
ua_internetexplorer = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)'
ua_chrome = 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.4 (KHTML, ' \
'like Gecko) Chrome/22.0.1229.79 Safari/537.4'
@ -33,7 +33,7 @@ jar = cookielib.CookieJar()
class HTMLTextExtractor(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self.result = [ ]
self.result = []
def handle_data(self, d):
self.result.append(d)
@ -76,7 +76,6 @@ def get_json(*args, **kwargs):
def open(url, query_params=None, user_agent=None, post_data=None,
referer=None, get_method=None, cookies=False, **kwargs):
if query_params is None:
query_params = {}
@ -112,7 +111,7 @@ def prepare_url(url, queries):
query = dict(urlparse.parse_qsl(query))
query.update(queries)
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))

View file

@ -8,7 +8,7 @@ import re
def munge(text, munge_count=0):
"munges up text."
"""munges up text."""
reps = 0
for n in xrange(len(text)):
rep = character_replacements.get(text[n])
@ -96,7 +96,7 @@ def multiword_replace(text, wordDic):
def truncate_words(content, length=10, suffix='...'):
"Truncates a string after a certain number of words."
"""Truncates a string after a certain number of words."""
nmsg = content.split(" ")
out = None
x = 0
@ -106,7 +106,7 @@ def truncate_words(content, length=10, suffix='...'):
out = out + " " + nmsg[x]
else:
out = nmsg[x]
x = x + 1
x += 1
if x <= length:
return out
else:
@ -115,7 +115,7 @@ def truncate_words(content, length=10, suffix='...'):
# from <http://stackoverflow.com/questions/250357/smart-truncate-in-python>
def truncate_str(content, length=100, suffix='...'):
"Truncates a string after a certain number of chars."
"""Truncates a string after a certain number of chars."""
if len(content) <= length:
return content
else:
@ -197,5 +197,5 @@ def get_text_list(list_, last_word='or'):
return list_[0]
return '%s %s %s' % (
# Translators: This string is used as a separator between list elements
(', ').join([i for i in list_][:-1]),
', '.join([i for i in list_][:-1]),
last_word, list_[-1])

View file

@ -43,12 +43,12 @@ def timesince(d, now=None):
Adapted from http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
"""
chunks = (
(60 * 60 * 24 * 365, ('year', 'years')),
(60 * 60 * 24 * 30, ('month', 'months')),
(60 * 60 * 24 * 7, ('week', 'weeks')),
(60 * 60 * 24, ('day', 'days')),
(60 * 60, ('hour', 'hours')),
(60, ('minute', 'minutes'))
(60 * 60 * 24 * 365, ('year', 'years')),
(60 * 60 * 24 * 30, ('month', 'months')),
(60 * 60 * 24 * 7, ('week', 'weeks')),
(60 * 60 * 24, ('day', 'days')),
(60 * 60, ('hour', 'hours')),
(60, ('minute', 'minutes'))
)
# Convert int or float (unix epoch) to datetime.datetime for comparison

View file

@ -38,13 +38,15 @@ class Normalizer(object):
self.regex = regex
self.normalize = normalize_func
normalizers = ( Normalizer( re.compile(r'(?:https?://)?(?:[a-zA-Z0-9\-]+\.)?(?:amazon|amzn){1}\.(?P<tld>[a-zA-Z\.]{2,})\/(gp/(?:product|offer-listing|customer-media/product-gallery)/|exec/obidos/tg/detail/-/|o/ASIN/|dp/|(?:[A-Za-z0-9\-]+)/dp/)?(?P<ASIN>[0-9A-Za-z]{10})'),
lambda m: r'http://amazon.%s/dp/%s' % (m.group('tld'), m.group('ASIN'))),
Normalizer( re.compile(r'.*waffleimages\.com.*/([0-9a-fA-F]{40})'),
lambda m: r'http://img.waffleimages.com/%s' % m.group(1) ),
Normalizer( re.compile(r'(?:youtube.*?(?:v=|/v/)|youtu\.be/|yooouuutuuube.*?id=)([-_a-zA-Z0-9]+)'),
lambda m: r'http://youtube.com/watch?v=%s' % m.group(1) ),
)
normalizers = (Normalizer(re.compile(
r'(?:https?://)?(?:[a-zA-Z0-9\-]+\.)?(?:amazon|amzn){1}\.(?P<tld>[a-zA-Z\.]{2,})\/(gp/(?:product|offer-listing|customer-media/product-gallery)/|exec/obidos/tg/detail/-/|o/ASIN/|dp/|(?:[A-Za-z0-9\-]+)/dp/)?(?P<ASIN>[0-9A-Za-z]{10})'),
lambda m: r'http://amazon.%s/dp/%s' % (m.group('tld'), m.group('ASIN'))),
Normalizer(re.compile(r'.*waffleimages\.com.*/([0-9a-fA-F]{40})'),
lambda m: r'http://img.waffleimages.com/%s' % m.group(1)),
Normalizer(re.compile(r'(?:youtube.*?(?:v=|/v/)|youtu\.be/|yooouuutuuube.*?id=)([-_a-zA-Z0-9]+)'),
lambda m: r'http://youtube.com/watch?v=%s' % m.group(1)),
)
def normalize(url, assume_scheme=False):
@ -78,12 +80,13 @@ def normalize(url, assume_scheme=False):
def clean(string):
string = unicode(unquote(string), 'utf-8', 'replace')
return unicodedata.normalize('NFC', string).encode('utf-8')
path = quote(clean(path), "~:/?#[]@!$&'()*+,;=")
fragment = quote(clean(fragment), "~")
# note care must be taken to only encode & and = characters as values
query = "&".join(["=".join([quote(clean(t), "~:/?#[]@!$'()*+,;=")
for t in q.split("=", 1)]) for q in query.split("&")])
for t in q.split("=", 1)]) for q in query.split("&")])
# Prevent dot-segments appearing in non-relative URI paths.
if scheme in ["", "http", "https", "ftp", "file"]:
@ -128,7 +131,7 @@ def normalize(url, assume_scheme=False):
if url.endswith("#") and query == "" and fragment == "":
path += "#"
normal_url = urlparse.urlunsplit((scheme, auth, path, query,
fragment)).replace("http:///", "http://")
fragment)).replace("http:///", "http://")
for norm in normalizers:
m = norm.regex.match(normal_url)
if m:

View file

@ -1,7 +1,9 @@
""" web.py - handy functions for web services """
import http, urlnorm
import json, urllib
import http
import urlnorm
import json
import urllib
import yql
short_url = "http://is.gd/create.php"
@ -39,11 +41,12 @@ def try_isgd(url):
out = url
return out
def haste(text, ext='txt'):
""" pastes text to a hastebin server """
page = http.get(paste_url + "/documents", post_data=text)
data = json.loads(page)
return("%s/%s.%s" % (paste_url, data['key'], ext))
return ("%s/%s.%s" % (paste_url, data['key'], ext))
def query(query, params={}):

View file

@ -1,8 +1,8 @@
'''
"""
Runs a given url through the w3c validator
by Vladi
'''
"""
from util import hook, http
@ -10,7 +10,7 @@ from util import hook, http
@hook.command('w3c')
@hook.command
def validate(inp):
"validate <url> -- Runs url through the w3c markup validator."
"""validate <url> -- Runs url through the w3c markup validator."""
if not inp.startswith('http://'):
inp = 'http://' + inp

View file

@ -25,22 +25,23 @@ def getSoundInfo(url, inp, jsondata=False):
quote = inp
data = http.get_json(url + "list.php?" + urlencode({"quote": quote, "who": who}))
if len(data) > 3:
numresults = data[2]
newdata = data[3:]
text = newdata[0]["text"]
if "music" in url:
textsplit = text.split('"')
text = ""
for i in xrange(len(textsplit)):
if i%2 != 0 and i < 6:
if i % 2 != 0 and i < 6:
if text:
text += " / " + textsplit[i]
else:
text = textsplit[i]
if not jsondata:
return "%s - %s %s" % (newdata[0]["who"],
text if len(text) < 325 else text[:325]+"...",
web.try_isgd(url + newdata[0]["id"] if not dostream else url+"sound.php?id="+newdata[0]["id"]+"&stream"))
text if len(text) < 325 else text[:325] + "...",
web.try_isgd(
url + newdata[0]["id"] if not dostream else url + "sound.php?id=" + newdata[0][
"id"] + "&stream"))
else:
if not jsondata:
return "No results."
@ -49,50 +50,72 @@ def getSoundInfo(url, inp, jsondata=False):
@hook.command
def portal2(inp):
"""portal2 [who - ]<quote> - Look up Portal 2 quote. Example: .portal2 cave johnson - demand to see life's manager , .portal2 i own the place | If - is not included, no 'who' data will be sent."""
"""portal2 [who - ]<quote> - Look up Portal 2 quote.
Example: .portal2 cave johnson - demand to see life's manager,
.portal2 i own the place | If - is not included, no 'who' data will be sent."""
return getSoundInfo(portal2url, inp)
@hook.command
def portal2dlc(inp):
"""portal2dlc [who - ]<quote> - Look up Portal 2 DLC quote. Example: .portal2dlc1 glados - I lie when i'm nervous , .portal2 these exhibits are interactive | If - is not included, no 'who' data will be sent."""
"""portal2dlc [who - ]<quote> - Look up Portal 2 DLC quote.
Example: .portal2dlc1 glados - I lie when i'm nervous
.portal2 these exhibits are interactive
If - is not included, no 'who' data will be sent."""
return getSoundInfo(portal2dlc1url, inp)
@hook.command("portal2pti")
@hook.command
def portal2dlc2(inp):
"""portal2dlc2 [who - ]<quote> - Look up Portal 2 Perpetual Testing Inititive quote. Example: .portal2 glados - I lie when i'm nervous , .portal2dlc2 these exhibits are interactive | If - is not included, no 'who' data will be sent."""
"""portal2dlc2 [who - ]<quote> - Look up Portal 2 Perpetual Testing Inititive quote.
Example: .portal2 glados - I lie when i'm nervous
.portal2dlc2 these exhibits are interactive
If - is not included, no 'who' data will be sent."""
return getSoundInfo(portal2dlc2url, inp)
@hook.command
def portal2music(inp):
"""portal2music <title> - Look up Portal 2 music. Example: .portal2 turret opera , .portal2music want you gone | If - is not included, no 'title' data will be sent."""
"""portal2music <title> - Look up Portal 2 music.
Example: .portal2 turret opera
.portal2music want you gone
If - is not included, no 'title' data will be sent."""
return getSoundInfo(portal2musicurl, inp + " - ")
@hook.command('portal1')
@hook.command
def portal(inp):
"""portal [who - ]<quote> - Look up Portal quote. Example: .portal glados - the last thing you want to do is hurt me , .portal this is your fault | If - is not included, no 'who' data will be sent."""
"""portal [who - ]<quote> - Look up Portal quote.
Example: .portal glados - the last thing you want to do is hurt me
.portal this is your fault
If - is not included, no 'who' data will be sent."""
return getSoundInfo(portal1url, inp)
@hook.command('portal1music')
@hook.command
def portalmusic(inp):
"""portalmusic <title> - Look up Portal music. Example: .portalmusic still alive | If - is not included, no 'title' data will be sent."""
"""portalmusic <title> - Look up Portal music.
Example: .portalmusic still alive
If - is not included, no 'title' data will be sent."""
return getSoundInfo(portal1musicurl, inp + " - ")
@hook.command('tf2sound')
@hook.command
def tf2(inp):
"""tf2 [who - ]<quote> - Look up TF2 quote. Example: .tf2 spy - may i borrow your earpiece , .tf2 nom nom nom | If - is not included, no 'who' data will be sent."""
"""tf2 [who - ]<quote> - Look up TF2 quote.
Example: .tf2 spy - may i borrow your earpiece
.tf2 nom nom nom
If - is not included, no 'who' data will be sent."""
return getSoundInfo(tf2url, inp)
@hook.command
def tf2music(inp):
"""tf2music title - Look up TF2 music lyrics. Example: .tf2music rocket jump waltz | If - is not included, no 'title' data will be sent."""
"""tf2music title - Look up TF2 music lyrics.
Example: .tf2music rocket jump waltz
If - is not included, no 'title' data will be sent."""
return getSoundInfo(tf2musicurl, inp + " - ")

View file

@ -3,16 +3,16 @@ from util import hook, http, timeformat
@hook.regex(r'vimeo.com/([0-9]+)')
def vimeo_url(match):
"vimeo <url> -- returns information on the Vimeo video at <url>"
"""vimeo <url> -- returns information on the Vimeo video at <url>"""
info = http.get_json('http://vimeo.com/api/v2/video/%s.json'
% match.group(1))
if info:
info[0]["duration"] = timeformat.timeformat(info[0]["duration"])
info[0]["stats_number_of_likes"] = format(
info[0]["stats_number_of_likes"], ",d")
info[0]["stats_number_of_likes"], ",d")
info[0]["stats_number_of_plays"] = format(
info[0]["stats_number_of_plays"], ",d")
info[0]["stats_number_of_plays"], ",d")
return ("\x02%(title)s\x02 - length \x02%(duration)s\x02 - "
"\x02%(stats_number_of_likes)s\x02 likes - "
"\x02%(stats_number_of_plays)s\x02 plays - "

View file

@ -5,8 +5,8 @@ base_url = "http://api.wunderground.com/api/{}/{}/q/{}.json"
@hook.command(autohelp=None)
def weather(inp, reply=None, db=None, nick=None, bot=None, notice=None):
"weather <location> [dontsave] -- Gets weather data"\
" for <location> from Wunderground."
"""weather <location> [dontsave] -- Gets weather data
for <location> from Wunderground."""
api_key = bot.config.get("api_keys", {}).get("wunderground")
@ -19,7 +19,7 @@ def weather(inp, reply=None, db=None, nick=None, bot=None, notice=None):
# if there is no input, try getting the users last location from the DB
if not inp:
location = db.execute("select loc from weather where nick=lower(?)",
[nick]).fetchone()
[nick]).fetchone()
if not location:
# no location saved in the database, send the user help text
notice(weather.__doc__)
@ -55,10 +55,11 @@ def weather(inp, reply=None, db=None, nick=None, bot=None, notice=None):
if response['location']['state']:
place_name = "\x02{}\x02, \x02{}\x02 (\x02{}\x02)".format(response['location']['city'],
response['location']['state'], response['location']['country'])
response['location']['state'],
response['location']['country'])
else:
place_name = "\x02{}\x02 (\x02{}\x02)".format(response['location']['city'],
response['location']['country'])
response['location']['country'])
forecast_today = response["forecast"]["simpleforecast"]["forecastday"][0]
forecast_tomorrow = response["forecast"]["simpleforecast"]["forecastday"][1]
@ -94,5 +95,5 @@ def weather(inp, reply=None, db=None, nick=None, bot=None, notice=None):
if location and not dontsave:
db.execute("insert or replace into weather(nick, loc) values (?,?)",
(nick.lower(), location))
(nick.lower(), location))
db.commit()

View file

@ -1,5 +1,5 @@
'''Searches wikipedia and returns first sentence of article
Scaevolus 2009'''
"""Searches wikipedia and returns first sentence of article
Scaevolus 2009"""
import re
@ -15,14 +15,14 @@ paren_re = re.compile('\s*\(.*\)$')
@hook.command('w')
@hook.command
def wiki(inp):
"wiki <phrase> -- Gets first sentence of Wikipedia article on <phrase>."
"""wiki <phrase> -- Gets first sentence of Wikipedia article on <phrase>."""
x = http.get_xml(search_url, search=inp)
ns = '{http://opensearch.org/searchsuggest2}'
items = x.findall(ns + 'Section/' + ns + 'Item')
if items == []:
if not items:
if x.find('error') is not None:
return 'error: %(code)s: %(info)s' % x.find('error').attrib
else:

View file

@ -6,7 +6,7 @@ from util import hook, http, text, web
@hook.command('wa')
@hook.command
def wolframalpha(inp, bot=None):
"wa <query> -- Computes <query> using Wolfram Alpha."
"""wa <query> -- Computes <query> using Wolfram Alpha."""
api_key = bot.config.get("api_keys", {}).get("wolframalpha", None)

View file

@ -3,7 +3,7 @@ from util import hook, web, text
@hook.command
def answer(inp):
"answer <query> -- find the answer to a question on Yahoo! Answers"
"""answer <query> -- find the answer to a question on Yahoo! Answers"""
query = "SELECT Subject, ChosenAnswer, Link FROM answers.search WHERE query=@query LIMIT 1"
result = web.query(query, {"query": inp.strip()}).one()

View file

@ -36,14 +36,14 @@ def get_video_description(video_id):
if 'rating' in data:
out += ' - rated \x02%.2f/5.0\x02 (%d)' % (data['rating'],
data['ratingCount'])
data['ratingCount'])
if 'viewCount' in data:
out += ' - \x02%s\x02 views' % format(data['viewCount'], ",d")
upload_time = time.strptime(data['uploaded'], "%Y-%m-%dT%H:%M:%S.000Z")
out += ' - \x02%s\x02 on \x02%s\x02' % (data['uploader'],
time.strftime("%Y.%m.%d", upload_time))
time.strftime("%Y.%m.%d", upload_time))
if 'contentRating' in data:
out += ' - \x034NSFW\x02'
@ -70,7 +70,7 @@ def youtube_url(match):
@hook.command('y')
@hook.command
def youtube(inp):
"youtube <query> -- Returns the first YouTube search result for <query>."
"""youtube <query> -- Returns the first YouTube search result for <query>."""
request = http.get_json(search_api_url, q=inp)
@ -84,19 +84,19 @@ def youtube(inp):
return get_video_description(video_id) + " - " + video_url % video_id
ytpl_re = (r'(.*:)//(www.youtube.com/playlist|youtube.com/playlist)(:[0-9]+)?(.*)', re.I)
@hook.regex(*ytpl_re)
def ytplaylist_url(match):
location = match.group(4).split("=")[-1]
try:
soup = http.get_soup("https://www.youtube.com/playlist?list=" + location)
soup = http.get_soup("https://www.youtube.com/playlist?list=" + location)
except Exception:
return "\x034\x02Invalid response."
return "\x034\x02Invalid response."
title = soup.find('title').text.split('-')[0].strip()
author = soup.find('img', {'class': 'channel-header-profile-image'})['title']
numofratings = int(soup.find('span', {'class': 'likes'}).text) + int(soup.find('span', {'class': 'dislikes'}).text)
rating = (int(soup.find('span', {'class': 'likes'}).text) / numofratings) * 100 / 20
numvideos = soup.find('ul', {'class': 'header-stats'}).findAll('li')[0].text.split(' ')[0]
views = soup.find('ul', {'class': 'header-stats'}).findAll('li')[1].text.split(' ')[0]
return u"\x02%s\x02 - \x02%s\x02 views - \x02%s\x02 videos - \x02%s\x02" % (title, views, numvideos, author)