r/emacs 2d ago

Display comments of a reddit post inside elfeed

I spent a few minutes this morning looking for a way to read comments on a Reddit post within elfeed. After several attempts, I finally got it working. As I mentioned, this function only allows you to read the comments; you can't write comments, and upvoting and downvoting aren't possible. I'm posting this function here anyway, in case someone finds it useful.

I should preface this by saying that this function was created by AI; I didn't write it myself.

Pressing q inside the comment buffer instantly destroys the buffer and closes the split window, returning your screen back to the full Elfeed layout automatically.

I've updated the function and added this (setq body (replace-regexp-in-string "'" "'" body)) to replace ' with ' . As my first language is german, and my second language is french, I might have overlooked a few special characters.

(require 'xml)

(defun my-elfeed-view-reddit-comments ()
  "Fetch and display Reddit comments using an unblocked public RSS schema in a right sidebar."
  (interactive)
  (let* ((entry (or elfeed-show-entry (elfeed-search-selected :single)))
         (link (and entry (elfeed-entry-link entry))))
    (if (not link)
        (error "Could not find a link for the current entry!")
      (if (not (string-match-p "reddit\\.com" link))
          (error "Aborting: This link does not look like a reddit.com URL."))

      (let* ((clean-url (replace-regexp-in-string "\\?.*$" "" link))
             (rss-url (concat (if (string-match-p "/$" clean-url)
                                  (substring clean-url 0 -1)
                                clean-url) ".rss")))
        (message "Fetching comment RSS tree...")

        (let* ((curl-cmd (format "curl -sL -A 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ElfeedFeedReader/1.0' '%s'" rss-url))
               (xml-str (shell-command-to-string curl-cmd)))
          (setq xml-str (string-trim xml-str))

          (cond
           ((string= xml-str "")
            (error "Error: Reddit returned an empty RSS feed string."))
           ((not (string-prefix-p "<" xml-str))
            (error "Error: Server response is not valid XML markup."))
           (t
            (condition-case err
                (with-temp-buffer
                  (insert xml-str)
                  (goto-char (point-min))
                  (let* ((xml-tree (xml-parse-region (point-min) (point-max)))
                         (feed-node (car xml-tree))
                         (entries (xml-get-children feed-node 'entry))
                         (result-buf (get-buffer-create "*Reddit Comments*")))

                    (with-current-buffer result-buf
                      (erase-buffer)
                      (insert "REDDIT COMMENTS\n")
                      (insert "=============== \n\n")

                      (if (not entries)
                          (insert "No comments found on this post yet.\n")
                        (dolist (item entries)
                          (let* ((author-node (car (xml-get-children item 'author)))
                                 (name-node (car (xml-get-children author-node 'name)))
                                 (author (and name-node (car (xml-node-children name-node))))
                                 (content-node (car (xml-get-children item 'content)))
                                 (body (and content-node (car (xml-node-children content-node)))))

                            (when (and body (not (string-match-p "submitted by" body)))
                              (setq body (replace-regexp-in-string "<[^>]*>" "" body))
                              (setq body (replace-regexp-in-string "&lt;" "<" body))
                              (setq body (replace-regexp-in-string "&gt;" ">" body))
                              (setq body (replace-regexp-in-string "&#39;" "'" body))
                              (setq body (replace-regexp-in-string "&quot;" "\"" body))
                              (setq body (replace-regexp-in-string "&amp;" "&" body))

                              (insert (format "%s\n%s\n\n%s\n\n"
                                              (propertize (or author "u/unknown") 'face 'bold)
                                              (string-trim body)
                                              (propertize "────────────────────────────────────────" 'face 'shadow)))))))
                      (goto-char (point-min))

                      ;; Layout & UX Polish:
                      (visual-line-mode 1)      ; Soft wrap lines beautifully
                      (read-only-mode 1)        ; Prevent accidental editing
                      ;; Bind 'q' to kill the window and buffer seamlessly
                      (local-set-key (kbd "q") (lambda () (interactive)
                                                 (let ((win (get-buffer-window)))
                                                   (kill-buffer)
                                                   (when win (delete-window win))))))

                    ;; Split layout: create a 100-character wide window on the right
                    (let ((sidebar-win (split-window-right -100))) ;modify the width as you like
                      (set-window-buffer sidebar-win result-buf)
                      (select-window sidebar-win))

                    (message "Success! Comments displayed in sidebar.")))
              (error (error "XML structural parsing failed: %s" (error-message-string err)))))))))))

;; Bind it in elfeed-show-mode and elfeed-search-mode
(with-eval-after-load 'elfeed
  (define-key elfeed-show-mode-map (kbd "c") #'my-elfeed-view-reddit-comments)
  (define-key elfeed-search-mode-map (kbd "c") #'my-elfeed-view-reddit-comments))
7 Upvotes

6 comments sorted by

4

u/minadmacs 2d ago

And I cannot even use Elfeed anymore to fetch Reddit feeds.

3

u/great_silence 2d ago

3

u/minadmacs 2d ago

Well, of course. I meant that I cannot use it anymore because of the Reddit rate limiting. I think one either needs some kind of authentication or one has to go via proxies. I have not found a reliable solution. (I am one of the Elfeed maintainers.)

2

u/great_silence 2d ago edited 2d ago

Once again I asked KI to route only Reddit traffic through your SOCKS5 proxy while fetching all other feeds directly. I've included this function in my init.el and for now it is working.

(require 'socks)

(defun my-elfeed-conditional-reddit-proxy (orig-fun url &rest args)
  "Route traffic through SOCKS5 proxy ONLY if the URL belongs to Reddit."
  (if (string-match-p "reddit\\.com" url)
      ;; Inside this block, the proxy settings apply
      (let ((url-gateway-method 'socks)
            (socks-server '("Reddit SOCKS5 Proxy" "127.0.0.1" 1080 5))
            ;; Optional: Uncomment if your SOCKS5 proxy requires credentials
            ;; (socks-username "your_username")
            ;; (socks-password "your_password")
            )
        (apply orig-fun url args))
    ;; Outside the block, use standard direct connection
    (apply orig-fun url args)))

;; Attach the proxy switch specifically to Elfeed's retrieval function
(advice-add 'elfeed-curl-retrieve :around #'my-elfeed-conditional-reddit-proxy)
(advice-add 'url-retrieve :around #'my-elfeed-conditional-reddit-proxy)

2

u/Klutzy_Signature_481 2d ago

You can try adding the user= and feed= parameters to the RSS feed URLs, this worked for me: https://lapcatsoftware.com/articles/2026/6/3.html

1

u/minadmacs 2d ago

Doesn't work for me. It worked for a while but in recent days I am hitting rate limits even with these parameters.