5 if {![info exists nick
]} { set nick Blight
}
6 if {![info exists ownfullname
]} { set ownfullname
"here to Help" }
7 set ownmailaddr blight
@chiark.greenend.org.uk
9 if {![info exists globalsecret
]} {
10 set gsfile
[open /dev
/urandom r
]
11 fconfigure $gsfile -translation binary
12 set globalsecret
[read $gsfile 32]
13 binary scan $globalsecret H
* globalsecret
18 proc manyset
{list args
} {
19 foreach val
$list var
$args {
25 proc try_except_finally
{try except finally
} {
26 global errorInfo errorCode
27 set er
[catch { uplevel 1 $try } emsg
]
31 if {[catch { uplevel 1 $except } emsg3
]} {
32 append ei
"\nALSO ERROR HANDLING ERROR:\n$emsg3"
35 set er2
[catch { uplevel 1 $finally } emsg2
]
38 append ei
"\nALSO ERROR CLEANING UP:\n$emsg2"
40 return -code $er -errorinfo $ei -errorcode $ec $emsg
42 return -code $er2 -errorinfo $errorInfo -errorcode $errorCode $emsg2
48 proc sendout
{command args
} {
50 if {[llength $args]} {
51 set la
[lindex $args end
]
52 set args
[lreplace $args end end
]
54 if {[regexp {[: ]} $i]} {
55 error "bad argument in output $i ($command $args)"
60 set args
[lreplace $args 0 -1 $command]
61 set string [join $args { }]
62 puts "[clock seconds] -> $string"
70 proc logerror
{data
} {
75 global saveei saveec errorInfo errorCode
80 puts ">$saveec|$saveei<"
90 global sock nick calling_nick errorInfo errorCode
92 if {[gets $sock line
] == -1} { set terminate
1; return }
93 regsub -all "\[^ -\176\240-\376\]" $line ? line
98 catch { unset calling_nick
}
102 if {[regexp -nocase {^
:([^
]+) (.
*)} $line dummy prefix remain
]} {
104 if {[regexp {^
([^
!]+)!} $prefix dummy maybenick
]} {
105 set calling_nick
$maybenick
106 if {"[irctolower $maybenick]" == "[irctolower $nick]"} return
111 if {![string length
$line]} { return }
112 if {![regexp -nocase {^
([0-9a-z
]+) *(.
*)} $line dummy command line
]} {
113 log
"bad command: $org"
116 set command
[string toupper
$command]
118 while {[regexp {^
([^
:]+) *(.
*)} $line dummy thisword line
]} {
119 lappend params
$thisword
121 if {[regexp {^
:(.
*)} $line dummy thisword
]} {
122 lappend params
$thisword
123 } elseif
{[string length
$line]} {
124 log
"junk at end: $org"
127 if {"$command" == "PRIVMSG" &&
128 [regexp {^
[&#+!]} [lindex $params 0]] &&
129 ![regexp {^
!} [lindex $params 1]]} {
130 # on-channel message, ignore
132 recordlastseen_p
$prefix "talking on [lindex $params 0]" 1
136 log
"[clock seconds] <- $org"
137 set procname msg_
$command
138 if {[catch { info body
$procname }]} { return }
140 eval [list $procname $prefix $command] $params
142 logerror
"error: $emsg ($prefix $command $params)"
147 proc sendprivmsg
{dest l
} {
148 foreach v
[split $l "\n"] {
149 sendout
[expr {[ischan
$dest] ?
"PRIVMSG" : "NOTICE"}] $dest $v
152 proc sendaction
{dest what
} { sendout PRIVMSG
$dest "\001ACTION $what\001" }
153 proc msendprivmsg
{dest ll
} { foreach l
$ll { sendprivmsg
$dest $l } }
154 proc msendprivmsg_delayed
{delay dest ll
} { after $delay [list msendprivmsg
$dest $ll] }
156 proc prefix_none
{} {
158 if {[string length
$p]} { error "prefix specified" }
161 proc msg_PING
{p c s1
} {
166 proc check_nick
{n
} {
167 if {[regexp -nocase {[^
][\\`_^
{|
}a-z0-9-
]} $n]} { error "bad char in nick" }
168 if {[regexp {^
[-0-9]} $n]} { error "bad nick start" }
172 return [regexp {^
[&#+!]} $dest]
175 proc irctolower
{v
} {
176 foreach {from to
} [list "\\\[" "{" \
180 regsub -all $from $v $to v
182 return [string tolower
$v]
185 proc prefix_nick
{} {
189 if {![regexp {^
([^
!]+)!} $p dummy n
]} { error "not from nick" }
191 if {"[irctolower $n]" == "[irctolower $nick]"} {
192 error "from myself" {} {}
196 proc showintervalsecs
{howlong
} {
197 return [showintervalsecs
/[opt timeformat
] $howlong]
200 proc showintervalsecs
/ks
{howlong
} {
201 if {$howlong < 1000} {
204 if {$howlong < 1000000} {
211 set value
[expr "$howlong.0 / $scale"]
212 foreach {min
format} {100 %.0f
10 %.1f
1 %.2f
} {
213 if {$value < $min} continue
214 return [format "$format${pfx}s" $value]
219 proc format_qty
{qty unit
} {
223 if {$qty != 1} { append o s
}
227 proc showintervalsecs
/hms
{qty
} {
228 set ul
{second
60 minute
60 hour
24 day
7 week
}
230 while {[llength $ul] > 1 && $qty >= [set uv
[lindex $ul 1]]} {
231 set remainu
[lindex $ul 0]
232 set remainv
[expr {$qty % $uv}]
233 set qty
[expr {($qty-$remainv)/$uv}]
234 set ul
[lreplace $ul 0 1]
236 set o
[format_qty
$qty [lindex $ul 0]]
239 append o
[format_qty
$remainv $remainu]
244 proc showinterval
{howlong
} {
248 return "[showintervalsecs $howlong] ago"
252 proc showtime
{when
} {
253 return [showinterval
[expr {[clock seconds
] - $when}]]
256 proc def_msgproc
{name argl body
} {
257 proc msg_
$name "varbase $argl" "\
258 upvar #0 msg/\$varbase/dest d\n\
259 upvar #0 msg/\$varbase/str s\n\
260 upvar #0 msg/\$varbase/accum a\n\
264 def_msgproc begin
{dest str
} {
270 def_msgproc
append {str
} {
272 if {[string length
$s] && [string length
$ns] > 65} {
273 msg__sendout
$varbase
274 set s
" [string trimleft $str]"
280 def_msgproc finish
{} {
281 msg__sendout
$varbase
287 def_msgproc _sendout
{} {
288 lappend a
[string trimright
$s]
292 proc looking_whenwhere
{when where
} {
293 set str
[showtime
[expr {$when-1}]]
294 if {[string length
$where]} { append str
" on $where" }
298 proc recordlastseen_n
{n how here
} {
299 global lastseen lookedfor
300 set lastseen
([irctolower
$n]) [list $n [clock seconds
] $how]
302 upvar #0 lookedfor([irctolower $n]) lf
303 if {[info exists lf
]} {
304 switch -exact [llength $lf] {
309 manyset
[lindex $lf 0] when who where
311 "FYI, $who was looking for you [looking_whenwhere $when $where]."]
314 msg_begin tosend
$n "FYI, people have been looking for you:"
320 msg_append tosend
" "
321 } elseif
{$i == [llength $lf]} {
322 msg_append tosend
" and "
325 msg_append tosend
", "
327 manyset
$e when who where
329 "$who ([looking_whenwhere $when $where])$fin"
331 set ml
[msg_finish tosend
]
335 msendprivmsg_delayed
1000 $n $ml
339 proc recordlastseen_p
{p how here
} {
341 recordlastseen_n
$n $how $here
344 proc chanmode_arg
{} {
346 set rv
[lindex $cm_args 0]
347 set cm_args
[lreplace cm_args
0 0]
351 proc chanmode_o1
{m g p chan
} {
352 global nick chan_initialop
354 set who
[chanmode_arg
]
355 recordlastseen_n
$n "being nice to $who" 1
356 if {"[irctolower $who]" == "[irctolower $nick]"} {
357 set nl
[irctolower
$n]
358 upvar #0 nick_unique($n) u
359 if {[chandb_exists
$chan]} {
360 sendprivmsg
$n Thanks.
361 } elseif
{![info exists u
]} {
362 sendprivmsg
$n {Op me
while not on the channel
, why don't you ?
}
364 set chan_initialop
([irctolower
$chan]) $u
366 "Thanks. You can use `channel manager ...' to register this channel."
367 if {![nickdb_exists
$n] ||
![string length
[nickdb_get
$n username
]]} {
369 "(But to do that you must register your nick securely first.)"
375 proc chanmode_o0
{m g p chan
} {
378 set who
[chanmode_arg
]
379 recordlastseen_p
$p "being mean to $who" 1
380 if {"[irctolower $who]" == "[irctolower $nick]"} {
381 set chandeop
($chan) [list [clock seconds
] $p]
385 proc msg_MODE
{p c dest modelist args
} {
386 if {![ischan
$dest]} return
387 if {[regexp {^
\-(.
+)$} $modelist dummy modelist
]} {
389 } elseif
{[regexp {^
\+(.
+)$} $modelist dummy modelist
]} {
392 error "invalid modelist"
394 foreach m
[split $modelist] {
395 set procname chanmode_
$m$give
396 if {[catch { info body
$procname }]} {
397 recordlastseen_p
$p "fiddling with $dest" 1
399 $procname $m $give $p $dest
404 proc channel_noone_seen
{chan
} {
406 foreach n
[array names nick_onchans
] {
407 upvar #0 nick_onchans($n) oc
408 set oc
[grep tc
{"$tc" != "$chan"} $oc]
412 proc process_kickpart
{chan user
} {
415 if {![ischan
$chan]} { error "not a channel" }
416 if {"[irctolower $user]" == "[irctolower $nick]"} {
417 channel_noone_seen
$chan
419 upvar #0 nick_onchans($user) oc
420 set lc
[irctolower
$chan]
421 set oc
[grep tc
{"$tc" != "$lc"} $oc]
422 if {![llength $oc]} { nick_forget
$user }
426 proc msg_KICK
{p c chans users comment
} {
427 set chans
[split $chans ,]
428 set users
[split $users ,]
429 if {[llength $chans] > 1} {
430 foreach chan
$chans user
$users { process_kickpart
$chan $user }
432 foreach user
$users { process_kickpart
[lindex $chans 0] $user }
436 proc msg_KILL
{p c user why
} {
441 set nick_arys
{onchans username unique
}
443 proc nick_forget
{n
} {
445 foreach ary
$nick_arys {
446 upvar #0 nick_${ary}($n) av
454 set nick_case
([irctolower
$n]) $n
457 proc msg_NICK
{p c newnick
} {
458 global nick_arys nick_case
460 recordlastseen_n
$n "changing nicks to $newnick" 0
461 recordlastseen_n
$newnick "changing nicks from $n" 1
462 foreach ary
$nick_arys {
463 upvar #0 nick_${ary}($n) old
464 upvar #0 nick_${ary}($newnick) new
465 if {[info exists new
]} { error "nick collision ?! $ary $n $newnick" }
466 if {[info exists old
]} { set new
$old; unset old
}
471 proc nick_ishere
{n
} {
473 upvar #0 nick_unique($n) u
474 if {![info exists u
]} { set u
[incr nick_counter
].
$n.
[clock seconds
] }
478 proc msg_JOIN
{p c chan
} {
480 recordlastseen_n
$n "joining $chan" 1
481 upvar #0 nick_onchans($n) oc
482 lappend oc
[irctolower
$chan]
485 proc msg_PART
{p c chan
} {
487 recordlastseen_n
$n "leaving $chan" 1
488 process_kickpart
$chan $n
490 proc msg_QUIT
{p c why
} {
492 recordlastseen_n
$n "leaving ($why)" 0
496 proc msg_PRIVMSG
{p c dest
text} {
498 if {[ischan
$dest]} {
499 recordlastseen_n
$n "invoking me in $dest" 1
502 recordlastseen_n
$n "talking to me" 1
508 regsub {^
! *} $text {} text
510 set procname ucmd
/[string tolower
$ucmd]
511 if {[catch { info body
$procname }]} {
512 error "unknown command; try help for help"
516 sendprivmsg
$n "error: $rv"
518 manyset
$rv priv_msgs pub_msgs priv_acts pub_acts
519 foreach {td val
} [list $n $priv_acts $output $pub_acts] {
520 foreach l
[split $val "\n"] {
524 foreach {td val
} [list $n $priv_msgs $output $pub_msgs] {
525 foreach l
[split $val "\n"] {
532 proc msg_INVITE
{p c n chan
} {
533 after 1000 [list sendout JOIN
$chan]
536 proc grep
{var predicate
list} {
540 if {[uplevel 1 [list expr $predicate]]} { lappend o
$v }
545 proc msg_353
{p c dest type chan nicklist
} {
546 global names_chans nick_onchans
547 if {![info exists names_chans
]} { set names_chans
{} }
548 set chan
[irctolower
$chan]
549 lappend names_chans
$chan
550 channel_noone_seen
$chan
551 foreach n
[split $nicklist { }] {
552 regsub {^
[@+]} $n {} n
553 if {![string length
$n]} continue
555 upvar #0 nick_onchans($n) oc
561 proc msg_366
{p c args
} {
562 global names_chans nick_onchans
563 if {[llength names_chans
] > 1} {
564 foreach n
[array names nick_onchans
] {
565 upvar #0 nick_onchans($n) oc
566 set oc
[grep tc
{[lsearch -exact $tc $names_chans] >= 0} $oc]
567 if {![llength $oc]} { nick_forget
$n }
575 return [expr {!![string length
$text]}]
580 if {[string length
$text]} { error "too many parameters" }
585 if {![regexp {^
([^
]+) *(.
*)} $text dummy firstword
text]} {
586 error "too few parameters"
598 proc def_ucmd
{cmdname body
} {
599 proc ucmd
/$cmdname {p dest
} " upvar 1 text text\n$body"
602 proc ucmdr
{priv pub args
} {
603 return -code return [concat [list $priv $pub] $args]
609 catch { unset help_topics
}
610 set f
[open helpinfos r
]
613 while {[gets $f l
] >= 0} {
615 if {[regexp {^
#.*} $l]} {
616 } elseif
{[regexp {^
*$} $l]} {
617 if {[info exists topic
]} {
618 set help_topics
($topic) [join $lines "\n"]
622 } elseif
{[regexp {^
!([-+._0-9a-z
]*)$} $l dummy newtopic
]} {
623 if {[info exists topic
]} {
624 error "help $newtopic while in $topic"
628 } elseif
{[regexp {^
[^
!#]} $l]} {
630 lappend lines
[string trimright
$l]
632 error "eh ? $lno: $l"
635 if {[info exists topic
]} { error "unfinished topic $topic" }
642 upvar #0 help_topics([irctolower [string trim $text]]) info
643 if {![info exists
info]} { ucmdr
"No help on $text, sorry." {} }
649 ucmdr
$help_topics() {}
652 proc check_username
{target
} {
654 [string length
$target] > 8 ||
655 [regexp {[^
-0-9a-z
]} $target] ||
656 ![regexp {^
[a-z
]} $target]
657 } { error "invalid username" }
660 proc somedb__head
{} {
662 set idl
[irctolower
$id]
663 upvar #0 ${nickchan}db($idl) ndbe
664 binary scan $idl H
* idh
665 set idfn
$fprefix$idh
666 if {![info exists iddbe
] && [file exists
$idfn]} {
668 try_except_finally
{ set newval
[read $f] } {} { close $f }
669 if {[llength $newval] % 2} { error "invalid length" }
675 proc def_somedb
{name arglist body
} {
676 foreach {nickchan fprefix
} {nick users
/n chan chans
/c
} {
677 proc ${nickchan
}db_
$name $arglist \
678 "set nickchan $nickchan; set fprefix $fprefix; somedb__head; $body"
682 def_somedb exists
{id
} {
683 return [info exists iddbe
]
686 def_somedb delete
{id
} {
687 catch { unset iddbe
}
691 set default_settings_nick
{timeformat ks
}
692 set default_settings_chan
{autojoin
1}
694 def_somedb
set {id args
} {
695 upvar #0 default_settings_$nickchan def
696 if {![info exists iddbe
]} { set iddbe
$def }
697 foreach {key value
} [concat $iddbe $args] { set a
($key) $value }
699 foreach {key value
} [array get a
] { lappend newval
$key $value }
700 set f
[open $idfn.new w
]
704 file rename -force $idfn.new
$idfn
712 def_somedb get
{id key
} {
713 upvar #0 default_settings_$nickchan def
714 if {[info exists iddbe
]} {
719 foreach {tkey value
} $l {
720 if {"$tkey" == "$key"} { return $value }
722 error "unset setting $key"
727 if {[info exists calling_nick
]} { set n
$calling_nick } { set n
{} }
728 return [nickdb_get
$n $key]
731 proc check_notonchan
{} {
733 if {[ischan
$dest]} { error "that command must be sent privately" }
736 proc nick_securitycheck
{strict
} {
738 if {![nickdb_exists
$n]} { error "you are unknown to me, use `register'." }
739 set wantu
[nickdb_get
$n username
]
740 if {![string length
$wantu]} {
742 error "that feature is only available to secure users, sorry."
747 upvar #0 nick_username($n) nu
748 if {![info exists nu
]} {
749 error "nick $n is secure, you must identify yourself first."
751 if {"$wantu" != "$nu"} {
752 error "you are the wrong user - the nick $n belongs to $wantu, not $nu"
756 proc channel_securitycheck
{channel n
} {
757 # You must also call `nick_securitycheck 1'
758 if {[lsearch -exact [irctolower
[chandb_get
$channel managers
]] $n] < 0} {
759 error "you are not a manager of $channel"
763 proc def_chancmd
{name body
} {
764 proc channel
/$name {} \
765 " upvar 1 target chan; upvar 1 n n; upvar 1 text text; $body"
768 def_chancmd manager
{
770 switch -exact _
$opcode {
773 if {[chandb_exists
$chan]} {
774 set ml
[chandb_get
$chan managers
]
776 set ml
[list [irctolower
$n]]
780 error "`channel manager' opcode must be one of + - ="
783 foreach nn
[split $text " "] {
784 if {![string length
$nn]} continue
786 set nn
[irctolower
$nn]
787 if {"$opcode" != "-"} {
790 set ml
[grep nq
{"$nq" != "$nn"} $ml]
794 chandb_set
$chan managers
$ml
795 ucmdr
"Managers of $chan: $ml" {}
798 ucmdr
{} {} "forgets about managing $chan." {}
802 def_chancmd autojoin
{
804 switch -exact [string tolower
$yesno] {
807 default { error "channel autojoin must be `yes' or `no' }
809 chandb_set $chan autojoin $nv
813 if {[chandb_exists $chan]} {
814 set l "Settings
for $chan: autojoin
"
815 append l [lindex {no yes} [chandb_get $chan autojoin]]
816 append l "\nManagers
: "
817 append l [join [chandb_get $chan managers] " "]
820 ucmdr {} "The channel
$chan is not managed.
"
825 if {[ischan $dest]} { set target $dest }
826 if {[ta_anymore]} { set target [ta_word] }
828 if {![info exists target]} { error "you must specify
, or
!... on
, the channel
" }
829 if {![ischan $target]} { error "not a valid channel
" }
830 if {![chandb_exists $target]} { error "$target is not a managed channel.
" }
833 channel_securitycheck $target $n
834 sendout MODE $target +o $n
838 if {[ischan $dest]} { set target $dest }
844 if {[ischan $subcmd]} {
852 if {![info exists target]} { error "privately
, you must specify a channel
" }
853 set procname channel/$subcmd
854 if {"$subcmd" != "show
"} {
855 if {[catch { info body $procname }]} { error "unknown channel setting
$subcmd" }
858 if {[chandb_exists $target]} {
859 channel_securitycheck $target $n
861 upvar #0 chan_initialop([irctolower $target]) io
862 upvar #0 nick_unique($n) u
863 if {![info exists io]} { error "$target is not a managed channel
" }
864 if {"$io" != "$u"} { error "you are not the interim manager of
$target" }
865 if {"$subcmd" != "manager
"} { error "use `channel manager' first
" }
873 set target [ta_word]; ta_nomore
878 set myself [expr {"$target" != "$n"}]
880 upvar #0 nick_case([irctolower $target]) nc
882 if {[info exists nc]} {
883 upvar #0 nick_onchans($nc) oc
884 upvar #0 nick_username($nc) nu
885 if {[info exists oc]} { set nshow $nc }
887 if {![nickdb_exists $target]} {
888 set ol "$nshow is not a registered nick.
"
889 } elseif {[string length [set username [nickdb_get $target username]]]} {
890 set ol "The nick
$nshow belongs to the user
$username.
"
892 set ol "The nick
$nshow is registered
(but not to a username
).
"
894 if {![info exists nc] || ![info exists oc]} {
896 append ol "\nI can't see
$nshow on anywhere.
"
898 append ol "\nYou aren't on any channels with me.
"
900 } elseif {![info exists nu]} {
901 append ol "\n$nshow has not identified themselves.
"
902 } elseif {![info exists username]} {
903 append ol "\n$nshow has identified themselves as the user
$nu.
"
904 } elseif {"$nu" != "$username"} {
905 append ol "\nHowever
, $nshow is being used by the user
$nu.
"
907 append ol "\n$nshow has identified themselves to me.
"
915 set old [nickdb_exists $n]
916 if {$old} { nick_securitycheck 0 }
917 switch -exact [string tolower [string trim $text]] {
919 upvar #0 nick_username($n) nu
920 if {![info exists nu]} {
922 "You must identify yourself before using `register'. See `help identify'
, or use `register insecure'.
"
924 nickdb_set $n username $nu
925 ucmdr {} {} "makes a note of your username.
" {}
929 ucmdr {} {} "forgets your nickname.
" {}
932 nickdb_set $n username {}
934 ucmdr {} "Security is now disabled
for your nickname
!"
936 ucmdr {} "This is fine
, but bear in mind that people will be able to mess with your settings. Channel management features need a secure registration.
" "makes an insecure registration
for your nick.
"
942 proc timeformat_desc {tf} {
944 ks { return "Times will be displayed in seconds or kiloseconds.
" }
945 hms { return "Times will be displayed in hours
, minutes
, etc.
" }
946 default { error "invalid timeformat
: $v" }
950 proc def_setting {opt show_body set_body} {
951 proc set_show/$opt {} "
955 if {![string length $set_body]} return
956 proc set_set/$opt {} "
963 def_setting timeformat {
964 set tf [nickdb_get $n timeformat]
965 return "$tf: [timeformat_desc
$tf]"
967 set tf [string tolower [ta_word]]
969 set desc [timeformat_desc $tf]
970 nickdb_set $n timeformat $tf
974 def_setting security {
975 set s [nickdb_get $n username]
976 if {[string length $s]} {
977 return "Your nick
, $n, is controlled by the user
$s.
"
979 return "Your nick
, $n, is not secure.
"
986 if {![nickdb_exists $n]} {
987 ucmdr {} "You are
unknown to me and so have no settings.
(Use `register'.
)"
991 foreach proc [lsort [info procs]] {
992 if {![regexp {^set_show/(.*)$} $proc dummy opt]} continue
993 lappend ol [format "%-10s %s
" $opt [set_show/$opt]]
995 ucmdr {} [join $ol "\n"]
998 if {[catch { info body set_show/$opt }]} {
999 error "no setting
$opt"
1001 if {![ta_anymore]} {
1002 ucmdr {} "$opt [set_show
/$opt]"
1004 nick_securitycheck 0
1005 if {[catch { info body set_set/$opt }]} {
1006 error "setting
$opt cannot be
set with `
set'
"
1013 def_ucmd identpass {
1014 set username [ta_word]
1015 set passmd5 [md5sum "[ta_word
]\n"]
1019 upvar #0 nick_onchans($n) onchans
1020 if {![info exists onchans] || ![llength $onchans]} {
1021 ucmdr "You must be on a channel with me to identify yourself.
" {}
1023 check_username $username
1024 exec userv --timeout 3 $username << "$passmd5\n" > /dev/null \
1026 upvar #0 nick_username($n) rec_username
1027 set rec_username $username
1028 ucmdr "Pleased to see you
, $username.
" {}
1032 set target [ta_word]
1034 check_username $target
1037 upvar #0 lastsummon($target) ls
1038 set now [clock seconds]
1039 if {[info exists ls]} {
1040 set interval [expr {$now - $ls}]
1041 if {$interval < 30} {
1043 "Please be patient
; $target was summoned only
[showinterval
$interval].
"
1046 regsub {^[^!]*!} $p {} path
1048 exec userv --timeout 3 $target irc-summon $n $path \
1049 [expr {[ischan $dest] ? "$dest" : ""}] \
1052 regsub -all "\n" $rv { / } rv
1055 if {[regexp {^problem (.*)} $rv dummy problem]} {
1056 ucmdr {} "The user `
$target'
$problem.
"
1057 } elseif {[regexp {^ok ([^ ]+) ([0-9]+)$} $rv dummy tty idlesince]} {
1058 set idletime [expr {$now - $idlesince}]
1060 ucmdr {} {} {} "invites
$target ($tty[expr {
1061 $idletime > 10 ?
", idle for [showintervalsecs $idletime]" : ""
1063 [ischan
$dest] ?
"join us here" : "talk to you"
1066 error "unexpected response from userv service
: $rv"
1070 proc md5sum {value} { exec md5sum << $value }
1073 global lastseen nick
1076 set nlower [irctolower $ncase]
1078 set now [clock seconds]
1079 if {"$nlower" == "[irctolower
$nick]"} {
1080 error "I am not self-aware.
"
1081 } elseif {![info exists lastseen($nlower)]} {
1082 set rstr "I've never seen
$ncase.
"
1084 manyset $lastseen($nlower) realnick time what
1085 set howlong [expr {$now - $time}]
1086 set string [showinterval $howlong]
1087 set rstr "I last saw
$realnick $string, $what.
"
1089 if {[ischan $dest]} {
1094 upvar #0 lookedfor($nlower) lf
1095 if {[info exists lf]} { set oldvalue $lf } else { set oldvalue {} }
1096 set lf [list [list $now $n $where]]
1097 foreach v $oldvalue {
1098 if {"[irctolower
[lindex $v 1]]" == "[irctolower
$n]"} continue
1104 if {![info exists sock]} {
1105 set sock [socket $host $port]
1106 fconfigure $sock -buffering line
1107 #fconfigure $sock -translation binary
1108 fconfigure $sock -translation crlf
1110 sendout USER blight 0 * $ownfullname
1112 fileevent $sock readable onread
1117 #if {![regexp {tclsh} $argv0]} {