Really do not report unused monitors
[ircbot] / irccore.tcl
index 0efb0e9..545446c 100644 (file)
@@ -1,23 +1,23 @@
 proc defset {varname val} {
-    upvar #0 $varname var
+    upvar 1 $varname var
     if {![info exists var]} { set var $val }
 }
 
 # must set host
 defset port 6667
+defset socketargs {}
 
 defset nick testbot
+defset ident blight
 defset ownfullname "testing bot"
 defset ownmailaddr test-irc-bot@example.com
 
-defset musthaveping_ms 10000
+defset muststartby_ms 10000
 defset out_maxburst 6
 defset out_interval 2100
 defset out_lag_lag 5000
 defset out_lag_very 25000
-
-defset marktime_min 300
-defset marktime_join_startdelay 5000
+defset ownping_every 300000
 
 proc manyset {list args} {
     foreach val $list var $args {
@@ -141,6 +141,10 @@ proc sendout {command args} { eval sendout_priority [list 0 $command] $args }
 proc log {data} {
     puts $data
 }
+    
+proc log_intern {what data} {
+    puts "[clock seconds] ++ $what $data"
+}
 
 proc logerror {data} {
     log $data
@@ -162,23 +166,22 @@ proc bgerror {msg} {
 }
 
 proc onread {args} {
-    global sock nick calling_nick errorInfo errorCode
-    
-    if {[gets $sock line] == -1} { fail "EOF/error on input" }
+    global sock nick calling_nick errorInfo errorCode line_org_endchar
+
+    if {[catch { gets $sock line } rv]} { fail "error on input: $rv" }
+    if {$rv == -1} { fail "EOF on input" }
+
+    set line_org_endchar [string range $line end end]
     regsub -all "\[^ -\176\240-\376\]" $line ? line
     set org $line
     
-    set ei $errorInfo
-    set ec $errorCode
-    catch { unset calling_nick }
-    set errorInfo $ei
-    set errorCode $ec
+    new_event
     
     if {[regexp -nocase {^:([^ ]+) (.*)} $line dummy prefix remain]} {
        set line $remain
        if {[regexp {^([^!]+)!} $prefix dummy maybenick]} {
            set calling_nick $maybenick
-           if {"[irctolower $maybenick]" == "[irctolower $nick]"} return
+           if {![ircnick_compare $maybenick $nick]} return
        }
     } else {
        set prefix {}
@@ -199,7 +202,8 @@ proc onread {args} {
        log "junk at end: $org"
        return
     }
-    if {"$command" == "PRIVMSG" && [privmsg_unlogged $prefix $params]} {
+    if {![string compare $command "PRIVMSG"] && \
+        [privmsg_unlogged $prefix [ischan [lindex $params 0]] $params]} {
        return
     }
     log "[clock seconds] <- $org"
@@ -213,6 +217,20 @@ proc onread {args} {
     }
 }
 
+proc catch_restoreei {body} {
+    global errorInfo errorCode
+    set l [list $errorInfo $errorCode]
+    catch { uplevel 1 $body }
+    manyset $l errorInfo errorCode
+}
+
+proc catch_logged {body} {
+    global errorInfo
+    if {[catch { uplevel 1 $body } emsg]} {
+       logerror "error (catch_logged): $emsg\n $errorInfo"
+    }
+}
+
 proc sendprivmsg {dest l} {
     foreach v [split $l "\n"] {
        sendout [expr {[ischan $dest] ? "PRIVMSG" : "NOTICE"}] $dest $v
@@ -227,6 +245,14 @@ proc msendprivmsg_delayed {delay dest ll} { after $delay [list msendprivmsg $des
 proc check_nick {n} {
     if {[regexp -nocase {[^][\\`_^{|}a-z0-9-]} $n]} { error "bad char in nick" }
     if {[regexp {^[-0-9]} $n]} { error "bad nick start" }
+    if {[string length $n] > 18} { error "nick too long" }
+}
+
+proc check_chan {n} {
+    if {![regsub {^\#} $n {} n]} { error "bad chan start" }
+    if {[regexp -nocase {[^][\\`_^{|}a-z0-9-]} $n]} { error "bad char in chan" }
+    if {[regexp {^[-0-9]} $n]} { error "bad chan name start" }
+    if {[string length $n] > 18} { error "chan name too long" }
 }
 
 proc ischan {dest} {
@@ -243,9 +269,77 @@ proc irctolower {v} {
     return [string tolower $v]
 }
 
+proc ircnick_compare {a b} {
+    return [string compare [irctolower $a] [irctolower $b]]
+}
+
+proc prefix_none {} {
+    upvar 1 p p
+    if {[string length $p]} { error "prefix specified" }
+}
+
+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 {![ircnick_compare $n $nick]} {
+       error "from myself" {} {}
+    }
+}
+
 proc msg_PING {p c s1} {
-    global musthaveping_after
     prefix_none
     sendout PONG $s1
-    if {[info exists musthaveping_after]} connected
+}
+
+proc sendownping {} {
+    global ownping_every nick
+    sendout ping $nick
+    after $ownping_every sendownping
+}
+
+proc msg_001 {args} {
+    global muststartby_after
+    if {[info exists muststartby_after]} {
+       after cancel $muststartby_after
+       unset muststartby_after
+       sendownping
+       connected
+    }
+}
+
+proc ensure_outqueue {} {
+    out__vars
+    if {[info exists out_queue]} return
+    set out_creditms 0
+    set out_creditat [clock seconds]
+    set out_queue {}
+    set out_lag_reported 0
+    set out_lag_reportwhen $out_creditat
+}
+
+proc fail {msg} {
+    logerror "failing: $msg"
+    exit 1
+}
+
+proc ensure_connecting {} {
+    global sock ownfullname host port nick ident socketargs
+    global muststartby_ms muststartby_after
+
+    ensure_outqueue
+    
+    if {[info exists sock]} return
+    set sock [eval socket $socketargs [list $host $port]]
+    fconfigure $sock -buffering line
+    fconfigure $sock -translation crlf
+
+    sendout USER $ident 0 * $ownfullname
+    sendout NICK $nick
+    fileevent $sock readable onread
+
+    set muststartby_after [after $muststartby_ms \
+           {fail "no successfuly connect within timeout"}]
 }