;;; erc-services.el --- Identify to NickServ
-;; Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2011 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; are made to test if NickServ is the real NickServ for a given network or
;; server.
-;; As a default, ERC has the data for the official nickname services on the
-;; networks Austnet, BrasNET, Dalnet, freenode, GalaxyNet, and Slashnet.
-;; You can add more by using M-x customize-variable RET erc-nickserv-alist.
+;; As a default, ERC has the data for the official nickname services on
+;; the networks Austnet, BrasNET, Dalnet, freenode, GalaxyNet, GRnet,
+;; and Slashnet. You can add more by using M-x customize-variable RET
+;; erc-nickserv-alist.
;; Usage:
;;
communication with those Services."
:group 'erc)
+(defcustom erc-nickserv-identify-mode 'both
+ "The mode which is used when identifying to Nickserv.
+
+Possible settings are:.
+
+'autodetect - Identify when the real Nickserv sends an identify request.
+'nick-change - Identify when you log in or change your nickname.
+'both - Do the former if the network supports it, otherwise do the
+ latter.
+nil - Disables automatic Nickserv identification.
+
+You can also use M-x erc-nickserv-identify-mode to change modes."
+ :group 'erc-services
+ :type '(choice (const autodetect)
+ (const nick-change)
+ (const both)
+ (const nil))
+ :set (lambda (sym val)
+ (set sym val)
+ ;; avoid recursive load at startup
+ (when (featurep 'erc-services)
+ (erc-nickserv-identify-mode val))))
+
;;;###autoload (autoload 'erc-services-mode "erc-services" nil t)
(define-erc-module services nickserv
"This mode automates communication with services."
(remove-hook 'erc-after-connect
'erc-nickserv-identify-on-connect)
(remove-hook 'erc-nick-changed-functions
- 'erc-nickserv-identify-on-nick-change)))
+ 'erc-nickserv-identify-on-nick-change)
+ (remove-hook 'erc-server-NOTICE-functions
+ 'erc-nickserv-identification-autodetect)))
;;;###autoload
(defun erc-nickserv-identify-mode (mode)
(interactive
(list (intern (completing-read
"Choose Nickserv identify mode (RET to disable): "
- '(("autodetect") ("nick-change")) nil t))))
+ '(("autodetect") ("nick-change") ("both")) nil t))))
+ (add-hook 'erc-server-NOTICE-functions
+ 'erc-nickserv-identification-autodetect)
+ (unless erc-networks-mode
+ ;; Force-enable networks module, because we need it to set
+ ;; erc-network for us.
+ (erc-networks-enable))
(cond ((eq mode 'autodetect)
(setq erc-nickserv-identify-mode 'autodetect)
(add-hook 'erc-server-NOTICE-functions
'erc-nickserv-identify-on-nick-change)
(remove-hook 'erc-server-NOTICE-functions
'erc-nickserv-identify-autodetect))
+ ((eq mode 'both)
+ (setq erc-nickserv-identify-mode 'both)
+ (add-hook 'erc-server-NOTICE-functions
+ 'erc-nickserv-identify-autodetect)
+ (add-hook 'erc-after-connect
+ 'erc-nickserv-identify-on-connect)
+ (add-hook 'erc-nick-changed-functions
+ 'erc-nickserv-identify-on-nick-change))
(t
(setq erc-nickserv-identify-mode nil)
(remove-hook 'erc-server-NOTICE-functions
(remove-hook 'erc-after-connect
'erc-nickserv-identify-on-connect)
(remove-hook 'erc-nick-changed-functions
- 'erc-nickserv-identify-on-nick-change))))
-
-(defcustom erc-nickserv-identify-mode 'autodetect
- "The mode which is used when identifying to Nickserv.
-
-Possible settings are:.
-
-'autodetect - Identify when the real Nickserv sends an identify request.
-'nick-change - Identify when you change your nickname.
-nil - Disables automatic Nickserv identification.
-
-You can also use M-x erc-nickserv-identify-mode to change modes."
- :group 'erc-services
- :type '(choice (const autodetect)
- (const nick-change)
- (const nil))
- :set (lambda (sym val)
- (set-default sym val)
- (erc-nickserv-identify-mode val)))
+ 'erc-nickserv-identify-on-nick-change)
+ (remove-hook 'erc-server-NOTICE-functions
+ 'erc-nickserv-identification-autodetect))))
(defcustom erc-prompt-for-nickserv-password t
"Ask for the password when identifying to NickServ."
:type '(repeat
(list :tag "Network"
(choice :tag "Network name"
- (const freenode)
+ (const Ars)
+ (const Austnet)
+ (const Azzurra)
+ (const BitlBee)
+ (const BRASnet)
(const DALnet)
+ (const freenode)
(const GalaxyNet)
- (const SlashNET)
- (const BRASnet)
+ (const GRnet)
(const iip)
- (const Austnet)
+ (const OFTC)
+ (const QuakeNet)
+ (const Rizon)
+ (const SlashNET)
(symbol :tag "Network name"))
(repeat :tag "Nickname and password"
(cons :tag "Identity"
;; Variables:
(defcustom erc-nickserv-alist
- '((DALnet
+ '((Ars
+ nil nil
+ "Census"
+ "IDENTIFY" nil nil nil)
+ (Austnet
+ "NickOP!service@austnet.org"
+ "/msg\\s-NickOP@austnet.org\\s-identify\\s-<password>"
+ "nickop@austnet.org"
+ "identify" nil nil nil)
+ (Azzurra
+ "NickServ!service@azzurra.org"
+ "\ 2/ns\\s-IDENTIFY\\s-password\ 2"
+ "NickServ"
+ "IDENTIFY" nil nil nil)
+ (BitlBee
+ nil nil
+ "&bitlbee"
+ "identify" nil nil nil)
+ (BRASnet
+ "NickServ!services@brasnet.org"
+ "\ 2/NickServ\\s-IDENTIFY\\s-\1fsenha\1f\ 2"
+ "NickServ"
+ "IDENTIFY" nil "" nil)
+ (DALnet
"NickServ!service@dal.net"
"/msg\\s-NickServ@services.dal.net\\s-IDENTIFY\\s-<password>"
"NickServ@services.dal.net"
- "IDENTIFY"
- nil)
+ "IDENTIFY" nil nil nil)
(freenode
"NickServ!NickServ@services."
- "/msg\\s-NickServ\\s-\ 2IDENTIFY\ 2\\s-<password>"
+ ;; freenode also accepts a password at login, see the `erc'
+ ;; :password argument.
+ "This\\s-nickname\\s-is\\s-registered.\\s-Please\\s-choose"
"NickServ"
- "IDENTIFY"
- nil)
+ "IDENTIFY" nil nil
+ ;; See also the 901 response code message.
+ "You\\s-are\\s-now\\s-identified\\s-for\\s-")
(GalaxyNet
"NS!nickserv@galaxynet.org"
"Please\\s-change\\s-nicks\\s-or\\s-authenticate."
"NS@services.galaxynet.org"
- "AUTH"
- t)
- (SlashNET
- "NickServ!services@services.slashnet.org"
- "/msg\\s-NickServ\\s-IDENTIFY\\s-\1fpassword"
- "NickServ@services.slashnet.org"
- "IDENTIFY"
- nil)
+ "AUTH" t nil nil)
+ (GRnet
+ "NickServ!service@irc.gr"
+ "This\\s-nickname\\s-is\\s-registered\\s-and\\s-protected."
+ "NickServ"
+ "IDENTIFY" nil nil
+ "Password\\s-accepted\\s--\\s-you\\s-are\\s-now\\s-recognized.")
(iip
"Trent@anon.iip"
"type\\s-/squery\\s-Trent\\s-identify\\s-<password>"
"Trent@anon.iip"
- "IDENTIFY"
+ "IDENTIFY" nil "SQUERY" nil)
+ (OFTC
+ "NickServ!services@services.oftc.net"
+ ;; OFTC's NickServ doesn't ask you to identify anymore.
nil
- "SQUERY")
- (BRASnet
- "NickServ!services@brasnet.org"
- "\ 2/NickServ\\s-IDENTIFY\\s-\1fsenha\1f\ 2"
"NickServ"
- "IDENTIFY"
- nil
- "")
- (Austnet
- "NickOP!service@austnet.org"
- "/msg\\s-NickOP@austnet.org\\s-identify\\s-<password>"
- "nickop@austnet.org"
- "identify"
- nil)
- (Azzurra
- "NickServ!service@azzurra.org"
- "\ 2/ns\\s-IDENTIFY\\s-password\ 2"
- "NickServ"
- "IDENTIFY"
- nil)
- (OFTC
- "NickServ!services@services.oftc.net"
- "/msg\\s-NickServ\\s-IDENTIFY\\s-\^_password"
- "NickServ"
- "IDENTIFY"
- nil))
+ "IDENTIFY" nil nil
+ "You\\s-are\\s-successfully\\s-identified\\s-as\\s-\ 2")
+ (Rizon
+ "NickServ!service@rizon.net"
+ "This\\s-nickname\\s-is\\s-registered\\s-and\\s-protected."
+ "NickServ"
+ "IDENTIFY" nil nil
+ "Password\\s-accepted\\s--\\s-you\\s-are\\s-now\\s-recognized.")
+ (QuakeNet
+ nil nil
+ "Q@CServe.quakenet.org"
+ "auth" t nil nil)
+ (SlashNET
+ "NickServ!services@services.slashnet.org"
+ "/msg\\s-NickServ\\s-IDENTIFY\\s-\1fpassword"
+ "NickServ@services.slashnet.org"
+ "IDENTIFY" nil nil nil))
"Alist of NickServer details, sorted by network.
Every element in the list has the form
- \(SYMBOL NICKSERV REGEXP NICK KEYWORD USE-CURRENT ANSWER)
+ \(SYMBOL NICKSERV REGEXP NICK KEYWORD USE-CURRENT ANSWER SUCCESS-REGEXP)
SYMBOL is a network identifier, a symbol, as used in `erc-networks-alist'.
NICKSERV is the description of the nickserv in the form nick!user@host.
USE-CURRENT indicates whether the current nickname must be used when
identifying.
ANSWER is the command to use for the answer. The default is 'privmsg.
- This last element is optional."
+SUCCESS-REGEXP is a regular expression matching the message nickserv
+ sends when you've successfully identified.
+The last two elements are optional."
:group 'erc-services
:type '(repeat
(list :tag "Nickserv data"
(symbol :tag "Network name")
- (string :tag "Nickserv's nick!user@host")
- (regexp :tag "Identify request sent by Nickserv")
+ (choice (string :tag "Nickserv's nick!user@host")
+ (const :tag "No message sent by Nickserv" nil))
+ (choice (regexp :tag "Identify request sent by Nickserv")
+ (const :tag "No message sent by Nickserv" nil))
(string :tag "Identify to")
(string :tag "Identify keyword")
(boolean :tag "Use current nick in identify message?")
(choice :tag "Command to use (optional)"
(string :tag "Command")
- (const :tag "No special command necessary" nil)))))
+ (const :tag "No special command necessary" nil))
+ (choice :tag "Detect Success"
+ (regexp :tag "Pattern to match")
+ (const :tag "Do not try to detect success" nil)))))
+
+
+(defsubst erc-nickserv-alist-sender (network &optional entry)
+ (nth 1 (or entry (assoc network erc-nickserv-alist))))
+
+(defsubst erc-nickserv-alist-regexp (network &optional entry)
+ (nth 2 (or entry (assoc network erc-nickserv-alist))))
+
+(defsubst erc-nickserv-alist-nickserv (network &optional entry)
+ (nth 3 (or entry (assoc network erc-nickserv-alist))))
+
+(defsubst erc-nickserv-alist-ident-keyword (network &optional entry)
+ (nth 4 (or entry (assoc network erc-nickserv-alist))))
+
+(defsubst erc-nickserv-alist-use-nick-p (network &optional entry)
+ (nth 5 (or entry (assoc network erc-nickserv-alist))))
+
+(defsubst erc-nickserv-alist-ident-command (network &optional entry)
+ (nth 6 (or entry (assoc network erc-nickserv-alist))))
+
+(defsubst erc-nickserv-alist-identified-regexp (network &optional entry)
+ (nth 7 (or entry (assoc network erc-nickserv-alist))))
;; Functions:
-(defun erc-nickserv-identify-autodetect (proc parsed)
- "Check for a NickServ identify request everytime a notice is received.
+(defcustom erc-nickserv-identified-hook nil
+ "Run this hook when NickServ acknowledged successful identification.
+Hooks are called with arguments (NETWORK NICK)."
+ :group 'erc-services
+ :type 'hook)
+
+(defun erc-nickserv-identification-autodetect (proc parsed)
+ "Check for NickServ's successful identification notice.
Make sure it is the real NickServ for this network and that it has
-specifically asked the user to IDENTIFY.
+specifically confirmed a successful identification attempt.
+If this is the case, run `erc-nickserv-identified-hook'."
+ (let* ((network (erc-network))
+ (sender (erc-nickserv-alist-sender network))
+ (success-regex (erc-nickserv-alist-identified-regexp network))
+ (sspec (erc-response.sender parsed))
+ (nick (car (erc-response.command-args parsed)))
+ (msg (erc-response.contents parsed)))
+ ;; continue only if we're sure it's the real nickserv for this network
+ ;; and it's told us we've successfully identified
+ (when (and sender (equal sspec sender)
+ success-regex
+ (string-match success-regex msg))
+ (erc-log "NickServ IDENTIFY success notification detected")
+ (run-hook-with-args 'erc-nickserv-identified-hook network nick)
+ nil)))
+
+(defun erc-nickserv-identify-autodetect (proc parsed)
+ "Identify to NickServ when an identify request is received.
+Make sure it is the real NickServ for this network.
If `erc-prompt-for-nickserv-password' is non-nil, prompt the user for the
password for this nickname, otherwise try to send it automatically."
(unless (and (null erc-nickserv-passwords)
(null erc-prompt-for-nickserv-password))
(let* ((network (erc-network))
- (nickserv (nth 1 (assoc network erc-nickserv-alist)))
- (identify-regex (nth 2 (assoc network erc-nickserv-alist)))
+ (sender (erc-nickserv-alist-sender network))
+ (identify-regex (erc-nickserv-alist-regexp network))
(sspec (erc-response.sender parsed))
(nick (car (erc-response.command-args parsed)))
(msg (erc-response.contents parsed)))
;; continue only if we're sure it's the real nickserv for this network
;; and it's asked us to identify
- (when (and nickserv (equal sspec nickserv)
+ (when (and sender (equal sspec sender)
+ identify-regex
(string-match identify-regex msg))
(erc-log "NickServ IDENTIFY request detected")
(erc-nickserv-call-identify-function nick)
(defun erc-nickserv-identify-on-connect (server nick)
"Identify to Nickserv after the connection to the server is established."
- (unless (and (null erc-nickserv-passwords)
- (null erc-prompt-for-nickserv-password))
+ (unless (or (and (null erc-nickserv-passwords)
+ (null erc-prompt-for-nickserv-password))
+ (and (eq erc-nickserv-identify-mode 'both)
+ (erc-nickserv-alist-regexp (erc-network))))
(erc-nickserv-call-identify-function nick)))
(defun erc-nickserv-identify-on-nick-change (nick old-nick)
"Identify to Nickserv whenever your nick changes."
- (unless (and (null erc-nickserv-passwords)
- (null erc-prompt-for-nickserv-password))
+ (unless (or (and (null erc-nickserv-passwords)
+ (null erc-prompt-for-nickserv-password))
+ (and (eq erc-nickserv-identify-mode 'both)
+ (erc-nickserv-alist-regexp (erc-network))))
(erc-nickserv-call-identify-function nick)))
(defun erc-nickserv-call-identify-function (nickname)
(let* ((erc-auto-discard-away nil)
(network (erc-network))
(nickserv-info (assoc network erc-nickserv-alist))
- (nickserv (or (nth 3 nickserv-info) "NickServ"))
- (identify-word (or (nth 4 nickserv-info) "IDENTIFY"))
- (nick (if (nth 5 nickserv-info)
+ (nickserv (or (erc-nickserv-alist-nickserv nil nickserv-info)
+ "NickServ"))
+ (identify-word (or (erc-nickserv-alist-ident-keyword
+ nil nickserv-info)
+ "IDENTIFY"))
+ (nick (if (erc-nickserv-alist-use-nick-p nil nickserv-info)
(concat (erc-current-nick) " ")
""))
- (msgtype (or (nth 6 nickserv-info) "PRIVMSG")))
+ (msgtype (or (erc-nickserv-alist-ident-command nil nickserv-info)
+ "PRIVMSG")))
(erc-message msgtype
(concat nickserv " " identify-word " " nick password)))))
;; tab-width: 8
;; End:
-;; arch-tag: d401c8aa-d938-4255-96a9-3efb64c47e58