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