Skip to content

Instantly share code, notes, and snippets.

@yssk22
Created September 12, 2010 14:14
Show Gist options
  • Save yssk22/576142 to your computer and use it in GitHub Desktop.
Save yssk22/576142 to your computer and use it in GitHub Desktop.
/**
* 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 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 || {
debug: function(){},
info: function(){},
warn: function(){},
critical: function(){},
error: function(){}
};
};
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 = atoken;
self._accessSecret = asecret;
callback && callback(null, akey, asecret);
}
}
);
});
}
});
};
Client.prototype._doGet = function(path, callback){
var url = [API_URL, path].join('');
this._oa.get(url, this._accessKey, this._accessSecret,
function(error, data, response){
callback && callback(error, data, response);
});;
};
Client.prototype._doPost = function(path, body, callback){
var url = [API_URL, path].join('');
this._oa.post(url, this._accessKey, this._accessSecret,
body,
function(error, data, response){
callback && callback(error, 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);
logger.debug('Emit data: ' + sys.inspect(obj));
event.emit('data', obj);
}catch(e){
err = e;
logger.debug('Emit error: ' + sys.inspect(err));
event.emit('error', e);
}
};
request.connection.on('error', function(err){
logger.debug('Connection Error: ' + sys.inspect(err));
event.emit('error', 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;
}
});
});
request.on('end', function(){
logger.debug('Request End');
event.emit('end');
});
return event;
}
Client.prototype.chirpStream = function(params){
if( typeof params == "function"){
callback = 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;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment