]> code.delx.au - gnu-emacs/blob - lisp/erc/erc-notify.el
Merge from emacs-24; up to 2012-12-06T01:39:03Z!monnier@iro.umontreal.ca
[gnu-emacs] / lisp / erc / erc-notify.el
1 ;;; erc-notify.el --- Online status change notification
2
3 ;; Copyright (C) 2002-2004, 2006-2013 Free Software Foundation, Inc.
4
5 ;; Author: Mario Lang <mlang@lexx.delysid.org>
6 ;; Maintainer: FSF
7 ;; Keywords: comm
8
9 ;; This file is part of GNU Emacs.
10
11 ;; GNU Emacs is free software: you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation, either version 3 of the License, or
14 ;; (at your option) any later version.
15
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
23
24 ;;; Commentary:
25
26 ;; This module defines a new command, /NOTIFY
27 ;; See the docstring of `erc-cmd-NOTIFY' for details.
28
29 ;;; Code:
30
31 (require 'erc)
32 (require 'erc-networks)
33 (eval-when-compile (require 'pcomplete))
34
35 ;;;; Customizable variables
36
37 (defgroup erc-notify nil
38 "Track online status of certain nicknames."
39 :group 'erc)
40
41 (defcustom erc-notify-list nil
42 "List of nicknames you want to be notified about online/offline
43 status change."
44 :group 'erc-notify
45 :type '(repeat string))
46
47 (defcustom erc-notify-interval 60
48 "Time interval (in seconds) for checking online status of notified
49 people."
50 :group 'erc-notify
51 :type 'integer)
52
53 (defcustom erc-notify-signon-hook nil
54 "Hook run after someone on `erc-notify-list' has signed on.
55 Two arguments are passed to the function, SERVER and NICK, both
56 strings."
57 :group 'erc-notify
58 :type 'hook
59 :options '(erc-notify-signon))
60
61 (defcustom erc-notify-signoff-hook nil
62 "Hook run after someone on `erc-notify-list' has signed off.
63 Two arguments are passed to the function, SERVER and NICK, both
64 strings."
65 :group 'erc-notify
66 :type 'hook
67 :options '(erc-notify-signoff))
68
69 (defun erc-notify-signon (server nick)
70 (message "%s signed on at %s" nick server))
71
72 (defun erc-notify-signoff (server nick)
73 (message "%s signed off from %s" nick server))
74
75 ;;;; Internal variables
76
77 (defvar erc-last-ison nil
78 "Last ISON information received through `erc-notify-timer'.")
79 (make-variable-buffer-local 'erc-last-ison)
80
81 (defvar erc-last-ison-time 0
82 "Last time ISON was sent to the server in `erc-notify-timer'.")
83 (make-variable-buffer-local 'erc-last-ison-time)
84
85 ;;;; Setup
86
87 (defun erc-notify-install-message-catalogs ()
88 (erc-define-catalog
89 'english
90 '((notify_current . "Notified people online: %l")
91 (notify_list . "Current notify list: %l")
92 (notify_on . "Detected %n on IRC network %m")
93 (notify_off . "%n has left IRC network %m"))))
94
95 ;;;###autoload (autoload 'erc-notify-mode "erc-notify" nil t)
96 (define-erc-module notify nil
97 "Periodically check for the online status of certain users and report
98 changes."
99 ((add-hook 'erc-timer-hook 'erc-notify-timer)
100 (add-hook 'erc-server-JOIN-functions 'erc-notify-JOIN)
101 (add-hook 'erc-server-NICK-functions 'erc-notify-NICK)
102 (add-hook 'erc-server-QUIT-functions 'erc-notify-QUIT))
103 ((remove-hook 'erc-timer-hook 'erc-notify-timer)
104 (remove-hook 'erc-server-JOIN-functions 'erc-notify-JOIN)
105 (remove-hook 'erc-server-NICK-functions 'erc-notify-NICK)
106 (remove-hook 'erc-server-QUIT-functions 'erc-notify-QUIT)))
107
108 ;;;; Timer handler
109
110 (defun erc-notify-timer (now)
111 (when (and erc-server-connected
112 erc-notify-list
113 (> (erc-time-diff
114 erc-last-ison-time now)
115 erc-notify-interval))
116 (erc-once-with-server-event
117 303
118 '(let* ((server (erc-response.sender parsed))
119 (ison-list (delete "" (split-string
120 (erc-response.contents parsed))))
121 (new-list ison-list)
122 (old-list (erc-with-server-buffer erc-last-ison)))
123 (while new-list
124 (when (not (erc-member-ignore-case (car new-list) old-list))
125 (run-hook-with-args 'erc-notify-signon-hook server (car new-list))
126 (erc-display-message
127 parsed 'notice proc
128 'notify_on ?n (car new-list) ?m (erc-network-name)))
129 (setq new-list (cdr new-list)))
130 (while old-list
131 (when (not (erc-member-ignore-case (car old-list) ison-list))
132 (run-hook-with-args 'erc-notify-signoff-hook server (car old-list))
133 (erc-display-message
134 parsed 'notice proc
135 'notify_off ?n (car old-list) ?m (erc-network-name)))
136 (setq old-list (cdr old-list)))
137 (setq erc-last-ison ison-list)
138 t))
139 (erc-server-send
140 (concat "ISON " (mapconcat 'identity erc-notify-list " ")))
141 (setq erc-last-ison-time now)))
142
143 (defun erc-notify-JOIN (proc parsed)
144 "Check if channel joiner is on `erc-notify-list' and not on `erc-last-ison'.
145 If this condition is satisfied, produce a notify_on message and add the nick
146 to `erc-last-ison' to prevent any further notifications."
147 (let ((nick (erc-extract-nick (erc-response.sender parsed))))
148 (when (and (erc-member-ignore-case nick erc-notify-list)
149 (not (erc-member-ignore-case nick erc-last-ison)))
150 (add-to-list 'erc-last-ison nick)
151 (run-hook-with-args 'erc-notify-signon-hook
152 (or erc-server-announced-name erc-session-server)
153 nick)
154 (erc-display-message
155 parsed 'notice proc
156 'notify_on ?n nick ?m (erc-network-name)))
157 nil))
158
159 (defun erc-notify-NICK (proc parsed)
160 "Check if new nick is on `erc-notify-list' and not on `erc-last-ison'.
161 If this condition is satisfied, produce a notify_on message and add the nick
162 to `erc-last-ison' to prevent any further notifications."
163 (let ((nick (erc-response.contents parsed)))
164 (when (and (erc-member-ignore-case nick erc-notify-list)
165 (not (erc-member-ignore-case nick erc-last-ison)))
166 (add-to-list 'erc-last-ison nick)
167 (run-hook-with-args 'erc-notify-signon-hook
168 (or erc-server-announced-name erc-session-server)
169 nick)
170 (erc-display-message
171 parsed 'notice proc
172 'notify_on ?n nick ?m (erc-network-name)))
173 nil))
174
175 (defun erc-notify-QUIT (proc parsed)
176 "Check if quitter is on `erc-notify-list' and on `erc-last-ison'.
177 If this condition is satisfied, produce a notify_off message and remove the
178 nick from `erc-last-ison' to prevent any further notifications."
179 (let ((nick (erc-extract-nick (erc-response.sender parsed))))
180 (when (and (erc-member-ignore-case nick erc-notify-list)
181 (erc-member-ignore-case nick erc-last-ison))
182 (setq erc-last-ison (erc-delete-if `(lambda (el)
183 (string= ,(erc-downcase nick)
184 (erc-downcase el)))
185 erc-last-ison))
186 (run-hook-with-args 'erc-notify-signoff-hook
187 (or erc-server-announced-name erc-session-server)
188 nick)
189 (erc-display-message
190 parsed 'notice proc
191 'notify_off ?n nick ?m (erc-network-name)))
192 nil))
193
194 ;;;; User level command
195
196 ;;;###autoload
197 (defun erc-cmd-NOTIFY (&rest args)
198 "Change `erc-notify-list' or list current notify-list members online.
199 Without args, list the current list of notified people online,
200 with args, toggle notify status of people."
201 (cond
202 ((null args)
203 ;; Print current notified people (online)
204 (let ((ison (erc-with-server-buffer erc-last-ison)))
205 (if (not ison)
206 (erc-display-message
207 nil 'notice 'active "No ison-list yet!")
208 (erc-display-message
209 nil 'notice 'active
210 'notify_current ?l ison))))
211 ((string= (car args) "-l")
212 (erc-display-message nil 'notice 'active
213 'notify_list ?l (mapconcat 'identity erc-notify-list
214 " ")))
215 (t
216 (while args
217 (if (erc-member-ignore-case (car args) erc-notify-list)
218 (progn
219 (setq erc-notify-list (delete (car args) erc-notify-list))
220 ;; Remove the nick from the value of erc-last-ison in
221 ;; every server buffer. This prevents seeing a signoff
222 ;; notification for a nick that you have just _removed_
223 ;; from your notify list.
224 (dolist (buf (erc-buffer-list))
225 (with-current-buffer buf
226 (if (erc-server-buffer-p)
227 (setq erc-last-ison (delete (car args) erc-last-ison))))))
228 (setq erc-notify-list (cons (erc-string-no-properties (car args))
229 erc-notify-list)))
230 (setq args (cdr args)))
231 (erc-display-message
232 nil 'notice 'active
233 'notify_list ?l (mapconcat 'identity erc-notify-list " "))))
234 t)
235
236 (autoload 'pcomplete-erc-all-nicks "erc-pcomplete")
237
238 ;;;###autoload
239 (defun pcomplete/erc-mode/NOTIFY ()
240 (pcomplete-here (pcomplete-erc-all-nicks)))
241
242 (erc-notify-install-message-catalogs)
243
244 (provide 'erc-notify)
245
246 ;;; erc-notify.el ends here
247 ;;
248 ;; Local Variables:
249 ;; indent-tabs-mode: t
250 ;; tab-width: 8
251 ;; End: