7
This module implements the commands a user can give. It also contains
8
the global cmnds object to which all commands are added.
14
cmnds.add('hello', handle_hello, 'USER')
17
:var cmnds: global commands object
21
__copyright__ = 'this file is in the public domain'
26
from gozerbot.stats import stats
27
from utils.generic import makeoptions
28
from eventbase import defaultevent
29
from config import config
30
from utils.log import rlog
31
from utils.trace import calledfrom
32
from utils.exception import handle_exception
33
from utils.locking import lockdec
34
from runner import cmndrunners
35
from threads.thr import start_new_thread, start_bot_command
38
import sys, re, copy, types, thread
45
commandlock = thread.allocate_lock()
46
locked = lockdec(commandlock)
50
class Command(object):
55
:param func: the function to call when a commands gets triggered
56
:param perm: permissions the command needs before it gets fired
58
:param plugname: the plugin this commands is implemented in
60
:param threaded: determines if the command has to be run in its own thread
61
:type threaded: False or True
62
:param allowqueue: determines if output of this commands can be used in pipeline queues
63
:type threaded: False or True
64
:param options: options for this command
69
def __init__(self, func, perm, plugname, speed=5, threaded=False, allowqueue=True, options={'--speed': 5, '--chan': '', '--filter': '', '--how': 'msg'}):
71
self.name = str(func) # function name is string representation of the function
72
self.func = func # function to call
74
# make sure permission(s) are stored in a list
75
if type(perm) == types.ListType:
76
self.perms = list(perm)
80
self.plugname = plugname # plugin name
81
self.speed = copy.deepcopy(speed) # speed to execute command with
82
self.threaded = copy.deepcopy(threaded) # set if threaded exec is required
83
self.allowqueue = copy.deepcopy(allowqueue) # set if command is allowed to be used in pipeline
84
self.options = dict(options) # options set in the command
90
the commands object is a dict containing the commands. dict key is the
95
def __setitem__(self, name, value):
99
dict.__setitem__(self, name, value)
101
def __delitem__(self, name):
103
""" delete command. """
105
dict.__delitem__(self, name)
114
.. literalinclude:: ../../gozerbot/commands.py
115
:pyobject: Commands.size
121
def activate(self, plugname):
123
for i in cp.values():
124
if i.plugname == plugname:
127
def disable(self, plugname):
129
for i in cp.values():
130
if i.plugname == plugname:
136
return all possible permissions.
140
.. literalinclude:: ../../gozerbot/commands.py
141
:pyobject: Commands.whatperms
147
# loop over the commands and collect all possible permissions
149
for i in cp.values():
156
def list(self, perm):
159
list commands with permission perm.
161
:param perm: the permission
165
.. literalinclude:: ../../gozerbot/commands.py
166
:pyobject: Commands.list
172
# make sure perm is a list
173
if type(perm) != types.ListType:
179
# loop over commands collecting all command having permission
181
for name, cmnd in cp.items():
188
def getfuncnames(self, plug):
191
get all function names of commands in a plugin.
193
:param plug: plugname
197
.. literalinclude:: ../../gozerbot/commands.py
198
:pyobject: Commands.getfuncnames
204
# collect function names
206
for i in cp.values():
207
if i.plugname == plug:
208
result.append(i.func.func_name)
212
def getoptions(self, command):
215
get options of a command.
217
:param command: the command to get options for
218
:type command: string
221
.. literalinclude:: ../../gozerbot/commands.py
222
:pyobject: Commands.getoptions
227
for name, cmnd in cp.iteritems():
229
return makeoptions(defaultevent, cmnd.options)
232
def permoverload(self, name, perms):
235
overload permission of function with funcname.
237
:param name: name of command to overload permission of
239
:param perms: permission to overload the command with
243
.. literalinclude:: ../../gozerbot/commands.py
244
:pyobject: Commands.permoverload
248
# make sure all perms are uppercase
249
perms = [perm.upper() for perm in perms]
251
# overload the command with given permissions
252
for com in self.values():
254
if com.func.func_name == name:
257
except AttributeError:
258
rlog(10, 'commands', "permoverload: no %s function" % name)
262
def add(self, cmnd, func, perm, speed=5, threaded=False, allowqueue=True, options={'--speed': 5, '--chan': '', '--filter': '', '--how': 'msg'}):
267
:param func: the function to call when a commands gets triggered
268
:param perm: permissions the command needs before it gets fired
270
:param plugname: the plugin this commands is implemented in
272
:param threaded: determines if the command has to be run in its own thread
273
:type threaded: boolean
274
:param allowqueue: determines if output of this commands can be used in pipeline queues
275
:type threaded: boolean
276
:param options: options for this command
279
.. literalinclude:: ../../gozerbot/commands.py
280
:pyobject: Commands.add
284
# plugin where the command is added
285
plugname = calledfrom(sys._getframe(0))
286
# check if plugin is in loadlist .. if not dont register command.
287
if config['loadlist'] and plugname not in config['loadlist']:
288
rlog(1, 'commands', 'NOT LOADING %s' % plugname)
291
rlog(-3, 'commands', 'added %s (%s) ' % (cmnd, plugname))
294
self[cmnd.lower()] = Command(func, perm, plugname, speed, threaded, allowqueue, options)
295
self[cmnd.lower()].name = cmnd.lower()
297
def apropos(self, txt, perms=[]):
302
:param txt: txt to search commands with
304
:param perms: contain permission that must match first
308
.. literalinclude:: ../../gozerbot/commands.py
309
:pyobject: Commands.apropos
315
# loop over commands collecting all commands that contain given txt
317
for name, cmnd in cp.iteritems():
325
if re.search(txt, name):
331
def unload(self, plugname):
334
unload plugin commands.
336
:param plugname: name of the plugin that needs to be unloaded
337
:type plugname: string
340
.. literalinclude:: ../../gozerbot/commands.py
341
:pyobject: Commands.unload
347
# look for the commands registerd in plugin
348
for name, cmnd in self.iteritems():
349
if cmnd.plugname == plugname:
359
rlog(-3, 'commands', 'unloaded %s (%s)' % (name, plugname))
367
def whereis(self, command):
370
locate plugin a command is registered in.
372
:param command: command to search for
373
:type command: string
376
.. literalinclude:: ../../gozerbot/commands.py
377
:pyobject: Commands.whereis
385
for name, cmnd in cp.iteritems():
387
if not cmnd.plugname in result:
388
result.append(cmnd.plugname)
392
def perms(self, name):
395
get permission of command.
397
:param command: command to lookup permissions for
398
:type command: string
401
.. literalinclude:: ../../gozerbot/commands.py
402
:pyobject: Commands.perms
408
if self.has_key(name):
409
return self[name].perms
414
def setperm(self, command, perm):
417
set permission of command.
419
:param command: command to set permission of
420
:type command: string
421
:param perm: the permission
425
.. literalinclude:: ../../gozerbot/commands.py
426
:pyobject: Commands.setperm
430
command = command.lower()
433
if self.has_key(command):
434
if perm not in self[command].perms:
435
self[command].perms.append(perm)
439
def getcommand(self, txt):
442
return command matching txt.
444
:param txt: txt to match commands against
447
.. literalinclude:: ../../gozerbot/commands.py
448
:pyobject: Commands.getcommand
452
textlist = txt.split()
457
cmnd = textlist[0].lower()
458
if self.has_key(cmnd):
459
com = self[cmnd] # the command
464
def options(self, command):
467
return options dict of command.
469
:param command: the command to get the options of
470
:type command: string
472
.. literalinclude:: ../../gozerbot/commands.py
473
:pyobject: Commands.options
478
return self[command].options
482
def getcommands(self, plugin):
485
get all commands of a plugin.
487
:param plugin: the plugin to get commands of
490
.. literalinclude:: ../../gozerbot/commands.py
491
:pyobject: Commands.getcommands
498
for name, cmnd in tmp.iteritems():
499
if cmnd.plugname == plugin:
505
def dispatch(self, com, txt, wait=False):
510
:param com: the command object to dispatch with
513
.. literalinclude:: ../../gozerbot/commands.py
514
:pyobject: Commands.dispatch
519
thread = start_new_thread(com.func, (txt, ))
523
cmndrunners[10-com.speed].put(com.name, com.func, txt)
526
class Botcommands(Commands):
529
commands for the bot .. dispatch with (bot, ircevent) as arguments.
534
def dispatch(self, com, bot, ievent, wait=False):
537
dispatch on event passing bot and ievent as arguments.
539
:param com: the command object
540
:type com: gozerbot.commands.Command
541
:param bot: the bot this command is given on
542
:type bot: gozerbot.botbase.BotBase
543
:param ievent: the event triggering this command
546
.. literalinclude:: ../../gozerbot/commands.py
547
:pyobject: Botcommands.dispatch
557
#ievent = copy.deepcopy(ieventin)
560
stats.up('cmnds', com.name)
561
stats.up('cmnds', com.plugname)
562
stats.up('cmnds', 'speed%s' % com.speed)
565
if com.threaded or ievent.threaded:
566
thread = start_bot_command(com.func, (bot, ievent))
570
speed = ievent.speed or com.speed
572
cmndrunners.put(com.name, com.func, bot, ievent)
577
cmnds = Botcommands()