photo-store.lisp 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. (in-package #:photo-store)
  2. (eval-when (:compile-toplevel :load-toplevel :execute)
  3. (restas::register-pkgmodule-traits 'photo-store)
  4. (restas:reconnect-all-routes))
  5. ;; photos: id | album_id | filename | size | taken | width | height | lat | lon
  6. ;; albums: id | parent_id | path | date | name | description | cover_id | accessibility
  7. (defstruct photo url title width height)
  8. (defun load-photo (path)
  9. (let ((info (load-photo-info path)))
  10. (make-photo :url (map-path path)
  11. :title (aget :name info)
  12. :width (first (aget :dim info))
  13. :height (second (aget :dim info)))))
  14. (defun load-photos-from-dir (directory)
  15. (mapcar 'load-photo (remove-if-not #'(lambda (p)
  16. (equal (string-downcase (pathname-type p)) "jpg"))
  17. (uiop:directory-files directory))))
  18. (defvar *path-url-mapping* nil "alist of path-2-url mapping")
  19. (defun map-path (path)
  20. (loop for (base-path . base-url) in *path-url-mapping*
  21. for rel-path = (uiop:subpathp path base-path)
  22. when rel-path do (return (concatenate 'string base-url (namestring rel-path)))
  23. finally (error "Can't map path ~S" path)))
  24. (defmethod yason:encode ((photo photo) &optional (stream *standard-output*))
  25. (yason:with-output (stream)
  26. (yason:with-object ()
  27. (yason:encode-object-element "src" (photo-url photo))
  28. (yason:encode-object-element "w" (photo-width photo))
  29. (yason:encode-object-element "h" (photo-height photo))
  30. (yason:encode-object-element "title" (photo-title photo)))))
  31. (restas:define-route main ("")
  32. (asdf:system-relative-pathname :photo-store "index.html"))
  33. ;; Assets file path
  34. (defparameter *assets-path*
  35. (asdf:system-relative-pathname :photo-store "assets/"))
  36. (restas:define-route assets/css ("css/:file" :content-type "text/css")
  37. (merge-pathnames file *assets-path*))
  38. (restas:define-route assets/js ("js/:file" :content-type "application/x-javascript")
  39. (merge-pathnames file *assets-path*))
  40. (defvar *incoming-path* nil "Path for incoming photos")
  41. (restas:define-route incoming ("incoming/"
  42. :content-type "application/json")
  43. (with-output-to-string (stream)
  44. (yason:encode
  45. (loop for subdir in (uiop:subdirectories *incoming-path*)
  46. append (load-photos-from-dir subdir))
  47. stream)))
  48. (defun start (&key (address "0.0.0.0") (port 8800))
  49. (restas:start '#:photo-store :address address :port port))