<commit_before>import inspect
import sys
import socket
import string
import re
import os

import threads

class Bot(object):
  def __init__(self, host, **kwargs):
    '''
    Initializes a new pyrc.Bot.
    '''
    nick = "PyrcBot" if self.__class__ == Bot else self.__class__.__name__
    password = os.environ.get('PASSWORD', None)

    self.config = dict(kwargs)
    self.config.setdefault('host', host)
    self.config.setdefault('port', 6667)
    self.config.setdefault('nick', nick)
    self.config.setdefault('names', [self.config['nick']])
    self.config.setdefault('ident', nick.lower())
    self.config.setdefault('realname', "A Pyrc Bot")
    self.config.setdefault('channels', [])
    self.config.setdefault('password', password)
    self.config.setdefault('break_on_match', True)
    self.config.setdefault('verbose', True)
    self.config.setdefault('prefix', '%')

    self._inbuffer = ""
    self._commands = []
    self._threads = []
    self.socket = None
    self.initialized = False
    self.listeners = {}

    self.add_listeners()
    self.addhooks()

  def message(self, recipient, s):
    "High level interface to sending an IRC message."
    self.cmd("PRIVMSG %s :%s" % (recipient, s))

  def connect(self):
    '''
    Connects to the IRC server with the options defined in `config`
    '''
    self._connect()

    try:
      self.listen()
    except (KeyboardInterrupt, SystemExit):
      pass
    finally:
      self.close()

  def listen(self):
    """
    Constantly listens to the input from the server. Since the messages come
    in pieces, we wait until we receive 1 or more full lines to start parsing.

    A new line is defined as ending in \r\n in the RFC, but some servers
    separate by \n. This script takes care of both.
    """
    while True:
      self._inbuffer = self._inbuffer + self.socket.recv(1024)
      # Some IRC servers disregard the RFC and split lines by \n rather than \r\n.

      temp = self._inbuffer.split("\n")
      self._inbuffer = temp.pop()

      for line in temp:
        # Strip \r from \r\n for RFC-compliant IRC servers.
        line = line.rstrip('\r')
        if self.config['verbose']: print line
        self.run_listeners(line)

  def run_listeners(self, line):
    """
    Each listener's associated regular expression is matched against raw IRC
    input. If there is a match, the listener's associated function is called
    with all the regular expression's matched subgroups.
    """
    for regex, callbacks in self.listeners.iteritems():
      match = re.match(regex, line)

      if not match:
        continue

      for callback in callbacks:
        callback(*match.groups())

  def addhooks(self):
    for func in self.__class__.__dict__.values():
      if callable(func) and hasattr(func, '_type'):
        if func._type == 'COMMAND':
          self._commands.append(func)
        elif func._type == "REPEAT":
          thread = threads.JobThread(func, self)
          self._threads.append(thread)
        else:
          raise "This is not a type I've ever heard of."

  def receivemessage(self, channel, nick, message):
    self.parsecommand(channel, message)

  def parsecommand(self, channel, message):
    command = self.bot_called(message)
    if not command:
      return

    for command_func in self._commands:
      match = command_func._matcher.search(command)
      if match:
        group_dict = match.groupdict()
        groups = match.groups()
        if group_dict and (len(groups) > len(group_dict)):
          # match.groups() also returns named parameters
          raise "You cannot use both named and unnamed parameters"
        elif group_dict:
          command_func(self, channel, **group_dict)
        else:
          command_func(self, channel, *groups)
        
        if self.config['break_on_match']: break

  def bot_called(self, message):
    """
    Checks if the bot was called by a user.
    This includes nick highlighting and adding a set 
    prefix infront of the command.<commit_msg>Documentation change<commit_after>import inspect
import sys
import socket
import string
import re
import os

import threads

class Bot(object):
  def __init__(self, host, **kwargs):
    '''
    Initializes a new pyrc.Bot.
    '''
    nick = "PyrcBot" if self.__class__ == Bot else self.__class__.__name__
    password = os.environ.get('PASSWORD', None)

    self.config = dict(kwargs)
    self.config.setdefault('host', host)
    self.config.setdefault('port', 6667)
    self.config.setdefault('nick', nick)
    self.config.setdefault('names', [self.config['nick']])
    self.config.setdefault('ident', nick.lower())
    self.config.setdefault('realname', "A Pyrc Bot")
    self.config.setdefault('channels', [])
    self.config.setdefault('password', password)
    self.config.setdefault('break_on_match', True)
    self.config.setdefault('verbose', True)
    self.config.setdefault('prefix', '%')

    self._inbuffer = ""
    self._commands = []
    self._threads = []
    self.socket = None
    self.initialized = False
    self.listeners = {}

    self.add_listeners()
    self.addhooks()

  def message(self, recipient, s):
    "High level interface to sending an IRC message."
    self.cmd("PRIVMSG %s :%s" % (recipient, s))

  def connect(self):
    '''
    Connects to the IRC server with the options defined in `config`
    '''
    self._connect()

    try:
      self.listen()
    except (KeyboardInterrupt, SystemExit):
      pass
    finally:
      self.close()

  def listen(self):
    """
    Constantly listens to the input from the server. Since the messages come
    in pieces, we wait until we receive 1 or more full lines to start parsing.

    A new line is defined as ending in \r\n in the RFC, but some servers
    separate by \n. This script takes care of both.
    """
    while True:
      self._inbuffer = self._inbuffer + self.socket.recv(1024)
      # Some IRC servers disregard the RFC and split lines by \n rather than \r\n.

      temp = self._inbuffer.split("\n")
      self._inbuffer = temp.pop()

      for line in temp:
        # Strip \r from \r\n for RFC-compliant IRC servers.
        line = line.rstrip('\r')
        if self.config['verbose']: print line
        self.run_listeners(line)

  def run_listeners(self, line):
    """
    Each listener's associated regular expression is matched against raw IRC
    input. If there is a match, the listener's associated function is called
    with all the regular expression's matched subgroups.
    """
    for regex, callbacks in self.listeners.iteritems():
      match = re.match(regex, line)

      if not match:
        continue

      for callback in callbacks:
        callback(*match.groups())

  def addhooks(self):
    for func in self.__class__.__dict__.values():
      if callable(func) and hasattr(func, '_type'):
        if func._type == 'COMMAND':
          self._commands.append(func)
        elif func._type == "REPEAT":
          thread = threads.JobThread(func, self)
          self._threads.append(thread)
        else:
          raise "This is not a type I've ever heard of."

  def receivemessage(self, channel, nick, message):
    self.parsecommand(channel, message)

  def parsecommand(self, channel, message):
    command = self.bot_called(message)
    if not command:
      return

    for command_func in self._commands:
      match = command_func._matcher.search(command)
      if match:
        group_dict = match.groupdict()
        groups = match.groups()
        if group_dict and (len(groups) > len(group_dict)):
          # match.groups() also returns named parameters
          raise "You cannot use both named and unnamed parameters"
        elif group_dict:
          command_func(self, channel, **group_dict)
        else:
          command_func(self, channel, *groups)
        
        if self.config['break_on_match']: break

  def bot_called(self, message):
    """
    Checks if the bot was called by a user.
    This includes nick highlighting and prepending a set 
    prefix to the command.
{'fraction_non_alphanumeric': 0.10827629122588675, 'fraction_numerical': 0.00224019912881145, 'mean_word_length': 2.7359367735936773, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2072314', 'n_tokens_mistral': 2379, 'n_tokens_neox': 2304, 'n_words': 739}