From 1cdc30f08ef77d2719ad60b26def738cb1fd5872 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 30 Jan 2007 01:35:09 +0000 Subject: [PATCH 1/1] Improved bans plugin, thanks to kamu (reworked) --- data/rbot/plugins/bans.rb | 674 ++++++++++++++++++++++++++------------ 1 file changed, 469 insertions(+), 205 deletions(-) diff --git a/data/rbot/plugins/bans.rb b/data/rbot/plugins/bans.rb index bbcf0f39..03fe2f34 100644 --- a/data/rbot/plugins/bans.rb +++ b/data/rbot/plugins/bans.rb @@ -1,205 +1,469 @@ -# 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 -# Licensed under GPL V2. - - -class BansPlugin < Plugin - def initialize - super - if @registry.has_key?(:bans) - @bansregexps = @registry[:bans] - else - @bansregexps = Hash.new - end - - if @registry.has_key?(:bansmasks) - @whitelist = @registry[:bansmasks] - else - @whitelist = Hash.new - end - end - - - def save - @registry[:bans] = @bansregexps - @registry[:bansmasks] = @whitelist - end - - - - - def help(plugin, topic="") - case topic - when "kickbans" - return "bans ban|quietban nick [channel] [timer]: bans|quietbans a nick from the channel for a specified time. bans kick nick [channel] [message]: kicks from with kick . bans kickban nick [channel] [timer] [message]: kick+ban, same parameters as before. timer is always specified as , like 3m, 10s, 1h." - when "whitelist" - return "bans addwhitelist : adds to whitelist (NEVER regexp ban this). bans whitelist: shows current whitelist. bans delwhitelist : delete whitelist entry ." - when "regexpbans" - return "bans addregexp type [timer] regexp: listens for , then do actions depending on (\"quietban\" or \"kickban\", currently). If timer if specified, it removes the ban after timer expires. timer is always specified as , like 3m, 10s, 1h. bans delregexp : remove watching for regexp . bans listregexps: show current regexp watching list." - else - return "Topics: \"kickbans\", \"whitelist\", \"regexpbans\"" - end -# 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 ; 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 - @whitelist.each_key do |key| - if Irc.netmaskmatch(@whitelist[key], m.source) then - return - end - next - 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.") - end - def cmd_whitelistadd(m, params) - regsize=@whitelist.length+1 - @whitelist[regsize]=params[:netmask] - m.reply("Done.") - end - def cmd_whitelist(m, params) - if @whitelist.length == 0 - m.reply("Whitelist is empty."); return - end - @whitelist.each_key do |key| - m.reply("Key: #{key}, netmask: #{@whitelist[key]}") - sleep 1 - next - end - end - def cmd_whitelistdel(m, params) - index=params[:index] - @whitelist.each_key do |key| - if ( "#{key}" == "#{index}" ) then - @whitelist.delete(key) - m.reply("Done.") - return - end - next - end - m.reply("Key #{index} not found.") - end -end -plugin = BansPlugin.new -plugin.register("bans") - -plugin.map 'bans whitelist', :action => 'cmd_whitelist', :auth => 'bans' -plugin.map 'bans delwhitelist :index', :action => 'cmd_whitelistdel', :auth => 'bans', :requirements => { :index => /^\d+$/ } -plugin.map 'bans addwhitelist :netmask', :action => 'cmd_whitelistadd', :auth => '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") +# BansPlugin v3 for 0.9.11 +# +# Managing kick and bans, automatically removing bans after timeouts, quiet bans, and kickban/quietban based on regexp +# +# (c) 2006 Marco Gulino +# (c) 2007 kamu +# (c) 2007 Giuseppe Bilotta +# +# v1 -> v2 (kamu's version, never released) +# * reworked +# * autoactions triggered on join +# * action on join or badword can be anything: kick, ban, kickban, quiet +# +# v2 -> v3 (GB) +# * remove the 'bans' prefix from most of the commands +# * (un)quiet has been renamed to (un)silence because 'quiet' was used to tell the bot to keep quiet +# * both (un)quiet and (un)silence are accepted as actions +# * use the more descriptive 'onjoin' term for autoactions +# * convert v1's (0.9.10) :bans and :bansmasks to BadWordActions and WhitelistEntries +# * enhanced list manipulation facilities +# * fixed regexp usage in requirements for plugin map +# * add proper auth management +# +# Licensed under GPL V2. + +OnJoinAction = Struct.new("OnJoinAction", :host, :action, :channel, :reason) +BadWordAction = Struct.new("BadWordAction", :regexp, :action, :channel, :timer, :reason) +WhitelistEntry = Struct.new("WhitelistEntry", :host, :channel) + + +class BansPlugin < Plugin + + IdxRe = /^\d+$/ + TimerRe = /^\d+[smhd]$/ + ChannelRe = /^#+[^\s]+$/ + ChannelAllRe = /^(?:all|#+[^\s]+)$/ + ActionRe = /(?:ban|kick|kickban|silence|quiet)/ + + def name + "bans" + end + + def make_badword_rx(txt) + return /\b#{txt}\b/i + end + + def initialize + super + + # Convert old BadWordActions, which were simpler and labelled :bans + if @registry.has_key? :bans + badwords = Array.new + bans = @registry[:bans] + @registry[:bans].each { |ar| + case ar[0] + when "quietban" + action = :silence + when "kickban" + action = :kickban + else + # Shouldn't happen + warn "Unknown action in old data #{ar.inspect} -- entry ignored" + next + end + bans.delete(ar) + chan = ar[1] + regexp = make_badword_rx(ar[2]) + badwords << BadWordAction.new(regexp, action, chan, "0s", "") + } + @registry[:badwords] = badwords + if bans.length > 0 + # Store the ones we couldn't convert + @registry[:bans] = bans + else + @registry.delete(:bans) + end + else + @registry[:badwords] = Array.new unless @registry.has_key? :badwords + end + + # Convert old WhitelistEntries, which were simpler and labelled :bansmasks + if @registry.has_key? :bans + wl = Array.new + @registry[:bansmasks].each { |mask| + badwords << WhitelistEntry.new(mask, "all") + } + @registry[:whitelist] = wl + @registry.delete(:bansmasks) + else + @registry[:whitelist] = Array.new unless @registry.has_key? :whitelist + end + + @registry[:onjoin] = Array.new unless @registry.has_key? :onjoin + end + + def help(plugin, topic="") + case plugin + when "ban" + return "ban [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" + when "unban" + return "unban [#channel]: unban a user from the given channel. defaults to the current channel" + when "kick" + return "kick [#channel] [reason ...]: kick a user from the given channel with the given reason. defaults to the current channel, no reason" + when "kickban" + return "kickban [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" + when "silence" + return "silence [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" + when "unsilence" + return "unsilence [#channel]: allow the given user to talk on the given channel. defaults to the current channel" + when "bans" + case topic + when "add" + return "bans add : add an automatic action for people that join or say some bad word, or a whitelist entry. further help available" + when "add onjoin" + return "bans add onjoin [action] [#channel] [reason ...]: will add an autoaction for any one who joins with hostmask. default action is silence, default channel is all" + when "add badword" + return "bans add badword [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" + when "add whitelist" + return "bans add whitelist [#channel|all]: add the given hostmask to the whitelist. no autoaction will be triggered by users on the whitelist" + when "rm" + return "bans rm [#channel], or bans rm index : removes the specified onjoin or badword rule or whitelist entry." + when "list" + return"bans list : lists all onjoin or badwords or whitelist entries" + end + end + return "bans : 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" + end + + def listen(m) + return unless m.respond_to?(:public?) and m.public? + @registry[:whitelist].each { |white| + next unless ['all', m.target.downcase].include?(white.channel) + return if m.source.matches?(white.host) + } + + @registry[:badwords].each { |badword| + next unless ['all', m.target.downcase].include?(badword.channel) + next unless badword.regexp.match(m.message) + + do_cmd(badword.action.to_sym, m.source.nick, m.target, badword.timer, badword.reason) + m.reply "bad word detected! #{badword.action} for #{badword.timer} because: #{badword.reason}" + return + } + end + + def join(m) + @registry[:whitelist].each { |white| + next unless ['all', m.target.downcase].include?(white.channel) + return if m.source.matches?(white.host) + } + + @registry[:onjoin].each { |auto| + next unless ['all', m.target.downcase].include?(auto.channel) + next unless m.source.matches? auto.host + + do_cmd(auto.action.to_sym, m.source.nick, m.target, "0s", auto.reason) + return + } + end + + def ban_user(m, params=nil) + nick, channel = params[:nick], check_channel(m, params[:channel]) + timer = params[:timer] + do_cmd(:ban, nick, channel, timer) + end + + def unban_user(m, params=nil) + nick, channel = params[:nick], check_channel(m, params[:channel]) + do_cmd(:unban, nick, channel) + end + + def kick_user(m, params=nil) + nick, channel = params[:nick], check_channel(m, params[:channel]) + reason = params[:reason].to_s + do_cmd(:kick, nick, channel, "0s", reason) + end + + def kickban_user(m, params=nil) + nick, channel, reason = params[:nick], check_channel(m, params[:channel]) + timer, reason = params[:timer], params[:reason].to_s + do_cmd(:kickban, nick, channel, timer, reason) + end + + def silence_user(m, params=nil) + nick, channel = params[:nick], check_channel(m, params[:channel]) + timer = params[:timer] + do_cmd(:silence, nick, channel, timer) + end + + def unsilence_user(m, params=nil) + nick, channel = params[:nick], check_channel(m, params[:channel]) + do_cmd(:unsilence, nick, channel) + end + + def add_onjoin(m, params=nil) + begin + host, channel = m.server.new_netmask(params[:host]), params[:channel].downcase + action, reason = params[:action], params[:reason].to_s + + autos = @registry[:onjoin] + autos << OnJoinAction.new(host, action, channel, reason.dup) + @registry[:onjoin] = autos + + m.okay + rescue + m.reply $! + end + end + + def list_onjoin(m, params=nil) + m.reply "onjoin rules: #{@registry[:onjoin].length}" + @registry[:onjoin].each_with_index { |auto, idx| + m.reply "\##{idx+1}: #{auto.host} | #{auto.action} | #{auto.channel} | '#{auto.reason}'" + } + end + + def rm_onjoin(m, params=nil) + autos = @registry[:onjoin] + count = autos.length + + idx = params[:idx].to_i + + if idx + if idx > count + m.reply "No such onjoin \##{idx}" + return + end + autos.delete_at(idx-1) + else + begin + host = m.server.new_netmask(params[:host]) + channel = params[:channel].downcase + + autos.each { |rule| + next unless ['all', rule.channel].include?(channel) + autos.delete rule if rule.host == host + } + rescue + m.reply $! + end + end + @registry[:onjoin] = autos + m.okay if count > autos.length + end + + def add_badword(m, params=nil) + regexp, channel = make_badword_rx(params[:regexp]), params[:channel].dup + action, timer, reason = params[:action], params[:timer].dup, params[:reason].to_s + + badwords = @registry[:badwords] + badwords << BadWordAction.new(regexp, action, channel, timer, reason) + @registry[:badwords] = badwords + + m.okay + end + + def list_badword(m, params=nil) + m.reply "badword rules: #{@registry[:badwords].length}" + + @registry[:badwords].each_with_index { |badword, idx| + m.reply "\##{idx+1}: #{badword.regexp.source} | #{badword.action} | #{badword.channel} | #{badword.timer} | #{badword.reason}" + } + end + + def rm_badword(m, params=nil) + badwords = @registry[:badwords] + count = badwords.length + + idx = params[:idx].to_i + + if idx + if idx > count + m.reply "No such badword \##{idx}" + return + end + badwords.delete_at(idx-1) + else + channel = params[:channel].downcase + + regexp = make_badword_rx(params[:regexp]) + debug "Trying to remove #{regexp.inspect} from #{badwords.inspect}" + + badwords.each { |badword| + next unless ['all', badword.channel].include?(channel) + badwords.delete(badword) if badword == regexp + } + end + + @registry[:badwords] = badwords + m.okay if count > badwords.length + end + + def add_whitelist(m, params=nil) + begin + host, channel = m.server.new_netmask(params[:host]), params[:channel].downcase + + # TODO check if a whitelist entry for this host already exists + whitelist = @registry[:whitelist] + whitelist << WhitelistEntry.new(host, channel) + @registry[:whitelist] = whitelist + + m.okay + rescue + m.reply $! + end + end + + def list_whitelist(m, params=nil) + m.reply "whitelist entries: #{@registry[:whitelist].length}" + @registry[:whitelist].each_with_index { |auto, idx| + m.reply "\##{idx+1}: #{auto.host} | #{auto.channel}" + } + end + + def rm_whitelist(m, params=nil) + wl = @registry[:whitelist] + count = wl.length + + idx = params[:idx].to_i + + if idx + if idx > count + m.reply "No such whitelist entry \##{idx}" + return + end + wl.delete_at(idx-1) + else + begin + host = m.server.new_netmask(params[:host]) + channel = params[:channel].downcase + + wl.each { |rule| + next unless ['all', rule.channel].include?(channel) + wl.delete rule if rule.host == host + } + rescue + m.reply $! + end + end + @registry[:whitelist] = wl + m.okay if count > whitelist.length + end + + private + def check_channel(m, strchannel) + begin + raise "must specify channel if using privmsg" if strchannel.empty? and m.private? + channel = strchannel.empty? ? m.target : m.server.channel(strchannel) + raise "I am not in that channel" unless channel.has_user?(@bot) + + return channel + rescue + m.reply $! + end + end + + def do_cmd(action, nick, channel, timer="0s", reason="") + if timer.eql? "0s" + timer = 0 + else + timer = $1.to_i if timer =~ /^(\d+)s$/ + timer = $1.to_i * 60 if timer =~ /^(\d+)m$/ + timer = $1.to_i * 60 * 60 if timer =~ /^(\d+)h$/ + timer = $1.to_i * 60 * 60 * 24 if timer =~ /^(\d+)d$/ + end + + case action + when :ban + set_mode(channel, "+b", nick) + @bot.timer.add_once(timer) { set_mode(channel, "-b", nick) } if timer > 0 + when :unban + set_mode(channel, "-b", nick) + when :kick + do_kick(channel, nick, reason) + when :kickban + set_mode(channel, "+b", nick) + @bot.timer.add_once(timer) { set_mode(channel, "-b", nick) } if timer > 0 + do_kick(channel, nick, reason) + when :silence, :quiet + set_mode(channel, "+q", nick) + @bot.timer.add_once(timer) { set_mode(channel, "-q", nick) } if timer > 0 + when :unsilence, :unquiet + set_mode(channel, "-q", nick) + end + end + + def set_mode(channel, mode, nick) + host = channel.has_user?(nick) ? "*!*@" + channel.get_user(nick).host : nick + @bot.mode(channel, mode, host) + end + + def do_kick(channel, nick, reason="") + @bot.kick(channel, nick, reason) + end +end + +plugin = BansPlugin.new + +plugin.default_auth( 'act', false ) +plugin.default_auth( 'edit', false ) +plugin.default_auth( 'list', true ) + +plugin.map 'ban :nick :timer :channel', :action => 'ban_user', + :requirements => {:timer => BansPlugin::TimerRe, :channel => BansPlugin::ChannelRe}, + :defaults => {:timer => '0s', :channel => ''}, + :auth_path => 'act' +plugin.map 'unban :nick :channel', :action => 'unban_user', + :requirements => {:channel => BansPlugin::ChannelRe}, + :defaults => {:channel => ''}, + :auth_path => 'act' +plugin.map 'kick :nick :channel *reason', :action => 'kick_user', + :requirements => {:channel => BansPlugin::ChannelRe}, + :defaults => {:channel => '', :reason => ''}, + :auth_path => 'act' +plugin.map 'kickban :nick :timer :channel *reason', :action => 'kickban_user', + :requirements => {:timer => BansPlugin::TimerRe, :channel => BansPlugin::ChannelRe}, + :defaults => {:timer => '0s', :channel => '', :reason => ''}, + :auth_path => 'act' +plugin.map 'silence :nick :timer :channel', :action => 'silence_user', + :requirements => {:timer => BansPlugin::TimerRe, :channel => BansPlugin::ChannelRe}, + :defaults => {:timer => '0s', :channel => ''}, + :auth_path => 'act' +plugin.map 'unsilence :nick :channel', :action => 'unsilence_user', + :requirements => {:channel => BansPlugin::ChannelRe}, + :defaults => {:channel => ''}, + :auth_path => 'act' + +plugin.map 'bans add onjoin :host :action :channel *reason', :action => 'add_onjoin', + :requirements => {:action => BansPlugin::ActionRe, :channel => BansPlugin::ChannelAllRe}, + :defaults => {:action => 'kickban', :channel => 'all', :reason => 'netmask not welcome'}, + :auth_path => 'edit::onjoin' +plugin.map 'bans rm onjoin index :idx', :action => 'rm_onjoin', + :requirements => {:num => BansPlugin::IdxRe}, + :auth_path => 'edit::onjoin' +plugin.map 'bans rm onjoin :host :channel', :action => 'rm_onjoin', + :requirements => {:channel => BansPlugin::ChannelAllRe}, + :defaults => {:channel => 'all'}, + :auth_path => 'edit::onjoin' +plugin.map 'bans list onjoin[s]', :action => 'list_onjoin', + :auth_path => 'list::onjoin' + +plugin.map 'bans add badword :regexp :action :timer :channel *reason', :action => 'add_badword', + :requirements => {:action => BansPlugin::ActionRe, :timer => BansPlugin::TimerRe, :channel => BansPlugin::ChannelAllRe}, + :defaults => {:action => 'silence', :timer => "0s", :channel => 'all', :reason => 'bad word'}, + :auth_path => 'edit::badword' +plugin.map 'bans rm badword index :idx', :action => 'rm_badword', + :requirements => {:num => BansPlugin::IdxRe}, + :auth_path => 'edit::badword' +plugin.map 'bans rm badword :regexp :channel', :action => 'rm_badword', + :requirements => {:channel => BansPlugin::ChannelAllRe}, + :defaults => {:channel => 'all'}, + :auth_path => 'edit::badword' +plugin.map 'bans list badword[s]', :action => 'list_badword', + :auth_path => 'list::badword' + +plugin.map 'bans add whitelist :host :channel', :action => 'add_whitelist', + :requirements => {:channel => BansPlugin::ChannelAllRe}, + :defaults => {:channel => 'all'}, + :auth_path => 'edit::whitelist' +plugin.map 'bans rm whitelist index :idx', :action => 'rm_whitelist', + :requirements => {:num => BansPlugin::IdxRe}, + :auth_path => 'edit::whitelist' +plugin.map 'bans rm whitelist :host :channel', :action => 'rm_whitelist', + :requirements => {:channel => BansPlugin::ChannelAllRe}, + :defaults => {:channel => 'all'}, + :auth_path => 'edit::whitelist' +plugin.map 'bans list whitelist', :action => 'list_whitelist', + :auth_path => 'list::whitelist' + -- 2.39.2