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