Permalink
Browse files

Merge remote branch 'upstream/master'

Conflicts:
	.gitignore
	public/lib/stream/app.js
	public/lib/stream/helpers.js
	public/lib/stream/streamplugins.js
	public/templates/settingsDialog.ejs.html
  • Loading branch information...
jeromeetienne committed Oct 12, 2010
2 parents d1027fe + 1c6f47a commit 1852bab46916e043788bed0553dce5e4ad7dbf0e
Showing with 2,415 additions and 962 deletions.
  1. +2 −1 .gitignore
  2. +9 −0 config.sample.json
  3. +31 −0 lib/config.js
  4. +99 −0 lib/message-queue.js
  5. +4 −4 lib/oauth.js
  6. +33 −50 lib/server.js
  7. +3 −3 lib/twitter-rest-proxy.js
  8. +203 −0 lib/twitter-site-stream-connector.js
  9. +14 −9 lib/twitter-stream-client.js
  10. +29 −0 package.json
  11. +0 −20 public/client.js
  12. +6 −1 public/css/basic.less
  13. +5 −0 public/css/forms.less
  14. +82 −44 public/css/stream.less
  15. +1 −0 public/css/vars.less
  16. +1 −1 public/ext/socket.io
  17. BIN public/images/ic_share.gif
  18. +6 −5 public/index.html
  19. +6 −3 public/lib/stream/app.js
  20. +13 −2 public/lib/stream/client.js
  21. +2 −0 public/lib/stream/helpers.js
  22. +78 −3 public/lib/stream/initplugins.js
  23. +12 −9 public/lib/stream/settings.js
  24. +14 −4 public/lib/stream/settingsDialog.js
  25. +132 −36 public/lib/stream/status.js
  26. +41 −3 public/lib/stream/streamplugins.js
  27. +3 −3 public/lib/stream/tweetstream.js
  28. +1 −0 public/lib/stream/twitterRestAPI.js
  29. +33 −0 public/lib/stream/versionControl.js
  30. +0 −191 public/prototype/client.html
  31. +270 −0 public/prototype/css/basic.less
  32. +259 −0 public/prototype/css/forms.less
  33. +10 −0 public/prototype/css/grid.less
  34. 0 public/prototype/{extensions → }/css/keyframe.css
  35. +18 −22 public/prototype/{extensions → }/css/popin.less
  36. +359 −0 public/prototype/css/stream.less
  37. +4 −2 public/prototype/{extensions/css/client.less → css/streamie.less}
  38. +219 −0 public/prototype/css/vars.less
  39. +67 −0 public/prototype/ext/less-1.0.35.min.js
  40. +0 −289 public/prototype/extensions/css/basic.less
  41. +0 −33 public/prototype/extensions/css/grid.less
  42. +0 −145 public/prototype/extensions/css/vars.less
  43. +0 −66 public/prototype/extensions/js/ext/less-1.0.33.min.js
  44. +324 −0 public/prototype/index.html
  45. +8 −5 public/templates/settingsDialog.ejs.html
  46. +3 −1 public/templates/status.ejs.html
  47. +10 −7 public/templates/tweet.ejs.html
  48. +1 −0 public/version.txt
