(declare-function erc--init-channel-modes "erc" (channel raw-args))
(declare-function erc--open-target "erc" (target))
(declare-function erc--parse-nuh "erc" (string))
+(declare-function erc--query-list "erc" ())
(declare-function erc--target-from-string "erc" (string))
(declare-function erc--update-modes "erc" (raw-args))
(declare-function erc-active-buffer "erc" nil)
?h host ?t tgt ?m mode)))
(erc-banlist-update proc parsed))))
+(defun erc--wrangle-query-buffers-on-nick-change (old new)
+ "Create or reuse a query buffer for NEW nick after considering OLD nick.
+Return a list of buffers in which to announce the change."
+ ;; Note that `new-buffer' may be older than `old-buffer', e.g., if
+ ;; the query target is switching to a previously used nick.
+ (let ((new-buffer (erc-get-buffer new erc-server-process))
+ (old-buffer (erc-get-buffer old erc-server-process))
+ (selfp (erc-current-nick-p old)) ; e.g., for note taking, etc.
+ buffers)
+ (when new-buffer
+ (push new-buffer buffers))
+ (when old-buffer
+ (push old-buffer buffers)
+ ;; Ensure the new nick is absent from the old query.
+ (unless selfp
+ (erc-remove-channel-member old-buffer old))
+ (when (or selfp (null new-buffer))
+ (let ((target (erc--target-from-string new))
+ (id (erc-networks--id-given erc-networks--id)))
+ (with-current-buffer old-buffer
+ (setq erc-default-recipients (cons new
+ (cdr erc-default-recipients))
+ erc--target target))
+ (setq new-buffer (erc-get-buffer-create erc-session-server
+ erc-session-port
+ nil target id)))))
+ (when new-buffer
+ (with-current-buffer new-buffer
+ (erc-update-mode-line)))
+ buffers))
+
(define-erc-response-handler (NICK)
"Handle nick change messages." nil
(let ((nn (erc-response.contents parsed))
;; erc-channel-users won't contain it
;;
;; Possibly still relevant: bug#12002
- (when-let ((buf (erc-get-buffer nick erc-server-process))
- (tgt (erc--target-from-string nn)))
- (with-current-buffer buf
- (setq erc-default-recipients (cons nn (cdr erc-default-recipients))
- erc--target tgt))
- (with-current-buffer (erc-get-buffer-create erc-session-server
- erc-session-port nil tgt
- (erc-networks--id-given
- erc-networks--id))
- ;; Current buffer is among bufs
- (erc-update-mode-line)))
- (erc-update-user-nick nick nn host nil nil login)
+ (dolist (buf (erc--wrangle-query-buffers-on-nick-change nick nn))
+ (cl-pushnew buf bufs))
+ (erc-update-user-nick nick nn host login)
(cond
((string= nick (erc-current-nick))
(cl-pushnew (erc-server-buffer) bufs)
+ ;; Show message in all query buffers.
+ (setq bufs (append (erc--query-list) bufs))
(erc-set-current-nick nn)
;; Rename session, possibly rename server buf and all targets
(when erc-server-connected
(define-erc-response-handler (QUIT)
"Another user has quit IRC." nil
(let ((reason (erc-response.contents parsed))
+ (erc--msg-prop-overrides erc--msg-prop-overrides)
bufs)
(pcase-let ((`(,nick ,login ,host)
(erc-parse-user (erc-response.sender parsed))))
(setq bufs (erc-buffer-list-with-nick nick proc))
- (erc-remove-user nick)
+ (when (erc-current-nick-p nick)
+ (setq bufs (append (erc--query-list) bufs))
+ (push '(erc--skip . (track)) erc--msg-prop-overrides))
(setq reason (erc-wash-quit-reason reason nick login host))
(erc-display-message parsed 'notice bufs
'QUIT ?n nick ?u login
- ?h host ?r reason))))
+ ?h host ?r reason)
+ (erc-remove-user nick)))
+ nil)
(define-erc-response-handler (TOPIC)
"The channel topic has changed." nil
`erc-server-connect-function's.
When TGT-INFO is non-nil, expect its string field to match the redundant
-param TARGET (retained for compatibility). Whenever possibly, prefer
+param TARGET (retained for compatibility). Whenever possible, prefer
returning TGT-INFO's string unmodified. But when a case-insensitive
collision prevents that, return target@ID when ID is non-nil or
target@network otherwise after renaming the conflicting buffer in the
(erc-server-user-buffers user)
nil))))
+(defun erc--query-list ()
+ "Return all query buffers for the current connection."
+ (erc-buffer-list #'erc-query-buffer-p erc-server-process))
+
;; Some local variables
;; TODO eventually deprecate this variable
--- /dev/null
+;;; erc-scenarios-base-query-participants.el --- Query user tables -*- lexical-binding: t -*-
+
+;; Copyright (C) 2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; 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 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
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-base-query-participants ()
+ :tags '(:expensive-test)
+
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/query-participants")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'legacy))
+ (expect (erc-d-t-make-expecter))
+ (port (process-contact dumb-server :service)))
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :user "tester"
+ :full-name "tester")
+ (funcall expect 10 "This server is in debug mode")
+ (erc-scenarios-common-say "/query bob")))
+
+ (ert-info ("Opening query on untracked user bob doesn't create entry.")
+ (with-current-buffer "bob"
+ (should-not (erc-get-channel-member "bob"))))
+
+ (ert-info ("DM from untracked user creates a query entry.")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "dummy"))
+ (funcall expect 10 "<dummy> hi")
+ (should (erc-get-channel-member "dummy"))
+ (should (erc-get-server-user "dummy"))))
+
+ (with-current-buffer "foonet"
+ (erc-scenarios-common-say "/join #chan"))
+
+ (ert-info ("Members in new chan not added to existing query buffers")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+ (funcall expect 10 "bob ")) ; some user bob is present in #chan
+ (with-current-buffer "bob"
+ (should-not (erc-get-channel-member "bob"))))
+
+ (ert-info ("Opening query on tracked user doesn't create entry")
+ ;; And DM'ing them makes no difference.
+ (with-current-buffer "#chan"
+ (funcall expect 10 " alice") ;; some user alice is present
+ (erc-scenarios-common-say "hi channel")
+ (funcall expect 10 "<tester> hi channel")
+ (erc-scenarios-common-say "/query alice"))
+ (with-current-buffer "alice"
+ (should-not (erc-get-channel-member "alice"))))
+
+ (ert-info ("DM from a tracked user creates entry in preexisting buffer")
+ (with-current-buffer "bob"
+ (funcall expect 10 "<bob> hi")
+ (should (erc-get-channel-member "bob"))))
+
+ (ert-info ("Query pal parting channel doesn't remove them from query")
+ ;; Identical result if they're kicked: they're removed from the
+ ;; server if they have no target buffers remaining, which can't
+ ;; be true if a query with them remains.
+ (with-current-buffer "#chan"
+ (funcall expect 10 "has left")
+ (should-not (erc-get-channel-member "dummy"))
+ (should (erc-get-server-user "dummy")))
+ (with-current-buffer "dummy"
+ (should (erc-get-channel-member "dummy"))))
+
+ (ert-info ("Query pal quitting channel removes them everywhere")
+ (with-current-buffer "#chan"
+ (funcall expect 10 "has quit")
+ (should-not (erc-get-channel-member "bob"))
+ (should-not (erc-get-server-user "bob")))
+ (with-current-buffer "bob"
+ (should-not (erc-get-channel-member "bob"))))
+
+ (ert-info ("Query pal re-joining doesn't repopulate query")
+ (with-current-buffer "#chan"
+ (erc-scenarios-common-say "bob gone")
+ (funcall expect 10 "<alice> bob, welcome back!")
+ (should (erc-get-server-user "bob")))
+ (with-current-buffer "bob"
+ (should-not (erc-get-channel-member "bob"))))
+
+ (ert-info ("Parting removes chan members from server unless in some query")
+ (with-current-buffer "#chan"
+ (erc-scenarios-common-say "/part")
+ (funcall expect 10 "you have left")
+ (should-not (erc-get-server-user "fsbot"))
+ (should-not (erc-get-server-user "alice")) ; she never said anything
+ (should-not (erc-get-server-user "bob")) ; missing from query
+ (should (erc-get-server-user "dummy"))))))
+
+
+;;; erc-scenarios-base-query-participants.el ends here
(erc-server-flood-penalty 0.1)
(erc-server-flood-margin 20)
(dumb-server (erc-d-run "localhost" t 'solo))
+ (expect (erc-d-t-make-expecter))
(port (process-contact dumb-server :service))
erc-autojoin-channels-alist
erc-server-buffer-foo)
(erc-d-t-wait-for 10 (get-buffer "foonet"))
- (ert-info ("Joined by bouncer to #foo, pal persent")
+ (ert-info ("Joined by bouncer to #foo, pal Lal is present")
(with-current-buffer (erc-d-t-wait-for 1 (get-buffer "#foo"))
- (erc-d-t-search-for 5 "On Thursday")
+ (funcall expect 10 "<bob> alice: On Thursday")
(erc-scenarios-common-say "hi")))
- (erc-d-t-wait-for 10 "Query buffer appears with message from pal"
- (get-buffer "Lal"))
-
- (ert-info ("Chat with pal, who changes name")
- (with-current-buffer "Lal"
- (erc-d-t-search-for 3 "hello")
+ (ert-info ("Query buffer appears from Lal, who renicks")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "Lal"))
+ (funcall expect 10 "<Lal> hello")
(erc-scenarios-common-say "hi")
- (erc-d-t-search-for 10 "is now known as Linguo")
- (should-not (search-forward "is now known as Linguo" nil t))))
-
- (erc-d-t-wait-for 1 (get-buffer "Linguo"))
- (should-not (get-buffer "Lal"))
-
- (with-current-buffer "Linguo" (erc-scenarios-common-say "howdy Linguo"))
+ (funcall expect 10 "is now known as Linguo")
+ ;; No duplicate message.
+ (funcall expect -0.1 "is now known as Linguo")
+ ;; No duplicate buffer.
+ (erc-d-t-wait-for 1 (equal (buffer-name) "Linguo"))
+ (should-not (get-buffer "Lal"))
+ (erc-scenarios-common-say "howdy Linguo")))
(with-current-buffer "#foo"
- (erc-d-t-search-for 10 "is now known as Linguo")
- (should-not (search-forward "is now known as Linguo" nil t))
- (erc-cmd-PART ""))
+ (funcall expect 10 "is now known as Linguo")
+ (funcall expect -0.1 "is now known as Linguo")
+ (erc-scenarios-common-say "/part"))
(with-current-buffer "Linguo"
- (erc-d-t-search-for 10 "get along"))))
+ (funcall expect 10 "get along"))))
+
+;; Someone you have a query with disconnects and reconnects under a
+;; new nick (perhaps due to their client appending a backtick or
+;; underscore). They then engage you in another query before
+;; renicking to their original nick. Prior to 5.5, ERC would add a
+;; uniquifying suffix of the form bob<2> to the new, post-renick
+;; query. ERC 5.6+ acts differently. It mimics popular standalone
+;; clients in reusing existing query buffers.
+(ert-deftest erc-scenarios-base-renick-queries/reassume ()
+ :tags '(:expensive-test)
+
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/renick/queries")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'reassume))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-autojoin-channels-alist '((foonet "#chan"))))
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester")
+ (funcall expect 10 "This server is in debug mode")))
+
+ (ert-info ("User dummy opens a query with you")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "dummy"))
+ (funcall expect 10 "hi")))
+
+ (ert-info ("User dummy quits, reconnects as user warwick")
+ (with-current-buffer "#chan"
+ (funcall expect 10 "has quit")
+ (should-not (erc-get-channel-member "dummy"))
+ (with-current-buffer "dummy"
+ (should-not (erc-get-channel-member "dummy")))
+ (funcall expect 10 "<bob> Alas! sir")
+ (funcall expect 10 "<bob> warwick, welcome")
+ (funcall expect 10 "<warwick> hola")))
+
+ (ert-info ("User warwick queries you, creating a new buffer")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "warwick"))
+ (should (get-buffer "dummy")) ; not reused
+ (funcall expect 10 "<warwick> howdy")
+ (funcall expect 10 "is now known as dummy")
+ (should-not (erc-get-channel-member "warwick"))
+ (should-not (erc-get-channel-member "dummy"))))
+
+ (ert-info ("User warwick renicks as user dummy")
+ (with-current-buffer "#chan"
+ (funcall expect 10 "is now known as dummy")
+ (should-not (erc-get-channel-member "warwick"))))
+
+ (with-current-buffer "dummy"
+ (should-not (get-buffer "dummy<2>"))
+ (funcall expect 10 "has quit" (point-min))
+ (funcall expect -0.1 "merging buffer")
+ (funcall expect 10 "is now known as dummy")
+ (should (erc-get-channel-member "dummy"))
+ (funcall expect 10 "<dummy> hey"))
+
+ (with-current-buffer "#chan"
+ (funcall expect 10 "<alice> bob: Than those that"))))
+
+;; This test asserts behavior for the other side of the conversation
+;; described by `erc-scenarios-base-renick-queries/reassume' above.
+;; After speaking with someone in a query, you disconnect and
+;; reconnect under a new nick. You then open a new query with the
+;; same person before changing your nick back to the previous one.
+;; The buffers for the two session should then be merged with the help
+;; of `erc-networks--transplant-target-buffer-function' and
+;; `erc-networks--copy-server-buffer-functions'.
+(ert-deftest erc-scenarios-base-renick-self/merge-query ()
+ :tags '(:expensive-test)
+
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/renick/self")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'merge-query-a 'merge-query-b))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-autojoin-channels-alist '((foonet "#chan"))))
+
+ (ert-info ("Connect to foonet as tester")
+ (with-current-buffer (erc :server "127.0.0.1" :port port :nick "tester")
+ (funcall expect 10 "This server is in debug mode")))
+
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+ (funcall expect 10 "<alice> bob: Speak to the people")
+ (erc-scenarios-common-say "/query observer"))
+
+ (with-current-buffer "observer"
+ (erc-scenarios-common-say "hi")
+ (funcall expect 10 "<observer> hi?"))
+
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+ (erc-scenarios-common-say "/quit"))
+
+ (with-current-buffer "foonet"
+ (funcall expect 10 "*** ERC finished ***"))
+
+ (ert-info ("Reconnect to foonet as dummy")
+ (with-current-buffer (erc :server "127.0.0.1" :port port :nick "dummy")
+ (funcall expect 10 "This server is in debug mode")))
+
+ (with-current-buffer
+ (erc-d-t-wait-for 10 (get-buffer "#chan@foonet/dummy"))
+ ;; Uniquification has been performed.
+ (should-not (get-buffer "#chan"))
+ (should (get-buffer "#chan@foonet/tester"))
+ (should-not (get-buffer "foonet"))
+ (should (get-buffer "foonet/tester"))
+ (should (get-buffer "foonet/dummy"))
+ (funcall expect 10 "<alice> bob: Pray you")
+ (erc-scenarios-common-say "/query observer"))
+
+ (with-current-buffer "observer@foonet/dummy"
+ (should-not (get-buffer "observer"))
+ (should (get-buffer "observer@foonet/tester"))
+ (erc-scenarios-common-say "hola")
+ (funcall expect 10 "<observer> whodis?"))
+
+ (with-current-buffer
+ (erc-d-t-wait-for 10 (get-buffer "#chan@foonet/dummy"))
+ (erc-scenarios-common-say "/nick tester"))
+
+ ;; All buffers have been merged.
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "observer"))
+ (should-not (get-buffer "observer@foonet/dummy"))
+ (should-not (get-buffer "observer@foonet/tester"))
+ ;; Goto last message from previous session. Notice that the
+ ;; quit message appears in all buffers, including queries.
+ (funcall expect 10 "has quit" (point-min))
+ (funcall expect -0.01 "\n\n[") ; duplicate date stamp removed
+ (funcall expect 1 (concat "*** Grafting buffer `observer@foonet/dummy'"
+ " onto `observer@foonet/tester'"))
+ (funcall expect 1 "<dummy> hola")
+ (funcall expect 1 "<observer> whodis?")
+ ;; The nickname change is announced in the query as well so that
+ ;; the nature of the merge is clear.
+ (funcall expect 1 "*** Your new nickname is tester"))
+
+ (with-current-buffer "foonet"
+ (should-not (get-buffer "foonet/dummy"))
+ (should-not (get-buffer "foonet/tester"))
+ ;; Goto last assertion.
+ (funcall expect 10 "*** ERC finished ***" (point-min))
+ (funcall expect -0.01 "\n\n[") ; duplicate date stamp removed
+ (funcall expect 5 "Grafting buffer `foonet/dummy' onto `foonet/tester'"))
+
+ (with-current-buffer "#chan"
+ (should-not (get-buffer "#chan@foonet/dummy"))
+ (should-not (get-buffer "#chan@foonet/tester"))
+ (funcall expect 10 "has quit" (point-min))
+ (funcall expect -0.01 "\n\n[") ; duplicate date stamp removed
+ (funcall expect 1 (concat "*** Grafting buffer `#chan@foonet/dummy'"
+ " onto `#chan@foonet/tester'"))
+ (funcall expect 1 "You have joined channel #chan")
+ (funcall expect 1 "<bob> alice: Have here bereft")
+ (funcall expect 1 "*** Your new nickname is tester"))))
;; You share a channel and a query buffer with a user on two different
;; networks (through a proxy). The user changes their nick on both
--- /dev/null
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER tester 0 * :tester")
+ (0.00 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.01 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.11.1")
+ (0.01 ":irc.foonet.org 003 tester :This server was created Sun, 26 May 2024 09:32:55 UTC")
+ (0.01 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.11.1 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# CHATHISTORY=25 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=25 :are supported by this server")
+ (0.02 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 tester 2 :channels formed")
+ (0.00 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0.03 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0.00 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0.00 ":irc.foonet.org 422 tester :MOTD File is missing")
+ (0.00 ":irc.foonet.org 221 tester +Zi")
+ (0.00 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((mode 10 "MODE tester +i")
+ (0.00 ":irc.foonet.org 221 tester +Zi")
+ (0.07 ":dummy!~u@psu3bp52z9f34.irc PRIVMSG tester :hi"))
+
+((join 10 "JOIN #chan")
+ (0.02 ":tester!~u@psu3bp52z9f34.irc JOIN #chan")
+ (0.06 ":irc.foonet.org 353 tester = #chan :bob dummy tester @fsbot alice")
+ (0.01 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.00 ":alice!~u@zmmipd3xfii2w.irc PRIVMSG #chan :tester, welcome!")
+ (0.03 ":bob!~u@zmmipd3xfii2w.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode-chan 10 "MODE #chan")
+ (0.02 ":irc.foonet.org 324 tester #chan +Cnt")
+ (0.01 ":irc.foonet.org 329 tester #chan 1716715981"))
+
+((privmsg-chan-a 10 "PRIVMSG #chan :hi channel")
+ (0.06 ":bob!~u@zmmipd3xfii2w.irc PRIVMSG #chan :Perchance, Iago, I will ne'er go home.")
+
+ ;; Bob (now known) sends us a DM
+ (0.07 ":bob!~u@zmmipd3xfii2w.irc PRIVMSG tester :hi")
+ (0.02 ":bob!~u@zmmipd3xfii2w.irc PRIVMSG #chan :alice: He is most in the company of the right noble Claudio.")
+ (0.05 ":alice!~u@zmmipd3xfii2w.irc PRIVMSG #chan :bob: Such were our faults; or then we thought them none.")
+ (0.03 ":bob!~u@zmmipd3xfii2w.irc PRIVMSG #chan :You, sir, I entertain you for one of my hundred; only I do not like the fashion of your garments: you will say, they are Persian attire; but let them be changed.")
+
+ ;; Dummy parts
+ (0.01 ":dummy!~u@psu3bp52z9f34.irc PART #chan :bye")
+ (0.08 ":bob!~u@zmmipd3xfii2w.irc PRIVMSG #chan :alice: To lay a complot to betray thy foes.")
+
+ ;; Bob quits
+ (0.02 ":bob!~u@zmmipd3xfii2w.irc QUIT :later")
+ (0.08 ":alice!~u@zmmipd3xfii2w.irc PRIVMSG #chan :bob: He was famous, sir, in his profession, and it was his great right to be so: Gerard de Narbon."))
+
+;; Bob rejoins
+((privmsg-chan-b 10 "PRIVMSG #chan :bob gone")
+
+ (0.04 ":bob!~u@zmmipd3xfii2w.irc JOIN #chan")
+ (0.01 ":alice!~u@zmmipd3xfii2w.irc PRIVMSG #chan :bob, welcome back!")
+ (0.03 ":bob!~u@zmmipd3xfii2w.irc PRIVMSG #chan :Our states are forfeit: seek not to undo us."))
+
+((part 10 "PART #chan :\2ERC\2")
+ (0.02 ":tester!~u@psu3bp52z9f34.irc PART #chan :\2ERC\2"))
(0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
(0 ":irc.foonet.org 422 tester :MOTD File is missing"))
-((mode-user 3.2 "MODE tester +i")
+((mode-user 10 "MODE tester +i")
(0 ":irc.foonet.org 221 tester +i")
(0 ":irc.foonet.org NOTICE tester :This server is still in debug mode."))
--- /dev/null
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :unknown")
+ (0.00 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.00 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.11.1")
+ (0.00 ":irc.foonet.org 003 tester :This server was created Thu, 09 May 2024 05:19:24 UTC")
+ (0.00 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.11.1 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# CHATHISTORY=25 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by this server")
+ (0.00 ":irc.foonet.org 005 tester KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=25 :are supported by this server")
+ (0.00 ":irc.foonet.org 251 tester :There are 0 users and 6 invisible on 1 server(s)")
+ (0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 tester 2 :channels formed")
+ (0.00 ":irc.foonet.org 255 tester :I have 6 clients and 0 servers")
+ (0.00 ":irc.foonet.org 265 tester 6 6 :Current local users 6, max 6")
+ (0.00 ":irc.foonet.org 266 tester 6 6 :Current global users 6, max 6")
+ (0.00 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10 "MODE tester +i")
+ (0.00 ":irc.foonet.org 221 tester +i")
+ (0.00 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 10 "JOIN #chan")
+ (0.03 ":irc.foonet.org 221 tester +i") ; dupe
+ (0.00 ":tester!~u@s8ceryiqkkcxk.irc JOIN #chan")
+ (0.04 ":irc.foonet.org 353 tester = #chan :@fsbot bob alice dummy tester")
+ (0.00 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.00 ":alice!~u@68v4mpismdues.irc PRIVMSG #chan :tester, welcome!")
+ (0.00 ":bob!~u@68v4mpismdues.irc PRIVMSG #chan :tester, welcome!")
+ (0.03 ":bob!~u@68v4mpismdues.irc PRIVMSG #chan :That eye that told you so look'd but a-squint."))
+
+((mode-chan 10 "MODE #chan")
+ (0.00 ":irc.foonet.org 324 tester #chan +Cnt")
+ (0.01 ":irc.foonet.org 329 tester #chan 1715231970")
+
+ ;; existing query with dummy
+ (0.05 ":dummy!~u@s8ceryiqkkcxk.irc PRIVMSG tester :hi")
+ (0.02 ":bob!~u@68v4mpismdues.irc PRIVMSG #chan :alice: Villains, forbear! we are the empress' sons.")
+ (0.01 ":alice!~u@68v4mpismdues.irc PRIVMSG #chan :bob: This matter of marrying his king's daughter,wherein he must be weighed rather by her value than his own,words him, I doubt not, a great deal from the matter.")
+
+ ;; dummy quits
+ (0.07 ":dummy!~u@s8ceryiqkkcxk.irc QUIT :Quit: \2ERC\2 5.5.0.29.1 (IRC client for GNU Emacs 29.3.50)")
+ (0.03 ":bob!~u@68v4mpismdues.irc PRIVMSG #chan :We will afflict the emperor in his pride.")
+ (0.03 ":alice!~u@68v4mpismdues.irc PRIVMSG #chan :bob: Why, then, is my pump well flowered.")
+ (0.05 ":bob!~u@68v4mpismdues.irc PRIVMSG #chan :Alas! sir, I know not Jupiter; I never drank with him in all my life.")
+
+ ;; rejoins as warwick
+ (0.03 ":warwick!~u@s8ceryiqkkcxk.irc JOIN #chan")
+ (0.00 ":bob!~u@68v4mpismdues.irc PRIVMSG #chan :warwick, welcome!")
+ (0.00 ":alice!~u@68v4mpismdues.irc PRIVMSG #chan :warwick, welcome!")
+ (0.03 ":warwick!~u@s8ceryiqkkcxk.irc PRIVMSG #chan :hola")
+ (0.03 ":alice!~u@68v4mpismdues.irc PRIVMSG #chan :bob: And stint thou too, I pray thee, nurse, say I.")
+
+ ;; Makes contact in a query
+ (0.02 ":warwick!~u@s8ceryiqkkcxk.irc PRIVMSG tester :howdy")
+ (0.03 ":alice!~u@68v4mpismdues.irc PRIVMSG #chan :bob: Nor more willingly leaves winter; such summer-birds are men. Gentlemen, our dinner will not recompense this long stay: feast your ears with the music awhile, if they will fare so harshly o' the trumpet's sound; we shall to 't presently.")
+ (0.03 ":bob!~u@68v4mpismdues.irc PRIVMSG #chan :If it please your honour, I know not well what they are; but precise villains they are, that I am sure of, and void of all profanation in the world that good Christians ought to have.")
+
+ ;; warwick renicks back to dummy
+ (0.08 ":warwick!~u@s8ceryiqkkcxk.irc NICK dummy")
+ (0.04 ":bob!~u@68v4mpismdues.irc PRIVMSG #chan :Pleasure and action make the hours seem short.")
+ (0.01 ":dummy!~u@s8ceryiqkkcxk.irc PRIVMSG tester :hey")
+ (0.02 ":alice!~u@68v4mpismdues.irc PRIVMSG #chan :bob: Than those that have more cunning to be strange."))
;; -*- mode: lisp-data; -*-
-((pass 1 "PASS :foonet:changeme"))
+((pass 10 "PASS :foonet:changeme"))
((nick 1 "NICK tester"))
((user 1 "USER user 0 * :tester")
(0 ":irc.foonet.org 001 tester :Welcome to the FooNet Internet Relay Chat Network tester")
(0 ":irc.foonet.org 372 tester :- Please visit us in #libera for questions and support.")
(0 ":irc.foonet.org 376 tester :End of /MOTD command."))
-((mode-user 1.2 "MODE tester +i")
+((mode-user 10 "MODE tester +i")
(0 ":tester!~u@gq7yjr7gsu7nn.irc MODE tester :+RZi")
(0 ":irc.znc.in 306 tester :You have been marked as being away")
(0 ":tester!~u@gq7yjr7gsu7nn.irc JOIN #foo")
(0 ":irc.foonet.org NOTICE tester :[09:56:57] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
(0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
-((mode 1 "MODE #foo")
+((mode-foo 10 "MODE #foo")
(0 ":irc.foonet.org 324 tester #foo +nt")
(0 ":irc.foonet.org 329 tester #foo 1622454985")
(0.1 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Farewell, pretty lady: you must hold the credit of your father.")
(0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: On Thursday, sir ? the time is very short."))
-((nick 2 "NICK dummy")
+((nick 10 "NICK dummy")
(0 ":tester!~u@gq7yjr7gsu7nn.irc NICK :dummy")
(0.1 ":dummy!~u@gq7yjr7gsu7nn.irc MODE dummy :+RZi")
(0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :dummy: Hi."))
--- /dev/null
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :unknown")
+ (0.00 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.01 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.11.1")
+ (0.00 ":irc.foonet.org 003 tester :This server was created Sun, 12 May 2024 00:41:10 UTC")
+ (0.00 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.11.1 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# CHATHISTORY=25 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=25 :are supported by this server")
+ (0.00 ":irc.foonet.org 251 tester :There are 0 users and 6 invisible on 1 server(s)")
+ (0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.02 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 tester 2 :channels formed")
+ (0.01 ":irc.foonet.org 255 tester :I have 6 clients and 0 servers")
+ (0.00 ":irc.foonet.org 265 tester 6 6 :Current local users 6, max 6")
+ (0.00 ":irc.foonet.org 266 tester 6 6 :Current global users 6, max 6")
+ (0.00 ":irc.foonet.org 422 tester :MOTD File is missing")
+ (0.00 ":irc.foonet.org 221 tester +i")
+ (0.00 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((mode-user 10 "MODE tester +i"))
+
+((join 10 "JOIN #chan")
+ (0.00 ":irc.foonet.org 221 tester +i")
+ (0.00 ":tester!~u@hyyensdmcrjxc.irc JOIN #chan")
+ (0.02 ":irc.foonet.org 353 tester = #chan :someone tester @fsbot alice bob observer")
+ (0.01 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.00 ":bob!~u@zb3s8yrduykma.irc PRIVMSG #chan :tester, welcome!")
+ (0.01 ":alice!~u@zb3s8yrduykma.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode-chan 10 "MODE #chan")
+ (0.00 ":irc.foonet.org 324 tester #chan +Cnt")
+ (0.02 ":irc.foonet.org 329 tester #chan 1715474476")
+ (0.09 ":bob!~u@zb3s8yrduykma.irc PRIVMSG #chan :alice: And, uncle, so will I, an if I live.")
+ (0.03 ":alice!~u@zb3s8yrduykma.irc PRIVMSG #chan :bob: Speak to the people, and they pity her."))
+
+((privmsg-observer 10 "PRIVMSG observer :hi")
+ (0.04 ":observer!~u@hyyensdmcrjxc.irc PRIVMSG tester :hi?")
+ (0.07 ":bob!~u@zb3s8yrduykma.irc PRIVMSG #chan :To ask of whence you are: report it."))
+
+((quit 10 "QUIT :\2ERC\2")
+ (0.03 ":tester!~u@hyyensdmcrjxc.irc QUIT :Quit: \2ERC\2 5.6-git (IRC client for GNU Emacs 30.0.50)")
+ (0.03 "ERROR :Quit: \2ERC\2 5.6-git (IRC client for GNU Emacs 30.0.50)"))
+
+((drop 0 DROP))
--- /dev/null
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK dummy"))
+((user 10 "USER user 0 * :unknown")
+ (0.01 ":irc.foonet.org 001 dummy :Welcome to the foonet IRC Network dummy")
+ (0.01 ":irc.foonet.org 002 dummy :Your host is irc.foonet.org, running version ergo-v2.11.1")
+ (0.01 ":irc.foonet.org 003 dummy :This server was created Sun, 12 May 2024 00:41:10 UTC")
+ (0.00 ":irc.foonet.org 004 dummy irc.foonet.org ergo-v2.11.1 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.03 ":irc.foonet.org 005 dummy AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# CHATHISTORY=25 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by this server")
+ (0.03 ":irc.foonet.org 005 dummy KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 dummy draft/CHATHISTORY=25 :are supported by this server")
+ (0.00 ":irc.foonet.org 251 dummy :There are 0 users and 6 invisible on 1 server(s)")
+ (0.00 ":irc.foonet.org 252 dummy 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 253 dummy 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 dummy 2 :channels formed")
+ (0.00 ":irc.foonet.org 255 dummy :I have 6 clients and 0 servers")
+ (0.00 ":irc.foonet.org 265 dummy 6 6 :Current local users 6, max 6")
+ (0.00 ":irc.foonet.org 266 dummy 6 6 :Current global users 6, max 6")
+ (0.03 ":irc.foonet.org 422 dummy :MOTD File is missing")
+ (0.00 ":irc.foonet.org 221 dummy +i")
+ (0.00 ":irc.foonet.org NOTICE dummy :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((mode-user 10 "MODE dummy +i"))
+
+((join-chan 10 "JOIN #chan")
+ (0.01 ":irc.foonet.org 221 dummy +i")
+ (0.00 ":dummy!~u@hyyensdmcrjxc.irc JOIN #chan")
+ (0.02 ":irc.foonet.org 353 dummy = #chan :@fsbot alice bob observer someone dummy")
+ (0.01 ":irc.foonet.org 366 dummy #chan :End of NAMES list")
+ (0.00 ":bob!~u@zb3s8yrduykma.irc PRIVMSG #chan :dummy, welcome!")
+ (0.01 ":alice!~u@zb3s8yrduykma.irc PRIVMSG #chan :dummy, welcome!"))
+
+((mode-chan 10 "MODE #chan")
+ (0.00 ":irc.foonet.org 324 dummy #chan +Cnt")
+ (0.02 ":irc.foonet.org 329 dummy #chan 1715474476")
+ (0.09 ":bob!~u@zb3s8yrduykma.irc PRIVMSG #chan :alice: Indeed, sir, he that sleeps feels not the toothache; but a man that were to sleep your sleep, and a hangman to help him to bed, I think he would change places with his officer; for look you, sir, you know not which way you shall go.")
+ (0.03 ":alice!~u@zb3s8yrduykma.irc PRIVMSG #chan :bob: Pray you, sir, deliver me this paper."))
+
+((privmsg-observer 10 "PRIVMSG observer :hola")
+ (0.01 ":bob!~u@zb3s8yrduykma.irc PRIVMSG #chan :alice: In manner and form following, sir; all those three: I was seen with her in the manor-house, sitting with her upon the form, and taken following her into the park; which, put together, is, in manner and form following. Now, sir, for the manner,it is the manner of a man to speak to a woman, for the form,in some form.")
+ (0.05 ":alice!~u@zb3s8yrduykma.irc PRIVMSG #chan :In Isbel's case and mine own. Service is no heritage; and I think I shall never have the blessing of God till I have issue o' my body, for they say barnes are blessings.")
+ (0.01 ":observer!~u@hyyensdmcrjxc.irc PRIVMSG dummy :whodis?")
+ (0.02 ":bob!~u@zb3s8yrduykma.irc PRIVMSG #chan :alice: Have here bereft my brother of his life."))
+
+((nick-tester 10 "NICK tester")
+ (0.02 ":dummy!~u@hyyensdmcrjxc.irc NICK tester")
+
+ (0.04 ":alice!~u@zb3s8yrduykma.irc PRIVMSG #chan :bob: You have too courtly a wit for me: I'll rest.")
+ (0.07 ":bob!~u@zb3s8yrduykma.irc PRIVMSG #chan :alice: And abstinence engenders maladies."))