>From ce69478143756927d661b47d17e79249c96a47f8 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Mon, 20 May 2024 03:08:47 -0700 Subject: [PATCH 5/7] [5.6] Update ERC query participants on JOIN and after NAMES * lisp/erc/erc-backend.el (erc-server-JOIN): Update query membership when someone else joins a channel. (erc-server-NICK): Update query membership after someone else changes their nick. (erc-server-PRIVMSG): After printing a query message from some other person, remove their user data if they're unknown, likely on account of them not being in any channels. (erc-server-311): Fix call to `erc-update-user-nick' so the userhost login component is no longer supplied as the `info' parameter but rather, correctly, as `login'. (erc-server-352): Handle asterisk as channel param. (erc-server-366): Update membership in all query buffers after all names have been received. * lisp/erc/erc-common.el (erc--get-server-user): New function, a thin wrapper around `erc-get-server-user' for cases were inlining would require declaring symbols not defined in erc-common. * lisp/erc/erc.el (erc-channel-members): Mention that this is used for queries as well. (erc--ensure-query-member, erc--ensure-query-members): New functions. (erc-cmd-QUERY): Ensure parties are present in the query buffer's membership table if they're known to be on the server. (erc-message-english-s352-you): New variable. (Bug#70928) --- lisp/erc/erc-backend.el | 68 ++++++++++++++++++++++++++++------------- lisp/erc/erc-common.el | 3 ++ lisp/erc/erc.el | 33 +++++++++++++++++--- 3 files changed, 79 insertions(+), 25 deletions(-) diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index 447139a2218..d1e7ff610c7 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -118,6 +118,8 @@ erc-nick (defvar erc-nick-change-attempt-count) (defvar erc-verbose-server-ping) +(declare-function erc--ensure-query-member "erc" (name)) +(declare-function erc--ensure-query-members "erc" ()) (declare-function erc--init-channel-modes "erc" (channel raw-args)) (declare-function erc--open-target "erc" (target)) (declare-function erc--parse-nuh "erc" (string)) @@ -1780,6 +1782,8 @@ erc--server-determine-join-display-context (list 'JOIN ?n nick ?u login ?h host ?c chnl))))) (when buffer (set-buffer buffer)) (erc-update-channel-member chnl nick nick t nil nil nil nil nil host login) + (unless (erc-current-nick-p nick) + (erc--ensure-query-member nick)) ;; on join, we want to stay in the new channel buffer ;;(set-buffer ob) (apply #'erc-display-message parsed 'notice buffer args)))))) @@ -1903,7 +1907,8 @@ erc--wrangle-query-buffers-on-nick-change (run-hook-with-args 'erc-nick-changed-functions nn nick)) (t (when erc-server-connected - (erc-networks--id-reload erc-networks--id proc parsed)) + (erc-networks--id-reload erc-networks--id proc parsed) + (erc--ensure-query-member nn)) (erc-handle-user-status-change 'nick (list nick login host) (list nn)) (erc-display-message parsed 'notice bufs 'NICK ?n nick ?u login ?h host ?N nn)))))) @@ -2051,7 +2056,7 @@ erc--speaker-status-prefix-wanted-p (erc--speaker-status-prefix-wanted-p nil) (erc-current-message-catalog erc--message-speaker-catalog) ;; - buffer statusmsg cmem-prefix fnick) + finalize buffer statusmsg cmem-prefix fnick) (setq buffer (erc-get-buffer (if privp nick tgt) proc)) ;; Even worth checking for empty target here? (invalid anyway) (unless (or buffer noticep (string-empty-p tgt) (eq ?$ (aref tgt 0)) @@ -2078,10 +2083,12 @@ erc--speaker-status-prefix-wanted-p (setq buffer (erc--open-target tgt)))))) (when buffer (with-current-buffer buffer - (when privp (erc--unhide-prompt)) - ;; update the chat partner info. Add to the list if private - ;; message. We will accumulate private identities indefinitely - ;; at this point. + (when privp + (erc--unhide-prompt) + ;; Remove untracked query partners after display. + (unless (erc--get-server-user nick) + (setq finalize (lambda () + (erc-remove-channel-member buffer nick))))) (erc-update-channel-member (if privp nick tgt) nick nick privp nil nil nil nil nil host login nil nil t) (defvar erc--cmem-from-nick-function) @@ -2120,7 +2127,9 @@ erc--speaker-status-prefix-wanted-p (run-hook-with-args 'erc-echo-notice-always-hook fmtmsg parsed buffer nick) (run-hook-with-args-until-success - 'erc-echo-notice-hook fmtmsg parsed buffer nick)))))))))) + 'erc-echo-notice-hook fmtmsg parsed buffer nick))))) + (when finalize (funcall finalize))) + nil)))) (define-erc-response-handler (QUIT) "Another user has quit IRC." nil @@ -2327,6 +2336,9 @@ erc--with-isupport-data See `erc-display-server-message'." nil (erc-display-server-message proc parsed)) +(define-erc-response-handler (263) "RPL_TRYAGAIN." nil + (erc-handle-unknown-server-response proc parsed)) + (define-erc-response-handler (275) "Display secure connection message." nil (pcase-let ((`(,nick ,_user ,_message) @@ -2379,7 +2391,7 @@ erc--with-isupport-data (catalog-entry (intern (format "s%s" (erc-response.command parsed))))) (pcase-let ((`(,nick ,user ,host) (cdr (erc-response.command-args parsed)))) - (erc-update-user-nick nick nick host nil fname user) + (erc-update-user-nick nick nick host user fname) (erc-display-message parsed 'notice 'active catalog-entry ?n nick ?f fname ?u user ?h host)))) @@ -2541,18 +2553,28 @@ erc-server-322-message (erc-display-message parsed 'notice (erc-get-buffer channel proc) 's341 ?n nick ?c channel))) -;; FIXME update or add server user instead when channel is "*". +(defun erc--extract-352-full-name (contents) + "Return full name from 352 trailing param, discarding hop count." + (pcase contents + ((rx (: bot (+ (any "0-9")) " ") (let full-name (group (* nonl))) eot) + full-name) + (_ contents))) + (define-erc-response-handler (352) - "WHO notice." nil - (pcase-let ((`(,channel ,user ,host ,_server ,nick ,away-flag) - (cdr (erc-response.command-args parsed)))) - (let ((full-name (erc-response.contents parsed))) - (when (string-match "\\(^[0-9]+ \\)\\(.*\\)$" full-name) - (setq full-name (match-string 2 full-name))) - (erc-update-channel-member channel nick nick nil nil nil nil nil nil host user full-name) - (erc-display-message parsed 'notice 'active 's352 - ?c channel ?n nick ?a away-flag - ?u user ?h host ?f full-name)))) + "RPL_WHOREPLY response." nil + (pcase-let* + ((`(,_ ,channel ,user ,host ,_server ,nick ,flags, hop-real) + (erc-response.command-args parsed)) + (full-name (erc--extract-352-full-name hop-real)) + (selfp (string= channel "*")) + (template (if selfp 's352-you 's352))) + (if selfp + (erc-update-user-nick nick nick host user full-name) + (erc-update-channel-member channel nick nick nil nil nil nil nil nil + host user full-name)) + (erc-display-message parsed 'notice 'active template + ?c channel ?n nick ?a flags + ?u user ?h host ?f full-name))) (define-erc-response-handler (353) "NAMES notice." nil @@ -2567,7 +2589,9 @@ erc-server-322-message (define-erc-response-handler (366) "End of NAMES." nil (erc-with-buffer ((cadr (erc-response.command-args parsed)) proc) - (erc-channel-end-receiving-names))) + (erc-channel-end-receiving-names)) + (erc--ensure-query-members) + nil) (define-erc-response-handler (367) "Channel ban list entries." nil @@ -2633,7 +2657,9 @@ erc-server-322-message (erc-log (format "cmd: WHOWAS: %s" nick/channel)) (erc-server-send (format "WHOWAS %s 1" nick/channel))) (erc-display-message parsed '(notice error) 'active - 's401 ?n nick/channel))) + 's401 ?n nick/channel) + (unless (erc-channel-p nick/channel) + (erc-remove-user nick/channel)))) (define-erc-response-handler (402) "No such server." nil diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el index 51a93bdaa50..c01ee6546cb 100644 --- a/lisp/erc/erc-common.el +++ b/lisp/erc/erc-common.el @@ -557,6 +557,9 @@ erc-get-server-user (gethash (erc-downcase ,nick) (erc-with-server-buffer erc-server-users))))) +(defun erc--get-server-user (nick) + (erc-get-server-user nick)) + (defmacro erc--with-dependent-type-match (type &rest features) "Massage Custom :type TYPE with :match function that pre-loads FEATURES." `(backquote-list* ',(car type) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 38547ea94bf..f070fd526ac 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -509,7 +509,7 @@ erc-connect-pre-hook (defvaralias 'erc-channel-users 'erc-channel-members) (defvar-local erc-channel-members nil - "Hash table of members in the current channel. + "Hash table of members in the current channel or query buffer. It associates nicknames with cons cells of the form \(SERVER-USER . MEMBER-DATA), where SERVER-USER is a `erc-server-user' object and MEMBER-DATA is a `erc-channel-user' @@ -549,6 +549,27 @@ erc-add-server-user (erc-with-server-buffer (puthash (erc-downcase nick) user erc-server-users))) +(defun erc--ensure-query-member (nick) + "Populate membership table in query buffer for online NICK." + (erc-with-buffer (nick) + (when-let (((zerop (hash-table-count erc-channel-users))) + (user (erc-get-server-user nick))) + (erc-update-current-channel-member nick nil t) + (erc--unhide-prompt) + t))) + +(defun erc--ensure-query-members () + "Update membership tables in all query buffers. +Ensure targets with an entry in `erc-server-users' are present in +`erc-channel-members'." + (erc-with-all-buffers-of-server erc-server-process #'erc-query-buffer-p + (when-let (((zerop (hash-table-count erc-channel-users))) + (target (erc-target)) + ((erc-get-server-user target))) + (erc-update-current-channel-member target nil t) + (erc--unhide-prompt)) + erc-server-process)) + (defun erc-remove-server-user (nick) "This function is for internal use only. @@ -5151,8 +5172,7 @@ erc-cmd-QUOTE (defun erc-cmd-QUERY (&optional user) "Open a query with USER. -How the query is displayed (in a new window, frame, etc.) depends -on the value of `erc-interactive-display'." +Display the query buffer in accordance with `erc-interactive-display'." ;; FIXME: The doc string used to say at the end: ;; "If USER is omitted, close the current query buffer if one exists ;; - except this is broken now ;-)" @@ -5168,7 +5188,11 @@ erc-cmd-QUERY (erc--display-context `((erc-interactive-display . /QUERY) ,@erc--display-context))) (erc-with-server-buffer - (erc--open-target user)))) + (if-let ((buffer (erc-get-buffer user erc-server-process))) + (prog1 buffer + (erc-setup-buffer buffer)) + (prog1 (erc--open-target user) ; becomes current buffer + (erc--ensure-query-member user)))))) (defalias 'erc-cmd-Q #'erc-cmd-QUERY) @@ -9521,6 +9545,7 @@ english (s333 . "%c: topic set by %n, %t") (s341 . "Inviting %n to channel %c") (s352 . "%-11c %-10n %-4a %u@%h (%f)") + (s352-you . "%n %a %u@%h (%f)") (s353 . "Users on %c: %u") (s367 . "Ban for %b on %c") (s367-set-by . "Ban for %b on %c set by %s on %t") -- 2.45.1