#by wiebe @ QuakeNet



set c_unban(xhost) "users.quakenet.org"



#help unban pub

bind pubm lomn|lomn "% ${botnet-nick} help unban" c_unban:help:pub

proc c_unban:help:pub { nick uhost handle chan text } {
  lappend output "Usage: unban \[<ban1> <ban2> .. <banN>|<number1> <number2> .. <numberN>\]"
  lappend output "Without bans/numbers, removes youngest ban. <numbers> refers to bans on the channel, where 1 is the youngest ban. Masks and numbers can not be mixed. #account can be used to unban a *!*@<account>.$::c_unban(xhost) mask. Halfops and ops can not remove bans set by masters or owners."
  if { [catch {set x [cnotice $nick $output]} error] || !$x } {
    foreach t $output { puthelp "NOTICE $nick :$t" }
  }
  putloglev c $chan "[lindex [split $text] 1]: $nick $uhost $handle $chan [join [lrange [split $text] 2 end]]"
}




#help unban msg

bind msgm lomn|lomn "help unban" c_unban:help:msg

proc c_unban:help:msg { nick uhost handle text } {
  lappend output "Usage: unban <channel> \[<ban1> <ban2> .. <banN>|<number1> <number2> .. <numberN>\]"
  lappend output "Without bans/numbers, removes youngest ban. <numbers> refers to bans on the channel, where 1 is the youngest ban. Masks and numbers can not be mixed. #account can be used to unban a *!*@<account>.$::c_unban(xhost) mask. Halfops and ops can not remove bans set by masters or owners."
  if { [catch {set x [cnotice $nick $output]} error] || !$x } {
    foreach t $output { puthelp "NOTICE $nick :$t" }
  }
  putcmdlog "($nick!$uhost) !$handle! $text"
}



#unban pub
bind pubm lomn|lomn "% ${botnet-nick} unban" c_unban:pub
bind pubm lomn|lomn "% ${botnet-nick} unban *" c_unban:pub

proc c_unban:pub { nick uhost handle chan text } {
  set masks [join [lrange [split $text] 2 end]]
  set output [c_unban:unban $chan $nick $handle $masks]
  if { ![botisop $chan] && ![botishalfop $chan] } {
    lappend output "I am not a channel operator on $chan"
    lappend output "Only internal bans will be removed from the internal banlist."
  }
  if { [catch {set x [cnotice $nick $output]} error] || !$x } {
    foreach t $output { puthelp "NOTICE $nick :$t" }
  }
  putloglev c $chan "[lindex [split $text] 1]: $nick $uhost $handle $chan [join [lrange [split $text] 2 end]]"
}



#unban msg
bind msg lomn|lomn unban c_unban:msg

proc c_unban:msg { nick uhost handle text } {
  set chan [lindex [split $text] 0]
  set masks [join [lrange [split $text] 1 end]]
  if { [string equal $chan ""] } {
    c_unban:help:msg $nick $uhost $handle $text
  } elseif { ![validchan $chan] || ![matchattr $handle lomn|lomn $chan] } {
    lappend output "No access or unknown channel $chan"
  } else {
    set output [c_unban:unban $chan $nick $handle $masks]
    if { ![botisop $chan] && ![botishalfop $chan] } {
      lappend output "I am not a channel operator on $chan"
      lappend output "Only internal bans will be removed from the internal banlist."
    }
  }
  if { [catch {set x [cnotice $nick $output]} error] || !$x } {
    foreach t $output { puthelp "NOTICE $nick :$t" }
  }
  return 1
}



#unban
proc c_unban:unban { chan nick handle masks } {

  set donei ""
  set donec ""
  set mnbans ""
  set gbans ""
  set numbers ""
  set output ""

#no param, set youngest ban and continue
  if { [string equal $masks ""] } { set masks [lindex [lindex [chanbans $chan] end] 0] }

#numbers find the numbers, sort them, find the bans, and continue
  if { [string is digit [lindex [split $masks] 0]] } {

    foreach mask [split $masks] { if { [string is digit $mask] } { lappend numbers $mask } }
    set chanbans ""
    set ban ""

    foreach ban [chanbans $chan] {
      if { [string equal $chanbans ""] } {
        set chanbans [lindex $ban 0]
      } else {
        set chanbans "[lindex $ban 0] $chanbans"
      }
    }
    set chanbans [split $chanbans]
    set numbers [lsort -decreasing $numbers]
    set masks ""

    foreach num $numbers {
      if { ![string is digit $num] || [string equal $num ""] } { continue }
      incr num -1
      if { ![string equal [lindex $chanbans $num] ""] } {
        set mask [lindex [split [lindex $chanbans $num]] 0]
        lappend masks $mask
      }
    }
    set masks [join $masks]
  }

#check and remove the masks
  foreach mask [split $masks] {

#transform to correct masks
#user@host
    if { [string match ?*@?* $mask] && ![string match ?*!?*@?* $mask] } {
      set mask *!$mask

#host
    } elseif { [string match *.* $mask] && ![string match ?*!?*@?* $mask] } {
      set mask *!*@$mask

#nick!user
    } elseif { [string match ?*!?* $mask] && ![string match ?*!?*@?* $mask] } {
      set mask $mask@*

# #account
  } elseif { [string match \#?* $mask] && ![string match ?*!?*@?* $mask] } {
    set mask *!*@[string range $mask 1 end].$::c_unban(xhost)

#nick
    } elseif { ![string match ?*!?*@?* $mask] } { set mask $mask!*@* }

    if { [isban $mask $chan] } {
      set creator [c_unban:creator $chan $mask]

#ban by +mn, nick is not +mn
      if { ![string equal $creator ""] && [matchattr $creator mn|mn $chan] && ![matchattr $handle mn|mn $chan] } {
        lappend mnbans $mask

#attempt to kill ban
      } elseif { [killchanban $chan $mask] } {
        lappend donei $mask

#ban is on global banlist
      } else {
        lappend gbans $mask
      }
    } elseif { [isban $mask] } {
      lappend gbans $mask
    } elseif { ![isban $mask] && [ischanban $mask $chan] } {
      pushmode $chan -b $mask
      lappend donec $mask
    }
  }

#reply
  set donei [join $donei]; set donec [join $donec]; set gbans [join $gbans]
  if { ![string equal $gbans ""] } { lappend output "Can not remove global bans: $gbans" }
  if { ![string equal $mnbans ""] } { lappend output "Can not remove bans added by masters or owners on $chan: $mnbans" }
  if { ![string equal $donei ""] } { lappend output "Unbanned from internal banlist on $chan: $donei" }
  if { ![string equal $donec ""] } { lappend output "Unbanned from channel banlist on $chan: $donec" }
  if { [string equal $output ""] } { lappend output "Found no bans to remove on $chan" }
  return $output
}



#creator
proc c_unban:creator { chan banmask } {
  if { ![validchan $chan] } { return }
  if { [string equal $banmask ""] } { return }
  foreach ban [banlist $chan] {
    set hostmask [lindex $ban 0]
    set creator [lindex $ban 5]
    if { [string equal -nocase $hostmask $banmask] } {
      if { [validuser $creator] } { return $creator } else { return }
    }
  }
  return
}

