Function: org-feed-update

org-feed-update is an autoloaded, interactive and byte-compiled function defined in org-feed.el.gz.

Signature

(org-feed-update FEED &optional RETRIEVE-ONLY)

Documentation

Get inbox items from FEED.

FEED can be a string with an association in org-feed-alist, or it can be a list structured like an entry in org-feed-alist.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/org/org-feed.el.gz
;;;###autoload
(defun org-feed-update (feed &optional retrieve-only)
  "Get inbox items from FEED.
FEED can be a string with an association in `org-feed-alist', or
it can be a list structured like an entry in `org-feed-alist'."
  (interactive (list (org-completing-read "Feed name: " org-feed-alist)))
  (if (stringp feed) (setq feed (assoc feed org-feed-alist)))
  (unless feed
    (error "No such feed in `org-feed-alist"))
  (catch 'exit
    (let ((name (car feed))
	  (url (nth 1 feed))
	  (file (or (nth 2 feed) (buffer-file-name (or (buffer-base-buffer)
						       (current-buffer)))))
	  (headline (nth 3 feed))
	  (filter (nth 1 (memq :filter feed)))
	  (formatter (nth 1 (memq :formatter feed)))
	  (new-handler (nth 1 (memq :new-handler feed)))
	  (changed-handler (nth 1 (memq :changed-handler feed)))
	  (template (or (nth 1 (memq :template feed))
			org-feed-default-template))
	  (drawer (or (nth 1 (memq :drawer feed))
		      org-feed-drawer))
	  (parse-feed (or (nth 1 (memq :parse-feed feed))
			  'org-feed-parse-rss-feed))
	  (parse-entry (or (nth 1 (memq :parse-entry feed))
			   'org-feed-parse-rss-entry))
	  feed-buffer inbox-pos new-formatted
	  entries old-status status new changed guid-alist guid olds)
      (setq feed-buffer (org-feed-get-feed url))
      (unless (and feed-buffer (bufferp (get-buffer feed-buffer)))
	(error "Cannot get feed %s" name))
      (when retrieve-only
	(throw 'exit feed-buffer))
      (setq entries (funcall parse-feed feed-buffer))
      (ignore-errors (kill-buffer feed-buffer))
      (save-excursion
	(save-window-excursion
	  (setq inbox-pos (org-feed-goto-inbox-internal file headline))
	  (setq old-status (org-feed-read-previous-status inbox-pos drawer))
	  ;; Add the "handled" status to the appropriate entries
	  (setq entries (mapcar (lambda (e)
				  (setq e
					(plist-put e :handled
						   (nth 1 (assoc
							   (plist-get e :guid)
							   old-status)))))
				entries))
	  ;; Find out which entries are new and which are changed
	  (dolist (e entries)
	    (if (not (plist-get e :handled))
		(push e new)
	      (setq olds (nth 2 (assoc (plist-get e :guid) old-status)))
	      (if (and olds
		       (not (string= (sha1
				      (plist-get e :item-full-text))
				     olds)))
		  (push e changed))))

	  ;; Parse the relevant entries fully
	  (setq new     (mapcar parse-entry new)
		changed (mapcar parse-entry changed))

	  ;; Run the filter
	  (when filter
	    (setq new     (delq nil (mapcar filter new))
		  changed (delq nil (mapcar filter new))))

	  (when (not (or new changed))
	    (message "No new items in feed %s" name)
	    (throw 'exit 0))

	  ;; Get alist based on guid, to look up entries
	  (setq guid-alist
		(append
		 (mapcar (lambda (e) (list (plist-get e :guid) e)) new)
		 (mapcar (lambda (e) (list (plist-get e :guid) e)) changed)))

	  ;; Construct the new status
	  (setq status
		(mapcar
		 (lambda (e)
		   (setq guid (plist-get e :guid))
		   (list guid
			 ;; things count as handled if we handle them now,
			 ;; or if they were handled previously
			 (if (assoc guid guid-alist) t (plist-get e :handled))
			 ;; A hash, to detect changes
			 (sha1 (plist-get e :item-full-text))))
		 entries))

	  ;; Handle new items in the feed
	  (when new
	    (if new-handler
		(progn
		  (goto-char inbox-pos)
		  (funcall new-handler new))
	      ;; No custom handler, do the default adding
	      ;; Format the new entries into an alist with GUIDs in the car
	      (setq new-formatted
		    (mapcar
		     (lambda (e) (org-feed-format-entry e template formatter))
		     new)))

	    ;; Insert the new items
	    (org-feed-add-items inbox-pos new-formatted))

	  ;; Handle changed items in the feed
	  (when (and changed-handler changed)
	    (goto-char inbox-pos)
	    (funcall changed-handler changed))

	  ;; Write the new status
	  ;; We do this only now, in case something goes wrong above, so
          ;; that would end up with a status that does not reflect
	  ;; which items truly have been handled
	  (org-feed-write-status inbox-pos drawer status)

	  ;; Normalize the visibility of the inbox tree
	  (goto-char inbox-pos)
	  (org-fold-subtree t)
	  (org-fold-show-children)

	  ;; Hooks and messages
	  (when org-feed-save-after-adding (save-buffer))
	  (message "Added %d new item%s from feed %s to file %s, heading %s"
		   (length new) (if (> (length new) 1) "s" "")
		   name
		   (file-name-nondirectory file) headline)
	  (run-hooks 'org-feed-after-adding-hook)
	  (length new))))))