aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuchen Pei <id@ypei.org>2025-08-31 19:27:01 +1000
committerYuchen Pei <id@ypei.org>2025-08-31 19:27:01 +1000
commit8b4937149fe396ed5c4a38fba063b730ec80a4ae (patch)
tree47a7836cd0405764b31bc31bfeecd40907e8114e
parent966bed8c8893980845f9b4c0cd8bb21481b1ec2a (diff)
[emacs] Save ttrss articles locally
-rw-r--r--emacs/.emacs.d/init/ycp-web.el4
-rw-r--r--emacs/.emacs.d/lisp/my/my-ttrss.el156
2 files changed, 137 insertions, 23 deletions
diff --git a/emacs/.emacs.d/init/ycp-web.el b/emacs/.emacs.d/init/ycp-web.el
index 4045777..c43aae6 100644
--- a/emacs/.emacs.d/init/ycp-web.el
+++ b/emacs/.emacs.d/init/ycp-web.el
@@ -405,6 +405,8 @@
(my-package ttrss
(:delay 60)
- (my-setq-from-local ttrss-address ttrss-user ttrss-password))
+ (my-setq-from-local ttrss-address ttrss-user ttrss-password)
+ (require 'my-ttrss)
+ (my-setq-from-local my-ttrss-dir))
(provide 'ycp-web)
diff --git a/emacs/.emacs.d/lisp/my/my-ttrss.el b/emacs/.emacs.d/lisp/my/my-ttrss.el
index 3695411..3cf6856 100644
--- a/emacs/.emacs.d/lisp/my/my-ttrss.el
+++ b/emacs/.emacs.d/lisp/my/my-ttrss.el
@@ -28,17 +28,97 @@
(require 'ttrss)
-(defun my-ttrss-fetch (n)
- "Fetch N articles."
- (let ((ttrss-sid (ttrss-login ttrss-address ttrss-user ttrss-password)))
- (if (ttrss-logged-in-p ttrss-address ttrss-sid)
+;;; TODO: my-ttrss-save-recent
+
+(defun my-ttrss-hello ()
+ (let ((sid (ttrss-login ttrss-address ttrss-user ttrss-password)))
+ (message "Server running version %s and API level %d\n"
+ (ttrss-get-version ttrss-address sid)
+ (ttrss-get-api-level ttrss-address sid))
+ (message "There are %s unread articles in %d feeds"
+ (ttrss-get-unread ttrss-address sid)
+ (length (ttrss-get-feeds ttrss-address sid :unread_only t)))))
+
+(defun my-ttrss-fetch-feeds ()
+ (let ((sid (ttrss-login ttrss-address ttrss-user ttrss-password)))
+ (ttrss-get-feeds ttrss-address sid :cat_id -3)))
+
+(defun my-ttrss-feed-dir (feed-title feed-id)
+ (file-name-concat
+ my-ttrss-dir
+ (my-make-doc-file-name
+ (format "%s [ttrss%s]" feed-title feed-id))))
+
+(defun my-ttrss-feed-last-id-file (feed-info)
+ (let* ((title (plist-get feed-info :title))
+ (id (plist-get feed-info :id)))
+ (expand-file-name
+ (file-name-concat (my-ttrss-feed-dir title id) "last-id"))))
+
+(defun my-ttrss-feed-get-last-id (feed-info)
+ (let* ((file (my-ttrss-feed-last-id-file feed-info)))
+ (if (file-exists-p file)
+ (with-temp-buffer
+ (insert-file-contents file)
+ (string-to-number (buffer-string)))
+ 0)))
+
+(defun my-ttrss-feed-write-last-id (feed-info last-id)
+ (let* ((file (my-ttrss-feed-last-id-file feed-info))
+ (inhibit-message t))
+ (with-temp-buffer
+ (insert (format "%d" last-id))
+ (write-file file))))
+
+(defun my-ttrss-fetch ()
+ "Fetch and save latest articles from all feeds."
+ (interactive)
+ (let* ((sid (ttrss-login ttrss-address ttrss-user ttrss-password))
+ (feeds (ttrss-get-feeds ttrss-address sid :cat_id -3))
+ (n (length feeds)))
+ (seq-do-indexed
+ (lambda (feed i)
+ (my-ttrss-fetch-feed-articles
+ sid feed
+ (format "[my-ttrss] (%d/%d) Fetching articles from %s..."
+ (1+ i) n (plist-get feed :title))))
+ feeds)))
+
+(defun my-ttrss-fetch-feed-articles (sid feed &optional message-head)
+ (unless message-head
+ (setq message-head
+ (format "[my-ttrss] Fetching articles from %s..."
+ (plist-get feed :title))))
+ (message "%s" message-head)
+ (let ((articles
+ (ttrss-get-headlines
+ ttrss-address sid
+ :feed_id (plist-get feed :id) :show_content t :include_attachments t
+ :since_id (my-ttrss-feed-last-id feed))))
+ (seq-do 'my-ttrss-save-article articles)
+ (unless (seq-empty-p articles)
+ (my-ttrss-feed-write-last-id feed (plist-get (elt articles 0) :id)))
+ (message
+ "%s Done - total %d articles"
+ message-head (length articles))))
+
+(defun my-ttrss-fetch-latest-articles (n &optional since-id)
+ "Fetch N latest articles."
+ (let ((sid (ttrss-login ttrss-address ttrss-user ttrss-password)))
+ (unless since-id (setq since-id 0))
+ (if (ttrss-logged-in-p ttrss-address sid)
(ttrss-get-headlines
- ttrss-address ttrss-sid
- :feed_id -4 :limit n :show_content t :include_attachments t)
+ ttrss-address sid
+ :feed_id -4 :limit n :show_content t :include_attachments t
+ :since_id since-id)
(message "Login failed"))))
(defun my-ttrss-save-article (info)
(with-temp-buffer
+ (insert "<!--\n Page saved with my-ttrss on "
+ (current-time-string) "\n"
+ (json-serialize (org-plist-delete info :content))
+ "\n-->\n")
(insert "<h2>" "<a href=\"" (plist-get info :link) "\">"
(plist-get info :title) "</a>" "</h2>")
(insert "<p>" "<a href=\"" (plist-get info :site_url) "\">"
@@ -56,25 +136,57 @@
(unless (seq-empty-p tags)
(insert "<p>tags: " (string-join tags ";") "</p>")))
(insert (plist-get info :content))
- (let ((change-major-mode-with-file-name nil))
- (write-file (my-ttrss-format-file-name info)))))
+ (let ((attached (plist-get info :attachments)))
+ (unless (seq-empty-p attached)
+ (insert "<p>Article attachments:</p>\n<ul>")
+ (seq-do (lambda (at)
+ (let ((title (plist-get at :title))
+ (url (plist-get at :content_url)))
+ (insert "\n<li><a href=" url ">"
+ (if (string-empty-p title) url title)
+ "</a></li>")))
+ attached)
+ (insert "\n</ul>")))
+ (let* ((change-major-mode-with-file-name nil)
+ (coding-system-for-write 'utf-8)
+ (inhibit-message t)
+ (file-name (my-ttrss-format-file-name info))
+ (dir (file-name-directory file-name)))
+ (unless (file-exists-p dir) (make-directory dir t))
+ (write-file file-name))))
+
+(defvar my-ttrss-dir "~/Downloads")
(defun my-ttrss-format-file-name (info)
"Format: $author - $title ($year) [ttrss$id].html"
- (let ((author (plist-get info :author)))
- (file-name-concat
- my-webpage-incoming-dir
- (my-make-doc-file-name
- (format "%s - %s (%s) [ttrss%s].html"
- (if (string-empty-p author)
- (plist-get info :feed_title)
- author)
- (plist-get info :title)
- (format-time-string
- "%Y"
- (encode-time (decode-time (plist-get info :updated))))
- (plist-get info :id))))))
+ (let* ((author (plist-get info :author))
+ (feed-title (plist-get info :feed_title))
+ (feed-id (plist-get info :feed_id))
+ (name
+ (expand-file-name
+ (file-name-concat
+ (my-ttrss-feed-dir feed-title feed-id)
+ (my-make-doc-file-name
+ (format "%s - %s (%s) [ttrss%s].html"
+ (if (string-empty-p author)
+ feed-title
+ author)
+ (plist-get info :title)
+ (format-time-string
+ "%Y"
+ (encode-time (decode-time (plist-get info :updated))))
+ (plist-get info :id)))))))
+ (if (length> name 250)
+ (expand-file-name
+ (file-name-concat
+ (my-ttrss-feed-dir feed-title feed-id)
+ (my-make-doc-file-name
+ (format "_ - _ (%s) [ttrss%s].html"
+ (format-time-string
+ "%Y"
+ (encode-time (decode-time (plist-get info :updated))))
+ (plist-get info :id)))))
+ name)))
(provide 'my-ttrss)
;;; my-ttrss.el ends here
-