109f2f2e14b90d03c28da8de86aa0912a1c9685c
[riece] / lisp / riece-300.el
1 ;;; riece-300.el --- handlers for 300 replies
2 ;; Copyright (C) 1998-2003 Daiki Ueno
3
4 ;; Author: Daiki Ueno <ueno@unixuser.org>
5 ;; Created: 1998-09-28
6 ;; Keywords: IRC, riece
7
8 ;; This file is part of Riece.
9
10 ;; This program is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; This program is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;; Code:
26
27 (require 'riece-misc)
28 (require 'riece-naming)
29 (require 'riece-signal)
30 (require 'riece-display)
31
32 (eval-when-compile
33   (autoload 'riece-default-handle-numeric-reply "riece-handle"))
34 (defun riece-handle-default-300-message (prefix number name string)
35   (riece-default-handle-numeric-reply
36    riece-info-prefix prefix number name string))
37
38 (defun riece-handle-302-message (prefix number name string)
39   "RPL_USERHOST \":*1<reply> *( \" \" <reply> )\""
40   (let ((replies (split-string (if (eq (aref string 0) ?:)
41                                    (substring string 1)
42                                  string)
43                                " ")))
44     (while replies
45       (if (string-match
46            (concat "^\\([^ ]+\\)\\(\\*\\)?=\\([-+]\\)\\([^ ]+\\)")
47            (car replies))
48           (let ((user (match-string 1 (car replies)))
49                 (operator (not (null (match-beginning 2))))
50                 (away (eq (match-string 3 (car replies)) ?-))
51                 (user-at-host (match-string 4 (car replies)))
52                 status)
53             (if away
54                 (setq status (cons "away" status)))
55             (if operator
56                 (setq status (cons "operator" status)))
57             (riece-user-toggle-away user away)
58             (riece-emit-signal 'user-away-changed
59                                (riece-make-identity user riece-server-name)
60                                away)
61             (riece-user-toggle-operator user operator)
62             (riece-emit-signal 'user-operator-changed
63                                (riece-make-identity user riece-server-name)
64                                operator)
65             (riece-insert-info
66              (list riece-dialogue-buffer riece-others-buffer)
67              (concat
68               (riece-concat-server-name
69                (riece-concat-user-status
70                 status
71                 (format "%s is (%s)"
72                         (riece-format-identity
73                          (riece-make-identity user riece-server-name)
74                          t)
75                         (riece-strip-user-at-host user-at-host))))
76               "\n"))))
77       (setq replies (cdr replies)))))
78
79 (defun riece-handle-303-message (prefix number name string)
80   (riece-insert-info
81    (list riece-dialogue-buffer riece-others-buffer)
82    (concat
83     (riece-concat-server-name
84      (concat "Online: "
85              (mapconcat
86               (lambda (user)
87                 (riece-format-identity
88                  (riece-make-identity user riece-server-name)
89                  t))
90               (split-string (if (eq (aref string 0) ?:)
91                                 (substring string 1)
92                               string)
93                             " ")
94               "")))
95     "\n")))
96
97 (defun riece-handle-301-message (prefix number name string)
98   (if (string-match (concat "^\\([^ ]+\\) :?") string)
99       (let ((user (match-string 1 string))
100             (message (substring string (match-end 0))))
101         (riece-user-toggle-away user t)
102         (riece-emit-signal 'user-away-changed
103                            (riece-make-identity user riece-server-name)
104                            t)
105         (riece-insert-info
106          (list riece-dialogue-buffer riece-others-buffer)
107          (concat
108           (riece-concat-server-name
109            (format "%s is away: %s"
110                    (riece-format-identity
111                     (riece-make-identity user riece-server-name)
112                     t)
113                    message))
114           "\n")))))
115
116 (defun riece-handle-305-message (prefix number name string)
117   (riece-user-toggle-away riece-real-nickname nil)
118   (riece-emit-signal 'user-away-changed
119                       (riece-make-identity riece-real-nickname
120                                            riece-server-name)
121                       nil))
122
123 (defun riece-handle-306-message (prefix number name string)
124   (riece-user-toggle-away riece-real-nickname t)
125   (riece-emit-signal 'user-away-changed
126                      (riece-make-identity riece-real-nickname
127                                           riece-server-name)
128                      t))
129
130 (defun riece-handle-311-message (prefix number name string)
131   (if (string-match
132        (concat "^\\([^ ]+\\) \\([^ ]+\\) \\([^ ]+\\) \\* :?")
133        string)
134       (let ((user (match-string 1 string))
135             (name (substring string (match-end 0)))
136             (user-at-host (concat (match-string 2 string) "@"
137                                   (match-string 3 string))))
138         (riece-insert-info
139          (list riece-dialogue-buffer riece-others-buffer)
140          (concat
141           (riece-concat-server-name
142            (format "%s is %s (%s)"
143                    (riece-format-identity
144                     (riece-make-identity user riece-server-name)
145                     t)
146                    name
147                    user-at-host))
148           "\n")))))
149
150 (defun riece-handle-312-message (prefix number name string)
151   (if (string-match
152        (concat "^\\([^ ]+\\) \\([^ ]+\\) :?")
153        string)
154       (riece-insert-info
155        (list riece-dialogue-buffer riece-others-buffer)
156        (concat
157         (riece-concat-server-name
158          (format "on via server %s: %s"
159                  (match-string 2 string)
160                  (substring string (match-end 0))))
161         "\n"))))
162
163 (defun riece-handle-313-message (prefix number name string)
164   (if (string-match "^[^ ]+" string)
165       (let ((user (match-string 0 string)))
166         (riece-insert-info
167          (list riece-dialogue-buffer riece-others-buffer)
168          (concat
169           (riece-concat-server-name
170            (concat (riece-format-identity
171                     (riece-make-identity user riece-server-name)
172                     t)
173                    " is an IRC operator"))
174           "\n")))))
175
176 (defun riece-handle-317-message (prefix number name string)
177   (if (string-match
178        (concat "^\\([^ ]+\\) \\([0-9]+\\) ")
179        string)
180       (let* ((user (match-string 1 string))
181              (seconds (string-to-number (match-string 2 string)))
182              (units (list (cons (/ seconds 60 60 24) "days")
183                           (cons (mod (/ seconds 60 60) 24) "hours")
184                           (cons (mod (/ seconds 60) 60) "minutes")
185                           (cons (mod seconds 60) "seconds"))))
186         (riece-insert-info
187          (list riece-dialogue-buffer riece-others-buffer)
188          (concat
189           (riece-concat-server-name
190            (format "%s is %s idle"
191                    (riece-format-identity
192                     (riece-make-identity user riece-server-name)
193                     t)
194                    (mapconcat #'identity
195                               (delq nil
196                                     (mapcar
197                                      (lambda (unit)
198                                        (if (/= (car unit) 0)
199                                            (format "%d %s"
200                                                    (car unit) (cdr unit))))
201                                      units))
202                               " ")))
203           "\n")))))
204
205 (defun riece-handle-319-message (prefix number name string)
206   (if (string-match (concat "^\\([^ ]+\\) :?") string)
207       (let ((user (match-string 1 string))
208             (channels
209              (mapconcat
210               (lambda (channel)
211                 (if (string-match
212                      (concat "^\\([@+]?\\)\\(" riece-channel-regexp "\\)")
213                      channel)
214                     (concat
215                      (match-string 1 channel)
216                      (riece-format-identity
217                       (riece-make-identity (match-string 2 channel)
218                                            riece-server-name)
219                       t))))
220               (split-string (substring string (match-end 0)) " ")
221               " ")))
222         (riece-insert-info
223          (list riece-dialogue-buffer riece-others-buffer)
224          (concat
225           (riece-concat-server-name
226            (format "%s: %s"
227                    (riece-format-identity
228                     (riece-make-identity user riece-server-name)
229                     t)
230                    channels))
231           "\n")))))
232
233 (defun riece-handle-351-message (prefix number name string)
234   (if (string-match "\\([^ ]+\\.[^ ]+\\) \\([^ ]+\\) :?" string)
235       (riece-insert-info
236        (list riece-dialogue-buffer riece-others-buffer)
237        (concat
238         (riece-concat-server-name
239          (format "%s is running on %s: %s"
240                  (match-string 1 string)
241                  (match-string 2 string)
242                  (substring string (match-end 0))))
243         "\n"))))
244
245 (defvar riece-353-message-alist nil)
246 (defun riece-handle-353-message (prefix number name string)
247   "RPL_NAMREPLY \"[=\*@] <channel> :[[@|+]<nick> [[@|+]<nick> [...]]]\"."
248   (make-local-variable 'riece-353-message-alist)      
249   (if (string-match "^[=\*@] *\\([^ ]+\\) +:?" string)
250       (let* ((channel (match-string 1 string))
251              (entry (riece-identity-assoc channel riece-353-message-alist t)))
252         (if entry
253             (setcdr entry
254                     (concat (cdr entry)
255                             (substring string (match-end 0))))
256           (setq riece-353-message-alist
257                 (cons (cons channel (substring string (match-end 0)))
258                       riece-353-message-alist))))))
259
260 (defun riece-handle-322-message (prefix number name string)
261   (if (string-match "^\\([^ ]+\\) \\([0-9]+\\) :?" string)
262       (let* ((channel (match-string 1 string))
263              (visible (match-string 2 string))
264              (topic (substring string (match-end 0))))
265         (riece-channel-set-topic (riece-get-channel channel) topic)
266         (let* ((channel-identity (riece-make-identity channel
267                                                       riece-server-name))
268                (buffer (riece-channel-buffer channel-identity)))
269           (riece-insert-info buffer (concat visible " users, topic: "
270                                             topic "\n"))
271           (riece-insert-info
272            (if (and riece-channel-buffer-mode
273                     (not (eq buffer riece-channel-buffer)))
274                (list riece-dialogue-buffer riece-others-buffer)
275              riece-dialogue-buffer)
276            (concat
277             (riece-concat-server-name
278              (format "%s: %s users, topic: %s"
279                      (riece-format-identity channel-identity t) visible topic))
280             "\n"))))))
281
282 (defun riece-handle-324-message (prefix number name string)
283   (if (string-match "^\\([^ ]+\\) \\([^ ]+\\) " string)
284       (let* ((channel (match-string 1 string))
285              (mode-string (match-string 2 string)))
286         (riece-naming-assert-channel-modes channel
287                                            (riece-parse-modes mode-string))
288         (let* ((channel-identity (riece-make-identity channel
289                                                       riece-server-name))
290                (buffer (riece-channel-buffer channel-identity)))
291           (riece-insert-info buffer (concat "Mode: " mode-string "\n"))
292           (riece-insert-info
293            (if (and riece-channel-buffer-mode
294                     (not (eq buffer riece-channel-buffer)))
295                (list riece-dialogue-buffer riece-others-buffer)
296              riece-dialogue-buffer)
297            (concat
298             (riece-concat-server-name
299              (format "Mode for %s: %s"
300                      (riece-format-identity channel-identity t)
301                      mode-string))
302             "\n"))))))
303
304 (defun riece-handle-set-topic (prefix number name string remove)
305   (if (string-match "^\\([^ ]+\\) :?" string)
306       (let* ((channel (match-string 1 string))
307              (message (substring string (match-end 0)))
308              (channel-identity (riece-make-identity channel riece-server-name))
309              (buffer (riece-channel-buffer channel-identity)))
310         (if remove
311             (riece-channel-set-topic (riece-get-channel channel) nil)
312           (riece-channel-set-topic (riece-get-channel channel) message)
313           (riece-insert-info buffer (concat "Topic: " message "\n"))
314           (riece-insert-info
315            (if (and riece-channel-buffer-mode
316                     (not (eq buffer riece-channel-buffer)))
317                (list riece-dialogue-buffer riece-others-buffer)
318              riece-dialogue-buffer)
319            (concat
320             (riece-concat-server-name
321              (format "Topic for %s: %s"
322                      (riece-format-identity channel-identity t)
323                      message))
324             "\n")))
325         (riece-emit-signal 'channel-topic-changed
326                             channel-identity
327                             (unless remove
328                               message)))))
329
330 (defun riece-handle-331-message (prefix number name string)
331   (riece-handle-set-topic prefix number name string t))
332
333 (defun riece-handle-332-message (prefix number name string)
334   (riece-handle-set-topic prefix number name string nil))
335
336 (defun riece-handle-341-message (prefix number name string)
337   (if (string-match "^\\([^ ]+\\) " string)
338       (let* ((channel (match-string 1 string))
339              (user (substring string (match-end 0)))
340              (channel-identity (riece-make-identity channel riece-server-name))
341              (buffer (riece-channel-buffer channel-identity)))
342         (riece-insert-info buffer (concat "Inviting " user "\n"))
343         (riece-insert-info
344          (if (and riece-channel-buffer-mode
345                   (not (eq buffer riece-channel-buffer)))
346              (list riece-dialogue-buffer riece-others-buffer)
347            riece-dialogue-buffer)
348          (concat
349           (riece-concat-server-name
350            (format "Inviting %s to %s" user
351                    (riece-format-identity channel-identity t)))
352           "\n")))))
353
354 (defun riece-handle-352-message (prefix number name string)
355   (if (string-match "^\\([^ ]+\\) \\([^ ]+\\) \\([^ ]+\\) \\([^ ]+\\) \\([^ ]+\\) \\([HG]\\)\\(\\*\\)?\\([@+]\\)? :\\([0-9]+\\) " string)
356       (let* ((channel (match-string 1 string))
357              (user (match-string 2 string))
358              (host (match-string 3 string))
359              (server (match-string 4 string))
360              (nick (match-string 5 string))
361              (away (equal (match-string 6 string) "G"))
362              (operator (not (null (match-beginning 7))))
363              (flag (match-string 8 string))
364              (hops (match-string 9 string))
365              (name (substring string (match-end 0)))
366              (buffer (riece-channel-buffer (riece-make-identity
367                                             channel riece-server-name)))
368              (info (format "%10s = %s (%s)"
369                            (concat
370                             (if (memq flag '(?@ ?+))
371                                 (char-to-string flag)
372                               " ")
373                             (riece-format-identity
374                              (riece-make-identity nick riece-server-name)
375                              t))
376                            name
377                            (riece-strip-user-at-host
378                             (concat user "@" host))))
379              status)
380         (if operator
381             (setq status (cons "operator" status)))
382         (if away
383             (setq status (cons "away" status)))
384         (unless (equal hops "0")
385           (setq status (cons (concat "on " server)
386                              (cons (concat hops " hops")
387                                    status))))
388         (if status
389             (setq status (nreverse status)))
390         (riece-naming-assert-join nick channel)
391         (riece-user-toggle-away user away)
392         (riece-emit-signal 'user-away-changed
393                            (riece-make-identity user riece-server-name)
394                            away)
395         (riece-user-toggle-operator user operator)
396         (riece-emit-signal 'user-operator-changed
397                            (riece-make-identity user riece-server-name)
398                            operator)
399         (riece-insert-info buffer (concat (riece-concat-user-status
400                                            status info)
401                                           "\n"))
402         (riece-insert-info
403          (if (and riece-channel-buffer-mode
404                   (not (eq buffer riece-channel-buffer)))
405              (list riece-dialogue-buffer riece-others-buffer)
406            riece-dialogue-buffer)
407          (concat
408           (riece-concat-server-name
409            (riece-concat-user-status
410             status
411             (concat
412              (riece-format-identity
413               (riece-make-identity channel riece-server-name)
414               t)
415              " "
416              info)))
417           "\n")))))
418
419 (defun riece-handle-315-message (prefix number name string))
420 (defun riece-handle-318-message (prefix number name string))
421 (defun riece-handle-323-message (prefix number name string))
422
423 (defun riece-handle-366-message (prefix number name string)
424   "RPL_ENDOFNAMES \"<channel> :End of NAMES list\""
425   (if (string-match "^\\([^ ]+\\) " string)
426       (let* ((channel (match-string 1 string))
427              (channel-identity (riece-make-identity channel
428                                                     riece-server-name))
429              (buffer (riece-channel-buffer channel-identity))
430              (entry (riece-identity-assoc channel riece-353-message-alist t))
431              (string (cdr entry))
432              (start 0)
433              users)
434         (if entry
435             (setq riece-353-message-alist
436                   (delq entry riece-353-message-alist)))
437         (while (string-match
438                 (concat "\\([@+]\\)?\\([^ ]+\\) *")
439                 string start)
440           (put-text-property (match-beginning 2) (match-end 2)
441                              'riece-identity
442                              (riece-make-identity (match-string 2 string)
443                                                   riece-server-name)
444                              string)
445           (setq start (match-end 0)
446                 users (cons (if (match-beginning 1)
447                                 (if (eq (aref string (match-beginning 1)) ?@)
448                                     (list (match-string 2 string) ?o)
449                                   (if (eq (aref string (match-beginning 1)) ?+)
450                                       (list (match-string 2 string) ?v)))
451                               (list (match-string 2 string)))
452                             users)))
453         (setq users (nreverse users))
454         (riece-naming-assert-channel-users users channel)
455         (riece-insert-info
456          buffer
457          (concat (format "%d users: " (length users)) string "\n"))
458         (riece-insert-info
459          (if (and riece-channel-buffer-mode
460                   (not (eq buffer riece-channel-buffer)))
461              (list riece-dialogue-buffer riece-others-buffer)
462            riece-dialogue-buffer)
463          (concat
464           (riece-concat-server-name
465            (concat (format "%d users on %s: "
466                            (length users)
467                            (riece-format-identity channel-identity t))
468                    string))
469           "\n")))))
470
471 (provide 'riece-300)
472
473 ;;; riece-300.el ends here