##### # !!!!!!! NOT A OFFICIAL RELEASE !!!!!!!! # Multichannel seen implementation by PreSSo (andrejp@luz.fe.uni-lj.si) # loosely based on seen by Robey # will show when nicks were last seen on the channel(s) no matter # if they are on the bot's userlist or not. # requires eggdrop 1.3.x bot # needs adbtools.tcl loaded! # Repaired by Ze_PilOt for 1.3.x # # HISTORY: # version 1.0 (dunno exactly, been a while) # version 1.1 (6 Aug, 1996) # - various small fixes # version 1.2 (18 Aug, 1996) # - new faster check_expired (this one really blows the socks off:) # - changed default nickexpire to 30 days # - various small changes # version 1.3 (18 Aug, 1996) # - added configurable bind msg/pub flags for users (see settings) # version 1.4 (1 Sep, 1996) # - added force update command. this was needed to fix the # bug where bot was showing incorrect seen info for users # that were added to the bot's userlist after they were # already in the seen nicks list (.seenupd) # - added dcc seen command # version 1.5 (2 Oct, 1996) # - the script now also reports how the user left (leave, kick..) # - old seen.nicks file is no longer valid (delete it) # - shows the channel where nick was last on for all nicks, not # just valid users (the code was already there, just not used:) # version 1.6 (17 Jan, 1997) # - the bot now reports 'one of my channels' instead of '#channel' # if the channel is marked +secret # version 1.7 (24 Jan, 1997) # - cosmetical fixes # version 1.8 (25 Jan, 1997) # - err...:) a little bug fix:) It won't putlog stupid things now:) # version 1.9 (29 Jul, 1997) # - changed and tuned script, so it should run on 1.1.5 now # Times for checking for expires (60 M.) and nicksaving (15 M.) are # now hardcoded, hey... who cares? I for my part don#t know why it # wouldn#t work with variables... Blackb|rd # version 1.9.1 (10 Aug, 1997) # - "corrected" and "rewrote" some of the answers (the grammar part # wasn't very good - my opinion... :)) - Queux # version 1.9.2 (16 Dec, 1997) (non official release !!!) # - I upgraded the script to use with eggdrop 1.3.x .. The seen on the # party don't work at 100%, but work perfectly on a channel ... # # COMMANDS: # dcc, msg: seen # public: !seen # # TODO: # - nicks get added to the nicklist even though they are valid bot users - fix this # - do a configurable 'reply on seen nick' ##### ### *** SETTINGS! *** # filename of the file where nicks list will be saved # (defaults to seen.nicks) set seennicks {seen.nicks} # save nicks each (this setting) minutes (defaults to 15 # minutes) set nicksavetime 10 # check for expired users on every this much minutes # this should be set to a reasonable value like one hour or # one day or something like that (defaults to 60 minutes) set expirechk 30 # time in hours for the nick that is NOT on the bot's # userlist to expire. this keeps the seennicks file from # getting huge (defaults to 720 hours -> 30 days) set nickexpire 336 ### # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # !!! DO NOT CHANGE ANYTHING BELOW THIS LINE !!! # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ### set seenver "adbseen.tcl v1.9.2fr" if {!([info exists seenpubf])} {set seenpubf "-"} if {!([info exists seenmsgf])} {set seenmsgf "-"} set nlist "" # delete fake/existing userlist users from the seennicks list proc seen_del_existing {uhand} { global nlist # delete nicks if the user exists in the userlist append fwho "+" $uhand set ind [lsearch -exact $nlist [string tolower $fwho]] set deld 0 if {$ind != -1} { set nlist [lreplace $nlist $ind [expr $ind + 3]] return 1 } return 0 } # force nick update proc force_seenupd {hand idx arg} { global seennicks if {[llength $arg] < 1} { #update all users putdcc $idx "Updating seen information for all users in the userlist..." set deld 0 foreach uhand [userlist] { incr deld [seen_del_existing $uhand] } if {$deld} { putdcc $idx "Removed $deld nick(s) from nicks list that existed in the userlist." } } else { #update specified nicks foreach uhand $arg { seen_del_existing $uhand } } putdcc $idx "Update complete." } # update nick's status.. proc nick_upd {chan nick uhand how} { global nlist #set uhand [string tolower $uhand] if {$uhand!="*"} { # this user is a valid user setlaston $uhand setuser $uhand XTRA seenon $chan setuser $uhand XTRA seenhow $how # delete possible fake user entry in the nick list append fwho "-" $uhand set ind [lsearch -exact $nlist [string tolower $fwho]] if {$ind != -1} { set nlist [lreplace $nlist $ind [expr $ind + 3]] } seen_del_existing $uhand return 1 } else { # this user is NOT a valid user.. if {[validuser $nick]} { # ..but he's using the nick of one of the valid users! append mnick "-" [string tolower $nick] } else { # ..and he's using his own nick.. (this one will most probably only happen to $botnick) append mnick "+" [string tolower $nick] } } set timeon [unixtime] set ind [lsearch -exact $nlist $mnick] if {($ind >= 0)} { #found nick! replace it set nlist [lreplace $nlist [expr $ind + 1] [expr $ind + 3] $timeon $chan $how] } else { #nick nonexistant. append to the list lappend nlist $mnick $timeon $chan $how } } # save nicks proc dcc_nick_save {hand idx arg} { global seennicks nick_save putdcc $idx "Nicks saved to file ${seennicks}" } proc nick_save {} { global seennicks nlist nicksavetime set f [open $seennicks w] puts $f $nlist close $f timer $nicksavetime "nick_save" } # delete expired users from the list proc check_expired {} { global nickexpire expirechk nlist putlog "-Seen- Checking for expired users. The bot will not respond until it's finished." set total [expr [llength $nlist] - 1] set mtotal [expr $total / 4] set nulist "" set nrdel 0 set ind 0 set nrtot 0 foreach ent $nlist { switch $ind { 0 { set nik $ent set ind 1 } 1 { set loff $ent set ind 2 } 2 { set lchan $ent set ind 3 } 3 { if {[expr ([unixtime] - $loff) / 3600] < $nickexpire} { #hasn't yet expired, add to the nulist lappend nulist $nik $loff $lchan $ent } else {incr nrdel 1} set ind 0 } } } set nlist $nulist if {$nrdel > 0} { putlog "-Seen- Deleted $nrdel expired nicks out of total $mtotal ([expr 100.0 * $nrdel / $mtotal]%)." } putlog "-Seen- Done. Next check will be done in $expirechk minutes." timer $expirechk "check_expired" } proc putseen {out isdcc text} { if {$isdcc} { putdcc $out $text } else { putserv "PRIVMSG $out :$text" } } # return how left proc adb_seengethow {who} { switch [user-get $who seenhow] { 1 { return "*kicked*" } default { return "on" } } } # return 'one of my channels' if the channel # is +secret # return 'the channel'/'my party line' if the # nick was on the same channel as the user is on # return channel nick was last seen on otherwise proc thechan {whochan userchan} { if {$whochan == "my party line"} { return "my party line" } if {[lsearch [channels] $whochan] == -1} { return $whochan } if {[string tolower $whochan] == [string tolower $userchan]} { return "this channel" } if {[lsearch [channel info $whochan] "+secret"] == -1} { return $whochan } return "" } # show when was last on proc adb_seen {channel nick uhost handle who isdcc} { global nlist botnick set unick "" if {$isdcc == 0} { if {[string compare $channel $nick] != 0} { append unick $nick ": " } } if {$who == ""} { putseen $channel $isdcc "${unick}Correct syntax is 'seen '" return 1 } set who [string trim [lindex $who 0] ?] if {[string compare [string tolower $botnick] [string tolower $who]] == 0} { putseen $channel $isdcc "${unick}Sure, I guess you don't see me now - right ??" return 1 } if {[string compare [string tolower $nick] [string tolower $who]] == 0} { putseen $channel $isdcc "${unick}Aren't you in here right now ?? :)" return 1 } if {$unick==""} { #request via MSG! foreach chan [channels] { if {[onchan $who $chan]} { putseen $channel $isdcc "Hmm... Isn't $who on IRC right now ??" return 1 } if {[onchansplit $who $chan]} { putseen $channel $isdcc "${who} was just on IRC, but got netsplit.. shame, huh?:)" return 1 } foreach i [chanlist $chan] { set hand [finduser $i![getchanhost $i $chan]] if {($hand != "*") && ([string compare [string tolower $hand] [string tolower $who]] == 0)} { if {[onchansplit $i $chan]} { putseen $channel $isdcc "$i is ${who}, and $i was just on [thechan $chan $channel] but got netsplit.." } { putseen $channel $isdcc "$i is ${who}, and $i is on [thechan $chan $channel] right now!" } return 1 } } } } else { #request via PUB! #check if the nick is on YOUR channel if {[onchansplit $who $channel]} { putseen $channel $isdcc "${unick}${who} was just here, but got netsplit.. shame, huh?:)" return 1 } if {[onchan $who $channel]} { putseen $channel $isdcc "${unick}${who} is on the channel right now - look in front of you !!" return 1 } foreach i [chanlist $channel] { set hand [finduser $i![getchanhost $i $channel]] if {($hand != "*") && ([string compare [string tolower $hand] [string tolower $who]] == 0)} { if {[onchansplit $i $channel]} { putseen $channel $isdcc "${unick}$i is ${who}, and $i was just here but got netsplit" } { putseen $channel $isdcc "${unick}$i is ${who}, and $i is on the channel right now!" } return 1 } } #hmm.. obviously not. let's check if he's on other channels we're on set channel [string tolower $channel] foreach chan [channels] { if {[string compare [string tolower $chan] $channel] == 0} { #already did this channel (YOUR channel) continue } if {[onchansplit $who $chan]} { putseen $channel $isdcc "${unick}${who} was just on [thechan $chan $channel] but got netsplit.. shame, huh?:)" return 1 } if {[onchan $who $chan]} { putseen $channel $isdcc "${unick}If I'm not mistaken ${who} is on [thechan $chan $channel] at the moment..." return 1 } foreach i [chanlist $chan] { set hand [finduser $i![getchanhost $i $chan]] if {($hand != "*") && ([string compare [string tolower $hand] [string tolower $who]] == 0)} { if {[onchansplit $i $chan]} { putseen $channel $isdcc "${unick}$i is ${who}, and $i was just on [thechan $chan $channel] but got netsplit.." } { putseen $channel $isdcc "${unick}$i is ${who}, and $i is on [thechan $chan $channel] right now!" } return 1 } } } } if {[hand2idx $who] >= 0} { if {[matchattr $handle p]} { putseen $channel $isdcc "${unick}$who is on my party line right now !!" return 1 } } append fwho "-" $who set find [lsearch -exact $nlist [string tolower $fwho]] if {$find!=-1} { set ind $find set ending " I cannot guarantee that it really was ${who} though (different host than the one I have stored in my userlist) !!" } else { append rwho "+" $who set ind [lsearch -exact $nlist [string tolower $rwho]] set ending "" } if {$ind == -1} { if {[validuser $who]} { set last [getuser $who LASTON $channel] set seenon [thechan [getuser $who XTRA seenon] $channel] switch [getuser $who XTRA seenhow] { 1 { set seenhow "*kicked*" } default { set seenhow "" } } if {$last == 0} { putseen $channel $isdcc "${unick}Sorry, but I haven't seen ${who} recently." return 1 } else { if {$seenon != ""} { putseen $channel $isdcc "${unick}I last saw $who on $seenon - [tdiff [unixtime] $last]ago." } else { putseen $channel $isdcc "${unick}I last saw $who [tdiff [unixtime] $last]ago." } return 1 } } putseen $channel $isdcc "${unick}I haven't seen anyone with the nick - ${who}." return 1 } else { set last [lindex $nlist [expr $ind + 1]] set seenon [thechan [lindex $nlist [expr $ind + 2]] $channel] switch [lindex $nlist [expr $ind + 3]] { 1 { set seenhow "*kicked*" } default { set seenhow "" } } if {($seenhow != "")&&($seenon != "")} { putseen $channel $isdcc "${unick}I last saw $who on $seenon - $seenhow - [tdiff [unixtime] $last]ago." } else { putseen $channel $isdcc "${unick}I last saw $who [tdiff [unixtime] $last]ago." } return 1 } } # time difference proc tdiff {time2 time1} { set ltime [expr $time2 - $time1] set seconds [expr $ltime % 60] set ltime [expr ($ltime - $seconds) / 60] set minutes [expr $ltime % 60] set ltime [expr ($ltime - $minutes) / 60] set hours [expr $ltime % 24] set days [expr ($ltime - $hours) / 24] set result "" if {$days} { append result "$days " if {$days == 1} { append result "day " } else { append result "days " } } if {$hours} { append result "$hours " if {$hours == 1} { append result "hour " } else { append result "hours " } } if {$minutes} { append result "$minutes " if {$minutes == 1} { append result "minute " } else { append result "minutes " } } if {$seconds} { append result " $seconds " if {$seconds == 1} { append result "second " } else { append result "seconds " } } return $result } proc dcc_seen {hand idx arg} { adb_seen $idx $hand "" $hand $arg 1 } bind dcc - seen dcc_seen proc pub_seen {nick uhost hand channel who} { adb_seen $channel $nick $uhost $hand $who 0 } bind pub - seen pub_seen proc msg_seen {nick uhost hand who} { adb_seen $nick $nick $uhost $hand $who 0 } bind msg - seen msg_seen proc seen_join {nick uhost hand channel} { nick_upd $channel $nick $hand 0 } bind join - * seen_join proc seen_part {nick uhost hand channel} { nick_upd $channel $nick $hand 0 } bind part - * seen_part proc seen_sign {nick uhost hand channel reason} { nick_upd $channel $nick $hand 0 } bind sign - * seen_sign proc seen_nickch {nick uhost hand channel newnick} { nick_upd $channel $nick $hand 0 nick_upd $channel $newnick $hand 0 } bind nick - * seen_nickch proc seen_kick {nick uhost hand channel kicked reason} { set hand [nick2hand $kicked $channel] nick_upd $channel $kicked $hand 1 } bind kick - * seen_kick proc seen_chof {hand idx} { nick_upd "my party line" $hand $hand 0 } bind chof - * seen_chof #for testing/emergency nick save only bind dcc m savenicks dcc_nick_save #force deletion of nicks in the nickfile that are in the userlist #(this command should be issued if new users are added to the bot's #userlist) bind dcc m seenupd force_seenupd # script initialization putlog "$seenver loaded" # set defaults if {!([info exists seennicks])} { set seennicks {seen.nicks} } if {!([info exists nicksavetime])} { set nicksavetime 15 } if {!([info exists nickexpire])} { set nickexpire 720 } if {!([info exists expirechk])} { set expirechk 60 } if [file exists $seennicks] { set f [open $seennicks r] if {[gets $f nlist] != -1} { if {[expr [llength $nlist] % 4] != 0} { putlog "-Seen- Invalid nicks list.. Clearing nicks list." set nlist "" } } else { putlog "-Seen- Invalid data file. Nicks list not loaded." set nlist "" } close $f } # update users on the channel foreach chan [channels] { foreach n [chanlist $chan] { set hand [nick2hand $n $chan] nick_upd $chan $n $hand 0 } } nick_save check_expired