node.js/twitter.js
author Dominqique Hazael-Massieux <dom@w3.org>
Thu, 01 Sep 2011 16:11:31 +0200
changeset 222 14c23b5c82db
parent 211 f05301b70cd7
child 227 bef61d10f80b
permissions -rw-r--r--
note about todo
182
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
     1
var http = require('http');
193
8c79cbf30714 using https for stream api
Dominique Hazaël-Massieux <dom@w3.org>
parents: 191
diff changeset
     2
var https = require('https');
182
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
     3
var EventEmitter = require('events').EventEmitter;
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
     4
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
     5
function loadTwitterListPage(owner, slug, cursor, users, callback) {
183
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
     6
    // Rate limited to 150 / hour, beware!
182
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
     7
   var request = http.get({host: 'api.twitter.com', path:'/1/lists/members.json?slug=' + slug + '&owner_screen_name=' + owner + '&skip_status=1&cursor=' + cursor}, function (response) {
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
     8
       response.setEncoding('utf8');
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
     9
       var twitterDataJSON = "", twitterData;
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
    10
       response.on('data', function (chunk) {
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
    11
	   twitterDataJSON = twitterDataJSON + chunk;
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
    12
       });
187
2054c111a2fb removing console.log
Dominique Hazaël-Massieux <dom@w3.org>
parents: 186
diff changeset
    13
       response.on(
2054c111a2fb removing console.log
Dominique Hazaël-Massieux <dom@w3.org>
parents: 186
diff changeset
    14
	   'end',
2054c111a2fb removing console.log
Dominique Hazaël-Massieux <dom@w3.org>
parents: 186
diff changeset
    15
	   function () {
2054c111a2fb removing console.log
Dominique Hazaël-Massieux <dom@w3.org>
parents: 186
diff changeset
    16
	       if (response.statusCode != 200){
2054c111a2fb removing console.log
Dominique Hazaël-Massieux <dom@w3.org>
parents: 186
diff changeset
    17
  		   console.log(response.statusCode + JSON.stringify(response.headers));		   
2054c111a2fb removing console.log
Dominique Hazaël-Massieux <dom@w3.org>
parents: 186
diff changeset
    18
	       }
2054c111a2fb removing console.log
Dominique Hazaël-Massieux <dom@w3.org>
parents: 186
diff changeset
    19
	       twitterData = JSON.parse(twitterDataJSON);
2054c111a2fb removing console.log
Dominique Hazaël-Massieux <dom@w3.org>
parents: 186
diff changeset
    20
	       users = users.concat(twitterData.users);
2054c111a2fb removing console.log
Dominique Hazaël-Massieux <dom@w3.org>
parents: 186
diff changeset
    21
	       if (twitterData.next_cursor) {
2054c111a2fb removing console.log
Dominique Hazaël-Massieux <dom@w3.org>
parents: 186
diff changeset
    22
		   loadTwitterListPage(owner, slug, twitterData.next_cursor, users, callback);
2054c111a2fb removing console.log
Dominique Hazaël-Massieux <dom@w3.org>
parents: 186
diff changeset
    23
	       } else {
2054c111a2fb removing console.log
Dominique Hazaël-Massieux <dom@w3.org>
parents: 186
diff changeset
    24
		   callback(users);
2054c111a2fb removing console.log
Dominique Hazaël-Massieux <dom@w3.org>
parents: 186
diff changeset
    25
	       }
2054c111a2fb removing console.log
Dominique Hazaël-Massieux <dom@w3.org>
parents: 186
diff changeset
    26
	   });
2054c111a2fb removing console.log
Dominique Hazaël-Massieux <dom@w3.org>
parents: 186
diff changeset
    27
			  });
182
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
    28
}
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
    29
211
f05301b70cd7 renamed listTwitterIds to listTwitterIdsFromTwitterlist
Dominqique Hazael-Massieux <dom@w3.org>
parents: 209
diff changeset
    30
