+#bs(no_log) is a list of channels you *don't* want the bot to log
+# data on. Enter chans in lower case.
+set bs(no_log) ""
+
+#bs(log_only) is a list of channels you *only* want the bot to log
+# data on. This is the opposite of bs(no_log). Set it to "" if you
+# want to log new channels the bot joins. Enter chans in lower case.
+set bs(log_only) ""
+
+#bs(cmdchar) is what command character should be used for making public
+# queries. The default is "!". Setting it to "" is a valid option.
+set bs(cmdchar) "!"
+
+#bs(flood) is used for flood protection, in the form x:y. Any queries
+# beyond x in y seconds is considered a flood and ignored.
+set bs(flood) 4:15
+#bs(ignore) is used as a switch for ignoring flooders (1=on)
+set bs(ignore) 1
+#bs(ignore_time) is used to define the amount of time a flooder is
+# ignored (minutes). This is meaningless if bs(ignore) is 0.
+set bs(ignore_time) 2
+
+#bs(smartsearch) is a master enable/disable for SmartSearch. SmartSearch ensures that
+# the most accurate and current results are returned for nick queries. (1=on)
+set bs(smartsearch) 1
+
+#bs(logqueries) is used to log DCC/MSG/PUB queries
+set bs(logqueries) 1
+
+#bs(path) is used to indicate what path to save the database and backup to.
+# Setting to "" will cause the script to be saved in the same path as the eggdrop executable
+# If you set it, use the full path, and make sure you terminate w/ a "/".
+# eg: set bs(path) "/usr/home/mydir/blah/"
+set bs(path) "$username/"
+
+###### Don't edit below here, even if you do know Tcl ######
+
+
+if {[bind msg -|- help] != "*msg:help"} {bind msg -|- help *msg:help} ; #this is to fix a bind I didn't intend to use in a prev version (which screwed up msg'd help). Sorry!
+proc bs_filt {data} {
+ regsub -all -- \\\\ $data \\\\\\\\ data ; regsub -all -- \\\[ $data \\\\\[ data ; regsub -all -- \\\] $data \\\\\] data
+ regsub -all -- \\\} $data \\\\\} data ; regsub -all -- \\\{ $data \\\\\{ data ; regsub -all -- \\\" $data \\\\\" data ; return $data
+}
+proc bs_flood_init {} {
+ global bs bs_flood_array ; if {![string match *:* $bs(flood)]} {putlog "$bs(version): var bs(flood) not set correctly." ; return}
+ set bs(flood_num) [lindex [split $bs(flood) :] 0] ; set bs(flood_time) [lindex [split $bs(flood) :] 1] ; set i [expr $bs(flood_num) - 1]
+ while {$i >= 0} {set bs_flood_array($i) 0 ; incr i -1 ; }
+} ; bs_flood_init
+proc bs_flood {nick uhost} {
+ global bs bs_flood_array ; if {$bs(flood_num) == 0} {return 0} ; set i [expr $bs(flood_num) - 1]
+ while {$i >= 1} {set bs_flood_array($i) $bs_flood_array([expr $i - 1]) ; incr i -1} ; set bs_flood_array(0) [unixtime]
+if {[lsearch -exact [bind time -|- "*2 * * * *"] bs_timedsave] > -1} {unbind time -|- "*2 * * * *" bs_timedsave} ; #backup frequency can be lower
+proc bs_read {} {
+ global bs_list userfile bs
+ if {![string match */* $userfile]} {set name [lindex [split $userfile .] 0]} {
+ set temp [split $userfile /] ; set temp [lindex $temp [expr [llength $temp]-1]] ; set name [lindex [split $temp .] 0]
+ }
+ if {![file exists $bs(path)bs_data.$name]} {
+ if {![file exists $bs(path)bs_data.$name.bak]} {
+ putlog " Old seen data not found!" ; putlog " If this is the first time you've run the script, don't worry." ; putlog " If there *should* be a data file from past runs of this script... worry." ; return
+ } {exec cp $bs(path)bs_data.$name.bak $bs(path)bs_data.$name ; putlog " Old seen data not found! Using backup data."}
+ } ; set fd [open $bs(path)bs_data.$name r]
+ set bsu_ver "" ; set break 0
+ while {![eof $fd]} {
+ set inp [gets $fd] ; if {[eof $fd]} {break} ; if {[string trim $inp " "] == ""} {continue}
+ if {[string index $inp 0] == "#"} {set bsu_version [string trimleft $inp #] ; continue}
+ putlog "$hand removed $chan from the bseen database. $tot entries removed."
+ putidx $idx "$chan successfully removed. $tot entries deleted from the bseen database."
+}
+bind bot -|- bs_botsearch bs_botsearch
+proc bs_botsearch {from cmd args} {
+ global botnick ; set args [join $args]
+ set command [lindex $args 0] ; set target [lindex $args 1] ; set nick [lindex $args 2] ; set search [bs_filt [join [lrange $args 3 e]]]
+ if {[string match *\\\** $search]} {
+ set output [bs_seenmask bot $nick $search]
+ if {$output != "No matches were found." && ![string match "I'm not on *" $output]} {putbot $from "bs_botsearch_reply $command \{$target\} {$nick, $botnick says: [bs_filt $output]}"}
+ set output [concat $n ($addy) was last seen parting $chan [bs_when $time] ago$reason]
+ }
+ quit { set output [concat $n ($addy) was last seen quitting from $chan [bs_when $time] ago stating ([join [lrange $data 5 e]]).] }
+ kick { set output [concat $n ($addy) was last seen being kicked from $chan by [lindex $data 5] [bs_when $time] ago with the reason ([join [lrange $data 6 e]]).] }
+ rnck {
+ set output [concat $n ($addy) was last seen changing nicks from [lindex $data 5] on [lindex $data 4] [bs_when $time] ago.]
+ if {[validchan [lindex $data 4]]} {
+ if {[onchan $n [lindex $data 4]]} {
+ set output [concat $output $n is still there.]
+ } {
+ set output [concat $output I don't see $n now, though.]
+ }
+ }
+ }
+ nick {
+ set output [concat $n ($addy) was last seen changing nicks to [lindex $data 5] on [lindex $data 4] [bs_when $time] ago.]
+ }
+ splt { set output [concat $n ($addy) was last seen parting $chan due to a split [bs_when $time] ago.] }
+ rejn {
+ set output [concat $n ($addy) was last seen rejoining $chan from a split [bs_when $time] ago.]
+ if {[validchan $chan]} {if {[onchan $n $chan]} {set output [concat $output $n is still on $chan.]} {set output [concat $output I don't see $n on $chan now, though.]}}
+ }
+ join {
+ set output [concat $n ($addy) was last seen joining $chan [bs_when $time] ago.]
+ if {[validchan $chan]} {if {[onchan $n $chan]} {set output [concat $output $n is still on $chan.]} {set output [concat $output I don't see $n on $chan now, though.]}}
+ }
+ away {
+ set reason [lrange $data 5 e]
+ if {$reason == ""} {
+ set output [concat $n ($addy) was last seen returning to the partyline on $chan [bs_when $time] ago.]
+ } {
+ set output [concat $n ($addy) was last seen being marked as away ($reason) on $chan [bs_when $time] ago.]
+ }
+ }
+ chon {
+ set output [concat $n ($addy) was last seen joining the partyline [bs_when $time] ago.] ; set lnick [string tolower $n]
+ foreach item [whom *] {if {$lnick == [string tolower [lindex $item 0]]} {set output [concat $output $n is on the partyline right now.] ; set marker 1 ; break}}
+ if {$marker == 0} {set output [concat $output I don't see $n on the partyline now, though.]}
+ }
+ chof {
+ set output [concat $n ($addy) was last seen leaving the partyline [bs_when $time] ago.] ; set lnick [string tolower $n]
+ foreach item [whom *] {if {$lnick == [string tolower [lindex $item 0]]} {set output [concat $output $n is on the partyline in [lindex $item 1] still.] ; break}}
+ }
+ chjn {
+ set output [concat $n ($addy) was last seen joining the partyline on $chan [bs_when $time] ago.] ; set lnick [string tolower $n]
+ foreach item [whom *] {if {$lnick == [string tolower [lindex $item 0]]} {set output [concat $output $n is on the partyline right now.] ; set marker 1 ; break}}
+ if {$marker == 0} {set output [concat $output I don't see $n on the partyline now, though.]}
+ }
+ chpt {
+ set output [concat $n ($addy) was last seen leaving the partyline from $chan [bs_when $time] ago.] ; set lnick [string tolower $n]
+ foreach item [whom *] {if {$lnick == [string tolower [lindex $item 0]]} {set output [concat $output $n is on the partyline in [lindex $item 1] still.] ; break}}
+ }
+ default {set output "error"}
+ } ; return $output
+ } {return 0}
+}
+proc bs_when {lasttime} {
+ #This is equiv to mIRC's $duration() function
+ set years 0 ; set days 0 ; set hours 0 ; set mins 0 ; set time [expr [unixtime] - $lasttime]
+ if {$time < 60} {return "only $time seconds"}
+ if {$time >= 31536000} {set years [expr int([expr $time/31536000])] ; set time [expr $time - [expr 31536000*$years]]}
+ if {$time >= 86400} {set days [expr int([expr $time/86400])] ; set time [expr $time - [expr 86400*$days]]}
+ if {$time >= 3600} {set hours [expr int([expr $time/3600])] ; set time [expr $time - [expr 3600*$hours]]}
+ if {$time >= 60} {set mins [expr int([expr $time/60])]}
+ if {![validchan $chan]} {return "I'm not on $chan."} {set chan [string tolower $chan]}
+ } { set $chan "" }
+ if {![info exists bs_list]} {return "No matches were found."} ; set data [bs_filt [string tolower [lindex $args 0]]]
+
+#bugfix: unnecessarily complex masks essentially freeze the bot
+ set maskfix 1
+ while $maskfix {
+ set mark 1
+ if [regsub -all -- \\?\\? $data ? data] {set mark 0}
+ if [regsub -all -- \\*\\* $data * data] {set mark 0}
+ if [regsub -all -- \\*\\? $data * data] {set mark 0}
+ if [regsub -all -- \\?\\* $data * data] {set mark 0}
+ if $mark {break}
+ }
+
+ set id [array startsearch bs_list]
+ while {[array anymore bs_list $id]} {
+ set item [array nextelement bs_list $id] ; if {$item == ""} {continue} ; set i 0 ; set temp "" ; set match [lindex $bs_list($item) 0] ; set addy [lindex $bs_list($item) 1]
+ if {[string match $data $item![string tolower $addy]]} {
+ set match [bs_filt $match] ; if {$chan != ""} {
+ if {[string match $chan [string tolower [lindex $bs_list($item) 4]]]} {set matches [concat $matches $match]}
+ } {set matches [concat $matches $match]}
+ }
+ }
+ array donesearch bs_list $id
+ set matches [string trim $matches " "]
+ if {$nick == "?"} {return [bs_filt $matches]}
+ set len [llength $matches]
+ if {$len == 0} {return "No matches were found."}
+ return "Currently I am tracking [array size bs_list]/$bs(limit) nicks, which comprise $totalm unique uhosts. The oldest record is [lindex $bs_list($name) 0]'s, which is from [bs_when $bs_record] ago."
+}
+bind dcc -|- chanstats bs_dccchanstats
+proc bs_dccchanstats {hand idx args} {
+ if {$args == "{}"} {set args [console $idx]}
+ if {[lindex $args 0] == "*"} {putdcc $idx "$hand, chanstats requires a channel arg, or a valid console channel." ; return 1}
+ putdcc $idx "[bs_chanstats [lindex $args 0]]"
+ return 1
+}
+bind pub -|- [string trim $bs(cmdchar)]chanstats bs_pubchanstats
+proc bs_pubchanstats {nick uhost hand chan args} {
+ array donesearch bs_list $id ; set total [array size bs_list]
+ return "$chan is the source of [expr 100*$totalc/$total]% ($totalc/$total) of the seen database entries. In $chan, there were a total of $totalm unique uhosts seen in the last [bs_when $bs_record]."