]> jfr.im git - erebus.git/blob - modlib.py
add compatibility with Python3. add README.
[erebus.git] / modlib.py
1 # Erebus IRC bot - Author: John Runyon
2 # module helper functions, see modules/modtest.py for usage
3 # This file is released into the public domain; see http://unlicense.org/
4
5 import sys
6
7 if sys.version_info.major < 3:
8 stringbase = basestring
9 else:
10 stringbase = str
11
12 class error(object):
13 def __init__(self, desc):
14 self.errormsg = desc
15 def __nonzero__(self):
16 return False #object will test to False
17 def __repr__(self):
18 return '<modlib.error %r>' % self.errormsg
19 def __str__(self):
20 return str(self.errormsg)
21
22 class modlib(object):
23 # default (global) access levels
24 OWNER = 100
25 MANAGER = 99
26 ADMIN = 75
27 STAFF = 50
28 AUTHED = 0
29 ANYONE = -1
30 IGNORED = -2
31
32 # (channel) access levels
33 COWNER = 5
34 MASTER = 4
35 OP = 3
36 VOICE = 2
37 KNOWN = 1
38 PUBLIC = 0 #anyone (use glevel to control auth-needed)
39 BANNED = -1
40 # [ 0 1 2 3 4 5 -1]
41 clevs = [None, 'Friend', 'Voice', 'Op', 'Master', 'Owner', None]
42
43 # messages
44 WRONGARGS = "Wrong number of arguments."
45
46 def __init__(self, name):
47 self.hooks = {}
48 self.numhooks = {}
49 self.chanhooks = {}
50 self.helps = []
51 self.parent = None
52
53 self.name = (name.split("."))[-1]
54
55 def modstart(self, parent):
56 #modstart can return a few things...
57 # None: unspecified success
58 # False: unspecified error
59 # modlib.error (or anything else False-y): specified error
60 # True: unspecified success
61 # non-empty string (or anything else True-y): specified success
62 #"specified" values will be printed. unspecified values will result in "OK" or "failed"
63 self.parent = parent
64 for cmd, func in self.hooks.items():
65 self.parent.hook(cmd, func)
66 self.parent.hook("%s.%s" % (self.name, cmd), func)
67 for num, func in self.numhooks.items():
68 self.parent.hooknum(num, func)
69 for chan, func in self.chanhooks.items():
70 self.parent.hookchan(chan, func)
71
72 for func, args, kwargs in self.helps:
73 try:
74 self.mod('help').reghelp(func, *args, **kwargs)
75 except:
76 pass
77 return True
78 def modstop(self, parent):
79 for cmd, func in self.hooks.items():
80 parent.unhook(cmd, func)
81 parent.unhook("%s.%s" % (self.name, cmd), func)
82 for num, func in self.numhooks.items():
83 parent.unhooknum(num, func)
84 for chan, func in self.chanhooks.items():
85 parent.unhookchan(chan, func)
86
87 for func, args, kwargs in self.helps:
88 try:
89 self.mod('help').dereghelp(func, *args, **kwargs)
90 except:
91 pass
92 return True
93
94 def hooknum(self, num):
95 def realhook(func):
96 self.numhooks[str(num)] = func
97 if self.parent is not None:
98 self.parent.hooknum(str(num), func)
99 return func
100 return realhook
101
102 def hookchan(self, chan, glevel=ANYONE, clevel=PUBLIC):
103 def realhook(func):
104 self.chanhooks[chan] = func
105 if self.parent is not None:
106 self.parent.hookchan(chan, func)
107 return func
108 return realhook
109
110 def hook(self, cmd=None, needchan=True, glevel=ANYONE, clevel=PUBLIC, wantchan=None):
111 if wantchan is None: wantchan = needchan
112 _cmd = cmd #save this since it gets wiped out...
113 def realhook(func):
114 cmd = _cmd #...and restore it
115 if cmd is None:
116 cmd = func.__name__ # default to function name
117 if isinstance(cmd, stringbase):
118 cmd = (cmd,)
119
120 func.needchan = needchan
121 func.wantchan = wantchan
122 func.reqglevel = glevel
123 func.reqclevel = clevel
124 func.cmd = cmd
125 func.module = func.__module__.split('.')[1]
126
127 for c in cmd:
128 self.hooks[c] = func
129 if self.parent is not None:
130 self.parent.hook(c, func)
131 self.parent.hook("%s.%s" % (self.name, c), func)
132 return func
133 return realhook
134
135 def mod(self, modname):
136 if self.parent is not None:
137 return self.parent.module(modname)
138 else:
139 return error('unknown parent')
140
141 def argsEQ(self, num):
142 def realhook(func):
143 def checkargs(bot, user, chan, realtarget, *args):
144 if len(args) == num:
145 return func(bot, user, chan, realtarget, *args)
146 else:
147 bot.msg(user, self.WRONGARGS)
148 checkargs.__name__ = func.__name__
149 checkargs.__module__ = func.__module__
150 return checkargs
151 return realhook
152
153 def argsGE(self, num):
154 def realhook(func):
155 def checkargs(bot, user, chan, realtarget, *args):
156 if len(args) >= num:
157 return func(bot, user, chan, realtarget, *args)
158 else:
159 bot.msg(user, self.WRONGARGS)
160 checkargs.__name__ = func.__name__
161 checkargs.__module__ = func.__module__
162 return checkargs
163 return realhook
164
165 def help(self, *args, **kwargs):
166 """help(syntax, shorthelp, longhelp?, more lines longhelp?, cmd=...?)
167 Example:
168 help("<user> <pass>", "login")
169 ^ Help will only be one line. Command name determined based on function name.
170 help("<user> <level>", "add a user", cmd=("adduser", "useradd"))
171 ^ Help will be listed under ADDUSER; USERADD will say "alias for adduser"
172 help(None, "do stuff", "This command is really complicated.")
173 ^ Command takes no args. Short description (in overall HELP listing) is "do stuff".
174 Long description (HELP <command>) will say "<command> - do stuff", newline, "This command is really complicated."
175 """
176 def realhook(func):
177 if self.parent is not None:
178 try:
179 self.mod('help').reghelp(func, *args, **kwargs)
180 except:
181 pass
182 self.helps.append((func,args,kwargs))
183 return func
184 return realhook