Spoof channel users in erc-button--phantom-users-mode

* lisp/erc/erc-backend.el (erc--cmem-from-nick-function): Update
forward declaration.
(erc-server-PRIVMSG): Use new name for `erc--user-from-nick-function',
now `erc--cmem-from-nick-function'.
* lisp/erc/erc-button.el (erc-button--phantom-users,
erc-button--phantom-cmems): Rename former to latter.
(erc-button--fallback-user-function,
erc-button--fallback-cmem-function): Rename former to latter.
(erc--phantom-channel-user, erc--phantom-server-user): New superficial
`cl-struct' definitions "subclassing" `erc-channel-user' and
`erc-server-user'.  Note that these symbols lack an `erc-button'
prefix.
(erc-button--add-phantom-speaker): Look for channel member instead of
server user, creating one if necessary.  Return a made-up
`erc-channel-user' along with a fake `erc-server-user'.
(erc-button--get-phantom-user, erc-button--get-phantom-cmem): Rename
former to latter.
(erc-button--phantom-users-mode, erc-button--phantom-users-enable,
erc-button--phantom-users-disable): Use updated "cmem" names for
function-valued interface variables and their implementing functions.
Remove obsolete comment.
(erc-button-add-nickname-buttons): Attempt to query fallback function
for channel member instead of server user.
* lisp/erc/erc.el (erc--user-from-nick-function,
erc--cmem-from-nick-function): Rename former to latter.
(erc--examine-nick, erc--cmem-get-existing): Rename former to
latter.  (Bug#60933)
This commit is contained in:
F. Jason Park 2023-09-06 19:40:11 -07:00
parent 69a154616e
commit a0ed463bab
3 changed files with 45 additions and 38 deletions

View file

@ -104,7 +104,7 @@
(defvar erc--called-as-input-p)
(defvar erc--display-context)
(defvar erc--target)
(defvar erc--user-from-nick-function)
(defvar erc--cmem-from-nick-function)
(defvar erc-channel-list)
(defvar erc-channel-users)
(defvar erc-default-nicks)
@ -1944,7 +1944,7 @@ add things to `%s' instead."
;; at this point.
(erc-update-channel-member (if privp nick tgt) nick nick
privp nil nil nil nil nil host login nil nil t)
(let ((cdata (funcall erc--user-from-nick-function
(let ((cdata (funcall erc--cmem-from-nick-function
(erc-downcase nick) sndr parsed)))
(setq fnick (funcall erc-format-nick-function
(car cdata) (cdr cdata))))))

View file

@ -380,32 +380,37 @@ buttonizing ought to proceed and nil otherwise. While running,
all faces defined in `erc-button' are bound temporarily and can
be updated at will.")
(defvar-local erc-button--phantom-users nil)
(defvar-local erc-button--phantom-cmems nil)
(defvar erc-button--fallback-user-function #'ignore
"Function to determine `erc-server-user' if not found in the usual places.
(defvar erc-button--fallback-cmem-function #'ignore
"Function to determine channel member if not found in the usual places.
Called with DOWNCASED-NICK, NICK, and NICK-BOUNDS when
`erc-button-add-nickname-buttons' cannot find a user object for
DOWNCASED-NICK in `erc-channel-users' or `erc-server-users'.")
;; Historical or fictitious users. As long as these two structs
;; remain superficial "subclasses" with the same slots and defaults,
;; they can live here instead of in erc-common.el.
(cl-defstruct (erc--phantom-channel-user (:include erc-channel-user)))
(cl-defstruct (erc--phantom-server-user (:include erc-server-user)))
(defun erc-button--add-phantom-speaker (downcased nuh _parsed)
"Stash fictitious `erc-server-user' while processing \"PRIVMSG\".
Expect DOWNCASED to be the downcased nickname, NUH to be a triple
of (NICK LOGIN HOST), and parsed to be an `erc-response' object."
(pcase-let* ((`(,nick ,login ,host) nuh)
(user (or (gethash downcased erc-button--phantom-users)
(make-erc-server-user
(cmem (gethash downcased erc-button--phantom-cmems))
(user (or (car cmem)
(make-erc--phantom-server-user
:nickname nick
:host (and (not (string-empty-p host)) host)
:login (and (not (string-empty-p login)) login)))))
(list (puthash downcased user erc-button--phantom-users))))
:login (and (not (string-empty-p login)) login))))
(cuser (or (cdr cmem)
(make-erc--phantom-channel-user
:last-message-time (current-time)))))
(puthash downcased (cons user cuser) erc-button--phantom-cmems)
(cons user cuser)))
(defun erc-button--get-phantom-user (down _word _bounds)
(gethash down erc-button--phantom-users))
(defun erc-button--get-phantom-cmem (down _word _bounds)
(gethash down erc-button--phantom-cmems))
;; In the future, we'll most likely create temporary
;; `erc-channel-users' tables during BATCH chathistory playback, thus
;; obviating the need for this mode entirely.
(define-minor-mode erc-button--phantom-users-mode
"Minor mode to recognize unknown speakers.
Expect to be used by module setup code for creating placeholder
@ -415,22 +420,22 @@ appeared in a prior \"353\" message and are thus a known member
of the channel. However, don't bother creating an actual
`erc-channel-user' object because their status prefix is unknown.
Instead, just spoof an `erc-server-user' and stash it during
\"PRIVMSG\" handling via `erc--user-from-nick-function' and
\"PRIVMSG\" handling via `erc--cmem-from-nick-function' and
retrieve it during buttonizing via
`erc-button--fallback-user-function'."
:interactive nil
(if erc-button--phantom-users-mode
(progn
(add-function :after-until (local 'erc--user-from-nick-function)
#'erc-button--add-phantom-speaker '((depth . -50)))
(add-function :after-until (local 'erc-button--fallback-user-function)
#'erc-button--get-phantom-user '((depth . 50)))
(setq erc-button--phantom-users (make-hash-table :test #'equal)))
(remove-function (local 'erc--user-from-nick-function)
(add-function :after-until (local 'erc--cmem-from-nick-function)
#'erc-button--add-phantom-speaker '((depth . 30)))
(add-function :after-until (local 'erc-button--fallback-cmem-function)
#'erc-button--get-phantom-cmem '((depth . 50)))
(setq erc-button--phantom-cmems (make-hash-table :test #'equal)))
(remove-function (local 'erc--cmem-from-nick-function)
#'erc-button--add-phantom-speaker)
(remove-function (local 'erc-button--fallback-user-function)
#'erc-button--get-phantom-user)
(kill-local-variable 'erc-nicks--phantom-users)))
(remove-function (local 'erc-button--fallback-cmem-function)
#'erc-button--get-phantom-cmem)
(kill-local-variable 'erc-button--phantom-cmems)))
(defun erc-button-add-nickname-buttons (entry)
"Search through the buffer for nicknames, and add buttons."
@ -451,11 +456,12 @@ retrieve it during buttonizing via
(down (erc-downcase word)))
(let* ((erc-button-mouse-face erc-button-mouse-face)
(erc-button-nickname-face erc-button-nickname-face)
(cuser (and erc-channel-users (gethash down erc-channel-users)))
(cuser (and erc-channel-users
(or (gethash down erc-channel-users)
(funcall erc-button--fallback-cmem-function
down word bounds))))
(user (or (and cuser (car cuser))
(and erc-server-users (gethash down erc-server-users))
(funcall erc-button--fallback-user-function
down word bounds)))
(and erc-server-users (gethash down erc-server-users))))
(data (list word)))
(when (or (not (functionp form))
(and-let* ((user)

View file

@ -5262,14 +5262,15 @@ Assume buffer is narrowed to the confines of an inserted message."
(next-single-property-change (point-min) 'erc-speaker))))
(cons beg (next-single-property-change beg 'erc-speaker)))))
(defvar erc--user-from-nick-function #'erc--examine-nick
"Function to possibly consider unknown user.
Must return either nil or a cons of an `erc-server-user' and a
possibly nil `erc-channel-user' for formatting a server user's
nick. Called in the appropriate buffer with the downcased nick,
the parsed NUH, and the original `erc-response' object.")
(defvar erc--cmem-from-nick-function #'erc--cmem-get-existing
"Function maybe returning a \"channel member\" cons from a nick.
Must return either nil or a cons of an `erc-server-user' and an
`erc-channel-user' (see `erc-channel-users') for use in
formatting a user's nick prior to insertion. Called in the
appropriate target buffer with the downcased nick, the parsed
NUH, and the current `erc-response' object.")
(defun erc--examine-nick (downcased _nuh _parsed)
(defun erc--cmem-get-existing (downcased _nuh _parsed)
(and erc-channel-users (gethash downcased erc-channel-users)))
(defun erc-format-privmessage (nick msg privp msgp)