title: Python IRC bot /mode, /ban, /part, /join
body: <p>Sooo I have an IRC bot based on Skybot (IRC bot). I've looked into its documentation but it's not stated how to do it. I'd like to make it join, quit, part, set mode and other irc commands, but typing them from chan. Simple example:</p>
  
  <p>.part #hello ~ Parts the chan
  .mode #hello +b Tom - Bans Tom</p>
  
  <p>That's what it has in its documentation about events </p>
  
  <blockquote>
    <p><code>@hook.event(irc_command)</code></p>
    
    <p>Event hooks are called whenever a specific IRC command is issued. For
    example, if you provide "*" as parameter, it will trigger on every
    line. If you provide "PRIVMSG", it will only trigger on actual lines
    of chat (not nick-changes).</p>
    
    <p>The first argument in these cases will be a two-element list of the
    form ["#channel", "text"].</p>
  </blockquote>
  
  <p>That's how a simple command works.</p>
  
  <pre><code>from util import hook, http
  
  
  @hook.command
  def calc(inp,say=None):
      'Does calculation'
  
      h = http.get_html('http://www.google.com/search', q=inp)
  
      m = h.xpath('//h2[@class="r"]/text()')
  
      if not m:
          say("I can't calculate " + inp + ".")
  
      res = ' '.join(m[0].split())
  
      say(res + ".")
  </code></pre>
  
  <p><strong>hook.py</strong></p>
  
  <pre><code>    import inspect
  import re
  
  
  def _hook_add(func, add, name=''):
      if not hasattr(func, '_hook'):
          func._hook = []
      func._hook.append(add)
  
      if not hasattr(func, '_filename'):
          func._filename = func.func_code.co_filename
  
      if not hasattr(func, '_args'):
          argspec = inspect.getargspec(func)
          if name:
              n_args = len(argspec.args)
              if argspec.defaults:
                  n_args -= len(argspec.defaults)
              if argspec.keywords:
                  n_args -= 1
              if argspec.varargs:
                  n_args -= 1
              if n_args != 1:
                  err = '%ss must take 1 non-keyword argument (%s)' % (name,
                              func.__name__)
                  raise ValueError(err)
  
          args = []
          if argspec.defaults:
              end = bool(argspec.keywords) + bool(argspec.varargs)
              args.extend(argspec.args[-len(argspec.defaults):
                          end if end else None])
          if argspec.keywords:
              args.append(0)  # means kwargs present
          func._args = args
  
      if not hasattr(func, '_thread'):  # does function run in its own thread?
          func._thread = False
  
  
  def sieve(func):
      if func.func_code.co_argcount != 5:
          raise ValueError(
                  'sieves must take 5 arguments: (bot, input, func, type, args)')
      _hook_add(func, ['sieve', (func,)])
      return func
  
  
  def command(arg=None, **kwargs):
      args = {}
  
      def command_wrapper(func):
          args.setdefault('name', func.func_name)
          _hook_add(func, ['command', (func, args)], 'command')
          return func
  
      if kwargs or not inspect.isfunction(arg):
          if arg is not None:
              args['name'] = arg
          args.update(kwargs)
          return command_wrapper
      else:
          return command_wrapper(arg)
  
  
  def event(arg=None, **kwargs):
      args = kwargs
  
      def event_wrapper(func):
          args['name'] = func.func_name
          args.setdefault('events', ['*'])
          _hook_add(func, ['event', (func, args)], 'event')
          return func
  
      if inspect.isfunction(arg):
          return event_wrapper(arg, kwargs)
      else:
          if arg is not None:
              args['events'] = arg.split()
          return event_wrapper
  
  
  def singlethread(func):
      func._thread = True
      return func
  
  
  def regex(regex, flags=0, **kwargs):
      args = kwargs
  
      def regex_wrapper(func):
          args['name'] = func.func_name
          args['regex'] = regex
          args['re'] = re.compile(regex, flags)
          _hook_add(func, ['regex', (func, args)], 'regex')
          return func
  
      if inspect.isfunction(regex):
          raise ValueError("regex decorators require a regex to match against")
      else:
          return regex_wrapper
  </code></pre>
  
  <p>and <strong>misc.py</strong>, there's one hook.event command there:</p>
  
  <pre><code>#autorejoin channels
  @hook.event('KICK')
  def rejoin(paraml, conn=None):
      if paraml[1] == conn.nick:
          if paraml[0].lower() in conn.channels:
              conn.join(paraml[0])
  
  
  #join channels when invited
  @hook.event('INVITE')
  def invite(paraml, conn=None):
      conn.join(paraml[-1])
  
  
  
  @hook.event('004')
  def onjoin(paraml, conn=None):
      # identify to services
      nickserv_password = conn.conf.get('nickserv_password', '')
      nickserv_name = conn.conf.get('nickserv_name', 'nickserv')
      nickserv_command = conn.conf.get('nickserv_command', 'IDENTIFY %s')
      if nickserv_password:
          conn.msg(nickserv_name, nickserv_command % nickserv_password)
          time.sleep(1)
  
      # set mode on self
      mode = conn.conf.get('mode')
      if mode:
          conn.cmd('MODE', [conn.nick, mode])
  
      # join channels
      for channel in conn.channels:
          conn.join(channel)
          time.sleep(1)  # don't flood JOINs
  
      # set user-agent
      ident, rev = get_version()
  </code></pre>
  
  <p><strong>main.py</strong>, where conn things are defined.</p>
  
  <pre><code>class Input(dict):
      def __init__(self, conn, raw, prefix, command, params,
                      nick, user, host, paraml, msg):
  
          chan = paraml[0].lower()
          if chan == conn.nick.lower():  # is a PM
              chan = nick
  
          def say(msg):
              conn.msg(chan, msg)
  
          def reply(msg):
              if chan == nick:  # PMs don't need prefixes
                  conn.msg(chan, msg)
              else:
                  conn.msg(chan, nick + ': ' + msg)
  
          def pm(msg):
              conn.msg(nick, msg)
  
          def set_nick(nick):
              conn.set_nick(nick)
  
          def me(msg):
              conn.msg(chan, "\x01%s %s\x01" % ("ACTION", msg))
  
          def notice(msg):
              conn.cmd('NOTICE', [nick, msg])
  
          dict.__init__(self, conn=conn, raw=raw, prefix=prefix, command=command,
                      params=params, nick=nick, user=user, host=host,
                      paraml=paraml, msg=msg, server=conn.server, chan=chan,
                      notice=notice, say=say, reply=reply, pm=pm, bot=bot,
                      me=me, set_nick=set_nick, lastparam=paraml[-1])
  
      # make dict keys accessible as attributes
      def __getattr__(self, key):
          return self[key]
  
      def __setattr__(self, key, value):
          self[key] = value
  </code></pre>
  
  <p>I don't really get how can I do it. Thanks for your help!</p>