plugins/modemanager.nb
# -*-ruby-*-
#
# Copyright (c) 2004-2005 SASADA Koichi <ko1 at atdot.net>
#
# This program is free software with ABSOLUTELY NO WARRANTY.
# You can re-distribute and/or modify this program under
# the same terms of the Ruby's license.
#
#
# $Id$
#
=begin
== Abstract
Mode management bot
== Configuration
=== nadokarc
BotConfig => [
{
:name => :ModeManager,
#
# You can specify modes setting in file or
# String directly.
#
:file => 'modes',
# or :modes_file => 'modes',
:modes => <<-__EOS__,
[all]
+o=*.jp
__EOS__
# wait for setting modes (by second, avarage)
:wait => 5,
}
]
=== mode setting format
[<channel name> or 'all']
<+-><mode> pattern
<+-><mode> /regexp pattern/
<mode>: 'b' or 'v' or 'o'
<+->: '+' means add mode, '-' means remove mode
[example] -------------------------------
[all]
+o=*.jp
+o=/.*\.net/
[#nadoka]
+o=kiyoya* unak*
-o=ko1*
-----------------------------------------
=end
class ModeManager < Nadoka::NDK_Bot
class Fnmexp
def initialize str
@str = str
end
def =~ x
File.fnmatch @str, x, File::FNM_CASEFOLD
end
end
def parse_setting setting
s = nil
setting.each_line{|l|
l.strip!
if /^\[(all|[\#\&\!\+].+)\]/ =~ l
s = @config.identical_channel_name($1)
elsif /^\[%(.+)\]/ =~ l # for compatibility with madoka
s = @config.identical_channel_name("\##{$1}:*.jp")
elsif s && l.sub!(/^([+-][bvo]+)\s*=\s*/, '')
mode = $1
l.scan(/\S+/){|prefix|
if %r!^/(.*)\/$! =~ prefix
user = [mode, Regexp.new($1, Regexp::IGNORECASE)]
else
user = [mode, Fnmexp.new(prefix)]
end
@userlist[s] << user
}
end
}
end
def bot_initialize
@userlist = Hash.new{|h, k| h[k] = []}
if file = (@bot_config[:modes_file] || @bot_config[:file])
begin
parse_setting File.read(file)
rescue Exception => e
"operator manager: #{e.class}(#{e.message})"
end
end
if setting = @bot_config[:modes]
parse_setting setting
end
@wait = @bot_config[:wait].to_i
@wait = 3 if @wait <= 0
end
def search_mode_in_list list, prefix
list.each{|e|
if e[1] =~ prefix
return e[0]
end
}
nil
end
def search_mode ch, prefix
search_mode_in_list(@userlist['all'], prefix) ||
search_mode_in_list(@userlist[ch], prefix)
end
def on_join prefix, rch
ch = @config.canonical_channel_name(rch)
Thread.new{
sleep(rand(@wait * 20) / 10.0)
if prefix.nick != @state.nick &&
(/o/ =~ @state.channel_user_mode(ch, @state.nick))
if mode = search_mode(ch, prefix.to_s)
current_modes = @state.channel_user_mode(ch, prefix.nick).split(//)
if /^\+/ =~ mode
noneed = mode.split(//)[1..-1].all?{|c| current_modes.include?(c)}
else
noneed = mode.split(//)[1..-1].all?{|c| !current_modes.include?(c)}
end
change_mode(rch, mode, prefix.nick) unless noneed
end
end
}
end
end