chiark / gitweb /
Move rcsid
[ircbot] / bot.tcl
diff --git a/bot.tcl b/bot.tcl
index 4ea4fd8cdd1702be8c2f0f992b17d671683a5181..8f25e2977983a4807d9902148ea95511124c2558 100755 (executable)
--- a/bot.tcl
+++ b/bot.tcl
@@ -18,7 +18,7 @@ proc privmsg_unlogged {prefix ischan params} {
     set chan [lindex $params 0]
     upvar #0 chan_lastactivity([irctolower $chan]) la
     set la [clock seconds]
-    catch_logged { recordlastseen_p $prefix "talking on $chan" 1 }
+    catch_logged { recordlastseen_p $prefix "talking on $chan" 2 }
     return 1
 }
 
@@ -145,11 +145,151 @@ proc looking_whenwhere {when where} {
     return $str
 }
 
+proc check_telling {nl event} {
+    # for all except `talk' we delay 750ms
+    switch -exact $event {
+       none {
+       }
+       talk {
+           check_telling_core $nl talk
+           check_telling_core $nl act
+       }
+       act - come {
+           after 750 [list check_telling_core $nl $event]
+       }
+       default {
+           error "check_telling $nl $event"
+       }
+    }
+}
+
+proc check_telling_core {nl event} {
+    # event is `talk', `act' or `come'
+    # When user talks we actually get talk now and act later
+FIXME - make it be called with come
+FIXME - implement all cmds
+FIXME - implement tells_deliver            set stt [list $u passed $now]
+FIXME - implement tells_delete                     catch { unset stt }   ?
+    set iml [msgdb_get $nl inbound]
+    if {![llength $iml]} return
+
+    upvar #0 nick_telling($nl) telling
+    upvar #0 nick_unique($nl) u
+
+    if {[info exists telling]} {
+       manyset $telling u2 stt telling_when
+       if {"$u2" != "$u"} { unset telling; unset stt; unset telling_when }
+    }
+
+    if {![info exists stt]} {
+       set stt norecord
+       set telling_when $now
+    }
+
+    set ago [expr {$now - $telling_when}]
+
+    # evstate is string of letters
+    #   event
+    #      t   talk
+    #      a   act
+    #      c   come
+    #   security level and timing
+    #      ii  Insecure
+    #      ss  Secure and soon (before interval)
+    #      sl  Secure and late (after interval)
+    #   current state
+    #      n   NORECORD
+    #      m   MENTIONED
+    #      p   PASSED
+    #   reliability and timing
+    #      uu  Unreliable
+    #      rv  Remind, very soon (before within-interval)
+    #      rs  Remind, soon (between)
+    #      rl  Remind, late (aftr every-interval)
+    #      ps  Pester, soon (before interval)
+    #      pl  Pester, late (after interval)
+    #   current identification
+    #      i   Identified
+    #      u   Unidentified
+    #   current visibility
+    #      v   Visible
+    #      h   Hidden (invisible, no unique)
+
+    manyset [nickdb_get $n tellsec] sec secwhen
+    switch -exact $sec {
+       insecure { set evstate ii }
+       secure { set evstate [expr {$ago<$secwhen ? "sl" : "ss"}] }
+       default { set evstate "#$sec#" }
+    }
+
+    append evstate [string range $stt 0 0]
+    
+    manyset [nickdb_set $n tellrel] rel relint relwithin
+    switch -exact $rel {
+       unreliable { append evstate uu }
+       remind { append evstate [expr {
+           $ago<$relwithin ? "rv" : $ago<$relint ? "rs" : "rl"
+       }]}
+       pester { append evstate [expr {$ago<$relint ? "ps" : "pl"}] }
+       default { append evstate "#$rel#" }
+    }
+
+    upvar #0 nick_username($nl) nu
+    if {[info exists nu] && "$nu" == "[nickdb_get $nl username]"} {
+       append evstate i
+    } else {
+       append evstate u
+    }
+
+    append evstate [expr {[info exists u] ? "v" : "h"}]
+
+    switch -glob $evstate {
+       t??prv?v {
+           # consider delivered:
+           #  (very recently passed, and the user talks)
+           tells_delete {} $nl
+       }
+       t??????? {
+           # ignore
+           #   (any other `talk's)
+       }
+       ?iin???? - ?iip?l?? - ?ii????? -
+       ?s?n??iv - ?s?m??iv - ?s?p?liv {
+           # pass messages
+           #  (insecure and not passed recently, or just arriving;
+           #   secure and not passed recently)
+           tells_deliver $nl
+       }
+       ?ssp???? - ???p?s?? - ???p?v?? {
+           # ignore
+           #  (recently mentioned or passed
+           #   immediate `talk' thing)
+       }
+       ?s?n???? - ?slm???? - cs?????? {
+           # mention messages
+           #  (secure and not mentioned recently or just arriving,
+           #           and should not pass)
+           sendprivmsg $nl \
+                   {You have messages (so identify yourself please).}]
+           set stt [list $u mentioned $now]
+       }
+       * {
+           error "check_telling_core nl=$nl evstate=$evstate ?"
+       }
+    }
+}
+
 proc recordlastseen_n {n how here} {
     global lastseen lookedfor
-    set lastseen([irctolower $n]) [list $n [clock seconds] $how]
+    set nl [irctolower $n]
+    set now [clock seconds]
+    set lastseen($nl) [list $n $now $how]
+
     if {!$here} return
-    upvar #0 lookedfor([irctolower $n]) lf
+
+    check_telling $nl [lindex {none act talk} $here]
+
+    upvar #0 lookedfor($nl) lf
     if {[info exists lf]} {
        switch -exact [llength $lf] {
            0 {
@@ -363,9 +503,10 @@ set nick_counter 0
 set nick_arys {onchans username unique}
 # nick_onchans($luser) -> [list ... $lchan ...]
 # nick_username($luser) -> <securely known local username>
-# nick_unique($luser) -> <counter>
+# nick_unique($luser) -> <includes-counter>
 # nick_case($luser) -> $user  (valid even if no longer visible)
 # nick_markid($luser) -> <after id for marktime>
+# nick_telling($luser) -> <unique> mentioned|passed <when>
 
 # chan_nicks($lchan) -> [list ... $luser ...]
 # chan_lastactivity($lchan) -> [clock seconds]
@@ -429,6 +570,7 @@ proc nick_ishere {n} {
 
 proc msg_JOIN {p c chan} {
     prefix_nick
+    nick_ishere $n
     recordlastseen_n $n "joining $chan" 1
     set nl [irctolower $n]
     set lchan [irctolower $chan]
@@ -440,7 +582,6 @@ proc msg_JOIN {p c chan} {
     }
     lappend oc $lchan
     lappend nlist $nl
-    nick_ishere $n
 }
 proc msg_PART {p c chan args} {
     prefix_nick