postal.js/example/node/twitter-search.js

129 lines
No EOL
3.4 KiB
JavaScript

var query = require( 'querystring' ),
http = require( 'http' );
var client = http.createClient( 80, "search.twitter.com" );
var TwitterSearch = function ( refreshInterval ) {
this.events = {};
this.timeoutFn = undefined;
this.searchPath = "/search.json";
this.refreshInterval = refreshInterval || 5000;
this.searchRegistry = {};
this.tweetRegistry = {};
this.defaultSearch = {};
this.nextSearch = undefined;
};
TwitterSearch.prototype = {
search : function ( searchTerm ) {
clearTimeout( this.timeoutFn );
this.raiseEvent( "search.init", searchTerm );
this.defaultSearch = {
q : searchTerm,
result_type : "recent",
rpp : 100
};
this.nextSearch = undefined;
this.searchRegistry = {};
this.tweetRegistry = {};
this.runSearch();
},
on : function ( eventName, callback ) {
if ( !this.events[ eventName ] ) {
this.events[ eventName ] = [];
}
this.events[ eventName ].push( callback );
return function () {
this.events[ eventName ] = _.without( this.events[ eventName ], callback );
}.bind( this );
},
raiseEvent : function ( eventName, data ) {
if ( this.events[ eventName ] ) {
this.events[ eventName ].forEach( function ( callback ) {
callback( data );
} );
}
},
buildUrl : function () {
var srchQry;
if ( this.nextSearch ) {
srchQry = this.nextSearch;
}
else {
if ( !this.defaultSearch.since_id ) {
delete this.defaultSearch.since_id;
}
srchQry = "?" + query.stringify( this.defaultSearch );
}
return this.searchPath + srchQry;
},
runSearch : function () {
var url = this.buildUrl();
if ( !this.searchRegistry[url] ) {
this.searchRegistry[url] = true;
this.raiseEvent( "search.current", { url : url } );
var request = client.request( "GET", url, {"host" : "search.twitter.com"} );
request.addListener( "response", function ( response ) {
var body = "";
response.addListener( "data", function ( data ) {
body += data;
} );
response.addListener( "end", function () {
this.onSearched( JSON.parse( body ) );
}.bind( this ) );
this.timeoutFn = setTimeout( this.runSearch.bind( this ), this.refreshInterval );
}.bind( this ) );
request.end();
}
else {
this.raiseEvent( "search.nodata", { url : url } );
this.timeoutFn = setTimeout( this.runSearch.bind( this ), this.refreshInterval );
}
},
onSearched : function ( payload ) {
// sift out errors
if ( !payload.error ) {
if ( payload.results.length > 0 ) {
this.processTweets( payload.results );
}
// do we have a next page option? If so, let's use it
if ( payload.next_page ) {
this.nextSearch = payload.next_page;
}
if ( payload.max_id ) {
this.defaultSearch.since_id = payload.max_id;
}
}
else {
this.nextSearch = undefined;
}
},
processTweets : function ( tweets ) {
var newTweets = tweets.filter( function ( t ) {
return !this.tweetRegistry[t];
}, this );
newTweets.forEach( function ( tweet ) {
if ( !this.tweetRegistry[tweet.id] ) {
this.tweetRegistry[tweet.id] = true;
}
// deal with the images that consistently fail from twitter...
if ( tweet.profile_image_url === "http://twitter.com/images/default_profile_normal.png" ||
tweet.profile_image_url === "http://static.twitter.com/images/default_profile_normal.png" ) {
tweet.profile_image_url = "templates/images/default_profile_1_normal.png";
}
}, this );
this.raiseEvent( "newTweets", newTweets );
}
};
module.exports = TwitterSearch;