####################################################
# by wiebe @ QuakeNet
#
####################################################

####################################################
# user:help:msg
####################################################
bind msgm lomn|lomn "help user" user:help:msgm
proc user:help:msgm { n u h t } {
  if {[matchattr $h bkZ]} { return 0 }
  lappend o "user: usage user add|del|list|info|level|help"
  if {[info procs cnotice] == ""} { foreach l $o { puthelp "NOTICE $n :$l" }
  } else { foreach l $o { cnotice $n $l puthelp "user: " } }
  putcmdlog "($n!$u) !$h! help user"
  return 1
}


####################################################
# user:msg
####################################################
bind msg lomn|lomn user user:msg
proc user:msg { n u h t } {
  if {[matchattr $h bkZ]} { return 0 }
  set t [split $t]; set c [string tolower [lindex $t 0]]; set t [join [lrange $t 1 end]]
  if {$c == "add"} { set o [user:add $h $t]
  } elseif {$c == "del"} { set o [user:del $h $t]
  } elseif {$c == "list"} { set o [user:list $h $t]
  } elseif {$c == "info"} { set o [user:info $h $t]
  } elseif {$c == "level"} { set o [user:level $h $t]
  } elseif {$c == "clean"} { set o [user:clean $h $t]
  } elseif {$c == "help"} { set o [user:help $t]
  } else {
    if {$c != ""} { lappend o "user: unknown subcommand $c" }
    lappend o "user: usage user add|del|list|info|level|clean|help"
  }
  if {[info procs cnotice] == ""} { foreach l $o { puthelp "NOTICE $n :$l" }
  } else { foreach l $o { cnotice $n $l puthelp "user: " } }
  return 1
}


####################################################
# user:dcc
####################################################
bind dcc -|- user user:dcc
proc user:dcc { h i t } {
  set t [split $t]; set c [string tolower [lindex $t 0]]; set t [join [lrange $t 1 end]]
  if {$c == "add"} { set o [user:add $h $t]
  } elseif {$c == "del"} { set o [user:del $h $t]
  } elseif {$c == "list"} { set o [user:list $h $t]
  } elseif {$c == "info"} { set o [user:info $h $t]
  } elseif {$c == "level"} { set o [user:level $h $t]
  } elseif {$c == "clean"} { set o [user:clean $h $t]
  } elseif {$c == "help"} { set o [user:help $t]
  } else {
    if {$c != ""} { lappend o "user: unknown subcommand $c" }
    lappend o "user: usage user add|del|list|info|level|clean|help"
  }
  foreach l $o { putidx $i $l }
  return 1
}


####################################################
# user:add
####################################################
proc user:add { h t } {
  set t [split $t]; set u [lindex $t 0]
  if {[validuser $u]} { set u [getuser $u HANDLE] }
  if {![matchattr $h mn]} { lappend o "user: no access"
  } elseif {$u == ""} { lappend o "user: usage add <user>"
  } elseif {[validuser $u]} { lappend o "user: user '$u' already exists"
  } elseif {![regexp {^[\w\-\_]+$} $u]} { lappend o "user: invalid username $u"
  } else { adduser $u; setuser $u XTRA by $h; lappend o "user: added user '$u' to the bot" }
  return $o
}


####################################################
# user:del
####################################################
proc user:del { h t } {
  set t [split $t]; set u [lindex $t 0]; set c [lindex $t 1]
  if {[validuser $u]} { set u [getuser $u HANDLE] }
  set m [string range [md5 "$h $u"] 0 5]
  set p [lsearch -exact [split [string tolower $::owner]] [string tolower $u]]
  if {$p == -1} { set p 0 } else { set p 1 }
  if {![matchattr $h mn]} { lappend o "user: no access"
  } elseif {$u != ""} { lappend o "user: usage del <user>"
  } elseif {![validuser $u]} { lappend o "user: unknown user $u"
  } elseif {[matchattr $u b]} { lappend o "user: cannot remove bot $u"
  } elseif {![matchattr $h n] && [matchattr $u mn]} {
    lappend o "user: cannot remove master or owner $u"
  } elseif {$p} { lappend o "user: cannot remove permanent owner $u"
  } elseif {$m != $c} {
    lappend o "user: WARNING! this will remove user '$u' from the bot, to confirm this use 'del $u $m'"
  } else { deluser $u; lappend o "user: removed user '$u' from the bot" }
  return $o
}


####################################################
# user:list
####################################################
proc user:list { h t } {
  set t [split $t]; set u [lindex $t 0]; set f [lindex $t 1]; set r ""
  if {![matchattr $h mn]} { lappend o "user: no access"
  } elseif {$u == ""} {
    lappend o "user: usage list <user> \[\[globalflags\]\{&/|\}\[chanflags\]\{&/|\}\[botflags\]\]"
  } else {
    if {$f == ""} { set x [userlist]; set f "any" } else { set x [userlist $f] }
    regsub -all {[][\\]} $u {\\\0} v
    foreach y $x { if {[string match -nocase $v $y]} { lappend r $y } }
    if {$r != ""} { lappend o "user: found [llength $r] users: [join $r "   "]"
    } else { lappend o "user: no users found matching '$u' with flags $f" }
  }
  return $o
}


