Following up on an earlier DevShed article covering the basics of Python and Internet Relay Chat, this article takes some common IRC tasks, such as listing the users in a given channel or manipulating a channel's modes, and shows how to turn them into Pyton code.
In “Python and IRC,” I explained the basics of connecting to an IRC server and sending a few messages. Obviously, however, you know that there is much more to IRC than I explained. Forgive the cliché, but what the last article covers is truly only the tip of the iceberg that is the Internet Relay Chat Protocol.
This article will cover some more basics. We'll take some common tasks, such as listing the users in a given channel or manipulating a channel's modes, and turn them into Python code. If you haven't read “Python and IRC,” this article won't do you much good. Even if you have, it might be helpful to speed through it and refresh your memory. With that said, let's move on.
Creating an IRC Module
If I loaded each and every example in this article with basic socket garbage, not only would it be incredibly pointless, but it would be annoying and difficult to sort through to actually get the important stuff. The solution is to create a module that will do all the socket work for us. Actually, scratch that, why not turn this article a bit and build a module that will do socket work and basic IRC tasks? That sounds a lot better, and, as a bonus, all the code we produce can be recycled in future applications.
Let's call our module irchat. In ths module, let's create a class, IRC. Our code will be put into IRC's methods. When an instance of IRC is created, Python will automatically connect to the network specified in the arguments, using the data specified in the arguments. To avoid repetition of “\r\n”, we'll create a send method that automatically appends “\r\n” to the given text and then sends it over. To connect to the server, we're going to have to specify a nickname using IRC's “NICK” command. Since you may want your Python client to use the “NICK” command again, we'll make a method for it. A quit method would also be helpful. Enough lecturing, though, let's get to some code:
The above module will handle the very basics. When an instance of IRC is created and the required data is passed to it, a socket is created and connected. The nickname is then set using the nick method, which takes advantage of the send method. The “USER” command is then sent. No suprises there.
To use the module, you would do something like this:
From here on, we will be adding methods to the IRC class. Keep that in mind. Don't go off and create lone functions and later wonder why nothing happens.
Let's catch up with “Python and IRC” now. One of the most important things that “Python and IRC” teaches us is how to receive messages from the server and take them apart, making them easier to process. To do this, we must first create a method, recv, which receives data from the network and then splits it up. The data should be split at “\r\n” (which effectively splits it into commands) and added to a variable, queue. Remember that data will get cut off, too, so we have to store partial data in a variable, partial, and let it get picked up by queue on the next call to recv. This may sound complicated, but it's pretty simple:
We must now create a method, retrieve, that pops the first command off of queue and returns it. If the queue is empty, the method should return False:
def retrieve ( self ):
if len ( self.queue ):
command = self.queue [ 0 ]
self.queue.pop ( 0 )
return command
else:
return False
Finally, we have to create a method that dismantles individual commands into something more workable. Recall what a message from the server looks like:
:source some parameters
:source some parameters :another parameter
Pulling that apart isn't too complicated, although it may seem like it. If we split the string in the correct places, we can manage:
Here's one way to use our new module. The following script connects to an IRC network and spawns a thread to constantly call the recv module, which, as you know, puts commands into the queue list. It then dismantles the data and prints it out in a neater form: