This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

node client

  • Loading branch information...
scoates committed Jul 12, 2011
0 parents commit e41a5388c59d8756acf22e4b80100fcd52a72949
Showing with 355 additions and 0 deletions.
  1. +174 −0 gimmebar.js
  2. +13 −0 package.json
  3. +117 −0 test.js
  4. +29 −0 test_public.js
  5. +22 −0 util.js
@@ -0,0 +1,174 @@
+const https = require('https')
+ , url = require('url')
+ , util = require('./util');
+
+//todo: deal with redirects properly
+
+const baseURL = 'https://gimmebar.com/api';
+const APIVersion = '0';
+const GimmebarMethods = {
+ 'getUser': {path: 'user', method: 'GET'},
+ 'getUserById': {path: 'user/:user_id', method: 'GET'},
+ 'getUserByName': {path: 'users/find', method: 'GET'},
+ 'createAsset': {path: 'asset', method: 'POST'},
+ 'getAssetById': {path: 'asset/:asset_id', method: 'GET'},
+ 'updateAsset': {path: 'asset/:asset_id', method: 'POST'},
+ 'deleteAsset': {path: 'asset/:asset_id', method: 'DELETE'},
+ 'getAssets': {path: 'assets', method: 'GET'},
+ 'getAssetsByUserId': {path: 'assets/user/:user_id', method: 'GET'},
+ 'searchAssets': {path: 'assets/search', method: 'GET'},
+ 'getCollections': {path: 'collections', method: 'GET'},
+ 'getCollectionsByUserId': {path: 'collections/user', method: 'GET'},
+ 'getAssetCollections': {path: 'collections/asset', method: 'GET'},
+ 'getCollectionBySlug': {path: 'collection/slug', method: 'GET'},
+ 'getCollectionById': {path: 'collection/:collection_id', method: 'GET'},
+ 'updateCollection': {path: 'collection/:collection_id', method: 'POST'},
+ 'deleteCollection': {'path': 'collection/:collection_id', method: 'DELETE'},
+ 'createCollection': {path: 'collection', method: 'POST'},
+ 'addAssetsToCollection': {path: 'collection/:collection_id/add', method: 'POST'},
+ 'removeAssetsFromCollection': {path: 'collection/:collection_id/remove', method: 'POST'},
+ 'getTags': {path: 'tags', method: 'GET'},
+ 'authGenerateReqToken': {path: 'auth/reqtoken', method: 'POST', unsigned: true},
+ 'authExchangeReqToken': {path: 'auth/exchange/request', method: 'POST', unsigned: true},
+ 'authExchangeAuthToken': {path: 'auth/exchange/authorization', method: 'POST', unsigned: true},
+ 'getPublicAssetsByUsername': {path: 'public/assets/:username', method: 'GET', unsigned: true},
+ 'getPublicAssetsByCollection': {path: 'public/assets/:username/:collection', method: 'GET', unsigned: true}
+};
+
+function Client(accessToken) {
+ if (accessToken) {
+ this.setAccessToken(accessToken);
+ }
+}
+
+Client.prototype = {
+ setAccessToken: function(accessToken) {
+ this.accessToken = accessToken;
+ },
+ makeReq: function(options, params) {
+ var self = this;
+ var req = https.request(options, function(res) {
+ var data = "";
+ res.setEncoding('utf8');
+ res.on('data', function(d) {
+ data += d;
+ });
+ res.on('end', function() {
+ var callback;
+ if (res.headers['content-type'].split(';')[0] === 'application/json') {
+ data = JSON.parse(data);
+ }
+ if (res.statusCode >= 200 && res.statusCode < 300) {
+ callback = params.success;
+ } else {
+ callback = params.failure;
+ }
+ if (callback) {
+ callback.call(null, data, res.statusCode, res.headers);
+ }
+ });
+ });
+ if (params.data) {
+ req.write(params.data);
+ }
+ req.end();
+
+ req.on('error', function(e) {
+ console.error(e);
+ });
+ },
+ prep: function(path, qs, method, cbs, signed) {
+ var id = function () {};
+ var defaultParams = {
+ success: id,
+ failure: id,
+ data: {}
+ };
+ var fullURL = [baseURL, 'v'+APIVersion, path].join('/');
+ var parsedURL = url.parse(fullURL);
+ var fullPath = parsedURL.pathname;
+ if (method === 'GET' && qs) {
+ fullPath += '?' + qs;
+ }
+ var options = {
+ host: parsedURL.host,
+ port: 443,
+ path: fullPath,
+ method: method,
+ headers: {
+ 'host': parsedURL.host,
+ 'accept': 'application/json',
+ 'user-agent': 'Gimmebar/0.0 node.js/' + process.version,
+ }
+ };
+ if (signed) {
+ if (this.accessToken) {
+ options.headers.Authorization = 'Bearer ' + this.accessToken;
+ } else {
+ throw "No access token";
+ }
+ }
+ if ((method === 'POST' || method === 'PUT') && qs) {
+ options.headers['content-length'] = qs.length;
+ }
+ var params = {
+ data: (method === 'POST' || method === 'PUT') ? qs : undefined,
+ success: cbs.success || id,
+ failure: cbs.failure || id
+ };
+ util.extend(defaultParams, params);
+ this.makeReq(options, params);
+ }
+};
+
+function buildUrl(template, params) {
+ util.forEach(params, function(name, value) {
+ var regex = new RegExp(':' + name + '(/|$)');
+ if (template.match(regex)) {
+ template = template.replace(regex, value);
+ delete params[name];
+ }
+ });
+ return template;
+}
+
+function buildQueryString(opts) {
+ var output = [];
+ util.forEach(opts, function(name, value) {
+ if (Array.isArray(value)) {
+ value.forEach(function(v) {
+ output.push([encodeURIComponent(name+'[]'), encodeURIComponent(v)]);
+ });
+ } else {
+ output.push([encodeURIComponent(name), encodeURIComponent(value)]);
+ }
+ });
+ return output.map(function(pair) { return pair.join('='); }).join('&');
+}
+
+util.forEach(GimmebarMethods, function(name, opts) {
+ Client.prototype[name] = function() {
+ var args = Array.prototype.slice.call(arguments);
+ var data = {}, cbs = {};
+ if (args.length === 2) {
+ data = args[0];
+ cbs = args[1];
+ } else if (args.length === 1) {
+ //heuristically determine if they're giving us data or callbacks
+ if (args[0].success || args[0].failure) {
+ cbs = args[0];
+ } else {
+ data = args[0];
+ }
+ }
+ var url = buildUrl(opts.path, data);
+ var qs = buildQueryString(data);
+ var signed = true;
+ if (opts.unsigned) {
+ signed = false;
+ }
+ this.prep(url, qs, opts.method, cbs, signed);
+ };
+});
+
+exports.Client = Client;
@@ -0,0 +1,13 @@
+{
+ "name": "gimmebar",
+ "description": "A Gimmebar API client.",
+ "version": "0.0.1",
+ "author": "Evan Haas <evan@fictivekin.com>",
+ "contributors": [
+ { "name": "Evan Haas", "email": "evan@fictivekin.com" },
+ { "name": "Sean Coates", "email": "sean@gimmebar.com" }
+ ],
+ "keywords": ["api", "gimmebar", "utility", "client"],
+ "engines": { "node": ">=0.4.0" },
+ "dependencies": { "hashlib": ">=1.0.0" }
+}
117 test.js
@@ -0,0 +1,117 @@
+var Gimmebar = require('./gimmebar');
+
+function obscureToken(t) {
+ var ret = t.substr(0, 4);
+ for (var i=0; i<t.length-8; i++) {
+ ret += '*';
+ }
+ ret += t.substr(-4);
+ return ret;
+}
+
+var client = new Gimmebar.Client();
+
+if (process.env.GIMMEBAR_ACCESS_TOKEN) {
+ console.log("Authenticating with access token: " + obscureToken(process.env.GIMMEBAR_ACCESS_TOKEN));
+
+ client.setAccessToken(process.env.GIMMEBAR_ACCESS_TOKEN);
+
+ client.getAssets({
+ success: function(data, status, headers) {
+ data.records.forEach(function (r) {
+ console.log(
+ r.short_url,
+ '"' + r.title + '"',
+ r.asset_type,
+ r.private ? 'private' : 'public'
+ );
+ });
+ process.exit(0);
+ },
+ failure: function(data, status, headers) {
+ console.log(data, status, headers);
+ process.exit(1);
+ }
+ });
+
+} else if (process.env.GIMMEBAR_CLIENT_ID && process.env.GIMMEBAR_REQUEST_TOKEN) {
+ console.log("Fetching access token from request token: " + obscureToken(process.env.GIMMEBAR_REQUEST_TOKEN));
+
+ client.authExchangeReqToken(
+ {
+ client_id: process.env.GIMMEBAR_CLIENT_ID,
+ token: process.env.GIMMEBAR_REQUEST_TOKEN,
+ response_type: 'code'
+ },
+ {
+ success: function(data, status, headers) {
+ console.log("Got authorization token:", data.code);
+ console.log("Requesting access token.");
+ client.authExchangeAuthToken(
+ {
+ code: data.code,
+ grant_type: 'authorization_code'
+ },
+ {
+ success: function(data, status, headers) {
+ console.log("Got access token:", data.access_token);
+ console.log("You can now call:");
+ console.log(
+ "GIMMEBAR_ACCESS_TOKEN=" + data.access_token
+ + " node test.js"
+ );
+ process.exit(0);
+ },
+ failure: function(data, status, headers) {
+ console.log("Something went wrong:", status, data);
+ process.exit(1);
+ }
+ }
+ );
+ },
+ failure: function(data, status, headers) {
+ console.log("Something went wrong:", status, data);
+ process.exit(1);
+ }
+ }
+ );
+
+} else if (process.env.GIMMEBAR_CLIENT_ID && process.env.GIMMEBAR_CLIENT_SECRET) {
+ console.log("No request or access token; fetching for client: " + process.env.GIMMEBAR_CLIENT_ID);
+
+ client.authGenerateReqToken(
+ {
+ client_id: process.env.GIMMEBAR_CLIENT_ID,
+ client_secret: process.env.GIMMEBAR_CLIENT_SECRET,
+ type: 'app'
+ },
+ {
+ success: function(data, status, headers) {
+ console.log("Got request token:", data.request_token);
+ console.log('Send the user to:');
+ console.log(
+ 'https://gimmebar.com/authorize?client_id='
+ + process.env.GIMMEBAR_CLIENT_ID
+ + '&token=' + data.request_token
+ + '&response_type=code'
+ );
+ console.log('... and then run: ');
+ console.log(
+ 'GIMMEBAR_CLIENT_ID=' + process.env.GIMMEBAR_CLIENT_ID
+ + ' GIMMEBAR_REQUEST_TOKEN=' + data.request_token
+ + ' node test.js');
+ process.exit(0);
+ },
+ failure: function(data, status, headers) {
+ console.log("Something went wrong:", status, data);
+ process.exit(1);
+ }
+ }
+ );
+
+} else {
+ console.log("You must set env.GIMMEBAR_CLIENT_ID and env.GIMMEBAR_CLIENT_SECRET");
+ console.log("GIMMEBAR_CLIENT_ID=4e1472222eaaaaaaaa00000 GIMMEBAR_CLIENT_SECRET=12345 node test.js");
+ process.exit(1);
+}
+
@@ -0,0 +1,29 @@
+var Gimmebar = require('./gimmebar');
+
+var client = new Gimmebar.Client();
+
+if (!process.argv[2]) {
+ console.log("Usage:");
+ console.log(process.argv[0], process.argv[1], "username");
+ process.exit(1);
+}
+
+client.getPublicAssetsByUsername({username: process.argv[2]}, {
+ success: function (data, status, headers) {
+ console.log("Great success!");
+ data.records.forEach(function (r) {
+ console.log(
+ r.short_url,
+ '"' + r.title + '"',
+ r.asset_type
+ );
+ });
+ },
+ failure: function (data, status, headers) {
+ if (404 === status) {
+ console.log("User not found.");
+ } else {
+ console.log("Something went wrong )-:", status, data);
+ }
+ }
+});
22 util.js
@@ -0,0 +1,22 @@
+module.exports = {
+ extend: function (a,b) {
+ for ( var i in b ) {
+ var g = b.__lookupGetter__(i), s = b.__lookupSetter__(i);
+
+ if ( g || s ) {
+ if ( g )
+ a.__defineGetter__(i, g);
+ if ( s )
+ a.__defineSetter__(i, s);
+ } else
+ a[i] = b[i];
+ }
+ return a;
+ },
+
+ forEach: function (obj, iterator) {
+ Object.keys(obj).forEach(function(key) {
+ iterator.call(null, key, obj[key]);
+ });
+ }
+};

0 comments on commit e41a538

Please sign in to comment.