~ubuntu-branches/ubuntu/utopic/gozerbot/utopic

« back to all changes in this revision

Viewing changes to build/lib/gozerbot/commands.py

  • Committer: Package Import Robot
  • Author(s): Jeremy Malcolm
  • Date: 2012-04-03 21:58:28 UTC
  • mfrom: (3.1.11 sid)
  • Revision ID: package-import@ubuntu.com-20120403215828-6mik0tzug5na93la
Tags: 0.99.1-2
* Removes logfiles on purge (Closes: #668767)
* Reverted location of installed files back to /usr/lib/gozerbot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# gozerbot/commands.py
 
2
#
 
3
#
 
4
 
 
5
""" 
 
6
 
 
7
    This module implements the commands a user can give. It also contains 
 
8
    the global cmnds object to which all commands are added.
 
9
 
 
10
    example:
 
11
 
 
12
    ::
 
13
 
 
14
        cmnds.add('hello', handle_hello, 'USER')
 
15
 
 
16
 
 
17
    :var cmnds: global commands object
 
18
 
 
19
"""
 
20
 
 
21
__copyright__ = 'this file is in the public domain'
 
22
 
 
23
# IMPORT SECTION
 
24
 
 
25
# gozerbot imports
 
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
 
36
 
 
37
# basic imports
 
38
import sys, re, copy, types, thread
 
39
 
 
40
# END IMPORT
 
41
 
 
42
# LOCK SECTION
 
43
 
 
44
# command lock
 
45
commandlock = thread.allocate_lock()
 
46
locked = lockdec(commandlock)
 
47
 
 
48
# END LOCK
 
49
 
 
50
class Command(object):
 
51
 
 
52
    """
 
53
        implements a command.
 
54
 
 
55
        :param func: the function to call when a commands gets triggered
 
56
        :param perm: permissions the command needs before it gets fired
 
57
        :type perm: list
 
58
        :param plugname: the plugin this commands is implemented in
 
59
        :type param: string
 
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
 
65
        :type options: dict
 
66
 
 
67
    """
 
68
 
 
69
    def __init__(self, func, perm, plugname, speed=5, threaded=False, allowqueue=True, options={'--speed': 5, '--chan': '', '--filter': '', '--how': 'msg'}):
 
70
 
 
71
        self.name = str(func) # function name is string representation of the function 
 
72
        self.func = func # function to call
 
73
 
 
74
        # make sure permission(s) are stored in a list
 
75
        if type(perm) == types.ListType:
 
76
            self.perms = list(perm)
 
77
        else:
 
78
            self.perms = [perm, ]
 
79
 
 
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 
 
85
        self.activate = True
 
86
        
 
87
class Commands(dict):
 
88
 
 
89
    """ 
 
90
        the commands object is a dict containing the commands. dict key is the 
 
91
        command (1 word).
 
92
 
 
93
    """
 
94
 
 
95
    def __setitem__(self, name, value):
 
96
 
 
97
        """ set command. """
 
98
 
 
99
        dict.__setitem__(self, name, value)
 
100
 
 
101
    def __delitem__(self, name):
 
102
 
 
103
        """ delete command. """
 
104
 
 
105
        dict.__delitem__(self, name)
 
106
 
 
107
    def size(self):
 
108
 
 
109
        """
 
110
            nr of commands.
 
111
 
 
112
            :rtype: integer
 
113
 
 
114
            .. literalinclude:: ../../gozerbot/commands.py
 
115
                :pyobject: Commands.size
 
116
 
 
117
        """
 
118
 
 
119
        return len(self)
 
120
 
 
121
    def activate(self, plugname):
 
122
        cp = dict(self)
 
123
        for i in cp.values():
 
124
            if i.plugname == plugname:
 
125
                i.activate = True
 
126
 
 
127
    def disable(self, plugname):
 
128
        cp = dict(self)
 
129
        for i in cp.values():
 
130
            if i.plugname == plugname:
 
131
                i.activate = False
 
132
 
 
133
    def whatperms(self):
 
134
 
 
135
        """
 
136
            return all possible permissions.
 
137
 
 
138
            :rtype: list
 
139
 
 
140
            .. literalinclude:: ../../gozerbot/commands.py
 
141
                :pyobject: Commands.whatperms
 
142
 
 
143
        """
 
144
 
 
145
        result = []
 
146
 
 
147
        # loop over the commands and collect all possible permissions
 
148
        cp = dict(self)
 
149
        for i in cp.values():
 
150
            for j in i.perms:
 
151
                if j not in result:
 
152
                    result.append(j)
 
153
 
 
154
        return result
 
155
 
 
156
    def list(self, perm):
 
157
 
 
158
        """
 
159
            list commands with permission perm.
 
160
 
 
161
            :param perm: the permission
 
162
            :type perm: string
 
163
            :rtype: list
 
164
 
 
165
            .. literalinclude:: ../../gozerbot/commands.py
 
166
                :pyobject: Commands.list
 
167
 
 
168
        """
 
169
 
 
170
        result = []
 
171
 
 
172
        # make sure perm is a list
 
173
        if type(perm) != types.ListType:
 
174
            perm = perm.upper()
 
175
            perms = [perm, ]
 
176
        else:
 
177
            perms = perm
 
178
 
 
179
        # loop over commands collecting all command having permission
 
180
        cp = dict(self)
 
181
        for name, cmnd in cp.items():
 
182
            for i in perms:
 
183
                if i in cmnd.perms:
 
184
                    result.append(name)
 
185
 
 
186
        return result
 
187
 
 
188
    def getfuncnames(self, plug):
 
189
 
 
190
        """
 
191
            get all function names of commands in a plugin.
 
192
 
 
193
            :param plug: plugname
 
194
            :type plug: string
 
195
            :rtype: list
 
196
 
 
197
            .. literalinclude:: ../../gozerbot/commands.py
 
198
                :pyobject: Commands.getfuncnames
 
199
 
 
200
        """
 
201
 
 
202
        result = []
 
203
 
 
204
        # collect function names 
 
205
        cp = dict(self)
 
206
        for i in cp.values():
 
207
            if i.plugname == plug:
 
208
                result.append(i.func.func_name)
 
209
 
 
210
        return result
 
211
 
 
212
    def getoptions(self, command):
 
213
 
 
214
        """
 
215
            get options of a command.
 
216
 
 
217
            :param command: the command to get options for
 
218
            :type command: string
 
219
            :rtype: dict
 
220
 
 
221
            .. literalinclude:: ../../gozerbot/commands.py
 
222
                :pyobject: Commands.getoptions
 
223
 
 
224
        """
 
225
 
 
226
        cp = dict(self)
 
227
        for name, cmnd in cp.iteritems():
 
228
            if name == command:
 
229
                return makeoptions(defaultevent, cmnd.options)
 
230
 
 
231
    #@locked
 
232
    def permoverload(self, name, perms):
 
233
 
 
234
        """
 
235
             overload permission of function with funcname.
 
236
 
 
237
            :param name: name of command to overload permission of
 
238
            :type name: string
 
239
            :param perms: permission to overload the command with
 
240
            :type perms: list
 
241
            :rtype: boolean
 
242
 
 
243
            .. literalinclude:: ../../gozerbot/commands.py
 
244
                :pyobject: Commands.permoverload
 
245
 
 
246
        """
 
247
 
 
248
        # make sure all perms are uppercase
 
249
        perms = [perm.upper() for perm in perms]
 
250
 
 
251
        # overload the command with given permissions
 
252
        for com in self.values():
 
253
            try:
 
254
                if com.func.func_name == name:
 
255
                    com.perms = perms
 
256
                    return True
 
257
            except AttributeError:
 
258
                rlog(10, 'commands', "permoverload: no %s function" % name)
 
259
        return False
 
260
 
 
261
    #@locked
 
262
    def add(self, cmnd, func, perm, speed=5, threaded=False, allowqueue=True, options={'--speed': 5, '--chan': '', '--filter': '', '--how': 'msg'}):
 
263
        
 
264
        """
 
265
            add a command.
 
266
 
 
267
            :param func: the function to call when a commands gets triggered
 
268
            :param perm: permissions the command needs before it gets fired
 
269
            :type perm: list
 
270
            :param plugname: the plugin this commands is implemented in
 
271
            :type param: string
 
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
 
277
            :type options: dict
 
278
 
 
279
            .. literalinclude:: ../../gozerbot/commands.py
 
280
                :pyobject: Commands.add
 
281
 
 
282
        """
 
283
 
 
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)
 
