rednet-google-contacts
Version:
API wrapper for Google Contacts
229 lines (192 loc) • 5.88 kB
JavaScript
/**
* @todo: recursively send requests until all contacts are fetched
*
* @see https://developers.google.com/google-apps/contacts/v3/reference#ContactsFeed
*
* To API test requests:
*
* @see https://developers.google.com/oauthplayground/
*
* To format JSON nicely:
*
* @see http://jsonviewer.stack.hu/
*
* Note: The Contacts API has a hard limit to the number of results it can return at a
* time even if you explicitly request all possible results. If the requested feed has
* more fields than can be returned in a single response, the API truncates the feed and adds
* a "Next" link that allows you to request the rest of the response.
*/
var EventEmitter = require("events").EventEmitter;
var _ = require("underscore");
var qs = require("querystring");
var util = require("util");
var url = require("url");
var https = require("https");
var GoogleContacts = function (opts) {
if (typeof opts === "string") {
opts = { token: opts }
}
if (!opts) {
opts = {};
}
this.contacts = [];
this.consumerKey = opts.consumerKey;
this.consumerSecret = opts.consumerSecret;
this.token = opts.token;
this.refreshToken = opts.refreshToken;
};
GoogleContacts.prototype = {};
util.inherits(GoogleContacts, EventEmitter);
GoogleContacts.prototype._get = function (params, cb) {
var self = this;
if (typeof params === "function") {
cb = params;
params = {};
}
var opts = {
hostname: "google.com",
port: 443,
path: this._buildPath(params),
method: "GET",
headers: {
"Authorization": "OAuth " + this.token
}
};
console.log("Req sent: ", opts);
https.request(opts, function (res) {
var data = "";
res.on("end", function () {
if (res.statusCode < 200 || res.statusCode >= 300) {
//console.log("statusCode: ", res.statusCode);
//console.log("headers: ", res.headers);
console.log("headers: ", res);
var error = new Error("Bad client request status: " + res.statusCode);
return cb(error);
}
try {
data = JSON.parse(data);
cb(null, data);
}
catch (err) {
cb(err);
}
});
res.on("data", function (chunk) {
//console.log(chunk.toString());
data += chunk;
});
res.on("error", function (err) {
cb(err);
});
//res.on("close", onFinish);
})
.on("error", function (err) {
cb(err);
})
.end();
};
GoogleContacts.prototype.getContacts = function (cb) {
var self = this;
this._get({ type: "contacts" }, receivedContacts);
function receivedContacts(err, data) {
if (err) return cb(err);
self._saveContactsFromFeed(data.feed);
var next = false;
data.feed.link.forEach(function (link) {
if (link.rel === "next") {
next = true;
var path = url.parse(link.href).path;
self._get({ path: path }, receivedContacts);
}
});
if (!next) {
cb(null, self.contacts);
}
}
};
GoogleContacts.prototype._saveContactsFromFeed = function (feed) {
var self = this;
//console.log(feed);
feed.entry.forEach(function (entry) {
try {
var name = entry.title["$t"];
var email = entry["gd$email"][0].address; // only save first email
self.contacts.push({ name: name, email: email });
}
catch (e) {
// property not available...
}
});
console.log(self.contacts);
console.log(self.contacts.length);
};
GoogleContacts.prototype._buildPath = function (params) {
if (params.path) return params.path;
params = params || {};
params.type = params.type || "contacts";
params.alt = params.alt || "json";
params.projection = params.projection || "full";
params.email = params.email || "default";
params["max-results"] = params["max-results"] || 2000;
var query = {
"alt": params.alt,
"max-results": params["max-results"]
};
var opts = ["type", "email", "projection"];
var path = "/m8/feeds";
opts.forEach(function(i) { path+= "/" + params[i]; });
path += "?" + qs.stringify(query);
return path;
};
GoogleContacts.prototype.refreshAccessToken = function (refreshToken, cb) {
if (typeof params === "function") {
cb = params;
params = {};
}
var data = {};
data.refresh_token = refreshToken;
data.client_id = this.consumerKey;
data.client_secret = this.consumerSecret;
data.grant_type = "refresh_token";
var body = qs.stringify(data);
var opts = {
host: "accounts.google.com",
port: 443,
path: "/o/oauth2/token",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Content-Length": body.length
}
};
var req = https.request(opts, function (res) {
var data = "";
res.on("end", function () {
if (res.statusCode < 200 || res.statusCode >= 300) {
var error = new Error("Bad client request status: " + res.statusCode);
return cb(error);
}
try {
data = JSON.parse(data);
//console.log(data);
cb(null, data.access_token);
}
catch (err) {
cb(err);
}
});
res.on("data", function (chunk) {
//console.log(chunk.toString());
data += chunk;
});
res.on("error", function (err) {
cb(err);
});
//res.on("close", onFinish);
}).on("error", function (err) {
cb(err);
});
req.write(body);
req.end();
};
exports.GoogleContacts = GoogleContacts;