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