# Random commands for sbnc
# Copyright (C) 2008 Khobbits
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

###############################################################################
############## You shouldn't NEED to edit anything in this file. ##############
### I don't recall where but the showusers command I stole from somewhere. ####
#### su's tag/settag doesnt list applicable tags, just gives suggestions. #####
###############################################################################

internalbind command kh:com

proc kh:com {client parameters} {

	set command [lindex $parameters 0]

	if {[string equal -nocase $command "help"]} {
		if {[getbncuser $client admin]} {
			set help "Syntax: su <user> <command> \[values/params\]\n
				Commands:
				raw <params> - sends the raw text to the server
				disconnect - disconnects user
				reconnect - reconnects user if disconnected
				jump - reconnect user
				set <setting> <value> - sets a user setting - see note below
				value <setting> - returns a user setting - see note below
				settag <setting> <value> - sets a 'tag' setting on a user - see note below
				tag <setting> - returns a 'tag' setting on user - see note below
				log - plays users log file
				eraselog - erases their user log
				addhost <value> - adds an connection host
				delhost <value> - removes a connection host
				clearhosts - wipes connection host list
				hosts - shows connection host list
				traffic - displays user traffic
				Values: connected (to server), onbnc, nick, seen, network, channels, uptimehr
				Channnel values: chanmode <chan>, topic <chan>, chanlist <chan>, usercount <chan>
				Note: set/value/settag/tag have specific sets of settings, to view these lists use the command without leaving setting null."

			bncaddcommand "showusers" "KHAdmin" "Shows the currently connected user counts"
			bncaddcommand "su" "KHAdmin" "Admin overide commands" $help
			bncaddcommand "msu" "KHAdmin" "Performs a mass su on all accounts" "Syntax: msu <command> \[values/params\]\nThis command has the same syntax and commands as su, except it will automatically replace the user feild, so skip it.\nUse /sbnc help su for a command list."
			bncaddcommand "msimul" "KHAdmin" "Makes all clients do the command" "Syntax msu <commands to perform>\nThis command does runs a simul command for all users at once.  Support for: \$me \$ip \$user \$1-5 vars"
			bncaddcommand "lastused" "KHAdmin" "Shows a list of last used times"
			bncaddcommand "usingvhost" "KHAdmin" "Shows a list of users using a specific vhost (ip)"
		} elseif {[getbncuser $client tag reseller] == "1"} {
			bncaddcommand "showusers" "KHAdmin" "Shows the currently connected user counts"
			bncaddcommand "lastused" "KHAdmin" "Shows a list of last used times"
			bncaddcommand "disconnect" "KHUser" "Disconnects from server"
		} else {
			bncaddcommand "disconnect" "KHUser" "Disconnects from server"
		}
		bncaddcommand "uptime" "KHUser" "Shows current connection length"
		bncaddcommand "traffic" "KHUser" "Shows user traffic"
	}

	if {[getbncuser $client admin]} {
		if {[string equal -nocase $command "msimul"]} { khz:msimul $client $parameters }
		if {[string equal -nocase $command "showusers"]} { khz:showusers $client $parameters }
		if {[string equal -nocase $command "su"]} { khz:su $client $parameters }
		if {[string equal -nocase $command "msu"]} { khz:msu $client $parameters }
		if {[string equal -nocase $command "lastused"]} { khz:lastused $client $parameters }
		if {[string equal -nocase $command "usingvhost"]} { khz:usingvhost $client $parameters }
		if {[string equal -nocase $command "simul"]} { admin:log $client "Simul'd [lindex $parameters 1]: [lrange $parameters 2 4]..." }
	} elseif {[getbncuser $client tag reseller] == "1"} {
		if {[string equal -nocase $command "showusers"]} { khz:showusers $client $parameters }
		if {[string equal -nocase $command "lastused"]} { khz:lastused $client $parameters }
		if {[string equal -nocase $command "disconnect"]} { bncdisconnect $client; haltoutput; }
	} else {
		if {[string equal -nocase $command "disconnect"]} { bncdisconnect $client; haltoutput; }
	}
	if {[string equal -nocase $command "eggdcc"]} { fakedcc $client $parameters }
	if {[string equal -nocase $command "uptime"]} { bncreply "User uptime: [duration [getbncuser $client uptime]]"; haltoutput; }
	if {[string equal -nocase $command "traffic"]} { bncreply "User traffic: Server in: [trafficstats $client server in]Bytes Server out: [trafficstats $client server out]Bytes Client in: [trafficstats $client client in]Bytes Client out: [trafficstats $client client out]Bytes"; haltoutput; }
}

