Initial commit of elfeed-prune
This commit is contained in:
commit
8e11981987
1 changed files with 165 additions and 0 deletions
165
elfeed-prune.el
Normal file
165
elfeed-prune.el
Normal file
|
@ -0,0 +1,165 @@
|
|||
;;; elfeed-prune.el --- Elfeed database pruning -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2024 Bram Schoenmakers
|
||||
|
||||
;; Author: Bram Schoenmakers <me@bramschoenmakers.nl>
|
||||
;; Maintainer: Bram Schoenmakers <me@bramschoenmakers.nl>
|
||||
;; Created: 1 July 2024
|
||||
;; Package-Version: 0.1
|
||||
;; Package-Requires: ((emacs "29.1"))
|
||||
;; Keywords:
|
||||
;; URL:
|
||||
|
||||
;; This file is not part of GNU Emacs.
|
||||
|
||||
;; MIT License
|
||||
|
||||
;; Copyright (c) 2024 Bram Schoenmakers
|
||||
|
||||
;; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
;; of this software and associated documentation files (the "Software"), to deal
|
||||
;; in the Software without restriction, including without limitation the rights
|
||||
;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
;; copies of the Software, and to permit persons to whom the Software is
|
||||
;; furnished to do so, subject to the following conditions:
|
||||
|
||||
;; The above copyright notice and this permission notice shall be included in all
|
||||
;; copies or substantial portions of the Software.
|
||||
|
||||
;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
;; SOFTWARE.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'elfeed)
|
||||
|
||||
(defcustom elfeed-prune-enabled nil
|
||||
"Set to t to perform actual pruning on the database.
|
||||
|
||||
This boolean serves as a safety pin, because the elfeed database
|
||||
was not designed to have items removed. By setting this boolean
|
||||
to t you are aware of the risks."
|
||||
:group 'elfeed-prune
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom elfeed-prune-days-read 90
|
||||
"Read items older than this amount of days will be pruned."
|
||||
:group 'elfeed-prune
|
||||
:type 'natnum)
|
||||
|
||||
(defcustom elfeed-prune-days-unread 30
|
||||
"Unread items older than this amount of days will be pruned."
|
||||
:group 'elfeed-prune
|
||||
:type 'natnum)
|
||||
|
||||
(defcustom elfeed-prune-gc t
|
||||
"Run `elfeed-db-gc' to remove stale content from disk."
|
||||
:group 'elfeed-prune
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom elfeed-prune-predicate #'elfeed-prune--elfeed-prune-entry-p
|
||||
"Function that determines which entries should be pruned.
|
||||
|
||||
The function accepts two parameters: the entry and the feed it
|
||||
belongs to. These are the data structures defined in the
|
||||
elfeed-db.el package.
|
||||
|
||||
Look inside `elfeed-prune--elfeed-prune-entry-p' for examples of
|
||||
using these data structures. Otherwise consult the elfeed-db.el
|
||||
sources."
|
||||
:group 'elfeed-prune
|
||||
:type 'function)
|
||||
|
||||
(defun elfeed-prune--entry-too-old-p (entry)
|
||||
"Return t if the given ENTRY is considered too old.
|
||||
|
||||
The thresholds are configured through the variables
|
||||
`elfeed-prune-days-read' and `elfeed-prune-days-unread'."
|
||||
(let* ((current-time (float-time))
|
||||
(entry-time (elfeed-entry-date entry))
|
||||
(unread-p (seq-contains-p (elfeed-entry-tags entry) 'unread))
|
||||
(threshold-days (if unread-p
|
||||
elfeed-prune-days-unread
|
||||
elfeed-prune-days-read))
|
||||
(threshold-seconds (* 60 60 24 threshold-days))
|
||||
(entry-age (- current-time entry-time)))
|
||||
(> entry-age threshold-seconds)))
|
||||
|
||||
(defun elfeed-prune--elfeed-prune-entry-p (entry feed)
|
||||
"Return t if the ENTRY should be removed from the database.
|
||||
|
||||
FEED can be used to remove entries for a whole feed.
|
||||
|
||||
Conditions, any of:
|
||||
- non-existing feed (not in `elfeed-feeds')
|
||||
- has tag `rm'
|
||||
- older than 90 days
|
||||
|
||||
Unless:
|
||||
- score > 2
|
||||
- has star tag"
|
||||
(let ((tags (elfeed-entry-tags entry))
|
||||
(score (elfeed-score-scoring-get-score-from-entry entry)))
|
||||
(and (or (seq-contains-p tags 'rm)
|
||||
(elfeed-prune--entry-too-old-p entry)
|
||||
(not (seq-contains-p (mapcar #'car elfeed-feeds)
|
||||
(elfeed-feed-url feed)
|
||||
#'string=))
|
||||
(<= score -5))
|
||||
(not (> score 2))
|
||||
(not (seq-contains-p tags 'star)))))
|
||||
|
||||
(defun elfeed-prune (&optional dry-run)
|
||||
"Prune the database entries.
|
||||
|
||||
Entries for which `elfeed-prune--elfeed-prune-entry-p' returns t are
|
||||
removed from the database.
|
||||
|
||||
When DRY-RUN in non-nil, no actual pruning will be done, but the
|
||||
number of items that would be removed will be shown in the echo
|
||||
area."
|
||||
(interactive "P")
|
||||
(elfeed-db-ensure)
|
||||
(let ((total-entries (hash-table-count elfeed-db-entries))
|
||||
(removed-entries 0)
|
||||
;; Make a copy so we don't iterate over a changing data structure
|
||||
;; Also useful to gather stats in a dry run.
|
||||
(elfeed-db-index-copy (avl-tree-copy elfeed-db-index))
|
||||
(elfeed-db-entries-copy (copy-hash-table elfeed-db-entries)))
|
||||
;; Remove entries
|
||||
(with-elfeed-db-visit (entry feed)
|
||||
;; The `with-elfeed-db-visit' declares the variable `id' that
|
||||
;; contains the entry ID.
|
||||
(when (funcall elfeed-prune-predicate entry feed)
|
||||
(setq removed-entries (1+ removed-entries))
|
||||
(avl-tree-delete elfeed-db-index-copy id)
|
||||
(remhash id elfeed-db-entries-copy)))
|
||||
(when (and
|
||||
elfeed-prune-enabled
|
||||
(not dry-run)
|
||||
(< 0 removed-entries))
|
||||
(setf (plist-get elfeed-db :index) elfeed-db-index-copy)
|
||||
(setf elfeed-db-index (plist-get elfeed-db :index))
|
||||
(setf (plist-get elfeed-db :entries) elfeed-db-entries-copy)
|
||||
(setf elfeed-db-entries (plist-get elfeed-db :entries))
|
||||
(elfeed-db-set-update-time)
|
||||
(elfeed-db-save-safe)
|
||||
(when elfeed-prune-gc
|
||||
(elfeed-db-gc-safe)))
|
||||
(if (or dry-run (not elfeed-prune-enabled))
|
||||
(message "Would remove %d/%d elfeed entries [dry run]"
|
||||
removed-entries
|
||||
total-entries)
|
||||
(message "Removed %d/%d elfeed entries"
|
||||
removed-entries
|
||||
total-entries))))
|
||||
|
||||
(provide 'elfeed-prune)
|
||||
;;; elfeed-prune.el ends here
|
Loading…
Reference in a new issue