1;;; erc-notify.el --- Online status change notification 2 3;; Copyright (C) 2002, 2003, 2004, 2006, 2007 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 2, or (at your option) 13;; 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; see the file COPYING. If not, write to the 22;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 23;; Boston, MA 02110-1301, USA. 24 25;;; Commentary: 26 27;; This module defines a new command, /NOTIFY 28;; See the docstring of `erc-cmd-NOTIFY' for details. 29 30;;; Code: 31 32(require 'erc) 33(require 'erc-networks) 34(eval-when-compile 35 (require 'cl) 36 (require 'pcomplete)) 37 38;;;; Customizable variables 39 40(defgroup erc-notify nil 41 "Track online status of certain nicknames." 42 :group 'erc) 43 44(defcustom erc-notify-list nil 45 "*List of nicknames you want to be notified about online/offline 46status change." 47 :group 'erc-notify 48 :type '(repeat string)) 49 50(defcustom erc-notify-interval 60 51 "*Time interval (in seconds) for checking online status of notificated 52people." 53 :group 'erc-notify 54 :type 'integer) 55 56(defcustom erc-notify-signon-hook nil 57 "*Hook run after someone on `erc-notify-list' has signed on. 58Two arguments are passed to the function, SERVER and NICK, both 59strings." 60 :group 'erc-notify 61 :type 'hook 62 :options '(erc-notify-signon)) 63 64(defcustom erc-notify-signoff-hook nil 65 "*Hook run after someone on `erc-notify-list' has signed off. 66Two arguments are passed to the function, SERVER and NICK, both 67strings." 68 :group 'erc-notify 69 :type 'hook 70 :options '(erc-notify-signoff)) 71 72(defun erc-notify-signon (server nick) 73 (message "%s signed on at %s" nick server)) 74 75(defun erc-notify-signoff (server nick) 76 (message "%s signed off from %s" nick server)) 77 78;;;; Internal variables 79 80(defvar erc-last-ison nil 81 "Last ISON information received through `erc-notify-timer'.") 82(make-variable-buffer-local 'erc-last-ison) 83 84(defvar erc-last-ison-time 0 85 "Last time ISON was sent to the server in `erc-notify-timer'.") 86(make-variable-buffer-local 'erc-last-ison-time) 87 88;;;; Setup 89 90(defun erc-notify-install-message-catalogs () 91 (erc-define-catalog 92 'english 93 '((notify_current . "Notificated people online: %l") 94 (notify_list . "Current notify list: %l") 95 (notify_on . "Detected %n on IRC network %m") 96 (notify_off . "%n has left IRC network %m")))) 97 98;;;###autoload (autoload 'erc-notify-mode "erc-notify" nil t) 99(define-erc-module notify nil 100 "Periodically check for the online status of certain users and report 101changes." 102 ((add-hook 'erc-timer-hook 'erc-notify-timer) 103 (add-hook 'erc-server-JOIN-functions 'erc-notify-JOIN) 104 (add-hook 'erc-server-NICK-functions 'erc-notify-NICK) 105 (add-hook 'erc-server-QUIT-functions 'erc-notify-QUIT)) 106 ((remove-hook 'erc-timer-hook 'erc-notify-timer) 107 (remove-hook 'erc-server-JOIN-functions 'erc-notify-JOIN) 108 (remove-hook 'erc-server-NICK-functions 'erc-notify-NICK) 109 (remove-hook 'erc-server-QUIT-functions 'erc-notify-QUIT))) 110 111;;;; Timer handler 112 113(defun erc-notify-timer (now) 114 (when (and 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'. 147If this condition is satisfied, produce a notify_on message and add the nick 148to `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'. 163If this condition is satisfied, produce a notify_on message and add the nick 164to `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'. 179If this condition is satisfied, produce a notify_off message and remove the 180nick 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. 201Without args, list the current list of notificated people online, 202with args, toggle notify status of people." 203 (cond 204 ((null args) 205 ;; Print current notificated 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 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: 252 253;; arch-tag: 0fb19dd0-1359-458a-89b7-81dc195a588e 254