Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: data/Media/tcl/irk/lib/irkreceive.tcl @ 5065

Last change on this file since 5065 was 5065, checked in by landauf, 16 years ago

added irk - a tcl library for irc

File size: 14.3 KB
Line 
1# irkreceive.tcl:
2#
3# Various commands invoked in response to input received from the server:
4
5namespace eval irk {
6
7    # This procedure deals with the PING special action:
8
9    proc RECV,PING {token nick user comm dest rest} {
10        variable state
11
12        if {[catch {set sock $state($token,socket)}]} {
13            error "$token: not a valid IRK connection"
14        }
15        puts $sock "PONG :$comm $rest"
16
17        return ""
18    }
19
20    # This procedure deals with the NOTICE special action:
21
22    proc RECV,NOTICE {token nick user comm dest rest} {
23        variable state
24
25        append state($token,GLOBALNOTICES) "$rest\n"
26
27        return ""
28    }
29
30
31    # This procedure deals with the ERROR special action:
32
33    proc RECV,ERROR {token nick user comm dest rest} {
34        variable state
35
36        set rest [eval concat $rest]
37        append state($token,ERRORS) "$nick $dest $rest\n"
38        puts "Got ERROR: $token $nick ---> $dest: $rest"
39
40        return ""
41    }
42
43    # This procedure deals with the AWAY response:
44
45    proc RECV,AWAY {token nick user comm dest rest} {
46        set id [lindex $rest 0]
47        set rest [lrange $rest 1 end]
48        set rest [lreplace $rest 0 0 [string range [lindex $rest 0] 1 end]]
49        set rest [eval concat $rest]
50        puts "$id is away: $rest"
51
52        return ""
53    }
54   
55    # This procedure deals with the WHOIS USER message:
56
57    proc RECV,WHOIS,NICK,USER {token nick user comm dest rest} {
58        variable state
59
60        # Split the rest of the line on space:
61
62        foreach {unick uuser uhost ustar urnm} [split $rest " "] break
63
64        # If the WHOIS information is about this user, save it specially:
65
66        if {[isus $token $unick]} {
67            set state($token,uuser)     $uuser
68            set state($token,uhost)     $uhost
69            set state($token,urnm)      $urnm
70        }
71
72        # Save the information for a regular user:
73
74        set state($token,ident,$unick,uuser)    $uuser
75        set state($token,ident,$unick,uhost)    $uhost
76        set state($token,ident,$unick,urnm)     $urnm
77    }
78
79    # This procedure deals with the WHOIS SERVER message:
80
81    proc RECV,WHOIS,NICK,SERVER {token nick user comm dest rest} {
82        variable state
83
84        # Split the rest of the line on space:
85
86        foreach {unick userv} [split $rest " "] break
87
88        # If the WHOIS information is about this user, save it specially:
89
90        if {[isus $token $unick]} {
91            set state($token,userv) $userv
92        }
93
94        # Save the information for a regular user:
95
96        set state($token,ident,$unick,userv) $userv
97    }
98
99    # This procedure deals with the WHOIS IDENT message
100
101    proc RECV,WHOIS,NICK,IDENT {token nick user comm dest rest} {
102        variable state
103
104        # Extract the nick of the user who has identified
105
106        set unick [lindex [split $rest " "] 0]
107
108        # If the WHOIS information is about this user, save it specially:
109
110        if {[isus $token $unick]} {
111            set state($token,ident) 1
112        }
113
114        # Save the information for a regular user:
115
116        set state($token,ident,$unick,ident) 1
117    }   
118
119    # This procedure deals with the WHOIS CONNECTTIME message:
120
121    proc RECV,WHOIS,NICK,CONNECTTIME {token nick user comm dest rest} {
122        variable state
123
124        # Split the rest of the input on space:
125
126        foreach {unick idle connecttime} [split $rest " "] break
127
128        # Format the connect time for this user:
129
130        set connecttime [clock format $connecttime]
131
132        # If the WHOIS information is about this user, save it specially:
133
134        if {[isus $token $unick]} {
135            set state($token,connecttime) $connecttime
136        }
137
138        # Save the information for a regular user:
139
140        set state($token,ident,$unick,connecttime) $connecttime
141    }
142
143    # Handle the WHOIS CHANNELS message:
144
145    proc RECV,WHOIS,NICK,CHANNELS {token nick user comm dest rest} {
146        variable state
147
148        # Split the rest on space.
149
150        set rest [split $rest " "]
151
152        # Get the nick for which this is the channel list:
153
154        set unick [lindex $rest 0]
155        set rest [lrange $rest 1 end]
156
157        # The first channel may have an extra ":", if it does get rid of it.
158
159        set firstchan [lindex $rest 0]
160        if {[string match ":*" $firstchan]} {
161            set rest [lreplace $rest 0 0 [string range $firstchan 1 end]]
162        }
163
164        # If the WHOIS information is about this user, save it specially:
165
166        if {[isus $token $unick]} {
167            set state($token,channels) $channels
168        }
169
170        # Save the information for a regular user:
171
172        set state($token,ident,$unick,channels) $rest
173    }
174
175    # This procedure deals with the WHOIS END message:
176
177    proc RECV,WHOIS,NICK,END {token nick user comm dest rest} {
178        variable state
179
180        set state($token,whois,done) 1
181    }
182
183    # This procedure deals with various MOTD actions:
184
185    proc RECV,MOTD {token nick user comm dest rest} {
186        variable state
187
188        append state($token,MOTD) "${rest}\n"
189
190        return ""
191    }
192
193    # This procedure deals with PONG actions:
194
195    proc RECV,PONG {token nick user comm dest rest} {
196        variable state
197
198        if {[info exists state($token,PINGSTART)]} {
199            set elapsed \
200                [expr [clock clicks -millis] - $state($token,PINGSTART)]
201            puts "$nick: $elapsed msecs"
202            unset state($token,PINGSTART)
203        }
204
205        return ""
206    }
207
208    # This procedure deals with NOTICE received from a regular user:
209
210    proc RECV,NOTICE,USER {token nick user comm dest rest} {
211        if {[string match "\001*" [lindex $rest 0]]} {
212            set rest [ctcpcleanup $rest]
213            RECV,NOTICE,CTCP,USER $token $nick $user $comm $dest \
214                    [lindex $rest 0] [lrange $rest 1 end]
215        } else {
216            set rest [eval concat $rest]
217            puts "$nick sends $dest a notice: $rest"
218        }
219
220        return ""
221    }
222
223    # This procedure helps with CTCP notice actions:
224
225    proc RECV,NOTICE,CTCP,USER {token nick user comm dest action rest} {
226        variable state
227
228        if {[info exists state($token,response,ctcp,$action)]} {
229            $state($token,response,ctcp,$action) \
230                                        $token $nick $user $comm $dest \
231                                        $action $rest
232        } else {
233            $state($token,response,ctcp,error) \
234                                        $token $nick $user $comm $dest \
235                                        $action $rest
236        }
237
238        return ""
239    }
240
241    # This procedure deals with JOIN actions:
242
243    proc RECV,JOIN {token nick user comm dest rest} {
244        variable state
245
246        # Check if it's us that joined the channel or someone else.
247
248        if {[isus $token $nick]} {
249            puts "You joined $dest"
250
251            addChannel $token $dest
252        } else {
253            puts "$nick joined $dest"
254
255            addToChannel $token $nick $dest
256        }
257
258        return ""
259    }
260
261    # This procedure deals with PART actions:
262
263    proc RECV,PART {token nick user comm dest rest} {
264        variable state
265
266        set chan [string tolower $dest]
267
268        if {[isus $token $nick]} {
269            puts "You left channel $chan"
270        } else {
271            puts "$nick left [string tolower $dest]"
272        }           
273        removeFromChannel $token $nick $chan
274        removeFromChannel $token @$nick $chan
275
276        return ""
277    }
278
279    # This procedure deals with MODE actions:
280
281    proc RECV,MODE {token nick user comm dest rest} {
282        set rest [eval concat $rest]
283        puts "$nick sets mode $dest $rest"
284
285        return ""
286    }
287
288    # This procedure deals with NICK actions:
289
290    proc RECV,NICK {token nick user comm dest rest} {
291        variable state
292
293        set newnick [string range $dest 1 end]
294
295        # If our nick changed, remember it as the nick associated with
296        # this connection:
297
298        if {[isus $token $nick]} {
299            set state($token,nick) $newnick
300            set state($token,$newnick,PRIVMSG)  $state(PRIVMSG,unsolicited)
301            catch {unset state($token,$nick,PRIVMSG)}
302        }
303
304        # Replace the old nick with the new in all channels that we're on:
305
306        replaceAllChannels $token $nick $newnick
307
308        puts "$nick ${user} ($token) changes his/her nickname to $newnick"
309
310        return ""
311    }
312
313    # This procedure deals with QUIT actions:
314
315    proc RECV,QUIT {token nick user comm dest rest} {
316        variable state
317
318        set rest [eval concat $rest]
319        puts "Received QUIT $token $nick $rest"
320
321        if {[string match ":*" $dest]} {
322            set dest [string range $dest 1 end]
323        }
324        if {[isus $token $nick]} {
325            puts "You left the server $state($token,host) ($dest $rest)"
326            forgetConnection $token
327        } else {
328            puts "$nick quits IRK ($dest $rest)"
329            removeFromAllChannels $token $nick
330            removeFromAllChannels $token @$nick
331        }
332
333        return ""
334    }
335
336    # This procedure deals with expected PRIVMSG actions:
337
338    proc RECV,PRIVMSG {token nick user comm dest rest} {
339        if {[string match "\001*" [lindex $rest 0]]} {
340            set rest [ctcpcleanup $rest]
341            RECV,PRIVMSG,CTCP,CHANNEL $token $nick $user $comm $dest \
342                    [lindex $rest 0] [lrange $rest 1 end]
343        } else {
344            puts "$nick$dest: [eval concat $rest]"
345        }
346
347        return ""
348    }
349
350    # This procedure handles CTCP actions on the channel:
351
352    proc RECV,PRIVMSG,CTCP,CHANNEL {token nick user comm dest action rest} {
353        variable state
354
355        if {[info exists state($token,channel,ctcp,$action)]} {
356            $state($token,channel,ctcp,$action) \
357                                        $token $nick $user $comm $dest \
358                                        $action $rest
359        } else {
360            $state($token,channel,ctcp,error) \
361                                        $token $nick $user $comm $dest \
362                                        $action $rest
363        }
364
365        return ""
366    }
367
368    # This procedure stores the result of USERHOST actions:
369
370    proc RECV,USERHOST {token nick user comm dest rest} {
371        return ""
372    }
373
374    # This procedure stores the channel topic:
375
376    proc RECV,CHANNEL,TOPIC {token nick user comm dest rest} {
377        variable state
378
379        set chan [lindex $rest 0]
380        set rest [lrange $rest 1 end]
381        if {[string match ":*" [lindex $rest 0]]} {
382            set rest [lreplace $rest 0 0 \
383                               [string range [lindex $rest 0] 1 end]]
384        }
385        set state($token,$chan,TOPIC) $rest
386        set state($token,$chan,TOPIC,SETBY) $nick
387        set state($token,$chan,TOPIC,SETAT) [clock format [clock seconds]]
388
389        return ""
390    }
391
392    # This procedure stores the channel byline:
393
394    proc RECV,CHANNEL,SETBY {token nick user comm dest rest} {
395        variable state
396
397        set chan [lindex $rest 0]
398        set rest [lrange $rest 1 end]
399        if {[string match ":*" [lindex $rest 0]]} {
400            set rest [lreplace $rest 0 0 \
401                               [string range [lindex $rest 0] 1 end]]
402        }
403        set state($token,$chan,TOPIC,SETBY) [lindex $rest 0]
404        set state($token,$chan,TOPIC,SETAT) [clock format [lindex $rest 1]]
405
406        return ""
407    }
408
409    # This procedure deals with unsolicited PRIVMSG actions:
410
411    proc RECV,PRIVMSG,unsolicited {token nick user comm dest rest} {
412        if {[string match "\001*" [lindex $rest 0]]} {
413            set rest [ctcpcleanup $rest]
414            RECV,PRIVMSG,CTCP,USER $token $nick $user $comm $dest \
415                    [lindex $rest 0] [lrange $rest 1 end]
416        } else {
417            puts "$nick: [eval concat $rest]"
418        }
419
420        return ""
421    }
422
423    # This procedure helps with CTCP private messages:
424
425    proc RECV,PRIVMSG,CTCP,USER {token nick user comm dest action rest} {
426        variable state
427
428        if {[info exists state($token,cmd,ctcp,$action)]} {
429            $state($token,cmd,ctcp,$action) \
430                                        $token $nick $user $comm $dest \
431                                        $action $rest
432        } else {
433            $state($token,cmd,ctcp,error) \
434                                        $token $nick $user $comm $dest \
435                                        $action $rest
436        }
437
438        return ""
439    }
440
441    # This procedure deals with a KICK action:
442
443    proc RECV,KICK {token nick user comm dest rest} {
444        set kicked [lindex $rest 0]
445        if {[string match ":*" $kicked]} {
446            set kicked [string range $kicked 1 end]
447        }
448        set reason [eval concat [lrange $rest 1 end]]
449        if {[string match ":*" $reason]} {
450            set reason [string range $reason 1 end]
451        }
452
453        if {[isus $token $kicked]} {
454            puts "$nick kicked you from $dest because $reason"
455
456            removeChannel $token $dest
457        } else {
458            puts "$nick kicks $kicked from $dest because $reason"
459
460            removeFromChannel $token $kicked $dest
461            removeFromChannel $token @$kicked $dest
462        }
463
464        return ""
465    }
466
467    # These procedures collect the name list for a channel:
468
469    proc RECV,CHANNEL,NAMELIST {token nick user comm dest rest} {
470        variable state
471
472        # Scan forward in $rest for the channel name:
473
474        for {set i 0; set l [llength $rest]} {$i < $l} {incr i} {
475            if {[string match "#*" [lindex $rest $i]]} {
476                break
477            }
478        }
479
480        # Didn't find it?
481
482        if {$i == $l} {
483            return
484        }
485
486        # Extract the channel name and the rest of the input:
487
488        set chan [lindex $rest $i]
489        set rest [lrange $rest [expr $i + 1] end]
490        set rest [lreplace $rest 0 0 [string range [lindex $rest 0] 1 end]]
491        set rest [eval concat $rest]
492
493        if {![info exists state($token,$chan,NAMES)]} {
494            set state($token,$chan,NAMES) ""
495        }
496        set state($token,$chan,NAMES) [concat $state($token,$chan,NAMES) $rest]
497
498        return ""
499    }
500
501    proc RECV,CHANNEL,NAMELIST,END {token nick user comm dest rest} {
502        variable state
503
504        set chan [lindex $rest 0]
505        set $state($token,$chan,NAMES) [split $state($token,$chan,NAMES) " "]
506    }
507
508    # This procedure deals with a request from the server to send a PONG
509    # with a given code.
510
511    proc RECV,PONG,REQUEST {token nick user comm dest rest} {
512        set pongcode [lindex $rest [expr [llength $rest] - 1]]
513        puts $token "PONG $pongcode"
514
515        return ""
516    }
517
518    # This procedure deals with a CTCP PING request:
519
520    proc RECV,CTCP,PING {token nick user comm dest action rest} {
521        variable state
522
523        if {[catch {set sock $state($token,socket)}]} {
524            error "$token: not a valid IRK connection"
525        }
526        puts $sock "NOTICE $nick :\001PING ${rest}\001"
527
528        return ""
529    }
530
531    # This procedure deals with a CTCP TIME request:
532
533    proc RECV,CTCP,TIME {token nick user comm dest action rest} {
534        variable state
535
536        if {[catch {set sock $state($token,socket)}]} {
537            error "$token: not a valid IRK connection"
538        }
539        puts $sock \
540            "NOTICE $nick :\001TIME :[clock format [clock seconds]]\001"
541
542        return ""
543    }
544
545    # This procedure deals with a CTCP VERSION request:
546
547    proc RECV,CTCP,VERSION {token nick user comm dest action rest} {
548        variable state
549        global tcl_platform
550
551        if {[catch {set sock $state($token,socket)}]} {
552            error "$token: not a valid IRK connection"
553        }
554        set version "$state(-useragent):$state(-version):$tcl_platform(os)"
555        puts $sock "NOTICE $nick :\001VERSION ${version}\001"
556    }
557
558    # This procedure deals with a CTCP USERINFO request:
559
560    proc RECV,CTCP,USERINFO {token nick user comm dest action rest} {
561        variable state
562
563        if {[catch {set sock $state($token,socket)}]} {
564            error "$token: not a valid IRK connection"
565        }
566        puts $sock "NOTICE $nick :\001USERINFO $state(-$token,user)\001"
567    }
568
569    # This procedure deals with CTCP ACTION messages:
570
571    proc RECV,CTCP,ACTION {token nick user comm dest action rest} {
572        puts "$nick $rest"
573
574        return ""
575    }
576
577    # This procedure is a catch all for CTCP actions that we do not
578    # understand:
579
580    proc RECV,CTCP,ERROR {token nick user comm dest action rest} {
581        variable state
582
583        if {[catch {set sock $state($token,socket)}]} {
584            error "$token: not a valid IRC connection"
585        }
586        if {[llength $rest] > 0} {
587            puts $sock \
588                "NOTICE $nick :\001ERRMSG $action $rest: unknown CTCP\001"
589        } else {
590            puts $sock "NOTICE $nick :\001ERRMSG $action: unknown CTCP\001"
591        }
592    }
593
594    # This is the default action, used by the default dispatcher
595    # when no action can be found for the given $token, $nick, $user,
596    # $comm, and $dest.
597
598    proc defaultAction {token nick user comm dest rest} {
599        puts "$token: $nick $user: $comm -> $dest ... [eval concat $rest]"
600
601        return ""
602    }
603}
Note: See TracBrowser for help on using the repository browser.