]>
Commit | Line | Data |
---|---|---|
1 | # Erebus IRC bot - Author: Erebus Team | |
2 | # vim: fileencoding=utf-8 | |
3 | # help module | |
4 | # This file is released into the public domain; see http://unlicense.org/ | |
5 | ||
6 | # module info | |
7 | modinfo = { | |
8 | 'author': 'Erebus Team', | |
9 | 'license': 'public domain', | |
10 | 'compatible': [0], | |
11 | 'depends': [], | |
12 | 'softdeps': [], | |
13 | } | |
14 | ||
15 | # preamble | |
16 | import modlib | |
17 | lib = modlib.modlib(__name__) | |
18 | def modstart(parent, *args, **kwargs): | |
19 | if parent.cfg.getboolean('erebus', 'nofakelag'): | |
20 | lib.hook('help', needchan=False)(lib.help('[@<module>|<command>]', 'lists commands or describes a command', 'with @<module>, lists all commands in <module>')(help_nolag)) | |
21 | else: | |
22 | lib.hook('help', needchan=False)(lib.help("<command>", "describes a command")(help)) | |
23 | return lib.modstart(parent, *args, **kwargs) | |
24 | modstop = lib.modstop | |
25 | ||
26 | # module code | |
27 | import os.path | |
28 | helps = {} | |
29 | cmds = {} | |
30 | ||
31 | # ! this is part of this module's API, called from modlib.help() | |
32 | def reghelp(func, *args, **kwargs): | |
33 | syntax = None | |
34 | shorthelp = None | |
35 | longhelps = [] | |
36 | ||
37 | if len(args) > 0: | |
38 | syntax = args[0] | |
39 | if len(args) > 1: | |
40 | shorthelp = args[1] | |
41 | if len(args) > 2: | |
42 | longhelps = args[2:] | |
43 | ||
44 | if 'syntax' in kwargs: | |
45 | syntax = kwargs['syntax'] | |
46 | if 'shorthelp' in kwargs: | |
47 | shorthelp = kwargs['shorthelp'] | |
48 | if 'longhelps' in kwargs: | |
49 | longhelps = kwargs['longhelps'] | |
50 | ||
51 | if syntax is None: syntax = "" | |
52 | if shorthelp is None: shorthelp = "" | |
53 | ||
54 | func.syntax = syntax | |
55 | func.shorthelp = shorthelp | |
56 | func.longhelps = longhelps | |
57 | helps[func] = func | |
58 | for c in func.cmd: | |
59 | cmds[c] = func | |
60 | ||
61 | def dereghelp(func, *args, **kwargs): | |
62 | for c in func.cmd: | |
63 | del cmds[c] | |
64 | del helps[func] | |
65 | ||
66 | class HelpLine(object): | |
67 | def __init__(self, cmd, syntax, shorthelp, admin, glevel, module, clevel): | |
68 | self.cmd = cmd | |
69 | self.syntax = syntax | |
70 | self.shorthelp = shorthelp | |
71 | self.admin = admin | |
72 | self.glevel = glevel | |
73 | self.module = module | |
74 | self.clevel = clevel | |
75 | ||
76 | def __cmp__(self, other): | |
77 | if self.glevel == other.glevel: | |
78 | return cmp(self.cmd, other.cmd) | |
79 | else: | |
80 | return cmp(self.glevel, other.glevel) | |
81 | ||
82 | ||
83 | def __str__(self): | |
84 | if self.admin: | |
85 | ret = "%-25s(%3s) - %-10s - " % (self.cmd+' '+self.syntax, self.glevel, self.module) | |
86 | else: | |
87 | ret = "%-30s - " % (self.cmd+' '+self.syntax) | |
88 | if self.clevel != 0: | |
89 | ret += "(%s) " % (lib.clevs[self.clevel]) | |
90 | ret += str(self.shorthelp) | |
91 | return ret | |
92 | ||
93 | def _mkhelp(level, func): | |
94 | lines = [] | |
95 | if level >= func.reqglevel: | |
96 | lines.append(HelpLine(func.cmd[0], func.syntax, func.shorthelp, (level > 0), func.reqglevel, func.module, func.reqclevel)) | |
97 | if len(func.cmd) > 1: | |
98 | for c in func.cmd[1:]: | |
99 | lines.append(HelpLine(c, "", "Alias of %s" % (func.cmd[0]), (level > 0), func.reqglevel, func.module, func.reqclevel)) | |
100 | return lines | |
101 | ||
102 | def _genhelp(bot, user, chan, realtarget, *args): | |
103 | module = '' | |
104 | minlevel = -1 | |
105 | maxlevel = 100 | |
106 | filepath = bot.parent.cfg.get('help', 'path', default='./help/%(@)s%(#)d.txt') | |
107 | for arg in args: | |
108 | if arg.startswith("@"): | |
109 | if "." in arg[1:]: | |
110 | raise Exception('Module option must not contain "."') | |
111 | module = arg[1:] | |
112 | elif arg.startswith("#") and user.glevel >= lib.ADMIN: | |
113 | minlevel = maxlevel = int(arg[1:]) | |
114 | elif arg.startswith("+"): | |
115 | maxlevel = int(arg[1:]) | |
116 | elif arg.startswith("-"): | |
117 | minlevel = int(arg[1:]) | |
118 | elif arg.startswith("./"): | |
119 | if "./" in arg[1:]: | |
120 | raise Exception('Filename option must not contain "./" except as the first two characters') | |
121 | else: | |
122 | filepath = os.path.join('help', arg[2:]) | |
123 | else: | |
124 | raise Exception('Unknown option given to GENHELP: %s' % (arg)) | |
125 | for level in range(minlevel, maxlevel+1): | |
126 | filename = filepath % {'#': level, '+': maxlevel, '-': minlevel, '@': module} | |
127 | fo = open(filename, 'w') | |
128 | lines = [] | |
129 | for func in helps.values(): | |
130 | if module != '' and func.module != module: | |
131 | continue | |
132 | lines += _mkhelp(level, func) | |
133 | for line in sorted(lines): | |
134 | fo.write(str(line)+"\n") | |
135 | fo.close() | |
136 | return True | |
137 | ||
138 | @lib.hook(glevel=1, needchan=False) | |
139 | @lib.help("[@<module>] [#<exact_level>] [+<max_level>] [-<min_level>] [./<filename>]", "generates help file", "arguments are all optional and may be specified in any order", "default file: ./help/<module><level>.txt, with module blank if not supplied", "filename can also contain %(@)s, %(#)s, %(+)s, %(-)s", "for module, current (single) level, max and min level, respectively") | |
140 | def genhelp(bot, user, chan, realtarget, *args): | |
141 | try: | |
142 | _genhelp(bot, user, chan, realtarget, *args) | |
143 | except Exception as e: | |
144 | bot.msg(user, "Failed writing help. %s" % (e)) | |
145 | return | |
146 | bot.msg(user, "Help written.") | |
147 | ||
148 | #@lib.hook(needchan=False) | |
149 | #@lib.help("<command>", "describes a command") | |
150 | @lib.argsGE(1) | |
151 | def help(bot, user, chan, realtarget, *args): | |
152 | cmd = str(' '.join(args)).lower() | |
153 | if cmd in cmds and user.glevel >= cmds[cmd].reqglevel: | |
154 | func = cmds[cmd] | |
155 | bot.slowmsg(user, str(HelpLine(func.cmd[0], func.syntax, func.shorthelp, (user.glevel > 0), func.reqglevel, func.module, func.reqclevel))) | |
156 | for line in func.longhelps: | |
157 | bot.slowmsg(user, " %s" % (line)) | |
158 | if len(func.cmd) > 1: | |
159 | bot.slowmsg(user, " Aliases: %s" % (' '.join(func.cmd[1:]))) | |
160 | else: | |
161 | bot.slowmsg(user, "No help found for %s" % (cmd)) | |
162 | ||
163 | @lib.hook(needchan=False) | |
164 | @lib.help(None, "provides command list") | |
165 | def showcommands(bot, user, chan, realtarget, *args): | |
166 | if bot.parent.cfg.getboolean('help', 'autogen'): | |
167 | try: | |
168 | _genhelp(bot, user, chan, realtarget, *args) | |
169 | except: pass | |
170 | ||
171 | url = bot.parent.cfg.get('help', 'url', default=None) | |
172 | if url is None: | |
173 | try: | |
174 | import urllib2 | |
175 | myip = urllib2.urlopen("https://api.ipify.org").read() | |
176 | url = "http://%s/help/%%d.txt (maybe)" % (myip) | |
177 | except: url = None | |
178 | if url is not None: | |
179 | url = url % (user.glevel) | |
180 | bot.msg(user, "Help is at: %s" % (url)) | |
181 | else: | |
182 | bot.msg(user, "I don't know where help is. Sorry. Contact my owner.") | |
183 | ||
184 | #@lib.hook(needchan=False) | |
185 | #@lib.help('[@<module>|<command>]', 'lists commands or describes a command', 'with @<module>, lists all commands in <module>') | |
186 | def help_nolag(bot, user, chan, realtarget, *args): | |
187 | if len(args) == 0: # list commands | |
188 | lines = [] | |
189 | for func in helps.values(): | |
190 | lines += _mkhelp(user, func) | |
191 | for line in sorted(lines): | |
192 | bot.slowmsg(user, str(line)) | |
193 | bot.slowmsg(user, "End of command listing.") | |
194 | elif args[0].startswith("@"): | |
195 | lines = [] | |
196 | mod = args[0][1:].lower() | |
197 | for func in helps.values(): | |
198 | if func.module == mod: | |
199 | lines += _mkhelp(user, func) | |
200 | for line in sorted(lines): | |
201 | bot.slowmsg(user, str(line)) | |
202 | bot.slowmsg(user, "End of command listing.") | |
203 | else: # help for a specific command/topic | |
204 | cmd = str(' '.join(args)).lower() | |
205 | if cmd in cmds and user.glevel >= cmds[cmd].reqglevel: | |
206 | func = cmds[cmd] | |
207 | bot.slowmsg(user, str(HelpLine(func.cmd[0], func.syntax, func.shorthelp, (user.glevel > 0), func.reqglevel, func.module, func.reqclevel))) | |
208 | for line in func.longhelps: | |
209 | bot.slowmsg(user, " %s" % (line)) | |
210 | bot.slowmsg(user, "End of help for %s." % (func.cmd[0])) | |
211 | ||
212 | if len(func.cmd) > 1: | |
213 | bot.slowmsg(user, " Aliases: %s" % (' '.join(func.cmd[1:]))) | |
214 | else: | |
215 | bot.slowmsg(user, "No help found for %s" % (cmd)) |