chiark / gitweb /
Do ownpings.
[ircbot] / irccore.tcl
CommitLineData
574abac6 1proc defset {varname val} {
281f2c0e 2 upvar 1 $varname var
574abac6
IJ
3 if {![info exists var]} { set var $val }
4}
5
6# must set host
7defset port 6667
8
9defset nick testbot
9e738c1d 10defset ident blight
574abac6
IJ
11defset ownfullname "testing bot"
12defset ownmailaddr test-irc-bot@example.com
13
0d3ea3aa 14defset muststartby_ms 10000
574abac6
IJ
15defset out_maxburst 6
16defset out_interval 2100
17defset out_lag_lag 5000
18defset out_lag_very 25000
ea990080 19defset ownping_every 300000
574abac6
IJ
20
21defset marktime_min 300
22defset marktime_join_startdelay 5000
23
24proc manyset {list args} {
25 foreach val $list var $args {
26 upvar 1 $var my
27 set my $val
28 }
29}
30
31proc try_except_finally {try except finally} {
32 global errorInfo errorCode
33 set er [catch { uplevel 1 $try } emsg]
34 if {$er} {
35 set ei $errorInfo
36 set ec $errorCode
37 if {[catch { uplevel 1 $except } emsg3]} {
38 append ei "\nALSO ERROR HANDLING ERROR:\n$emsg3"
39 }
40 }
41 set er2 [catch { uplevel 1 $finally } emsg2]
42 if {$er} {
43 if {$er2} {
44 append ei "\nALSO ERROR CLEANING UP:\n$emsg2"
45 }
46 return -code $er -errorinfo $ei -errorcode $ec $emsg
47 } elseif {$er2} {
48 return -code $er2 -errorinfo $errorInfo -errorcode $errorCode $emsg2
49 } else {
50 return $emsg
51 }
52}
53
54proc out__vars {} {
55 uplevel 1 {
56 global out_queue out_creditms out_creditat out_interval out_maxburst
57 global out_lag_lag out_lag_very
58#set pr [lindex [info level 0] 0]
59#puts $pr>[clock seconds]|$out_creditat|$out_creditms|[llength $out_queue]<
60 }
61}
62
63proc out_lagged {} {
64 out__vars
65 if {[llength $out_queue]*$out_interval > $out_lag_very} {
66 return 2
67 } elseif {[llength $out_queue]*$out_interval > $out_lag_lag} {
68 return 1
69 } else {
70 return 0
71 }
72}
73
74proc out_restart {} {
75 out__vars
76
77 set now [clock seconds]
78 incr out_creditms [expr {($now - $out_creditat) * 1000}]
79 set out_creditat $now
80 if {$out_creditms > $out_maxburst*$out_interval} {
81 set out_creditms [expr {$out_maxburst*$out_interval}]
82 }
83 out_runqueue $now
84}
85
86proc out_runqueue {now} {
87 global sock
88 out__vars
89
90 while {[llength $out_queue] && $out_creditms >= $out_interval} {
91#puts rq>$now|$out_creditat|$out_creditms|[llength $out_queue]<
92 manyset [lindex $out_queue 0] orgwhen msg
93 set out_queue [lrange $out_queue 1 end]
94 if {[llength $out_queue]} {
95 append orgwhen "+[expr {$now - $orgwhen}]"
96 append orgwhen "([llength $out_queue])"
97 }
98 puts "$orgwhen -> $msg"
99 puts $sock $msg
100 incr out_creditms -$out_interval
101 }
102 if {[llength $out_queue]} {
103 after $out_interval out_nextmessage
104 }
105}
106
107proc out_nextmessage {} {
108 out__vars
109 set now [clock seconds]
110 incr out_creditms $out_interval
111 set out_creditat $now
112 out_runqueue $now
113}
114
115proc sendout_priority {priority command args} {
116 global sock out_queue
117 if {[llength $args]} {
118 set la [lindex $args end]
119 set args [lreplace $args end end]
120 foreach i $args {
121 if {[regexp {[: ]} $i]} {
122 error "bad argument in output $i ($command $args)"
123 }
124 }
125 lappend args :$la
126 }
127 set args [lreplace $args 0 -1 $command]
128 set string [join $args { }]
129 set now [clock seconds]
130 set newe [list $now $string]
131 if {$priority} {
132 set out_queue [concat [list $newe] $out_queue]
133 } else {
134 lappend out_queue $newe
135 }
136 if {[llength $out_queue] == 1} {
137 out_restart
138 }
139}
140
141proc sendout {command args} { eval sendout_priority [list 0 $command] $args }
142
143proc log {data} {
144 puts $data
145}
146
147proc logerror {data} {
148 log $data
149}
150
151proc saveeic {} {
152 global saveei saveec errorInfo errorCode
153
154 set saveei $errorInfo
155 set saveec $errorCode
156
157 puts ">$saveec|$saveei<"
158}
159
160proc bgerror {msg} {
161 global save
162 logerror $msg
163 saveeic
164}
165
166proc onread {args} {
892f5a82 167 global sock nick calling_nick errorInfo errorCode line_org_endchar
281f2c0e 168
574abac6 169 if {[gets $sock line] == -1} { fail "EOF/error on input" }
892f5a82 170 set line_org_endchar [string range $line end end]
574abac6
IJ
171 regsub -all "\[^ -\176\240-\376\]" $line ? line
172 set org $line
173
281f2c0e 174 new_event
574abac6
IJ
175
176 if {[regexp -nocase {^:([^ ]+) (.*)} $line dummy prefix remain]} {
177 set line $remain
178 if {[regexp {^([^!]+)!} $prefix dummy maybenick]} {
179 set calling_nick $maybenick
180 if {"[irctolower $maybenick]" == "[irctolower $nick]"} return
181 }
182 } else {
183 set prefix {}
184 }
185 if {![string length $line]} { return }
186 if {![regexp -nocase {^([0-9a-z]+) *(.*)} $line dummy command line]} {
187 log "bad command: $org"
188 return
189 }
190 set command [string toupper $command]
191 set params {}
192 while {[regexp {^([^ :]+) *(.*)} $line dummy thisword line]} {
193 lappend params $thisword
194 }
195 if {[regexp {^:(.*)} $line dummy thisword]} {
196 lappend params $thisword
197 } elseif {[string length $line]} {
198 log "junk at end: $org"
199 return
200 }
281f2c0e
IJ
201 if {"$command" == "PRIVMSG" && \
202 [privmsg_unlogged $prefix [ischan [lindex $params 0]] $params]} {
574abac6
IJ
203 return
204 }
205 log "[clock seconds] <- $org"
206 set procname msg_$command
207 if {[catch { info body $procname }]} { return }
208 if {[catch {
209 eval [list $procname $prefix $command] $params
210 } emsg]} {
211 logerror "error: $emsg ($prefix $command $params)"
212 saveeic
213 }
214}
215
216proc sendprivmsg {dest l} {
217 foreach v [split $l "\n"] {
218 sendout [expr {[ischan $dest] ? "PRIVMSG" : "NOTICE"}] $dest $v
219 }
220}
221proc sendaction_priority {priority dest what} {
222 sendout_priority $priority PRIVMSG $dest "\001ACTION $what\001"
223}
224proc msendprivmsg {dest ll} { foreach l $ll { sendprivmsg $dest $l } }
225proc msendprivmsg_delayed {delay dest ll} { after $delay [list msendprivmsg $dest $ll] }
226
227proc check_nick {n} {
228 if {[regexp -nocase {[^][\\`_^{|}a-z0-9-]} $n]} { error "bad char in nick" }
229 if {[regexp {^[-0-9]} $n]} { error "bad nick start" }
230}
231
232proc ischan {dest} {
233 return [regexp {^[&#+!]} $dest]
234}
235
236proc irctolower {v} {
237 foreach {from to} [list "\\\[" "{" \
238 "\\\]" "}" \
239 "\\\\" "|" \
240 "~" "^"] {
241 regsub -all $from $v $to v
242 }
243 return [string tolower $v]
244}
245
281f2c0e
IJ
246proc prefix_none {} {
247 upvar 1 p p
248 if {[string length $p]} { error "prefix specified" }
249}
250
251proc prefix_nick {} {
252 global nick
253 upvar 1 p p
254 upvar 1 n n
255 if {![regexp {^([^!]+)!} $p dummy n]} { error "not from nick" }
256 check_nick $n
257 if {"[irctolower $n]" == "[irctolower $nick]"} {
258 error "from myself" {} {}
259 }
260}
261
574abac6 262proc msg_PING {p c s1} {
574abac6
IJ
263 prefix_none
264 sendout PONG $s1
0d3ea3aa
IJ
265}
266
ea990080
IJ
267proc sendownping {} {
268 global ownping_every nick
269 sendout ping $nick
270 after $ownping_every sendownping
271}
272
0d3ea3aa
IJ
273proc msg_001 {args} {
274 global muststartby_after
275 if {[info exists muststartby_after]} {
276 after cancel $muststartby_after
277 unset muststartby_after
ea990080 278 sendownping
281f2c0e
IJ
279 connected
280 }
281}
282
283proc ensure_outqueue {} {
284 out__vars
285 if {[info exists out_queue]} return
286 set out_creditms 0
287 set out_creditat [clock seconds]
288 set out_queue {}
289 set out_lag_reported 0
290 set out_lag_reportwhen $out_creditat
291}
292
293proc fail {msg} {
294 logerror "failing: $msg"
295 exit 1
296}
297
298proc ensure_connecting {} {
9e738c1d 299 global sock ownfullname host port nick ident socketargs
0d3ea3aa 300 global muststartby_ms muststartby_after
281f2c0e
IJ
301
302 ensure_outqueue
303
304 if {[info exists sock]} return
305 set sock [eval socket $socketargs [list $host $port]]
306 fconfigure $sock -buffering line
307 fconfigure $sock -translation crlf
308
9e738c1d 309 sendout USER $ident 0 * $ownfullname
281f2c0e
IJ
310 sendout NICK $nick
311 fileevent $sock readable onread
312
0d3ea3aa
IJ
313 set muststartby_after [after $muststartby_ms \
314 {fail "no successfuly connect within timeout"}]
574abac6 315}