asyncore/asynchat IRC client

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • brks
    New Member
    • Jul 2007
    • 6

    asyncore/asynchat IRC client

    Hi there guys and girls.

    I'm writing an IRC bot (even though there are loads out there that can do what I want, I love to learn-by-doing) and currently use the following to connect to the server:

    [CODE=python]import sys, string, os
    import socket, asyncore, asynchat
    from irc_config import *
    from irc_parse import *
    from irc_modules import *
    #from irc_connect import *

    # create our socket
    sock = socket.socket()

    # start us up
    parser = parse( sock, config.s )

    # load all our modules
    startup_modules ( parser )

    # connect to our server
    sock.connect( ( config.s, config.p ) )

    # our buffer destination
    readbuffer = ''

    # send our initial nick/user bits
    sock.send( 'NICK %s\r\n' % config.n )
    sock.send( 'USER %s iw 0 :%s\r\n' % ( config.i, config.r ) )

    # enter our data loop
    while 1:
    try:
    bytes_received = readbuffer

    while bytes_received >= config.b:
    packet = sock.recv( config.b )
    bytes_received = len( packet )
    readbuffer += packet

    except Exception, e:
    if config.b == 1:
    print e
    print '<< DEBUG >> Fatal error.'
    sys.exit(1)

    while readbuffer.find ( '\r\n' ) >= 0:
    currentline = readbuffer[:readbuffer.fin d( '\r\n' )]
    readbuffer = readbuffer[len( currentline )+2:]
    print currentline

    parser.irc_pars e( currentline )[/CODE]

    Now, this works - just fine and dandy. However, the birds aren't quite tweeting and I'm not sitting bare arsed on the office photocopier with a party hat on quite yet. No, no. In fact, I realise that this blocking method of reading sucks hard. I have written numerous IRC clients in C before that use select and fifo buffers and I wish to do the same in python.

    I am having a very hard time getting my head around even where to start with this - can someone please help with a very simple example that I can butcher to my own evil devices?

    Thanks for the help in advance,

    Ian
    Last edited by bartonc; Jul 2 '07, 10:54 PM. Reason: Added =python to code tags
  • bartonc
    Recognized Expert Expert
    • Sep 2006
    • 6478

    #2
    Hey, Ian. Love the way you write. I've got a USB model that queues read packets for the app to read when it gets around to it around here somewhere. I'll dig up that link for you.

    I hope you like our Python forum,
    Barton

    Comment

    • bartonc
      Recognized Expert Expert
      • Sep 2006
      • 6478

      #3
      Originally posted by bartonc
      Hey, Ian. Love the way you write. I've got a USB model that queues read packets for the app to read when it gets around to it around here somewhere. I'll dig up that link for you.

      I hope you like our Python forum,
      Barton
      Ah, here it is. Threading and Queuing, all in one.

      I haven't used the asyn* modules.

      Comment

      • brks
        New Member
        • Jul 2007
        • 6

        #4
        Originally posted by bartonc
        Hey, Ian. Love the way you write.
        Thank you - I've found over the years that the more entertaining your questions are to read, the more likely people are to read and reply! :o)

        Originally posted by bartonc
        Ah, here it is. Threading and Queuing, all in one.

        I haven't used the asyn* modules.
        Thanks again for that - it was an interesting read. I see the logic behind the threading, almost deamonizing reading and the concept I think it pretty much what I need. However, much to my distress, every current example of python IRC bots manages to utilise asyn* modules in such a way as to completely confuse me and, I personally think, over-complicate the whole thing. I'm pretty sure it should go somewhere along the lines of (mostly from python bot 'phenny'):

        [CODE=python]
        import sys, os, socket, asyncore, asynchat

        class Bot:
        def __init__(self, nick):
        asynchat.async_ chat.__init__(s elf)
        self.buffer = ''
        self.set_termin ator('\r\n')
        self.nick = nick
        self.msgstack = []

        def write(self, args, text=None):
        if text is not None:
        self.push(' '.join(args) + ' :' + text + '\r\n')
        else: self.push(' '.join(args) + '\r\n')

        def handle_connect( self):
        self.write(('NI CK', self.nick))
        self.write(('US ER', self.uid, '+iw', self.nick), self.name)

        def collect_incomin g_data(self, data):
        self.buffer += data

        def found_terminato r(self):
        line = self.buffer
        self.buffer = ''
        if line.startswith (':'):
        origin, line = line[1:].split(' ', 1)
        origin = Origin(origin)
        else: origin = None

        if ' :' in line:
        args, text = line.split(' :', 1)
        else: args, text = line, ''
        args = args.split()

        if origin: origin.replyTo( self.nick, args)
        self.dispatch(a rgs, text, origin)

        def todo(self, args, *text):
        command = ' '.join(args)
        if text:
        command = '%s : %s' % (command, ' '.join(text))
        command = re.sub(r"\n", "", command)
        command = re.sub(r"\r", "", command)
        self.push(comma nd + CRLF)

        def run(self, host, port):
        self.create_soc ket(socket.AF_I NET, socket.SOCK_STR EAM)
        time.sleep(0.5)
        self.connect((h ost, port))
        time.sleep(0.5)
        asyncore.loop()

        test = Bot.run
        test( 'irc.some.serve r.org', 6667 ) # should start the bot off
        [/CODE]

        Now that I've pasted nearly all of somebody else's work I guess I should ask a few questions hey!

        1) asyncore.loop() - what exactly is that doing? Is that like my initial while 1: loop in my very first post? If so, where is the data read to? self.buffer?

        2) does assigning something to self. make it globally available or is it just accessible within that class?

        3) can someone explain what 'dispatch' is doing exactly?

        Originally posted by bartonc
        I hope you like our Python forum,
        Barton
        If everyone is as helpful and friendly as yourself I'll be sticking around a lot more!

        All the best,

        Ian

        Comment

        • brks
          New Member
          • Jul 2007
          • 6

          #5
          OK - I've finally done it.

          After many cups of coffee and a very late night, the problem has been solved and I have asynchronous reading once more. Awesome.

          Thanks for your help - I'm sure I'll be sticking around :o)

          All the best,

          Ian

          Comment

          • bartonc
            Recognized Expert Expert
            • Sep 2006
            • 6478

            #6
            Originally posted by brks
            OK - I've finally done it.

            After many cups of coffee and a very late night, the problem has been solved and I have asynchronous reading once more. Awesome.

            Thanks for your help - I'm sure I'll be sticking around :o)

            All the best,

            Ian
            Any chance that we can get a peek at you work for the benefit of the budding Pythoneers who visit in the future?

            Comment

            • brks
              New Member
              • Jul 2007
              • 6

              #7
              Sure thing!

              [CODE=python]#!/usr/bin/env python

              import os, sys
              import socket, asyncore, asynchat
              import irc_config
              import irc_parse
              import irc_modules

              class Bot( asynchat.async_ chat ):
              def __init__( self, config ):
              asynchat.async_ chat.__init__( self )
              self.buffer = ''
              self.set_termin ator( '\r\n' )
              self.nick = config.n
              self.ident = config.i
              self.realname = config.r
              self.debug = config.d
              self.parser = irc_parse.parse _irc_input( config.s, self.write )

              # load all our modules
              irc_modules.sta rtup_modules( self.parser )

              def write( self, text ):
              if self.debug == 1:
              print '<< DEBUG >> WRITING "%s" TO SOCKET!' % text
              self.push( text + '\r\n' )


              def handle_connect( self ):
              self.write( 'NICK %s' % self.nick )
              self.write( 'USER %s iw 0 :%s' % ( self.ident, self.realname ) )

              def collect_incomin g_data( self, data ):
              self.buffer += data

              def found_terminato r( self ):
              line = self.buffer
              self.buffer = ''
              if self.debug == 1:
              print '<< DEBUG >> %s' % line
              self.parser.par se_text( line )

              def run( self, host, port ):
              self.create_soc ket( socket.AF_INET, socket.SOCK_STR EAM )
              self.connect( ( host, port ) )
              asyncore.loop()

              # attemptfork is thanks to phenny irc bot ( http://inamidst.com/phenny/ )
              def attemptfork():
              try:
              pid = os.fork()
              if pid > 0:
              sys.exit( 0 )
              except OSError, e:
              raise OSError( 'Could not daemonize process: %d ( %s )' % ( e.errno, e.strerror ) )
              os.setsid()
              os.umask( 0 )
              try:
              pid = os.fork()
              if pid > 0:
              sys.exit( 0 )
              except OSError, e:
              raise OSError( 'Could not daemonize process: %d ( %s )' % ( e.errno, e.strerror ) )

              # load our config
              conf = irc_config.conf ig

              if conf.d == 0 and conf.b == 1 and hasattr( os, 'fork' ):
              attemptfork()

              # initialize
              mypybot = Bot( conf )

              # and run
              mypybot.run( conf.s, conf.p )[/CODE]

              there's a lot left to the imagination, but you see the general jist of what's happening as far as asynchronous data transfer goes!

              All the best guys,

              Ian

              Comment

              • bartonc
                Recognized Expert Expert
                • Sep 2006
                • 6478

                #8
                Thanks, Ian. Hope to see ya 'round...
                Barton

                Comment

                • bvdet
                  Recognized Expert Specialist
                  • Oct 2006
                  • 2851

                  #9
                  Ian,

                  I appreciate your sharing with us. This is new to me - maybe I can learn something!

                  BV

                  Comment

                  • brks
                    New Member
                    • Jul 2007
                    • 6

                    #10
                    no problems guys - glad it was so useful

                    i'll keep you all updated on the architecture i'm releasing as a barse-bones module driven irc bot

                    if you're a die-hard irc'er like myself then you'll love it!

                    cheerio

                    Ian

                    Comment

                    • bartonc
                      Recognized Expert Expert
                      • Sep 2006
                      • 6478

                      #11
                      Originally posted by brks
                      no problems guys - glad it was so useful

                      i'll keep you all updated on the architecture i'm releasing as a barse-bones module driven irc bot

                      if you're a die-hard irc'er like myself then you'll love it!

                      cheerio

                      Ian
                      (OK) You meant to say "barse-bones", right? ROFL

                      Comment

                      • brks
                        New Member
                        • Jul 2007
                        • 6

                        #12
                        It was meant to be 'bare-bones' admittedly, but i thought no-one would notice ;)

                        Comment

                        • William Manley
                          New Member
                          • Mar 2007
                          • 56

                          #13
                          This looks very interesting. I use irclib.py for my ircbot, but I think I will take a look at this, when you release it, as well.
                          Last edited by William Manley; Jul 5 '07, 11:21 AM. Reason: clarifying my statement

                          Comment

                          Working...