proc khz:msimul {client arg} {
	foreach user [bncuserlist] {
		setctx $user
		set msg [string map [list \$me [getcurrentnick] \$ip [getbncuser $user vhost] \$user $user \$1 [lindex [split $arg] 1] \$2 [lindex [split $arg] 2] \$3 [lindex [split $arg] 3] \$4 [lindex [split $arg] 4] \$5 [lindex [split $arg] 5]] $arg]
		puthelp "[join [lrange $msg 1 end]]"
	}
	admin:log $client "Used msimul: $arg"
	haltoutput
	return
}

proc khz:usingvhost {client parameters} {
	if {[lindex $parameters 1] == ""} {
		bncreply "Syntax: usingbhost <ip>"
		haltouput
		return
	}
	bncreply "Using vhost '[lindex $parameters 1]':"
	foreach x [bncuserlist] {
		if { [getbncuser $x vhost] == [lindex $parameters 1] } {
			bncreply $x
		}
	}
    haltoutput
  return
}

proc khz:showusers {client parameters} {
    variable ctx [getctx]
    variable online 0 connected 0 suspended 0 unknown 0
    array set networks {}

    foreach user [bncuserlist] {
      setctx $user
      if { [getbncuser $user hasclient] } {
        incr online
      }

      if { [getbncuser $user hasserver] } {
        incr connected
        set un [getisupport NETWORK]
        if { $un eq "" } {
          incr unknown
          continue
        }
        if { ![info exists networks($un)] } {
          set networks($un) 1
        } else {
          incr networks($un)
        }
      }
      if { ([getbncuser $user lock] eq "1") } {
        incr suspended
      }
    }

    setctx $ctx
    bncreply "Total current user count: [llength [bncuserlist]], logged on: $online, connected to IRC: $connected, suspended: $suspended."
    set result [list]
    foreach name [array names networks] {
      lappend result "$networks($name) on $name"
    }
    if { $unknown ne "0" } {
      lappend result "$unknown on unknown networks"
    }
    bncreply [join $result {, }]
    haltoutput
  return
}

proc khz:lastused {client parameters} {
	set y [lindex $parameters 1]
	if {[catch {expr int($y)}]} { set y -1 }
	if ([getbncuser $client admin]) {
		foreach x [bncuserlist] {
			if { [getbncuser $x seen] != 0 } {
				if { [expr ( [clock seconds] - [getbncuser $x seen] ) /86400.0 ] > $y } {
						bncreply "$x last logged in [duration [expr [clock seconds] - [getbncuser $x seen]]]days ago"
				}
			} else {
				bncreply "$x has never logged in"
			}
		}
	} elseif {[getbncuser $client tag reseller] == "1"} {
		foreach x [bncuserlist] {
			if {[string equal -nocase [virtual:getgroup $x] [virtual:getgroup $client]]} {
				if { [getbncuser $x seen] != 0 } {
					if { [expr ( [clock seconds] - [getbncuser $x seen] ) /86400.0 ] > $y } {
							bncreply "$x last logged in [duration [expr [clock seconds] - [getbncuser $x seen]]]days ago"
					}
				} else {
					bncreply "$x has never logged in"
				}
			}
		}
	}
	haltoutput
  return
}

proc khz:msu {client arg} {
	foreach user [bncuserlist] {
		khz:su $client "su $user [join [lrange $arg 1 end]]"
	}
	haltoutput
	return
}

proc khz:su {client parameters} {

		catch {su [join [lrange $parameters 1 end]]} result

		if {$result == ""} { set result "<null>" }
		foreach sline [split $result \n] {
			bncreply "$sline"
		}
		haltoutput
	return
}