View
@@ -1,4 +1,5 @@
lib/startup.bash
lib/data/
-*.kpf
*bbproject*
+config.json
+.DS_Store
View
@@ -0,0 +1,9 @@
+{
+ "hostNameAndOptionalPort": "streamie.com:8888",
+ "oauthKey": "asdgsdfgsdfgsdfg",
+ "oauthSecret": "sdfgsdfgsdfgsdfgsd",
+ "port": 8888,
+ "imgurKey": "sdfgsdfgsdfgsdfgsdfg",
+ "staticFilesExpireSeconds": 0,
+ "siteStreamOAuthToken": "asdasdfasd"
+}
View
@@ -0,0 +1,31 @@
+
+/* Streamie configuration
+
+Sample:
+
+{
+ "hostNameAndOptionalPort": "streamie.com:8888",
+ "oauthKey": "asfsadgsadgsdfg",
+ "oauthSecret": "sdfgsdfgsdfgsdfgsdfg",
+ "port": "8888",
+ "imgurKey": "sdfgsdfgsdfg", // Optional
+ "staticFilesExpireSeconds": 0,
+ "siteStreamOAuthToken": "efasdfasdf" // Optional
+}
+
+*/
+
+
+
+function init() {
+ var filename = __dirname+"/../config.json";
+ var text = require("fs").readFileSync(filename);
+ if(!text) {
+ throw new Error("Couldn't read config file "+filename);
+ }
+ var obj = JSON.parse(text);
+ console.log("Successfully read and parsed config file \n"+JSON.stringify(obj, null, " ")+"\n");
+ return obj;
+}
+
+exports.config = init();
View
@@ -0,0 +1,99 @@
+
+/*
+ A Module that exposes a message queue. One can subscribe to channels and receive
+ callbacks when someone publishes messages to these channels
+*/
+
+var Subscribers = {};
+
+// Subscription objects are returned by the subscribe function.
+function Subscription (channels, cb) {
+ this.channels = channels;
+ this.cb = cb;
+}
+
+// Call this method to unsubscribe a subscription
+Subscription.prototype.unsubscribe = function () {
+ var cb = this.cb;
+ this.channels.forEach(function (channel) {
+ var subs = Subscribers[channel];
+ if(subs) {
+ var filtered = subs.filter(function (s) {
+ return s !== cb;
+ });
+ if(filtered.length === 0) {
+ delete Subscribers[channel]
+ } else {
+ Subscribers[channel] = filtered;
+ }
+ }
+ })
+}
+
+// Subscribe to an array of channels (TODO make this an array or string)
+// listenerCB will be fired when an event is published to one of the channels.
+exports.subscribe = function (channels, listenerCB) {
+ if(typeof listenerCB != "function") {
+ throw new Error("subscribe needs a callback parameter");
+ }
+ channels.forEach(function (channel) {
+ var subs = Subscribers[channel];
+ if(!subs) {
+ subs = Subscribers[channel] = [];
+ }
+ subs.push(listenerCB);
+ })
+ return new Subscription(channels, listenerCB);
+}
+
+// Publish an event of data to a channel
+exports.publish = function (channel, data) {
+ var subs = Subscribers[channel];
+ if(subs) {
+ for(var i = 0, len = subs.length; i < len; ++i) {
+ subs[i](data, channel);
+ }
+ }
+}
+
+function ok(bool, msg) {
+ if(bool) {
+ console.log("OK "+msg);
+ } else {
+ console.log("OK "+msg);
+ }
+}
+
+function test() {
+ var pubsub = exports;
+ var s0 = pubsub.subscribe(["foo", "bar"], function (data, channel) {
+ console.log("Fire s0 "+channel+" "+data);
+ });
+ var s1 = pubsub.subscribe(["bar"], function (data, channel) {
+ console.log("Fire s1 "+channel+" "+data);
+ });
+ var s2 = pubsub.subscribe(["foo", "bar", "baz"], function (data, channel) {
+ console.log("Fire s2 "+channel+" "+data);
+ });
+
+ pubsub.publish("foo", 1);
+ pubsub.publish("foo", 2);
+ pubsub.publish("bar", 3);
+ pubsub.publish("baz", 4);
+
+ ok(Subscribers["bar"].length === 3, "3 subs to bar");
+ s1.unsubscribe();
+ pubsub.publish("bar", 5);
+ ok(Subscribers["bar"].length === 2, "2 subs to bar");
+ s2.unsubscribe();
+ pubsub.publish("bar", 6);
+ ok(Subscribers["bar"].length === 1, "1 subs to bar");
+ s0.unsubscribe();
+ ok(!("bar" in Subscribers), "no subscribers to bar");
+ pubsub.publish("bar", 7);
+ var s3 = pubsub.subscribe(["foo", "bar"], function (data, channel) {
+ console.log("Fire s3 "+channel+" "+data);
+ });
+ ok(("bar" in Subscribers), "A subscriber came back");
+ pubsub.publish("bar", 8);
+}
View
@@ -43,21 +43,21 @@ exports.request = function (key, secret, oauth_callback_url, cb) {
oa.getOAuthRequestToken(function(error, oauth_token, oauth_token_secret, results){
if(error) cb('error :' + JSON.stringify(error))
else {
- sys.puts('oauth_token :' + oauth_token)
+ /*sys.puts('oauth_token :' + oauth_token)
sys.puts('oauth_token_secret :' + oauth_token_secret)
sys.puts('requestoken results :' + sys.inspect(results))
sys.puts("Requesting access token")
- sys.puts("http://api.twitter.com/oauth/authorize?oauth_token="+oauth_token);
+ sys.puts("http://api.twitter.com/oauth/authorize?oauth_token="+oauth_token);*/
var cont = function (oauth_token_verifier, cb) {
oa.getOAuthAccessToken(oauth_token, oauth_token_secret, oauth_token_verifier, function(error, oauth_access_token, oauth_access_token_secret, results2) {
if(error) {
cb("Request Error "+JSON.stringify(error))
} else {
- sys.puts('oauth_access_token :' + oauth_access_token)
+ /*sys.puts('oauth_access_token :' + oauth_access_token)
sys.puts('oauth_token_secret :' + oauth_access_token_secret)
sys.puts('accesstoken results :' + sys.inspect(results2))
- sys.puts("Requesting access token")
+ sys.puts("Requesting access token")*/
var data= "";
store.save(oauth_token, {
View
@@ -8,22 +8,29 @@ var http = require('http'),
twitterClient = require('./twitter-stream-client'),
twitterProxy = require('./twitter-rest-proxy'),
lessHandler = require('./less-handler'),
- stats = require('./stats');
-
+ stats = require('./stats'),
+ config = require('./config').config,
+ stream = require('./twitter-site-stream-connector');
// change this to a configuration file
-var host = process.ARGV[2];
-var key = process.ARGV[3];
-var secret = process.ARGV[4];
-var port = parseInt(process.ARGV[5], 10) || 8888;
-var IMGUR_KEY = process.ARGV[6];
+var host = config.hostNameAndOptionalPort;
+var key = config.oauthKey;
+var secret = config.oauthSecret;
+var port = config.port;
+var IMGUR_KEY = config.imgurKey;
+var cacheTime = config.staticFilesExpireSeconds || 0;
if(!host || !key || !secret) {
- sys.error("USAGE node process.js HOST(optional incl. portnumer for non-80) KEY SECRET PORT [imgur.com key]");
+ sys.error("Missing config paras. Config is "+JSON.stringify(config, null, " "));
process.exit();
}
+process.on('uncaughtException', function (err) {
+ console.log('[UNCAUGHT EXCEPTION] ' +err+'\n' + JSON.stringify(err, null, " "));
+ process.exit();
+});
+
// the static file server
-var file = new(static.Server)('../public', { cache: 0 });
+var file = new(static.Server)('../public', { cache: parseInt(cacheTime, 10) });
var Token = {}; // Temp store for Tokens. TODO: Make this not a memory leak and scale to multiple nodes
var TransferURL = {};
@@ -56,7 +63,7 @@ var server = http.createServer(function (request, response) {
// Please somebody put in a middleware/router thing!
var url = require('url').parse(request.url, true);
- console.log(JSON.stringify(request.headers))
+ console.log("Request "+url.pathname);
// /access
// Prepare oauth negotiation and send user to Twitter
@@ -86,6 +93,11 @@ var server = http.createServer(function (request, response) {
console.log("oauth step 1 success");
Token[token] = cont;
+
+ setTimeout(function () { // clear out memory after 10 minutes
+ delete Token[token];
+ }, 60 * 10 * 1000);
+
response.writeHead(302, { // onto Twitter
'Location': transferURL
});
@@ -184,7 +196,7 @@ var server = http.createServer(function (request, response) {
request.on("end", function () {
getTwitterApiClient(function (err, requester) {
- console.log("Proxying API call "+request.url);
+ //console.log("Proxying API call "+request.url);
twitterProxy.proxy(requester, request, response, data.join(""))
});
})
@@ -267,13 +279,13 @@ function now() {
socket.on('connection', function(client){
console.log("Connection");
- var tweety, interval;
-
// We always send JSON
function send(data) {
client.send(JSON.stringify(data))
}
+ var subscription;
+
var last = now();
client.on('message', function(msg){
@@ -300,38 +312,11 @@ socket.on('connection', function(client){
info: info
})
- var open = true;
-
- interval = setInterval(function () {
- if(now() - last > 10000) {
- clearInterval(interval)
- if(tweety && open) {
- console.log("Client Connection Timeout. Close Stream")
- tweety.end();
- }
- }
- }, 10000)
-
- // connect to backend twitter stream
- tweety = twitterClient.connect(requester, function (err, data) {
- console.log("Stream response "+err+data)
- if(err) {
- open = false;
- console.log(err);
- send({
- streamError: err
- });
- if(!err.connection == "close") {
- tweety.end();
- }
- } else {
- dummies.push(data);
- send({
- tweet: data
- });
- console.log(data);
- }
- });
+ subscription = stream.subscribe(info.user_id, function (data) {
+ send({
+ tweet: data
+ });
+ }, requester);
}
});
}
@@ -350,11 +335,9 @@ socket.on('connection', function(client){
stats.inc("con");
client.on('disconnect', function(){
stats.dec("con");
- if(interval) {
- clearInterval(interval);
- }
- if(tweety) {
- tweety.end();
+ if(subscription) {
+ subscription.unsubscribe();
}
})
});
+
@@ -6,7 +6,7 @@ var base = "https://api.twitter.com";
exports.proxy = function (requester, serverRequest, serverResponse, data) {
var url = serverRequest.url + (data ? '?'+data : ''); // for now send post data via Query String. (bug in node-oauth with post not going into signature)
- console.log("Onto twitter "+serverRequest.method);
+ //console.log("Onto twitter "+serverRequest.method);
exports.client(requester, url, serverRequest.method, function (error, request) {
if(error) {
response.writeHead(501, {
@@ -15,10 +15,10 @@ exports.proxy = function (requester, serverRequest, serverResponse, data) {
response.end(error+"");
console.log("Twitter OAuth Error "+error);
} else {
- console.log("Got request");
+ //console.log("Got request");
request.on("response", function (response) {
response.setEncoding('utf8');
- console.log("Got Twitter response "+response.statusCode + " "+JSON.stringify(response.headers));
+ //console.log("Got Twitter response "+response.statusCode + " "+JSON.stringify(response.headers));
serverResponse.writeHead(response.statusCode, response.headers);
response.on("data", function (chunk) {
serverResponse.write(chunk);
Oops, something went wrong.

0 comments on commit 1852bab

Please sign in to comment.