####################################################
# user:clean
####################################################
proc user:clean { h t } {
  if {![matchattr $h mn]} { lappend o "user: no access"
  } else {
    set t [clock seconds]; set r ""
    foreach u [userlist] {
      if {[matchattr $u b]} { continue }
      set s [lindex [split [getuser $u LASTON]] 0]
      if {$s == ""} { set s [getuser $u XTRA created] }
      if {$s == ""} { set s 0 }
      if {[expr $t - $s] < 6912000} { continue }
      if {[handonchan $u]} { continue }
      if {[hand2idx $u] != -1} { continue }
      lappend r $u
    }
    if {$r != ""} {
      set c [llength $r]; set r [join $r "   "]
      lappend o "user: $c users that have not been seen in the past 80 days: $r"
    } else { lappend o "user: no users found that have not been seen in the past 80 days" }
  }
  return $o
}


####################################################
# user:level
####################################################
proc user:level { h t } {
  set t [split $t]; set u [lindex $t 0]; set f [lindex $t 1]
  if {[validuser $u]} { set u [getuser $u HANDLE] }
  if {![matchattr $h n]} { lappend o "user: no access"
  } elseif {$u == "" || $f == ""} {
    lappend o "user: level <user> <flags>"
  } elseif {![validuser $u]} { lappend o "user: unknown user $u"
  } elseif {![regexp {^[+-][adfgklmnopqruvyA-Z\-\+]+$} $f]} {
    lappend o "user: invalid flag specified, valid flags are a, c-z and A-Z"
    lappend o "user: valid flags are:   a=auto-op   b=bot   d=deny-op   f=friend   g=auto-voice   k=auto-ban   l=halfop   m=master   n=owner   o=op   p=party-line   q=deny-voice   r=deny-halfop   u=unshared   v=voice   y=auto-halfop"
    if {[info procs userflag:get] != ""} { set r [userflag:get]; if {$r != ""} { lappend o $r] } }
  } else {
    set f [chattr $u $f]
    if {$f == ""} { set f "<none>" } else { set f "'+$f'" }
    lappend o "user: global flags for user '$u' are now $f"
  }
  return $o
}


####################################################
# user:info
####################################################
proc user:info { h t } {
  set t [split $t]; set n [lindex $t 0]; set p 0
  if {![matchattr $h omn] && [onchan $n]} {
    foreach c [channels] {
      if {![onchan $n $c]} { continue }
      if {![matchattr $h lomn|lomn $c]} { continue }
      set p 1; break
    }
  }
  if {$n == ""} { lappend o "user: usage info <nick>"
  } elseif {[matchattr $h omn] && ![onchan $n]} {
    lappend o "user: user '$n' is not on any of my channels"
  } elseif {![matchattr $h omn] && (![onchan $n] || !$p)} {
    lappend o "user: no access or unknown nick $n"
  } else {
    lappend r "handle=[nick2hand $n]"; lappend r "userhost=[getchanhost $n]"
    if {[info procs dnsdb:get] != ""} {
      set a [dnsdb:get $n h]; if {$a != ""} { lappend r "realhost=$a" }
      set a [dnsdb:get $n i]; if {$a != ""} { lappend r "IP=$a" }
    }
    if {[info procs whox:get] != ""} { set a [whox:get $n all]; if {$a != ""} { lappend r "WHOX=$a" } }
    lappend o "user: info for $n: [join $r "   "]"
  }
  return $o
}


####################################################
# user:help
####################################################
proc user:help { t } {
  set c [string tolower [lindex [split $t] 0]]
  if {$c == "add"} {
    lappend o "user: add <user>"
    lappend o "user: creates a user record on the bot"
  } elseif {$c == "del"} {
    lappend o "user: del <user>"
    lappend o "user: deletes a user record from the bot"
  } elseif {$c == "list"} {
    lappend o "user: list <user> \[\[globalflags\]\{&/|\}\[chanflags\]\{&/|\}\[botflags\]"
    lappend o "user: where <user> can contain wildcards, the & means AND and the | means OR"
  } elseif {$c == "info"} {
    lappend o "user: <nick>"
    lappend o "user: shows available info for nick (user@host, hostname, IP and WHOX)"
  } elseif {$c == "level"} {
    lappend o "user: level <user> <flags>"
    lappend o "user: changes a user's global flags"
  } elseif {$c == "clean"} {
    lappend o "user: clean"
    lappend o "user: shows users that have not been seen in the past 40 days"
  } else {
    lappend o "user: usage help add|del|list|info|level|clean"
    lappend o "user: shows help in general or for the given subcommand"
  }
  return $o
}


####################################################
# user:time
####################################################
bind time -|- "00 06 * * *" user:time
proc user:time { n h d m y } {
  set t [clock seconds]
  foreach u [userlist] {
    set s [lindex [split [getuser $u LASTON]] 0]
    if {$s == ""} { set s [getuser $u XTRA created] }
    if {$s == ""} { setuser $u XTRA created $t; continue }
    if {[expr $t - $s] < 3456000} { continue }
    if {[handonchan $u]} { continue }
    if {[hand2idx $u] != -1} { continue }
    if {[string match {*[a-z]*} [chattr $u]]} { continue }
    if {[user:chan $u]} { continue }
    putlog "user: deleting user $u (has no flags and has not been seen in over 80 days)"
    deluser $u
  }
}


####################################################
# user:chan
####################################################
proc user:chan { u } {
  if {![validuser $u]} { return 0 }
  foreach c [channels] { if {![string match "*|-" [chattr $u "" $c]]} { return 1 } }
  return 0
}


set ::scriptdb(user) {
  "provides user command for adding/deleting user records, viewing user info collected by other scripts, listing users"
}

