Skip to content

Instantly share code, notes, and snippets.

@delebedev
Created June 7, 2015 11:09
Show Gist options
  • Save delebedev/6a2b11a5f3514a77da51 to your computer and use it in GitHub Desktop.
Save delebedev/6a2b11a5f3514a77da51 to your computer and use it in GitHub Desktop.
Export Foursquare checkins to GPX
//
// main.swift
// ForsquareGPX
//
// Created by Dzianis Lebedzeu on 07/06/2015.
// Copyright (c) 2015 Home. All rights reserved.
//
import Foundation
let token = "YOUR_FORSQUARE_TOKEN"
var checkins = [NSDictionary]()
let limit = 250
func iso8601Formatter() -> NSDateFormatter {
let formatter = NSDateFormatter()
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"
return formatter
}
func escapeXML(xml: String) -> String {
return CFXMLCreateStringByEscapingEntities(kCFAllocatorDefault, xml, nil) as String
}
func checkinsURLWithOffset(offset: Int) -> NSURL {
let path = "https://api.foursquare.com/v2/users/self/checkins"
let urlComponents = NSURLComponents(string: path)!
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "YYYYMMDD"
urlComponents.queryItems = [
NSURLQueryItem(name: "oauth_token", value: token),
NSURLQueryItem(name: "v", value: dateFormatter.stringFromDate(NSDate())),
NSURLQueryItem(name: "limit", value: "\(limit)"),
NSURLQueryItem(name: "offset", value: "\(offset)")]
return urlComponents.URL!
}
func fetchCheckins(offset: Int) {
println("fetching checkins with offset: \(offset)")
let task = NSURLSession.sharedSession().dataTaskWithURL(checkinsURLWithOffset(offset)) { (data, urlResponse, error) -> Void in
if let error = error {
println(error.localizedDescription)
exit(1)
}
var jsonError: NSError?
let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &jsonError) as? NSDictionary
if let json = json {
if let serverError = json.valueForKeyPath("meta.errorDetail") as? String {
println(serverError)
return
}
let items = json.valueForKeyPath("response.checkins.items") as? [NSDictionary]
let count = json.valueForKeyPath("response.checkins.count") as? Int
if let items = items, count = count {
if (offset < count) {
checkins += items
fetchCheckins(offset + limit)
} else {
writeCheckinsToGPX(checkins)
}
}
} else if let jsonError = jsonError {
println(jsonError.localizedDescription)
exit(1)
}
}
task.resume()
}
func writeCheckinsToGPX(checkins: [NSDictionary]) {
let formatter = iso8601Formatter()
let now = formatter.stringFromDate(NSDate())
var xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n" +
"<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" xmlns:gpxx=\"http://www.garmin.com/xmlschemas/GpxExtensions/v3\" xmlns:gpxtpx=\"http://www.garmin.com/xmlschemas/TrackPointExtension/v1\" creator=\"Oregon 400t\" version=\"1.1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd\">\n" +
"<metadata>" +
"<link href=\"http://www.foursquare.com\">" +
"<text>Foursquare Checkins</text>" +
"</link>" +
"<time>\(now)</time>" +
"</metadata>" + "\n"
for checkin in checkins {
if let name = checkin.valueForKeyPath("venue.name") as? String,
let lat = checkin.valueForKeyPath("venue.location.lat") as? Double,
let lon = checkin.valueForKeyPath("venue.location.lng") as? Double,
let time = checkin.valueForKeyPath("createdAt") as? Double {
let date = NSDate(timeIntervalSince1970: time)
xml += "\n<trk><name>\(escapeXML(name))</name><trkseg><trkpt lat=\"\(lat)\" lon=\"\(lon)\"><time>\(formatter.stringFromDate(date))</time></trkpt></trkseg></trk>"
}
}
xml += "\n"
xml += "</gpx>"
println("writing data to GPX file...")
var error: NSError?
xml.writeToFile("foursquare.gpx", atomically: true, encoding: NSUTF8StringEncoding, error: &error)
assert( error == nil, "Failed to write GPX.")
println("Done.")
exit(0)
}
fetchCheckins(0)
dispatch_main() // TODO: Any better solutions for async console execution?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment