Twitter だって使えるんだぜ。
もう一つ。こちらも必要だったので。
/** * Twitter Client for node.js */ var sys = require('sys'), url = require('url'), querystring = require('querystring'), http = require('http'), crypto = require('crypto'), EventEmitter = require('events').EventEmitter; var OAuth = require('oauth').OAuth; var OAUTH_CONFIG = { RequestTokenUrl : "https://api.twitter.com/oauth/request_token" , AccessTokenUrl : "https://api.twitter.com/oauth/access_token" , Version : "1.0" , Method : "HMAC-SHA1" }; var logger = require('./logger').DefaultLogger; var API_URL = "http://api.twitter.com/1"; var Client = function(consumerKey, consumerSecret, options){ if(!options) options = {}; this._oa = new OAuth( OAUTH_CONFIG.RequestTokenUrl , OAUTH_CONFIG.AccessTokenUrl , consumerKey , consumerSecret , OAUTH_CONFIG.Version , null , OAUTH_CONFIG.Method ); this._accessKey = options.accessKey; this._accessSecret = options.accessSecret; this._logger = options.logger || logger; }; Client.prototype.getAccessToken = function(callback){ var self = this; this._oa.getOAuthRequestToken(function(err, token, token_secret, results){ if(err){ callback && callback(err); } else{ var stdin = process.openStdin(); stdin.setEncoding('utf8'); var url = "http://twitter.com/oauth/authorize?oauth_token=" + token; process.stdout.write('please visit ' + url + ' to get verification code.\n'); process.stdout.write('input verification code: '); stdin.on('data', function (chunk) { var verifier = chunk.split('\n')[0]; self._oa.getOAuthAccessToken( token, token_secret, verifier, function(error, akey, asecret, results2){ if(error){ callback && callback(error); }else{ self._accessKey = akey; self._accessSecret = asecret; callback && callback(null, akey, asecret); } } ); }); } }); }; Client.prototype._doGet = function(path, callback){ var self = this; var url = [API_URL, path].join(''); self._logger.debug('[Twitter] GET {url}', {url: url}); this._oa.get(url, this._accessKey, this._accessSecret, function(error, data, response){ self._logger.debug('[Twitter] ' + data); if(callback){ callback(error, JSON.parse(data), response); } });; }; Client.prototype._doPost = function(path, body, callback){ var self = this; var url = [API_URL, path].join(''); self._logger.debug('[Twitter] POST {url}', {url: url}); self._logger.debug('[Twitter] ' + body); this._oa.post(url, this._accessKey, this._accessSecret, body, function(error, data, response){ self._logger.debug('[Twitter] ' + data); if(callback){ callback(error, JSON.parse(data), response); } });; } Client.prototype.update = function(status, params, callback){ if( typeof params == "function" ) { callback= params; params = {}; } this._doPost("/statuses/update.json", {status: status}, callback); } Client.prototype.follow = function(params, callback){ if( typeof params == "string"){ params = { "user_id" : params }; } this._doPost("/friendships/create.json", params, callback); } Client.prototype.unfollow = function(params, callback){ if( typeof params == "string"){ params = { "user_id" : params }; } this._doPost("/friendships/destroy.json", params, callback); } var allowedTL = ['public', 'home', 'friends', 'user']; Client.prototype.timeline = function(type, params, callback){ if( allowedTL.indexOf(type) == -1 ){ throw "Invalid timeline type '"+ type + "'"; } var qs = querystring.stringify(params); this._doGet('/statuses/' + type + "_timeline.json?" + qs, callback); } Client.prototype._handleStream = function(request, callback){ var logger = this._logger; var event = new EventEmitter(); function _invokeCallback(str){ var obj, err; try{ obj = JSON.parse(str); try{ event.emit('data', obj); }catch(e1){ logger.error(e1); } }catch(e2){ logger.error('Emit error: ' + sys.inspect(e2)); event.emit('error', e2); } }; request.connection.on('error', function(err){ logger.error('Connection Error: ' + sys.inspect(err)); event.emit('error', err); event.emit('end', err); }); request.on('response', function(response){ response.setEncoding('utf8'); response.on('end', function(){ logger.debug('Connection End'); event.emit('end'); }); var buff = ""; response.on('data', function(chunk){ if( chunk.match(/\n/) ){ var chunks = chunk.split(/\r?\n/); var jsonStr = buff + chunks.shift(); var obj = null, err = null; if( jsonStr.length > 0 ){ _invokeCallback(jsonStr); } if( chunks.length ){ buff = chunks.pop(); // last buffer. } var c = ''; while(c = chunks.shift()){ _invokeCallback(c); } }else{ buff += chunk; } }); }); return event; } Client.prototype.chirpStream = function(params){ if( !params ){ params = {}; } var self = this; var url = "http://chirpstream.twitter.com/2b/user.json"; var request = this._oa.get(url, this._accessKey, this._accessSecret); var event = this._handleStream(request); request.end(); return event; } exports.Client = Client;
再利用できるようにライブラリ化を進めているので、機会があったら github に公開して、npm にも放り込んでおこうかと思います。モダンなAPIにアクセスするためのクライアント実装サンプル、みたいなモノ。