289
            return
 
290
 
 
291
        rlog(-3, 'commands', 'added %s (%s) ' % (cmnd, plugname))
 
292
 
 
293
        # add command
 
294
        self[cmnd.lower()] = Command(func, perm, plugname, speed, threaded, allowqueue, options)
 
295
        self[cmnd.lower()].name = cmnd.lower()
 
296
 
 
297
    def apropos(self, txt, perms=[]):
 
298
 
 
299
        """
 
300
            search for command.
 
301
 
 
302
            :param txt: txt to search commands with
 
303
            :type txt: string
 
304
            :param perms: contain permission that must match first
 
305
            :type perms: list
 
306
            :rtype: list
 
307
 
 
308
            .. literalinclude:: ../../gozerbot/commands.py
 
309
                :pyobject: Commands.apropos
 
310
 
 
311
        """
 
312
 
 
313
        result = []
 
314
 
 
315
        #  loop over commands collecting all commands that contain given txt
 
316
        cp = dict(self)
 
317
        for name, cmnd in cp.iteritems():
 
318
            if perms:
 
319
                go = False
 
320
                for i in perms:
 
321
                    if i in cmnd.perms:
 
322
                        go = True
 
323
                if not go:
 
324
                    continue                
 
325
            if re.search(txt, name):
 
