]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - data/rbot/plugins/bans.rb
Plugin header boilerplating.
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / bans.rb
index 7f4b63eb15a29c6be2128e445263b6d52a9c5a66..17281d4cc0b83162924303ee61c3a9c516ee36d6 100644 (file)
-# Plugin for the Ruby IRC bot (http://linuxbrit.co.uk/rbot/)
-#
-# Managing kick and bans, automatically removing bans after timeouts, quiet bans, and kickban/quietban based on regexp
-#
-# Commands are little Ruby programs that run in the context of the command plugin. You
-# can create them directly in an IRC channel, and invoke them just like normal rbot plugins.
-#
-# (c) 2006 Marco Gulino <marco@kmobiletools.org>
-# Licensed under GPL V2.
-
-
-class BansPlugin < Plugin
-  def initialize
-    super
-     if @registry.has_key?(:bans)
-       @bansregexps = @registry[:bans]
-     else
-       @bansregexps = Hash.new
-     end
-    end
-
-
-    def save
-#      @bot.action("#rck.train", @bansregexps.inspect)
-      @registry[:bans] = @bansregexps
-    end
-
-
-
-
-  def help(plugin, topic="")
-    return "Channel administration plugin. bans ban nick [channel] [timer]: bans a nick from the channel for a specified time; bans unban nick [channel]: removes the ban on <nick>; bans quiet nick [channel] [timer] and bans unquiet nick [channel]: same as ban and unban, but uses quiet ban instead. Timer is specified as 6s, 10m, 2h. If channel is not specified will use current channel.\nbans listregexps|addregexp type timeout regexp|delregexp: regexp banning management. Type can be quietban or kickban"
-  end
-
-
-  def cmd_setmode(m, nick, channel, smode, time, umode )
-    channel=channel != '####currentchannel' ? channel : m.target
-    timercnt=/^(\d+)([smh])$/.match(time)[1]
-    timeru=/^(\d+)([smh])$/.match(time)[2]
-    timer = timercnt.to_i if timeru == "s"
-    timer = timercnt.to_i*60 if timeru == "m"
-    timer = timercnt.to_i*3600 if timeru == "h"
-    if timer > 0 then @bot.timer.add_once(timer, m ) {|m|
-      @bot.sendq("MODE #{channel} #{umode} #{nick}")
-      #                m.reply("Undo mode")
-    } end
-
-    @bot.sendq("MODE #{channel} #{smode} #{nick}")
-    #  m.reply "ban cmd nick=#{nick} channel=#{channel} timer=#{timercnt} #{timeru} #{timer}"
-  end
-  def cmd_dokick(m, nick, channel, message)
-      channel=channel != '####currentchannel' ? channel : m.target
-      @bot.sendq("KICK #{channel} #{nick} :#{message}")
-  end
-
-
-  def cmd_kick(m,params)
-    cmd_dokick(m,params[:nick], params[:channel], params[:message])
-  end
-  def cmd_ban(m, params)
-    cmd_setmode(m, params[:nick], params[:channel], "+b", params[:timer], "-b")
-  end
-  def cmd_kickban(m,params)
-      cmd_setmode(m, params[:nick], params[:channel], "+b", params[:timer], "-b")
-      cmd_dokick(m,params[:nick], params[:channel], params[:message])
-  end
-
-
-  def cmd_quietban(m, params)
-    cmd_setmode(m, params[:nick], params[:channel], "+q", params[:timer], "-q")
-  end
-  def cmd_unban(m, params)
-    cmd_setmode(m, params[:nick], params[:channel], "-b", "0s", "")
-  end
-  def cmd_unquiet(m, params)
-    cmd_setmode(m, params[:nick], params[:channel], "-q", "0s", "")
-  end
-
-  def listen(m)
-    if @bansregexps.length <= 0 then return end
-    @bansregexps.each_key do |key|
-      match=@bansregexps[key][2]
-      if m.message =~ /^.*#{match}.*$/i then
-        case @bansregexps[key][0]
-       when "quietban"
-               cmd_setmode(m, m.sourcenick, m.channel, "+q", @bansregexps[key][1], "-q")
-               return
-       when "kickban"
-                cmd_setmode(m, m.sourcenick, m.channel, "+b", @bansregexps[key][1], "-b")
-               cmd_dokick(m, m.sourcenick, m.channel, "Autokick")
-               return
-       end
-      end
-      next
-    end
-  end
-
-  def cmd_addregexp(m, params)
-    toadd=Array[ params[:type], params[:timeout], "#{params[:regexp]}" ]
-    regsize=@bansregexps.length+1
-#    m.reply("Current registry size: #{regsize}")
-
-    @bansregexps[regsize]=toadd
-#    @bansregexps.store(toadd)
-    regsize=@bansregexps.length
-#    m.reply("New registry size: #{regsize}")
-    m.reply("Done.")
-  end
-  def cmd_listregexp(m, params)
-    if @bansregexps.length == 0
-      m.reply("No regexps stored."); return
-    end
-    @bansregexps.each_key do |key|
-           m.reply("Key: #{key}, type: #{@bansregexps[key][0]}, timeout: #{@bansregexps[key][1]}, pattern: #{@bansregexps[key][2]}")
-           sleep 1
-           next
-    end
-  end
-  def cmd_delregexp(m, params)
-    index=params[:index]
-    @bansregexps.each_key do |key|
-           if ( "#{key}" == "#{index}" ) then
-                   @bansregexps.delete(key)
-                   m.reply("Done.")
-                   return
-           end
-           next
-end
-m.reply("Key #{index} not found")
-#    unless @bansregexps.has_key?(index)
-#      m.reply("Regexp \"#{index}\" doesn't exist"); return
-#    end
-#    m.reply("Done.")
-  end
-end
-plugin = BansPlugin.new
-plugin.register("bans")
-
-
-plugin.map 'bans delregexp :index', :action => 'cmd_delregexp', :auth => 'bans', :requirements => { :index => /^\d+$/ }
-plugin.map 'bans addregexp :type :timeout *regexp', :action => 'cmd_addregexp', :auth => 'bans', :requirements => {:timeout => /^\d+[smh]$/, :type => /(quietban)|(kickban)/ }, :defaults => { :timeout => "0s" }
-plugin.map 'bans listregexps', :action => 'cmd_listregexp', :auth => 'bans'
-plugin.map 'bans ban :nick :channel :timer', :action => 'cmd_ban', :auth => 'bans', :requirements => {:timer => /^\d+[smh]$/, :channel => /^#+[^\s]+$/}, :defaults => {:channel => '####currentchannel', :timer => '0s'}
-plugin.map 'bans quiet :nick :channel :timer', :action => 'cmd_quietban', :auth => 'bans', :requirements => {:timer => /^\d+[smh]$/, :channel => /^#+[^\s]+$/}, :defaults => {:channel => '####currentchannel', :timer => '0s'}
-
-plugin.map 'bans kick :nick :channel *message', :action => 'cmd_kick', :auth => 'bans', :requirements => {:channel => /^#+[^\s]+$/}, :defaults => {:channel => '####currentchannel', :message => 'Au revoir.'}
-plugin.map 'bans kickban :nick :channel :timer *message', :action => 'cmd_kickban', :auth => 'bans', :requirements => {:channel => /^#+[^\s]+$/, :timer => /^\d+[smh]$/ }, :defaults => {:channel => '####currentchannel', :message => 'Au revoir.', :timer => '0s'}
-
-
-plugin.map 'bans unban :nick :channel', :action => 'cmd_unban', :auth => 'bans', :requirements => { :channel => /^#+[^\s]+$/}, :defaults => {:channel =>       '####currentchannel'}
-plugin.map 'bans unquiet :nick :channel', :action => 'cmd_unquiet', :auth => 'bans', :requirements => { :channel => /^#+[^\s]+$/}, :defaults => {:channel =>   '####currentchannel'}
-
-#plugin.map 'admin kick :nick :channel *message', :action => 'cmd_kick', :auth => 'admin'
-#plugin.map 'admin kickban :nick :channel *message', :action => 'cmd_kickban' :auth => 'admin'
-#plugin.register("quietban")
-#plugin.register("kickban")
+#-- vim:sw=2:et\r
+#++\r
+#\r
+# :title: Bans Plugin v3 for rbot 0.9.11 and later\r
+#\r
+# Author:: Marco Gulino <marco@kmobiletools.org>\r
+# Author:: kamu <mr.kamu@gmail.com>\r
+# Author:: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>\r
+#\r
+# Copyright:: (C) 2006 Marco Gulino\r
+# Copyright:: (C) 2007 kamu, Giuseppe Bilotta\r
+#\r
+# License:: GPL V2.\r
+#\r
+# Managing kick and bans, automatically removing bans after timeouts, quiet\r
+# bans, and kickban/quietban based on regexp\r
+#\r
+# v1 -> v2 (kamu's version, never released)\r
+#   * reworked\r
+#   * autoactions triggered on join\r
+#   * action on join or badword can be anything: kick, ban, kickban, quiet\r
+#\r
+# v2 -> v3 (GB)\r
+#   * remove the 'bans' prefix from most of the commands\r
+#   * (un)quiet has been renamed to (un)silence because 'quiet' was used to\r
+#     tell the bot to keep quiet\r
+#   * both (un)quiet and (un)silence are accepted as actions\r
+#   * use the more descriptive 'onjoin' term for autoactions\r
+#   * convert v1's (0.9.10) :bans and :bansmasks to BadWordActions and\r
+#     WhitelistEntries\r
+#   * enhanced list manipulation facilities\r
+#   * fixed regexp usage in requirements for plugin map\r
+#   * add proper auth management\r
+\r
+OnJoinAction = Struct.new("OnJoinAction", :host, :action, :channel, :reason)\r
+BadWordAction = Struct.new("BadWordAction", :regexp, :action, :channel, :timer, :reason)\r
+WhitelistEntry = Struct.new("WhitelistEntry", :host, :channel)\r
+\r
+\r
+class BansPlugin < Plugin\r
+\r
+  IdxRe = /^\d+$/\r
+  TimerRe = /^\d+[smhd]$/\r
+  ChannelRe = /^#+[^\s]+$/\r
+  ChannelAllRe = /^(?:all|#+[^\s]+)$/\r
+  ActionRe = /(?:ban|kick|kickban|silence|quiet)/\r
+\r
+  def name\r
+    "bans"\r
+  end\r
+\r
+  def make_badword_rx(txt)\r
+    return /\b(?:#{txt})\b/i\r
+  end\r
+\r
+  def initialize\r
+    super\r
+\r
+    # Convert old BadWordActions, which were simpler and labelled :bans\r
+    if @registry.has_key? :bans\r
+      badwords = Array.new\r
+      bans = @registry[:bans]\r
+      @registry[:bans].each { |ar|\r
+        case ar[0]\r
+        when "quietban"\r
+          action = :silence\r
+        when "kickban"\r
+          action = :kickban\r
+        else\r
+          # Shouldn't happen\r
+          warn "Unknown action in old data #{ar.inspect} -- entry ignored"\r
+          next\r
+        end\r
+        bans.delete(ar)\r
+        chan = ar[1].downcase\r
+        regexp = make_badword_rx(ar[2])\r
+        badwords << BadWordAction.new(regexp, action, chan, "0s", "")\r
+      }\r
+      @registry[:badwords] = badwords\r
+      if bans.length > 0\r
+        # Store the ones we couldn't convert\r
+        @registry[:bans] = bans\r
+      else\r
+        @registry.delete(:bans)\r
+      end\r
+    else\r
+      @registry[:badwords] = Array.new unless @registry.has_key? :badwords\r
+    end\r
+\r
+    # Convert old WhitelistEntries, which were simpler and labelled :bansmasks\r
+    if @registry.has_key? :bans\r
+      wl = Array.new\r
+      @registry[:bansmasks].each { |mask|\r
+        badwords << WhitelistEntry.new(mask, "all")\r
+      }\r
+      @registry[:whitelist] = wl\r
+      @registry.delete(:bansmasks)\r
+    else\r
+      @registry[:whitelist] = Array.new unless @registry.has_key? :whitelist\r
+    end\r
+\r
+    @registry[:onjoin] = Array.new unless @registry.has_key? :onjoin\r
+  end\r
+\r
+  def help(plugin, topic="")\r
+    case plugin\r
+    when "ban"\r
+      return "ban <nick/hostmask> [Xs/m/h/d] [#channel]: ban a user from the given channel for the given amount of time. default is forever, on the current channel"\r
+    when "unban"\r
+      return "unban <nick/hostmask> [#channel]: unban a user from the given channel. defaults to the current channel"\r
+    when "kick"\r
+      return "kick <nick> [#channel] [reason ...]: kick a user from the given channel with the given reason. defaults to the current channel, no reason"\r
+    when "kickban"\r
+      return "kickban <nick> [Xs/m/h/d] [#channel] [reason ...]: kicks and bans a user from the given channel for the given amount of time, with the given reason. default is forever, on the current channel, with no reason"\r
+    when "silence"\r
+      return "silence <nick/hostmask> [Xs/m/h/d] [#channel]: silence a user on the given channel for the given time. default is forever, on the current channel. not all servers support silencing users"\r
+    when "unsilence"\r
+      return "unsilence <nick/hostmask> [#channel]: allow the given user to talk on the given channel. defaults to the current channel"\r
+    when "bans"\r
+      case topic\r
+      when "add"\r
+        return "bans add <onjoin|badword|whitelist>: add an automatic action for people that join or say some bad word, or a whitelist entry. further help available"\r
+      when "add onjoin"\r
+        return "bans add onjoin <hostmask> [action] [#channel] [reason ...]: will add an autoaction for any one who joins with hostmask. default action is silence, default channel is all"\r
+      when "add badword"\r
+        return "bans add badword <regexp> [action] [Xs/m/h/d] [#channel|all] [reason ...]: adds a badword regexp, if a user sends a message that matches regexp, the action will be invoked. default action is silence, default channel is all"\r
+      when "add whitelist"\r
+        return "bans add whitelist <hostmask> [#channel|all]: add the given hostmask to the whitelist. no autoaction will be triggered by users on the whitelist"\r
+      when "rm"\r
+        return "bans rm <onjoin|badword|whitelist> <hostmask/regexp> [#channel], or bans rm <onjoin|badword|whitelist> index <num>: removes the specified onjoin or badword rule or whitelist entry."\r
+      when "list"\r
+        return"bans list <onjoin|badword|whitelist>: lists all onjoin or badwords or whitelist entries"\r
+      end\r
+    end\r
+    return "bans <command>: allows a user of the bot to do a range of bans and unbans. commands are: [un]ban, kick[ban], [un]silence, add, rm and list"\r
+  end\r
+\r
+  def listen(m)\r
+    return unless m.respond_to?(:public?) and m.public?\r
+    @registry[:whitelist].each { |white|\r
+      next unless ['all', m.target.downcase].include?(white.channel)\r
+      return if m.source.matches?(white.host)\r
+    }\r
+\r
+    @registry[:badwords].each { |badword|\r
+      next unless ['all', m.target.downcase].include?(badword.channel)\r
+      next unless badword.regexp.match(m.message)\r
+\r
+      do_cmd(badword.action.to_sym, m.source.nick, m.target, badword.timer, badword.reason)\r
+      m.reply "bad word detected! #{badword.action} for #{badword.timer} because: #{badword.reason}"\r
+      return\r
+    }\r
+  end\r
+\r
+  def join(m)\r
+    @registry[:whitelist].each { |white|\r
+      next unless ['all', m.target.downcase].include?(white.channel)\r
+      return if m.source.matches?(white.host)\r
+    }\r
+\r
+    @registry[:onjoin].each { |auto|\r
+      next unless ['all', m.target.downcase].include?(auto.channel)\r
+      next unless m.source.matches? auto.host\r
+\r
+      do_cmd(auto.action.to_sym, m.source.nick, m.target, "0s", auto.reason)\r
+      return\r
+    }\r
+  end\r
+\r
+  def ban_user(m, params=nil)\r
+    nick, channel = params[:nick], check_channel(m, params[:channel])\r
+    timer = params[:timer]\r
+    do_cmd(:ban, nick, channel, timer)\r
+  end\r
+\r
+  def unban_user(m, params=nil)\r
+    nick, channel = params[:nick], check_channel(m, params[:channel])\r
+    do_cmd(:unban, nick, channel)\r
+  end\r
+\r
+  def kick_user(m, params=nil)\r
+    nick, channel = params[:nick], check_channel(m, params[:channel])\r
+    reason = params[:reason].to_s\r
+    do_cmd(:kick, nick, channel, "0s", reason)\r
+  end\r
+\r
+  def kickban_user(m, params=nil)\r
+    nick, channel, reason = params[:nick], check_channel(m, params[:channel])\r
+    timer, reason = params[:timer], params[:reason].to_s\r
+    do_cmd(:kickban, nick, channel, timer, reason)\r
+  end\r
+\r
+  def silence_user(m, params=nil)\r
+    nick, channel = params[:nick], check_channel(m, params[:channel])\r
+    timer = params[:timer]\r
+    do_cmd(:silence, nick, channel, timer)\r
+  end\r
+\r
+  def unsilence_user(m, params=nil)\r
+    nick, channel = params[:nick], check_channel(m, params[:channel])\r
+    do_cmd(:unsilence, nick, channel)\r
+  end\r
+\r
+  def add_onjoin(m, params=nil)\r
+    begin\r
+      host, channel = m.server.new_netmask(params[:host]), params[:channel].downcase\r
+      action, reason = params[:action], params[:reason].to_s\r
+\r
+      autos = @registry[:onjoin]\r
+      autos << OnJoinAction.new(host, action, channel, reason.dup)\r
+      @registry[:onjoin] = autos\r
+\r
+      m.okay\r
+    rescue\r
+      error $!\r
+      m.reply $!\r
+    end\r
+  end\r
+\r
+  def list_onjoin(m, params=nil)\r
+    m.reply "onjoin rules: #{@registry[:onjoin].length}"\r
+    @registry[:onjoin].each_with_index { |auto, idx|\r
+      m.reply "\##{idx+1}: #{auto.host} | #{auto.action} | #{auto.channel} | '#{auto.reason}'"\r
+    }\r
+  end\r
+\r
+  def rm_onjoin(m, params=nil)\r
+    autos = @registry[:onjoin]\r
+    count = autos.length\r
+\r
+    idx = nil\r
+    idx = params[:idx].to_i if params[:idx]\r
+\r
+    if idx\r
+      if idx > count\r
+        m.reply "No such onjoin \##{idx}"\r
+        return\r
+      end\r
+      autos.delete_at(idx-1)\r
+    else\r
+      begin\r
+        host = m.server.new_netmask(params[:host])\r
+        channel = params[:channel].downcase\r
+\r
+        autos.each { |rule|\r
+          next unless ['all', rule.channel].include?(channel)\r
+          autos.delete rule if rule.host == host\r
+        }\r
+      rescue\r
+        error $!\r
+        m.reply $!\r
+      end\r
+    end\r
+    @registry[:onjoin] = autos\r
+    if count > autos.length\r
+      m.okay\r
+    else\r
+      m.reply "No matching onjoin rule for #{host} found"\r
+    end\r
+  end\r
+\r
+  def add_badword(m, params=nil)\r
+    regexp, channel = make_badword_rx(params[:regexp]), params[:channel].downcase.dup\r
+    action, timer, reason = params[:action], params[:timer].dup, params[:reason].to_s\r
+\r
+    badwords = @registry[:badwords]\r
+    badwords << BadWordAction.new(regexp, action, channel, timer, reason)\r
+    @registry[:badwords] = badwords\r
+\r
+    m.okay\r
+  end\r
+\r
+  def list_badword(m, params=nil)\r
+    m.reply "badword rules: #{@registry[:badwords].length}"\r
+\r
+    @registry[:badwords].each_with_index { |badword, idx|\r
+      m.reply "\##{idx+1}: #{badword.regexp.source} | #{badword.action} | #{badword.channel} | #{badword.timer} | #{badword.reason}"\r
+    }\r
+  end\r
+\r
+  def rm_badword(m, params=nil)\r
+    badwords = @registry[:badwords]\r
+    count = badwords.length\r
+\r
+    idx = nil\r
+    idx = params[:idx].to_i if params[:idx]\r
+\r
+    if idx\r
+      if idx > count\r
+        m.reply "No such badword \##{idx}"\r
+        return\r
+      end\r
+      badwords.delete_at(idx-1)\r
+    else\r
+      channel = params[:channel].downcase\r
+\r
+      regexp = make_badword_rx(params[:regexp])\r
+      debug "Trying to remove #{regexp.inspect} from #{badwords.inspect}"\r
+\r
+      badwords.each { |badword|\r
+        next unless ['all', badword.channel].include?(channel)\r
+       debug "Removing #{badword.inspect}" if badword == regexp\r
+        badwords.delete(badword) if badword == regexp\r
+      }\r
+    end\r
+\r
+    @registry[:badwords] = badwords\r
+    if count > badwords.length\r
+      m.okay\r
+    else\r
+      m.reply "No matching badword #{regexp} found"\r
+    end\r
+  end\r
+\r
+  def add_whitelist(m, params=nil)\r
+    begin\r
+      host, channel = m.server.new_netmask(params[:host]), params[:channel].downcase\r
+\r
+      # TODO check if a whitelist entry for this host already exists\r
+      whitelist = @registry[:whitelist]\r
+      whitelist << WhitelistEntry.new(host, channel)\r
+      @registry[:whitelist] = whitelist\r
+\r
+      m.okay\r
+    rescue\r
+      error $!\r
+      m.reply $!\r
+    end\r
+  end\r
+\r
+  def list_whitelist(m, params=nil)\r
+    m.reply "whitelist entries: #{@registry[:whitelist].length}"\r
+    @registry[:whitelist].each_with_index { |auto, idx|\r
+      m.reply "\##{idx+1}: #{auto.host} | #{auto.channel}"\r
+    }\r
+  end\r
+\r
+  def rm_whitelist(m, params=nil)\r
+    wl = @registry[:whitelist]\r
+    count = wl.length\r
+\r
+    idx = nil\r
+    idx = params[:idx].to_i if params[:idx]\r
+\r
+    if idx\r
+      if idx > count\r
+        m.reply "No such whitelist entry \##{idx}"\r
+        return\r
+      end\r
+      wl.delete_at(idx-1)\r
+    else\r
+      begin\r
+        host = m.server.new_netmask(params[:host])\r
+        channel = params[:channel].downcase\r
+\r
+        wl.each { |rule|\r
+          next unless ['all', rule.channel].include?(channel)\r
+          wl.delete rule if rule.host == host\r
+        }\r
+      rescue\r
+        error $!\r
+        m.reply $!\r
+      end\r
+    end\r
+    @registry[:whitelist] = wl\r
+    if count > whitelist.length\r
+      m.okay\r
+    else\r
+      m.reply "No host matching #{host}"\r
+    end\r
+  end\r
+\r
+  private\r
+  def check_channel(m, strchannel)\r
+    begin\r
+      raise "must specify channel if using privmsg" if m.private? and not strchannel\r
+      channel = m.server.channel(strchannel) || m.target\r
+      raise "I am not in that channel" unless channel.has_user?(@bot.nick)\r
+\r
+      return channel\r
+    rescue\r
+      error $!\r
+      m.reply $!\r
+    end\r
+  end\r
+\r
+  def do_cmd(action, nick, channel, timer_in=nil, reason=nil)\r
+    case timer_in\r
+    when nil\r
+      timer = 0\r
+    when /^(\d+)s$/\r
+      timer = $1.to_i\r
+    when /^(\d+)m$/\r
+      timer = $1.to_i * 60\r
+    when /^(\d+)h$/\r
+      timer = $1.to_i * 60 * 60 \r
+    when /^(\d+)d$/\r
+      timer = $1.to_i * 60 * 60 * 24\r
+    else\r
+      raise "Wrong time specifications"\r
+    end\r
+\r
+    case action\r
+    when :ban\r
+      set_mode(channel, "+b", nick)\r
+      @bot.timer.add_once(timer) { set_mode(channel, "-b", nick) } if timer > 0\r
+    when :unban\r
+      set_mode(channel, "-b", nick)\r
+    when :kick\r
+      do_kick(channel, nick, reason)\r
+    when :kickban\r
+      set_mode(channel, "+b", nick)\r
+      @bot.timer.add_once(timer) { set_mode(channel, "-b", nick) } if timer > 0\r
+      do_kick(channel, nick, reason)\r
+    when :silence, :quiet\r
+      set_mode(channel, "+q", nick)\r
+      @bot.timer.add_once(timer) { set_mode(channel, "-q", nick) } if timer > 0\r
+    when :unsilence, :unquiet\r
+      set_mode(channel, "-q", nick)\r
+    end\r
+  end\r
+\r
+  def set_mode(channel, mode, nick)\r
+    host = channel.has_user?(nick) ? "*!*@" + channel.get_user(nick).host : nick\r
+    @bot.mode(channel, mode, host)\r
+  end\r
+\r
+  def do_kick(channel, nick, reason="")\r
+    @bot.kick(channel, nick, reason)\r
+  end\r
+end\r
+\r
+plugin = BansPlugin.new\r
+\r
+plugin.default_auth( 'act', false )\r
+plugin.default_auth( 'edit', false )\r
+plugin.default_auth( 'list', true )\r
+\r
+plugin.map 'ban :nick :timer :channel', :action => 'ban_user',\r
+  :requirements => {:timer => BansPlugin::TimerRe, :channel => BansPlugin::ChannelRe},\r
+  :defaults => {:timer => nil, :channel => nil},\r
+  :auth_path => 'act'\r
+plugin.map 'unban :nick :channel', :action => 'unban_user',\r
+  :requirements => {:channel => BansPlugin::ChannelRe},\r
+  :defaults => {:channel => nil},\r
+  :auth_path => 'act'\r
+plugin.map 'kick :nick :channel *reason', :action => 'kick_user',\r
+  :requirements => {:channel => BansPlugin::ChannelRe},\r
+  :defaults => {:channel => nil, :reason => 'requested'},\r
+  :auth_path => 'act'\r
+plugin.map 'kickban :nick :timer :channel *reason', :action => 'kickban_user',\r
+  :requirements => {:timer => BansPlugin::TimerRe, :channel => BansPlugin::ChannelRe},\r
+  :defaults => {:timer => nil, :channel => nil, :reason => 'requested'},\r
+  :auth_path => 'act'\r
+plugin.map 'silence :nick :timer :channel', :action => 'silence_user',\r
+  :requirements => {:timer => BansPlugin::TimerRe, :channel => BansPlugin::ChannelRe},\r
+  :defaults => {:timer => nil, :channel => nil},\r
+  :auth_path => 'act'\r
+plugin.map 'unsilence :nick :channel', :action => 'unsilence_user',\r
+  :requirements => {:channel => BansPlugin::ChannelRe},\r
+  :defaults => {:channel => nil},\r
+  :auth_path => 'act'\r
+\r
+plugin.map 'bans add onjoin :host :action :channel *reason', :action => 'add_onjoin',\r
+  :requirements => {:action => BansPlugin::ActionRe, :channel => BansPlugin::ChannelAllRe},\r
+  :defaults => {:action => 'kickban', :channel => 'all', :reason => 'netmask not welcome'},\r
+  :auth_path => 'edit::onjoin'\r
+plugin.map 'bans rm onjoin index :idx', :action => 'rm_onjoin',\r
+  :requirements => {:num => BansPlugin::IdxRe},\r
+  :auth_path => 'edit::onjoin'\r
+plugin.map 'bans rm onjoin :host :channel', :action => 'rm_onjoin',\r
+  :requirements => {:channel => BansPlugin::ChannelAllRe},\r
+  :defaults => {:channel => 'all'},\r
+  :auth_path => 'edit::onjoin'\r
+plugin.map 'bans list onjoin[s]', :action => 'list_onjoin',\r
+  :auth_path => 'list::onjoin'\r
+\r
+plugin.map 'bans add badword :regexp :action :timer :channel *reason', :action => 'add_badword',\r
+  :requirements => {:action => BansPlugin::ActionRe, :timer => BansPlugin::TimerRe, :channel => BansPlugin::ChannelAllRe},\r
+  :defaults => {:action => 'silence', :timer => "0s", :channel => 'all', :reason => 'bad word'},\r
+  :auth_path => 'edit::badword'\r
+plugin.map 'bans rm badword index :idx', :action => 'rm_badword',\r
+  :requirements => {:num => BansPlugin::IdxRe},\r
+  :auth_path => 'edit::badword'\r
+plugin.map 'bans rm badword :regexp :channel', :action => 'rm_badword',\r
+  :requirements => {:channel => BansPlugin::ChannelAllRe},\r
+  :defaults => {:channel => 'all'},\r
+  :auth_path => 'edit::badword'\r
+plugin.map 'bans list badword[s]', :action => 'list_badword',\r
+  :auth_path => 'list::badword'\r
+\r
+plugin.map 'bans add whitelist :host :channel', :action => 'add_whitelist',\r
+  :requirements => {:channel => BansPlugin::ChannelAllRe},\r
+  :defaults => {:channel => 'all'},\r
+  :auth_path => 'edit::whitelist'\r
+plugin.map 'bans rm whitelist index :idx', :action => 'rm_whitelist',\r
+  :requirements => {:num => BansPlugin::IdxRe},\r
+  :auth_path => 'edit::whitelist'\r
+plugin.map 'bans rm whitelist :host :channel', :action => 'rm_whitelist',\r
+  :requirements => {:channel => BansPlugin::ChannelAllRe},\r
+  :defaults => {:channel => 'all'},\r
+  :auth_path => 'edit::whitelist'\r
+plugin.map 'bans list whitelist', :action => 'list_whitelist',\r
+  :auth_path => 'list::whitelist'\r
+\r