30
30
31
31
import re
32
32
import os
33
+ import imp
33
34
import sys
34
35
import time
35
36
49
50
from supybot .i18n import PluginInternationalization , internationalizeDocstring
50
51
_ = PluginInternationalization ('Misc' )
51
52
53
+ def get_suffix (file ):
54
+ for suffix in imp .get_suffixes ():
55
+ if file [- len (suffix [0 ]):] == suffix [0 ]:
56
+ return suffix
57
+ return None
58
+
59
+ def getPluginsInDirectory (directory ):
60
+ # get modules in a given directory
61
+ plugins = []
62
+ for filename in os .listdir (directory ):
63
+ pluginPath = os .path .join (directory , filename )
64
+ if os .path .isdir (pluginPath ):
65
+ if all (os .path .isfile (os .path .join (pluginPath , x ))
66
+ for x in ['__init__.py' , 'config.py' , 'plugin.py' ]):
67
+ plugins .append (filename )
68
+ return plugins
69
+
52
70
class RegexpTimeout (Exception ):
53
71
pass
54
72
@@ -121,34 +139,57 @@ def invalidCommand(self, irc, msg, tokens):
121
139
122
140
@internationalizeDocstring
123
141
def list (self , irc , msg , args , optlist , cb ):
124
- """[--private] [<plugin>]
142
+ """[--private] [--unloaded] [ <plugin>]
125
143
126
144
Lists the commands available in the given plugin. If no plugin is
127
145
given, lists the public plugins available. If --private is given,
128
- lists the private plugins.
146
+ lists the private plugins. If --unloaded is given, it will list
147
+ available plugins that are not loaded.
129
148
"""
130
149
private = False
150
+ unloaded = False
131
151
for (option , argument ) in optlist :
132
152
if option == 'private' :
133
153
private = True
134
154
if not self .registryValue ('listPrivatePlugins' ) and \
135
155
not ircdb .checkCapability (msg .prefix , 'owner' ):
136
156
irc .errorNoCapability ('owner' )
157
+ elif option == 'unloaded' :
158
+ unloaded = True
159
+ if not self .registryValue ('listUnloadedPlugins' ) and \
160
+ not ircdb .checkCapability (msg .prefix , 'owner' ):
161
+ irc .errorNoCapability ('owner' )
162
+ if unloaded and private :
163
+ irc .error (_ ('--private and --unloaded are uncompatible options.' ))
164
+ return
137
165
if not cb :
138
- def isPublic (cb ):
139
- name = cb .name ()
140
- return conf .supybot .plugins .get (name ).public ()
141
- names = [cb .name () for cb in irc .callbacks
142
- if (private and not isPublic (cb )) or
143
- (not private and isPublic (cb ))]
144
- names .sort ()
145
- if names :
146
- irc .reply (format ('%L' , names ))
166
+ if unloaded :
167
+ installedPluginsDirectory = os .path .join (
168
+ os .path .dirname (__file__ ), '..' )
169
+ plugins = getPluginsInDirectory (installedPluginsDirectory )
170
+ for directory in conf .supybot .directories .plugins ()[:]:
171
+ plugins .extend (getPluginsInDirectory (directory ))
172
+ # Remove loaded plugins:
173
+ loadedPlugins = [x .name () for x in irc .callbacks ]
174
+ plugins = [x for x in plugins if x not in loadedPlugins ]
175
+
176
+ plugins .sort ()
177
+ irc .reply (format ('%L' , plugins ))
147
178
else :
148
- if private :
149
- irc .reply (_ ('There are no private plugins.' ))
179
+ def isPublic (cb ):
180
+ name = cb .name ()
181
+ return conf .supybot .plugins .get (name ).public ()
182
+ names = [cb .name () for cb in irc .callbacks
183
+ if (private and not isPublic (cb )) or
184
+ (not private and isPublic (cb ))]
185
+ names .sort ()
186
+ if names :
187
+ irc .reply (format ('%L' , names ))
150
188
else :
151
- irc .reply (_ ('There are no public plugins.' ))
189
+ if private :
190
+ irc .reply (_ ('There are no private plugins.' ))
191
+ else :
192
+ irc .reply (_ ('There are no public plugins.' ))
152
193
else :
153
194
commands = cb .listCommands ()
154
195
if commands :
@@ -162,7 +203,8 @@ def isPublic(cb):
162
203
'Try "config list supybot.plugins.%s" to see '
163
204
'what configuration variables it has.' ),
164
205
cb .name ()))
165
- list = wrap (list , [getopts ({'private' :'' }), additional ('plugin' )])
206
+ list = wrap (list , [getopts ({'private' :'' , 'unloaded' :'' }),
207
+ additional ('plugin' )])
166
208
167
209
@internationalizeDocstring
168
210
def apropos (self , irc , msg , args , s ):
0 commit comments