aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Feinstein2012-08-20 09:08:51 -0700
committerJosh Feinstein2012-08-20 09:08:51 -0700
commit487a247f1d48faac2aa789baddd5ee5d7fa28d4a (patch)
tree19d7148692b9c9b5eaac8414903b8c1dc1206966
parenta32fbbcf262a71891032ef84f596bf5525f9124a (diff)
downloademacs-487a247f1d48faac2aa789baddd5ee5d7fa28d4a.tar.gz
emacs-487a247f1d48faac2aa789baddd5ee5d7fa28d4a.zip
Hide specified message types sent by lurkers
* erc.el (erc-display-message): Abstract message hiding decision to new function erc-hide-current-message-p. (erc-lurker): New customization group. (erc-lurker-state, erc-lurker-trim-nicks, erc-lurker-ignore-chars) (erc-lurker-hide-list, erc-lurker-cleanup-interval) (erc-lurker-threshold-time): New variables. (erc-lurker-maybe-trim, erc-lurker-initialize, erc-lurker-cleanup) (erc-hide-current-message-p, erc-canonicalize-server-name) (erc-lurker-update-status, erc-lurker-p): New functions. Together they maintain state about which users have spoken in the last erc-lurker-threshold-time, with all other users being considered lurkers whose messages of types in erc-lurker-hide-list will not be displayed by erc-display-message.
-rw-r--r--lisp/erc/ChangeLog16
-rw-r--r--lisp/erc/erc.el174
2 files changed, 189 insertions, 1 deletions
diff --git a/lisp/erc/ChangeLog b/lisp/erc/ChangeLog
index b87cfd41f61..dd62cae7de1 100644
--- a/lisp/erc/ChangeLog
+++ b/lisp/erc/ChangeLog
@@ -1,3 +1,19 @@
12012-08-20 Josh Feinstein <jlf@foxtail.org>
2
3 * erc.el (erc-display-message): Abstract message hiding decision
4 to new function erc-hide-current-message-p.
5 (erc-lurker): New customization group.
6 (erc-lurker-state, erc-lurker-trim-nicks, erc-lurker-ignore-chars)
7 (erc-lurker-hide-list, erc-lurker-cleanup-interval)
8 (erc-lurker-threshold-time): New variables.
9 (erc-lurker-maybe-trim, erc-lurker-initialize, erc-lurker-cleanup)
10 (erc-hide-current-message-p, erc-canonicalize-server-name)
11 (erc-lurker-update-status, erc-lurker-p): New functions. Together
12 they maintain state about which users have spoken in the last
13 erc-lurker-threshold-time, with all other users being considered
14 lurkers whose messages of types in erc-lurker-hide-list will not
15 be displayed by erc-display-message.
16
12012-08-06 Julien Danjou <julien@danjou.info> 172012-08-06 Julien Danjou <julien@danjou.info>
2 18
3 * erc-match.el (erc-match-exclude-server-buffer) 19 * erc-match.el (erc-match-exclude-server-buffer)
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 0fc308621b1..feef75940f3 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -100,6 +100,10 @@
100 "Ignoring certain messages" 100 "Ignoring certain messages"
101 :group 'erc) 101 :group 'erc)
102 102
103(defgroup erc-lurker nil
104 "Hide specified message types sent by lurkers"
105 :group 'erc-ignore)
106
103(defgroup erc-query nil 107(defgroup erc-query nil
104 "Using separate buffers for private discussions" 108 "Using separate buffers for private discussions"
105 :group 'erc) 109 :group 'erc)
@@ -2455,6 +2459,174 @@ See also `erc-make-notice'."
2455 string) 2459 string)
2456 string))) 2460 string)))
2457 2461
2462(defvar erc-lurker-state nil
2463 "Track the time of the last PRIVMSG for each (server,nick) pair.
2464
2465This is implemented as a hash of hashes, where the outer key is
2466the canonicalized server name (as returned by
2467`erc-canonicalize-server-name') and the outer value is a hash
2468table mapping nicks (as returned by `erc-lurker-maybe-trim') to
2469the times of their most recently received PRIVMSG on any channel
2470on the given server.")
2471
2472(defcustom erc-lurker-trim-nicks t
2473 "If t, trim trailing `erc-lurker-ignore-chars' from nicks.
2474
2475This causes e.g. nick and nick` to be considered as the same
2476individual for activity tracking and lurkiness detection
2477purposes."
2478 :group 'erc-lurker
2479 :type 'boolean)
2480
2481(defun erc-lurker-maybe-trim (nick)
2482 "Maybe trim trailing `erc-lurker-ignore-chars' from NICK.
2483
2484Returns NICK unmodified unless `erc-lurker-trim-nicks' is
2485non-nil."
2486 (if erc-lurker-trim-nicks
2487 (replace-regexp-in-string
2488 (format "[%s]"
2489 (mapconcat (lambda (char)
2490 (regexp-quote (char-to-string char)))
2491 erc-lurker-ignore-chars ""))
2492 "" nick)
2493 nick))
2494
2495(defcustom erc-lurker-ignore-chars "`_"
2496 "Characters at the end of a nick to strip for activity tracking purposes.
2497
2498See also `erc-lurker-trim-nicks'."
2499 :group 'erc-lurker
2500 :type 'string)
2501
2502(defcustom erc-lurker-hide-list nil
2503 "List of IRC type messages to hide when sent by lurkers.
2504
2505A typical value would be '(\"JOIN\" \"PART\" \"QUIT\").
2506See also `erc-lurker-p' and `erc-hide-list'."
2507 :group 'erc-lurker
2508 :type 'erc-message-type)
2509
2510(defcustom erc-lurker-threshold-time (* 60 60 24) ; 24h by default
2511 "Nicks from which no PRIVMSGs have been received within this
2512interval (in units of seconds) are considered lurkers by
2513`erc-lurker-p' and as a result their messages of types in
2514`erc-lurker-hide-list' will be hidden."
2515 :group 'erc-lurker
2516 :type 'integer)
2517
2518(defun erc-lurker-initialize ()
2519 "Initialize ERC lurker tracking functionality.
2520
2521This function adds `erc-lurker-update-status' to
2522`erc-insert-pre-hook' in order to record the time of each nick's
2523most recent PRIVMSG as well as initializing the state variable
2524storing this information."
2525 (setq erc-lurker-state (make-hash-table :test 'equal))
2526 (add-hook 'erc-insert-pre-hook 'erc-lurker-update-status))
2527
2528(defun erc-lurker-cleanup ()
2529 "Remove all last PRIVMSG state older than `erc-lurker-threshold-time'.
2530
2531This should be called regularly to avoid excessive resource
2532consumption for long-lived IRC or Emacs sessions."
2533 (maphash
2534 (lambda (server hash)
2535 (maphash
2536 (lambda (nick last-PRIVMSG-time)
2537 (when
2538 (> (time-to-seconds (time-subtract
2539 (current-time)
2540 last-PRIVMSG-time))
2541 erc-lurker-threshold-time)
2542 (remhash nick hash)))
2543 hash)
2544 (if (zerop (hash-table-count hash))
2545 (remhash server erc-lurker-state)))
2546 erc-lurker-state))
2547
2548(defvar erc-lurker-cleanup-count 0
2549 "Internal counter variable for use with `erc-lurker-cleanup-interval'.")
2550
2551(defvar erc-lurker-cleanup-interval 100
2552 "Specifies frequency of cleaning up stale erc-lurker state.
2553
2554`erc-lurker-update-status' calls `erc-lurker-cleanup' once for
2555every `erc-lurker-cleanup-interval' updates to
2556`erc-lurker-state'. This is designed to limit the memory
2557consumption of lurker state during long Emacs sessions and/or ERC
2558sessions with large numbers of incoming PRIVMSGs.")
2559
2560(defun erc-lurker-update-status (message)
2561 "Update `erc-lurker-state' if necessary.
2562
2563This function is called from `erc-insert-pre-hook'. If the
2564current message is a PRIVMSG, update `erc-lurker-state' to
2565reflect the fact that its sender has issued a PRIVMSG at the
2566current time. Otherwise, take no action.
2567
2568This function depends on the fact that `erc-display-message'
2569dynamically binds `parsed', which is used to check if the current
2570message is a PRIVMSG and to determine its sender. See also
2571`erc-lurker-trim-nicks' and `erc-lurker-ignore-chars'.
2572
2573In order to limit memory consumption, this function also calls
2574`erc-lurker-cleanup' once every `erc-lurker-cleanup-interval'
2575updates of `erc-lurker-state'."
2576 (when (and (boundp 'parsed) (erc-response-p parsed))
2577 (let* ((command (erc-response.command parsed))
2578 (sender
2579 (erc-lurker-maybe-trim
2580 (car (erc-parse-user (erc-response.sender parsed)))))
2581 (server
2582 (erc-canonicalize-server-name erc-server-announced-name)))
2583 (when (equal command "PRIVMSG")
2584 (when (>= (incf erc-lurker-cleanup-count) erc-lurker-cleanup-interval)
2585 (setq erc-lurker-cleanup-count 0)
2586 (erc-lurker-cleanup))
2587 (unless (gethash server erc-lurker-state)
2588 (puthash server (make-hash-table :test 'equal) erc-lurker-state))
2589 (puthash sender (current-time)
2590 (gethash server erc-lurker-state))))))
2591
2592(defun erc-lurker-p (nick)
2593 "Predicate indicating NICK's lurking status on the current server.
2594
2595Lurking is the condition where NICK has issued no PRIVMSG on this
2596server within `erc-lurker-threshold-time'. See also
2597`erc-lurker-trim-nicks' and `erc-lurker-ignore-chars'."
2598 (unless erc-lurker-state (erc-lurker-initialize))
2599 (let* ((server
2600 (erc-canonicalize-server-name erc-server-announced-name))
2601 (last-PRIVMSG-time
2602 (gethash (erc-lurker-maybe-trim nick)
2603 (gethash server erc-lurker-state (make-hash-table)))))
2604 (or (null last-PRIVMSG-time)
2605 (> (time-to-seconds
2606 (time-subtract (current-time) last-PRIVMSG-time))
2607 erc-lurker-threshold-time))))
2608
2609(defun erc-canonicalize-server-name (server)
2610 "Returns the canonical network name for SERVER if any,
2611otherwise `erc-server-announced-name'. SERVER is matched against
2612`erc-common-server-suffixes'."
2613 (when server
2614 (or (cdar (erc-remove-if-not
2615 (lambda (net) (string-match (car net) server))
2616 erc-common-server-suffixes))
2617 erc-server-announced-name)))
2618
2619(defun erc-hide-current-message-p (parsed)
2620 "Predicate indicating whether the parsed ERC response PARSED should be hidden.
2621
2622Messages are always hidden if the message type of PARSED appears in
2623`erc-hide-list'. In addition, messages whose type is a member of
2624`erc-lurker-hide-list' are hidden if `erc-lurker-p' returns true."
2625 (let* ((command (erc-response.command parsed))
2626 (sender (car (erc-parse-user (erc-response.sender parsed)))))
2627 (or (member command erc-hide-list)
2628 (and (member command erc-lurker-hide-list) (erc-lurker-p sender)))))
2629
2458(defun erc-display-message (parsed type buffer msg &rest args) 2630(defun erc-display-message (parsed type buffer msg &rest args)
2459 "Display MSG in BUFFER. 2631 "Display MSG in BUFFER.
2460 2632
@@ -2479,7 +2651,7 @@ See also `erc-format-message' and `erc-display-line'."
2479 2651
2480 (if (not (erc-response-p parsed)) 2652 (if (not (erc-response-p parsed))
2481 (erc-display-line string buffer) 2653 (erc-display-line string buffer)
2482 (unless (member (erc-response.command parsed) erc-hide-list) 2654 (unless (erc-hide-current-message-p parsed)
2483 (erc-put-text-property 0 (length string) 'erc-parsed parsed string) 2655 (erc-put-text-property 0 (length string) 'erc-parsed parsed string)
2484 (erc-put-text-property 0 (length string) 'rear-sticky t string) 2656 (erc-put-text-property 0 (length string) 'rear-sticky t string)
2485 (erc-display-line string buffer))))) 2657 (erc-display-line string buffer)))))