68719
|
1 ;;; erc-services.el --- Identify to NickServ
|
|
2
|
79706
|
3 ;; Copyright (C) 2002, 2003, 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
|
68719
|
4
|
|
5 ;; This file is part of GNU Emacs.
|
|
6
|
94660
|
7 ;; GNU Emacs is free software: you can redistribute it and/or modify
|
68719
|
8 ;; it under the terms of the GNU General Public License as published by
|
94660
|
9 ;; the Free Software Foundation, either version 3 of the License, or
|
|
10 ;; (at your option) any later version.
|
68719
|
11
|
|
12 ;; GNU Emacs is distributed in the hope that it will be useful,
|
|
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15 ;; GNU General Public License for more details.
|
|
16
|
|
17 ;; You should have received a copy of the GNU General Public License
|
94660
|
18 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
68719
|
19
|
|
20 ;;; Commentary:
|
|
21
|
|
22 ;; There are two ways to go about identifying yourself automatically to
|
|
23 ;; NickServ with this module. The more secure way is to listen for identify
|
|
24 ;; requests from the user NickServ. Another way is to identify yourself to
|
|
25 ;; NickServ directly after a successful connection and every time you change
|
|
26 ;; your nickname. This method is rather insecure, though, because no checks
|
|
27 ;; are made to test if NickServ is the real NickServ for a given network or
|
|
28 ;; server.
|
|
29
|
87202
|
30 ;; As a default, ERC has the data for the official nickname services on
|
|
31 ;; the networks Austnet, BrasNET, Dalnet, freenode, GalaxyNet, GRnet,
|
|
32 ;; and Slashnet. You can add more by using M-x customize-variable RET
|
|
33 ;; erc-nickserv-alist.
|
68719
|
34
|
|
35 ;; Usage:
|
|
36 ;;
|
|
37 ;; Put into your .emacs:
|
|
38 ;;
|
|
39 ;; (require 'erc-services)
|
|
40 ;; (erc-services-mode 1)
|
|
41 ;;
|
|
42 ;; Add your nickname and NickServ password to `erc-nickserv-passwords'.
|
|
43 ;; Using the freenode network as an example:
|
|
44 ;;
|
|
45 ;; (setq erc-nickserv-passwords '((freenode (("nickname" "password")))))
|
|
46 ;;
|
|
47 ;; The default automatic identification mode is autodetection of NickServ
|
|
48 ;; identify requests. Set the variable `erc-nickserv-identify-mode' if
|
|
49 ;; you'd like to change this behavior. You can also change the way
|
|
50 ;; automatic identification is handled by using:
|
|
51 ;;
|
|
52 ;; M-x erc-nickserv-identify-mode
|
|
53 ;;
|
|
54 ;; If you'd rather not identify yourself automatically but would like access
|
|
55 ;; to the functions contained in this file, just load this file without
|
|
56 ;; enabling `erc-services-mode'.
|
|
57 ;;
|
|
58
|
|
59 ;;; Code:
|
|
60
|
|
61 (require 'erc)
|
|
62 (require 'erc-networks)
|
|
63 (eval-when-compile (require 'cl))
|
|
64
|
|
65 ;; Customization:
|
|
66
|
|
67 (defgroup erc-services nil
|
|
68 "Configuration for IRC services.
|
|
69
|
|
70 On some networks, there exists a special type of automated irc bot,
|
|
71 called Services. Those usually allow you to register your nickname,
|
|
72 post/read memos to other registered users who are currently offline,
|
|
73 and do various other things.
|
|
74
|
|
75 This group allows you to set variables to somewhat automate
|
|
76 communication with those Services."
|
|
77 :group 'erc)
|
|
78
|
75259
|
79 (defcustom erc-nickserv-identify-mode 'both
|
|
80 "The mode which is used when identifying to Nickserv.
|
|
81
|
|
82 Possible settings are:.
|
|
83
|
|
84 'autodetect - Identify when the real Nickserv sends an identify request.
|
|
85 'nick-change - Identify when you log in or change your nickname.
|
|
86 'both - Do the former if the network supports it, otherwise do the
|
|
87 latter.
|
|
88 nil - Disables automatic Nickserv identification.
|
|
89
|
|
90 You can also use M-x erc-nickserv-identify-mode to change modes."
|
|
91 :group 'erc-services
|
|
92 :type '(choice (const autodetect)
|
|
93 (const nick-change)
|
|
94 (const both)
|
|
95 (const nil))
|
|
96 :set (lambda (sym val)
|
|
97 (set sym val)
|
|
98 ;; avoid recursive load at startup
|
|
99 (when (featurep 'erc-services)
|
|
100 (erc-nickserv-identify-mode val))))
|
|
101
|
68719
|
102 ;;;###autoload (autoload 'erc-services-mode "erc-services" nil t)
|
|
103 (define-erc-module services nickserv
|
|
104 "This mode automates communication with services."
|
|
105 ((erc-nickserv-identify-mode erc-nickserv-identify-mode))
|
|
106 ((remove-hook 'erc-server-NOTICE-functions
|
|
107 'erc-nickserv-identify-autodetect)
|
|
108 (remove-hook 'erc-after-connect
|
|
109 'erc-nickserv-identify-on-connect)
|
|
110 (remove-hook 'erc-nick-changed-functions
|
87202
|
111 'erc-nickserv-identify-on-nick-change)
|
|
112 (remove-hook 'erc-server-NOTICE-functions
|
|
113 'erc-nickserv-identification-autodetect)))
|
68719
|
114
|
|
115 ;;;###autoload
|
|
116 (defun erc-nickserv-identify-mode (mode)
|
|
117 "Set up hooks according to which MODE the user has chosen."
|
|
118 (interactive
|
|
119 (list (intern (completing-read
|
|
120 "Choose Nickserv identify mode (RET to disable): "
|
75092
|
121 '(("autodetect") ("nick-change") ("both")) nil t))))
|
87202
|
122 (add-hook 'erc-server-NOTICE-functions
|
|
123 'erc-nickserv-identification-autodetect)
|
87952
|
124 (unless erc-networks-mode
|
|
125 ;; Force-enable networks module, because we need it to set
|
|
126 ;; erc-network for us.
|
|
127 (erc-networks-enable))
|
68719
|
128 (cond ((eq mode 'autodetect)
|
|
129 (setq erc-nickserv-identify-mode 'autodetect)
|
|
130 (add-hook 'erc-server-NOTICE-functions
|
|
131 'erc-nickserv-identify-autodetect)
|
|
132 (remove-hook 'erc-nick-changed-functions
|
|
133 'erc-nickserv-identify-on-nick-change)
|
|
134 (remove-hook 'erc-after-connect
|
|
135 'erc-nickserv-identify-on-connect))
|
|
136 ((eq mode 'nick-change)
|
|
137 (setq erc-nickserv-identify-mode 'nick-change)
|
|
138 (add-hook 'erc-after-connect
|
|
139 'erc-nickserv-identify-on-connect)
|
|
140 (add-hook 'erc-nick-changed-functions
|
|
141 'erc-nickserv-identify-on-nick-change)
|
|
142 (remove-hook 'erc-server-NOTICE-functions
|
|
143 'erc-nickserv-identify-autodetect))
|
75092
|
144 ((eq mode 'both)
|
|
145 (setq erc-nickserv-identify-mode 'both)
|
|
146 (add-hook 'erc-server-NOTICE-functions
|
|
147 'erc-nickserv-identify-autodetect)
|
|
148 (add-hook 'erc-after-connect
|
|
149 'erc-nickserv-identify-on-connect)
|
|
150 (add-hook 'erc-nick-changed-functions
|
|
151 'erc-nickserv-identify-on-nick-change))
|
68719
|
152 (t
|
|
153 (setq erc-nickserv-identify-mode nil)
|
|
154 (remove-hook 'erc-server-NOTICE-functions
|
|
155 'erc-nickserv-identify-autodetect)
|
|
156 (remove-hook 'erc-after-connect
|
|
157 'erc-nickserv-identify-on-connect)
|
|
158 (remove-hook 'erc-nick-changed-functions
|
87202
|
159 'erc-nickserv-identify-on-nick-change)
|
|
160 (remove-hook 'erc-server-NOTICE-functions
|
|
161 'erc-nickserv-identification-autodetect))))
|
68719
|
162
|
|
163 (defcustom erc-prompt-for-nickserv-password t
|
|
164 "Ask for the password when identifying to NickServ."
|
|
165 :group 'erc-services
|
|
166 :type 'boolean)
|
|
167
|
|
168 (defcustom erc-nickserv-passwords nil
|
|
169 "Passwords used when identifying to NickServ automatically.
|
|
170
|
|
171 Example of use:
|
|
172 (setq erc-nickserv-passwords
|
|
173 '((freenode ((\"nick-one\" . \"password\")
|
|
174 (\"nick-two\" . \"password\")))
|
|
175 (DALnet ((\"nick\" . \"password\")))))"
|
|
176 :group 'erc-services
|
|
177 :type '(repeat
|
|
178 (list :tag "Network"
|
|
179 (choice :tag "Network name"
|
76856
|
180 (const Ars)
|
68719
|
181 (const Austnet)
|
75092
|
182 (const Azzurra)
|
76856
|
183 (const BitlBee)
|
|
184 (const BRASnet)
|
|
185 (const DALnet)
|
|
186 (const freenode)
|
|
187 (const GalaxyNet)
|
87202
|
188 (const GRnet)
|
76856
|
189 (const iip)
|
|
190 (const OFTC)
|
|
191 (const QuakeNet)
|
87952
|
192 (const Rizon)
|
76856
|
193 (const SlashNET)
|
68719
|
194 (symbol :tag "Network name"))
|
|
195 (repeat :tag "Nickname and password"
|
|
196 (cons :tag "Identity"
|
|
197 (string :tag "Nick")
|
|
198 (string :tag "Password"))))))
|
|
199
|
|
200 ;; Variables:
|
|
201
|
|
202 (defcustom erc-nickserv-alist
|
76856
|
203 '((Ars
|
|
204 nil nil
|
|
205 "Census"
|
87202
|
206 "IDENTIFY" nil nil nil)
|
76856
|
207 (Austnet
|
|
208 "NickOP!service@austnet.org"
|
|
209 "/msg\\s-NickOP@austnet.org\\s-identify\\s-<password>"
|
|
210 "nickop@austnet.org"
|
87202
|
211 "identify" nil nil nil)
|
76856
|
212 (Azzurra
|
|
213 "NickServ!service@azzurra.org"
|
|
214 "/ns\\s-IDENTIFY\\s-password"
|
|
215 "NickServ"
|
87202
|
216 "IDENTIFY" nil nil nil)
|
76856
|
217 (BitlBee
|
|
218 nil nil
|
75259
|
219 "&bitlbee"
|
87202
|
220 "identify" nil nil nil)
|
76856
|
221 (BRASnet
|
|
222 "NickServ!services@brasnet.org"
|
|
223 "/NickServ\\s-IDENTIFY\\s-senha"
|
|
224 "NickServ"
|
87202
|
225 "IDENTIFY" nil "" nil)
|
75259
|
226 (DALnet
|
68719
|
227 "NickServ!service@dal.net"
|
|
228 "/msg\\s-NickServ@services.dal.net\\s-IDENTIFY\\s-<password>"
|
|
229 "NickServ@services.dal.net"
|
87202
|
230 "IDENTIFY" nil nil nil)
|
68719
|
231 (freenode
|
|
232 "NickServ!NickServ@services."
|
87687
|
233 ;; freenode also accepts a password at login, see the `erc'
|
|
234 ;; :password argument.
|
96081
|
235 "This\\s-nickname\\s-is\\s-registered.\\s-Please\\s-choose"
|
68719
|
236 "NickServ"
|
87202
|
237 "IDENTIFY" nil nil
|
96081
|
238 ;; See also the 901 response code message.
|
|
239 "You\\s-are\\s-now\\s-identified\\s-for\\s-")
|
68719
|
240 (GalaxyNet
|
|
241 "NS!nickserv@galaxynet.org"
|
|
242 "Please\\s-change\\s-nicks\\s-or\\s-authenticate."
|
|
243 "NS@services.galaxynet.org"
|
87202
|
244 "AUTH" t nil nil)
|
|
245 (GRnet
|
|
246 "NickServ!service@irc.gr"
|
|
247 "This\\s-nickname\\s-is\\s-registered\\s-and\\s-protected."
|
|
248 "NickServ"
|
|
249 "IDENTIFY" nil nil
|
|
250 "Password\\s-accepted\\s--\\s-you\\s-are\\s-now\\s-recognized.")
|
76856
|
251 (iip
|
|
252 "Trent@anon.iip"
|
|
253 "type\\s-/squery\\s-Trent\\s-identify\\s-<password>"
|
|
254 "Trent@anon.iip"
|
87202
|
255 "IDENTIFY" nil "SQUERY" nil)
|
76856
|
256 (OFTC
|
|
257 "NickServ!services@services.oftc.net"
|
87687
|
258 ;; OFTC's NickServ doesn't ask you to identify anymore.
|
|
259 nil
|
76856
|
260 "NickServ"
|
87687
|
261 "IDENTIFY" nil nil
|
|
262 "You\\s-are\\s-successfully\\s-identified\\s-as\\s-")
|
87952
|
263 (Rizon
|
|
264 "NickServ!service@rizon.net"
|
|
265 "This\\s-nickname\\s-is\\s-registered\\s-and\\s-protected."
|
|
266 "NickServ"
|
|
267 "IDENTIFY" nil nil
|
|
268 "Password\\s-accepted\\s--\\s-you\\s-are\\s-now\\s-recognized.")
|
76856
|
269 (QuakeNet
|
|
270 nil nil
|
|
271 "Q@CServe.quakenet.org"
|
87202
|
272 "auth" t nil nil)
|
68719
|
273 (SlashNET
|
|
274 "NickServ!services@services.slashnet.org"
|
|
275 "/msg\\s-NickServ\\s-IDENTIFY\\s-password"
|
|
276 "NickServ@services.slashnet.org"
|
87202
|
277 "IDENTIFY" nil nil nil))
|
68719
|
278 "Alist of NickServer details, sorted by network.
|
|
279 Every element in the list has the form
|
87202
|
280 \(SYMBOL NICKSERV REGEXP NICK KEYWORD USE-CURRENT ANSWER SUCCESS-REGEXP)
|
68719
|
281
|
|
282 SYMBOL is a network identifier, a symbol, as used in `erc-networks-alist'.
|
|
283 NICKSERV is the description of the nickserv in the form nick!user@host.
|
|
284 REGEXP is a regular expression matching the message from nickserv.
|
|
285 NICK is nickserv's nickname. Use nick@server where necessary/possible.
|
|
286 KEYWORD is the keyword to use in the reply message to identify yourself.
|
|
287 USE-CURRENT indicates whether the current nickname must be used when
|
|
288 identifying.
|
|
289 ANSWER is the command to use for the answer. The default is 'privmsg.
|
87202
|
290 SUCCESS-REGEXP is a regular expression matching the message nickserv
|
|
291 sends when you've successfully identified.
|
|
292 The last two elements are optional."
|
68719
|
293 :group 'erc-services
|
|
294 :type '(repeat
|
|
295 (list :tag "Nickserv data"
|
|
296 (symbol :tag "Network name")
|
76856
|
297 (choice (string :tag "Nickserv's nick!user@host")
|
|
298 (const :tag "No message sent by Nickserv" nil))
|
|
299 (choice (regexp :tag "Identify request sent by Nickserv")
|
|
300 (const :tag "No message sent by Nickserv" nil))
|
68719
|
301 (string :tag "Identify to")
|
|
302 (string :tag "Identify keyword")
|
|
303 (boolean :tag "Use current nick in identify message?")
|
|
304 (choice :tag "Command to use (optional)"
|
|
305 (string :tag "Command")
|
|
306 (const :tag "No special command necessary" nil)))))
|
|
307
|
75259
|
308 (defsubst erc-nickserv-alist-sender (network &optional entry)
|
|
309 (nth 1 (or entry (assoc network erc-nickserv-alist))))
|
|
310
|
|
311 (defsubst erc-nickserv-alist-regexp (network &optional entry)
|
|
312 (nth 2 (or entry (assoc network erc-nickserv-alist))))
|
|
313
|
|
314 (defsubst erc-nickserv-alist-nickserv (network &optional entry)
|
|
315 (nth 3 (or entry (assoc network erc-nickserv-alist))))
|
|
316
|
|
317 (defsubst erc-nickserv-alist-ident-keyword (network &optional entry)
|
|
318 (nth 4 (or entry (assoc network erc-nickserv-alist))))
|
|
319
|
|
320 (defsubst erc-nickserv-alist-use-nick-p (network &optional entry)
|
|
321 (nth 5 (or entry (assoc network erc-nickserv-alist))))
|
|
322
|
|
323 (defsubst erc-nickserv-alist-ident-command (network &optional entry)
|
|
324 (nth 6 (or entry (assoc network erc-nickserv-alist))))
|
|
325
|
87202
|
326 (defsubst erc-nickserv-alist-identified-regexp (network &optional entry)
|
|
327 (nth 7 (or entry (assoc network erc-nickserv-alist))))
|
|
328
|
68719
|
329 ;; Functions:
|
|
330
|
87202
|
331 (defcustom erc-nickserv-identified-hook nil
|
|
332 "Run this hook when NickServ acknowledged successful identification.
|
|
333 Hooks are called with arguments (NETWORK NICK)."
|
|
334 :group 'erc-services
|
|
335 :type 'hook)
|
|
336
|
|
337 (defun erc-nickserv-identification-autodetect (proc parsed)
|
|
338 "Check for NickServ's successful identification notice.
|
|
339 Make sure it is the real NickServ for this network and that it has
|
|
340 specifically confirmed a successful identification attempt.
|
|
341 If this is the case, run `erc-nickserv-identified-hook'."
|
|
342 (let* ((network (erc-network))
|
|
343 (sender (erc-nickserv-alist-sender network))
|
|
344 (success-regex (erc-nickserv-alist-identified-regexp network))
|
|
345 (sspec (erc-response.sender parsed))
|
|
346 (nick (car (erc-response.command-args parsed)))
|
|
347 (msg (erc-response.contents parsed)))
|
|
348 ;; continue only if we're sure it's the real nickserv for this network
|
|
349 ;; and it's told us we've successfully identified
|
|
350 (when (and sender (equal sspec sender)
|
87687
|
351 success-regex
|
87202
|
352 (string-match success-regex msg))
|
|
353 (erc-log "NickServ IDENTIFY success notification detected")
|
|
354 (run-hook-with-args 'erc-nickserv-identified-hook network nick)
|
|
355 nil)))
|
|
356
|
68719
|
357 (defun erc-nickserv-identify-autodetect (proc parsed)
|
87687
|
358 "Identify to NickServ when an identify request is received.
|
|
359 Make sure it is the real NickServ for this network.
|
68719
|
360 If `erc-prompt-for-nickserv-password' is non-nil, prompt the user for the
|
|
361 password for this nickname, otherwise try to send it automatically."
|
|
362 (unless (and (null erc-nickserv-passwords)
|
|
363 (null erc-prompt-for-nickserv-password))
|
|
364 (let* ((network (erc-network))
|
75259
|
365 (sender (erc-nickserv-alist-sender network))
|
|
366 (identify-regex (erc-nickserv-alist-regexp network))
|
68719
|
367 (sspec (erc-response.sender parsed))
|
|
368 (nick (car (erc-response.command-args parsed)))
|
|
369 (msg (erc-response.contents parsed)))
|
|
370 ;; continue only if we're sure it's the real nickserv for this network
|
|
371 ;; and it's asked us to identify
|
75259
|
372 (when (and sender (equal sspec sender)
|
87687
|
373 identify-regex
|
68719
|
374 (string-match identify-regex msg))
|
|
375 (erc-log "NickServ IDENTIFY request detected")
|
|
376 (erc-nickserv-call-identify-function nick)
|
|
377 nil))))
|
|
378
|
|
379 (defun erc-nickserv-identify-on-connect (server nick)
|
|
380 "Identify to Nickserv after the connection to the server is established."
|
75092
|
381 (unless (or (and (null erc-nickserv-passwords)
|
|
382 (null erc-prompt-for-nickserv-password))
|
|
383 (and (eq erc-nickserv-identify-mode 'both)
|
75259
|
384 (erc-nickserv-alist-regexp (erc-network))))
|
68719
|
385 (erc-nickserv-call-identify-function nick)))
|
|
386
|
|
387 (defun erc-nickserv-identify-on-nick-change (nick old-nick)
|
|
388 "Identify to Nickserv whenever your nick changes."
|
75092
|
389 (unless (or (and (null erc-nickserv-passwords)
|
|
390 (null erc-prompt-for-nickserv-password))
|
|
391 (and (eq erc-nickserv-identify-mode 'both)
|
75259
|
392 (erc-nickserv-alist-regexp (erc-network))))
|
68719
|
393 (erc-nickserv-call-identify-function nick)))
|
|
394
|
|
395 (defun erc-nickserv-call-identify-function (nickname)
|
|
396 "Call `erc-nickserv-identify' interactively or run it with NICKNAME's
|
|
397 password.
|
|
398 The action is determined by the value of `erc-prompt-for-nickserv-password'."
|
|
399 (if erc-prompt-for-nickserv-password
|
|
400 (call-interactively 'erc-nickserv-identify)
|
|
401 (when erc-nickserv-passwords
|
|
402 (erc-nickserv-identify
|
|
403 (cdr (assoc nickname
|
|
404 (nth 1 (assoc (erc-network)
|
|
405 erc-nickserv-passwords))))))))
|
|
406
|
|
407 ;;;###autoload
|
|
408 (defun erc-nickserv-identify (password)
|
|
409 "Send an \"identify <PASSWORD>\" message to NickServ.
|
|
410 When called interactively, read the password using `read-passwd'."
|
|
411 (interactive
|
|
412 (list (read-passwd
|
|
413 (format "NickServ password for %s on %s (RET to cancel): "
|
|
414 (erc-current-nick)
|
|
415 (or (and (erc-network)
|
|
416 (symbol-name (erc-network)))
|
|
417 "Unknown network")))))
|
|
418 (when (and password (not (string= "" password)))
|
|
419 (let* ((erc-auto-discard-away nil)
|
|
420 (network (erc-network))
|
|
421 (nickserv-info (assoc network erc-nickserv-alist))
|
75259
|
422 (nickserv (or (erc-nickserv-alist-nickserv nil nickserv-info)
|
|
423 "NickServ"))
|
|
424 (identify-word (or (erc-nickserv-alist-ident-keyword
|
|
425 nil nickserv-info)
|
|
426 "IDENTIFY"))
|
|
427 (nick (if (erc-nickserv-alist-use-nick-p nil nickserv-info)
|
68719
|
428 (concat (erc-current-nick) " ")
|
|
429 ""))
|
75259
|
430 (msgtype (or (erc-nickserv-alist-ident-command nil nickserv-info)
|
|
431 "PRIVMSG")))
|
68719
|
432 (erc-message msgtype
|
|
433 (concat nickserv " " identify-word " " nick password)))))
|
|
434
|
|
435 (provide 'erc-services)
|
|
436
|
|
437 ;;; erc-services.el ends here
|
|
438 ;;
|
|
439 ;; Local Variables:
|
|
440 ;; indent-tabs-mode: t
|
|
441 ;; tab-width: 8
|
|
442 ;; End:
|
|
443
|
|
444 ;; arch-tag: d401c8aa-d938-4255-96a9-3efb64c47e58
|