summaryrefslogtreecommitdiff
path: root/lisp/erc
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/erc')
-rw-r--r--lisp/erc/erc-join.el121
1 files changed, 50 insertions, 71 deletions
diff --git a/lisp/erc/erc-join.el b/lisp/erc/erc-join.el
index 425de4dc564..d4edca236d1 100644
--- a/lisp/erc/erc-join.el
+++ b/lisp/erc/erc-join.el
@@ -33,8 +33,6 @@
;;; Code:
(require 'erc)
-(require 'auth-source)
-(require 'erc-networks)
(defgroup erc-autojoin nil
"Enable autojoining."
@@ -57,11 +55,16 @@
Every element in the alist has the form (SERVER . CHANNELS).
SERVER is a regexp matching the server, and channels is the list
of channels to join. SERVER can also be a symbol, in which case
-it is matched against the value of `erc-network' instead of
+it's matched against a non-nil `:id' passed to `erc' or `erc-tls'
+when connecting or the value of the current `erc-network' instead of
`erc-server-announced-name' or `erc-session-server' (this can be
useful when connecting to an IRC proxy that relays several
networks under the same server).
+Note that for historical reasons, this option is mutated at runtime,
+which is regrettable but here to stay. Please double check the value
+before saving it to a `custom-file'.
+
If the channel(s) require channel keys for joining, the passwords
are found via auth-source. For instance, if you use ~/.authinfo
as your auth-source backend, then put something like the
@@ -123,33 +126,32 @@ This is called from a timer set up by `erc-autojoin-channels'."
(erc-autojoin-channels server nick))))
(defun erc-autojoin-server-match (candidate)
- "Match the current network or server against CANDIDATE.
-This should be a key from `erc-autojoin-channels-alist'."
- (or (eq candidate (erc-network))
- (and (stringp candidate)
- (string-match-p candidate
- (or erc-server-announced-name
- erc-session-server)))))
+ "Match the current network ID or server against CANDIDATE.
+CANDIDATE is a key from `erc-autojoin-channels-alist'. Return the
+matching entity, either a string or a non-nil symbol (in the case of a
+network or a network ID). Return nil on failure."
+ (if (symbolp candidate)
+ (eq (or (erc-networks--id-given erc-networks--id) (erc-network))
+ candidate)
+ (when (stringp candidate)
+ (string-match-p candidate (or erc-server-announced-name
+ erc-session-server)))))
+
+(defun erc-autojoin--join ()
+ ;; This is called in the server buffer
+ (pcase-dolist (`(,name . ,channels) erc-autojoin-channels-alist)
+ (when-let ((match (erc-autojoin-server-match name)))
+ (dolist (chan channels)
+ (let ((buf (erc-get-buffer chan erc-server-process)))
+ (unless (and buf (with-current-buffer buf
+ (erc--current-buffer-joined-p)))
+ (erc-server-join-channel match chan)))))))
(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
- (cancel-timer erc--autojoin-timer)))
(when (eq erc-autojoin-timing 'ident)
- (let ((server (or erc-session-server erc-server-announced-name))
- (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 (erc-autojoin-server-match (car l))
- (dolist (chan (cdr l))
- (unless (erc-member-ignore-case chan joined)
- (erc-server-join-channel server chan)))))))
- nil)
+ (erc-autojoin--join)))
(defun erc-autojoin-channels (server nick)
"Autojoin channels in `erc-autojoin-channels-alist'."
@@ -162,24 +164,7 @@ This function is run from `erc-nickserv-identified-hook'."
#'erc-autojoin-channels-delayed
server nick (current-buffer))))
;; `erc-autojoin-timing' is `connect':
- (let ((server (or erc-session-server erc-server-announced-name)))
- (dolist (l erc-autojoin-channels-alist)
- (when (erc-autojoin-server-match (car l))
- (dolist (chan (cdr l))
- (let ((buffer
- (car (erc-buffer-filter
- (lambda ()
- (let ((current (erc-default-target)))
- (and (stringp current)
- (erc-autojoin-server-match (car l))
- (string-equal (erc-downcase chan)
- (erc-downcase current)))))))))
- (when (or (not buffer)
- (not (with-current-buffer buffer
- (erc--current-buffer-joined-p))))
- (erc-server-join-channel server chan))))))))
- ;; Return nil to avoid stomping on any other hook funcs.
- nil)
+ (erc-autojoin--join)))
(defun erc-autojoin-current-server ()
"Compute the current server for lookup in `erc-autojoin-channels-alist'.
@@ -190,24 +175,29 @@ Respects `erc-autojoin-domain-only'."
(match-string 1 server)
server)))
+(defun erc-autojoin--mutate (proc parsed remove)
+ (when-let* ((nick (car (erc-parse-user (erc-response.sender parsed))))
+ ((erc-current-nick-p nick))
+ (chnl (car (erc-response.command-args parsed)))
+ (elem (or (and (erc--valid-local-channel-p chnl)
+ (regexp-quote erc-server-announced-name))
+ (erc-networks--id-given erc-networks--id)
+ (erc-network)
+ (with-current-buffer (process-buffer proc)
+ (erc-autojoin-current-server))))
+ (test (if (symbolp elem) #'eq #'equal)))
+ (if remove
+ (let ((cs (delete chnl (assoc-default elem erc-autojoin-channels-alist
+ test))))
+ (setf (alist-get elem erc-autojoin-channels-alist nil (null cs) test)
+ cs))
+ (cl-pushnew chnl
+ (alist-get elem erc-autojoin-channels-alist nil nil test)
+ :test #'equal))))
+
(defun erc-autojoin-add (proc parsed)
"Add the channel being joined to `erc-autojoin-channels-alist'."
- (let* ((chnl (erc-response.contents parsed))
- (nick (car (erc-parse-user (erc-response.sender parsed))))
- (server (with-current-buffer (process-buffer proc)
- (erc-autojoin-current-server))))
- (when (erc-current-nick-p nick)
- (let ((elem (or (assoc (erc-network) erc-autojoin-channels-alist)
- (assoc server erc-autojoin-channels-alist))))
- (if elem
- (unless (member chnl (cdr elem))
- (setcdr elem (cons chnl (cdr elem))))
- ;; This always keys on server, not network -- user can
- ;; override by simply adding a network to
- ;; `erc-autojoin-channels-alist'
- (setq erc-autojoin-channels-alist
- (cons (list server chnl)
- erc-autojoin-channels-alist))))))
+ (erc-autojoin--mutate proc parsed nil)
;; We must return nil to tell ERC to continue running the other
;; functions.
nil)
@@ -216,18 +206,7 @@ Respects `erc-autojoin-domain-only'."
(defun erc-autojoin-remove (proc parsed)
"Remove the channel being left from `erc-autojoin-channels-alist'."
- (let* ((chnl (car (erc-response.command-args parsed)))
- (nick (car (erc-parse-user (erc-response.sender parsed))))
- (server (with-current-buffer (process-buffer proc)
- (erc-autojoin-current-server))))
- (when (erc-current-nick-p nick)
- (let ((elem (or (assoc (erc-network) erc-autojoin-channels-alist)
- (assoc server erc-autojoin-channels-alist))))
- (when elem
- (setcdr elem (delete chnl (cdr elem)))
- (unless (cdr elem)
- (setq erc-autojoin-channels-alist
- (delete elem erc-autojoin-channels-alist)))))))
+ (erc-autojoin--mutate proc parsed 'remove)
;; We must return nil to tell ERC to continue running the other
;; functions.
nil)