115 lines
3.1 KiB
Python
115 lines
3.1 KiB
Python
import inspect
|
|
import thread
|
|
import traceback
|
|
import Queue
|
|
|
|
|
|
def _isfunc(x):
|
|
if type(x) == type(_isfunc):
|
|
return True
|
|
return False
|
|
|
|
|
|
def _hook_add(func, add, name=''):
|
|
if not hasattr(func, '_skybot_hook'):
|
|
func._skybot_hook = []
|
|
func._skybot_hook.append(add)
|
|
if not hasattr(func, '_skybot_args'):
|
|
argspec = inspect.getargspec(func)
|
|
if name:
|
|
n_args = len(argspec.args)
|
|
if argspec.defaults:
|
|
n_args -= len(argspec.defaults)
|
|
if argspec.keywords:
|
|
n_args -= 1
|
|
if argspec.varargs:
|
|
n_args -= 1
|
|
if n_args != 1:
|
|
err = '%ss must take 1 non-keyword argument (%s)' % (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])
|
|
if argspec.keywords:
|
|
args.append(0) # means kwargs present
|
|
func._skybot_args = args
|
|
|
|
|
|
def _make_sig(f):
|
|
return f.func_code.co_filename, f.func_name, f.func_code.co_firstlineno
|
|
|
|
|
|
def sieve(func):
|
|
if func.func_code.co_argcount != 4:
|
|
raise ValueError(
|
|
'sieves must take 4 arguments: (bot, input, func, args)')
|
|
_hook_add(func, ['sieve', (_make_sig(func), func)])
|
|
return func
|
|
|
|
|
|
def command(func=None, hook=None, **kwargs):
|
|
args = {}
|
|
|
|
def command_wrapper(func):
|
|
args.setdefault('name', func.func_name)
|
|
args.setdefault('hook', args['name'] + r'(?:\s+|$)(.*)')
|
|
_hook_add(func, ['command', (_make_sig(func), func, args)], 'command')
|
|
return func
|
|
|
|
if hook is not None or kwargs or not _isfunc(func):
|
|
if func is not None:
|
|
args['name'] = func
|
|
if hook is not None:
|
|
args['hook'] = hook
|
|
args.update(kwargs)
|
|
return command_wrapper
|
|
else:
|
|
return command_wrapper(func)
|
|
|
|
|
|
def event(arg=None, **kwargs):
|
|
args = kwargs
|
|
|
|
def event_wrapper(func):
|
|
args['name'] = func.func_name
|
|
args['prefix'] = False
|
|
args.setdefault('events', '*')
|
|
_hook_add(func, ['event', (_make_sig(func), func, args)], 'event')
|
|
return func
|
|
|
|
if _isfunc(arg):
|
|
return event_wrapper(arg, kwargs)
|
|
else:
|
|
if arg is not None:
|
|
args['events'] = arg.split()
|
|
return event_wrapper
|
|
|
|
|
|
def tee(func, **kwargs):
|
|
"passes _all_ input lines to function, in order (skips sieves)"
|
|
|
|
if func.func_code.co_argcount != 2:
|
|
raise ValueError('tees must take 2 arguments: (bot, input)')
|
|
|
|
_hook_add(func, ['tee', (_make_sig(func), func, kwargs)])
|
|
func._iqueue = Queue.Queue()
|
|
|
|
def trampoline(func):
|
|
input = None
|
|
while True:
|
|
input = func._iqueue.get()
|
|
if input == StopIteration:
|
|
return
|
|
try:
|
|
func(*input)
|
|
except Exception:
|
|
traceback.print_exc(Exception)
|
|
|
|
thread.start_new_thread(trampoline, (func,))
|
|
|
|
return func
|