Home arrow Python arrow Page 3 - IRC on a Higher Level

Events - Python

Python is very suitable for working with the Internet Relay Chat (IRC) protocol. But working directly with a protocol can be a bit messy. Fortunately, there is a library that can simplify this work: Python-IRCLib. This article, the first of three parts, takes a look at this library and what you can do with it, with a focus on event handling.

TABLE OF CONTENTS:
  1. IRC on a Higher Level
  2. Getting Started
  3. Events
  4. All Supported Events
By: Peyton McCullough
Rating: starstarstarstarstar / 10
October 05, 2005

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

Now that you know how to connect your application to an IRC network, you are probably wondering how to do something useful, namely how to process incoming information and respond appropriately to it. Before we get to that, though, it is important that you understand exactly what information is coming to you. Python-IRCLib will display information to and from the server if you simply add this line after you import irclib:

irclib.DEBUG = True

Try creating a program with the line and examining the incoming and outgoing data.

Now we need to handle the data. Let's work on handling the data initially received from the server first. To do this, we register an event handler with the add_global_handler, passing two or three arguments. The first argument is the code that corresponds to the event we want to handle. We'll get to this in a second. The second argument points to the function that is to handle the event. The third argument is optional, and it is named priority. The lower the number is, the higher the priority of the event:

import irclib

# Connection information
network = 'irc.freenode.net'
port = 6667
channel = '#irclib'
nick = 'PyTest'
name = 'Test One'

# Generic echo handler ( space added )
# This is used to output some initial information from the server
def handleEcho ( connection, event ):

   print
   print ' '.join ( event.arguments() )

# Generic echo handler ( no space added )
def handleNoSpace ( connection, event ):

   print ' '.join ( event.arguments() )

# Handle private notices
def handlePrivNotice ( connection, event ):

   if event.source():
      print ':: ' + event.source() + ' ->' + event.arguments() [ 0 ]
   else:
      print event.arguments() [ 0 ]

# Handle channel joins
def handleJoin ( connection, event ):

   # The source needs to be split into just the name
   # It comes in the format nickname!user@host
   print event.source().split ( '!' ) [ 0 ] + ' has joined ' + event.target()

# Create the IRC object
irc = irclib.IRC()

# Register handlers
irc.add_global_handler ( 'privnotice', handlePrivNotice ) #
Private notice
irc.add_global_handler ( 'welcome', handleEcho ) # Welcome
message
irc.add_global_handler ( 'yourhost', handleEcho ) # Host message
irc.add_global_handler ( 'created', handleEcho ) # Server
creation message
irc.add_global_handler ( 'myinfo', handleEcho ) # "My info"
message
irc.add_global_handler ( 'featurelist', handleEcho ) # Server feature list
irc.add_global_handler ( 'luserclient', handleEcho ) # User count
irc.add_global_handler ( 'luserop', handleEcho ) # Operator count
irc.add_global_handler ( 'luserchannels', handleEcho ) # Channel
count
irc.add_global_handler ( 'luserme', handleEcho ) # Server client
count
irc.add_global_handler ( 'n_local', handleEcho ) # Server client
count/maximum
irc.add_global_handler ( 'n_global', handleEcho ) # Network
client count/maximum
irc.add_global_handler ( 'luserconns', handleEcho ) # Record
client count
irc.add_global_handler ( 'luserunknown', handleEcho ) # Unknown
connections
irc.add_global_handler ( 'motdstart', handleEcho ) # Message of
the day ( start )
irc.add_global_handler ( 'motd', handleNoSpace ) # Message of the
day
irc.add_global_handler ( 'edofmotd', handleEcho ) # Message of
the day ( end )
irc.add_global_handler ( 'join', handleJoin ) # Channel join
irc.add_global_handler ( 'namreply', handleNoSpace ) # Channel
name list
irc.add_global_handler ( 'endofnames', handleNoSpace ) # Channel
name list ( end )

# Connect to the network
server = irc.server()
server.connect ( network, port, nick, ircname = name )
server.join ( channel )

# Run an infinite loop
irc.process_forever()

The above code may seem like a lot, but in reality, it's not. Before we create the IRC object, we define a few functions to handle certain events. Two are generic functions that merely echo the arguments of the received commands, and the other two are aimed at specific events. We then create the IRC object and register handlers for a number of events.

The first events we handle are private notices. The server will issue several of these upon connection, so we need to find a way to display them. We then handle a number of messages that the server gives us upon connection. The messages mainly deal with statistics and features of the server, so I won't get into too much detail. They are pretty easy to analyze.

When the server is about to send us the message of the day, it sends us the command “375”. Python-IRCLib translates this to “motdstart”. We'll be handling many numeric commands from the server, so I'll provide a list shortly. If the DEBUG variable is set to True, the library will display the translated command to us, too. The server then sends us the message of the day, followed by a command to end the message of the day.

