Code: Select all
namespace eval MassKick {
# set the masskick limit (count:time)
set mass(limit) "3:10"
# timeout of the check access command sent to ChanServ
set mass(timeout) "60"
# memo to be sent when an AOP was removed
set memo(mass) "The AOP of %nick user on %chan channel has been deleted due to attempt to masskick."
# memo to be sent when bot was kicked by an AOP
set memo(bot) "The AOP of %nick user on %chan channel has been deleted cos he kicked me."
# memo to be sent when SOP or higher masskicked and bot didn't triggered any actions
set memo(skip) "User %nick has level %level (%rank) on the %chan channel, so his action (%action) has been ignored, also added him to the skip list."
# memo to be sent when someone without any access triggered a masskick or kicked the bot
set memo(zero) "Someone oped user %nick on the %chan channel and %action the channel..."
# customize the text of %action in the lines above
set memo(action) {
"masskicked"
"booted me off"
}
# ignore the actions of the users that have this flags
set mass(friends) "f|f"
# don't edit below this line
setudef flag massKick
set flags { "massKicker" "massCount" "checkList" "checkAct" "massSkip" }
foreach flag $flags {
setudef str $flag
}
# binds
bind kick * * [namespace current]::kicked
bind part - * [namespace current]::remove
bind sign - * [namespace current]::remove
bind nick - * [namespace current]::nickCh
bind notc * * [namespace current]::checkReply
#bind raw - MODE [namespace current]::massMode
# bot kicked
proc botKicked {chan nick} {
channel set $chan checkList [lappend [channel get $chan checkAct] $nick "1"]
massCheck $chan $nick
}
# reset
proc resetChan {chan} {
if {![validchan $chan]} return
set flags { "massKicker" "massCount" "checkList" "checkAct" }
foreach flag $flags {
channel set $chan $flag {}
}
}
# access checking
proc massCheck {chan nick} {
set checkList [channel get $chan checkList]
if {$nick in $checkList} {
if {$nick in [channel get $chan massSkip]} {
set pos [lsearch $checkList $nick]
channel set $chan checkList [lreplace $checkList $pos $pos]
}
return
}
variable mass
channel set $chan checkList [lappend checkList $nick]
puthelp "ChanServ access $chan $nick"
utimer $mass(timeout) [list [namespace current]::doThis "5" $chan $nick]
}
# reply of ACC command from ChanServ
proc checkReply {nick uhost hand text {dest ""}} {
if {[string equal -length 1 # $dest]} return
if {$nick eq "ChanServ"} {
foreach {user cmd chan level rank} [split $text] { break }
set checkList [channel get $chan checkList]
if {$nick ni $checkList} return
set pos [lsearch $checkList $nick]
set act [lindex [channel get $chan checkAct] $pos]
actLevel $chan $user $level $rank $act
}
}
# access trigger actions
proc actLevel {chan nick level rank act} {
variable memo
set action [lindex $memo(action) $act]
set rank [string trim [lindex [split $rank] 0] {()}]
switch -- $level {
"0" {
putserv "Chanserv deop $chan $nick"
set message [string map -nocase [list "%chan" "$chan" "%nick" "$nick" "%action" "$action"] $memo(zero)]
}
"10" {
putserv "Chanserv deop $chan $nick"
putserv "Chanserv aop $chan del $nick"
putlog "del aop & deop"
if {$act eq "0"} {
set message [string map -nocase [list "%chan" "$chan" "%nick" "$nick"] $memo(mass)]
} elseif {$act eq "1"} {
set message [string map -nocase [list "%chan" "$chan" "%nick" "$nick"] $memo(bot)]
}
}
"20" - "30" - "40" - "50" - "60" {
channel set $chan massSkip [lappend [channel get $chan massSkip] $nick]
set message [string map -nocase [list "%chan" "$chan" "%nick" "$nick" "%level" "$level" "%action" "$action" "%rank" "$rank"] $memo(skip)]
}
}
putserv "Memoserv send $chan $message"
doThis "2" $chan $nick
doThis "5" $chan $nick
}
# triggers:
# 1 - add, 2 - remove massKicker/massCount, 3 - replace nick
# 4 - replace count, 5 - remove checklist
proc doThis {act chan nick {pos ""} {count ""} {newNick ""}} {
set massKicker [channel get $chan massKicker]
set massCount [channel get $chan massCount]
set checkAct [channel get $chan checkAct]
switch -- $act {
"1" {
lappend massKicker $nick
lappend massCount 1
lappend checkAct 0
}
"2" {
set pos [lsearch $massKicker $nick]
set massKicker [lreplace $massKicker $pos $pos]
set massCount [lreplace $massCount $pos $pos]
}
"3" {
set massKicker [lreplace $massKicker $pos $pos $newNick]
}
"4" {
set massCount [lreplace $massCount $pos $pos $count]
}
"5" {
set checkList [channel get $chan checkList]
if {$nick ni $checkList} return
set pos [lsearch $checkList $nick]
channel set $chan checkList [lreplace $checkList $pos $pos]
set checkAct [lreplace $checkAct $pos $pos]
}
"6" {
set checkList [channel get $chan checkList]
if {$nick in $checkList} {
set pos [lsearch $checkList $nick]
channel set $chan checkList [lreplace $checkList $pos $pos]
}
set massSkip [channel get $chan massSkip]
if {$nick in $massSkip} {
set pos [lsearch $massSkip $nick]
channel set $chan massSkip [lreplace $massSkip $pos $pos]
}
}
}
channel set $chan massKicker $massKicker
channel set $chan massCount $massCount
channel set $chan checkAct $checkAct
}
# triggers:
# 1 - part & sign, 2 - nick change
proc eventThis {event chan nick {newNick ""}} {
set massKicker [channel get $chan massKicker]
if {$nick ni $massKicker} return
set pos [lsearch $massKicker $nick]
switch -- $event {
"1" {
doThis "2" $chan $nick
doThis "5" $chan $nick
}
"2" {
doThis "3" $chan $nick $pos "0" $newNick
doThis "6" $chan $nick $newNick
}
}
}
# part & sign
proc remove {nick uhost handle chan {text ""}} {
if {![channel get $chan massKick]} return
if {[isbotnick $nick]} {
resetChan $chan
} else {
eventThis "1" $chan $nick
}
}
# nick
proc nickCh {nick uhost handle chan newnick} {
if {![channel get $chan massKick]} return
if {[isbotnick $nick]} return
eventThis "2" $chan $nick $newNick
}
# kick
proc kicked {nick uhost hand chan target reason} {
if {![channel get $chan massKick]} return
variable mass
if {[matchattr $hand $mass(friends) $chan]} return
if {[isbotnick $nick]} return
if {$nick eq "ChanServ"} return
if {$nick in [channel get $chan massSkip]} return
if {[isbotnick $target]} {
botKicked $chan $nick
return
}
set massKicker [channel get $chan massKicker]
if {$nick ni $massKicker} {
doThis "1" $chan $nick
return
}
set pos [lsearch $massKicker $nick]
set count [lindex [channel get $chan massCount] $pos]
set info [split $mass(limit) :]
if {$count >= [lindex $info 0]} {
massCheck $chan $nick
return
} else {
incr count
}
utimer [lindex $info 1] [list [namespace current]::doThis "2" $chan $nick]
doThis "4" $chan $nick $pos $count
}
}
To be honest I would rather create a "special" user (like massUser) to the bot and give him some flags that aren't used in any other script and set that flag in mass(friends) in the previous code, then add the host masks of the people that I want to be skipped from any punishment, than depend on ChanServ's reply with the access level of a person that's mass kicking. Right now the bot won't react until it receives a reply of that access command from ChanServ and removes the user from his check list after the timeout that is set at mass(timeout).
In the massMode I was thinking on monitoring all +o on the channel, then issue an WHY command and store that user in massSkip list if it's level is above the requirements. This should save some time but in case some user that isn't in that list the script still will depend on how fast ChanServ will reply to the access command.
If you got any other idea feel free to contribute.