(in-package :cl-user) (defpackage #:timeliner.foursquare (:use :cl #:timeliner.utils :cl-mongo) (:export #:*access-token* #:on-cron)) (in-package #:timeliner.foursquare) (defvar *access-token*) (defun make-checkin-doc (checkin) (let* ((venue (gethash "venue" checkin)) (location (and venue (gethash "location" venue)))) (when venue (kv (kv :ts (local-time:unix-to-timestamp (gethash "createdAt" checkin))) (kv :type "checkin") (kv :title (format nil "~A~:[~;~:* (~A)~]~:[~;~:*: ~A~]" (gethash "name" venue) (gethash "address" location) (gethash "shout" checkin))) (kv :loc (kv (kv :type "Point") ; GeoJSON Point (kv :coordinates (list (gethash "lng" location) (gethash "lat" location))))))))) (defun load-checkins (from) (let ((checkins (gethash "checkins" (gethash "response" (yason:parse (flexi-streams:octets-to-string (drakma:http-request "https://api.foursquare.com/v2/users/self/checkins" :parameters (list (cons "oauth_token" *access-token*) (cons "limit" "250") (cons "sort" "oldestfirst") (cons "afterTimestamp" (if from (princ-to-string (1+ (local-time:timestamp-to-unix from))) "0")) (cons "v" "20140704"))) :external-format :utf-8)))))) (when checkins (loop for item in (gethash "items" checkins) for doc = (make-checkin-doc item) when doc collect doc)))) (defun on-cron () (handler-case (let* ((last-checkin (first (docs (db.sort "events" ($ "type" "checkin") :field "ts" :asc nil :limit 1)))) (from (and last-checkin (ms->ts (cl-mongo::raw (get-element "ts" last-checkin))))) (checkins (load-checkins from))) (log:info "Got ~A checkins from ~A~%" (length checkins) from) (save-events checkins)) (error (e) (log:error e))))