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