IRC on a Higher Level Concluded (
Page 1 of 4 )
If you've been following this series of articles closely, then you already have the skills necessary to develop applications that communicate through IRC. The Python-IRCLib library is easy to learn and use, so putting it to work should not be a difficult task at all. However, the library contains a few more gems that are worth taking a look at, and these gems can make your development process go even more smoothly.SimpleIRCClient
In the first article of this series, I explained how to catch and respond to events in an application. However, you probably noticed that the code behind this was a bit messy and long. First, we have to define a handler function that responds to the triggered event. Then, we need to wire our handler function to our IRC object, using the add_global_handler method, which accepts a string corresponding to the event we want to work with and the name of the handler function. The code doesn't look pretty at all, but, fortunately, the library contains a shortcut to this all: the SimpleIRCClient class.
The SimpleIRCClient class can be subclassed to create a functional IRC client. It eliminates many of the steps normally required. All you have to do is create an instance of the SimpleIRCClient and call the connect method to get started. From there, you can access the methods of ServerConnection. After that, all that's left is calling the start method to accept incoming data. Let's create a simple client that joins a given channel and sits there:
import irclib
# Connection information
network = 'irc.freenode.net'
port = 6667
channel = '#irclib'
nick = 'PyTest'
name = 'Python Test'
# Subclass SimpleIRCClient
class ClientClass ( irclib.SimpleIRCClient ):
pass
# Create an instance of ClientClass
client = ClientClass()
# Connect
client.connect ( network, port, nick, ircname = name )
# Join the specified channel
client.connection.join ( channel )
# Start
client.start()
As you can see, this object-oriented approach to creating a client is very simple to employ. In case you don't immediately see the advantage of using the SimpleIRCClient class, however, let's move on to the next topic now that we've established a connection. Events are, as I've stated several times in the previous articles, crucial to most applications of purpose. The SimpleIRCClient really shines when it comes to events, allowing you to create methods of your subclass that handle events. These methods come in the form of on_event, and they are called automatically when the appropriate event is triggered. For example, here is an application that logs messages in the file “channelLog.txt”:
import irclib
# Connection information
network = 'irc.freenode.net'
port = 6667
channel = '#irclib'
nick = 'PyTest'
name = 'Python Test'
# Open a file to store the logs in
# We will append data to this file ( "a" )
logFile = open ( 'channelLog.txt', 'a' )
# Subclass SimpleIRCClient
class ClientClass ( irclib.SimpleIRCClient ):
# Handle private messages
def on_pubmsg ( self, connection, event ):
# Write to the log
source = event.source().split ( '!' ) [ 0 ]
text = event.arguments() [ 0 ]
logFile.write ( source + '-> ' + text + '\n' )
# Create our client and connect
client = ClientClass()
client.connect ( network, port, nick, ircname = name )
client.connection.join ( channel )
# Start the client
client.start()
As you can see from the above example, the handler method is structured the exact same way as a normal handler, except that it's a method and its name corresponds to the event we want to handle. We omit the add_global_handler method, compacting our code.
Any event will work with the SimpleIRCClient class. You are certainly not limited to the common ones. Here's an application that gathers information on clients joining the application's channel through the use of the client-to-client protocol:
import irclib
import time
# Connection variables
network = 'irc.freenode.net'
port = 6667
channel = '#irclib'
nick = 'PyTest'
name = 'Python Test'
# Our client class
class QueryClient ( irclib.SimpleIRCClient ):
# Query users who join the channel
def on_join ( self, connection, event ):
source = event.source().split ( '!' ) [ 0 ]
connection.ctcp ( 'TIME', source )
connection.ctcp ( 'VERSION', source )
connection.ctcp ( 'USERINFO', source )
connection.ctcp ( 'PING', source, str ( time.time() ) )
# Handle CTCP replies
def on_ctcpreply ( self, connection, event ):
source = event.source().split ( '!' ) [ 0 ]
command = event.arguments() [ 0 ].upper()
# Display the user's local time
if command == 'TIME':
print source + '-> Local time: ' + event.arguments()
[ 1 ]
# Display the user's verison
elif command == 'VERSION':
print source + '-> Verison: ' + event.arguments() [ 1 ]
# Display the user's information
elif command == 'USERINFO':
print source + '-> Info: ' + event.arguments() [ 1 ]
# Display the user's ping
elif command == 'PING':
print source + '-> Ping: ' + str ( time.time() - float ( event.arguments() [ 1 ] ) ) + ' seconds'
# Create the client and connect
client = QueryClient()
client.connect ( network, port, nick, ircname = name )
client.connection.join ( channel )
# Loop
client.start()
Even in a more complex application, the code is neat and organized.