foursquare.lisp 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. (in-package #:chatikbot)
  2. (defparameter *fsq-checkins-url* "https://api.foursquare.com/v2/checkins/recent"
  3. "URL of recent checkins API")
  4. (defparameter *fsq-api-url* "https://api.foursquare.com/v2/~A"
  5. "Foursquare API URL")
  6. (defvar *fsq-access-token* nil "Access token for a user under which the process is run")
  7. (defvar *fsq-last-timestamp* nil "Timestamp of the last checkin. To only fetch latest")
  8. (defun %fsq-api-call (method &optional params)
  9. (let* ((resp
  10. (yason:parse
  11. (flex:make-flexi-stream
  12. (handler-case
  13. (bordeaux-threads:with-timeout (5)
  14. (drakma:http-request
  15. (format nil *fsq-api-url* method)
  16. :parameters (list*
  17. (cons "oauth_token" *fsq-access-token*)
  18. (cons "v" "20150811")
  19. params)
  20. :force-binary t
  21. :want-stream t
  22. :decode-content t))
  23. (bordeaux-threads:timeout (e)
  24. (declare (ignore e))
  25. (error "Timeout")))
  26. :external-format :utf-8)
  27. :object-as :alist))
  28. (meta (aget "meta" resp)))
  29. (when (not (= 200 (aget "code" meta)))
  30. (error (format nil "Foursquare API error, code ~A, errorType '~A', errorDetail '~A'"
  31. (aget "code" meta) (aget "errorType" meta) (aget "errorDetail" meta))))
  32. (aget "response" resp)))
  33. (defun fsq-fetch-checkins (&optional after-timestamp limit)
  34. (aget "recent"
  35. (%fsq-api-call "checkins/recent"
  36. (list (cons "afterTimestamp" (or after-timestamp "0"))
  37. (cons "limit" (or limit "20"))))))
  38. (defun fsq-fetch-new-checkins ()
  39. (let ((recent (fsq-fetch-checkins *fsq-last-timestamp*)))
  40. (when (first recent)
  41. (setf *fsq-last-timestamp* (princ-to-string (1+ (aget "createdAt" (first recent))))))
  42. recent))
  43. (defun fsq-fetch-friends (&optional offset)
  44. (list*
  45. (aget "user" (%fsq-api-call "users/self"))
  46. (aget "items"
  47. (aget "friends"
  48. (%fsq-api-call "users/self/friends"
  49. (list (cons "offset" (or offset "0"))))))))
  50. (defun fsq-format-checkin (checkin &optional with-dates)
  51. (when checkin
  52. (let ((user (aget "user" checkin))
  53. (venue (aget "venue" checkin)))
  54. (format nil "📍 ~@[~A~]~@[ ~A~]~@[ в ~A~]~@[ (~A)~]~@[ 📢 ~A~]~:[~; ~A~]"
  55. (aget "firstName" user) (aget "lastName" user)
  56. (aget "name" venue) (first (aget "formattedAddress" (aget "location" venue)))
  57. (aget "shout" checkin)
  58. with-dates (local-time:format-timestring
  59. nil
  60. (local-time:unix-to-timestamp (aget "createdAt" checkin))
  61. :format '(:year "-" (:month 2) "-" (:day 2) " " (:hour 2) ":" (:min 2)))))))