From fac63f9fe3cc4ea4c71ab1ba8a260aa63b73a81a Mon Sep 17 00:00:00 2001 From: Jaidyn Levesque <10477760+JadedCtrl@users.noreply.github.com> Date: Fri, 18 Nov 2022 21:48:35 -0600 Subject: [PATCH] Better templates/templating, `write-entr[y|ies]` Now entries can be written to a file-path, with feedsnake-unix. Single-file formats supported (including built-in mbox). Templating is more flexible for feedsnake itself. --- feedsnake.scm | 175 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 140 insertions(+), 35 deletions(-) diff --git a/feedsnake.scm b/feedsnake.scm index 5f0b427..c1de956 100644 --- a/feedsnake.scm +++ b/feedsnake.scm @@ -18,7 +18,22 @@ (load "date-strings.scm") (load "named-format.scm") +;; Misc helper functions used in both feedsnake and feedsnake-unix +(module feedsnake-helpers + (alist-car-ref) +(import scheme + (chicken base)) + +;; Just car's the value of alist-ref (if it exists) +(define (alist-car-ref key alist) + (let ([value (alist-ref key alist)]) + (if value + (car value) + #f)))) + + +;; The main feedsnake module; parses atom feeds into alists and strings (module feedsnake (updated-feed-string read-feed entries-since entry->string) @@ -26,6 +41,7 @@ (chicken base) (chicken condition) (chicken io) (chicken port) srfi-1 srfi-19 srfi-69 date-strings + feedsnake-helpers http-client named-format atom rss) @@ -72,49 +88,71 @@ (define (entry->string entry template) (named-format template - (entry-string-templating-parameters entry template))) + (append entry + (entry-templating-parameters entry template)))) ;; Returns an alist of string replacements/parameters for a given entry ;; For use with named-format -(define (entry-string-templating-parameters entry template) - (let* ([alist-car - (lambda (key alist) - (let ([value (alist-ref key alist)]) - (if value - (car value))))] - [updated (or (alist-car 'updated entry) (alist-car 'published entry))] - [published (or (alist-car 'published entry) updated)] - [urls (alist-car 'url entry)]) - `((title ,(alist-car 'title entry)) - (updated ,(if updated (date->rfc228-string updated))) - (published ,(if published (date->rfc228-string published))) - (summary ,(alist-car 'summary entry)) - (url ,(cond +(define (entry-templating-parameters entry template) + (append + entry + (entry-url-templating-parameters entry) + (entry-author-templating-parameters entry) + (entry-date-templating-parameters entry))) + + +;; URL-related named-format templating parameters for given entry +(define (entry-url-templating-parameters entry) + (let ([urls (alist-car-ref 'urls entry)]) + `((url ,(cond [(list? urls) (car urls)] - [(string? urls) urls])) - (urls ,(cond - [(list? urls) urls] - [(string? urls) (list urls)]))))) + [(string? urls) urls]))))) + + +;; Author-related named-format templating parameters for given entry +(define (entry-author-templating-parameters entry) + (let* ([authors (alist-car-ref 'authors entry)] + [author (if authors (car authors) (alist-car-ref 'feed-title entry))]) + `((author ,author)))) + + +;; Date-related named-format templating parameters for given entry +(define (entry-date-templating-parameters entry) + (let* ([updated (or (alist-car-ref 'updated entry) (alist-car-ref 'published entry))] + [published (or (alist-car-ref 'published entry) updated)]) + `((updated-rfc228 ,(if updated (date->rfc228-string updated))) + (published-rfc228 ,(if published (date->rfc228-string published))) + (updated-mbox ,(if updated (date->mbox-string updated))) + (published-mbox ,(if published (date->mbox-string published)))))) ;; Parse an atom feed into a feedsnake-friendly alist (define (atom-doc->feedsnake-feed atom) `((title ,(last (feed-title atom))) + (urls ,(feed-links atom)) + (authors ,(map author-name (feed-authors atom))) (updated ,(feed-updated atom)) (entry-updated ,(atom-feed-latest-entry-date atom)) - (entries ,(map atom-entry->feedsnake-entry (feed-entries atom))))) + (entries ,(map + (lambda (entry) + (atom-entry->feedsnake-entry entry atom)) + (feed-entries atom))))) ;; Parse an atom entry into a feedsnake entry :> -(define (atom-entry->feedsnake-entry entry) +(define (atom-entry->feedsnake-entry entry atom) (let ([published (rfc339-string->date (entry-published entry))] - [updated (rfc339-string->date (entry-updated entry))]) + [updated (rfc339-string->date (entry-updated entry))] + [feed-authors (map author-name (feed-authors atom))] + [entry-authors (map author-name (entry-authors entry))]) `((title ,(last (entry-title entry))) (updated ,(or updated published)) (published ,(or published updated)) (summary ,(last (entry-summary entry))) - (url ,(map link-uri (entry-links entry)))))) + (urls ,(map link-uri (entry-links entry))) + (authors ,(if (null? entry-authors) feed-authors entry-authors)) + (feed-title ,(feed-title atom))))) ;; Get an atom feed's latest date for an entry's updating/publishing @@ -142,17 +180,94 @@ ;; The UNIX-style frontend for feedsnake (module feedsnake-unix - (update-feed-file latest-entries feed-files) + (update-feed-file latest-entries all-entries write-entry write-entries feed-files *mbox-template*) (import scheme (chicken base) (chicken condition) (chicken file) (chicken io) (chicken process-context) (chicken process-context posix) srfi-1 srfi-19 date-strings - feedsnake + feedsnake feedsnake-helpers xattr) +(define *maildir-template* + `((entry-template + ,(string-append + "From: ~{{~A ||||from-name}}" + "<~{{~A||feedsnake||FROM_USER||author-user||feed-title}}" + "@" + "~{{~A||localhost||FROM_HOST||author-domain||feed-domain}}>" + "\n" + "To:~{{ ~A ||You||TO_NAME||USER}}" + "<~{{~A||you||TO_USER||USER}}" + "@" + "~{{~A||localhost||TO_HOST||HOSTNAME}}>" + "\n" + "Subject: ~{{~A||Unnamed post||title}}\n" + "Date: ~{{~A||||updated||published}}\n" + "\n" + "~{{~{~a~^, ~}~%***~%||||urls}}\n" + "~{{~A||||summary}}\n")) + (multifile-output? #t))) + + +(define *mbox-template* + `((entry-template ,(string-append + "From FEEDSNAKE ~{{~A||||updated-mbox||published-mbox}}\n" + (car (alist-ref 'entry-template *maildir-template*)) + "\n")) + (multifile-output? #f))) + + +(define *html-template* + `((entry-template + "
~{{~A||No summary||summary}}