From a62a26239780684d481533a57d12de520b737f9b Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Thu, 30 Jan 2025 19:07:00 -0800 Subject: [PATCH] Run erc-services-regain-mode callback on a timer * lisp/erc/erc-services.el (erc-services-regain-timeout-seconds): New variable. (erc-services-regain-mode): Mention CertFP in doc string. (erc--nickname-in-use-make-request): Ensure the 900 RPL_LOGGEDIN callback always runs after `erc-services-regain-timeout-seconds', even when SASL isn't being used. * test/lisp/erc/erc-scenarios-services-misc.el (erc-scenarios-services-misc--regain-command/oftc): New test. * test/lisp/erc/resources/services/regain/taken-regain-oftc.eld: New file. --- lisp/erc/erc-services.el | 25 ++++++++--- test/lisp/erc/erc-scenarios-services-misc.el | 25 +++++++++++ .../services/regain/taken-regain-oftc.eld | 42 +++++++++++++++++++ 3 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 test/lisp/erc/resources/services/regain/taken-regain-oftc.eld diff --git a/lisp/erc/erc-services.el b/lisp/erc/erc-services.el index d16aa8c54d8..429424117eb 100644 --- a/lisp/erc/erc-services.el +++ b/lisp/erc/erc-services.el @@ -548,6 +548,9 @@ for details and use cases." (function-item erc-services-issue-ghost-and-retry-nick) function))) +(defvar erc-services-regain-timeout-seconds 5 + "Seconds after which to run callbacks if necessary.") + (defun erc-services-retry-nick-on-connect (want) "Try at most once to grab nickname WANT after reconnecting. Expect to be used when automatically reconnecting to servers @@ -608,8 +611,8 @@ consider its main option, `erc-services-regain-alist': In practical terms, this means that this module, which is still somewhat experimental, is likely only useful in conjunction with -SASL authentication rather than the traditional approach provided -by the `services' module it shares a library with (see Info +SASL authentication or CertFP rather than the traditional approach +provided by the `services' module it shares a library with (see Info node `(erc) SASL' for more)." nil nil localp) @@ -632,11 +635,21 @@ one." (funcall found want)))) (on-900 (lambda (_ parsed) + (cancel-timer timer) (remove-hook 'erc-server-900-functions on-900 t) - (unless erc-server-connected - (when (equal (car (erc-response.command-args parsed)) temp) - (add-hook 'erc-after-connect after-connect nil t))) - nil))) + (unless (equal want (erc-current-nick)) + (if erc-server-connected + (funcall after-connect nil temp) + (when (or (eq parsed 'forcep) + (equal (car (erc-response.command-args parsed)) temp)) + (add-hook 'erc-after-connect after-connect nil t)))) + nil)) + (timer (run-at-time erc-services-regain-timeout-seconds + nil (lambda (buffer) + (when (buffer-live-p buffer) + (with-current-buffer buffer + (funcall on-900 nil 'forcep)))) + (current-buffer)))) (add-hook 'erc-server-900-functions on-900 nil t)) (cl-call-next-method)) diff --git a/test/lisp/erc/erc-scenarios-services-misc.el b/test/lisp/erc/erc-scenarios-services-misc.el index 823c97dd96b..13d66a54d3a 100644 --- a/test/lisp/erc/erc-scenarios-services-misc.el +++ b/test/lisp/erc/erc-scenarios-services-misc.el @@ -223,6 +223,31 @@ ;; Works with "given" `:id'. (should (and (erc-network) (not (eq (erc-network) 'ExampleNet))))))) +(ert-deftest erc-scenarios-services-misc--regain-command/oftc () + :tags '(:expensive-test) + (erc-scenarios-common-with-cleanup + ((erc-server-flood-penalty 0.1) + (erc-scenarios-common-dialog "services/regain") + (dumb-server (erc-d-run "localhost" t 'taken-regain-oftc)) + (port (process-contact dumb-server :service)) + (erc-modules `(services-regain ,@erc-modules)) + (erc-services-regain-timeout-seconds 1) + (use-id-p (cl-evenp (truncate (float-time)))) + (erc-services-regain-alist (list (cons (if use-id-p 'oftc 'OFTC) + #'erc-services-issue-regain))) + (expect (erc-d-t-make-expecter))) + + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "dummy" + :user "tester" + :full-name "tester" + :id (and use-id-p 'oftc)) + (funcall expect 10 "Nickname dummy is already in use, trying dummy`") + (funcall expect 10 "-NickServ- REGAIN succeed on nickname") + (funcall expect 10 "*** Your new nickname is dummy") + (funcall expect 10 "*** dummy has changed mode for dummy to +R")))) + (ert-deftest erc-scenarios-services-misc--ghost-and-retry-nick () :tags '(:expensive-test) (erc-scenarios-common-with-cleanup diff --git a/test/lisp/erc/resources/services/regain/taken-regain-oftc.eld b/test/lisp/erc/resources/services/regain/taken-regain-oftc.eld new file mode 100644 index 00000000000..c6fa09dc45c --- /dev/null +++ b/test/lisp/erc/resources/services/regain/taken-regain-oftc.eld @@ -0,0 +1,42 @@ +;; -*- mode: lisp-data; -*- +((nick 10 "NICK dummy")) +((user 10 "USER tester 0 * :tester") + (0.09 ":reflection.oftc.net NOTICE AUTH :*** Looking up your hostname...") + (0.03 ":reflection.oftc.net NOTICE AUTH :*** Checking Ident") + (0.02 ":reflection.oftc.net NOTICE AUTH :*** Found your hostname") + (0.01 ":reflection.oftc.net NOTICE AUTH :*** No Ident response") + (0.01 ":reflection.oftc.net 433 * dummy :Nickname is already in use.")) +((nick 10 "NICK dummy`") + (0.09 ":reflection.oftc.net NOTICE dummy` :*** Connected securely via TLSv1.3 TLS_AES_256_GCM_SHA384-256") + (0.03 ":reflection.oftc.net NOTICE dummy` :*** Your client certificate fingerprint is 4F6DDB61A5CFFA42719D39E3819B45DC58E4E307") + (0.01 ":reflection.oftc.net 001 dummy` :Welcome to the OFTC Internet Relay Chat Network dummy`") + (0.01 ":reflection.oftc.net 002 dummy` :Your host is reflection.oftc.net[64.86.243.183/6697], running version hybrid-7.2.2+oftc1.7.3") + (0.01 ":reflection.oftc.net 003 dummy` :This server was created Nov 1 2023 at 10:10:46") + (0.00 ":reflection.oftc.net 004 dummy` reflection.oftc.net hybrid-7.2.2+oftc1.7.3 CDGPRSabcdfgijklnorsuwxyz bciklmnopstvzeIMRS bkloveI") + (0.01 ":reflection.oftc.net 005 dummy` CALLERID CASEMAPPING=rfc1459 DEAF=D KICKLEN=160 MODES=4 NICKLEN=30 PREFIX=(ov)@+ STATUSMSG=@+ TOPICLEN=391 NETWORK=OFTC MAXLIST=beI:100 MAXTARGETS=1 CHANTYPES=# :are supported by this server") + (0.03 ":reflection.oftc.net 005 dummy` CHANLIMIT=#:250 CHANNELLEN=50 CHANMODES=eIqb,k,l,cimnpstzMRS AWAYLEN=160 KNOCK ELIST=CMNTU SAFELIST EXCEPTS=e INVEX=I :are supported by this server") + (0.01 ":reflection.oftc.net 042 dummy` 8L3AAEM45 :your unique ID") + (0.00 ":reflection.oftc.net 251 dummy` :There are 31 users and 16297 invisible on 19 servers") + (0.00 ":reflection.oftc.net 252 dummy` 20 :IRC Operators online") + (0.00 ":reflection.oftc.net 253 dummy` 25 :unknown connection(s)") + (0.00 ":reflection.oftc.net 254 dummy` 4118 :channels formed") + (0.00 ":reflection.oftc.net 255 dummy` :I have 1245 clients and 1 servers") + (0.00 ":reflection.oftc.net 265 dummy` :Current local users: 1245 Max: 1782") + (0.00 ":reflection.oftc.net 266 dummy` :Current global users: 16328 Max: 19479") + (0.00 ":reflection.oftc.net 250 dummy` :Highest connection count: 1783 (1782 clients) (203288 connections received)") + (0.03 ":reflection.oftc.net 375 dummy` :- reflection.oftc.net Message of the Day - ") + (0.00 ":reflection.oftc.net 372 dummy` :- O") + (0.00 ":reflection.oftc.net 372 dummy` :- Thanks and enjoy your stay! The OFTC team.") + (0.00 ":reflection.oftc.net 376 dummy` :End of /MOTD command.") + (0.03 ":dummy`!~tester@static-198-54-134-141.cust.tzulo.com MODE dummy` :+i")) +((mode 10 "MODE dummy` +i") + (0.00 ":CTCPServ!services@services.oftc.net PRIVMSG dummy` :\1VERSION\1")) +((~notice 10 "NOTICE CTCPServ :\1VERSION \2ERC\2")) +((privmsg 10 "PRIVMSG NickServ :REGAIN dummy") + (0.01 ":NickServ!services@services.oftc.net NOTICE dummy` :REGAIN succeed on nickname \2dummy\2. You have been changed to your nickname.") + (0.05 ":dummy`!~tester@static-198-54-134-141.cust.tzulo.com NICK :dummy") + (0.01 ":dummy MODE dummy :+R") + (0.04 ":dummy MODE dummy :-R") + (0.01 ":dummy MODE dummy :+R")) +((quit 10 "QUIT :\2ERC\2 5") + (0.08 "ERROR :Closing Link: static-198-54-134-141.cust.tzulo.com ()"))