From d607158012f5b0c7d303c112c1222ec95c4fd352 Mon Sep 17 00:00:00 2001 From: SqrtMinusOne Date: Mon, 23 May 2022 16:55:22 +0300 Subject: [PATCH] feat: sync feeds works --- elfeed-sync.el | 155 +++++++++++++++++++++++++++++++++++++++++++++++++ init.php | 26 ++++++--- 2 files changed, 174 insertions(+), 7 deletions(-) create mode 100644 elfeed-sync.el diff --git a/elfeed-sync.el b/elfeed-sync.el new file mode 100644 index 0000000..b2a34b8 --- /dev/null +++ b/elfeed-sync.el @@ -0,0 +1,155 @@ +;;; elfeed-sync.el --- TODO -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Korytov Pavel + +;; Author: Korytov Pavel +;; Maintainer: Korytov Pavel +;; Version: 0.1.0 +;; Package-Requires: ((emacs "27.1") (elfeed "3.4.1") (request "0.3.2")) +;; Homepage: https://github.com/SqrtMinusOne/avy-dired.el + +;; This file is NOT part of GNU Emacs. + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program 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 General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; TODO + +;;; Code: +(require 'elfeed) +(require 'request) + +(defgroup elfeed-sync () + "Sync elfeed with tt-rss." + :group 'elfeed) + +(defcustom elfeed-sync-tt-rss-instance "http://localhost:8280/tt-rss" + "URL of the tt-rss instance." + :group 'elfeed-sync + :type 'string) + +(defcustom elfeed-sync-tt-rss-login "admin" + "Login of the tt-rss instance." + :group 'elfeed-sync + :type 'string) + +(defcustom elfeed-sync-tt-rss-password "password" + "Password of the tt-rss instance." + :group 'elfeed-sync + :type 'string) + +(defvar elfeed-sync--tt-rss-sid nil + "Session ID.") + +(defun elfeed-sync--with-session (callback) + "Run CALLBACK with the active tt-rss session. + +The `elfeed-sync--tt-rss-sid' variable stores the active session ID. +If it's non-nil, CALLBACK is called outright, otherwise CALLBACK is +called only after a succesful login query." + (if elfeed-sync--tt-rss-sid + (funcall callback) + (request (concat elfeed-sync-tt-rss-instance "/api/") + :type "POST" + :data (json-encode + `(("op" . "login") + ("user" . ,elfeed-sync-tt-rss-login) + ("password" . ,elfeed-sync-tt-rss-password))) + :headers '(("Content-Type" . "application/json")) + :parser 'json-read + :success (elfeed-sync--handler + (setq elfeed-sync--tt-rss-sid + (alist-get 'session_id + (alist-get 'content data))) + (funcall callback)) + :error + (cl-function (lambda (&key error-thrown &allow-other-keys) + (message "Error: %S" error-thrown)))))) + +(defmacro elfeed-sync--session (&rest body) + "A wrapper around `elfeed-sync--with-session'." + `(elfeed-sync--with-session + (lambda () + ,@body))) + +(defun elfeed-sync--get-tree-summary (&optional data) + "Get list of feeds and categories from elfeed-summary." + (unless data + (setq data (elfeed-summary--get-data))) + (cl-loop for datum in data + for type = (car datum) + if (eq type 'group) + collect `(("group" . (("name" . + ,(alist-get :title (alist-get 'params (cdr datum)))) + ("children" . + ,(when-let ((children + (alist-get 'children (cdr datum)))) + (elfeed-sync--get-tree-summary children)))))) + if (eq type 'feed) + collect `(("feed" . (("tags" . ,(alist-get 'tags (cdr datum))) + ("url" . ,(elfeed-feed-url + (alist-get 'feed (cdr datum)))) + ("title" . ,(or (plist-get + (elfeed-feed-meta + (alist-get 'feed (cdr datum))) + :title) + (elfeed-feed-title + (alist-get 'feed (cdr datum)))))))))) + +(defun elfeed-sync--get-tree-plain () + "Get list of feeds and categories from plain elfeed." + (cl-loop for datum in elfeed-feeds + collect `(("feed" . (("tags" . ,(cdr datum)) + ("url" . ,(car datum))))))) + +(defun elfeed-sync--get-tree () + "Get list of feeds and categories." + (if (fboundp #'elfeed-summary--get-data) + (elfeed-sync--get-tree-summary) + (elfeed-sync--get-tree-plain))) + +(defmacro elfeed-sync--handler (&rest body) + "Default response handler for tt-rss." + `(cl-function + (lambda (&key data &allow-other-keys) + (if (= (alist-get 'status data) 0) + (progn + ,@body) + (message "Error!: %S" (alist-get 'content data)) + (when (string-equal + "NOT_LOGGED_IN" + (alist-get 'error (alist-get 'content data))) + (message "Login error. Try again") + (setq elfeed-sync--tt-rss-sid nil)))))) + +(defun elfeed-sync-feeds () + "Sync feeds with tt-rss." + (interactive) + (elfeed-sync--session + (request (concat elfeed-sync-tt-rss-instance "/api/") + :type "POST" + :data (json-encode + `(("op" . "setFeedsTree") + ("sid" . ,elfeed-sync--tt-rss-sid) + ("tree" . ,(elfeed-sync--get-tree)))) + :headers '(("Content-Type" . "application/json")) + :parser 'json-read + :success (elfeed-sync--handler + (message "Success!")) + :error + (cl-function (lambda (&key error-thrown &allow-other-keys) + (message "Error: %S" error-thrown)))))) + +(provide 'elfeed-sync) +;;; elfeed-sync.el ends here diff --git a/init.php b/init.php index 02d43c4..ff84316 100644 --- a/init.php +++ b/init.php @@ -82,14 +82,26 @@ class Elfeed_Sync extends Plugin { $results = array(); foreach($feeds as $feed_datum) { $cat_id = $cat_ids[$feed_datum["cat"]]; - $rc = Feeds::_subscribe($feed_datum["url"], $cat_id); - if ($rc["code"] === 0 || $rc["code"] === 1) { - $feed = ORM::for_table('ttrss_feeds') - ->where('id', $rc["feed_id"]) - ->where('owner_uid', $_SESSION['uid']) - ->find_one(); + $feed = ORM::for_table('ttrss_feeds') + ->where('feed_url', $feed_datum["url"]) + ->where('owner_uid', $_SESSION['uid']) + ->find_one(); + if (!$feed) { + $rc = Feeds::_subscribe($feed_datum["url"], $cat_id); + if ($rc["code"] === 0 || $rc["code"] === 1) { + $feed = ORM::for_table('ttrss_feeds') + ->where('id', $rc['feed_id']) + ->where('owner_uid', $_SESSION['uid']) + ->find_one(); + } + } + if ($feed) { + if (array_key_exists('title', $feed_datum)) { + $feed->set([ + 'title' => $feed_datum['title'], + ]); + } $feed->set([ - 'title' => $feed_datum['title'], 'cat_id' => $cat_id ]); $feed->save();