erc / erc-nickserv.el

;;; erc-nickserv.el --- Identify to NickServ

;; Copyright (C) 2002, 2003, 2004  Free Software Foundation, Inc.

;; This file 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.

;; This file 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., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.

;;; Commentary:

;; Listens for notices from NickServ, and if it detects an identify
;; request, it will either prompt for the password in the minibuffer
;; or identify automatically depending upon how the variables
;; `erc-prompt-for-nickserv-password' and `erc-nickserv-passwords' are
;; set.

;; At this time ERC only recognizes the official nickname services on the
;; networks Dalnet, GalaxyNet, Freenode, Slashnet and BrasNET.

;; Usage:
;; Put into your .emacs:
;; (require 'erc-nickserv)
;; (erc-nickserv-mode 1)

;;; Code:

(require 'erc)
(require 'erc-nets)

(defconst erc-nickserv-version "$Revision$"
  "ERC NickServ revision.")

;; Customization:

(defgroup erc-services nil
  "Configuration for IRC services.

On some networks, there exists a special type of automated irc bot,
called Services.  Those usually allow you to register your nickname,
post/read memos to other registered users who are currently offline,
and do various other things.

This group allows you to set variables to somewhat automate
communication with those Services."
  :group 'erc)

;;;###autoload (autoload 'erc-services-mode "erc-nickserv" nil t)
(define-erc-module services nickserv
  "This mode automates communication with services."
  ((add-hook 'erc-server-NOTICE-hook
  ((remove-hook 'erc-server-NOTICE-hook

(defcustom erc-prompt-for-nickserv-password t
  "Ask for the NickServ password when a NickServ identify request has been
detected.  At this time ERC recognizes NickServ on the networks
Open Projects, DalNet, Slashnet and GalaxyNet.

If both this and `erc-nickserv-passwords' are nil, ERC will not check for
NickServ identify requests, and you can identify yourself manually."
  :group 'erc-services
  :type 'boolean)

(defcustom erc-nickserv-passwords nil
  "Passwords used when identifying oneself to NickServ (not necessary).

Example of use:
  (setq erc-nickserv-passwords
        '((freenode ((\"nick-one\" . \"password\")
                     (\"nick-two\" . \"password\")))
          (dalnet ((\"nick\" . \"password\")))))

If both this and `erc-prompt-for-nickserv-password' are nil, ERC will not
check for NickServ identify requests, and you can identify yourself manually."
  :group 'erc-services
  :type '(repeat
	  (list :tag "Network"
		(choice (const freenode)
			(const dalnet)
			(const galaxynet)
			(const slashdot)
                        (const brasnet)
			(const iip))
		(repeat (cons :tag "Identity"
			      (string :tag "Nick")
			      (string :tag "Password"))))))

;; Variables:

(defvar erc-nickserv-alist
     (Austnet "NickOP!"
   "Alist of NickServer details, sorted by network.
Every element in the list has the form

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.
REGEXP is a regular expression matching the message from nickserv.
NICK is nickserv's nickname.  Use nick@server where necessary/possible.
KEYWORD is the keyword to use in the reply message to identify yourself.
USE-CURRENT indicates whether the current nickname must be used when
ANSWER is the command to use for the answer.  The default is 'privmsg.
  This last element is optional.")

;; Functions:

(defun erc-nickserv-identify-autodetect (proc parsed)
  "Check for a NickServ identify request everytime a notice is sent to this
user.  Make sure it is the real NickServ for this network and that it has
specifically asked the user to IDENTIFY.
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)))
           (sspec (aref parsed 1))
           (nick (aref parsed 2))
           (msg (aref parsed 3)))
      ;; 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)
                 (string-match identify-regex msg))
        (erc-log (format "NickServ IDENTIFY request detected"))
        (if erc-prompt-for-nickserv-password
            (call-interactively 'erc-nickserv-identify)
          (when erc-nickserv-passwords
             (cdr (assoc nick
                         (nth 1 (assoc network

(defun erc-nickserv-identify (&optional password)
  "Send a \"identify <PASSWORD>\" to NickServ.
When called interactively, read the password using `read-passwd'."
   (list (read-passwd
          (format "NickServ password for %s on %s: "
                  (or (and (erc-network)
                           (symbol-name (erc-network)))
                      "Unknown network")))))
  (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)
                   (concat (erc-current-nick) " ")
	 (msgtype (or (nth 6 nickserv-info) "PRIVMSG")))
    (erc-message msgtype
		 (concat nickserv " " identify-word " " nick password))))

(provide 'erc-nickserv)

;;; erc-nickserv.el ends here