Our client is set to join the channel “#irclib”. When this happens, a message will be sent to the channel notifying its users of our presence. The function handleJoin handles this event. We simply take the source of the command and join it to the target of the command. We also break apart the source to get a more readable name. When we join the channel, the server sends a list of names to us, which we display with handleNoSpace.

The handler functions are passed two arguments, an event object and a server object. The former contains the source of the command ( event.source ), the target of the command ( event.target ) and the arguments of the command ( event.arguments ). The latter is used in case we need to respond to the message sent. For example, let's consider an “INVITE” message from another user. It is simply a message from the user inviting us to join a certain channel. We could set up a handler that would automatically join the channel like this:

def handleInvite ( connection, event ):

   connection.join ( event.arguments() [ 0 ] )

...

irc.add_global_handler ( 'invite', handleInvite ) # Invite

Our application is, of course, far from complete if we're looking to handle even the more common events. We still have more events to consider. For example, if someone sends a message to use or the channel, it would be wise to display or consider a reply:

# Private messages
def handlePrivMessage ( connection, event ):

   print event.source().split ( '!' ) [ 0 ] + ': ' + event.arguments() [ 0 ]

   # Respond to a “hello” message
   if event.arguments() [ 0 ].lower().find ( 'hello' ) == 0:
      connection.privmsg ( event.source().split ( '!' ) [ 0 ],
'Hello.' )

# Public messages
def handlePubMessage ( connection, event ):

   print event.target() + '> ' + event.source().split ( '!' ) [ 0 ] + ': ' +
event.arguments() [ 0 ]

...

irc.add_global_handler ( 'privmsg', handlePrivMessage )
irc.add_global_handler ( 'pubmsg', handlePubMessage )

Another common event would be someone changing the topic of a channel. This event could easily be caught:

def handleTopic ( connection, event ):

   print event.source().split ( '!' ) [ 0 ] + ' has set the topic
to "' + event.arguments() [ 0 ] + '"'

...

irc.add_global_handler ( 'topic', handleTopic )

Another common event would be a mode change to either a channel or a user. This bit of code will catch the event and display the appropriate message:

def handleMode ( connection, event ):

   # Channel mode
   if len ( event.arguments() ) < 2:
      print event.source().split ( '!' ) [ 0 ] + ' has altered
the channel\'s mode: ' + event.arguments() [ 0 ]

   # User mode
   else:
      print event.source().split ( '!' ) [ 0 ] + ' has altered '
+ event.arguments() [ 1 ] + '\'s mode: ' + event.arguments()
[ 0 ]

...

irc.add_global_handler ( 'mode', handleMode )

Of course, the users of a network will leave channels, and we should learn how to catch such an event. A user may part a channel, disconnect from the network or be removed from the channel by an operator, so we should consider all three events:

def handlePart ( connection, event ):

   print event.source().split ( '!' ) [ 0 ] + ' has quit ' +
event.target()

def handleQuit ( connection, event ):

   print event.source().split ( '!' ) [ 0 ] + ' has disconnected:
' + event.arguments() [ 0 ]

def handleKick ( connection, event ):

   print event.arguments() [ 0 ] + ' has been kicked by ' +
event.source().split ( '!' ) [ 0 ] + ': ' + event.arguments()
[ 1 ]

...

irc.add_global_handler ( 'part', handlePart )
irc.add_global_handler ( 'quit', handleQuit )
irc.add_global_handler ( 'kick', handleKick )

Now our application should be sensitive to a variety of common events. Each handler function can be modified to perform an appropriate action. For examle, if you wanted to welcome users to the channel when they join, you would simply modify whatever function is attached to the event “join”.

Sometimes, you'll want to unbind a function. For example, let's say you wanted to remove handleKick from the “kick” event. You would call the remove_global_handler method, which takes the same arguments as add_global_handler:

irc.remove_global_handler ( 'kick', handleKick )



 
 
>>> More Python Articles          >>> More By Peyton McCullough
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PYTHON ARTICLES

- Python Big Data Company Gets DARPA Funding
- Python 32 Now Available
- Final Alpha for Python 3.2 is Released
- Python 3.1: String Formatting
- Python 3.1: Strings and Quotes
- Python 3.1: Programming Basics and Strings
- Tuples and Other Python Object Types
- The Dictionary Python Object Type
- String and List Python Object Types
- Introducing Python Object Types
- Mobile Programming using PyS60: Advanced UI ...
- Nested Functions in Python
- Python Parameters, Functions and Arguments
- Python Statements and Functions
- Statements and Iterators in Python

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: