diff options
Diffstat (limited to 'emacs/.emacs.d/lisp/my/my-ttrss.el')
-rw-r--r-- | emacs/.emacs.d/lisp/my/my-ttrss.el | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/emacs/.emacs.d/lisp/my/my-ttrss.el b/emacs/.emacs.d/lisp/my/my-ttrss.el new file mode 100644 index 0000000..046f596 --- /dev/null +++ b/emacs/.emacs.d/lisp/my/my-ttrss.el @@ -0,0 +1,200 @@ +;;; my-ttrss.el -- ttrss utilities -*- lexical-binding: t -*- + +;; Copyright (C) 2025 Free Software Foundation, Inc. + +;; Author: Yuchen Pei <id@ypei.org> +;; Package-Requires: ((emacs "30.1")) + +;; This file is part of dotted. + +;; dotted is free software: you can redistribute it and/or modify it under +;; the terms of the GNU Affero General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; dotted is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General +;; Public License for more details. + +;; You should have received a copy of the GNU Affero General Public +;; License along with dotted. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; ttrss utilities. + +;;; Code: + +(require 'ttrss) +(require 'my-utils) +(require 'org-macs) + +;;; 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-get-last-id feed)))) + (seq-do 'my-ttrss-save-article articles) + (unless (seq-empty-p articles) + (my-ttrss-feed-write-last-id + feed + (seq-reduce + (lambda (acc article) (max acc (plist-get article :id))) + articles + 0))) + (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 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) "\">" + (plist-get info :feed_title) "</a>") + (when-let ((author (plist-get info :author))) + (unless (or (string-empty-p author) + (equal author (plist-get info :feed_title))) + (insert " (" author ")"))) + (let ((updated (format-time-string + "%Y-%m-%d %a %H:%M:%S" + (encode-time (decode-time (plist-get info :updated)))))) + (insert " " updated) + (insert "</p>") + (let ((tags (plist-get info :tags))) + (unless (seq-empty-p tags) + (insert "<p>tags: " (string-join tags ";") "</p>"))) + (insert (plist-get info :content)) + (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) + (my-touch-file-mtime file-name updated))))) + +(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)) + (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 |