diff options
Diffstat (limited to 'elfeed-custom-feeds-github.el')
| -rw-r--r-- | elfeed-custom-feeds-github.el | 124 |
1 files changed, 58 insertions, 66 deletions
diff --git a/elfeed-custom-feeds-github.el b/elfeed-custom-feeds-github.el index 97a2f60..49e0d6b 100644 --- a/elfeed-custom-feeds-github.el +++ b/elfeed-custom-feeds-github.el | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | ;;; Code: | 11 | ;;; Code: |
| 12 | 12 | ||
| 13 | (require 'elfeed) | 13 | (require 'elfeed) |
| 14 | (require 'url) | 14 | (require 'elfeed-curl) |
| 15 | (require 'json) | 15 | (require 'json) |
| 16 | (require 'cl-lib) | 16 | (require 'cl-lib) |
| 17 | 17 | ||
| @@ -44,29 +44,27 @@ | |||
| 44 | (dn display-name)) | 44 | (dn display-name)) |
| 45 | (run-at-time delay nil | 45 | (run-at-time delay nil |
| 46 | (lambda () | 46 | (lambda () |
| 47 | (url-retrieve url | 47 | (elfeed-curl-enqueue url |
| 48 | (lambda (status) | 48 | (lambda (status) |
| 49 | (if (plist-get status :error) | 49 | (if (not status) |
| 50 | (message "Error fetching GitHub PRs %s [%s]: %s" r dn (plist-get status :error)) | 50 | (message "Error fetching GitHub PRs %s [%s]: %s" r dn elfeed-curl-error-message) |
| 51 | (goto-char (point-min)) | 51 | ;; Capture JSON text for async parsing |
| 52 | (re-search-forward "\n\n") | 52 | (let ((json-text (buffer-substring-no-properties (point-min) (point-max)))) |
| 53 | ;; Capture JSON text for async parsing | 53 | ;; Parse JSON in idle timer to avoid blocking |
| 54 | (let ((json-text (buffer-substring-no-properties (point) (point-max)))) | 54 | (run-with-idle-timer 0 nil |
| 55 | ;; Parse JSON in idle timer to avoid blocking | 55 | (lambda () |
| 56 | (run-with-idle-timer 0 nil | 56 | (condition-case err |
| 57 | (lambda () | 57 | (with-temp-buffer |
| 58 | (condition-case err | 58 | (insert json-text) |
| 59 | (with-temp-buffer | 59 | (goto-char (point-min)) |
| 60 | (insert json-text) | 60 | (let* ((json-object-type 'alist) |
| 61 | (goto-char (point-min)) | 61 | (json-array-type 'list) |
| 62 | (let* ((json-object-type 'alist) | 62 | (response (json-read)) |
| 63 | (json-array-type 'list) | 63 | (items (alist-get 'items response))) |
| 64 | (response (json-read)) | 64 | (funcall cb r dn items))) |
| 65 | (items (alist-get 'items response))) | 65 | (error |
| 66 | (funcall cb r dn items))) | 66 | (message "Error parsing JSON for GitHub %s [%s]: %s" r dn err)))))))) |
| 67 | (error | 67 | :headers '(("Accept" . "application/vnd.github+json"))))))) |
| 68 | (message "Error parsing JSON for GitHub %s [%s]: %s" r dn err))))))) | ||
| 69 | nil t))))) | ||
| 70 | 68 | ||
| 71 | (defun elfeed-custom-feeds-github--prs-to-elfeed (repo display-name prs completion-callback) | 69 | (defun elfeed-custom-feeds-github--prs-to-elfeed (repo display-name prs completion-callback) |
| 72 | "Convert GitHub PRS to elfeed entries for REPO with DISPLAY-NAME. | 70 | "Convert GitHub PRS to elfeed entries for REPO with DISPLAY-NAME. |
| @@ -126,7 +124,7 @@ Call COMPLETION-CALLBACK with (repo display-name new-entries) when done." | |||
| 126 | (run-with-idle-timer 0 nil #'process-next-chunk) | 124 | (run-with-idle-timer 0 nil #'process-next-chunk) |
| 127 | ;; All done - call completion callback | 125 | ;; All done - call completion callback |
| 128 | (funcall completion-callback repo display-name (nreverse new-entries))))))) | 126 | (funcall completion-callback repo display-name (nreverse new-entries))))))) |
| 129 | (process-next-chunk))))) | 127 | (process-next-chunk)))) |
| 130 | 128 | ||
| 131 | ;;;###autoload | 129 | ;;;###autoload |
| 132 | (defun elfeed-custom-feeds-github-update () | 130 | (defun elfeed-custom-feeds-github-update () |
| @@ -138,48 +136,42 @@ Batches all entries and updates UI once at the end to avoid blocking." | |||
| 138 | (all-new-entries '()) | 136 | (all-new-entries '()) |
| 139 | (results '())) | 137 | (results '())) |
| 140 | 138 | ||
| 141 | (when (zerop total) | 139 | (if (zerop total) |
| 142 | (message "No GitHub PR queries configured") | 140 | (message "No GitHub PR queries configured") |
| 143 | (cl-return-from elfeed-custom-feeds-github-update nil)) | 141 | (let ((completion-callback |
| 144 | 142 | (lambda (repo display-name new-entries) | |
| 145 | ;; Completion callback that batches everything | 143 | (run-with-idle-timer 0 nil |
| 146 | (let ((completion-callback | 144 | (lambda () |
| 147 | (lambda (repo display-name new-entries) | 145 | (setq processed (1+ processed)) |
| 148 | (run-with-idle-timer 0 nil | 146 | (when new-entries |
| 149 | (lambda () | 147 | (setq all-new-entries (append all-new-entries new-entries))) |
| 150 | (setq processed (1+ processed)) | 148 | (push (list repo display-name (length new-entries)) results) |
| 151 | (when new-entries | 149 | ;; When all queries are done, batch add to DB and update UI once |
| 152 | (setq all-new-entries (append all-new-entries new-entries))) | 150 | (when (= processed total) |
| 153 | (push (list repo display-name (length new-entries)) results) | 151 | (let ((total-count (length all-new-entries))) |
| 154 | 152 | (when (> total-count 0) | |
| 155 | ;; When all queries are done, batch add to DB and update UI once | 153 | (run-with-idle-timer 0 nil |
| 156 | (when (= processed total) | 154 | (lambda () |
| 157 | (let ((total-count (length all-new-entries))) | 155 | (elfeed-db-add all-new-entries)))) |
| 158 | (when (> total-count 0) | 156 | ;; Report results for each feed |
| 159 | (run-with-idle-timer 0 nil | 157 | (dolist (result (nreverse results)) |
| 158 | (message "GitHub feed %s [%s]: %d new entries" | ||
| 159 | (nth 0 result) (nth 1 result) (nth 2 result))) | ||
| 160 | ;; Defer UI update to avoid blocking | ||
| 161 | (run-with-idle-timer 0.2 nil | ||
| 160 | (lambda () | 162 | (lambda () |
| 161 | (elfeed-db-add all-new-entries)))) | 163 | (when (get-buffer "*elfeed-search*") |
| 162 | ;; Report results for each feed | 164 | (with-current-buffer "*elfeed-search*" |
| 163 | (dolist (result (nreverse results)) | 165 | (elfeed-search-update--force)))))))))))) |
| 164 | (message "GitHub feed %s [%s]: %d new entries" | 166 | ;; Start all async fetches |
| 165 | (nth 0 result) (nth 1 result) (nth 2 result))) | 167 | (cl-loop for (repo query display-name) in elfeed-custom-github-pr-queries |
| 166 | ;; Defer UI update to avoid blocking | 168 | for i from 0 |
| 167 | (run-with-idle-timer 0.2 nil | 169 | for delay = (* i elfeed-custom-github-request-delay) |
| 168 | (lambda () | 170 | do (elfeed-custom-feeds-github--fetch-prs |
| 169 | (when (get-buffer "*elfeed-search*") | 171 | repo query display-name |
| 170 | (with-current-buffer "*elfeed-search*" | 172 | (lambda (r dn items) |
| 171 | (elfeed-search-update--force))))))))))))) | 173 | (elfeed-custom-feeds-github--prs-to-elfeed r dn items completion-callback)) |
| 172 | 174 | delay)))))) | |
| 173 | ;; Start all async fetches | ||
| 174 | (cl-loop for (repo query display-name) in elfeed-custom-github-pr-queries | ||
| 175 | for i from 0 | ||
| 176 | for delay = (* i elfeed-custom-github-request-delay) | ||
| 177 | do (elfeed-custom-feeds-github--fetch-prs | ||
| 178 | repo query display-name | ||
| 179 | (lambda (r dn items) | ||
| 180 | (elfeed-custom-feeds-github--prs-to-elfeed r dn items completion-callback)) | ||
| 181 | delay))) | ||
| 182 | nil) | ||
| 183 | 175 | ||
| 184 | (provide 'elfeed-custom-feeds-github) | 176 | (provide 'elfeed-custom-feeds-github) |
| 185 | 177 | ||
