#by wiebe @ QuakeNet



#help chanlev msg
bind msgm fvlomn|fvlomn "help chanlev" c_chanlev:help:msg

proc c_chanlev:help:msg { nick uhost handle text } {
  lappend output "Usage: chanlev <channel> \[<nick>|<#account> \[<flags>\]\]"
  lappend output "To view the chanlev list for the channel, to view the flags for nick/#account on the channel, or to change flags for the user on the channel given. A +v|l|o user can change +g|y|a flags on himself without needing +m."
  lappend output "\002a\002=auto-op \002d\002=deny-op \002f\002=friend \002g\002=auto-voice \002k\002=auto-kickban \002l\002=halfop \002m\002=master \002n\002=owner \002o\002=op \002q\002=deny-voice \002r\002=deny-halfop \002v\002=voice \002y\002=auto-halfop"
  if { [catch {set x [cnotice $nick $output]} error] || !$x } {
    foreach t $output { puthelp "NOTICE $nick :$t" }
  }
  putcmdlog "($nick!$uhost) !$handle! $text"
}



#chanlev msg
bind msg fvlomn|fvlomn chanlev c_chanlev:msg

proc c_chanlev:msg { nick uhost handle text } {

  set chan [lindex [split $text] 0]
  set target [lindex [split $text] 1]
  set flags [lindex [split $text] 2]
  set accountgiven 0
  if { [string match \#* $target] } {
    set account [string range $target 1 end]
    set accountgiven 1
  } else {
    set account [nick2hand $target]
    if { [string equal $account *] } { set account "" }
  }
  if { !$accountgiven } { set accountshow "$target ($account)" } else { set accountshow $account }

#always require a channel param
  if { [string equal $chan ""] } {
    lappend output "Usage: chanlev <channel> \[<nick>|<#account> \[<flags>\]\]"

#unknown channel or no access
  } elseif { ![validchan $chan] || ![matchattr $handle fvlomn|fvlomn $chan] } {
    lappend output "No access or unknown channel $chan"

#show chanlev list
  } elseif { [string equal $target ""] } {
    lappend output "Listing chanlev for $chan"
    set result 0
    set total 0
    set owner 0
    set master 0
    set op 0
    set halfop 0
    set voice 0
    set friend 0
    set kickban 0
    set rest 0
    foreach user [lsort [userlist]] {
      if { [haschanrec $user $chan] } {
        set flags [lindex [split [chattr $user $chan] |] 1]
        if { ![string equal $flags -] } {
          set result 1

          incr total 1
          if { [string match *n* $flags] } { incr owner 1
          } elseif { [string match *m* $flags] } { incr master 1
          } elseif { [string match *o* $flags] } { incr op 1
          } elseif { [string match *l* $flags] } { incr halfop 1
          } elseif { [string match *v* $flags] } { incr voice 1
          } elseif { [string match *f* $flags] } { incr friend 1
          } elseif { [string match *k* $flags] } { incr kickban 1
          } else { incr rest 1 }

          set space1 [string repeat " " [expr 20 - [string length $user]]]
          set laston [getuser $user LASTON $chan]
          if { [string equal $laston 0] } { set laston "" }
          set lastondate ""
          if { ![string equal $laston ""] } { set lastondate [clock format $laston -format %d/%m/%y] }
          set date [clock format [unixtime] -format %d/%m/%y]
          if { [handonchan $user $chan] } {
            set laston "on channel"
          } elseif { [string equal $lastondate $date] } {
            set ago "[c_chanlev:ts $laston] ago"
            set laston "[clock format $laston -format %H:%M]"
            set ago "[string repeat " " [expr 23 - [string length $ago] - [string length $laston]]] $ago"
            set laston $laston$ago
          } elseif { ![string equal $laston ""] } {
            set ago "[c_chanlev:ts $laston] ago"
            set laston "[clock format $laston -format %d/%m/%y]"
            set ago "[string repeat " " [expr 23 - [string length $ago] - [string length $laston]]] $ago"
            set laston $laston$ago
          } else {
            set laston never
          }
          set space2 [string repeat " " [expr 15 - [string length $flags]]]
          lappend output "$user$space1$flags$space2$laston"

        } else {
          delchanrec $user $chan
        }
      }
    }
    if { !$result } {
      lappend output "No users known on $chan"
    } else {
      lappend output "Total: $total (owner: $owner, master: $master, op: $op, halfop: $halfop, voice: $voice, friend: $friend, kickban: $kickban, rest: $rest)"
      lappend output "End of chanlev list for $chan"
    }

#error nick is unknown, or unknown account
  } elseif { ![validuser $account] && ![string equal $target ""] } {
    if { $accountgiven } {
      lappend output "Account $account is not known."
    } else {
      lappend output "$target is not known."
    }

#account exists, no flags given
  } elseif { [string equal $flags ""] } {
    set flags [lindex [split [chattr $account $chan] |] 1]
    if { ![string equal $flags -] } {
      set laston [getuser $account LASTON $chan]
      if { [string equal $laston 0] } { set laston "" }
      set lastondate ""
      if { ![string equal $laston ""] } { set lastondate [clock format $laston -format %d/%m/%y] }
      set date [clock format [unixtime] -format %d/%m/%y]
      if { [handonchan $account $chan] } {
        set laston "currently on channel"
      } elseif { [string equal $lastondate $date] } {
        set ago "[c_chanlev:ts $laston] ago"
        set laston "last seen [clock format $laston -format %H:%M]     $ago"
      } elseif { ![string equal $laston ""] } {
        set ago "[c_chanlev:ts $laston] ago"
        set laston "last seen [clock format $laston -format %d/%m/%y]      $ago"
      } else {
        set laston never
      }
      lappend output "$accountshow has flags $flags on $chan      $laston"
    } else {
      lappend output "$accountshow is not known on $chan"
    }

#nick tries to change flags for himself and isnt mn
  } elseif { [string equal $handle $account] && ![matchattr $handle mn|mn $chan] } {
    if { ![matchattr $handle -|vlo $chan] } {
      lappend output "You can not change flags on yourself."
    } else {
      set allow ""
      if { [matchattr $handle -|v $chan] } { set allow g }
      if { [matchattr $handle -|l $chan] } { set allow gy }
      if { [matchattr $handle -|o $chan] } { set allow gya }
      set regexp ^\[^-+\]|\[^-+$allow\]
      if { ![regexp $regexp $flags] && ![string equal $allow ""] } {
        set flags [lindex [split [chattr $handle |$flags $chan] |] 1]
        lappend output "Your flags on $chan are now $flags"
      } else {
        lappend output "You can only change flags $allow on yourself on $chan"
      }
    }

#tries to change flags for other user but isnt mn|mn
  } elseif { ![matchattr $handle mn|mn $chan] } {
    lappend output "You are not a master or owner on $chan"

#nick +m tries to change flags for a +mn target
  } elseif { ![matchattr $handle n|n $chan] && [matchattr $account mn|mn $chan] } {
    lappend output "You can not change flags on other masters or owners on $chan"

#tries to change mn flags, but isnt owner
  } elseif { ([string match *m* $flags] || [string match *n* $flags]) && ![matchattr $handle n|n $chan] } {
    lappend output "You must be an owner to change master or owner flags on $chan"

#tries to set +n with other flags, target not +n
  } elseif { [regexp {\+[^-]*n} $flags] && ![string equal $flags +n] && ![matchattr $account -|n $chan] } {

    lappend output "You are about to make $accountshow an owner on $chan, if you are sure you want this use:"
    lappend output "/msg $::botnick chanlev $chan $target +n"

#other flags, invalid
  } elseif { [regexp {^[^-+]|[^-+adfgklmnoqrvyA-Z]} $flags] } {
    lappend output "Invalid flags specified, see '/msg $::botnick help chanlev' for a list of valid flags."

#do it
  } else {
    set flags [lindex [split [chattr $account |$flags $chan] |] 1]
    if { [string equal $flags -] } {
      lappend output "$accountshow now has no flags on $chan"
    } else {
      lappend output "Flags for account $accountshow on $chan are now $flags"
    }
  }

  if { [catch {set x [cnotice $nick $output]} error] || !$x } {
    foreach t $output { puthelp "NOTICE $nick :$t" }
  }
  return 1
}



#give timestamp, returns duration since/to in Xy Xw Xd Xh Xm Xs format
proc c_chanlev:ts { ts } {
  if { ![string is digit $ts] } { return 0 }
  if { $ts > [unixtime] } {
    set ts [duration [expr $ts - [unixtime]]]
  } else {
    set ts [duration [expr [unixtime] - $ts]]
  }
  set ts [string map [list " seconds" "s" "search" "replace" "search" "replace"] $ts]
  set ts [string map [list " second" "s" "search" "replace" "search" "replace"] $ts]
  set ts [string map [list " minutes" "m" "search" "replace" "search" "replace"] $ts]
  set ts [string map [list " minute" "m" "search" "replace" "search" "replace"] $ts]
  set ts [string map [list " hours" "h" "search" "replace" "search" "replace"] $ts]
  set ts [string map [list " hour" "h" "search" "replace" "search" "replace"] $ts]
  set ts [string map [list " days" "d" "search" "replace" "search" "replace"] $ts]
  set ts [string map [list " day" "d" "search" "replace" "search" "replace"] $ts]
  set ts [string map [list " weeks" "w" "search" "replace" "search" "replace"] $ts]
  set ts [string map [list " week" "w" "search" "replace" "search" "replace"] $ts]
  set ts [string map [list " years" "y" "search" "replace" "search" "replace"] $ts]
  set ts [string map [list " year" "y" "search" "replace" "search" "replace"] $ts]
  return [join [lrange [split $ts] 0 1] " "]
}