326
                result.append(name)
 
327
 
 
328
        return result
 
329
 
 
330
    #@locked
 
331
    def unload(self, plugname):
 
332
 
 
333
        """
 
334
            unload plugin commands.
 
335
 
 
336
            :param plugname: name of the plugin that needs to be unloaded
 
337
            :type plugname: string
 
338
            :rtype: boolean
 
339
 
 
340
            .. literalinclude:: ../../gozerbot/commands.py
 
341
                :pyobject: Commands.unload
 
342
 
 
343
        """
 
344
 
 
345
        results = []
 
346
 
 
347
        # look for the commands registerd in plugin
 
348
        for name, cmnd in self.iteritems():
 
349
            if cmnd.plugname == plugname:
 
350
                results.append(name)
 
351
 
 
352
        got = False
 
353
 
 
354
        # remove commands
 
355
        for name in results:
 
356
 
 
357
            try:
 
358
                del self[name]
 
359
                rlog(-3, 'commands', 'unloaded %s (%s)' % (name, plugname))
 
360
                got = True
 
361
            except KeyError:
 
362
                got = False
 
363
 
 
364
        if got:
 
365
            return True
 
366
 
 
367
    def whereis(self, command):
 
368
 
 
369
        """
 
370
            locate plugin a command is registered in.
 
371
 
 
372
            :param command: command to search for
 
373
            :type command: string
 
374
            :rtype: list
 
375
 
 
376
            .. literalinclude:: ../../gozerbot/commands.py
 
377
                :pyobject: Commands.whereis
 
378
 
 
379
        """
 
380
 
 
381
        result = []
 
382
 
 
383
        # find plugin 
 
384
        cp = dict(self)
 
385
        for name, cmnd in cp.iteritems():
 
386
            if name == command:
 
387
                if not cmnd.plugname in result:
 
388
                    result.append(cmnd.plugname)
 
389
 
 
390
        return result
 
391
 
 
392
    def perms(self, name):
 
393
 
 
394
        """
 
395
            get permission of command.
 
396
 
 
397
            :param command: command to lookup permissions for
 
398
            :type command: string
 
399
            :rtype: list
 
400
 
 
401
            .. literalinclude:: ../../gozerbot/commands.py
 
402
                :pyobject: Commands.perms
 
403
 
 
404
        """
 
405
 
 
406
        name = name.lower()
 
407
 
 
408
        if self.has_key(name):
 
409
            return self[name].perms
 
410
        else:
 
411
            return []
 
412
 
 
413
    #@locked
 
414
    def setperm(self, command, perm):
 
415
 
 
416
        """
 
417
            set permission of command.
 
418
 
 
419
            :param command: command to set permission of
 
420
            :type command: string
 
421
            :param perm: the permission
 
422
            :type perm: string
 
423
            :rtype: boolean
 
424
 
 
425
            .. literalinclude:: ../../gozerbot/commands.py
 
426
                :pyobject: Commands.setperm
 
427
 
 
428
        """
 
429
 
 
430
        command = command.lower()
 
431
        perm = perm.upper()
 
432
 
 
433
        if self.has_key(command):
 
