Elfeed

Table of Contents

1. Description

Elfeed is an Emacs web feeds client

2. Configuration

2.1. Configure elfeed package

(use-package elfeed
  :ensure t
  :bind (("C-c e" . elfeed)

         :map elfeed-search-mode-map
         ("SPC" . alan-elfeed-search-tag-toggle-unread)
         ("/" . alan-elfeed-search-tag-filter)
         ("a" . elfeed-search-untag-all-unread)
         ("d" . alan-elfeed-download-video-at-point)
         ("f" . alan-elfeed-search-feed-filter)
         ("F" . alan-elfeed-search-feed-filter-at-point)
         ("h" . elfeed-search-quit-window)
         ("i" . alan-elfeed-mpv-image-at-point)
         ("I" . alan-elfeed-search-jump-to-filters)
         ("J" . alan-elfeed-search-jump-to-feed-at-point)
         ("j" . next-line)
         ("k" . previous-line)
         ("L" . alan-elfeed-search-jump-to-log-buffer)
         ("l" . elfeed-search-show-entry)
         ("o" . alan-elfeed-browse-link-at-point)
         ("r" . nil)
         ("s" . alan-elfeed-search-tag-filter)
         ("t" . alan-elfeed-search-tag-filter)
         ("U" . alan-elfeed-search-jump-to-feed-at-point)
         ("u" . elfeed-search-tag-all-unread)
         ("W" . alan-elfeed-mpv-video-at-point)
         ("y" . alan-elfeed-search-copy-link)

         :map elfeed-show-mode-map
         ("<backtab>" . alan-shr-previous-link)
         ("<tab>" . alan-shr-next-link)
         ("TAB" . alan-shr-next-link)
         ("d" . alan-elfeed-download-video-at-point)
         ("h" . elfeed-kill-buffer)
         ("i" . alan-elfeed-mpv-image-at-point)
         ("j" . next-line)
         ("k" . previous-line)
         ("o" . alan-elfeed-browse-link-at-point)
         ("W" . alan-elfeed-mpv-video-at-point)
         ("y" . alan-elfeed-show-copy-link))

  :custom
  (elfeed-db-directory (locate-user-emacs-file "elfeed/"))
  (elfeed-enclosure-default-dir "~/downloads/")
  (elfeed-search-date-format '("%d %b %R" 14 :left))
  (elfeed-search-filter "@2-weeks-ago +unread")
  (elfeed-search-title-max-width 145)
  (elfeed-show-unique-buffers t)
  (elfeed-use-curl t)
  (elfeed-curl-extra-arguments
   '("--proxy" "socks5h://127.0.0.1:13207"))
  (elfeed-feeds
   '(
     ("https://example.org/rss" tag1 tag2)
     ))

  :config
  (add-hook 'elfeed-new-entry-hook
            (elfeed-make-tagger :before "2 weeks ago"
                                :remove 'unread))
  (add-hook 'elfeed-new-entry-hook
            (elfeed-make-tagger :entry-title "\\(?:firefox\\|manifest\\|mozilla\\|ublock\\)"
                                :add 'firefox))

  (when (and (boundp evil-mode) evil-mode)
    (evil-set-initial-state 'elfeed-search-mode 'emacs)
    (evil-set-initial-state 'elfeed-show-mode 'emacs))

  (require 'alan-elfeed))

2.1.1. SOCKS5 Proxy

Using curl(1) to proxy the traffic is not enough since images within articles are not using curl.

(use-package elfeed
  :custom
  (elfeed-curl-extra-arguments '("--proxy" "socks5h://127.0.0.1:13207"))
  ;; OR ...
  :init
  (setenv "ALL_PROXY" "socks5h://127.0.0.1:13207"))

2.2. Configure elfeed-score package

elfeed-score brings Gnus-style scoring to Elfeed

(use-package elfeed-score
  :after elfeed
  :ensure t
  :config
  (defun alan-elfeed-score-load-score-file ()
    (interactive)
    (elfeed-score-load-score-file elfeed-score-serde-score-file))
  (elfeed-score-enable))

3. How to use Elfeed score

Info: elfeed-score Website: https://www.unwoundstack.com/doc/elfeed-score/curr

This will set the score of every articles from Feed Author to +10 in the feed titled Feed Title with tag1 as tag and reduce by -10 every other articles within that feed, mark 0 will set the score of every non-matching articles to 0.

(("authors"
  (:text "Feed Author" :value 10 :type W :tags (t tag1) :feeds (t . (t S "Feed Title"))))
 ("feed"
  (:text "Feed Title" :value -10 :type S :tags (t tag1) :attr t))
 (mark 0))

Find the score of an entry with M-x elfeed-score-get-score

  1. Run M-x elfeed-score-load-score-file RET ~/path/to/efleed.score to refresh the rules
  2. Check if the selected entries are matching something M-x elfeed-score-explain
  3. To set the score value on selected entries M-x elfeed-score-score

3.1. Elfeed score file template

;; #+begin_src emacs-lisp :tangle ~/.emacs.d/elfeed.score
(("authors"
  (:text "ARTICLE_AUTHOR_CASE_SENSITIVE_SUBSTRING" :value 10 :type S :feeds (t . (t S "FEED_TITLE_CASE_SENSITIVE_SUBSTRING"))))
 ("feed"
  (:text "FEED_TITLE_CASE_SENSITIVE_WORD" :value 5 :type W :tags (t TAG) :attr t :comment "Add 5 points to feeds tagged TAG and title that contains WORD")
  (:text "FEED_URL_SUBSTRING" :value 20 :type s :tags (t TAG_1 TAG_2) :attr u)
 ("link"
  (:text "\\(ARTICLE_LINK_REGEXP\\|ARTICLE_LINK_REGEXP\\)" :value -10 :type r :tags (t TAG) :feeds (t . (t s "FEED_TITLE_SUBSTRING"))))
 ("tag"
  (:tags (nil . TAG) :value -5 :comment "Remove 5 points from entries not tagged TAG")
  (:tags (t . TAG) :value 10 :comment "Add 10 points for entries tagged TAG"))
 ("title"
  (:text "ARTICLE_TITLE_WORD" :value -5 :type w :tags (nil TAG) :comment "Remove 5 points from entries not tagged TAG and title containing WORD")
  (:text "ARTICLE_TITLE_REGEXP" :value 10 :type r :tags (t TAG_1 TAG_2) :feeds (t . (u R "FEED_URL_CASE_SENSITIVE_REGEXP")))
  (:text "ARTICLE_TITLE_CASE_SENSITIVE_SUBSTRING" :value 10 :type S :tags (t TAG) :feeds (t . (t W "FEED_TITLE_CASE_SENSITIVE_WORD"))))
 ("content"
  :text "ARTICLE_CONTENT_CASE_SENSITIVE_REGEXP" :value -5 :type R :feeds (t . (u r "FEED_URL_REGEXP")))
 ("title-or-content"
  (:text "ARTICLE_TITLE_OR_CONTENT_REGEXP" :title-value 50 :content-value 45 :type r :tags (t TAG) :feeds (t . ((t S "FEED_URL_CASE_SENSITIVE_SUBSTRING")))))
 (mark 0))

3.2. :attr

Determines the attribute of the feed against which this rule’s text will be matched.

Symbol Description
a Author
t Title
u URL

3.3. :type

Symbol Description
s case-insensitive substring match
S case-sensitive substring match
r case-insensitive regexp match
R case-sensitive regexp match
w case-insensitive whole word match
W case-sensitive whole word match

3.4. :feeds

(boolean . ((attr match-type match-text)...))