exports.listTwitterIdsFromTwitterList = function(list_owner, list_slug, callback) {
183
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    31
    loadTwitterListPage(
186
b05a161d3ad3 fixing variable names
Dominique Hazaël-Massieux <dom@w3.org>
parents: 183
diff changeset
    32
	list_owner,
b05a161d3ad3 fixing variable names
Dominique Hazaël-Massieux <dom@w3.org>
parents: 183
diff changeset
    33
	list_slug,
183
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    34
	    -1,
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    35
	[], 
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    36
	function (users) {
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    37
	    var twitterIds = [];
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    38
	    for (u in users) {
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    39
		twitterIds.push(users[u].id);
182
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
    40
	    }
183
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    41
	    callback(twitterIds);
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    42
    
182
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
    43
	});
183
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    44
};
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    45
208
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    46
exports.getTwitterId = function(screen_name, callback) {
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    47
   var request = http.get(
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    48
       {host: 'api.twitter.com', path:'/1/users/lookup.json?screen_name=' + screen_name},
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    49
       function (response) {
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    50
	   response.setEncoding('utf8');
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    51
	   var twitterDataJSON = "", twitterData;
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    52
	   response.on('data', function (chunk) {
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    53
	       twitterDataJSON = twitterDataJSON + chunk;
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    54
	   });
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    55
	   response.on(
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    56
	       'end',
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    57
	       function () {
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    58
		   if (response.statusCode != 200){
209
96dd338b6730 error reporting
Dominqique Hazael-Massieux <dom@w3.org>
parents: 208
diff changeset
    59
		       callback("Looking twitter user id failed: " + response.statusCode + JSON.stringify(response.headers), null);
208
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    60
		   } else {
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    61
		       try {
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    62
			   twitterData = JSON.parse(twitterDataJSON);
209
96dd338b6730 error reporting
Dominqique Hazael-Massieux <dom@w3.org>
parents: 208
diff changeset
    63
			   callback(null, twitterData[0].id);
208
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    64
		       } catch (err) {
209
96dd338b6730 error reporting
Dominqique Hazael-Massieux <dom@w3.org>
parents: 208
diff changeset
    65
			   callback("Failed to parse response from Twitter API (" + err + ")", null);
208
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    66
		       }
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    67
		   }
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    68
	       });
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    69
       });
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    70
};
d815783a4272 added getTwitterId function
Dominqique Hazael-Massieux <dom@w3.org>
parents: 204
diff changeset
    71
194
6830fb1e027b use emitter as param
Dominique Hazaël-Massieux <dom@w3.org>
parents: 193
diff changeset
    72
exports.listenToTweets = function(emitter, twitter_ids, twitter_auth)  {
193
8c79cbf30714 using https for stream api
Dominique Hazaël-Massieux <dom@w3.org>
parents: 191
diff changeset
    73
    var stream = https.request(
222
14c23b5c82db note about todo
Dominqique Hazael-Massieux <dom@w3.org>
parents: 211
diff changeset
    74
	{
14c23b5c82db note about todo
Dominqique Hazael-Massieux <dom@w3.org>
parents: 211
diff changeset
    75
	    host: 'stream.twitter.com'
14c23b5c82db note about todo
Dominqique Hazael-Massieux <dom@w3.org>
parents: 211
diff changeset
    76
	    // host: 'localhost', port: 3030
14c23b5c82db note about todo
Dominqique Hazael-Massieux <dom@w3.org>
parents: 211
diff changeset
    77
	 , path:'/1/statuses/filter.json', 'method': 'POST'}, 
183
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    78
	function (res) {
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    79
	    res.setEncoding('utf8');
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    80
	    var incompleteChunk = "";
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    81
	    res.on(
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    82
		'data',
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    83
		function (chunk) {
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    84
		    incompleteChunk += chunk;
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    85
		    incompleteChunk = incompleteChunk.trim();
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    86
		    if (incompleteChunk) {
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    87
			try {
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    88
			    var tweet = JSON.parse(incompleteChunk);
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    89
			    emitter.emit("tweet", tweet);
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    90
			    incompleteChunk = "";
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    91
			} catch (err) {
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    92
			    console.log(err);
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    93
			}
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    94
		    }
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    95
		});
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    96
	    res.on(
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    97
		'end',
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    98
		function () {
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
    99
		    console.log("Twitter stream terminated with error " + res.statusCode);
191
7b0015a41e79 more console.logging in case of error
Dominique Hazaël-Massieux <dom@w3.org>
parents: 190
diff changeset
   100
		    console.log(JSON.stringify(res.headers));
222
14c23b5c82db note about todo
Dominqique Hazael-Massieux <dom@w3.org>
parents: 211
diff changeset
   101
		    // @@@ retry connection but with rate regulation
183
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
   102
		});
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
   103
	}
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
   104
    );
182
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
   105
    stream.setHeader("Content-Type", "application/x-www-form-urlencoded");
190
1bf9fc669e29 use encoded auth header
Dominique Hazaël-Massieux <dom@w3.org>
parents: 187
diff changeset
   106
    stream.setHeader("Authorization", 'Basic ' + twitter_auth);
183
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
   107
    stream.write("follow=" + twitter_ids.join(","));
182
659a8ba1c9f5 experimenting with twitter access
Dominqique Hazael-Massieux <dom@w3.org>
parents:
diff changeset
   108
    stream.end();
204
ccfdf62e9770 event for twitterListChange
Dominqique Hazael-Massieux <dom@w3.org>
parents: 194
diff changeset
   109
    emitter.on("twitterListChange", function() {
ccfdf62e9770 event for twitterListChange
Dominqique Hazael-Massieux <dom@w3.org>
parents: 194
diff changeset
   110
	stream.abort();
ccfdf62e9770 event for twitterListChange
Dominqique Hazael-Massieux <dom@w3.org>
parents: 194
diff changeset
   111
    });
183
ff93e10d4604 reorganized as a module
Dominique Hazaël-Massieux <dom@w3.org>
parents: 182
diff changeset
   112
};