#by wiebe @ Quakenet



#help mode pub
bind pubm omn|omn "% ${botnet-nick} help mode" c_mode:help:pub

proc c_mode:help:pub { nick uhost handle chan text } {
  lappend output "Usage: mode <modes> \[<params>\]"
  lappend output "Changes modes on the channel, modes b v h o are ignored."
  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 mode msg
bind msgm omn|omn "help mode" c_mode:help:msg

proc c_mode:help:msg { nick uhost handle text } {
  lappend output "Usage: mode <channel> <modes> \[<params>\]"
  lappend output "Changes modes on the channel given, modes b v h o are ignored."
  if { [catch {set x [cnotice $nick $output]} error] || !$x } {
    foreach t $output { puthelp "NOTICE $nick :$t" }
  }
  putcmdlog "($nick!$uhost) !$handle! $text"
}



#mode pub
bind pubm omn|omn "% ${botnet-nick} mode" c_mode:pub
bind pubm omn|omn "% ${botnet-nick} mode *" c_mode:pub

proc c_mode:pub { nick uhost handle chan text } {
  set mode [join [lrange [split $text] 2 end]]
  if { ![botisop $chan] && ![botishalfop $chan] } {
    lappend output "I am not a channel operator on $chan"
  } elseif { ![string equal $mode ""] } {
    c_mode:parse $chan $mode
    lappend output "Parsed modes $mode on $chan"
  } else {
    lappend output "Usage: mode <channel> <modes> \[<params>\] (modes bvho will be ignored)"
  }
  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]]"
}



#mode msg
bind msg omn|omn mode c_mode:msg

proc c_mode:msg { nick uhost handle text } {
  set chan [lindex [split $text] 0]
  set mode [join [lrange [split $text] 1 end]]
  if { ![validchan $chan] && ![string equal $chan ""] } {
    lappend output "No access or unknown channel $chan"
  } elseif { [string equal $chan ""] || [string equal $mode ""] } {
    lappend output "Usage: mode <channel> <modes> \[<params>\] (modes bvho will be ignored)"
  } elseif { ![matchattr $handle lomn|lomn $chan] } {
    lappend output "No access or unknown channel $chan"
  } elseif { ![botisop $chan] && ![botishalfop $chan] } {
    lappend output "I am not a channel operator on $chan"  } else {
    c_mode:parse $chan $mode
    lappend output "Parsed modes $mode on $chan"
  }
  if { [catch {set x [cnotice $nick $output]} error] || !$x } {
    foreach t $output { puthelp "NOTICE $nick :$t" }
  }
  return 1
}



#parse modes
#disallow bvho modes, allow klimnpstrDcCNu
#only parse "modes param", not "mode param mode param etc" (ircu does support this)
proc c_mode:parse { chan mode } {
  set params [join [lrange [split $mode] 1 end]]
  set mode [lindex [split $mode] 0]
  set status "+"
  foreach m [split $mode ""] {
    if { [string equal + $m] || [string equal - $m] } {
      set status $m
    } elseif { [string match {[bvho]} $m] } {
      set params [join [lrange [split $params] 1 end]]
    } elseif { [string equal $m k] } {
      set newkey [lindex [split $params] 0]
      set params [join [lrange [split $params] 1 end]]
#-k
      if { [string equal $status -] } {

#key given
        if { ![string equal $newkey ""] } {
          pushmode $chan $status$m $newkey
#find key
        } elseif { [string match *k* [lindex [split [getchanmode $chan]] 0]] } {
          set k 1
          foreach n [split [lindex [split [getchanmode $chan]] 0] ""] {
            if { [string equal $n k] } { break }
            if { [string equal $n l] } { incr k 1 }
          }
          set oldkey [lindex [split [getchanmode $chan]] $k]
          pushmode $chan -k $oldkey
        }

#+k
      } else {
        if { [string match *k* [lindex [split [getchanmode $chan]] 0]] } {
          set k 1
          foreach n [split [lindex [split [getchanmode $chan]] 0] ""] {
            if { [string equal $n k] } { break }
            if { [string equal $n l] } { incr k 1 }
          }
          set oldkey [lindex [split [getchanmode $chan]] $k]
          pushmode $chan -k $oldkey
        }
        pushmode $chan $status$m $newkey
      }

#limit
    } elseif { [string equal $m l] } {
      if { [string equal $status -] } {
        pushmode $chan $status$m
      } else {
        set limit [lindex [split $params] 0]
        set params [join [lrange [split $params] 1 end]]
        if { [string equal $status -] || (![string equal $limit ""] && [string is digit $limit] && $limit > "0") } {
          pushmode $chan $status$m
        }
      }

#other modes
    } elseif { [string match {[imnpstrDcCNu]} $m] } {
      pushmode $chan $status$m
    }
  }
}

