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