Flexible Lisp Blogware. Fork for personal use. Mirrored from https://github.com/kingcons/coleslaw originally.

import.lisp 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. (asdf:oos 'asdf:load-op 'cxml)
  2. (asdf:oos 'asdf:load-op 'split-sequence)
  3. (asdf:oos 'asdf:load-op 'local-time)
  4. (asdf:oos 'asdf:load-op 'cl-ppcre)
  5. (defpackage :coleslaw-import
  6. (:use :cl :coleslaw :cxml)
  7. (:import-from :local-time #:+short-month-names+
  8. #:encode-timestamp)
  9. (:import-from :split-sequence #:split-sequence)
  10. (:import-from :cl-ppcre #:regex-replace-all))
  11. (in-package :coleslaw-import)
  12. (defgeneric import-post (service post)
  13. (:documentation "Import POST into *storage*. The method to construct the POST
  14. object is determined by SERVICE."))
  15. (defmethod import-post ((service (eql :wordpress)) post)
  16. (labels ((nodes (name)
  17. (dom:get-elements-by-tag-name post name))
  18. (value (node)
  19. (let ((child (dom:last-child node)))
  20. (when child (dom:data child))))
  21. (node-val (name)
  22. (let ((nodes (nodes name)))
  23. (if (string= "category" name)
  24. (loop for node across nodes collecting (value node))
  25. (when (plusp (length nodes)) (value (elt nodes 0))))))
  26. (public-p ()
  27. (string= "publish" (node-val "wp:status")))
  28. (make-timestamp (pubdate)
  29. (let* ((date (split-sequence #\Space (subseq pubdate 5)))
  30. (time (split-sequence #\: (fourth date))))
  31. (encode-timestamp 0
  32. (parse-integer (third time)) ; sec
  33. (parse-integer (second time)) ; min
  34. (parse-integer (first time)) ; hr
  35. (parse-integer (first date)) ; day
  36. (position (second date) +short-month-names+
  37. :test #'string=) ; month
  38. (parse-integer (third date)))))) ; year
  39. (when (public-p)
  40. (let ((new-post (make-post (node-val "title")
  41. (node-val "category")
  42. (make-timestamp (node-val "pubDate"))
  43. (regex-replace-all (string #\Newline)
  44. (node-val "content:encoded")
  45. "<br>")
  46. :aliases (parse-integer (node-val "wp:post_id"))))
  47. (comments (nodes "wp:comment")))
  48. (add-post new-post (post-id new-post))))))
  49. (defgeneric import-posts (service filepath)
  50. (:documentation "Import the posts (and potentially comments or other data)
  51. from FILEPATH, converting them to appropriate coleslaw objects and inserting
  52. them into *storage*. The method to parse the file is determined by SERVICE."))
  53. (defmethod import-posts ((service (eql :wordpress)) filepath)
  54. (let* ((xml (cxml:parse-file filepath (cxml-dom:make-dom-builder)))
  55. (posts (dom:get-elements-by-tag-name xml "item")))
  56. (loop for post across posts do (import-post service post))))