disable !command, enable fuzzy command matching, make help automatic, add disabled_command (for fuzzy command match disabling), misc bugs
This commit is contained in:
parent
e5b623cb68
commit
6452c1169c
6
bot.py
6
bot.py
|
@ -25,6 +25,10 @@ eval(compile(open(os.path.join('core', 'reload.py'), 'U').read(),
|
|||
os.path.join('core', 'reload.py'), 'exec'))
|
||||
reload(init=True)
|
||||
|
||||
config()
|
||||
if not hasattr(bot, 'config'):
|
||||
exit()
|
||||
|
||||
print 'Connecting to IRC'
|
||||
|
||||
bot.conns = {}
|
||||
|
@ -39,7 +43,7 @@ try:
|
|||
bot.conns[name] = IRC(conf['server'], conf['nick'], conf=conf,
|
||||
port=conf.get('port', 6667), channels=conf['channels'])
|
||||
except Exception, e:
|
||||
print 'ERROR: malformed config file', Exception, e
|
||||
print 'ERROR: malformed config file', e
|
||||
sys.exit()
|
||||
|
||||
bot.persist_dir = os.path.abspath('persist')
|
||||
|
|
|
@ -3,10 +3,6 @@ import json
|
|||
import os
|
||||
|
||||
|
||||
def load():
|
||||
return
|
||||
|
||||
|
||||
def save(conf):
|
||||
json.dump(conf, open('config', 'w'), sort_keys=True, indent=2)
|
||||
|
||||
|
@ -22,14 +18,20 @@ if not os.path.exists('config'):
|
|||
"nick": "skybot",
|
||||
"channels": ["#test"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"disabled_plugins": [],
|
||||
"disabled_commands": [],
|
||||
"acls": {}
|
||||
}''') + '\n')
|
||||
|
||||
bot.config = json.load(open('config'))
|
||||
bot._config_mtime = os.stat('config').st_mtime
|
||||
|
||||
|
||||
def config():
|
||||
# reload config from file if file has changed
|
||||
if bot._config_mtime != os.stat('config').st_mtime:
|
||||
bot.config = json.load(open('config'))
|
||||
try:
|
||||
bot.config = json.load(open('config'))
|
||||
except ValueError, e:
|
||||
print 'ERROR: malformed config!', e
|
||||
|
||||
|
||||
bot._config_mtime = 0
|
||||
|
|
30
core/main.py
30
core/main.py
|
@ -105,18 +105,33 @@ class Handler(object):
|
|||
self.input_queue.put(value)
|
||||
|
||||
|
||||
def dispatch(input, kind, func, args):
|
||||
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:
|
||||
return
|
||||
|
||||
if autohelp and args.get('autohelp', True) and not input.inp:
|
||||
input.reply(func.__doc__)
|
||||
return
|
||||
|
||||
if func._thread:
|
||||
bot.threads[func].put(input)
|
||||
else:
|
||||
thread.start_new_thread(run, (func, input))
|
||||
|
||||
|
||||
def match_command(command):
|
||||
commands = list(bot.commands)
|
||||
|
||||
# do some fuzzy matching
|
||||
prefix = filter(lambda x: x.startswith(command), commands)
|
||||
if len(prefix) == 1:
|
||||
return prefix[0]
|
||||
|
||||
return command
|
||||
|
||||
|
||||
def main(conn, out):
|
||||
inp = Input(conn, *out)
|
||||
|
||||
|
@ -127,9 +142,9 @@ def main(conn, out):
|
|||
if inp.command == 'PRIVMSG':
|
||||
# COMMANDS
|
||||
if inp.chan == inp.nick: # private message, no command prefix
|
||||
prefix = r'^(?:[.!]?|'
|
||||
prefix = r'^(?:[.]?|'
|
||||
else:
|
||||
prefix = r'^(?:[.!]|'
|
||||
prefix = r'^(?:[.]|'
|
||||
|
||||
command_re = prefix + inp.conn.nick
|
||||
command_re += r'[:,]*\s+)(\w+)(?:$|\s+)(.*)'
|
||||
|
@ -137,14 +152,17 @@ def main(conn, out):
|
|||
m = re.match(command_re, inp.lastparam)
|
||||
|
||||
if m:
|
||||
command = m.group(1).lower()
|
||||
trigger = m.group(1).lower()
|
||||
command = match_command(trigger)
|
||||
|
||||
if command in bot.commands:
|
||||
input = Input(conn, *out)
|
||||
input.trigger = trigger
|
||||
input.inp_unstripped = m.group(2)
|
||||
input.inp = m.group(2).strip()
|
||||
input.inp = input.inp_unstripped.strip()
|
||||
|
||||
func, args = bot.commands[command]
|
||||
dispatch(input, "command", func, args)
|
||||
dispatch(input, "command", func, args, autohelp=True)
|
||||
|
||||
# REGEXES
|
||||
for func, args in bot.plugs['regex']:
|
||||
|
|
|
@ -55,9 +55,6 @@ def babel_gen(inp):
|
|||
def babel(inp):
|
||||
".babel <sentence> -- translates <sentence> through multiple languages"
|
||||
|
||||
if not inp:
|
||||
return babel.__doc__
|
||||
|
||||
try:
|
||||
return list(babel_gen(inp))[-1][2]
|
||||
except IOError, e:
|
||||
|
@ -68,9 +65,6 @@ def babel(inp):
|
|||
def babelext(inp):
|
||||
".babelext <sentence> -- like .babel, but with more detailed output"
|
||||
|
||||
if not inp:
|
||||
return babelext.__doc__
|
||||
|
||||
try:
|
||||
babels = list(babel_gen(inp))
|
||||
except IOError, e:
|
||||
|
|
|
@ -15,9 +15,6 @@ MAX_STEPS = 1000000
|
|||
def bf(inp):
|
||||
".bf <prog> -- executes brainfuck program <prog>"""
|
||||
|
||||
if not inp:
|
||||
return bf.__doc__
|
||||
|
||||
program = re.sub('[^][<>+-.,]', '', inp)
|
||||
|
||||
# create a dict of brackets pairs, for speed later on
|
||||
|
|
|
@ -5,9 +5,6 @@ from util import hook, http
|
|||
def bam(inp):
|
||||
".bam [basic|magic|pepsi|jprdy] <message> -- creates a big ass message"
|
||||
|
||||
if not inp:
|
||||
return bam.__doc__
|
||||
|
||||
host = 'http://bigassmessage.com/'
|
||||
path = 'dsx_BAM/boe.php?'
|
||||
params = {'action': 'saveMsg', 'theStyle': 'basic', 'theMessage': inp}
|
||||
|
|
|
@ -8,9 +8,6 @@ from util import hook
|
|||
def choose(inp):
|
||||
".choose <choice1>, <choice2>, ... <choicen> -- makes a decision"
|
||||
|
||||
if not inp:
|
||||
return choose.__doc__
|
||||
|
||||
c = re.findall(r'([^,]+)', inp)
|
||||
if len(c) == 1:
|
||||
c = re.findall(r'(\S+)', inp)
|
||||
|
|
|
@ -30,13 +30,11 @@ def nrolls(count, n):
|
|||
(((n+1)*(2*n+1)/6.-(.5*(1+n))**2)*count)**.5))
|
||||
|
||||
|
||||
@hook.command
|
||||
@hook.command('roll')
|
||||
@hook.command
|
||||
def dice(inp):
|
||||
".dice <diceroll> -- simulates dicerolls, e.g. .dice 2d20-d5+4 roll 2 " \
|
||||
"D20s, subtract 1D5, add 4"
|
||||
if not inp:
|
||||
return dice.__doc__
|
||||
|
||||
spec = whitespace_re.sub('', inp)
|
||||
if not valid_diceroll_re.match(spec):
|
||||
|
|
|
@ -7,9 +7,7 @@ from util import hook, http
|
|||
@hook.command
|
||||
def urban(inp):
|
||||
'''.u/.urban <phrase> -- looks up <phrase> on urbandictionary.com'''
|
||||
if not inp:
|
||||
return urban.__doc__
|
||||
|
||||
|
||||
url = 'http://www.urbandictionary.com/define.php'
|
||||
page = http.get_html(url, term=inp)
|
||||
words = page.xpath("//td[@class='word']")
|
||||
|
@ -28,13 +26,10 @@ def urban(inp):
|
|||
|
||||
|
||||
# define plugin by GhettoWizard & Scaevolus
|
||||
@hook.command('dict')
|
||||
@hook.command('dictionary')
|
||||
@hook.command
|
||||
def define(inp):
|
||||
".define/.dict <word> -- fetches definition of <word>"
|
||||
|
||||
if not inp:
|
||||
return define.__doc__
|
||||
".define/.dictionary <word> -- fetches definition of <word>"
|
||||
|
||||
url = 'http://ninjawords.com/'
|
||||
|
||||
|
|
|
@ -47,9 +47,6 @@ def dotnetpad(lang, code, timeout=10):
|
|||
def fs(inp):
|
||||
".fs -- post a F# code snippet to dotnetpad.net and print the results"
|
||||
|
||||
if not inp:
|
||||
return fs.__doc__
|
||||
|
||||
return dotnetpad('fsharp', inp)
|
||||
|
||||
|
||||
|
@ -57,9 +54,6 @@ def fs(inp):
|
|||
def cs(snippet):
|
||||
".cs -- post a C# code snippet to dotnetpad.net and print the results"
|
||||
|
||||
if not snippet:
|
||||
return cs.__doc__
|
||||
|
||||
file_template = ('using System; '
|
||||
'using System.Linq; '
|
||||
'using System.Collections.Generic; '
|
||||
|
|
|
@ -7,9 +7,6 @@ from util import hook, http
|
|||
def down(inp):
|
||||
'''.down <url> -- checks to see if the site is down'''
|
||||
|
||||
if not inp:
|
||||
return down.__doc__
|
||||
|
||||
if 'http://' not in inp:
|
||||
inp = 'http://' + inp
|
||||
|
||||
|
|
|
@ -12,9 +12,7 @@ ed_url = "http://encyclopediadramatica.com/"
|
|||
def drama(inp):
|
||||
'''.drama <phrase> -- gets first paragraph of Encyclopedia Dramatica ''' \
|
||||
'''article on <phrase>'''
|
||||
if not inp:
|
||||
return drama.__doc__
|
||||
|
||||
|
||||
j = http.get_json(api_url, search=inp)
|
||||
if not j[1]:
|
||||
return 'no results found'
|
||||
|
|
|
@ -5,8 +5,6 @@ from pycparser.cdecl import explain_c_declaration
|
|||
@hook.command
|
||||
def explain(inp):
|
||||
".explain <c expression> -- gives an explanation of C expression"
|
||||
if not inp:
|
||||
return explain.__doc__
|
||||
|
||||
inp = inp.encode('utf8', 'ignore')
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@ from util import hook, http
|
|||
@hook.command
|
||||
def calc(inp):
|
||||
'''.calc <term> -- returns Google Calculator result'''
|
||||
if not inp:
|
||||
return calc.__doc__
|
||||
|
||||
page = http.get('http://www.google.com/search', q=inp)
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@ def api_get(kind, query):
|
|||
@hook.command
|
||||
def gis(inp):
|
||||
'''.gis <term> -- returns first google image result (safesearch off)'''
|
||||
if not inp:
|
||||
return gis.__doc__
|
||||
|
||||
parsed = api_get('images', inp)
|
||||
if not 200 <= parsed['responseStatus'] < 300:
|
||||
|
@ -25,12 +23,10 @@ def gis(inp):
|
|||
['unescapedUrl'] # squares is dumb
|
||||
|
||||
|
||||
@hook.command
|
||||
@hook.command('g')
|
||||
@hook.command
|
||||
def google(inp):
|
||||
'''.g/.google <query> -- returns first google search result'''
|
||||
if not inp:
|
||||
return google.__doc__
|
||||
|
||||
parsed = api_get('web', inp)
|
||||
if not 200 <= parsed['responseStatus'] < 300:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from util import hook
|
||||
|
||||
|
||||
@hook.command
|
||||
@hook.command(autohelp=False)
|
||||
def help(inp, bot=None, pm=None):
|
||||
".help [command] -- gives a list of commands/help for a command"
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import re
|
|||
from util import hook
|
||||
|
||||
|
||||
@hook.command
|
||||
@hook.command(autohelp=False)
|
||||
def mem(inp):
|
||||
".mem -- returns bot's current memory usage -- linux/windows only"
|
||||
|
||||
|
|
|
@ -7,9 +7,6 @@ from util import hook, http
|
|||
def mtg(inp):
|
||||
".mtg <name> -- gets information about Magic the Gathering card <name>"
|
||||
|
||||
if not inp:
|
||||
return mtg.__doc__
|
||||
|
||||
url = 'http://magiccards.info/query?v=card&s=cname'
|
||||
h = http.get_html(url, q=inp)
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@ from util import hook
|
|||
@hook.command
|
||||
def profile(inp):
|
||||
".profile <username> -- links to <username>'s profile on SA"
|
||||
if not inp:
|
||||
return profile.__doc__
|
||||
|
||||
|
||||
return 'http://forums.somethingawful.com/member.php?action=getinfo' + \
|
||||
'&username=' + '+'.join(inp.split())
|
||||
|
|
|
@ -7,11 +7,8 @@ re_lineends = re.compile(r'[\r\n]*')
|
|||
|
||||
|
||||
@hook.command
|
||||
def py(inp):
|
||||
".py <prog> -- executes python code <prog>"
|
||||
|
||||
if not inp:
|
||||
return py.__doc__
|
||||
def python(inp):
|
||||
".python <prog> -- executes python code <prog>"
|
||||
|
||||
res = http.get("http://eval.appspot.com/eval", statement=inp).splitlines()
|
||||
|
||||
|
|
|
@ -83,5 +83,3 @@ def quote(inp, nick='', chan='', db=None):
|
|||
selected_quote = quotes[num - 1]
|
||||
|
||||
return format_quote(selected_quote, num, n_quotes)
|
||||
else:
|
||||
return quote.__doc__
|
||||
|
|
|
@ -6,9 +6,6 @@ from util import hook, http
|
|||
def bible(inp):
|
||||
".bible <passage> -- gets <passage> from the Bible (ESV)"
|
||||
|
||||
if not inp:
|
||||
return bible.__doc__
|
||||
|
||||
base_url = ('http://www.esvapi.org/v2/rest/passageQuery?key=IP&'
|
||||
'output-format=plain-text&include-heading-horizontal-lines&'
|
||||
'include-headings=false&include-passage-horizontal-lines=false&'
|
||||
|
@ -31,9 +28,6 @@ def bible(inp):
|
|||
def koran(inp): # Koran look-up plugin by Ghetto Wizard
|
||||
".koran <chapter.verse> -- gets <chapter.verse> from the Koran"
|
||||
|
||||
if not inp:
|
||||
return koran.__doc__
|
||||
|
||||
url = 'http://quod.lib.umich.edu/cgi/k/koran/koran-idx?type=simple'
|
||||
|
||||
results = http.get_html(url, q1=inp).xpath('//li')
|
||||
|
|
|
@ -44,8 +44,6 @@ def remember(inp, nick='', chan='', db=None):
|
|||
@hook.command
|
||||
def forget(inp, chan='', db=None):
|
||||
".forget <word> -- forgets the mapping that word had"
|
||||
if not inp:
|
||||
return forget.__doc__
|
||||
|
||||
db_init(db)
|
||||
data = get_memory(db, chan, inp)
|
||||
|
|
|
@ -26,9 +26,6 @@ def seeninput(paraml, input=None, db=None, bot=None):
|
|||
def seen(inp, nick='', chan='', db=None):
|
||||
".seen <nick> -- Tell when a nickname was last in active in irc"
|
||||
|
||||
if not inp:
|
||||
return seen.__doc__
|
||||
|
||||
if inp.lower() == nick.lower():
|
||||
return "Have you looked in a mirror lately?"
|
||||
|
||||
|
|
|
@ -5,8 +5,15 @@ from util import hook
|
|||
|
||||
@hook.sieve
|
||||
def sieve_suite(bot, input, func, kind, args):
|
||||
if input.command == 'PRIVMSG' and input.nick.lower()[-3:] == 'bot' \
|
||||
and args.get('ignorebots', True):
|
||||
if input.command == 'PRIVMSG'
|
||||
if input.nick.lower()[-3:] == 'bot' and args.get('ignorebots', True):
|
||||
return None
|
||||
elif input.trigger in bot.config.get('disabled_commands', []):
|
||||
return None
|
||||
|
||||
fn = re.match(r'^plugins.(.+).py$', func._filename)
|
||||
disabled = bot.config.get('disabled_plugins', [])
|
||||
if fn and fn.group(1).lower() in disabled:
|
||||
return None
|
||||
|
||||
acl = bot.config.get('acls', {}).get(func.__name__)
|
||||
|
@ -20,9 +27,4 @@ def sieve_suite(bot, input, func, kind, args):
|
|||
if input.chan.lower() in denied_channels:
|
||||
return None
|
||||
|
||||
fn = re.match(r'^plugins.(.+).py$', func._filename)
|
||||
disabled = bot.config.get('disabled_plugins', {})
|
||||
if fn and fn.group(1).lower() in disabled:
|
||||
return None
|
||||
|
||||
return input
|
||||
|
|
|
@ -8,9 +8,7 @@ from util import hook, http
|
|||
@hook.command
|
||||
def suggest(inp, inp_unstripped=''):
|
||||
".suggest [#n] <phrase> -- gets a random/the nth suggested google search"
|
||||
if not inp:
|
||||
return suggest.__doc__
|
||||
|
||||
|
||||
inp = inp_unstripped
|
||||
m = re.match('^#(\d+) (.+)$', inp)
|
||||
if m:
|
||||
|
|
|
@ -100,9 +100,6 @@ def tag(inp, chan='', db=None):
|
|||
nick, subject = add.groups()
|
||||
return add_tag(db, chan, nick, subject)
|
||||
else:
|
||||
if not inp:
|
||||
return tag.__doc__
|
||||
|
||||
tags = get_tags_by_nick(db, chan, inp)
|
||||
|
||||
if not tags:
|
||||
|
|
|
@ -47,7 +47,7 @@ def tellinput(paraml, input=None, db=None, bot=None):
|
|||
input.notice(reply)
|
||||
|
||||
|
||||
@hook.command
|
||||
@hook.command(autohelp=False)
|
||||
def showtells(inp, nick='', chan='', notice=None, db=None):
|
||||
".showtells -- view all pending tell messages (sent in PM)."
|
||||
|
||||
|
@ -75,7 +75,7 @@ def tell(inp, nick='', chan='', db=None):
|
|||
|
||||
query = inp.split(' ', 1)
|
||||
|
||||
if not inp or len(query) != 2:
|
||||
if len(query) != 2:
|
||||
return tell.__doc__
|
||||
|
||||
user_to = query[0].lower()
|
||||
|
|
|
@ -11,9 +11,6 @@ from util import hook, http
|
|||
def tf(inp):
|
||||
""".tf/.hats <SteamID> -- Shows items waiting to be received in TF2."""
|
||||
|
||||
if not inp:
|
||||
return tf.__doc__
|
||||
|
||||
if inp.isdigit():
|
||||
link = 'profiles'
|
||||
else:
|
||||
|
|
|
@ -31,9 +31,6 @@ def twitter(inp):
|
|||
"tweet from <user>/gets tweet <id>/gets random tweet with #<hashtag>/"\
|
||||
"gets replied tweet from @<user>"
|
||||
|
||||
if not inp:
|
||||
return twitter.__doc__
|
||||
|
||||
def add_reply(reply_name, reply_id):
|
||||
if len(history) == history_max_size:
|
||||
history.pop()
|
||||
|
|
|
@ -46,7 +46,7 @@ def sieve(func):
|
|||
return func
|
||||
|
||||
|
||||
def command(arg, **kwargs):
|
||||
def command(arg=None, **kwargs):
|
||||
args = {}
|
||||
|
||||
def command_wrapper(func):
|
||||
|
|
|
@ -7,14 +7,9 @@ by Vladi
|
|||
from util import hook, http
|
||||
|
||||
|
||||
@hook.command('val')
|
||||
@hook.command('valid')
|
||||
@hook.command
|
||||
def validate(inp):
|
||||
".val/.valid/.validate <url> -- runs url through w3c markup validator"
|
||||
|
||||
if not inp:
|
||||
return validate.__doc__
|
||||
".validate <url> -- runs url through w3c markup validator"
|
||||
|
||||
if not inp.startswith('http://'):
|
||||
inp = 'http://' + inp
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
from util import hook, http
|
||||
|
||||
|
||||
@hook.command
|
||||
@hook.command(autohelp=False)
|
||||
def weather(inp, nick='', server='', reply=None, db=None):
|
||||
".weather <location> [dontsave] -- gets weather data from Google"
|
||||
|
||||
|
|
|
@ -18,9 +18,6 @@ def wiki(inp):
|
|||
'''.w/.wiki <phrase> -- gets first sentence of wikipedia ''' \
|
||||
'''article on <phrase>'''
|
||||
|
||||
if not inp:
|
||||
return wiki.__doc__
|
||||
|
||||
x = http.get_xml(search_url, search=inp)
|
||||
|
||||
ns = '{http://opensearch.org/searchsuggest2}'
|
||||
|
|
|
@ -3,15 +3,12 @@ import re
|
|||
from util import hook, http
|
||||
|
||||
|
||||
@hook.command
|
||||
@hook.command('wa')
|
||||
@hook.command
|
||||
def wolframalpha(inp):
|
||||
".wa/.wolframalpha <query> -- scrapes Wolfram Alpha's" \
|
||||
"results for <query>"
|
||||
|
||||
if not inp:
|
||||
return wolframalpha.__doc__
|
||||
|
||||
url = "http://www.wolframalpha.com/input/?asynchronous=false"
|
||||
|
||||
h = http.get_html(url, i=inp)
|
||||
|
|
|
@ -61,8 +61,6 @@ def youtube_url(match):
|
|||
@hook.command
|
||||
def youtube(inp):
|
||||
'.youtube <query> -- returns the first YouTube search result for <query>'
|
||||
if not inp:
|
||||
return youtube.__doc__
|
||||
|
||||
j = http.get_json(search_api_url, q=inp)
|
||||
|
||||
|
|
Loading…
Reference in New Issue