X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/10dc9f9eba4636988cc3fee62abc8c93ca402fa0..4ee57b2a2d197452b39217907075951008cf5589:/lisp/erc/erc-services.el?ds=sidebyside diff --git a/lisp/erc/erc-services.el b/lisp/erc/erc-services.el index b93317e612..5062816725 100644 --- a/lisp/erc/erc-services.el +++ b/lisp/erc/erc-services.el @@ -1,13 +1,13 @@ ;;; erc-services.el --- Identify to NickServ -;; Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. +;; Copyright (C) 2002, 2003, 2004, 2006, 2007, 2008 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 @@ -15,9 +15,7 @@ ;; 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 . ;;; Commentary: @@ -29,9 +27,10 @@ ;; 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: ;; @@ -77,6 +76,29 @@ This group allows you to set variables to somewhat automate 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." @@ -86,7 +108,9 @@ communication with those 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) @@ -95,6 +119,12 @@ communication with those Services." (list (intern (completing-read "Choose Nickserv identify mode (RET to disable): " '(("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 @@ -126,28 +156,9 @@ communication with those Services." (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 '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 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) - (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." @@ -166,15 +177,20 @@ Example of use: :type '(repeat (list :tag "Network" (choice :tag "Network name" - (const freenode) - (const OFTC) + (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 Azzurra) + (const OFTC) + (const QuakeNet) + (const Rizon) + (const SlashNET) (symbol :tag "Network name")) (repeat :tag "Nickname and password" (cons :tag "Identity" @@ -184,65 +200,83 @@ Example of use: ;; 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-" + "nickop@austnet.org" + "identify" nil nil nil) + (Azzurra + "NickServ!service@azzurra.org" + "/ns\\s-IDENTIFY\\s-password" + "NickServ" + "IDENTIFY" nil nil nil) + (BitlBee + nil nil + "&bitlbee" + "identify" nil nil nil) + (BRASnet + "NickServ!services@brasnet.org" + "/NickServ\\s-IDENTIFY\\s-senha" + "NickServ" + "IDENTIFY" nil "" nil) + (DALnet "NickServ!service@dal.net" "/msg\\s-NickServ@services.dal.net\\s-IDENTIFY\\s-" "NickServ@services.dal.net" - "IDENTIFY" - nil) + "IDENTIFY" nil nil nil) (freenode "NickServ!NickServ@services." + ;; freenode also accepts a password at login, see the `erc' + ;; :password argument. "/msg\\s-NickServ\\s-IDENTIFY\\s-" "NickServ" - "IDENTIFY" - nil) + "IDENTIFY" nil nil + "Password\\s-accepted\\s--\\s-you\\s-are\\s-now\\s-recognized") (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-password" - "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-" "Trent@anon.iip" - "IDENTIFY" - nil - "SQUERY") - (BRASnet - "NickServ!services@brasnet.org" - "/NickServ\\s-IDENTIFY\\s-senha" - "NickServ" - "IDENTIFY" - nil - "") - (Austnet - "NickOP!service@austnet.org" - "/msg\\s-NickOP@austnet.org\\s-identify\\s-" - "nickop@austnet.org" - "identify" - nil) - (Azzurra - "NickServ!service@azzurra.org" - "/ns\\s-IDENTIFY\\s-password" - "NickServ" - "IDENTIFY" - nil) + "IDENTIFY" nil "SQUERY" nil) (OFTC "NickServ!services@services.oftc.net" - "/msg\\s-NickServ\\s-IDENTIFY\\s-\^_password" + ;; OFTC's NickServ doesn't ask you to identify anymore. + nil + "NickServ" + "IDENTIFY" nil nil + "You\\s-are\\s-successfully\\s-identified\\s-as\\s-") + (Rizon + "NickServ!service@rizon.net" + "This\\s-nickname\\s-is\\s-registered\\s-and\\s-protected." "NickServ" - "IDENTIFY" - nil)) + "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-password" + "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. @@ -252,13 +286,17 @@ KEYWORD is the keyword to use in the reply message to identify yourself. 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?") @@ -266,25 +304,72 @@ ANSWER is the command to use for the answer. The default is 'privmsg. (string :tag "Command") (const :tag "No special command necessary" 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) @@ -295,7 +380,7 @@ password for this nickname, otherwise try to send it automatically." (unless (or (and (null erc-nickserv-passwords) (null erc-prompt-for-nickserv-password)) (and (eq erc-nickserv-identify-mode 'both) - (nth 2 (assoc (erc-network) erc-nickserv-alist)))) + (erc-nickserv-alist-regexp (erc-network)))) (erc-nickserv-call-identify-function nick))) (defun erc-nickserv-identify-on-nick-change (nick old-nick) @@ -303,7 +388,7 @@ password for this nickname, otherwise try to send it automatically." (unless (or (and (null erc-nickserv-passwords) (null erc-prompt-for-nickserv-password)) (and (eq erc-nickserv-identify-mode 'both) - (nth 2 (assoc (erc-network) erc-nickserv-alist)))) + (erc-nickserv-alist-regexp (erc-network)))) (erc-nickserv-call-identify-function nick))) (defun erc-nickserv-call-identify-function (nickname) @@ -333,12 +418,16 @@ When called interactively, read the password using `read-passwd'." (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)))))