chiark / gitweb /
Can do "seen" now.
authorijackson <ijackson>
Tue, 15 Aug 2000 13:02:14 +0000 (13:02 +0000)
committerijackson <ijackson>
Tue, 15 Aug 2000 13:02:14 +0000 (13:02 +0000)
bot.tcl

diff --git a/bot.tcl b/bot.tcl
index 1e4d9482610f203867d292e4aef4ecb7d2e8af64..edc249c1dd723ab353bbd7528de81a7298828576 100755 (executable)
--- a/bot.tcl
+++ b/bot.tcl
@@ -76,6 +76,9 @@ proc onread {args} {
         [regexp {^[&#+!]} [lindex $params 0]] &&
         ![regexp {^!} [lindex $params 1]]} {
        # on-channel message, ignore
+       catch {
+           recordlastseen_p $prefix "talking on [lindex $params 0]"
+       }
        return
     }
     log "<- $org"
@@ -104,26 +107,182 @@ proc check_nick {n} {
     if {[regexp {^[-0-9]} $n]} { error "bad nick start" }
 }
 
+proc ischan {dest} {
+    return [regexp {^[&#+!]} $dest]
+}
+
+proc irctolower {v} {
+    foreach {from to} [list "\\\[" "{" \
+                         "\\\]" "}" \
+                         "\\\\" "|" \
+                         "~"    "^"] {
+       regsub -all $from $v $to v
+    }
+    return [string tolower $v]
+}
+
 proc prefix_nick {} {
     global nick
     upvar 1 p p
     upvar 1 n n
     if {![regexp {^([^!]+)!} $p dummy n]} { error "not from nick" }
     check_nick $n
-    if {"[string tolower $n]" == "$nick"} { error "from myself" }
+    if {"[irctolower $n]" == "[irctolower $nick]"} { error "from myself" }
+}
+
+proc recordlastseen_n {n how} {
+    global lastseen
+    set lastseen([irctolower $n]) [list $n [clock seconds] $how]
+}
+               
+proc recordlastseen_p {p how} {
+    prefix_nick
+    recordlastseen_n $n $how
+}
+
+proc chanmode_arg {} {
+    upvar 2 args cm_args
+    set rv [lindex $cm_args 0]
+    set cm_args [lreplace cm_args 0 0]
+    return $rv
+}
+
+proc chanmode_o0 {m g p chan} {
+    global nick chandeop
+    prefix_nick
+    set who [chanmode_arg]
+    recordlastseen_p $p "being mean to $who"
+    if {"[irctolower $who]" == "[irctolower $nick]"} {
+       set chandeop($chan) [list [clock seconds] $p]
+    }
 }
 
+proc msg_MODE {p c dest modelist args} {
+    if {![ischan $dest]} return
+    if {[regexp {^\-(.+)$} $modelist dummy modelist]} {
+       set give 0
+    } elseif {[regexp {^\+(.+)$} $modelist dummy modelist]} {
+       set give 1
+    } else {
+       error "invalid modelist"
+    }
+    foreach m [split $modelist] {
+       set procname chanmode_$m$give
+       if {[catch { info body $procname }]} {
+           recordlastseen_p $p "fiddling with $dest"
+       } else {
+           $procname $m $give  $p $dest
+       }
+    }
+}
+
+proc msg_JOIN {p c chan} { recordlastseen_p $p "joining $chan" }
+proc msg_PART {p c chan} { recordlastseen_p $p "leaving $chan" }
+proc msg_QUIT {p c why} { recordlastseen_p $p "leaving ($why)" }
+
 proc msg_PRIVMSG {p c dest text} {
     prefix_nick
-    if {[regexp {^[&#+!]} $dest]} {
-       set what "!..."
-       set them it
+    if {[ischan $dest]} {
+       recordlastseen_n $n "invoking me in $dest"
+       set output $dest
     } else {
-       set what "private messages"
-       set them them
+       recordlastseen_n $n "talking to me"
+       set output $n
+    }
+
+    if {[catch {
+       regsub {^! *} $text {} text
+       set ucmd [ta_word]
+       set procname ucmd_[string tolower $ucmd]
+       if {[catch { info body $procname }]} {
+           error "unknown command; try help for help"
+       }
+       $procname
+    } rv]} {
+       sendout PRIVMSG $n "error: $rv"
+    } else {
+       foreach {td val} [list $n [lindex $rv 0] $output [lindex $rv 1]] {
+           foreach l [split $val "\n"] {
+               sendout PRIVMSG $td $l
+           }
+       }
+    }
+}
+
+proc ta_nomore {} {
+    upvar 1 text text
+    if {[string length $text]} { error "too many parameters" }
+}
+
+proc ta_word {} {
+    upvar 1 text text
+    if {![regexp {^([^         ]+) *(.*)} $text dummy firstword text]} {
+       error "too few parameters"
+    }
+    return $firstword
+}
+
+proc ta_nick {} {
+    upvar 1 text text
+    set v [ta_word]
+    check_nick $v
+    return $v
+}
+
+proc ucmdr {priv pub} {
+    return -code return [list $priv $pub]
+}
+    
+proc ucmd_help {} {
+    upvar 1 text text
+    ta_nomore
+    ucmdr \
+{Commands currently understood:
+help
+seen <nick>} {}
+}
+
+proc manyset {list args} {
+    foreach val $list var $args {
+       upvar 1 $var my
+       set my $val
+    }
+}
+
+proc ucmd_seen {} {
+    global lastseen nick
+    upvar 1 text text
+    set n [irctolower [ta_nick]]
+    ta_nomore
+    if {"$n" == "[irctolower $nick]"} {
+       error "I am not self-aware."
+    } elseif {![info exists lastseen($n)]} {
+       ucmdr {} "I've never seen $n."
+    } else {
+       manyset $lastseen($n) realnick time what
+       set howlong [expr {[clock seconds] - $time}]
+       if {$howlong <= 0} {
+           set string now
+       } elseif {$howlong < 1000} {
+           set string "${howlong}s ago"
+       } else {
+           if {$howlong < 1000000} {
+               set pfx k
+               set scale 1000
+           } else {
+               set pfx M
+               set scale 1000000
+           }
+           set value [expr "$howlong.0 / $scale"]
+           foreach {min format} {100 %.0f 10 %.1f 1 %.2f} {
+               if {$value < $min} continue
+               set string [format "$format${pfx}s ago" $value]
+               break
+           }
+       }
+       if {![info exists string]} { set string now }
+       ucmdr {} "I last saw $realnick $string, $what."
     }
-    sendout PRIVMSG $n \
-           "I will respond to $what at some point; for now I just log $them."
 }
 
 if {![info exists sock]} {