LoveAbleElf

seen.tcl

Feb 28th, 2018
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 34.63 KB | None | 0 0
  1. #
  2. ###
  3. #Bass's Seen script. v1.4.2c 2/2000
  4. #*!bass@*.psu.edu on Undernet. Email: bass@tclslave.net or bass@mars.age.psu.edu
  5. #This script maintains a database of *all* nicks seen online,
  6. #not just those ppl who are in the userlist. Simple flood
  7. #protection is built-in. Wildcard searches are supported.
  8. #
  9. #Input is accepted from:
  10. # pub: !seen <query> [#chan]
  11. # msg: seen <query> [#chan]
  12. # and dcc: .seen <query> [#chan]
  13. #
  14. #Queries can be in the following formats (public examples given):
  15. # 'regular' !seen lamer; !seen lamest | SmartSearch-enabled query
  16. # 'limited' !seennick lamer | SmartSearch-bypassed query
  17. # 'masked' !seen *l?mer*; !seen *.lame.com; !seen *.edu #mychan
  18. #
  19. #Bonus feature: !lastspoke <nick>
  20. # You can use wildcard matching for <nick>. The results for the
  21. # first match are returned.
  22.  
  23. ###Parameters:
  24.  
  25. #bs(limit) is the database record limit.
  26. set bs(limit) 4000
  27.  
  28. #bs(nicksize) is the maximum nickname length (9 on Undernet)
  29. set bs(nicksize) 9
  30.  
  31. #bs(no_pub) is a list of channels you *don't* want the bot to post public
  32. # replies to (public queries ignored). Enter in lower case, eg: #lamer
  33. set bs(no_pub) ""
  34.  
  35. #bs(quiet_chan) is a list of channels you want replies to requests sent
  36. # to the person who made the query via notice. (The bot replies to
  37. # public queries via notice.) Enter in lower case.
  38. set bs(quiet_chan) ""
  39.  
  40. #bs(no_log) is a list of channels you *don't* want the bot to log
  41. # data on. Enter chans in lower case.
  42. set bs(no_log) ""
  43.  
  44. #bs(log_only) is a list of channels you *only* want the bot to log
  45. # data on. This is the opposite of bs(no_log). Set it to "" if you
  46. # want to log new channels the bot joins. Enter chans in lower case.
  47. set bs(log_only) ""
  48.  
  49. #bs(cmdchar) is what command character should be used for making public
  50. # queries. The default is "!". Setting it to "" is a valid option.
  51. set bs(cmdchar) "!"
  52.  
  53. #bs(flood) is used for flood protection, in the form x:y. Any queries
  54. # beyond x in y seconds is considered a flood and ignored.
  55. set bs(flood) 4:15
  56. #bs(ignore) is used as a switch for ignoring flooders (1=on)
  57. set bs(ignore) 1
  58. #bs(ignore_time) is used to define the amount of time a flooder is
  59. # ignored (minutes). This is meaningless if bs(ignore) is 0.
  60. set bs(ignore_time) 2
  61.  
  62. #bs(smartsearch) is a master enable/disable for SmartSearch. SmartSearch ensures that
  63. # the most accurate and current results are returned for nick queries. (1=on)
  64. set bs(smartsearch) 1
  65.  
  66. #bs(logqueries) is used to log DCC/MSG/PUB queries
  67. set bs(logqueries) 1
  68.  
  69. #bs(path) is used to indicate what path to save the database and backup to.
  70. # Setting to "" will cause the script to be saved in the same path as the eggdrop executable
  71. # If you set it, use the full path, and make sure you terminate w/ a "/".
  72. # eg: set bs(path) "/usr/home/mydir/blah/"
  73. set bs(path) ""
  74.  
  75. ###### Don't edit below here, even if you do know Tcl ######
  76.  
  77.  
  78. 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!
  79. proc bs_filt {data} {
  80. regsub -all -- \\\\ $data \\\\\\\\ data ; regsub -all -- \\\[ $data \\\\\[ data ; regsub -all -- \\\] $data \\\\\] data
  81. regsub -all -- \\\} $data \\\\\} data ; regsub -all -- \\\{ $data \\\\\{ data ; regsub -all -- \\\" $data \\\\\" data ; return $data
  82. }
  83. proc bs_flood_init {} {
  84. global bs bs_flood_array ; if {![string match *:* $bs(flood)]} {putlog "$bs(version): var bs(flood) not set correctly." ; return}
  85. 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]
  86. while {$i >= 0} {set bs_flood_array($i) 0 ; incr i -1 ; }
  87. } ; bs_flood_init
  88. proc bs_flood {nick uhost} {
  89. global bs bs_flood_array ; if {$bs(flood_num) == 0} {return 0} ; set i [expr $bs(flood_num) - 1]
  90. while {$i >= 1} {set bs_flood_array($i) $bs_flood_array([expr $i - 1]) ; incr i -1} ; set bs_flood_array(0) [unixtime]
  91. if {[expr [unixtime] - $bs_flood_array([expr $bs(flood_num) - 1])] <= $bs(flood_time)} {
  92. putlog "$bs(version): Flood detected from $nick." ; if {$bs(ignore)} {newignore [join [maskhost *!*[string trimleft $uhost ~]]] $bs(version) flood $bs(ignore_time)} ; return 1
  93. } {return 0}
  94. }
  95. if {[lsearch -exact [bind time -|- "*2 * * * *"] bs_timedsave] > -1} {unbind time -|- "*2 * * * *" bs_timedsave} ; #backup frequency can be lower
  96. proc bs_read {} {
  97. global bs_list userfile bs
  98. if {![string match */* $userfile]} {set name [lindex [split $userfile .] 0]} {
  99. set temp [split $userfile /] ; set temp [lindex $temp [expr [llength $temp]-1]] ; set name [lindex [split $temp .] 0]
  100. }
  101. if {![file exists $bs(path)bs_data.$name]} {
  102. if {![file exists $bs(path)bs_data.$name.bak]} {
  103. 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
  104. } {exec cp $bs(path)bs_data.$name.bak $bs(path)bs_data.$name ; putlog " Old seen data not found! Using backup data."}
  105. } ; set fd [open $bs(path)bs_data.$name r]
  106. set bsu_ver "" ; set break 0
  107. while {![eof $fd]} {
  108. set inp [gets $fd] ; if {[eof $fd]} {break} ; if {[string trim $inp " "] == ""} {continue}
  109. if {[string index $inp 0] == "#"} {set bsu_version [string trimleft $inp #] ; continue}
  110. if {![info exists bsu_version] || $bsu_version == "" || $bsu_version < $bs(updater)} {
  111. putlog "Updating database to new version of bseen..."
  112. #bugfix (b) - loading the wrong updater version
  113. if {[source scripts/bseen_updater1.4.2.tcl] != "ok"} {set temp 1} {set temp 0}
  114. if {$temp || [bsu_go] || [bsu_finish]} {
  115. putlog "A serious problem was encountered while updating the bseen database."
  116. if {$temp} {putlog " The updater script could not be found."}
  117. putlog "It is *not* safe to run the bot w/ a bseen database that is not matched to this version of bseen."
  118. putlog "If you can't find the problem, the only option is to remove the bs_data.$name and bs_data.$name.bak files. Then restart the bot."
  119. putlog "Because this is a potential crash point in the bot, the bot will now halt." ; die "critical error in bseen encountered"
  120. } ; set break 1 ; break
  121. }
  122. set nick [lindex $inp 0] ; set bs_list([string tolower $nick]) $inp
  123. } ; close $fd
  124. if {$break} {bs_read} {putlog " Done loading [array size bs_list] seen records."}
  125. }
  126.  
  127. ###
  128. #Must check to make sure the version didn't change during a .rehash
  129. proc bs_update {} {
  130. global bs
  131. putlog "A new version of bseen is dynamically being loaded."
  132. putlog " Verifying the integrity of the database across versions..."
  133. bs_save ; bs_read
  134. }
  135. set bs(updater) 10402 ; set bs(version) bseen1.4.2c
  136. if {[info exists bs_list]} {
  137. #a rehash was done
  138. if {[info exists bs(oldver)]} {
  139. if {$bs(oldver) < $bs(updater)} {bs_update} ;# old ver found
  140. } {bs_update} ;# pre- 1.4.0
  141. }
  142. set bs(oldver) $bs(updater)
  143. putlog "$bs(version): -- Bass's SEEN loaded --"
  144. if {![info exists bs_list] || [array size bs_list] == 0} {putlog " Loading seen database..." ; bs_read}
  145. ###
  146.  
  147. bind time - "12 * * * *" bs_timedsave
  148. proc bs_timedsave {min b c d e} {bs_save}
  149. proc bs_save {} {
  150. global bs_list userfile bs ; if {[array size bs_list] == 0} {return}
  151. if {![string match */* $userfile]} {set name [lindex [split $userfile .] 0]} {
  152. set temp [split $userfile /] ; set temp [lindex $temp [expr [llength $temp]-1]] ; set name [lindex [split $temp .] 0]
  153. }
  154. if {[file exists $bs(path)bs_data.$name]} {catch {exec cp -f $bs(path)bs_data.$name $bs(path)bs_data.$name.bak}}
  155. set fd [open $bs(path)bs_data.$name w] ; set id [array startsearch bs_list] ; putlog "Backing up seen data..."
  156. puts $fd "#$bs(updater)"
  157. while {[array anymore bs_list $id]} {set item [array nextelement bs_list $id] ; puts $fd "$bs_list($item)"} ; array donesearch bs_list $id ; close $fd
  158. }
  159. #bugfix -- support new PART in egg1.5.x+
  160. if {[string trimleft [lindex $version 1] 0] >= 1050000} {
  161. bind part -|- * bs_part
  162. } {
  163. if {[lsearch -exact [bind part -|- *] bs_part] > -1} {unbind part -|- * bs_part}
  164. bind part -|- * bs_part_oldver
  165. }
  166. proc bs_part_oldver {a b c d} {bs_part $a $b $c $d ""}
  167. #bugfix - new bs_part proc
  168. proc bs_part {nick uhost hand chan reason} {bs_add $nick "[list $uhost] [unixtime] part $chan [split $reason]"}
  169. bind join -|- * bs_join
  170. proc bs_join {nick uhost hand chan} {bs_add $nick "[list $uhost] [unixtime] join $chan"}
  171. bind sign -|- * bs_sign
  172. proc bs_sign {nick uhost hand chan reason} {bs_add $nick "[list $uhost] [unixtime] quit $chan [split $reason]"}
  173. bind kick -|- * bs_kick
  174. proc bs_kick {nick uhost hand chan knick reason} {bs_add $knick "[getchanhost $knick $chan] [unixtime] kick $chan [list $nick] [list $reason]"}
  175. bind nick -|- * bs_nick
  176. proc bs_nick {nick uhost hand chan newnick} {set time [unixtime] ; bs_add $nick "[list $uhost] [expr $time -1] nick $chan [list $newnick]" ; bs_add $newnick "[list $uhost] $time rnck $chan [list $nick]"}
  177. bind splt -|- * bs_splt
  178. proc bs_splt {nick uhost hand chan} {bs_add $nick "[list $uhost] [unixtime] splt $chan"}
  179. bind rejn -|- * bs_rejn
  180. proc bs_rejn {nick uhost hand chan} {bs_add $nick "[list $uhost] [unixtime] rejn $chan"}
  181. bind chon -|- * bs_chon
  182. proc bs_chon {hand idx} {foreach item [dcclist] {if {[lindex $item 3] != "CHAT"} {continue} ; if {[lindex $item 0] == $idx} {bs_add $hand "[lindex $item 2] [unixtime] chon" ; break}}}
  183. if {[lsearch -exact [bind chof -|- *] bs_chof] > -1} {unbind chof -|- * bs_chof} ; #this bind isn't needed any more
  184. bind chjn -|- * bs_chjn
  185. proc bs_chjn {bot hand channum flag sock from} {bs_add $hand "[string trimleft $from ~] [unixtime] chjn $bot"}
  186. bind chpt -|- * bs_chpt
  187. proc bs_chpt {bot hand args} {set old [split [bs_search ? [string tolower $hand]]] ; if {$old != "0"} {bs_add $hand "[join [string trim [lindex $old 1] ()]] [unixtime] chpt $bot"}}
  188.  
  189. if {[string trimleft [lindex $version 1] 0] > 1030000} {bind away -|- * bs_away}
  190. proc bs_away {bot idx msg} {
  191. global botnet-nick
  192. if {$bot == ${botnet-nick}} {set hand [idx2hand $idx]} {return}
  193. set old [split [bs_search ? [string tolower $hand]]]
  194. if {$old != "0"} {bs_add $hand "[join [string trim [lindex $old 1] ()]] [unixtime] away $bot [bs_filt [join $msg]]"}
  195. }
  196. bind dcc n|- unseen bs_unseen
  197. proc bs_unseen {hand idx args} {
  198. global bs_list
  199. set tot 0 ; set chan [string tolower [lindex $args 0]] ; set id [array startsearch bs_list]
  200. while {[array anymore bs_list $id]} {
  201. set item [array nextelement bs_list $id]
  202. if {$chan == [string tolower [lindex $bs_list($item) 4]]} {incr tot ; lappend remlist $item}
  203. }
  204. array donesearch bs_list $id ; if {$tot > 0} {foreach item $remlist {unset bs_list($item)}}
  205. putlog "$hand removed $chan from the bseen database. $tot entries removed."
  206. putidx $idx "$chan successfully removed. $tot entries deleted from the bseen database."
  207. }
  208. bind bot -|- bs_botsearch bs_botsearch
  209. proc bs_botsearch {from cmd args} {
  210. global botnick ; set args [join $args]
  211. set command [lindex $args 0] ; set target [lindex $args 1] ; set nick [lindex $args 2] ; set search [bs_filt [join [lrange $args 3 e]]]
  212. if {[string match *\\\** $search]} {
  213. set output [bs_seenmask bot $nick $search]
  214. 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]}"}
  215. } {
  216. set output [bs_output bot $nick [bs_filt [lindex $search 0]] 0]
  217. if {$output != 0 && [lrange [split $output] 1 4] != "I don't remember seeing"} {putbot $from "bs_botsearch_reply $command \{$target\} {$nick, $botnick says: [bs_filt $output]}"}
  218. }
  219. }
  220. if {[info exists bs(bot_delay)]} {unset bs(bot_delay)}
  221. bind bot -|- bs_botsearch_reply bs_botsearch_reply
  222. proc bs_botsearch_reply {from cmd args} {
  223. global bs ; set args [join $args]
  224. if {[lindex [lindex $args 2] 5] == "not" || [lindex [lindex $args 2] 4] == "not"} {return}
  225. if {![info exists bs(bot_delay)]} {
  226. set bs(bot_delay) on ; utimer 10 {if {[info exists bs(bot_delay)]} {unset bs(bot_delay)}}
  227. if {![lindex $args 0]} {putdcc [lindex $args 1] "[join [lindex $args 2]]"} {puthelp "[lindex $args 1] :[join [lindex $args 2]]"}
  228. }
  229. }
  230. bind dcc -|- seen bs_dccreq1
  231. bind dcc -|- seennick bs_dccreq2
  232. proc bs_dccreq1 {hand idx args} {bs_dccreq $hand $idx $args 0}
  233. proc bs_dccreq2 {hand idx args} {bs_dccreq $hand $idx $args 1}
  234. proc bs_dccreq {hand idx args no} {
  235. set args [bs_filt [join $args]] ; global bs
  236. if {[string match *\\\** [lindex $args 0]]} {
  237. set output [bs_seenmask dcc $hand $args]
  238. if {$output == "No matches were found."} {putallbots "bs_botsearch 0 $idx $hand $args"}
  239. if {[string match "I'm not on *" $output]} {putallbots "bs_botsearch 0 $idx $hand $args"}
  240. putdcc $idx $output ; return $bs(logqueries)
  241. }
  242. set search [bs_filt [lindex $args 0]]
  243. set output [bs_output dcc $hand $search $no]
  244. if {$output == 0} {return 0}
  245. if {[lrange [split $output] 1 4] == "I don't remember seeing"} {putallbots "bs_botsearch 0 $idx $hand $args"}
  246. putdcc $idx "$output" ; return $bs(logqueries)
  247. }
  248. bind msg -|- seen bs_msgreq1
  249. bind msg -|- seennick bs_msgreq2
  250. proc bs_msgreq1 {nick uhost hand args} {bs_msgreq $nick $uhost $hand $args 0}
  251. proc bs_msgreq2 {nick uhost hand args} {bs_msgreq $nick $uhost $hand $args 1}
  252. proc bs_msgreq {nick uhost hand args no} {
  253. if {[bs_flood $nick $uhost]} {return 0} ; global bs
  254. set args [bs_filt [join $args]]
  255. if {[string match *\\\** [lindex $args 0]]} {
  256. set output [bs_seenmask msg $nick $args]
  257. if {$output == "No matches were found."} {putallbots "bs_botsearch 1 \{notice $nick\} $nick $args"}
  258. if {[string match "I'm not on *" $output]} {putallbots "bs_botsearch 1 \{notice $nick\} $nick $args"}
  259. puthelp "notice $nick :$output" ; return $bs(logqueries)
  260. }
  261. set search [bs_filt [lindex $args 0]]
  262. set output [bs_output $search $nick $search $no]
  263. if {$output == 0} {return 0}
  264. if {[lrange [split $output] 1 4] == "I don't remember seeing"} {putallbots "bs_botsearch 1 \{notice $nick\} $nick $args"}
  265. puthelp "notice $nick :$output" ; return $bs(logqueries)
  266. }
  267. bind pub -|- [string trim $bs(cmdchar)]seen bs_pubreq1
  268. bind pub -|- [string trim $bs(cmdchar)]seennick bs_pubreq2
  269. proc bs_pubreq1 {nick uhost hand chan args} {bs_pubreq $nick $uhost $hand $chan $args 0}
  270. proc bs_pubreq2 {nick uhost hand chan args} {bs_pubreq $nick $uhost $hand $chan $args 1}
  271. proc bs_pubreq {nick uhost hand chan args no} {
  272. if {[bs_flood $nick $uhost]} {return 0}
  273. global botnick bs ; set i 0
  274. if {[lsearch -exact $bs(no_pub) [string tolower $chan]] >= 0} {return 0}
  275. if {$bs(log_only) != "" && [lsearch -exact $bs(log_only) [string tolower $chan]] == -1} {return 0}
  276. set args [bs_filt [join $args]]
  277. if {[lsearch -exact $bs(quiet_chan) [string tolower $chan]] >= 0} {set target "notice $nick"} {set target "privmsg $chan"}
  278. if {[string match *\\\** [lindex $args 0]]} {
  279. set output [bs_seenmask $chan $hand $args]
  280. if {$output == "No matches were found."} {putallbots "bs_botsearch 1 \{$target\} $nick $args"}
  281. if {[string match "I'm not on *" $output]} {putallbots "bs_botsearch 1 \{$target\} $nick $args"}
  282. puthelp "$target :$output" ; return $bs(logqueries)
  283. }
  284. set data [bs_filt [string trimright [lindex $args 0] ?!.,]]
  285. if {[string tolower $nick] == [string tolower $data] } {puthelp "$target :$nick, go look in a mirror." ; return $bs(logqueries)}
  286. if {[string tolower $data] == [string tolower $botnick] } {puthelp "$target :$nick, I'm right here. Quit wasting my time!" ; return $bs(logqueries)}
  287. if {[onchan $data $chan]} {puthelp "$target :$nick, $data is right here!" ; return $bs(logqueries)}
  288. set output [bs_output $chan $nick $data $no] ; if {$output == 0} {return 0}
  289. if {[lrange [split $output] 1 4] == "I don't remember seeing"} {putallbots "bs_botsearch 1 \{$target\} $nick $args"}
  290. puthelp "$target :$output" ; return $bs(logqueries)
  291. }
  292. proc bs_output {chan nick data no} {
  293. global botnick bs version bs_list
  294. set data [string tolower [string trimright [lindex $data 0] ?!.,]]
  295. if {$data == ""} {return 0}
  296. if {[string tolower $nick] == $data} {return [concat $nick, go look in a mirror.]}
  297. if {$data == [string tolower $botnick]} {return [concat $nick, I'm right here. Quit wasting my time!]}
  298. if {[string length $data] > $bs(nicksize)} {return 0}
  299. if {$bs(smartsearch) != 1} {set no 1}
  300. if {$no == 0} {
  301. set matches "" ; set hand "" ; set addy ""
  302. if {[lsearch -exact [array names bs_list] $data] != "-1"} {
  303. set addy [lindex $bs_list([string tolower $data]) 1] ; set hand [finduser $addy]
  304. foreach item [bs_seenmask dcc ? [maskhost $addy]] {if {[lsearch -exact $matches $item] == -1} {set matches "$matches $item"}}
  305. }
  306. if {[validuser $data]} {set hand $data}
  307. if {$hand != "*" && $hand != ""} {
  308. if {[string trimleft [lindex $version 1] 0]>1030000} {set hosts [getuser $hand hosts]} {set hosts [gethosts $hand]}
  309. foreach addr $hosts {
  310. foreach item [string tolower [bs_seenmask dcc ? $addr]] {
  311. if {[lsearch -exact [string tolower $matches] [string tolower $item]] == -1} {set matches [concat $matches $item]}
  312. }
  313. }
  314. }
  315. if {$matches != ""} {
  316. set matches [string trimleft $matches " "]
  317. set len [llength $matches]
  318. if {$len == 1} {return [bs_search $chan [lindex $matches 0]]}
  319. if {$len > 99} {return [concat I found $len matches to your query\; please refine it to see any output.]}
  320. set matches [bs_sort $matches]
  321. set key [lindex $matches 0]
  322. if {[string tolower $key] == [string tolower $data]} {return [bs_search $chan $key]}
  323. if {$len <= 5} {
  324. set output [concat I found $len matches to your query (sorted): [join $matches].]
  325. set output [concat $output [bs_search $chan $key]] ; return $output
  326. } {
  327. set output [concat I found $len matches to your query. Here are the 5 most recent (sorted): [join [lrange $matches 0 4]].]
  328. set output [concat $output [bs_search $chan $key]] ; return $output
  329. }
  330. }
  331. }
  332. set temp [bs_search $chan $data]
  333. if {$temp != 0} { return $temp } {
  334. #$data not found in $bs_list, so search userfile
  335. if {![validuser [bs_filt $data]] || [string trimleft [lindex $version 1] 0]<1030000} {
  336. return "$nick, I don't remember seeing $data."
  337. } {
  338. set seen [getuser $data laston]
  339. if {[getuser $data laston] == ""} {return "$nick, I don't remember seeing $data."}
  340. if {($chan != [lindex $seen 1] || $chan == "bot" || $chan == "msg" || $chan == "dcc") && [validchan [lindex $seen 1]] && [lindex [channel info [lindex $seen 1]] 23] == "+secret"} {
  341. set chan "-secret-"
  342. } {
  343. set chan [lindex $seen 1]
  344. }
  345. return [concat $nick, $data was last seen on $chan [bs_when [lindex $seen 0]] ago.]
  346. }
  347. }
  348. }
  349. proc bs_search {chan n} {
  350. global bs_list ; if {![info exists bs_list]} {return 0}
  351. if {[lsearch -exact [array names bs_list] [string tolower $n]] != "-1"} {
  352. #bugfix: let's see if the split added below fixes the eggdrop1.4.2 truncation bug
  353. set data [split $bs_list([string tolower $n])]
  354. #bugfix: added a join on the $n (c)
  355. set n [join [lindex $data 0]] ; set addy [lindex $data 1] ; set time [lindex $data 2] ; set marker 0
  356. if {([string tolower $chan] != [string tolower [lindex $data 4]] || $chan == "dcc" || $chan == "msg" || $chan == "bot") && [validchan [lindex $data 4]] && [lindex [channel info [lindex $data 4]] 23] == "+secret"} {
  357. set chan "-secret-"
  358. } {
  359. set chan [lindex $data 4]
  360. }
  361. switch -- [lindex $data 3] {
  362. part {
  363. set reason [lrange $data 5 e]
  364. if {$reason == ""} {set reason "."} {set reason " stating \"$reason\"."}
  365. set output [concat $n ($addy) was last seen parting $chan [bs_when $time] ago$reason]
  366. }
  367. quit { set output [concat $n ($addy) was last seen quitting from $chan [bs_when $time] ago stating ([join [lrange $data 5 e]]).] }
  368. 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]]).] }
  369. rnck {
  370. set output [concat $n ($addy) was last seen changing nicks from [lindex $data 5] on [lindex $data 4] [bs_when $time] ago.]
  371. if {[validchan [lindex $data 4]]} {
  372. if {[onchan $n [lindex $data 4]]} {
  373. set output [concat $output $n is still there.]
  374. } {
  375. set output [concat $output I don't see $n now, though.]
  376. }
  377. }
  378. }
  379. nick {
  380. set output [concat $n ($addy) was last seen changing nicks to [lindex $data 5] on [lindex $data 4] [bs_when $time] ago.]
  381. }
  382. splt { set output [concat $n ($addy) was last seen parting $chan due to a split [bs_when $time] ago.] }
  383. rejn {
  384. set output [concat $n ($addy) was last seen rejoining $chan from a split [bs_when $time] ago.]
  385. 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.]}}
  386. }
  387. join {
  388. set output [concat $n ($addy) was last seen joining $chan [bs_when $time] ago.]
  389. 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.]}}
  390. }
  391. away {
  392. set reason [lrange $data 5 e]
  393. if {$reason == ""} {
  394. set output [concat $n ($addy) was last seen returning to the partyline on $chan [bs_when $time] ago.]
  395. } {
  396. set output [concat $n ($addy) was last seen being marked as away ($reason) on $chan [bs_when $time] ago.]
  397. }
  398. }
  399. chon {
  400. set output [concat $n ($addy) was last seen joining the partyline [bs_when $time] ago.] ; set lnick [string tolower $n]
  401. 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}}
  402. if {$marker == 0} {set output [concat $output I don't see $n on the partyline now, though.]}
  403. }
  404. chof {
  405. set output [concat $n ($addy) was last seen leaving the partyline [bs_when $time] ago.] ; set lnick [string tolower $n]
  406. 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}}
  407. }
  408. chjn {
  409. set output [concat $n ($addy) was last seen joining the partyline on $chan [bs_when $time] ago.] ; set lnick [string tolower $n]
  410. 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}}
  411. if {$marker == 0} {set output [concat $output I don't see $n on the partyline now, though.]}
  412. }
  413. chpt {
  414. set output [concat $n ($addy) was last seen leaving the partyline from $chan [bs_when $time] ago.] ; set lnick [string tolower $n]
  415. 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}}
  416. }
  417. default {set output "error"}
  418. } ; return $output
  419. } {return 0}
  420. }
  421. proc bs_when {lasttime} {
  422. #This is equiv to mIRC's $duration() function
  423. set years 0 ; set days 0 ; set hours 0 ; set mins 0 ; set time [expr [unixtime] - $lasttime]
  424. if {$time < 60} {return "only $time seconds"}
  425. if {$time >= 31536000} {set years [expr int([expr $time/31536000])] ; set time [expr $time - [expr 31536000*$years]]}
  426. if {$time >= 86400} {set days [expr int([expr $time/86400])] ; set time [expr $time - [expr 86400*$days]]}
  427. if {$time >= 3600} {set hours [expr int([expr $time/3600])] ; set time [expr $time - [expr 3600*$hours]]}
  428. if {$time >= 60} {set mins [expr int([expr $time/60])]}
  429. if {$years == 0} {set output ""} elseif {$years == 1} {set output "1 year,"} {set output "$years years,"}
  430. if {$days == 1} {lappend output "1 day,"} elseif {$days > 1} {lappend output "$days days,"}
  431. if {$hours == 1} {lappend output "1 hour,"} elseif {$hours > 1} {lappend output "$hours hours,"}
  432. if {$mins == 1} {lappend output "1 minute"} elseif {$mins > 1} {lappend output "$mins minutes"}
  433. return [string trimright [join $output] ", "]
  434. }
  435. proc bs_add {nick data} {
  436. global bs_list bs
  437. if {[lsearch -exact $bs(no_log) [string tolower [lindex $data 3]]] >= 0 || ($bs(log_only) != "" && [lsearch -exact $bs(log_only) [string tolower [lindex $data 3]]] == -1)} {return}
  438. set bs_list([string tolower $nick]) "[bs_filt $nick] $data"
  439. }
  440. bind time - "*1 * * * *" bs_trim
  441. proc bs_lsortcmd {a b} {global bs_list ; set a [lindex $bs_list([string tolower $a]) 2] ; set b [lindex $bs_list([string tolower $b]) 2] ; if {$a > $b} {return 1} elseif {$a < $b} {return -1} {return 0}}
  442. proc bs_trim {min h d m y} {
  443. global bs bs_list ; if {![info exists bs_list] || ![array exists bs_list]} {return} ; set list [array names bs_list] ; set range [expr [llength $list] - $bs(limit) - 1] ; if {$range < 0} {return}
  444. set list [lsort -increasing -command bs_lsortcmd $list] ; foreach item [lrange $list 0 $range] {unset bs_list($item)}
  445. }
  446. proc bs_seenmask {ch nick args} {
  447. global bs_list bs ; set matches "" ; set temp "" ; set i 0 ; set args [join $args] ; set chan [lindex $args 1]
  448. if {$chan != "" && [string trimleft $chan #] != $chan} {
  449. if {![validchan $chan]} {return "I'm not on $chan."} {set chan [string tolower $chan]}
  450. } { set $chan "" }
  451. if {![info exists bs_list]} {return "No matches were found."} ; set data [bs_filt [string tolower [lindex $args 0]]]
  452.  
  453. #bugfix: unnecessarily complex masks essentially freeze the bot
  454. set maskfix 1
  455. while $maskfix {
  456. set mark 1
  457. if [regsub -all -- \\?\\? $data ? data] {set mark 0}
  458. if [regsub -all -- \\*\\* $data * data] {set mark 0}
  459. if [regsub -all -- \\*\\? $data * data] {set mark 0}
  460. if [regsub -all -- \\?\\* $data * data] {set mark 0}
  461. if $mark {break}
  462. }
  463.  
  464. set id [array startsearch bs_list]
  465. while {[array anymore bs_list $id]} {
  466. 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]
  467. if {[string match $data $item![string tolower $addy]]} {
  468. set match [bs_filt $match] ; if {$chan != ""} {
  469. if {[string match $chan [string tolower [lindex $bs_list($item) 4]]]} {set matches [concat $matches $match]}
  470. } {set matches [concat $matches $match]}
  471. }
  472. }
  473. array donesearch bs_list $id
  474. set matches [string trim $matches " "]
  475. if {$nick == "?"} {return [bs_filt $matches]}
  476. set len [llength $matches]
  477. if {$len == 0} {return "No matches were found."}
  478. if {$len == 1} {return [bs_output $ch $nick $matches 1]}
  479. if {$len > 99} {return "I found $len matches to your query; please refine it to see any output."}
  480. set matches [bs_sort $matches]
  481. if {$len <= 5} {
  482. set output [concat I found $len matches to your query (sorted): [join $matches].]
  483. } {
  484. set output "I found $len matches to your query. Here are the 5 most recent (sorted): [join [lrange $matches 0 4]]."
  485. }
  486. return [concat $output [bs_output $ch $nick [lindex [split $matches] 0] 1]]
  487. }
  488. proc bs_sort {data} {global bs_list ; set data [bs_filt [join [lsort -decreasing -command bs_lsortcmd $data]]] ; return $data}
  489. bind dcc -|- seenstats bs_dccstats
  490. proc bs_dccstats {hand idx args} {putdcc $idx "[bs_stats]"; return 1}
  491. bind pub -|- [string trim $bs(cmdchar)]seenstats bs_pubstats
  492. proc bs_pubstats {nick uhost hand chan args} {
  493. global bs ; if {[bs_flood $nick $uhost] || [lsearch -exact $bs(no_pub) [string tolower $chan]] >= 0 || ($bs(log_only) != "" && [lsearch -exact $bs(log_only) [string tolower $chan]] == -1)} {return 0}
  494. if {[lsearch -exact $bs(quiet_chan) [string tolower $chan]] >= 0} {set target "notice $nick"} {set target "privmsg $chan"} ; puthelp "$target :[bs_stats]" ; return 1
  495. }
  496. bind msg -|- seenstats bs_msgstats
  497. proc bs_msgstats {nick uhost hand args} {global bs ; if {[bs_flood $nick $uhost]} {return 0} ; puthelp "notice $nick :[bs_stats]" ; return $bs(logqueries)}
  498. proc bs_stats {} {
  499. global bs_list bs ; set id [array startsearch bs_list] ; set bs_record [unixtime] ; set totalm 0 ; set temp ""
  500. while {[array anymore bs_list $id]} {
  501. set item [array nextelement bs_list $id]
  502. set tok [lindex $bs_list($item) 2] ; if {$tok == ""} {putlog "Damaged seen record: $item" ; continue}
  503. if {[lindex $bs_list($item) 2] < $bs_record} {set bs_record [lindex $bs_list($item) 2] ; set name $item}
  504. set addy [string tolower [maskhost [lindex $bs_list($item) 1]]] ; if {[lsearch -exact $temp $addy] == -1} {incr totalm ; lappend temp $addy}
  505. }
  506. array donesearch bs_list $id
  507. 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."
  508. }
  509. bind dcc -|- chanstats bs_dccchanstats
  510. proc bs_dccchanstats {hand idx args} {
  511. if {$args == "{}"} {set args [console $idx]}
  512. if {[lindex $args 0] == "*"} {putdcc $idx "$hand, chanstats requires a channel arg, or a valid console channel." ; return 1}
  513. putdcc $idx "[bs_chanstats [lindex $args 0]]"
  514. return 1
  515. }
  516. bind pub -|- [string trim $bs(cmdchar)]chanstats bs_pubchanstats
  517. proc bs_pubchanstats {nick uhost hand chan args} {
  518. global bs ; set chan [string tolower $chan]
  519. if {[bs_flood $nick $uhost] || [lsearch -exact $bs(no_pub) $chan] >= 0 || ($bs(log_only) != "" && [lsearch -exact $bs(log_only) [string tolower $chan]] == -1)} {return 0}
  520. if {[lsearch -exact $bs(quiet_chan) $chan] >= 0} {set target "notice $nick"} {set target "privmsg $chan"}
  521. if {[lindex $args 0] != ""} {set chan [lindex $args 0]} ; puthelp "$target :[bs_chanstats $chan]" ; return $bs(logqueries)
  522. }
  523. bind msg -|- chanstats bs_msgchanstats
  524. proc bs_msgchanstats {nick uhost hand args} {global bs ; if {[bs_flood $nick $uhost]} {return 0} ; puthelp "notice $nick :[bs_chanstats [lindex $args 0]]" ; return $bs(logqueries)}
  525. proc bs_chanstats {chan} {
  526. global bs_list ; set chan [string tolower $chan] ; if {![validchan $chan]} {return "I'm not on $chan."}
  527. set id [array startsearch bs_list] ; set bs_record [unixtime] ; set totalc 0 ; set totalm 0 ; set temp ""
  528. while {[array anymore bs_list $id]} {
  529. set item [array nextelement bs_list $id] ; set time [lindex $bs_list($item) 2] ; if {$time == ""} {continue}
  530. if {$chan == [string tolower [lindex $bs_list($item) 4]]} {
  531. if {$time < $bs_record} {set bs_record $time} ; incr totalc
  532. set addy [string tolower [maskhost [lindex $bs_list($item) 1]]]
  533. if {[lsearch -exact $temp $addy] == -1} {incr totalm ; lappend temp $addy}
  534. }
  535. }
  536. array donesearch bs_list $id ; set total [array size bs_list]
  537. 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]."
  538. }
  539. foreach chan [string tolower [channels]] {if {![info exists bs_botidle($chan)]} {set bs_botidle($chan) [unixtime]}}
  540. bind join -|- * bs_join_botidle
  541. proc bs_join_botidle {nick uhost hand chan} {
  542. global bs_botidle botnick
  543. if {$nick == $botnick} {
  544. set bs_botidle([string tolower $chan]) [unixtime]
  545. }
  546. }
  547. bind pub -|- [string trim $bs(cmdchar)]lastspoke lastspoke
  548.  
  549. #bugfix: fixed lastspoke to handle [blah] nicks better (c)
  550. proc lastspoke {nick uhost hand chan args} {
  551. global bs botnick bs_botidle
  552. set chan [string tolower $chan] ; if {[bs_flood $nick $uhost] || [lsearch -exact $bs(no_pub) $chan] >= 0 || ($bs(log_only) != "" && [lsearch -exact $bs(log_only) $chan] == -1)} {return 0}
  553. if {[lsearch -exact $bs(quiet_chan) $chan] >= 0} {set target "notice $nick"} {set target "privmsg $chan"}
  554. set data [lindex [bs_filt [join $args]] 0]
  555. set ldata [string tolower $data]
  556. if {[string match *\** $data]} {
  557. set chanlist [string tolower [chanlist $chan]]
  558. if {[lsearch -glob $chanlist $ldata] > -1} {set data [lindex [chanlist $chan] [lsearch -glob $chanlist $ldata]]}
  559. }
  560. if {[onchan $data $chan]} {
  561. if {$ldata == [string tolower $botnick]} {puthelp "$target :$nick, must you waste my time?" ; return 1}
  562. set time [getchanidle $data $chan] ; set bottime [expr ([unixtime] - $bs_botidle($chan))/60]
  563. if {$time < $bottime} {
  564. if {$time > 0} {set diftime [bs_when [expr [unixtime] - $time*60 -15]]} {set diftime "less than a minute"}
  565. puthelp "$target :$data last uttered a word on $chan $diftime ago."
  566. } {
  567. set diftime [bs_when $bs_botidle($chan)]
  568. puthelp "$target :$data hasn't uttered a word since I joined $chan $diftime ago."
  569. }
  570. }
  571. return 1
  572. }
  573. bind msgm -|- "help seen" bs_help_msg_seen
  574. bind msgm -|- "help chanstats" bs_help_msg_chanstats
  575. bind msgm -|- "help seenstats" bs_help_msg_seenstats
  576. proc bs_help_msg_seen {nick uhost hand args} {
  577. global bs ; if {[bs_flood $nick $uhost]} {return 0}
  578. puthelp "notice $nick :### seen <query> \[chan\] $bs(version)"
  579. puthelp "notice $nick : Queries can be in the following formats:"
  580. puthelp "notice $nick : 'regular': seen lamer; seen lamest "
  581. puthelp "notice $nick : 'masked': seen *l?mer*; seen *.lame.com; seen *.edu #mychan" ; return 0
  582. }
  583. proc bs_help_msg_chanstats {nick uhost hand args} {
  584. global bs ; if {[bs_flood $nick $uhost]} {return 0}
  585. puthelp "notice $nick :### chanstats <chan> $bs(version)"
  586. puthelp "notice $nick : Returns the usage statistics of #chan in the seen database." ; return 0
  587. }
  588. proc bs_help_msg_seenstats {nick uhost hand args} {
  589. global bs ; if {[bs_flood $nick $uhost]} {return 0}
  590. puthelp "notice $nick :### seenstats $bs(version)"
  591. puthelp "notice $nick : Returns the status of the bseen database." ; return 0
  592. }
  593. bind dcc -|- seenversion bs_version
  594. proc bs_version {hand idx args} {global bs ; putidx $idx "### Bass's Seen script, $bs(version)."}
  595. bind dcc -|- help bs_help_dcc
  596. proc bs_help_dcc {hand idx args} {
  597. global bs
  598. switch -- $args {
  599. seen {
  600. putidx $idx "### seen <query> \[chan\] $bs(version)" ; putidx $idx " Queries can be in the following formats:"
  601. putidx $idx " 'regular': seen lamer; seen lamest " ; putidx $idx " 'masked': seen *l?mer*; seen *.lame.com; seen *.edu #mychan"
  602. }
  603. seennick {putidx $idx "### seen <nick> $bs(version)"}
  604. chanstats {putidx $idx "### chanstats <chan>" ; putidx $idx " Returns the usage statistics of #chan in the seen database."}
  605. seenstats {putidx $idx "### seenstats $bs(version)" ; putidx $idx " Returns the status of the bseen database."}
  606. unseen {if {[matchattr $hand n]} {putidx $idx "### unseen <chan> $bs(version)" ; putidx $idx " Deletes all <chan> entries from the bseen database."}}
  607. default {*dcc:help $hand $idx [join $args] ; return 0}
  608. } ; return 1
  609. }
Add Comment
Please, Sign In to add comment