]>
Commit | Line | Data |
---|---|---|
1 | #!/usr/bin/python | |
2 | ||
3 | ||
4 | # TODO notes: | |
5 | # | |
6 | # - impliment handle_* functions for everything x3 has register fetaures for | |
7 | # - impliment script load/unload for user scripts. | |
8 | # - load a script via this script. | |
9 | # - script calls functions from here to set its functions up for calling on various actions | |
10 | # - provide helper functions for subscripts to save settings attached to users/chanels | |
11 | # - provide helper functions for scripts to do common things like msg a person or a channel, | |
12 | # reply, etc. | |
13 | ||
14 | import _svc | |
15 | ||
16 | import math | |
17 | ||
18 | import sys | |
19 | ||
20 | ||
21 | class irc: | |
22 | """Used to interact with the world of IRC from module scripts""" | |
23 | ||
24 | # some defaults to make shorthand easy | |
25 | caller = '' | |
26 | target = '' | |
27 | service = '' | |
28 | ||
29 | def __init__(self, service = None, caller = None, target = None): | |
30 | """ Constructor """ | |
31 | self.caller = caller #the person who sent the command/message | |
32 | self.service = service #the service who saw the message | |
33 | self.target = target #the channel message was in (if public) | |
34 | ||
35 | def send_target_privmsg(self, source, target, message): | |
36 | _svc.send_target_privmsg(source, target, "%s "%(message)) | |
37 | ||
38 | def reply(self, message): | |
39 | """ Send a private reply to the user using convenience values""" | |
40 | #print "DEBUG: sending a message from %s to %s: %s"%(self.service, self.caller, message) | |
41 | if(len(self.target)): | |
42 | self.send_target_privmsg(self.service, self.target, "%s: %s"%(self.caller, message)) | |
43 | else: | |
44 | self.send_target_privmsg(self.service, self.caller, message) | |
45 | ||
46 | class handler: | |
47 | """ Main hub of python system. Handle callbacks from c. """ | |
48 | ||
49 | def __init__(self): | |
50 | #print "DEBUG: constructor for handler initing" | |
51 | self.plugins = plugins(self) | |
52 | if(not self.plugins): | |
53 | print "DEBUG: unable to make self.plugins!?!" | |
54 | ||
55 | def init(self, irc): # not to be confused with __init__! | |
56 | """ This gets called once all the objects are up and running. Otherwise, | |
57 | were not done initing this own instance to be able to start calling it """ | |
58 | #print "DEBUG: in handler.init()" | |
59 | self.plugins.init() | |
60 | return 0 | |
61 | ||
62 | def join(self, irc, channel, nick): | |
63 | #user = _svc.get_user(nick) | |
64 | #print "DEBUG: handler.join()" | |
65 | return self.plugins.callhandler("join", irc, [channel, nick], [channel, nick]) | |
66 | ||
67 | def server_link(self, irc, name, desc): | |
68 | return self.plugins.callhandler("server_link", irc, [name, desc], [name, desc]) | |
69 | ||
70 | def new_user(self, irc, nick, ident, hostname, info): | |
71 | # we may filter on all the user fields, but we only pass the nick because | |
72 | # the plugin can get the rest itself | |
73 | return self.plugins.callhandler("new_user", irc, [nick, ident, hostname, info], [nick]) | |
74 | ||
75 | def nick_change(self, irc, nick, old_nick): | |
76 | return self.plugins.callhandler("nick_change", irc, [nick, old_nick], [nick, old_nick]) | |
77 | ||
78 | def cmd_run(self, irc, cmd): | |
79 | #print "DEBUG: handler.cmd_run: %s"%cmd | |
80 | eval(cmd) | |
81 | return 0 | |
82 | ||
83 | def addhook(self, event, method, filter=[None], data=None): | |
84 | self.plugins.addhook(event, method, filter, data) | |
85 | return 0 | |
86 | ||
87 | def addcommand(self, plugin, command, method): | |
88 | self.addhook("command", method, [plugin, command]) | |
89 | ||
90 | def cmd_command(self, irc, plugin, cmd, args): | |
91 | #print "DEBUG: handel.cmd_command; %s %s; args= %s"%(plugin, cmd, args) | |
92 | return self.plugins.callhandler("command", irc, [plugin, cmd], [args]) | |
93 | ||
94 | def load(self, irc, plugin): | |
95 | return self.plugins.load(plugin) | |
96 | ||
97 | class plugins: | |
98 | """Class to handle loading/unloading of plugins""" | |
99 | loaded_plugins = {} | |
100 | hooks = [] | |
101 | ||
102 | class hook: | |
103 | """ This is a request from a plugin to be called on an event """ | |
104 | event = "" # Event to be called on (eg "join") | |
105 | method = None # Method to call | |
106 | filter = None # Arguments to filter | |
107 | data = "" # plugin-supplied data for plugin use | |
108 | ||
109 | def __init__(self, event, method, filter, data): | |
110 | self.event = event | |
111 | self.method = method | |
112 | self.filter = filter | |
113 | self.data = data | |
114 | ||
115 | def event_is(self, event, evdata): | |
116 | if(self.event == event): | |
117 | for i in range(len(self.filter)): | |
118 | if( self.filter[i] != None | |
119 | and self.filter[i] != evdata[i]): # should be case insensitive? or how to compare? | |
120 | #print "DEBUG: rejecting event, %s is not %s"%(self.filter[i], evdata[i]) | |
121 | return False | |
122 | return True | |
123 | else: | |
124 | return False | |
125 | ||
126 | def trigger(self, irc, args): | |
127 | #print "DEBUG: Triggering %s event. with '%s' arguments."%(self.event, args) | |
128 | self.method(irc, *args) | |
129 | ||
130 | def __init__(self, handler): | |
131 | """ Constructor """ | |
132 | #print "DEBUG: constructor for plugins initing" | |
133 | self.handler = handler | |
134 | ||
135 | def init(self): | |
136 | #print "DEBUG: in plugins.init()" | |
137 | self.load("annoy") | |
138 | self.load("hangman") | |
139 | ||
140 | def addhook(self, event, method, filter=[None], data=None): | |
141 | #print "DEBUG: Adding hook for %s."%event | |
142 | self.hooks.append(self.hook(event, method, filter, data)) | |
143 | ||
144 | def findhooksforevent(self, event, data): | |
145 | ret = [] | |
146 | #print "DEBUG: findhooksforevent() looking..." | |
147 | for hook in self.hooks: | |
148 | #print "DEBUG: looking at a %s hook..."%hook.event | |
149 | if(hook.event_is(event, data)): | |
150 | ret.append(hook) | |
151 | return ret | |
152 | ||
153 | def callhandler(self, event, irc, filter, args): | |
154 | for hook in self.findhooksforevent(event, filter): | |
155 | if(hook.trigger(irc, args)): | |
156 | return 1 | |
157 | return 0 | |
158 | ||
159 | def load(self, name): | |
160 | """ Loads a plugin by name """ | |
161 | mod_name = "plugins.%s"%name | |
162 | need_reload = False | |
163 | if(sys.modules.has_key(mod_name)): | |
164 | need_reload = true | |
165 | #TODO: try to catch compile errors etc. | |
166 | ||
167 | if(need_reload == False): | |
168 | __import__(mod_name) | |
169 | module = sys.modules[mod_name] | |
170 | if(need_reload == True): | |
171 | reload(module) # to ensure its read fresh | |
172 | Class = module.Class | |
173 | pluginObj = Class(self.handler, irc()) | |
174 | self.loaded_plugins[mod_name] = pluginObj | |
175 | return True | |
176 |