############################
### HostSpy.tcl		 ###
### Version 1.7 	 ###
### By Wcc		 ###
### wcc@techmonkeys.org  ###
### http://dawg.dynu.com ###
### EFnet #|DAWG|Tcl     ###
############################

############################################################################
### Copyright © 2000 - 2001 |DAWG| Scripting Group. All rights reserved. ###
############################################################################

####################################################################
### Do not release this script without permission of the author. ###
####################################################################

#####################################################################
## This script logs all events from a host to a file. When used on ##
## DALNet or another network that supports WATCH, you can use the  ##
## .hostspy watch command to monitor when a user logs on or off of ##
## the irc server.						   ##
#####################################################################

##############
## COMMANDS ##
##################################################
## DCC ## .hostspy <command> (Can be changed)	##
######### See .hostspy help for a command list.	##
##################################################

#############################################################
## Just load the script, set the variables, and rehash.    ##
#############################################################

#################################################
# Set the folder to store logfiles in here.	#
# (This directory must exist.)			#
#################################################

set hostspy_setting(logdir) "./hostspy/"

#########################################################
# Set the main dcc command for using the script here.	#
#########################################################

set hostspy_setting(cmd) "hostspy"

####################################################
# Set the flag required for using the script here. #
####################################################

set hostspy_setting(flag) "+H"

###################################
# Enable use of bold in DCC chat? #
###################################

set hostspy_setting(bold) 1

###########################################
# Prefix "HOSTSPY:" in DCC chat messages? #
###########################################

set hostspy_setting(HOSTSPY:) 1

####################
# Code begins here #
####################

if {![string match 1.6.* $version]} {
	putlog "\002HOSTSPY:\002 \002CRITICAL ERROR\002 HostSpy.tcl requires eggdrop 1.6.x to run."
	die "\002HOSTSPY:\002 \002CRITICAL ERROR\002 HostSpy.tcl requires eggdrop 1.6.x to run."
}
if {[info tclversion] < 8.2} {
	putlog "\002HOSTSPY:\002 \002CRITICAL ERROR\002 HostSpy.tcl requires TCL 8.2 or above to run."
	die "\002HOSTSPY:\002 \002CRITICAL ERROR\002 HostSpy.tcl requires TCL 8.2 or above to run."
}
bind msgm - * hostspy_msg_chk
bind pubm - * hostspy_pub_chk
bind notc - * hostspy_notc_chk
bind join - * hostspy_join_chk
bind part - * hostspy_part_chk
bind sign - * hostspy_sign_chk
bind topc - * hostspy_topc_chk
bind kick - * hostspy_kick_chk
bind nick - * hostspy_nick_chk
bind mode - * hostspy_mode_chk
bind ctcp - * hostspy_ctcp_chk
bind ctcr - * hostspy_ctcr_chk
bind flud - * hostspy_flud_chk
bind raw - 600 hostspy_watch_online
bind raw - 601 hostspy_watch_offline
bind dcc $hostspy_setting(flag) $hostspy_setting(cmd) hostspy_hostspy
bind evnt - init-server hostspy_connect_watch

