emacs-opml-to-elfeed-feeds

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | LICENSE

commit c96e27f23406354be080776ce77a2ba8bf0c706d
parent 218d60b2690051456f90f26bac865858322465cc
Author: Yuval Langer <yuval.langer@gmail.com>
Date:   Wed, 26 Jun 2024 14:10:38 +0300

Add functions and customization variables for more than one OPML.

Diffstat:
Mget-craftering-opml.el | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
1 file changed, 84 insertions(+), 32 deletions(-)

diff --git a/get-craftering-opml.el b/get-craftering-opml.el @@ -28,19 +28,33 @@ ;;; Code: -(defcustom gco--craftering-url - "https://craftering.systemcrafters.net/Craftering.opml" - "Craftering OPML address." +(defcustom gco-opml-list + '(("https://craftering.systemcrafters.net/Craftering.opml" blog craftering) + ("https://planet.debian.org/opml.xml" blog debian planet)) + "A list holding the OPML URLs. + +Each member is either a string or the URL, or a list with the URL +as the first member and optional tags. + +The tags would be attached to each feed in the OPML file." + :type + '(repeat (choice string + (cons string (repeat symbol))))) + +(defcustom gco-elfeed-feeds + '() + "The GCO `elfeed-feeds'." :type - '(string)) + '(repeat (choice string + (cons string (repeat symbol))))) (defun gco--blogger-name-to-symbol (blogger-name) (intern (downcase (replace-regexp-in-string "[ .]+" "-" blogger-name)))) -(defun gco--get-response-buffer () - (url-retrieve-synchronously gco--craftering-url)) +(defun gco--get-response-buffer (opml-url) + (url-retrieve-synchronously opml-url)) (defun gco--url-response-body-position (response-buffer) (with-current-buffer response-buffer @@ -56,7 +70,7 @@ (t (loop (1+ position))))))) -(defun gco--parse-response-buffer-opml (response-buffer) +(defun gco--parse-response-buffer-to-xml (response-buffer) (with-current-buffer response-buffer (let ((beg (gco--url-response-body-position response-buffer)) (end (buffer-end 1))) @@ -64,30 +78,48 @@ end response-buffer)))) -(defun gco--response-buffer-to-elfeed-feed (response-buffer) - (let ((xml (gco--parse-response-buffer-opml response-buffer))) - (pcase xml - (`((opml . ,rest-of-opml)) - (let ((body (assq 'body rest-of-opml))) - (pcase body - ;; TODO: What the hell is this? - (`(body ,TODO-WHAT-THE-HELL-IS-THIS? . ,outlines) - (named-let loop ((outlines outlines) - (accumulator '())) - (pcase outlines - ('() - accumulator) - (`((outline . (,outline-values)) . ,rest-of-outlines) - (let ((text (cdr (assq 'text - outline-values))) - (xml-url (cdr (assq 'xmlUrl - outline-values)))) - (loop rest-of-outlines - (cons (list xml-url - 'blog - 'craftering - (gco--blogger-name-to-symbol text)) - accumulator))))))))))))) +(defun gco--xml-to-opml-outlines (xml) + (pcase xml + (`((opml . ,rest-of-opml)) + (let ((body (assq 'body rest-of-opml))) + (pcase body + ;; TODO: What the hell is this? + (`(body ,TODO-WHAT-THE-HELL-IS-THIS? . ,outlines) + outlines)))))) + +(cl-defun gco--response-buffer-to-elfeed-feed (response-buffer &key (tags '())) + (let* ((xml (gco--parse-response-buffer-to-xml response-buffer)) + (outlines (gco--xml-to-opml-outlines xml))) + (named-let loop ((outlines outlines) + (accumulator '())) + (cond + ((null outlines) + accumulator) + ((and (consp (car outlines)) + (eq (caar outlines) + 'outline)) + (let* ((outline-values (cadar outlines)) + (rest-of-outlines (cdr outlines)) + (text (cdr (assq 'text + outline-values))) + (xml-url (cdr (assq 'xmlUrl + outline-values))) + (blogger-name-tag (gco--blogger-name-to-symbol text)) + (elfeed-feed-entry (append (list xml-url) + (elfeed-normalize-tags + (list blogger-name-tag) + tags)))) + (cond + ((string-empty-p xml-url) + (loop rest-of-outlines + accumulator)) + (t + (loop rest-of-outlines + (cons elfeed-feed-entry + accumulator)))))) + ((stringp (car outlines)) + (loop (cdr outlines) + accumulator)))))) (defun gco--elfeed-feeds-entry-url (elfeed-feeds-entry) "Takes an `elfeed-feeds' kind of entry as ELFEED-FEEDS-ENTRY and return its URL." @@ -117,7 +149,7 @@ patch if you know." (sort (hash-table-keys hash-table) 'string<))) -(defun gco--deduplicate-elfeed-feeds (elfeed-feeds) +(defun gco--normalise-elfeed-feeds (elfeed-feeds) (let (;; XXX: Pass ":test 'equal" into make-hash-table so that ;; string comparisons work, otherwise it'll put many of the ;; same string as keys, each with its own values, like: @@ -142,6 +174,26 @@ patch if you know." (loop rest-of-entries))))) (gco--hash-table-to-alist hash))) +(defun gco--update-gco-efleed-feeds () + (named-let loop ((opml-list (reverse gco-opml-list)) + (our-elfeed-feeds '())) + (pcase opml-list + ('() + our-elfeed-feeds) + (`(,opml-list-entry . ,rest-of-opml-list) + (let* ((url+tags (cond + ((stringp opml-list-entry) + (list opml-list-entry)) + ((and (consp opml-list-entry) + (stringp (car opml-list-entry))) + opml-list-entry))) + (url (car url+tags)) + (tags (cdr url+tags)) + (response-buffer (gco--get-response-buffer url))) + (loop rest-of-opml-list + (append (gco--response-buffer-to-elfeed-feed response-buffer :tags tags) + our-elfeed-feeds))))))) + (provide 'get-craftering-opml) ;; Local Variables: