All pastes #125691 Raw Edit

Anonymous

public python v1 · immutable
·published 2006-08-10 20:52 UTC
rendered paste body
import socketimport threadingimport reimport timeimport messagesDEFAULT_PORT    = 6667DEFAULT_BUFSIZE = 512"""Client provides the outer and friendlier layer for connectingto an IRC server and interacting with it. The client willhandle all messages received and invoke message handlers."""class Client:  """  Initialize Client  """  def __init__(self, host, **kwargs):    self.host     = host    self.port     = kwargs.get('port'    , DEFAULT_PORT)    self.bufsize  = kwargs.get('bufsize' , DEFAULT_BUFSIZE)    self.messages = kwargs.get('messages', messages.DEFAULT)    self.sock     = Socket(host, self.port)    self.lock     = threading.Lock()    self.handlers = []    # Append default handlers.    # self.handlers.append(...)  """  Parse a given line and return its corresponding message object.  """  def parse(self, line):    # Take the origin out of the line, for easier parsing.    origin, line = re.match('^(?::(\S+) )?(.+?)$', line).groups()        # Attempt to match an IRC message.    match = re.match('^(\S+)(?: (.*?))?(?: :(.+?))?$', line)        # Is it a match? If not, create the UnknownMessage.    if match:      command, args, data = match.groups()            # Empty args list.      if not args :  args = []      else        :  args = args.split(' ')            # Special treatment for NOTICE AUTH.      if command == 'NOTICE' and args and args[0] == 'AUTH':        args.pop(0)        command = 'NOTICE AUTH'      # Check for a NOTICE AUTH, a numeric, or any other      # message and attempt to create their message objects.      if   command == 'NOTICE AUTH' :  key = 'noticeauth'      elif command.isdigit()        :  key = 'numeric'      else                          :  key = command.lower()    else:      # Defaults for an unknown message.      args = []      data = None      key  = 'unknown'    # Now create the message object and return it.    return self.messages[key](self, line, command, args, data)  """  Call this to put the client into its main loop. During this  time the client will receive data from the server, parse it,  and invoke handlers.  """  def main(self):    while 1:      line    = self.sock.gets(self.bufsize) # - Read data      message = self.parse(line.strip())     # - Parse into message"""The Socket class is a light wrapper around standard sockets thatmakes it easy to receive *lines* from a socket, rather thanuncomfortably having to deal with bytes."""class Socket:  """  Initialize Socket  """  def __init__(self, host, port):    self.buffer = []    self.sock   = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.SOL_TCP)    self.sock.connect((host, port))  """  Write to the socket  """  def send(data):    self.sock.send(data)  """  Read a line from the socket  """  def gets(self, bufsize = DEFAULT_BUFSIZE):    # Simple switch indicating whether a buffer needs    # concatenating (continuing off last line) or    # appending (adding a whole new line)    buffer_is_incomplete = False    # Loop until there is even a single line to return.    while 1:      # Test whether the buffer is empty or not.      if self.buffer:        line = self.buffer[0]        # Even if the buffer isn't empty, we still need to        # make sure there's a *complete* line to return.        if line.endswith('\n'):          self.buffer.pop(0)          return line        else:          buffer_is_incomplete = True      # Attempt to read from the socket... could be nothing.      data = self.sock.recv(bufsize)      if data:        lines = data.splitlines(True)        # If the buffer isn't complete, that means we        # need to concatenate, not append.        if buffer_is_incomplete:          self.buffer[0] += lines[0]          lines.pop(0)        # Here we go, appending new lines!        for line in lines:          self.buffer.append(line)      else:        # Let's sleep a little if there was nothing to read.        time.sleep(0.1)    """A blank object used for the sake of being able to setattributes on it."""class OpenStruct: pass