erc-notify.el 8.4 KB

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