git.fiddlerwoaroof.com
reading-list-reader.lisp
6f42890d
 (defpackage :reading-list-reader
   (:use :cl )
   (:export ))
 (in-package :reading-list-reader)
 
 (serapeum:eval-always
1aa0f8f7
   (named-readtables:in-readtable :objc-readtable))
6f42890d
 
d5a8a26b
 (defun slugify (s)
   (cl-ppcre:regex-replace-all "\\s+"
                               (string-downcase s)
                               "_"))
 
 (defun select-child (d title)
   (flet ((get-title (h)
            (equal (gethash "Title" h)
                   title)))
     (fw.lu:let-each (:be *)
       (gethash "Children" d)
       (remove-if-not #'get-title *))))
 
 (defparameter *reading-list-location* "Library/Safari/Bookmarks.plist")
 (defun get-bookmark-filename ()
   (uiop:native-namestring
    (merge-pathnames *reading-list-location*
                     (truename "~/"))))
 
 (defun translate-plist (fn)
   (objc-runtime.data-extractors:extract-from-objc
    (objc-runtime.data-extractors:get-plist fn)))
6f42890d
 
d5a8a26b
 (defun make-org-file (s reading-list-info)
1aa0f8f7
   (format s "~&* Safari Reading List~%")
   (serapeum:mapply (serapeum:partial 'make-org-entry s)
d5a8a26b
                    reading-list-info))
 
 (defun make-org-entry (s date title url preview tag)
   (format s "~&** ~a (~a) :~{~a:~}~% ~a~2% ~{~<~% ~1,80:;~a~> ~}~2%"
           title
           (local-time:format-timestring nil date
                                         :format local-time:+rfc3339-format/date-only+)
           (alexandria:ensure-list tag)
6f42890d
           url
           (serapeum:tokens preview)))
d5a8a26b
 
6f42890d
 (defun get-readinglist-info (bookmarks)
d5a8a26b
   (sort (mapcar 'extract-link-info
85382f54
                 (gethash "Children"
                          (car
                           (select-child bookmarks
d5a8a26b
                                         "com.apple.ReadingList"))))
         'local-time:timestamp>
         :key 'car))
6f42890d
 
47822ccc
 (defun extract-link-info (link)
d5a8a26b
   (list (local-time:parse-rfc3339-timestring (or (fw.lu:pick '("ReadingList" "DateAdded") link)
                                                  (fw.lu:pick '("ReadingList" "DateLastViewed") link)
                                                  (fw.lu:pick '("ReadingListNonSync" "DateLastFetched") link)
                                                  (local-time:now)))
         (fw.lu:pick '("URIDictionary" "title") link)
47822ccc
         (fw.lu:pick '("URLString") link)
         (plump:decode-entities (coerce (fw.lu:pick '("ReadingList" "PreviewText") link) 'simple-string) t)
         (fw.lu:may (slugify (fw.lu:pick '("ReadingListNonSync" "siteName") link)))))
 
d5a8a26b
 (defun main ()
   #+(and build sbcl)
   (progn (sb-ext:disable-debugger)
          (sb-alien:alien-funcall
           (sb-alien:extern-alien "disable_lossage_handler"
                                  (function sb-alien:void))))
   (make-org-file *standard-output*
                  (get-readinglist-info 
                   (translate-plist 
                    (get-bookmark-filename)))))