5
""" provide plugin infrastructure """
7
__copyright__ = 'this file is in the public domain'
11
from gozerbot.stats import stats
12
from gozerbot.tests import tests
13
from gozerbot.datadir import datadir
14
from users import users
15
from irc.monitor import outmonitor, saymonitor
16
from xmpp.monitor import xmppmonitor
17
from utils.log import rlog
18
from utils.exception import handle_exception
19
from utils.generic import checkchan
20
from utils.locking import lockdec, funclocked, Locked
21
from utils.generic import plugnames, waitforqueue, uniqlist, makeoptions, makeargrest, cleanpycfile
22
from gozerimport import gozer_import, force_import
23
from persist.persist import Persist
24
from persist.persistconfig import PersistConfig
25
from config import config
26
from commands import cmnds
27
from callbacks import callbacks, jcallbacks, gn_callbacks
28
from redispatcher import rebefore, reafter
29
from aliases import aliascheck, aliasget
30
from ignore import shouldignore
31
from threads.thr import start_new_thread, getname
32
from persist.persiststate import PersistState
33
from simplejson import loads
34
from morphs import inputmorphs, outputmorphs
35
from eventbase import EventBase
36
from admin import cmndtable, pluginlist
39
import os, os.path, thread, time, Queue, re, copy
45
loadlock = thread.allocate_lock()
46
loadlocked = lockdec(loadlock)
50
class Plugins(object):
58
self.plugs = {} # dict with the plugins
59
self.reloadlock = thread.allocate_lock()
60
# persisted data for deny of plugins (blacklist)
61
self.plugdeny = Persist(datadir + os.sep + 'plugdeny', init=False)
62
if not self.plugdeny.data:
63
self.plugdeny.data = []
64
# persisted data for allowing of plugins (whitelist)
65
self.plugallow = Persist(datadir + os.sep + 'plugallow', init=False)
66
if not self.plugallow.data:
67
self.plugallow.data = []
68
self.avail = [] # available plugins
69
self.ondisk = [] # plugisn available for reload
70
self.initcalled = [] # plugins which init functions are called
71
self.overloads = {} # plugins to overload
73
for plug in config['plugdeny']:
76
def __getitem__(self, item):
83
if self.plugs.has_key(item):
84
return self.plugs[item]
88
def get(self, item, attr):
91
get attribute of plugin.
93
:param item: plugin to get attribute of
95
:param attr: attribute to fetch
98
.. literalinclude:: ../../gozerbot/plugins.py
99
:pyobject: Plugins.get
103
if self.plugs.has_key(item):
104
return getattr(self.plugs[item], attr)
109
return what permissions are possible.
113
.. literalinclude:: ../../gozerbot/plugins.py
114
:pyobject: Plugins.whatperms
120
# search RE callbacks before the commands
121
for i in rebefore.whatperms():
125
# search the commands
126
for i in cmnds.whatperms():
130
# search RE callbacks after commands
131
for i in reafter.whatperms():
138
def exist(self, name):
141
see if plugin exists.
143
:param name: name of plugin to check for
147
.. literalinclude:: ../../gozerbot/plugins.py
148
:pyobject: Plugins.exist
152
if self.plugs.has_key(name):
156
def disable(self, name):
159
prevent plugin to be loaded. plugins does get imported but
160
commands, callbacks, monitors etc are not enabled.
162
:param name: name of the plugin to disable
165
.. literalinclude:: ../../gozerbot/plugins.py
166
:pyobject: Plugins.disable
171
config['loadlist'].remove(name)
173
self.plugdeny.data.append(name)
179
def enable(self, name):
184
:param name: name of plugin to enable
187
.. literalinclude:: ../../gozerbot/plugins.py
188
:pyobject: Plugins.enable
194
if name not in config['loadlist']:
195
config['loadlist'].append(name)
202
self.plugdeny.data.remove(name)
211
call the size() function in all plugins.
213
:rtype: list .. list of plugin sizes
215
.. literalinclude:: ../../gozerbot/plugins.py
216
:pyobject: Plugins.plugsizes
220
cp = dict(self.plugs)
221
for i, j in cp.iteritems():
223
reslist.append("%s: %s" % (i, j.size()))
224
except AttributeError:
231
list of registered plugins.
233
:rtype: list .. list of enabled plugins
235
.. literalinclude:: ../../gozerbot/plugins.py
236
:pyobject: Plugins.list
243
def plugimport(self, mod, name):
248
:param mod: module to import plugin from
250
:param name: name of the plugin to import
252
:rtype: module .. the plugin
254
.. literalinclude:: ../../gozerbot/plugins.py
255
:pyobject: Plugins.plugimport
259
if name in config['loadlist']:
260
return self.load(mod, name)
262
def regplugin(self, mod, name):
267
:param mod: module to import plugin from
269
:param name: name of the plugin to import
271
:rtype: module .. the plugin
273
.. literalinclude:: ../../gozerbot/plugins.py
274
:pyobject: Plugins.regplugin
280
modname = mod + '.' + name
282
# see if plugin is in deny
283
if name in self.avail:
284
rlog(0, 'plugins', '%s already registered' % name)
287
if name in config['plugdeny']:
288
rlog(0, 'plugins', '%s is in config.plugdeny .. not loading' % name)
291
if name in self.plugdeny.data:
292
rlog(0, 'plugins', '%s.%s in deny .. not loading' % (mod, name))
295
if config.has_key('loadlist') and name not in config['loadlist'] and 'gplugs' in modname and name not in self.plugallow.data:
296
rlog(9, 'plugins', 'not loading %s.%s' % (mod, name))
299
# if plugin is already registered unload it
300
if self.plugs.has_key(name):
301
rlog(10, 'plugins', 'overloading %s plugin with %s version' % (name, mod))
302
self.unloadnosave(name)
304
# create the plugin data dir
305
if hasattr(os, 'mkdir'):
306
if not os.path.isdir(datadir + os.sep + 'plugs'):
307
os.mkdir(datadir + os.sep + 'plugs')
309
if not os.path.isdir(datadir + os.sep + 'plugs' + os.sep + name):
310
os.mkdir(datadir + os.sep + 'plugs' + os.sep + name)
313
plug = self.plugimport(mod, name)
316
rlog(0, 'plugins', "%s.%s registered" % (mod, name))
318
if name not in self.avail:
319
self.avail.append(name)
324
rlog(10, 'plugins', "can't import %s.%s .. try plug-enable" % (mod, name))
326
def showregistered(self):
329
show registered plugins.
331
.. literalinclude:: ../../gozerbot/plugins.py
332
:pyobject: Plugins.showregistered
337
rlog(10, 'plugins', 'registered %s' % ' .. '.join(self.avail))
340
def regdir(self, dirname, exclude=[]):
343
register a directory.
345
:param dirname: directory to import plugins from
346
:type dirname: string
347
:param exclude: plugins to exclude from importing
348
:type exclude: list .. list of plugin names
349
:rtype: list .. list of plugin names that are registered
351
.. literalinclude:: ../../gozerbot/plugins.py
352
:pyobject: Plugins.regdir
358
for plug in plugnames(dirname):
359
if plug in exclude or plug.startswith('.'):
362
self.regplugin(dirname, plug)
366
self.ondisk.extend(plugs)
372
register core plugins.
374
.. literalinclude:: ../../gozerbot/plugins.py
375
:pyobject: Plugins.regcore
379
self.plugdeny.init([])
380
self.plugallow.init([])
382
plugs = force_import('gozerbot.plugs')
384
for i in plugs.__plugs__:
389
self.regplugin('gozerbot.plugs', i)
390
except Exception, ex:
395
self.ondisk.extend(avail)
402
.. literalinclude:: ../../gozerbot/plugins.py
403
:pyobject: Plugins.enableall
407
for name in self.available():
410
def regplugins(self):
413
register all plugins.
415
.. literalinclude:: ../../gozerbot/plugins.py
416
:pyobject: Plugins.regplugins
423
# check for myplugs directory
424
if os.path.isdir('myplugs'):
425
avail.extend(self.regdir('myplugs'))
427
for i in os.listdir('myplugs'):
429
if i.startswith('.'):
432
if os.path.isdir('myplugs' + os.sep + i):
433
avail.extend(self.regdir('myplugs' + os.sep + i))
435
rlog(10, 'plugins', 'no myplugs directory found')
437
# check for gplugs package
439
gplugs = gozer_import('gplugs')
441
rlog(20, 'plugins', "no gplugs package found")
446
for i in gplugs.__plugs__:
449
self.regplugin('gplugs', i)
451
except Exception, ex:
454
if config.get('db_driver') == "olddb":
455
# check for gplugs package
457
gplugs = gozer_import('gplugs.olddb')
459
rlog(20, 'plugins', "no gplugs.old package found")
464
for i in gplugs.__plugs__:
467
self.regplugin('gplugs.olddb', i)
469
except Exception, ex:
472
# check for gplugs package
474
gplugs = gozer_import('gplugs.alchemy')
476
rlog(20, 'plugins', "no gplugs.alchemy package found")
481
for i in gplugs.__plugs__:
484
self.regplugin('gplugs.alchemy', i)
486
except Exception, ex:
489
self.ondisk.extend(avail)
491
start_new_thread(self.showregistered, ())
493
def readoverload(self):
496
see if there is a permoverload file and if so use it to overload
497
permissions based on function name.
499
.. literalinclude:: ../../gozerbot/plugins.py
500
:pyobject: Plugins.readoverload
505
overloadfile = open(datadir + os.sep + 'permoverload', 'r')
511
for i in overloadfile:
513
splitted = i.split(',')
516
funcname = splitted[0].strip()
518
for j in splitted[1:]:
519
perms.append(j.strip())
521
rlog(10, 'plugins', "permoverload: can't set perms of %s" \
526
rlog(10, 'plugins', "permoverload: no function provided")
530
rlog(10, 'plugins', "permoverload: no permissions \
531
provided for %s" % funcname)
534
self.overloads[funcname] = perms
536
except Exception, ex:
542
overload functions in self.overloads.
544
.. literalinclude:: ../../gozerbot/plugins.py
545
:pyobject: Plugins.overload
548
for funcname, perms in self.overloads.iteritems():
550
if self.permoverload(funcname, perms):
551
rlog(0, 'plugins', '%s permission set to %s' % (funcname, \
557
available plugins not yet registered.
559
.. literalinclude:: ../../gozerbot/plugins.py
560
:pyobject: Plugins.available
567
def saveplug(self, plugname):
570
call save() function of plugin.
572
:param plugname: name of the plugin to call save() on
573
:type plugname: string
575
.. literalinclude:: ../../gozerbot/plugins.py
576
:pyobject: Plugins.saveplug
580
self.plugs[plugname].save()
582
except AttributeError:
591
call registered plugins save.
593
.. literalinclude:: ../../gozerbot/plugins.py
594
:pyobject: Plugins.save
598
for plug in self.plugs.values():
603
except AttributeError:
606
except Exception, ex:
612
call registered plugins configuration save.
614
.. literalinclude:: ../../gozerbot/plugins.py
615
:pyobject: Plugins.save_cfg
619
for plug in self.plugs.values():
621
cfg = getattr(plug, 'cfg')
622
if isinstance(cfg, PersistConfig):
627
except AttributeError:
630
def save_cfgname(self, name):
633
save plugin persisted config data.
635
:param name: name of the plugin to call cfg.save for
638
.. literalinclude:: ../../gozerbot/plugins.py
639
:pyobject: Plugins.save_cfgname
643
plug = self.plugs[name]
644
cfg = getattr(plug, 'cfg')
646
if isinstance(cfg, PersistConfig):
653
except (AttributeError, KeyError):
659
call shutdown on all registered plugins.
661
.. literalinclude:: ../../gozerbot/plugins.py
662
:pyobject: Plugins.exit
669
# call shutdown on all plugins
670
for name, plug in self.plugs.iteritems():
673
shutdown = getattr(plug, 'shutdown')
674
thread = start_new_thread(shutdown, ())
675
threadlist.append((name, thread))
678
self.initcalled.remove(name)
682
except AttributeError:
685
except Exception, ex:
686
rlog(10, 'plugins', 'error shutting down %s: %s' % (name, str(ex)))
688
# join shutdown threads
691
for name, thread in threadlist:
693
rlog(10, 'plugins', '%s shutdown finished' % name)
697
def getoptions(self, command):
700
return options entry of a command.
702
:param command: command name to get options of
703
:type command: string
706
.. literalinclude:: ../../gozerbot/plugins.py
707
:pyobject: Plugins.getoptions
711
return cmnds.getoptions(command)
713
def getdepend(self, plugname):
716
get plugins the plugin depends on. NOT USED ANYMORE ..
718
we use the __depending__ attribute now which checks for the
719
reverse case ala what plugins depends on this plugin. code is
724
# try to import the plugin
725
if plugname in self.plugs:
726
plug = self.plugs[plugname]
728
for mod in ['gozerbot.plugs', 'gplugs', 'myplugs']:
730
plug = gozer_import('%s.%s' % (mod, plugname))
734
# check for the __depend__ attribute
736
depends = plug.__depend__
742
def load(self, mod , name, enable=True):
743
#if name in config['plugdeny']:
745
# force an import of the plugin
746
modname = mod + '.' + name
751
plug = self.plugs[name] = gozer_import(modname)
752
plug.loadtime = time.time()
756
# call plugins init() function
758
rlog(0, 'plugins', 'calling %s init()' % modname)
760
self.initcalled.append(modname)
762
except (AttributeError, KeyError):
765
except Exception, ex:
766
rlog(10, 'plugins', '%s module init failed' % name)
769
rlog(0, 'plugins', 'enabled %s' % name)
775
def reload(self, mod, name, enable=True):
780
:param mod: module to import plugin from
782
:param name: name of the plugin to reload
784
:param enable: whether plugin should be enabled on reload
785
:type enable: boolean
786
:rtype: list .. list of names of reloaded plugins
788
.. literalinclude:: ../../gozerbot/plugins.py
789
:pyobject: Plugins.reload
793
# create the plugin data dir
794
if not os.path.isdir(datadir + os.sep + 'plugs'):
795
os.mkdir(datadir + os.sep + 'plugs')
797
if not os.path.isdir(datadir + os.sep + 'plugs' + os.sep + name):
798
os.mkdir(datadir + os.sep + 'plugs' + os.sep + name)
801
modname = mod + '.' + name
803
# force an import of the plugin
804
plug = self.load(mod, name)
806
# recurse the reload function if plugin is a dir
808
for p in plug.__plugs__:
809
self.load(modname, p)
812
except (KeyError, AttributeError):
815
rlog(0, 'plugins', 'reloaded plugin %s' % modname)
816
reloaded.append(name)
817
self.plugallow.data.append(name)
820
self.plugdeny.data.remove(name)
824
if name not in self.avail:
825
self.avail.append(name)
827
# recurse on plugins the depend on this plugin
829
depends = plug.__depending__
832
rlog(10, 'plugins', 'loading depending plugin %s (%s)' % (plug, name))
833
self.load(mod, plug, False)
834
reloaded.append(plug)
836
except AttributeError:
841
def activate(self, plugname):
842
self.activated[plugname] = True
844
cmnds.activate(plugname)
845
callbacks.activate(plugname)
846
gn_callbacks.activate(plugname)
847
jcallbacks.activate(plugname)
848
rebefore.activate(plugname)
849
reafter.activate(plugname)
850
saymonitor.activate(plugname)
851
outmonitor.activate(plugname)
852
xmppmonitor.activate(plugname)
853
tests.activate(plugname)
854
outputmorphs.activate(plugname)
855
inputmorphs.activate(plugname)
856
except Exception, ex:
860
def down(self, plugname):
861
self.activated[plugname] = False
863
cmnds.disable(plugname)
864
callbacks.disable(plugname)
865
gn_callbacks.disable(plugname)
866
jcallbacks.disable(plugname)
867
rebefore.disable(plugname)
868
reafter.disable(plugname)
869
saymonitor.disable(plugname)
870
outmonitor.disable(plugname)
871
xmppmonitor.disable(plugname)
872
tests.disable(plugname)
873
outputmorphs.disable(plugname)
874
inputmorphs.disable(plugname)
875
except Exception, ex:
879
def unload(self, plugname):
884
:param plugname: name of the plugin to unload
885
:type plugname: string
886
:rtype: list .. list of unloaded plugins
888
.. literalinclude:: ../../gozerbot/plugins.py
889
:pyobject: Plugins.unload
893
# call plugins shutdown function if available
894
unloaded = [plugname, ]
896
# recurse if plugin is dir
898
plug = self.plugs[plugname]
900
for p in plug.__plugs__:
902
raise Exception("same plugin name as dir name (%s)" % plugname)
903
unloaded.extend(self.unload(p))
905
except (KeyError, AttributeError):
909
for plugname in unloaded:
910
self.saveplug(plugname)
911
self.unloadnosave(plugname)
914
self.avail.remove(plugname)
921
def unloadnosave(self, plugname):
924
unload plugin without saving.
926
:param plugname: name of the plugin to unload
927
:type plugname: string
928
:rtype: list .. list of unloaded plugins
930
.. literalinclude:: ../../gozerbot/plugins.py
931
:pyobject: Plugins.unloadnosave
935
# call shutdown function
937
self.plugs[plugname].shutdown()
938
rlog(10, 'plugins', '%s shutdown called' % plugname)
940
except (AttributeError, KeyError):
943
except Exception, ex:
946
# remove from plugallow
948
self.plugallow.data.remove(plugname)
949
except (KeyError, ValueError):
952
# remove from avail list
954
self.avail.remove(plugname)
958
# remove from initcalled list
960
self.initcalled.remove(plugname)
964
# unload commands, RE callbacks, callbacks, monitorsetc.
966
cmnds.unload(plugname)
967
callbacks.unload(plugname)
968
gn_callbacks.unload(plugname)
969
jcallbacks.unload(plugname)
970
rebefore.unload(plugname)
971
reafter.unload(plugname)
972
saymonitor.unload(plugname)
973
outmonitor.unload(plugname)
974
xmppmonitor.unload(plugname)
975
tests.unload(plugname)
976
outputmorphs.unload(plugname)
977
inputmorphs.unload(plugname)
979
if self.plugs.has_key(plugname):
980
del self.plugs[plugname]
982
except Exception, ex:
986
rlog(0, 'plugins', '%s unloaded' % plugname)
989
def whereis(self, what):
994
:param what: name of command to search
996
:rtype: string .. plugin the command is in
998
.. literalinclude:: ../../gozerbot/plugins.py
999
:pyobject: Plugins.whereis
1003
return cmnds.whereis(what)
1005
def permoverload(self, funcname, perms):
1008
overload permission of a function.
1010
:param funcname: name of function to overload permissions of
1011
:type funcname: string
1012
:param perms: permissions to overload
1013
:type perms: list .. list of permissions
1014
:rtype: boolean: whether overload worked or not
1016
.. literalinclude:: ../../gozerbot/plugins.py
1017
:pyobject: Plugins.permoverload
1021
if not rebefore.permoverload(funcname, perms):
1023
if not cmnds.permoverload(funcname, perms):
1025
if not reafter.permoverload(funcname, perms):
1030
def woulddispatch(self, bot, ievent):
1033
function to determine whether a event would dispatch.
1035
:param bot: bot on which command is given
1036
:type bot: gozerbot.botbase.BotBase
1037
:param ievent: the event triggering the command
1038
:type ievent: gozerbot.eventbase.EventBase
1039
:rtype: boolean .. whether the dispatch should fire
1041
.. literalinclude:: ../../gozerbot/plugins.py
1042
:pyobject: Plugins.woulddispatch
1045
#self.needreloadcheck(bot, ievent)
1046
(what, command) = self.dispatchtest(bot, ievent)
1048
#if what and not what.activate:
1051
if what and command:
1057
def dispatchtest(self, bot, ievent, direct=False):
1060
return (dispatcher, command) on which command should fire.
1062
:param bot: bot on which command is given
1063
:type bot: gozerbot.botbase.BotBase
1064
:param ievent: the event triggering the command
1065
:type ievent: gozerbot.eventbase.EventBase
1066
:param direct: whether user permission should be checked
1067
:type direct: boolean .. when set user permission is NOT checked
1068
:rtype: tuple .. (dispatcher, command) tuples
1070
.. literalinclude:: ../../gozerbot/plugins.py
1071
:pyobject: Plugins.dispatchtest
1075
if shouldignore(ievent.userhost):
1078
# check for throttle
1079
if ievent.userhost in bot.throttle:
1082
# set target properly
1083
if ievent.txt.find(' | ') != -1:
1084
target = ievent.txt.split(' | ')[0]
1085
elif ievent.txt.find(' && ') != -1:
1086
target = ievent.txt.split(' && ')[0]
1092
# first check for RE before commands dispatcher
1093
com = rebefore.getcallback(target)
1095
if com and not target.startswith('!'):
1097
result = [rebefore, com]
1101
if ievent.txt.startswith('!'):
1102
ievent.txt = ievent.txt[1:]
1105
com = cmnds.getcommand(ievent.txt)
1109
result = [cmnds, com]
1110
ievent.txt = ievent.txt.strip()
1114
# try RE after commands
1115
com = reafter.getcallback(target)
1118
result = [reafter, com]
1121
# check for auto registration
1122
if config['auto_register'] and not users.getname(ievent.userhost):
1124
users.add(ievent.userhost , [ievent.userhost, ], ['USER', ])
1125
elif not bot.jabber:
1126
users.add("%s!%s" % (ievent.nick, ievent.userhost) , [ievent.userhost, ], ['USER', ])
1127
bot.ratelimit(ievent.userhost, 20)
1129
if ievent.groupchat:
1130
users.add(ievent.userhost , [ievent.userhost, ], ['USER', ])
1131
bot.ratelimit(ievent.userhost)
1133
users.add(ievent.stripped , [ievent.stripped, ], ['USER', ])
1134
bot.ratelimit(ievent.stripped, 20)
1136
# check for anon access
1137
if config['anon_enable'] and not 'OPER' in result[1].perms:
1140
# check if command is allowed (all-add command)
1141
if com.name in bot.state['allowed'] or getname(com.func) in bot.state['allowed']:
1144
# check for channel permissions
1146
chanperms = bot.channels[ievent.channel.lower()]['perms']
1148
for i in result[1].perms:
1149
if i in chanperms and not ievent.msg:
1153
except (KeyError, TypeError):
1156
# if direct is set dont check the user database
1160
# use event.stripped in case of jabber
1161
if bot.jabber and ievent.jabber:
1162
if not ievent.groupchat or ievent.jidchange:
1163
if users.allowed(ievent.stripped, result[1].perms):
1167
if users.allowed(ievent.userhost, result[1].perms):
1172
def cmnd(self, bot, ievent, timeout=15, response=False, onlyqueues=True):
1175
launch command and wait for result.
1177
:param bot: bot on which command is given
1178
:type bot: gozerbot.botbase.BotBase
1179
:param ievent: the event triggering the command
1180
:type ievent: gozerbot.eventbase.EventBase
1181
:param timeout: number of seconds to wait for a result
1182
:type timeout: integer
1183
:param response: whether to notify user we are running the command
1184
:type response: string
1185
:rtype: list .. list of results
1187
.. literalinclude:: ../../gozerbot/plugins.py
1188
:pyobject: Plugins.cmnd
1192
ievent.reply('launching %s on %s bot' % (ievent.txt, bot.name))
1193
#ii = self.clonedevent(bot, ievent)
1195
#ii.queues.append(q)
1196
#ii.onlyqueues = onlyqueues
1198
ievent.queues.append(q)
1199
self.trydispatch(bot, ievent)
1200
return waitforqueue(q, timeout)
1202
def waitdispatch(self, bot, ievent, direct=False):
1205
dispatch command and wait for results.
1207
:param bot: bot on which command is given
1208
:type bot: gozerbot.botbase.BotBase
1209
:param ievent: the event triggering the command
1210
:type ievent: gozerbot.eventbase.EventBase
1211
:param direct: whether user permission should be checked
1212
:type direct: boolean .. when set user permission is NOT checked
1213
:rtype: boolean .. whether dispatch succeeded or not
1215
.. literalinclude:: ../../gozerbot/plugins.py
1216
:pyobject: Plugins.waitdispatch
1219
ievent.threaded = True
1220
return self.trydispatch(bot, ievent, direct, wait=True)
1222
def trydispatch(self, bot, ievent, direct=False, wait=False):
1225
try to dispatch ievent.
1227
:param bot: bot on which command is given
1228
:type bot: gozerbot.botbase.BotBase
1229
:param ievent: the event triggering the command
1230
:type ievent: gozerbot.eventbase.EventBase
1231
:param direct: whether user permission should be checked
1232
:type direct: boolean .. when set user permission is NOT checked
1233
:param wait: whether function should wait for results
1235
:rtype: boolean .. whether dispatch succeeded or not
1237
.. literalinclude:: ../../gozerbot/plugins.py
1238
:pyobject: Plugins.trydispatch
1243
if shouldignore(ievent.userhost):
1248
ievent.printto = ievent.nick
1250
ievent.printto = ievent.channel
1252
# see if ievent would dispatch
1253
# what is rebefore, cmnds of reafter, com is the command object
1254
# check if redispatcher or commands object needs to be used
1255
#self.needreloadcheck(bot, ievent)
1257
(what, com) = self.dispatchtest(bot, ievent, direct)
1262
ievent.txt = ievent.txt.replace(' || ', ' | ')
1264
if ievent.txt.find(' | ') != -1:
1266
if ievent.txt[0] == '!':
1267
ievent.txt = ievent.txt[1:]
1269
self.splitpipe(bot, ievent)
1272
elif ievent.txt.find(' && ') != -1:
1273
self.multiple(bot, ievent)
1276
return self.dispatch(what, com, bot, ievent, wait)
1278
def dispatch(self, what, com, bot, ievent, wait=False):
1281
do the actual dispatch of event.
1283
:param what: the dispatcher to dispatch the command on
1284
:type what: gozerbot.redispatcher.REdispatcher or gozerbot.commands.Commands
1285
:param com: the command to dispatch
1286
:type com: gozerbot.redispatcher.REcallback or gozerbot.commands.Command
1287
:param bot: bot on which command is given
1288
:type bot: gozerbot.botbase.BotBase
1289
:param ievent: the event triggering the command
1290
:type ievent: gozerbot.eventbase.EventBase
1291
:param wait: whether function should wait for results
1293
:rtype: boolean .. whether dispatch succeeded or not
1295
.. literalinclude:: ../../gozerbot/plugins.py
1296
:pyobject: Plugins.dispatch
1302
# make command options
1304
makeoptions(ievent, com.options)
1308
# make arguments and rest
1310
ievent.usercmnd = True
1311
rlog(10, 'plugins', 'dispatching %s for %s' % (ievent.command, ievent.userhost))
1314
what.dispatch(com, bot, ievent, wait)
1317
def clonedevent(self, bot, event):
1323
:param bot: bot on which command is given
1324
:type bot: gozerbot.botbase.BotBase
1325
:param ievent: the event triggering the command
1326
:type ievent: gozerbot.eventbase.EventBase
1327
:rtype: gozerbot.eventbase.EventBase
1329
.. literalinclude:: ../../gozerbot/plugins.py
1330
:pyobject: Plugins.clonedevent
1334
ie = copy.deepcopy(event)
1338
def multiple(self, bot, ievent):
1341
execute multiple commands.
1344
:param bot: bot on which command is given
1345
:type bot: gozerbot.botbase.BotBase
1346
:param ievent: the event triggering the command
1347
:type ievent: gozerbot.eventbase.EventBase
1349
.. literalinclude:: ../../gozerbot/plugins.py
1350
:pyobject: Plugins.multiple
1354
for i in ievent.txt.split(' && '):
1355
ie = self.clonedevent(bot, ievent)
1357
#self.needreloadcheck(bot, ievent)
1358
self.trydispatch(bot, ie)
1360
def splitpipe(self, bot, ievent):
1363
execute commands in a pipeline.
1365
:param bot: bot on which command is given
1366
:type bot: gozerbot.botbase.BotBase
1367
:param ievent: the event triggering the command
1368
:type ievent: gozerbot.eventbase.EventBase
1370
.. literalinclude:: ../../gozerbot/plugins.py
1371
:pyobject: Plugins.splitpipe
1375
origqueues = ievent.queues
1378
txt = ievent.txt.replace(' || ', ' ##')
1381
for i in txt.split(' | '):
1382
item = i.replace(' ##', ' | ')
1383
ie = self.clonedevent(bot, ievent)
1384
ie.userhost = ievent.userhost
1385
ie.onlyqueues = True
1386
ie.txt = item.strip()
1387
#self.needreloadcheck(bot, ie)
1390
# loop over events .. chain queues
1393
for i in events[:-1]:
1400
events[-1].inqueue = prevq
1401
events[-1].onlyqueues = False
1404
events[-1].queues = origqueues
1406
# check if all commands would dispatch
1408
if not self.woulddispatch(bot, i):
1409
ievent.reply("can't execute %s" % str(i.txt))
1414
(what, com) = self.dispatchtest(bot, i)
1416
self.dispatch(what, com, bot, i)
1418
def needreloadcheck(self, bot, event, target=None):
1424
rlog(10, 'plugins', 'target set: %s' % target)
1428
t = event.txt.split()[0]
1429
cmnd = aliasget(t) or t
1430
plugin = cmndtable[cmnd]
1432
rlog(10, 'plugins', 'cmnd: %s plugin: %s' % (cmnd, plugin))
1434
if self.exist(plugin):
1438
self.reload('gozerbot.plugs', plugin)
1439
except ImportError, ex:
1442
self.reload('gplugs', plugin)
1443
except ImportError, ex:
1444
if config.get('db_driver') == 'olddb':
1446
self.reload('gplugs.olddb', plugin)
1447
except ImportError, ex: pass
1450
self.reload('gplugs.alchemy', plugin)
1451
except ImportError, ex: pass
1453
self.reload('myplugs', plugin)
1454
except ImportError, ex:
1457
rlog(100, 'plugins', 'reloaded %s' % plugin)
1459
except KeyError, ex:
1460
rlog(10, 'plugins', "can't find plugin to reload for %s" % event.txt.split()[0])
1463
def listreload(self, pluglist):
1466
reload list of plugins.
1468
:param pluglist: list of plugin names
1469
:type pluglist: list
1470
:rtype: list .. list of plugins where reload failed
1472
.. literalinclude:: ../../gozerbot/plugins.py
1473
:pyobject: Plugins.listreload
1479
# loop over the plugin list and reload them
1480
for what in pluglist:
1481
splitted = what[:-3].split(os.sep)
1482
mod = '.'.join(splitted[:-1])
1485
if config.get('db_driver') == "olddb":
1486
mod = "gplugs.olddb"
1487
elif config.get("db_driver") == "alchemy":
1488
mod = "gplugs.alchemy"
1496
self.reload(mod, plug)
1498
except Exception, ex:
1505
# THE plugins object