summaryrefslogtreecommitdiff
path: root/elfeed-custom-feeds-huggingface.el
diff options
context:
space:
mode:
Diffstat (limited to 'elfeed-custom-feeds-huggingface.el')
-rw-r--r--elfeed-custom-feeds-huggingface.el114
1 files changed, 52 insertions, 62 deletions
diff --git a/elfeed-custom-feeds-huggingface.el b/elfeed-custom-feeds-huggingface.el
index 81f4b5b..703b92e 100644
--- a/elfeed-custom-feeds-huggingface.el
+++ b/elfeed-custom-feeds-huggingface.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(require 'dom) 17(require 'dom)
@@ -44,37 +44,33 @@
44 (mid model-id)) 44 (mid model-id))
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 (run-with-idle-timer 0 nil cb nil) 50 (run-with-idle-timer 0 nil cb nil)
51 (goto-char (point-min)) 51 ;; Capture raw HTML for async processing
52 (if (re-search-forward "\n\n" nil t) 52 (let ((html-text (buffer-substring-no-properties (point-min) (point-max))))
53 ;; Capture raw HTML for async processing 53 ;; Process HTML parsing in idle timer to avoid blocking
54 (let ((html-text (buffer-substring-no-properties (point) (point-max)))) 54 (run-with-idle-timer 0 nil
55 ;; Process HTML parsing 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 html-text)
59 (with-temp-buffer 59 (let* ((html (libxml-parse-html-region (point-min) (point-max)))
60 (insert html-text) 60 (content-div (or (dom-by-class html "model-card-content")
61 (let* ((html (libxml-parse-html-region (point-min) (point-max))) 61 (dom-by-class html "prose")
62 (content-div (or (dom-by-class html "model-card-content") 62 (dom-by-tag html 'article))))
63 (dom-by-class html "prose") 63 (if content-div
64 (dom-by-tag html 'article)))) 64 (with-temp-buffer
65 (if content-div 65 (dom-print (if (listp content-div)
66 (with-temp-buffer 66 (car content-div)
67 (dom-print (if (listp content-div) 67 content-div))
68 (car content-div) 68 (let ((html-string (buffer-string)))
69 content-div)) 69 (funcall cb (elfeed-custom-feeds-huggingface--strip-svg-tags html-string))))
70 (let ((html-string (buffer-string))) 70 (funcall cb nil))))
71 (funcall cb (elfeed-custom-feeds-huggingface--strip-svg-tags html-string)))) 71 (error
72 (funcall cb nil)))) 72 (message "Error parsing HTML for %s: %s" mid err)
73 (error 73 (funcall cb nil)))))))))))))
74 (message "Error parsing HTML for %s: %s" mid err)
75 (funcall cb nil))))))
76 (run-with-idle-timer 0 nil cb nil))))
77 nil t)))))
78 74
79(defun elfeed-custom-feeds-huggingface--fetch-models (org-name callback) 75(defun elfeed-custom-feeds-huggingface--fetch-models (org-name callback)
80 "Fetch models for ORG-NAME from HuggingFace API and call CALLBACK with results." 76 "Fetch models for ORG-NAME from HuggingFace API and call CALLBACK with results."
@@ -82,28 +78,25 @@
82 (url-hexify-string org-name))) 78 (url-hexify-string org-name)))
83 (cb callback) 79 (cb callback)
84 (org org-name)) 80 (org org-name))
85 (url-retrieve url 81 (elfeed-curl-enqueue url
86 (lambda (status) 82 (lambda (status)
87 (if (plist-get status :error) 83 (if (not status)
88 (message "Error fetching HF org %s: %s" org (plist-get status :error)) 84 (message "Error fetching HF org %s: %s" org elfeed-curl-error-message)
89 (goto-char (point-min)) 85 ;; Capture JSON text for async parsing
90 (re-search-forward "\n\n") 86 (let ((json-text (buffer-substring-no-properties (point-min) (point-max))))
91 ;; Capture JSON text for async parsing 87 ;; Parse JSON in idle timer to avoid blocking
92 (let ((json-text (buffer-substring-no-properties (point) (point-max)))) 88 (run-with-idle-timer 0 nil
93 ;; Parse JSON in idle timer to avoid blocking 89 (lambda ()
94 (run-with-idle-timer 0 nil 90 (condition-case err
95 (lambda () 91 (with-temp-buffer
96 (condition-case err 92 (insert json-text)
97 (with-temp-buffer 93 (goto-char (point-min))
98 (insert json-text) 94 (let* ((json-object-type 'alist)
99 (goto-char (point-min)) 95 (json-array-type 'list)
100 (let* ((json-object-type 'alist) 96 (models (json-read)))
101 (json-array-type 'list) 97 (funcall cb org models)))
102 (models (json-read))) 98 (error
103 (funcall cb org models))) 99 (message "Error parsing JSON for HF org %s: %s" org err)))))))))))
104 (error
105 (message "Error parsing JSON for HF org %s: %s" org err))))))))
106 nil t)))
107 100
108(defun elfeed-custom-feeds-huggingface--create-entry (org-name model model-card-html) 101(defun elfeed-custom-feeds-huggingface--create-entry (org-name model model-card-html)
109 "Create an elfeed entry for MODEL with model card HTML content. 102 "Create an elfeed entry for MODEL with model card HTML content.
@@ -154,13 +147,10 @@ Batches all entries and updates UI once at the end to avoid blocking."
154 (setf (elfeed-feed-url feed) feed-url 147 (setf (elfeed-feed-url feed) feed-url
155 (elfeed-feed-title feed) (format "HuggingFace: %s" org-name))))) 148 (elfeed-feed-title feed) (format "HuggingFace: %s" org-name)))))
156 149
157 ;; Return immediately if no models 150 (if (zerop total)
158 (when (zerop total) 151 (message "HuggingFace feed %s: no models to process" org-name)
159 (message "HuggingFace feed %s: no models to process" org-name) 152 ;; Fetch model cards asynchronously and batch entries
160 (cl-return-from elfeed-custom-feeds-huggingface--models-to-elfeed nil)) 153 (cl-loop for model in models
161
162 ;; Fetch model cards asynchronously and batch entries
163 (cl-loop for model in models
164 for i from 0 154 for i from 0
165 for model-id = (alist-get 'id model) 155 for model-id = (alist-get 'id model)
166 for delay = (* i elfeed-custom-huggingface-request-delay) 156 for delay = (* i elfeed-custom-huggingface-request-delay)
@@ -190,7 +180,7 @@ Batches all entries and updates UI once at the end to avoid blocking."
190 (with-current-buffer "*elfeed-search*" 180 (with-current-buffer "*elfeed-search*"
191 (elfeed-search-update--force))))))))))) 181 (elfeed-search-update--force)))))))))))
192 delay)) 182 delay))
193 nil)) 183 nil)))
194 184
195;;;###autoload 185;;;###autoload
196(defun elfeed-custom-feeds-huggingface-update () 186(defun elfeed-custom-feeds-huggingface-update ()