2 #Let's keep this file in particular as clean and neatly organized as possible.
3 #If this is nice and organized, then writing new modules will be a snap and this
4 #file should rarely have to be edited.
11 ################################################################################
12 #set to False to turn off debugging to stdout
19 ################################################################################
24 def modload_cmd(c
,list,bot
):
25 """modload - Loads a module"""
26 cmd
= list[4].split(" ")[0]
28 if cmd
== "modload" and list[3]:
29 param
= list[4].split(" ")[1]
30 c
.privmsg(list[5], bot
.load_module(param
))
32 def modunload_cmd(c
, list, bot
):
33 """modunload - Unloads a module"""
34 cmd
= list[4].split(" ")[0]
35 if cmd
== "modunload" and list[3]:
36 param
= list[4].split(" ")[1]
37 c
.privmsg(list[5], bot
.unload_module(param
))
38 exec(list[4].split(" ")[1])
40 def modlist_cmd(c
,list,bot
):
41 """modlist - Lists loaded modules"""
42 if list[4] == "modlist" and list[3]:
43 c
.privmsg(list[5],bot
.modulelist
)
45 def getevents_cmd(c
, list, bot
):
46 cmd
= list[4].split(" ")[0]
47 if cmd
== "getevents" and list[3]:
48 param
= list[4].split(" ")[1]
49 param
= "bot."+param
+"_events"
50 c
.privmsg(list[5], eval(param
))
52 #this is our main bot class. Once scrappy.py is called, an instance of this
53 #class (our bot) gets created and some initialization is done. The real work is
54 #done via modules that get loaded here.
57 debug("Scrappy bot started.")
58 #hard-code these for now
59 #then write a config loading module
61 self
.nickname
= 'scrappy'
62 self
.username
= 'scrappy'
63 self
.realname
= 'Scrappy Bot'
67 self
.ircsock
= '' #this will be the socket
68 self
.connection
= '' #Thomas, explain this to me later
72 #each module adds functions to be called to these events.
73 #each event handler calls all of the functions within its list.
74 self
.events
= ["connect", "disconnect", "error", "invite",
75 "join", "kick", "load", "mode", "msg", "part", "ping", "pong",
76 "privmsg", "privnotice", "pubmsg", "pubnotice", "quit"]
78 self
.connect_events
= []
79 self
.disconnect_events
= []
80 self
.error_events
= []
81 self
.invite_events
= []
90 self
.privmsg_events
= []
91 self
.privnotice_events
= []
92 self
.pubmsg_events
= []
93 self
.pubnotice_events
= []
94 self
.quit_events
= [] #for other users quitting, not the bot
95 #self.what_other_events? = []
97 #load modules(currently in main())
98 #self.load_module("config")
99 #self.load_module("core")
100 #self.load_module("markov")
102 #self.register_onload_event(loadme)
109 ########################################################################
110 def parse_argv(self
):
111 """Parse the commandline args and print a usage message if incorrect."""
112 if len(sys
.argv
) < 3: #Need at least server
116 #split out the port if specified
117 s
= sys
.argv
[1].split(":", 1)
123 self
.port
= int(s
[1])
125 print "Error: Erroneous port."
128 self
.nickname
= sys
.argv
[2]
129 #add channels to chanlist
130 for ch
in sys
.argv
[3:]:
131 self
.chanlist
.append('#%s' % ch
)
133 def print_usage(self
):
134 print 'Usage: %s <server[:port]> <nickname> [channel 1 channel 2 ... channelN]' % sys
.argv
[0]
136 ########################################################################
138 """The real work. Initialize our connection and register events."""
139 #parse comamnd line and create a new socket
141 self
.ircsock
= irclib_scrappy
.IRC()
143 #attempt to create a socket and connect to the server
145 self
.connection
= self
.ircsock
.server().connect(self
.server
,
146 self
.port
, self
.nickname
,
147 username
=self
.username
,ircname
=self
.realname
)
148 #connection failed, print error and exit
149 except irclib_scrappy
.ServerConnectionError
, x
:
153 #if all goes well, register handlers
154 self
.connection
.add_global_handler("welcome", self
.on_connect
)
155 self
.connection
.add_global_handler("disconnect", self
.on_disconnect
)
156 self
.connection
.add_global_handler("error", self
.on_error
)
157 self
.connection
.add_global_handler("invite", self
.on_invite
)
158 self
.connection
.add_global_handler("join", self
.on_join
)
159 self
.connection
.add_global_handler("kick", self
.on_kick
)
160 self
.connection
.add_global_handler("mode", self
.on_mode
)
161 self
.connection
.add_global_handler("part", self
.on_part
)
162 self
.connection
.add_global_handler("ping", self
.on_ping
)
163 self
.connection
.add_global_handler("pong", self
.on_pong
)
164 self
.connection
.add_global_handler("privmsg", self
.on_privmsg
)
165 self
.connection
.add_global_handler("privnotice", self
.on_privnotice
)
166 self
.connection
.add_global_handler("pubmsg", self
.on_privmsg
)
167 self
.connection
.add_global_handler("quit", self
.on_quit
)
169 #register some events
170 #self.register_msg_event(modload_cmd)
171 #self.register_msg_event(modlist_cmd)
172 #self.register_msg_event(modunload_cmd)
173 self
.register_event("msg", modload_cmd
)
174 self
.register_event("msg", modlist_cmd
)
175 self
.register_event("msg", modunload_cmd
)
176 self
.register_event("privmsg", getevents_cmd
)
180 #enter main event loop after this
183 self
.ircsock
.process_forever()
184 except KeyboardInterrupt:
185 self
.connection
.quit("Keyboard interrupt!")
188 ########################################################################
193 def register_event(self
, event_type
, func
):
194 """Call this with an event_type and a function to call when that event_type happens."""
195 #list of legal event types
198 if not event_type
in self
.events
:
199 debug("I don't know what an %s event is." % event_type
)
202 #event type is good. Add it to appropriate event list
203 #special case for convenience of msg
204 if event_type
== "msg":
205 self
.msg_events
.append(func
)
206 self
.privmsg_events
.append(func
)
207 self
.pubmsg_events
.append(func
)
209 listname
= "self."+event_type
+"_events.append(func)"
211 #debug("Added '%s' to '%s'." % (func, event_type+"_events[]"))
214 def unregister_event(self
, event_type
, func
):
218 ########################################################################
223 def on_connect(self
, conn
, eventlist
):
224 """Called when bot makes a connection to the server."""
225 #do all of our events
226 for func
in self
.connect_events
:
227 thread
.start_new_thread(func
)
230 for chan
in self
.chanlist
:
231 if irclib_scrappy
.is_channel(chan
):
234 ########################################################################
235 def on_disconnect(self
, conn
, eventlist
):
236 """Called when the connection to the server is closed."""
237 for func
in self
.disconnect_events
:
238 thread
.start_new_thread(func
)
239 conn
.quit("Scrappy bot signing off.")
240 #do we need to clean stuff up?
243 ########################################################################
244 def on_error(self
, conn
, eventlist
):
245 debug("Error received: %s" % eventlist
.arguments())
246 for func
in self
.error_events
:
247 thread
.start_new_thread(func
)
250 ########################################################################
251 def on_invite(self
, conn
, eventlist
):
252 debug("Received an invite: %s" % eventlist
.arguments())
253 for func
in self
.invite_events
:
254 thread
.start_new_thread(func
)
256 ########################################################################
257 def on_join(self
, conn
, eventlist
):
258 debug("User joined: %s" % eventlist
.arguments())
259 for func
in self
.join_events
:
260 thread
.start_new_thread(func
)
262 ########################################################################
263 def on_kick(self
, conn
, eventlist
):
264 debug("Someone was kicked: %s" % eventlist
.arguments())
265 for func
in self
.kick_events
:
266 thread
.start_new_thread(func
)
268 ########################################################################
269 def on_mode(self
, conn
, eventlist
):
270 debug("Mode change: %s" % eventlist
.arguments())
271 for func
in self
.mode_events
:
272 thread
.start_new_thread(func
)
274 ########################################################################
275 def on_part(self
, conn
, eventlist
):
276 debug("Part: %s" % eventlist
.arguments())
277 for func
in self
.part_events
:
278 thread
.start_new_thread(func
)
280 ########################################################################
281 def on_ping(self
, conn
, eventlist
):
282 debug("Ping: %s" % eventlist
.arguments())
283 for func
in self
.ping_events
:
284 thread
.start_new_thread(func
)
286 ########################################################################
287 def on_pong(self
, conn
, eventlist
):
288 debug("Pong: %s" % eventlist
.arguments())
289 for func
in self
.pong_events
:
290 thread
.start_new_thread(func
)
292 ########################################################################
293 def on_privmsg(self
, conn
, eventlist
):
294 """Called when bot receives a private or channel (public) message."""
295 #eventlist.arguments() = the message body
296 arg
= eventlist
.arguments()[0]
297 debug(dir(eventlist
))
298 debug(eventlist
.arguments())
299 debug(eventlist
.eventtype())
300 debug(eventlist
.source())
301 debug(eventlist
.target())
304 nick
= irclib_scrappy
.nm_to_n(eventlist
.source())
305 user
= irclib_scrappy
.nm_to_u(eventlist
.source())
306 host
= irclib_scrappy
.nm_to_h(eventlist
.source())
308 if arg
[0] == self
.cmdchar
:
314 for func
in self
.privmsg_events
:
315 thread
.start_new_thread(func
, (conn
, [nick
, user
, host
, iscmd
, cmd
, eventlist
.target()], self
))
319 ########################################################################
320 def on_privnotice(self
, conn
, eventlist
):
321 debug("Privnotice: %s" % eventlist
.arguments())
322 for func
in self
.privnotice_events
:
323 thread
.start_new_thread(func
)
327 ########################################################################
328 #right now this isn't used because it's assumed that privmsg == pubmsg
329 #this should probably be changed...
330 def on_pubmsg(self
, conn
, eventlist
):
331 debug("Pubmsg: % " % eventlist
.arguments())
332 for func
in pubmsg_events
:
335 ########################################################################
336 def on_quit(self
, conn
, eventlist
):
337 debug("Quit: %s" % eventlist
.arguments())
338 for func
in quit_events
:
339 thread
.start_new_thread(func
)
345 def register_privmsg_event(self
,func
):
346 self
.privmsg_events
.append(func
)
348 def register_pubmsg_event(self
,func
):
349 self
.pubmsg_events
.append(func
)
351 #Convenience function, registers the func
352 #for both privmsgs and pubmsgs
353 def register_msg_event(self
,func
):
354 self
.register_privmsg_event(func
)
355 self
.register_pubmsg_event(func
)
357 def register_onload_event(self
,func
):
358 self
.onload_events
.append(func
)
360 def register_onquit_event(self
,func
):
361 self
.onquit_events
.append(func
)
366 # def on_connect(self, c, event):
367 # for ch in self.chanlist:
368 # if irclib_scrappy.is_channel(ch) :
371 # if self.identify == True:
372 # self.c.privmsg("nickserv", "identify %s" % self.nickservpass)
374 # def on_pubmsg(self, c, event):
375 # arg = event.arguments()[0]
378 # nick = irclib_scrappy.nm_to_n(event.source())
379 # user = irclib_scrappy.nm_to_u(event.source())
380 # host = irclib_scrappy.nm_to_h(event.source())
382 # if arg[0] == self.cmdchar:
388 # #dispatch the command
389 # for func in self.pubmsg_events:
390 # thread.start_new_thread(func, (c,[nick,user,host,iscmd,cmd,event.target()],self))
392 # def on_privmsg(self, c, event):
393 # cmd = event.arguments()[0]
396 # nick = irclib_scrappy.nm_to_n(event.source())
397 # user = irclib_scrappy.nm_to_u(event.source())
398 # host = irclib_scrappy.nm_to_h(event.source())
400 # if cmd[0] == self.cmdchar:
401 # c.privmsg(nick,"You privmsged me, you don't need to " +
402 # "prefix commands with %s" % self.cmdchar)
407 # #dispatch the command
408 # for func in self.privmsg_events:
409 # thread.start_new_thread(func, (c,[nick,user,host,iscmd,cmd,event.target()],self))
412 # def on_disconnect(self, c, event):
413 # for func in self.onquit_events:
419 # for func in self.onload_events:
425 def load_module(self
,name
):
426 #for whatever reason, OS X needs your modules folder to be in PYTHONPATH to load
428 sys
.path
.append(os
.path
.join(os
.getcwd(), "modules"))
429 exec("from %s import %s" % (name
, name
))
430 #module = __import__(name)
432 #should be error output
433 print "No such module\n"
434 print traceback
.print_exc()
435 return "Sorry, there was an error loading %s." % name
437 eval(name
).init(self
)
438 self
.register_module(name
,'foo','foo')
439 return "Loaded %s." % name
441 def unload_module(self
, name
):
443 self
.modulelist
.index(name
)
445 print "No such module!"
446 return "Sorry, no module named %s is loaded." % name
447 self
.unregister_module(name
)
448 return "%s unloaded." % name
450 def register_module(self
, name
, eventlist
, function
):
451 self
.modulelist
.append(name
)
453 def unregister_module(self
, name
):
454 self
.modulelist
.remove(name
)
458 def list_modules(self
):
459 """List currently loaded modules."""
460 print "Currently loaded modules:"
461 for mod
in self
.modulelist
:
465 if(__name__
== "__main__"):