Recipe13.16.Connecting to IRC and Logging Messages to Disk


Recipe 13.16. Connecting to IRC and Logging Messages to Disk

Credit: Gian Mario Tagliaretti, J P Calderone

Problem

You want to connect to an IRC (Internet Relay Chat) server, join a channel, and store private messages into a file on your hard disk for future reading.

Solution

The Twisted framework has excellent support for many network protocols, including IRC, so we can perform this recipe's task with a very simple script:

from twisted.internet import reactor, protocol from twisted.protocols import irc class LoggingIRCClient(irc.IRCClient):     logfile = file('/tmp/msg.txt', 'a+')     nickname = 'logging_bot'     def signedOn(self):         self.join('#test_py')     def privmsg(self, user, channel, message):         self.logfile.write(user.split('!')[0] + ' -> ' + message + '\n')         self.logfile.flush( ) def main( ):     f = protocol.ReconnectingClientFactory( )     f.protocol = LoggingIRCClient     reactor.connectTCP('irc.freenode.net', 6667, f)     reactor.run( ) if _ _name_ _ == '_ _main_ _':     main( )

Discussion

If, for some strange reason, you cannot use Twisted, then you can implement similar functionality from scratch based only on the Python Standard Library. Here's a reasonable approachnowhere as simple, solid, and robust as, and lacking the beneficial performance of, Twisted, but nevertheless sort of workable:

import socket SERVER = 'irc.freenode.net' PORT = 6667 NICKNAME = 'logging_bot' CHANNEL = '#test_py' IRC = socket.socket(socket.AF_INET, socket.SOCK_STREAM) def irc_conn( ):     IRC.connect((SERVER, PORT)) def send_data(command):     IRC.send(command + '\n') def join(channel):     send_data("JOIN %s" % channel) def login(nickname, username='user', password=None,           realname='Pythonist', hostname='Helena', servername='Server'):     send_data("USER %s %s %s %s" %                (username, hostname, servername, realname))     send_data("NICK %s" % nickname) irc_conn( ) login(NICKNAME) join(CHANNEL) filetxt = open('/tmp/msg.txt', 'a+') try:     while True:         buffer = IRC.recv(1024)         msg = buffer.split( )         if msg[0] == "PING":             # answer PING with PONG, as RFC 1459 specifies             send_data("PONG %s" % msg[1])           if msg [1] == 'PRIVMSG' and msg[2] == NICKNAME:             nick_name = msg[0][:msg[0].find("!")]             message = ' '.join(msg[3:])             filetxt.write(nick_name.lstrip(':') + ' -> ' +                           message.lstrip(':') + '\n')             filetxt.flush( ) finally:     filetxt.close( )

For this roll-our-own reimplementation, we do need some understanding of the protocol's RFC, such as the need to answer a server's PING with a proper PONG to confirm that our connection is alive. In any case, since the code has already grown to over twice as much as Twisted requires, we've omitted niceties (which are very important for reliable unattended operation) such as automatic reconnection attempts when the connection drops, which Twisted gives us effortlessly via its protocol.ReconnectingClientFactory.

See Also

Documentation for the standard library module socket in the Library Reference and Python in a Nutshell; twisted is at http://www.twistedmatrix.com.



Python Cookbook
Python Cookbook
ISBN: 0596007973
EAN: 2147483647
Year: 2004
Pages: 420

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net