####################################################
# by wiebe @ QuakeNet
#
# adds bans properly, see below
#
####################################################

####################################################
#
# newchanban / newban basicly do "pushmode ..; flushmode ..; putkick ..
# when you ban 5 users using newchanban this happens (+dynamicbans):
# mode +b host1
# kick nick1
# mode +b host2
# kick nick2
# mode +b host3
# kick nick3
# mode +b host4
# kick nick4
# mode +b host5
# kick nick5
# this takes 2 * 5 = 10 commands
#
# while it should do it neat, like this:
# mode +bbbbb host1 host2 host3 host4 host5
# kick nick1
# kick nick2
# kick nick3
# kick nick4
# kick nick5
# this takes 1 + 5 = 6 commands (4 commands/lines less)
####################################################


####################################################
# newchanban:ban
####################################################
proc newchanban:ban { chan ban creator comment {lifetime ""} {options ""} } {
  set c $chan; set b $ban; set d $creator; set r $comment; set l $lifetime; set o $options
  if {![validchan $c]} { return 0 }
  set f 1; set o [string tolower $o]; if {[string equal $o ""]} { set o "none" }
  # hidden ban, forward
  if {[string match @*!*@* $b] && [info procs hiddenbans:checkmask] != ""} {
    newchanban $c $b $d $r $l $o
    hiddenbans:checkmask $b $c
    return 1
  }
  if {[info exists ::max-bans]} { set h ${::max-bans} } else { set h "45" }
  if {[isban $b $c] && ![isban $b]} { return 0 }
  if {[isban &$b $c] && ![isban &$b]} { return 0 }
  if {![botisop $c] && ![botishalfop $c]} { set f 0 }
  if {[llength [chanbans $c]] >= $h} { set f 0 }
  if {[newchanban:set $c $b]} { set f 0 }
  if {![newchanban:activate $c $b]} { set f 0 }
  if {[string equal $o "sticky"]} { set f 1 }
  if {$f} {
    pushmode $c +b $b; set e 0
    if {![channel get $c dynamicbans]} { set e 1 }
    if {$e} { channel set $c +dynamicbans }
    newchanban $c &$b $d $r $l $o
    if {$e} { channel set $c -dynamicbans }
  } else { newchanban $c $b $d $r $l $o }
  putallbots "ncb $c $b"
  return 1
}


####################################################
# newchanban:mode
#
# check for &ban in banlist and change it
####################################################
bind mode -|- "% +b" newchanban:mode
proc newchanban:mode { n u h c m b } {
  if {![string equal $m "+b"]} { return 0 }
  if {![isban &$b $c]} { return 0 }
  set t [clock seconds]
  foreach e [banlist $c] {
    set h [lindex $e 0]
    if {![string equal -nocase &$b $h]} { continue }
    set r [lindex $e 1]; set f [lindex $e 2]; set d [lindex $e 5]; set l [expr ($f - $t) / 60]
    set s "none"; if {[isbansticky $b $c]} { set s "sticky" }
    newchanban $c $b $d $r $l $s; killchanban $c $h; return 0
  }
}


####################################################
# newchanban:time
#
# check for &bans and activate them
####################################################
bind time -|- "* * * * *" newchanban:time
proc newchanban:time { mi ho da mo ye } {
  set t [clock seconds]
  foreach c [channels] {
    foreach e [banlist $c] {
      set h [lindex $e 0]
      if {![string match -nocase &* $h]} { continue }
      set a [lindex $e 3]
      if {[expr $t - $a] < "120"} { continue }
      set r [lindex $e 1]; set f [lindex $e 2]; set d [lindex $e 5]; set l [expr ($f - $t) / 60]
      set s "none"; if {[isbansticky $h $c]} { set s "sticky" }
      killchanban $c $h; set h [string range $h 1 end]; newchanban $c $h $d $r $l $s
    }
  }
}


####################################################
# newchanban:activate
#
# return 1 if ban needs to be activated
####################################################
proc newchanban:activate { c b } {
  regsub -all {[][\\]} $b {\\\0} b
  set b [newchanban:lower $b]
  set h 0
  foreach n [chanlist $c] {
    if {[isbotnick $n]} { continue }
    if {[onchansplit $n $c]} { continue }
    set m $n![getchanhost $n $c]; set m [newban:lower $m]
    if {![string match $b $m]} { continue }
    set g [nick2hand $n $c]
    if {[matchattr $g omn|omn $c] && [channel get $c dontkickops]} { continue }
    set h 1
    if {[isop $n $c]} { pushmode $c -o $n }
    if {[ishalfop $n $c]} { pushmode $c -h $n }
  }
  return $h
}


####################################################
# newchanban:set
#
# returns 1 if the ban is already set
####################################################
proc newchanban:set { c b } {
  if {[ischanban $b $c]} { return 1 }
  set b [newchanban:lower $b]
  foreach e [chanbans $c] {
    set e [lindex $e 0]; set e [newchanban:lower $e]
    regsub -all {[][\\]} $e {\\\0} e
    if {[string match $e $b]} { return 1 }
  }
  return 0
}


####################################################
# newchanban:lower
#
# change text to lower, rfc1459 if needed
####################################################
proc newchanban:lower { t } {
  global rfc-compliant
  if {[info exists rfc-compliant] && [string equal ${rfc-compliant} "1"]} {
    set t [string map "\\{ \[ \\} \] ~ ^ \\\\ |" $t]
  }
  set t [string tolower $t]
  return $t
}


####################################################
# newchanban:bot
####################################################
bind bot -|- ncb newchanban:bot
proc newchanban:bot { b c t } {
  if {![islinked $b]} { return 0 }
  if {![string equal $c "ncb"]} { return 0 }
  set t [split $t]; set c [lindex $t 0]; set b [lindex $t 1]; set f 1
  if {![validchan $c]} { return 0 }
  if {[string equal $b ""]} { return 0 }
  if {![botisop $c] && ![botishalfop $c]} { return 0 }
  if {![isban $b $c] && ![isban &$b $c]} { return 0 }
  if {[info exists ::max-bans]} { set h ${::max-bans} } else { set h "45" }
  foreach e [banlist $c] {
# hostmask, comment, expiration timestamp, time added, last time active, and creator.
    set m [lindex $e 0]; set r [lindex $e 1]; set d [lindex $e 5]
    if {![string equal -nocase $m $b] && ![string equal -nocase $m &$b]} { continue }
    if {[isbansticky $b $c]} { set o "sticky" } else { set o "none" }
    set l [expr ([lindex $e 2] - [clock seconds]) / 60]
    if {[llength [chanbans $c]] >= $h} { set f 0 }
    if {[newchanban:set $c $b]} { set f 0 }
    if {![newchanban:activate $c $b]} { set f 0 }
    if {[string equal $o "sticky"]} { set f 1 }
    if {$f} {
      pushmode $c +b $b; set e 0
      if {![channel get $c dynamicbans]} { set e 1 }
      if {$e} { channel set $c +dynamicbans }
      newchanban $c &$b $d $r $l $o
      if {$e} { channel set $c -dynamicbans }
# else needed?
    } else { newchanban $c $b $d $r $l $o }
    return 1
  }
}


set scriptdb(newchanban) {
  "improvement of the eggdrop newchanban command, multiple bans in a short time are handled correct"
}

