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.
10 ################################################################################
11 #set to False to turn off debugging to stdout
18 ################################################################################
20 #this is our main bot class. Once scrappy.py is called, an instance of this
21 #class (our bot) gets created and some initialization is done. The real work is
22 #done via modules that get loaded here.
26 debug("Scrappy bot started.")
27 #hard-code these for now
28 #then write a config loading module
30 self
.nickname
= 'Scrappy'
31 self
.username
= 'scrappy'
32 self
.realname
= 'Scrappy Bot'
40 #each module adds functions to be called to these events.
41 #each event handler calls all of the functions within its list.
43 self
.eventlist
= ["connect", "disconnect", "error", "invite",
44 "join", "kick", "load", "mode", "msg", "part", "ping", "pong",
45 "privmsg", "privnotice", "pubmsg", "pubnotice", "quit"]
46 self
.connect_events
= []
47 self
.disconnect_events
= []
48 self
.error_events
= []
49 self
.invite_events
= []
58 self
.privmsg_events
= []
59 self
.privnotice_events
= []
60 self
.pubmsg_events
= []
61 self
.pubnotice_events
= []
67 ########################################################################
69 """Parse the command line args and print a usage message if incorrect."""
70 #need at least a server to connect to
75 #split out the port if specified
76 s
= sys
.argv
[1].split(":",1)
79 if len(s
) == 2: #have a port
83 print "Error: Invalid port."
86 self
.nickname
= sys
.argv
[2]
87 #add the channels to a list
88 for chan
in sys
.argv
[3:]:
89 self
.chanlist
.append("#%s" % chan
)
91 def print_usage(self
):
92 print 'Usage: %s <server[:port]> <nickname> [channel 1 channel 2 ... channelN]' % sys
.argv
[0]
94 ########################################################################
96 """The real work. Initialize our connection and register events."""
97 #parse comamnd line and create a new socket
99 self
.ircsock
= irclib_scrappy
.IRC()
101 #attempt to create a socket and connect to the server
103 self
.connection
= self
.ircsock
.server().connect(self
.server
, self
.port
, self
.nickname
, username
= self
.username
, ircname
= self
.realname
)
104 except irclib_scrappy
.ServerConnectionError
, x
: #connection failed, print error and exit
108 #register handlers for events
109 self
.connection
.add_global_handler("welcome", self
.on_connect
)
110 self
.connection
.add_global_handler("disconnect", self
.on_disconnect
)
111 self
.connection
.add_global_handler("error", self
.on_error
)
112 self
.connection
.add_global_handler("invite", self
.on_invite
)
113 self
.connection
.add_global_handler("join", self
.on_join
)
114 self
.connection
.add_global_handler("kick", self
.on_kick
)
115 self
.connection
.add_global_handler("mode", self
.on_mode
)
116 self
.connection
.add_global_handler("part", self
.on_part
)
117 self
.connection
.add_global_handler("ping", self
.on_ping
)
118 self
.connection
.add_global_handler("pong", self
.on_pong
)
119 self
.connection
.add_global_handler("privmsg", self
.on_privmsg
)
120 self
.connection
.add_global_handler("privnotice", self
.on_privnotice
)
121 self
.connection
.add_global_handler("pubmsg", self
.on_privmsg
)
122 self
.connection
.add_global_handler("quit", self
.on_quit
)
126 #enter main event loop after this
129 self
.ircsock
.process_forever()
130 except KeyboardInterrupt:
131 self
.connection
.quit("Keyboard interrupt!")
133 ########################################################################
138 def register_event(self
, event_type
, func
):
139 """Call this with an event_type and a function to call when that event_type happens."""
140 #list of legal event types
144 if not event_type
in self
.eventlist
:
145 debug("Oops! I don't know what a %s event is." % event_type
)
147 #event is good, add them to event list
148 #keep these in ABC order
149 #should these require the func name be unique?
151 if event_type
== "connect":
152 self
.connect_events
.append(func
)
153 if event_type
== "disconnect":
154 self
.disconnect_events
.append(func
)
155 if event_type
== "error":
156 self
.error_events
.append(func
)
157 if event_type
== "invite":
158 self
.invite_events
.append(func
)
159 if event_type
== "join":
160 self
.join_events
.append(func
)
161 if event_type
== "kick":
162 self
.kick_events
.append(func
)
163 if event_type
== "load":
164 self
.load_events
.append(func
)
165 if event_type
== "mode":
166 self
.mode_events
.append(func
)
167 if event_type
== "msg":
168 self
.privmsg_events
.append(func
)
169 self
.pubmsg_events
.append(func
)
170 if event_type
== "part":
171 self
.part_events
.append(func
)
172 if event_type
== "ping":
173 self
.ping_events
.append(func
)
174 if event_type
== "pong":
175 self
.pong_events
.append(func
)
176 if event_type
== "privmsg":
177 self
.privmsg_events
.append(func
)
178 if event_type
== "privnotice":
179 self
.privnotice_events
.append(func
)
180 if event_type
== "pubmsg":
181 self
.pubmsg_events
.append(func
)
182 if event_type
== "pubnotice":
183 self
._events
.append(func
)
184 if event_type
== "quit":
185 self
.quit_events
.append(func
)
188 def deregister_event(self
, event_type
, func
):
190 ########################################################################
194 #note that right now these don't all pass args to the functions they call
195 #We'll need to eventuall pass the appropriate args.
197 def on_connect(self
, conn
, eventlist
):
198 """Called when bot makes a connection to the server."""
199 #do all of our events
200 for func
in self
.connect_events
:
204 for chan
in self
.chanlist
:
205 if irclib_scrappy
.is_channel(chan
):
208 ########################################################################
209 def on_disconnect(self
, conn
, eventlist
):
210 """Called when the connection to the server is closed."""
211 for func
in self
.disconnect_events
:
213 conn
.quit("Scrappy bot signing off.")
214 #do we need to clean stuff up?
217 ########################################################################
218 def on_error(self
, conn
, eventlist
):
219 debug("Error received: %s" % eventlist
.arguments())
220 for func
in self
.error_events
:
223 ########################################################################
224 def on_invite(self
, conn
, eventlist
):
225 debug("Received an invite: %s" % eventlist
.arguments())
226 for func
in self
.invite_events
:
229 ########################################################################
230 def on_join(self
, conn
, eventlist
):
231 debug("User joined: %s" % eventlist
.arguments())
232 for func
in self
.join_events
:
235 ########################################################################
236 def on_kick(self
, conn
, eventlist
):
237 debug("Someone was kicked: %s" % eventlist
.arguments())
238 for func
in self
.kick_events
:
241 ########################################################################
242 def on_mode(self
, conn
, eventlist
):
243 debug("Mode change: %s" % eventlist
.arguments())
244 for func
in self
.mode_events
:
247 ########################################################################
248 def on_part(self
, conn
, eventlist
):
249 debug("Part: %s" % eventlist
.arguments())
250 for func
in self
.part_events
:
253 ########################################################################
254 def on_ping(self
, conn
, eventlist
):
255 debug("Ping: %s" % eventlist
.arguments())
256 for func
in self
.ping_events
:
259 ########################################################################
260 def on_pong(self
, conn
, eventlist
):
261 debug("Pong: %s" % eventlist
.arguments())
262 for func
in self
.pong_events
:
265 ########################################################################
266 def on_privmsg(self
, conn
, eventlist
):
267 """Called when bot receives a private or channel (public) message."""
268 #eventlist.arguments() = the message body
269 cmd
= eventlist
.arguments()[0]
271 nick
= irclib_scrappy
.nm_to_n(eventlist
.source())
272 user
= irclib_scrappy
.nm_to_u(eventlist
.source())
273 host
= irclib_scrappy
.nm_to_h(eventlist
.source())
275 for func
in self
.privmsg_events
:
276 func(conn
, [nick
, user
, host
, true
, None, event
.target()], self
)
278 ########################################################################
279 def on_privnotice(self
, conn
, eventlist
):
280 debug("Privnotice: %s" % eventlist
.arguments())
281 for func
in self
.privnotice_events
:
284 ########################################################################
285 def on_pubmsg(self
, conn
, eventlist
):
286 debug("Pubmsg: % " % eventlist
.arguments())
287 for func
in pubmsg_events
:
290 ########################################################################
291 def on_quit(self
, conn
, eventlist
):
292 debug("Quit: %s" % eventlist
.arguments())
293 for func
in quit_events
:
297 ################################################################################
299 if __name__
== "__main__":