proc hostspy_dopre {} {
	global hostspy_setting
	if {!$hostspy_setting(HOSTSPY:)} {
		return ""
	} elseif {!$hostspy_setting(bold)} {
		return "HOSTSPY: "
	} else {
		return "\002HOSTSPY:\002 "
	}
}
proc hostspy_savearray {array file} {
	upvar $array ours
	if {(![catch {open $file w} fd]) && (![array exists ours])} {
		foreach entry [array names ours] {
			puts $fd "%!%$entry!!!$ours($entry)"
		}
		close $fd
	}
}
proc hostspy_readarray {array file} {
	upvar $array ours
	if {![catch {open $file r} fd]} {
		if {[array exists ours]} {
			unset ours
		}
		while {![eof $fd]} {
			set line [gets $fd]
			if {[string range $line 0 2] == "%!%"} {
				set line [string range $line 3 end]
				if {[scan $line "%\[^!!!\]!!!%s" name data] > 0} {
					if {![info exists data]} {set data ""}
					set ours($name) $data
				}
			}
		}
		close $fd
	}
}
if {(![array exists hostspy_spy]) && ([file exists ${hostspy_setting(logdir)}spy.db])} {
	hostspy_readarray hostspy_spy ${hostspy_setting(logdir)}spy.db
	putlog "\002HOSTSPY:\002 Reloading spy array from ${hostspy_setting(logdir)}spy.db"
}
if {(![array exists hostspy_watch]) && ([file exists ${hostspy_setting(logdir)}watch.db])} {
	hostspy_readarray hostspy_watch ${hostspy_setting(logdir)}watch.db
	putlog "\002HOSTSPY:\002 Reloading watch array from ${hostspy_setting(logdir)}watch.db"
}
proc hostspy_putdcc {idx text} {
	putdcc $idx "[hostspy_dopre]$text"
}
proc hostspy_hostspy {hand idx text} {
	global hostspy_setting hostspy_watch hostspy_spy
	set cmd [lindex [split $text] 0]
	set arg1 [lindex [split $text] 1]
	set arg2 [lindex [split $text] 2]
	if {($cmd == "") || (([string match -nocase help $cmd]) && ($arg1 == ""))} {
		hostspy_putdcc $idx "Usage: .$hostspy_setting(cmd) <command>"
		hostspy_putdcc $idx "Commands:"
		hostspy_putdcc $idx "AddSpy - Adds a host to the spy list."
		hostspy_putdcc $idx "AddWatch - Adds a nick to the watch list."
		hostspy_putdcc $idx "ClearSpy - Clears the spy list."
		hostspy_putdcc $idx "ClearWatch - Clears the watch list."
		hostspy_putdcc $idx "DelSpy - Deletes a channel from the database."
		hostspy_putdcc $idx "DelWatch - Deletes a nick from the database."
		hostspy_putdcc $idx "ListSpy - Displays the spy list."
		hostspy_putdcc $idx "ListWatch - Displays the watch list."
		hostspy_putdcc $idx "See .$hostspy_setting(cmd) help <command> for more information."
	} elseif {[string match -nocase help $cmd]} {
		if {[string match -nocase addspy $arg1]} {
			hostspy_putdcc $idx "Usage: .$hostspy_setting(cmd) AddSpy <nick!user@host>"
			hostspy_putdcc $idx "This command adds a host to the spy list."
		} elseif {[string match -nocase addwatch $arg1]} {
			hostspy_putdcc $idx "Usage: .$hostspy_setting(cmd) AddWatch <nick>"
			hostspy_putdcc $idx "This command adds a host to the spy list."
		} elseif {[string match -nocase clearspy $arg1]} {
			hostspy_putdcc $idx "Usage: .$hostspy_setting(cmd) ClearSpy"
			hostspy_putdcc $idx "This command clears the spy list."
		} elseif {[string match -nocase clearwatch $arg1]} {
			hostspy_putdcc $idx "Usage: .$hostspy_setting(cmd) ClearWatch"
			hostspy_putdcc $idx "This command clears the watch list."
		} elseif {[string match -nocase delspy $arg1]} {
			hostspy_putdcc $idx "Usage: .$hostspy_setting(cmd) DelSpy <nick!user@host>"
			hostspy_putdcc $idx "This command deletes a host from the spy list."
		} elseif {[string match -nocase delwatch $arg1]} {
			hostspy_putdcc $idx "Usage: .$hostspy_setting(cmd) DelWatch <nick>"
			hostspy_putdcc $idx "This command deletes a nick from the watch list."
		} elseif {[string match -nocase listspy $arg1]} {
			hostspy_putdcc $idx "Usage: .$hostspy_setting(cmd) ListSpy"
			hostspy_putdcc $idx "This command displays the spy list."
		} elseif {[string match -nocase listwatch $arg1]} {
			hostspy_putdcc $idx "Usage: .$hostspy_setting(cmd) ListWatch"
			hostspy_putdcc $idx "This command displays the watch list."
		} else {
			hostspy_putdcc $idx "No help is available for that command."
		}
	} elseif {[string match -nocase addspy $cmd]} {
		if {$arg1 == ""} {
			hostspy_putdcc $idx "Usage: .$hostspy_setting(cmd) AddSpy <nick!user@host>"
		} elseif {[info exists hostspy_spy([string tolower [hostspy_hreplace $arg1]])]} {
			hostspy_putdcc $idx "$arg1 already exists on the spy list."
		} else {
			set hostspy_spy([string tolower [hostspy_hreplace $arg1]]) [string tolower [hostspy_hreplace $arg1]]
			hostspy_savearray hostspy_spy ${hostspy_setting(logdir)}spy.db
			hostspy_putdcc $idx "Now logging events from $arg1 to [string tolower [hostspy_hreplace $arg1]].event."
		}
	} elseif {[string match -nocase addwatch $cmd]} {
		if {$arg1 == ""} {
			hostspy_putdcc $idx "Usage: .$hostspy_setting(cmd) AddWatch <nick>"
		} elseif {[info exists hostspy_watch([string tolower $arg1])]} {
			hostspy_putdcc $idx "$arg1 already exists on the watch list."
		} else {
			putquick "WATCH +$arg1"
			set hostspy_watch([string tolower $arg1]) [string tolower $arg1]
			hostspy_savearray hostspy_watch ${hostspy_setting(logdir)}watch.db
			hostspy_putdcc $idx "$arg1 has been added to the watch list. \(Logging to [string tolower $arg1].watch\)"
		}
	} elseif {[string match -nocase clearspy $cmd]} {
		if {[array size hostspy_spy] == 0} {
			hostspy_putdcc $idx "There are no users on the spy list."
		} else {
			foreach g [array names hostspy_spy] {
				hostspy_putdcc $idx "[hostspy_undohreplace $hostspy_spy($g)] has been removed from the spy list."
				unset hostspy_spy($g)
			}
		
		}
	} elseif {[string match -nocase clearwatch $cmd]} {
		if {[array size hostspy_watch] == 0} {
			hostspy_putdcc $idx "There are no users on the watch list."
		} else {
			foreach g [array names hostspy_watch] {
				putquick "WATCH -$hostspy_watch($g)"
				hostspy_putdcc $idx "$hostspy_watch($g) has been removed from the WATCH list."
				unset hostspy_watch($g)
			}
			hostspy_savearray hostspy_watch ${hostspy_setting(logdir)}watch.db
		}
	} elseif {[string match -nocase delspy $cmd]} {
		if {$arg1 == ""} {
			hostspy_putdcc $idx "Usage: .$hostspy_setting(cmd) DelSpy <nick!user@host>"
		} elseif {![info exists hostspy_spy([hostspy_hreplace [string tolower $arg1]])]} {
			hostspy_putdcc $idx "$arg1 does not exist on the spy list."
		} else {
			foreach g [array names hostspy_spy] {
				if {[string match -nocase $arg1 [hostspy_undohreplace $hostspy_spy($g)]]} {
					hostspy_putdcc $idx "[hostspy_undohreplace $hostspy_spy($g)] has been removed from the spy list."
					unset hostspy_spy($g)
				}
			}
			hostspy_savearray hostspy_spy ${hostspy_setting(logdir)}spy.db
		}
	} elseif {[string match -nocase delwatch $cmd]} {
		if {$arg1 == ""} {
			hostspy_putdcc $idx "Usage: .$hostspy_setting(cmd) DelWatch <nick>"
		} elseif {![info exists hostspy_watch($arg1)]} {
			hostspy_putdcc $idx "$arg1 does not exist on the watch list."
		} else {
			foreach g [array names hostspy_watch] {
				if {[string match -nocase $arg1 $hostspy_watch($g)]} {
					putquick "WATCH -$hostspy_watch($g)"
					hostspy_putdcc $idx "$hostspy_watch($g) has been removed from the watch list."
					unset hostspy_watch($g)
				}
			}
			hostspy_savearray hostspy_watch ${hostspy_setting(logdir)}watch.db
		}
	} elseif {[string match -nocase listspy $cmd]} {
		if {([array size hostspy_spy] == 0) || (![array exists hostspy_spy])} {
			hostspy_putdcc $idx "There are no users on the spy list."
		} else {
			hostspy_putdcc $idx "Spy list:"
			foreach g [array names hostspy_spy] {
				hostspy_putdcc $idx "Spy List: [hostspy_undohreplace $hostspy_spy($g)]"
			}
			hostspy_putdcc $idx "End of spy list."
		}
	} elseif {[string match -nocase listwatch $cmd]} {
		if {([array size hostspy_watch] == 0) || (![array exists hostspy_spy])} {
			hostspy_putdcc $idx "There are no users on the watch list."
		} else {
			hostspy_putdcc $idx "Watch list:"
			foreach g [array names hostspy_watch] {
				hostspy_putdcc $idx "Watch List: $hostspy_watch($g)"
			}
			hostspy_putdcc $idx "End of watch list."
		}
	} else {
		hostspy_putdcc $idx "Usage: .$hostspy_setting(cmd) <command>"
		hostspy_putdcc $idx "See .$hostspy_setting(cmd) help for a command list."
	}
}
proc hostspy_add_event {g text} {
	global hostspy_setting hostspy_spy
	set fd [open ${hostspy_setting(logdir)}$hostspy_spy($g).event a]
	puts $fd "$text"
	close $fd
}
proc hostspy_watch_online {from keyword text} {
	global hostspy_watch hostspy_setting
	foreach g [array names hostspy_watch] {
		if {[string match -nocase $hostspy_watch($g) $nick]} {
			set fd [open ${hostspy_setting(logdir)}$hostspy_watch($g).watch a]
			puts $fd "\[[clock format [clock seconds] -format "%D"]\] \[[clock format [clock seconds] -format "%I:%M:%S %p"]\] Online: [lindex [split $text] 1]![lindex [split $text] 2]@[lindex [split $text] 3]"
			close $fd
		}
	}

}
proc hostspy_watch_offline {from keyword text} {
	global hostspy_watch hostspy_setting
	foreach g [array names hostspy_watch] {
		if {[string match -nocase $hostspy_watch($g) $nick]} {
			set fd [open ${hostspy_setting(logdir)}$hostspy_watch($g).watch a]
			puts $fd "\[[clock format [clock seconds] -format "%D"]\] \[[clock format [clock seconds] -format "%I:%M:%S %p"]\] Offline: [lindex [split $text] 1]![lindex [split $text] 2]@[lindex [split $text] 3]"
			close $fd
		}
	}

}
proc hostspy_msg_chk {nick uhost hand text} {
	global hostspy_spy
	foreach g [array names hostspy_spy] {
		if {[string match -nocase [hostspy_undohreplace $hostspy_spy($g)] $nick!$uhost]} {
			hostspy_add_event $g "\[[clock format [clock seconds] -format "%D"]\] \[[clock format [clock seconds] -format "%I:%M:%S %p"]\] Private Message: ${nick}!${uhost} Text: $text"
		}
	}
}
proc hostspy_pub_chk {nick uhost hand chan text} {
	global hostspy_spy
	foreach g [array names hostspy_spy] {
		if {[string match -nocase [hostspy_undohreplace $hostspy_spy($g)] $nick!$uhost]} {
			hostspy_add_event $g "\[[clock format [clock seconds] -format "%D"]\] \[[clock format [clock seconds] -format "%I:%M:%S %p"]\] Public Text: ${nick}!${uhost} Chan: $chan Text: $text"
		}
	}
}
proc hostspy_notc_chk {nick uhost hand text dest} {
	global hostspy_spy
	foreach g [array names hostspy_spy] {
		if {[string match -nocase [hostspy_undohreplace $hostspy_spy($g)] $nick!$uhost]} {
			hostspy_add_event $g "\[[clock format [clock seconds] -format "%D"]\] \[[clock format [clock seconds] -format "%I:%M:%S %p"]\] Notice: ${nick}!${uhost} Destination: $dest Text: $text"
		}
	}
}
proc hostspy_join_chk {nick uhost hand chan} {
	global hostspy_spy
	foreach g [array names hostspy_spy] {
		if {[string match -nocase [hostspy_undohreplace $hostspy_spy($g)] $nick!$uhost]} {
			hostspy_add_event $g "\[[clock format [clock seconds] -format "%D"]\] \[[clock format [clock seconds] -format "%I:%M:%S %p"]\] Join: ${nick}!${uhost} Chan: $chan"
		}
	}
}
proc hostspy_part_chk {nick uhost hand chan msg} {
	global hostspy_spy
	foreach g [array names hostspy_spy] {
		if {[string match -nocase [hostspy_undohreplace $hostspy_spy($g)] $nick!$uhost]} {
			hostspy_add_event $g "\[[clock format [clock seconds] -format "%D"]\] \[[clock format [clock seconds] -format "%I:%M:%S %p"]\] Part: ${nick}!${uhost} Chan: $chan Part Message: $msg"
		}
	}
}
proc hostspy_sign_chk {nick uhost hand chan text} {
	global hostspy_spy
	foreach g [array names hostspy_spy] {
		if {[string match -nocase [hostspy_undohreplace $hostspy_spy($g)] $nick!$uhost]} {
			hostspy_add_event $g "\[[clock format [clock seconds] -format "%D"]\] \[[clock format [clock seconds] -format "%I:%M:%S %p"]\] Quit: ${nick}!${uhost} Chan: $chan Quit Message: $text"
		}
	}
}
proc hostspy_topc_chk {nick uhost hand chan text} {
	global hostspy_spy
	foreach g [array names hostspy_spy] {
		if {[string match -nocase [hostspy_undohreplace $hostspy_spy($g)] $nick!$uhost]} {
			hostspy_add_event $g "\[[clock format [clock seconds] -format "%D"]\] \[[clock format [clock seconds] -format "%I:%M:%S %p"]\] Topic Change: ${nick}!${uhost} Chan: $chan New Topic: $text"
		}
	}
}
proc hostspy_kick_chk {nick uhost hand chan target text} {
	global hostspy_spy
	foreach g [array names hostspy_spy] {
		if {[string match -nocase [hostspy_undohreplace $hostspy_spy($g)] $nick!$uhost]} {
			hostspy_add_event $g "\[[clock format [clock seconds] -format "%D"]\] \[[clock format [clock seconds] -format "%I:%M:%S %p"]\] Kick: ${nick}!${uhost} Chan: $chan Target: $target Kick Message: $text"
		}
	}
}
proc hostspy_nick_chk {nick uhost hand chan newnick} {
	global hostspy_spy
	foreach g [array names hostspy_spy] {
		if {[string match -nocase [hostspy_undohreplace $hostspy_spy($g)] $nick!$uhost]} {
			hostspy_add_event $g "\[[clock format [clock seconds] -format "%D"]\] \[[clock format [clock seconds] -format "%I:%M:%S %p"]\] Nick Change: ${nick}!${uhost} Chan: $chan New Nick: $newnick"
		}
	}
}
proc hostspy_mode_chk {nick uhost hand chan mode vict} {
	global hostspy_spy
	foreach g [array names hostspy_spy] {
		if {[string match -nocase [hostspy_undohreplace $hostspy_spy($g)] $nick!$uhost]} {
			hostspy_add_event $g "\[[clock format [clock seconds] -format "%D"]\] \[[clock format [clock seconds] -format "%I:%M:%S %p"]\] Mode Change: ${nick}!${uhost} Chan: $chan Modes: $mode $vict"		
		}
	}
}
proc hostspy_ctcp_chk {nick uhost hand dest keyword text} {
	global hostspy_spy
	foreach g [array names hostspy_spy] {
		if {[string match -nocase [hostspy_undohreplace $hostspy_spy($g)] $nick!$uhost]} {
			hostspy_add_event $g "\[[clock format [clock seconds] -format "%D"]\] \[[clock format [clock seconds] -format "%I:%M:%S %p"]\] CTCP: ${nick}!${uhost} Destination: $dest Keyword: $keyword Text: $text"
		}
	}
}
proc hostspy_ctcr_chk {nick uhost hand dest keyword text} {
	global hostspy_spy
	foreach g [array names hostspy_spy] {
		if {[string match -nocase [hostspy_undohreplace $hostspy_spy($g)] $nick!$uhost]} {
			hostspy_add_event $g "\[[clock format [clock seconds] -format "%D"]\] \[[clock format [clock seconds] -format "%I:%M:%S %p"]\] CTCR: ${nick}!${uhost} Destination: $dest Keyword: $keyword Text: $text"
		}
	}
}
proc hostspy_flud_chk {nick uhost hand type chan} {
	global hostspy_spy
	foreach g [array names hostspy_spy] {
		if {[string match -nocase [hostspy_undohreplace $hostspy_spy($g)] $nick!$uhost]} {
			hostspy_add_event $g "\[[clock format [clock seconds] -format "%D"]\] \[[clock format [clock seconds] -format "%I:%M:%S %p"]\] Flood Trigger: ${nick}!${uhost} Chan: $chan Type: $type"
		}
	}
}
proc hostspy_connect_watch {init-server} {
	global hostspy_watch
	foreach g [array names hostspy_watch] {
		puthelp "WATCH +$g"
	}
}
proc hostspy_hreplace {text} {
	regsub -all -- "\\*" "$text" "#" text
	regsub -all -- "\\?" "$text" "\\&" text
	regsub -all -- "!" "$text" "+" text
	return $text
}
proc hostspy_undohreplace {text} {
	regsub -all -- "\\#" "$text" "*" text
	regsub -all -- "\\+" "$text" "!" text
	regsub -all -- "\\&" "$text" "?" text
	return $text
}
putlog "\002HOSTSPY:\002 HostSpy.tcl Version 1.7 by Wcc is loaded."