Commit | Line | Data |
---|---|---|
c6b99621 | 1 | ;;; erc-join.el --- autojoin channels on connect and reconnects |
597993cf | 2 | |
ba318903 | 3 | ;; Copyright (C) 2002-2004, 2006-2014 Free Software Foundation, Inc. |
597993cf MB |
4 | |
5 | ;; Author: Alex Schroeder <alex@gnu.org> | |
34dc21db | 6 | ;; Maintainer: emacs-devel@gnu.org |
597993cf MB |
7 | ;; Keywords: irc |
8 | ;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcAutoJoin | |
9 | ||
10 | ;; This file is part of GNU Emacs. | |
11 | ||
4ee57b2a | 12 | ;; GNU Emacs is free software: you can redistribute it and/or modify |
597993cf | 13 | ;; it under the terms of the GNU General Public License as published by |
4ee57b2a GM |
14 | ;; the Free Software Foundation, either version 3 of the License, or |
15 | ;; (at your option) any later version. | |
597993cf MB |
16 | |
17 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | ;; GNU General Public License for more details. | |
21 | ||
22 | ;; You should have received a copy of the GNU General Public License | |
4ee57b2a | 23 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
597993cf MB |
24 | |
25 | ;;; Commentary: | |
26 | ||
27 | ;; This allows us to customize an `erc-autojoin-channels-alist'. As | |
28 | ;; we /JOIN and /PART channels, this alist is updated to reflect our | |
29 | ;; current setup, so that when we reconnect, we rejoin the same | |
30 | ;; channels. The alist can be customized, so that the customized | |
31 | ;; value will be used when we reconnect in our next Emacs session. | |
32 | ||
33 | ;;; Code: | |
34 | ||
35 | (require 'erc) | |
b2459884 | 36 | (require 'auth-source) |
597993cf MB |
37 | |
38 | (defgroup erc-autojoin nil | |
39 | "Enable autojoining." | |
40 | :group 'erc) | |
41 | ||
c6b99621 | 42 | ;;;###autoload (autoload 'erc-autojoin-mode "erc-join" nil t) |
597993cf MB |
43 | (define-erc-module autojoin nil |
44 | "Makes ERC autojoin on connects and reconnects." | |
45 | ((add-hook 'erc-after-connect 'erc-autojoin-channels) | |
8a8d54cd | 46 | (add-hook 'erc-nickserv-identified-hook 'erc-autojoin-after-ident) |
597993cf MB |
47 | (add-hook 'erc-server-JOIN-functions 'erc-autojoin-add) |
48 | (add-hook 'erc-server-PART-functions 'erc-autojoin-remove)) | |
49 | ((remove-hook 'erc-after-connect 'erc-autojoin-channels) | |
8a8d54cd | 50 | (remove-hook 'erc-nickserv-identified-hook 'erc-autojoin-after-ident) |
597993cf MB |
51 | (remove-hook 'erc-server-JOIN-functions 'erc-autojoin-add) |
52 | (remove-hook 'erc-server-PART-functions 'erc-autojoin-remove))) | |
53 | ||
54 | (defcustom erc-autojoin-channels-alist nil | |
55 | "Alist of channels to autojoin on IRC networks. | |
56 | Every element in the alist has the form (SERVER . CHANNELS). | |
57 | SERVER is a regexp matching the server, and channels is the | |
58 | list of channels to join. | |
59 | ||
b2459884 LMI |
60 | If the channel(s) require channel keys for joining, the passwords |
61 | are found via auth-source. For instance, if you use ~/.authinfo | |
62 | as your auth-source backend, then put something like the | |
63 | following in that file: | |
64 | ||
65 | machine irc.example.net login \"#fsf\" password sEcReT | |
66 | ||
597993cf MB |
67 | Customize this variable to set the value for your first connect. |
68 | Once you are connected and join and part channels, this alist | |
69 | keeps track of what channels you are on, and will join them | |
70 | again when you get disconnected. When you restart Emacs, however, | |
71 | those changes are lost, and the customization you saved the last | |
72 | time is used again." | |
73 | :group 'erc-autojoin | |
74 | :type '(repeat (cons :tag "Server" | |
75 | (regexp :tag "Name") | |
76 | (repeat :tag "Channels" | |
77 | (string :tag "Name"))))) | |
78 | ||
8a8d54cd VD |
79 | (defcustom erc-autojoin-timing 'connect |
80 | "When ERC should attempt to autojoin a channel. | |
81 | If the value is `connect', autojoin immediately on connecting. | |
82 | If the value is `ident', autojoin after successful NickServ | |
83 | identification, or after `erc-autojoin-delay' seconds. | |
84 | Any other value means the same as `connect'." | |
85 | :group 'erc-autojoin | |
c4077254 | 86 | :version "24.1" |
cb785792 JF |
87 | :type '(choice (const :tag "On Connection" connect) |
88 | (const :tag "When Identified" ident))) | |
8a8d54cd VD |
89 | |
90 | (defcustom erc-autojoin-delay 30 | |
91 | "Number of seconds to wait before attempting to autojoin channels. | |
92 | This only takes effect if `erc-autojoin-timing' is `ident'. | |
93 | If NickServ identification occurs before this delay expires, ERC | |
94 | autojoins immediately at that time." | |
95 | :group 'erc-autojoin | |
c4077254 | 96 | :version "24.1" |
8a8d54cd VD |
97 | :type 'integer) |
98 | ||
597993cf MB |
99 | (defcustom erc-autojoin-domain-only t |
100 | "Truncate host name to the domain name when joining a server. | |
101 | If non-nil, and a channel on the server a.b.c is joined, then | |
102 | only b.c is used as the server for `erc-autojoin-channels-alist'. | |
103 | This is important for networks that redirect you to other | |
104 | servers, presumably in the same domain." | |
105 | :group 'erc-autojoin | |
106 | :type 'boolean) | |
107 | ||
8a8d54cd VD |
108 | (defvar erc--autojoin-timer nil) |
109 | (make-variable-buffer-local 'erc--autojoin-timer) | |
110 | ||
111 | (defun erc-autojoin-channels-delayed (server nick buffer) | |
112 | "Attempt to autojoin channels. | |
113 | This is called from a timer set up by `erc-autojoin-channels'." | |
114 | (if erc--autojoin-timer | |
115 | (setq erc--autojoin-timer | |
116 | (erc-cancel-timer erc--autojoin-timer))) | |
117 | (with-current-buffer buffer | |
118 | ;; Don't kick of another delayed autojoin or try to wait for | |
119 | ;; another ident response: | |
120 | (let ((erc-autojoin-delay -1) | |
121 | (erc-autojoin-timing 'connect)) | |
122 | (erc-log "Delayed autojoin started (no ident success detected yet)") | |
123 | (erc-autojoin-channels server nick)))) | |
124 | ||
125 | (defun erc-autojoin-after-ident (network nick) | |
126 | "Autojoin channels in `erc-autojoin-channels-alist'. | |
127 | This function is run from `erc-nickserv-identified-hook'." | |
128 | (if erc--autojoin-timer | |
129 | (setq erc--autojoin-timer | |
130 | (erc-cancel-timer erc--autojoin-timer))) | |
131 | (when (eq erc-autojoin-timing 'ident) | |
132 | (let ((server (or erc-server-announced-name erc-session-server)) | |
133 | (joined (mapcar (lambda (buf) | |
134 | (with-current-buffer buf (erc-default-target))) | |
135 | (erc-channel-list erc-server-process)))) | |
136 | ;; We may already be in these channels, e.g. because the | |
137 | ;; autojoin timer went off. | |
138 | (dolist (l erc-autojoin-channels-alist) | |
139 | (when (string-match (car l) server) | |
140 | (dolist (chan (cdr l)) | |
141 | (unless (erc-member-ignore-case chan joined) | |
b2459884 | 142 | (erc-server-join-channel server chan))))))) |
8a8d54cd VD |
143 | nil) |
144 | ||
597993cf MB |
145 | (defun erc-autojoin-channels (server nick) |
146 | "Autojoin channels in `erc-autojoin-channels-alist'." | |
8a8d54cd VD |
147 | (if (eq erc-autojoin-timing 'ident) |
148 | ;; Prepare the delayed autojoin timer, in case ident doesn't | |
149 | ;; happen within the allotted time limit: | |
150 | (when (> erc-autojoin-delay 0) | |
151 | (setq erc--autojoin-timer | |
152 | (run-with-timer erc-autojoin-delay nil | |
153 | 'erc-autojoin-channels-delayed | |
154 | server nick (current-buffer)))) | |
155 | ;; `erc-autojoin-timing' is `connect': | |
156 | (dolist (l erc-autojoin-channels-alist) | |
157 | (when (string-match (car l) server) | |
158 | (dolist (chan (cdr l)) | |
b2459884 | 159 | (erc-server-join-channel server chan))))) |
8a8d54cd VD |
160 | ;; Return nil to avoid stomping on any other hook funcs. |
161 | nil) | |
597993cf | 162 | |
b2459884 LMI |
163 | (defun erc-server-join-channel (server channel) |
164 | (let* ((secret (plist-get (nth 0 (auth-source-search | |
165 | :max 1 | |
166 | :host server | |
167 | :port "irc" | |
168 | :user channel)) | |
169 | :secret)) | |
170 | (password (if (functionp secret) | |
171 | (funcall secret) | |
172 | secret))) | |
173 | (erc-server-send (concat "join " channel | |
174 | (if password | |
175 | (concat " " password) | |
176 | ""))))) | |
177 | ||
597993cf MB |
178 | (defun erc-autojoin-add (proc parsed) |
179 | "Add the channel being joined to `erc-autojoin-channels-alist'." | |
180 | (let* ((chnl (erc-response.contents parsed)) | |
181 | (nick (car (erc-parse-user (erc-response.sender parsed)))) | |
182 | (server (with-current-buffer (process-buffer proc) | |
183 | (or erc-server-announced-name erc-session-server)))) | |
184 | (when (erc-current-nick-p nick) | |
185 | (when (and erc-autojoin-domain-only | |
21bc768b | 186 | (string-match "[^.\n]+\\.\\([^.\n]+\\.[^.\n]+\\)$" server)) |
597993cf MB |
187 | (setq server (match-string 1 server))) |
188 | (let ((elem (assoc server erc-autojoin-channels-alist))) | |
189 | (if elem | |
190 | (unless (member chnl (cdr elem)) | |
191 | (setcdr elem (cons chnl (cdr elem)))) | |
192 | (setq erc-autojoin-channels-alist | |
193 | (cons (list server chnl) | |
194 | erc-autojoin-channels-alist)))))) | |
195 | ;; We must return nil to tell ERC to continue running the other | |
196 | ;; functions. | |
197 | nil) | |
198 | ||
199 | ;; (erc-parse-user "kensanata!~user@dclient217-162-233-228.hispeed.ch") | |
200 | ||
201 | (defun erc-autojoin-remove (proc parsed) | |
202 | "Remove the channel being left from `erc-autojoin-channels-alist'." | |
203 | (let* ((chnl (car (erc-response.command-args parsed))) | |
204 | (nick (car (erc-parse-user (erc-response.sender parsed)))) | |
205 | (server (with-current-buffer (process-buffer proc) | |
206 | (or erc-server-announced-name erc-session-server)))) | |
207 | (when (erc-current-nick-p nick) | |
208 | (when (and erc-autojoin-domain-only | |
21bc768b | 209 | (string-match "[^.\n]+\\.\\([^.\n]+\\.[^.\n]+\\)$" server)) |
597993cf MB |
210 | (setq server (match-string 1 server))) |
211 | (let ((elem (assoc server erc-autojoin-channels-alist))) | |
212 | (when elem | |
213 | (setcdr elem (delete chnl (cdr elem))) | |
214 | (unless (cdr elem) | |
215 | (setq erc-autojoin-channels-alist | |
216 | (delete elem erc-autojoin-channels-alist))))))) | |
217 | ;; We must return nil to tell ERC to continue running the other | |
218 | ;; functions. | |
219 | nil) | |
220 | ||
c6b99621 | 221 | (provide 'erc-join) |
597993cf | 222 | |
c6b99621 | 223 | ;;; erc-join.el ends here |
597993cf MB |
224 | ;; |
225 | ;; Local Variables: | |
226 | ;; indent-tabs-mode: t | |
227 | ;; tab-width: 8 | |
228 | ;; End: | |
229 |