#by wiebe @ QuakeNet

#requires unbind.tcl
#  because eggdrop comes with its own /msg bot help,
#  which overrides this command and all other help commands from these files.



#help help pub
bind pubm fvlomn|fvlomn "% ${botnet-nick} help help" c_help:help:pub

proc c_help:help:pub { nick uhost handle chan text } {
  lappend output "Usage: help \[<command>\]"
  lappend output "Lists all channel commands available to you or shows help for the specified channel command."
  lappend output "Where \002f\002=friend \002v\002=voice \002l\002=halfop \002o\002=op \002m\002=master \002n\002=owner, upper case means global flag. Note: commands available in the channel and in private differ"
  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 help msg
bind msgm fvlomn|fvlomn "help help" c_help:help:msg

proc c_help:help:msg { nick uhost handle text } {
  lappend output "Usage: help \[<command>|<channel>\]"
  lappend output "Lists all private commands available to you, shows help for the specified private command, or lists all channel commands available to you on the given channel."
  lappend output "Where \002f\002=friend \002v\002=voice \002l\002=halfop \002o\002=op \002m\002=master \002n\002=owner, upper case means global flag. Note: commands available in the channel and in private differ."
  if { [catch {set x [cnotice $nick $output]} error] || !$x } {
    foreach t $output { puthelp "NOTICE $nick :$t" }
  }
  putcmdlog "($nick!$uhost) !$handle! $text"
}



#help #chan/&chan
bind msgm fvlomn|fvlomn "help #*" c_help:msg:chan
bind msgm fvlomn|fvlomn "help &*" c_help:msg:chan

proc c_help:msg:chan { nick uhost handle text } {
  set chan [lindex [split $text] 1]
  if { ![validchan $chan] || ![matchattr $handle fvlomn|fvlomn $chan] } {
    lappend output "No access or unknown channel $chan"
    if { [catch {set x [cnotice $nick $output]} error] || !$x } {
      foreach t $output { puthelp "NOTICE $nick :$t" }
    }
  } else {
    c_help:pub $nick $uhost $handle $chan "${::botnet-nick} help"
  }
  putcmdlog "($nick!$uhost) !$handle! $text"
}



#help pub
bind pubm fvlomn|fvlomn "% ${botnet-nick} help" c_help:pub

proc c_help:pub { nick uhost handle chan text } {
  lappend output "Listing channel commands available to you on $chan"
  set gaccess [c_help:getglobalaccess $handle]
  set caccess [c_help:getchanaccess $handle]
  set command(all) ""
  set command(cf) ""
  set command(cv) ""
  set command(cl) ""
  set command(co) ""
  set command(cm) ""
  set command(cn) ""
  set command(gF) ""
  set command(gV) ""
  set command(gL) ""
  set command(gO) ""
  set command(gM) ""
  set command(gN) ""
  set command(rest) ""
  set commands ""

  foreach bind [binds pubm] {
    set type [lindex $bind 0]
    set flags [lindex $bind 1]
    set gflags [lindex [split $flags |] 0]
    set cflags [lindex [split $flags |] 1]
    set trigger [lindex $bind 2]
    set proc [lindex $bind 4]
    set cregexp (\[$cflags\])
    set gregexp (\[$gflags\])
    set trigger2 [lindex [split $trigger] 2]
    set do [lsearch $commands $trigger2]
    if { [string match "% ${::botnet-nick} *" $trigger] && [string match c_*:pub* $proc] && [string equal $do -1] && [string match {[13]} [llength $trigger]] } {
      set trigger $trigger2
      lappend commands $trigger
      if { ![string equal $caccess ""] && [regexp $cregexp $caccess flag flag] } {
        if { ![string equal [lsearch "f v l o m n" $flag] -1] } {
          lappend command(c$flag) $trigger
        } else {
          lappend command(rest) $trigger
        }
      } elseif { ![string equal $gaccess ""] && [regexp $gregexp $gaccess flag flag] } {
        if { ![string equal [lsearch "f v l o m n" $flag] -1] } {
          set flag [string toupper $flag]
          lappend command(g$flag) $trigger
        } else {
          lappend command(rest) $trigger
        }
      } elseif { [string equal $flags -] || [string equal $flags -|-]  } {
        lappend command(all) $trigger
      }
    }
  }

  set allflags "all cf cv cl co cm cn gF gV gL gO gM gN rest"
  foreach allflag [split $allflags] {
    if { ![string equal $command($allflag) ""] } {
      set command($allflag) [lsort $command($allflag)]
      if { [string equal $allflag all] } {
        set prefix \002all\002
      } elseif { [string equal $allflag rest] } {
        set prefix \002rest\002
      } else {
        set prefix \002[string range $allflag 1 1]\002
      }
      lappend output "$prefix: [join $command($allflag)]"
    }
  }

  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 msg
bind msgm fvlomn|fvlomn "help" c_help:msg

proc c_help:msg { nick uhost handle text } {
  set gaccess [c_help:getglobalaccess $handle]
  set caccess [c_help:getchanaccess $handle]
  if { [string length $gaccess] > [string length $caccess] } { set caccess $gaccess }
  set output ""
  set command(all) ""
  set command(cf) ""
  set command(cv) ""
  set command(cl) ""
  set command(co) ""
  set command(cm) ""
  set command(cn) ""
  set command(gF) ""
  set command(gV) ""
  set command(gL) ""
  set command(gO) ""
  set command(gM) ""
  set command(gN) ""
  set command(rest) ""
  set commands ""

#add msgm binds (help, seen, gseen)
  set binds [binds msg]
  lappend binds [binds msgm]
  foreach bind $binds {
    set type [lindex $bind 0]
    set flags [lindex $bind 1]
    set gflags [lindex [split $flags |] 0]
    set cflags [lindex [split $flags |] 1]
    set trigger [lindex $bind 2]
    set proc [lindex $bind 4]
    set cregexp (\[$cflags\])
    set gregexp (\[$gflags\])
    set trigger2 [join [lrange [split $trigger] 0 end]]
    set do [lsearch $commands $trigger2]
    if { ([string match c_*:msg $proc] && [string equal $do -1] && [string equal [llength $trigger2] 1] && [string equal $type msgm]) || [string equal $type msg] } {
      if { [string equal $type msgm] } {
        set trigger $trigger2
        lappend commands $trigger
      }
      if { ![string equal $caccess ""] && [regexp $cregexp $caccess flag flag] } {
        if { ![string equal [lsearch "f v l o m n" $flag] -1] } {
          lappend command(c$flag) $trigger
        } else {
          lappend command(rest) $trigger
        }
      } elseif { ![string equal $gaccess ""] && [regexp $gregexp $gaccess flag flag] } {
        if { ![string equal [lsearch "f v l o m n" $flag] -1] } {
          set flag [string toupper $flag]
          lappend command(g$flag) $trigger
        } else {
          lappend command(rest) $trigger
        }
      } elseif { [string equal $flags -] || [string equal $flags -|-]  } {
        lappend command(all) $trigger
      }
    }
  }

  set allflags "all cf cv cl co cm cn gF gV gL gO gM gN rest"
  foreach allflag [split $allflags] {
    if { ![string equal $command($allflag) ""] } {
      set command($allflag) [lsort $command($allflag)]
      if { [string equal $allflag all] } {
        set prefix \002all\002
      } elseif { [string equal $allflag rest] } {
        set prefix \002rest\002
      } else {
        set prefix \002[string range $allflag 1 1]\002
      }
      lappend output "$prefix: [join $command($allflag)]"
    }
  }

  if { [catch {set x [cnotice $nick $output]} error] || !$x } {
    foreach t $output { puthelp "NOTICE $nick :$t" }
  }
  putcmdlog "($nick!$uhost) !$handle! $text"
}



#return highest flag on any channel
proc c_help:getchanaccess { handle } {
  if { ![validuser $handle] } { return }
  set f 0; set v 0; set l 0; set o 0; set m 0; set n 0
  foreach chan [channels] {
    if { [haschanrec $handle $chan] } {
      set flags [chattr $handle $chan]

#highest possible, return at once
      if { [string match *|*n* $flags] } { return fvlomn
      } elseif { [string match *|*m* $flags] } { set m 1
      } elseif { [string match *|*o* $flags] } { set o 1
      } elseif { [string match *|*l* $flags] } { set l 1
      } elseif { [string match *|*v* $flags] } { set v 1
      } elseif { [string match *|*f* $flags] } { set f 1
      }
    }
  }

#return highest flag found
  if { $m } { return fvlom }
  if { $o } { return fvlo }
  if { $l } { return fvl }
  if { $v } { return fv }
  if { $f } { return f }
}



#return highest global flag
proc c_help:getglobalaccess { handle } {
  if { ![validuser $handle] } { return }
  set flags [chattr $handle]
  if { [string match *n* $flags] } { return fvlomn }
  if { [string match *m* $flags] } { return fvlom }
  if { [string match *o* $flags] } { return fvlo }
  if { [string match *l* $flags] } { return fvl }
  if { [string match *v* $flags] } { return fv }
  if { [string match *f* $flags] } { return f }
}