proc su {parameters} {
	variable ctx [getctx]

	set user [lindex $parameters 0]

	catch {lsearch -inline -regex [bncuserlist] "(?i)^${user}$"} result
	if {$result != ""} {
		set user $result
	} else {
		return "No such user. Syntax: su <user> <command> \[values/params\]. see /sbnc help su for more information."
	}

	set command [lindex $parameters 1]
	set params [join [lrange $parameters 2 end]]
	setctx $user
	set result ""
	switch -- $command {
		raw {
			puthelp [join $params]
			set result "RAW: [join $params]"
		}
		disconnect {
			bncdisconnect [join [lrange $params 0 end]]
			set result "Disconnecting for \"[join [lrange $params 0 end]]\""
		}
		reconnect {
			if {![getbncuser $user hasserver]} {
				jump
				set result "Reconnecting!"
			} else {
				set result "Connected to server..."
			}
		}
		connected {
			if {![getbncuser $user hasserver]} {
				set result "Not connected to irc server."
			} else {
				set result "Connected to irc server."
			}
		}
		onbnc {
			if {![getbncuser $user hasclient]} {
				set result "Not connected to bnc."
			} else {
				set result "Connected to bnc."
			}
		}
		nick {
			set result $::botnick
		}
		value {
			if {[lsearch -exact [list server port serverpass client realname nick awaynick away uptime lock admin hasserver hasclient vhost channels tag delayjoin seen appendts quitasaway automodes dropmodes suspendreason sslclient realserver ident] [lindex $params 0]] == -1} {
				set result "Not a valid setting. Settings: server port serverpass client realname nick awaynick away uptime lock admin hasserver hasclient vhost channels tag delayjoin seen appendts quitasaway automodes dropmodes suspendreason sslclient realserver ident"
			} else {
				set result [getbncuser $user [lindex $params 0]]
			}
		}
		tag {
			if {[lindex $params 0] == ""} {
				set result "Seems you didnt supply a tag, try: nickserv.nick nickserv.reply nickserv.warning amsg_enable amsg_channel amsg_counter awaymessage"
			} else {
				set result [getbncuser $user tag [lindex $params 0]]
			}
		}
		settag {
			if {[lindex $params 0] == ""} {
				set result "Seems you didnt supply a tag, try: nickserv.nick nickserv.password nickserv.reply nickserv.warning amsg_enable amsg_channel amsg_counter awaymessage"
			} else {
				setbncuser $user tag [lindex $params 0] [join [lrange $params 1 end]]
				set result 1
			}
		}
		network {
			set result [getisupport NETWORK]
		}
		channels {
			set result [join [internalchannels]]
		}
		uptimehr {
			set result [duration [getbncuser $user uptime]]
		}
		traffic {
			set result "Server in: [trafficstats $user server in]Bytes Server out: [trafficstats $user server out]Bytes Client in: [trafficstats $user client in]Bytes Client out: [trafficstats $user client out]Bytes"
		}
		chanmode {
			set result [getchanmode [lindex $params 0]]
		}
		topic {
			set result [topic [lindex $params 0]]
		}
		chanlist {
			set result [join [internalchanlist [lindex $params 0]]]
		}
		usercount {
			set result [llength [internalchanlist [lindex $params 0]]]
		}
		jump {
			jump
			set result "Jumping!"
		}
		set {
			if {[lsearch -exact [list server port serverpass realname nick awaynick away lock admin channels tag vhost delayjoin password appendts quitasaway automodes dropmodes suspendreason ident] [lindex $params 0]] == -1} {
				set result "Not a valid setting. Settings: server port serverpass realname nick awaynick away lock admin channels tag vhost delayjoin password appendts quitasaway automodes dropmodes suspendreason ident"
			} else {
				setbncuser $user [lindex $params 0] [join [lrange $params 1 end]]
				set result 1
			}
		}
		log {
			set error [catch "open users/$user.log r" file]
			if {$error} {
				set result "Log could not be opened (user is case sensitive)"
			} else {
				set stuff [read $file]
				close $file
				set result "${stuff}\nsu $user $command - Log end."
			}
		}
		eraselog {
			set file [open users/$user.log w+]
			close $file
		}
		addhost {
			if {[addbnchost [lindex $params 0]] == 1} {
				set result "Added host [lindex $params 0]"
			} else {
				set result "Failed to add host [lindex $params 0]"
			}
		}
		delhost {
			delbnchost [lindex $params 0]
			set result "Deleted host [lindex $params 0]"
		}
		clearhosts {
			set hostclear [getbnchosts]
			foreach hosts [getbnchosts] {
				delbnchost $hosts

			}
			set result "Cleared hosts: $hostclear"
		}
		hosts {
			set result [join [getbnchosts]]
		}
		seen {
			set result "Time since last login: [duration [expr [clock seconds] - [getbncuser $user seen]]]"
		}
		default {
		set result "Syntax: su <user> <command> \[values/params\]
		/sbnc help su for more information and a list of valid commands."
		}
	}
	admin:log $ctx "Used su $user $command - [lrange [split $result] 0 3]..."
	setctx $ctx
	return "su $user $command - $result"
}

proc admin:log {client text} {
	foreach x [bncuserlist] {
		if {[getbncuser $x admin]} {
		setctx $x
			if {[getbncuser $x hasclient]} {
				putclient ":-sBNC!core@shroudbnc.org PRIVMSG $x :\[Admin log\] $client: $text"
			}
			putlog "\[Admin log\] $client: $text"
		}
	}
}

proc fakedcc {client text} {
	global botnick
	if {[llength $text] < 4} {
		bncreply "This command lets you fake DCC incoming headers.  Party will be informed via /ctcp <target> chat"
		bncreply "Syntax: <nick> [address] <longip> <port>"
	}
	if {[llength $text] == 4} {
		set text [linsert $text 2 "a@b.c"]
	}
	putserv "privmsg [lindex $text 1] \001chat\001"
	putclient "\:[lindex $text 1]![lindex $text 2] PRIVMSG $botnick \:\001DCC CHAT chat [lindex $text 3] [lindex $text 4]\001"
	haltoutput
	return 0
}