O'Reilly Hacks
oreilly.comO'Reilly NetworkSafari BookshelfConferences Sign In/My Account | View Cart   
Book List Learning Lab PDFs O'Reilly Gear Newsletters Press Room Jobs  

Buy the book!
IRC Hacks
By Paul Mutton
July 2004
More Info

A Simple Python IRC Client
Python doesn't include an IRC module as standard, but connecting is nonetheless easy. Make a simple client that connects to an IRC server
The Code
[Discuss (1) | Link to this hack]

The Code

Save this as simplebot.py:

import sys
import socket
import string


s=socket.socket( )
s.connect((HOST, PORT))
s.send("NICK %s\r\n" % NICK)
s.send("USER %s %s bla :%s\r\n" % (IDENT, HOST, REALNAME))

while 1:
    temp=string.split(readbuffer, "\n")
    readbuffer=temp.pop( )

    for line in temp:

            s.send("PONG %s\r\n" % line[1])

Lots of this code should be self-explanatory by now. It starts by importing all the modules you're going to need. The second block of code is a bunch of variables that you can change. These determine which server we connect to, the nickname we use, and so forth.

The block of code after that is the first one that actually does anything. It creates a socket and connects to the server of choice. This example will connect to the freenode IRC network (irc.freenode.net). It also registers the client by sending NICK and USER commands to the server.

The bot then enters an infinite loop (to shut it down, press Ctrl-C). The first block of code inside the loop reads a maximum of 1024 bytes from the server and appends it to the readbuffer. You need a readbuffer because you might not always be able to read complete IRC commands from the server (due to a saturated Internet connection, operating system limits, etc). So whatever you read, you need to append it to the read buffer. The read buffer is then split into a list of strings, using \n as a separator. The last line in this list is possibly a half-received line, so it is stored back into the read buffer.

Before we're able to process the lines from the read buffer in a normal manner, there's one thing left to do. You need to remove the trailing \r character from the end of the lines. The string.rstrip( ) function does exactly this.

I can hear you thinking, "IRC uses \r\n as a message separator. Why don't you just split the lines using that as a separator, instead of just \n? You won't end up with an \r in the first place, then." This would be a better solution, if it weren't for some stubborn IRC networks that choose to ignore the RFC and use \n instead. So although the RFC says each message is supposed to be separated by an \r\n, you need to treat \r as optional.

Now that you have "clean" lines to process, you need to look for PING commands sent to the client. If the server sends it PING:randomstring, you need to reply with PONG :randomstring. The last three lines of code do this. The line is split into a list of strings, using a space as a separator. The if statement checks to see if the line started with a PING and sends back a PONG in response.

That's all there is to it. Of course, this bot doesn't do anything yet, but I'm sure you're able to figure out how to go on from here. One last thing—you may have noticed that I'm not using a send buffer. If you send something over an Internet socket, it's not guaranteed that all data is actually sent. So if you wanted to make this example completely resilient, you'd need to implement a send buffer to store any data you might not be able to send. This simple bot does not include this feature, as it isn't often required and would make the example more complex. If this is a concern, you can use IRCLib , which implements the send buffer for you.

O'Reilly Home | Privacy Policy

© 2007 O'Reilly Media, Inc.
Website: | Customer Service: | Book issues:

All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.