changeset 109784:2abe46caa971

Allow delayed autojoin in ERC (Bug#5521). * erc/erc-join.el (erc-autojoin-timing, erc-autojoin-delay): New vars. (erc-autojoin-channels-delayed, erc-autojoin-after-ident): New functions. (erc-autojoin-channels): Allow autojoining after ident (Bug#5521).
author Chong Yidong <cyd@stupidchicken.com>
date Sat, 14 Aug 2010 18:58:10 -0400
parents 43f98127e0f3
children de5d6a3f1493
files etc/NEWS lisp/erc/ChangeLog lisp/erc/erc-join.el
diffstat 3 files changed, 87 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/etc/NEWS	Sat Aug 14 22:14:02 2010 +0000
+++ b/etc/NEWS	Sat Aug 14 18:58:10 2010 -0400
@@ -213,6 +213,14 @@
 
 ** Archive Mode has basic support to browse 7z archives.
 
+** ERC changes
+
+*** New vars `erc-autojoin-timing' and `erc-autojoin-delay'.
+If the value of `erc-autojoin-timing' is 'ident, ERC autojoins after a
+successful NickServ identification, or after `erc-autojoin-delay'
+seconds.  The default value, 'ident, means to autojoin immediately
+after connecting.
+
 ** In ido-mode, C-v is no longer bound to ido-toggle-vc.
 The reason is that this interferes with cua-mode.
 
--- a/lisp/erc/ChangeLog	Sat Aug 14 22:14:02 2010 +0000
+++ b/lisp/erc/ChangeLog	Sat Aug 14 18:58:10 2010 -0400
@@ -1,3 +1,10 @@
+2010-08-14  Vivek Dasmohapatra  <vivek@etla.org>
+
+	* erc-join.el (erc-autojoin-timing, erc-autojoin-delay): New vars.
+	(erc-autojoin-channels-delayed, erc-autojoin-after-ident): New
+	functions.
+	(erc-autojoin-channels): Allow autojoining after ident (Bug#5521).
+
 2010-08-08  Fran Litterio  <flitterio@gmail.com>
 
 	* erc-backend.el (erc-server-filter-function): Call
--- a/lisp/erc/erc-join.el	Sat Aug 14 22:14:02 2010 +0000
+++ b/lisp/erc/erc-join.el	Sat Aug 14 18:58:10 2010 -0400
@@ -42,9 +42,11 @@
 (define-erc-module autojoin nil
   "Makes ERC autojoin on connects and reconnects."
   ((add-hook 'erc-after-connect 'erc-autojoin-channels)
+   (add-hook 'erc-nickserv-identified-hook 'erc-autojoin-after-ident)
    (add-hook 'erc-server-JOIN-functions 'erc-autojoin-add)
    (add-hook 'erc-server-PART-functions 'erc-autojoin-remove))
   ((remove-hook 'erc-after-connect 'erc-autojoin-channels)
+   (remove-hook 'erc-nickserv-identified-hook 'erc-autojoin-after-ident)
    (remove-hook 'erc-server-JOIN-functions 'erc-autojoin-add)
    (remove-hook 'erc-server-PART-functions 'erc-autojoin-remove)))
 
@@ -66,6 +68,24 @@
 		       (repeat :tag "Channels"
 			       (string :tag "Name")))))
 
+(defcustom erc-autojoin-timing 'connect
+  "When ERC should attempt to autojoin a channel.
+If the value is `connect', autojoin immediately on connecting.
+If the value is `ident', autojoin after successful NickServ
+identification, or after `erc-autojoin-delay' seconds.
+Any other value means the same as `connect'."
+  :group 'erc-autojoin
+  :type  '(choice (const :tag "On Connection" 'connect)
+		  (const :tag "When Identified" 'ident)))
+
+(defcustom erc-autojoin-delay 30
+  "Number of seconds to wait before attempting to autojoin channels.
+This only takes effect if `erc-autojoin-timing' is `ident'.
+If NickServ identification occurs before this delay expires, ERC
+autojoins immediately at that time."
+  :group 'erc-autojoin
+  :type  'integer)
+
 (defcustom erc-autojoin-domain-only t
   "Truncate host name to the domain name when joining a server.
 If non-nil, and a channel on the server a.b.c is joined, then
@@ -75,12 +95,60 @@
   :group 'erc-autojoin
   :type 'boolean)
 
+(defvar erc--autojoin-timer nil)
+(make-variable-buffer-local 'erc--autojoin-timer)
+
+(defun erc-autojoin-channels-delayed (server nick buffer)
+  "Attempt to autojoin channels.
+This is called from a timer set up by `erc-autojoin-channels'."
+  (if erc--autojoin-timer
+      (setq erc--autojoin-timer
+	    (erc-cancel-timer erc--autojoin-timer)))
+  (with-current-buffer buffer
+    ;; Don't kick of another delayed autojoin or try to wait for
+    ;; another ident response:
+    (let ((erc-autojoin-delay -1)
+	  (erc-autojoin-timing 'connect))
+      (erc-log "Delayed autojoin started (no ident success detected yet)")
+      (erc-autojoin-channels server nick))))
+
+(defun erc-autojoin-after-ident (network nick)
+  "Autojoin channels in `erc-autojoin-channels-alist'.
+This function is run from `erc-nickserv-identified-hook'."
+  (if erc--autojoin-timer
+      (setq erc--autojoin-timer
+	    (erc-cancel-timer erc--autojoin-timer)))
+  (when (eq erc-autojoin-timing 'ident)
+    (let ((server (or erc-server-announced-name erc-session-server))
+	  (joined (mapcar (lambda (buf)
+			    (with-current-buffer buf (erc-default-target)))
+			  (erc-channel-list erc-server-process))))
+      ;; We may already be in these channels, e.g. because the
+      ;; autojoin timer went off.
+      (dolist (l erc-autojoin-channels-alist)
+	(when (string-match (car l) server)
+	  (dolist (chan (cdr l))
+	    (unless (erc-member-ignore-case chan joined)
+	      (erc-server-send (concat "join " chan))))))))
+  nil)
+
 (defun erc-autojoin-channels (server nick)
   "Autojoin channels in `erc-autojoin-channels-alist'."
-  (dolist (l erc-autojoin-channels-alist)
-    (when (string-match (car l) server)
-      (dolist (chan (cdr l))
-	(erc-server-send (concat "join " chan))))))
+  (if (eq erc-autojoin-timing 'ident)
+      ;; Prepare the delayed autojoin timer, in case ident doesn't
+      ;; happen within the allotted time limit:
+      (when (> erc-autojoin-delay 0)
+	(setq erc--autojoin-timer
+	      (run-with-timer erc-autojoin-delay nil
+			      'erc-autojoin-channels-delayed
+			      server nick (current-buffer))))
+    ;; `erc-autojoin-timing' is `connect':
+    (dolist (l erc-autojoin-channels-alist)
+      (when (string-match (car l) server)
+	(dolist (chan (cdr l))
+	  (erc-server-send (concat "join " chan))))))
+  ;; Return nil to avoid stomping on any other hook funcs.
+  nil)
 
 (defun erc-autojoin-add (proc parsed)
   "Add the channel being joined to `erc-autojoin-channels-alist'."