434
            if perm not in self[command].perms:
 
435
                self[command].perms.append(perm)
 
436
            return True
 
437
        return False
 
438
 
 
439
    def getcommand(self, txt):
 
440
 
 
441
        """
 
442
            return command matching txt.
 
443
 
 
444
            :param txt: txt to match commands against
 
445
            :type txt: string
 
446
 
 
447
            .. literalinclude:: ../../gozerbot/commands.py
 
448
                :pyobject: Commands.getcommand
 
449
 
 
450
        """
 
451
 
 
452
        textlist = txt.split()
 
453
 
 
454
        if not textlist:
 
455
            return None
 
456
 
 
457
        cmnd = textlist[0].lower()
 
458
        if self.has_key(cmnd):
 
459
            com = self[cmnd] # the command
 
460
            return com
 
461
        else:
 
462
            return None
 
463
 
 
464
    def options(self, command):
 
465
 
 
466
        """
 
467
            return options dict of command.
 
468
 
 
469
            :param command: the command to get the options of
 
470
            :type command: string
 
471
 
 
472
            .. literalinclude:: ../../gozerbot/commands.py
 
473
                :pyobject: Commands.options
 
474
 
 
475
        """
 
476
 
 
477
        try:
 
478
            return self[command].options
 
479
        except KeyError:
 
480
            return 
 
481
 
 
482
    def getcommands(self, plugin):
 
483
 
 
484
        """
 
485
            get all commands of a plugin.
 
486
 
 
487
            :param plugin: the plugin to get commands of
 
488
            :type plugin: string
 
489
 
 
490
            .. literalinclude:: ../../gozerbot/commands.py
 
491
                :pyobject: Commands.getcommands
 
492
 
 
493
        """
 
494
 
 
495
        result = []
 
496
        
 
497
        tmp = dict(self)
 
498
        for name, cmnd in tmp.iteritems():
 
499
            if cmnd.plugname == plugin:
 
500
                result.append(name)
 
501
 
 
502
        return result
 
503
 
 
504
    #@locked
 
505
    def dispatch(self, com, txt, wait=False):
 
506
 
 
507
        """
 
508
            dispatch command.
 
509
 
 
510
            :param com: the command object to dispatch with
 
511
            :type com: Command
 
512
 
 
513
            .. literalinclude:: ../../gozerbot/commands.py
 
514
                :pyobject: Commands.dispatch
 
515
 
 
516
        """
 
517
 
 
518
        if com.threaded:
 
519
            thread = start_new_thread(com.func, (txt, ))
 
520
            if wait:
 
521
                thread.join()
 
522
        else:
 
523
            cmndrunners[10-com.speed].put(com.name, com.func, txt)
 
524
        return 1
 
525
 
 
526
class Botcommands(Commands):
 
527
 
 
528
    """
 
529
        commands for the bot .. dispatch with (bot, ircevent) as arguments. 
 
530
 
 
531
    """
 
532
 
 
533
    #@locked
 
534
    def dispatch(self, com, bot, ievent, wait=False):
 
535
 
 
536
        """
 
537
             dispatch on event passing bot and ievent as arguments.
 
538
 
 
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
 
544
             :rtype: boolean
 
545
 
 
546
             .. literalinclude:: ../../gozerbot/commands.py
 
547
                 :pyobject: Botcommands.dispatch
 
548
 
 
549
        """
 
550
 
 
551
        if not com.activate:
 
552
            return False
 
553
 
 
554
        if bot.stopped:
 
555
            return False
 
556
 
 
557
        #ievent = copy.deepcopy(ieventin)
 
558
 
 
559
        # stats
 
560
        stats.up('cmnds', com.name)
 
561
        stats.up('cmnds', com.plugname)
 
562
        stats.up('cmnds', 'speed%s' % com.speed)
 
563
 
 
564
        # execute command
 
565
        if com.threaded or ievent.threaded:
 
566
            thread = start_bot_command(com.func, (bot, ievent))
 
567
            #if thread and wait:
 
568
            #    thread.join()
 
569
        else:   
 
570
            speed = ievent.speed or com.speed
 
571
            ievent.speed = speed
 
572
            cmndrunners.put(com.name, com.func, bot, ievent)
 
573
        return True
 
574
 
 
575
# INIT SECTION
 
576
 
 
577
cmnds = Botcommands()
 
578
 
 
579
# END INIT