Merge
authorRaphael Velt <raph.velt@gmail.com>
Fri, 14 Oct 2011 17:36:34 +0200
changeset 315 77ccba188e08
parent 314 0f1e6ce19b6d (diff)
parent 313 270b9d0db234 (current diff)
child 316 26d83703fa63
child 325 7d9c576bfaac
Merge
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tweetcast/nodejs/client/css/style.css	Fri Oct 14 17:36:34 2011 +0200
@@ -0,0 +1,76 @@
+/* Browser-reset CSS */
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed, 
+figure, figcaption, footer, header, hgroup, 
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+	margin: 0;
+	padding: 0;
+	border: 0;
+	font-size: 100%;
+	font: inherit;
+	vertical-align: baseline;
+}
+
+body {
+	font-family: Helvetica, Arial, sans-serif;
+}
+
+/* Liste de Tweets */
+
+#tweetcontainer {
+	position: absolute; top: 25px; bottom: 5px; width: 270px; overflow: auto;
+}
+
+#tweetlist {
+	list-style: none;
+}
+
+li.tweet {
+	border: 1px solid #999; margin: 5px; width: 240px; height: 100px; overflow: hidden;
+}
+
+.tweet h4, .tweet p {
+	margin: 5px;
+}
+
+.tweet h4 {
+	font-size: 15px;
+}
+
+.tweet p {
+	font-size: 12px;
+}
+
+img.tweet_profile_image {
+	float: left; margin: 5px; width: 32px; height: 32px;
+}
+
+p.tweet_created_at {
+	font-style: italic; color: #999;
+}
+
+.a_positive {
+	background: #c5e7cd;
+}
+
+.a_negative {
+	background: #f6ced0;
+}
+
+.a_reference {
+	background: #ecedc1;
+}
+
+.a_question {
+	background: #bfdbec;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tweetcast/nodejs/client/index.html	Fri Oct 14 17:36:34 2011 +0200
@@ -0,0 +1,22 @@
+<!doctype html>
+<html>
+ <head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <title>Polemic Tweet “TweetCast”</title>
+  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
+  <script type="text/javascript">
+    S_IO_HOST = document.location.hostname;
+    S_IO_PORT = 8000;
+    document.write('<script type="text/javascript" src="http://' + S_IO_HOST + ':' + S_IO_PORT + '/socket.io/socket.io.js"><' + '/script>');
+  </script>
+  <script type="text/javascript" src="js/script.js"></script>
+  <link rel="stylesheet" href="css/style.css" type="text/css" />
+ </head>
+ <body>
+ <h1>Liste de Tweets</h1>
+ <div id="tweetcontainer">
+  <ul id="tweetlist">
+  </ul>
+ </div>
+ </body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tweetcast/nodejs/client/js/script.js	Fri Oct 14 17:36:34 2011 +0200
@@ -0,0 +1,153 @@
+var socket,
+    tweets = [],
+    waitoldtweets = true,
+    tl,
+    tc;
+
+function tweetToHtml(tweet) {
+	html = '<li class="tweet';
+	for (var i in tweet.annotations) {
+		html += ' a_' + tweet.annotations[i]
+	}
+	html += '" id="tweet_' + tweet.id + '">';
+	a_user = '<a href="http://twitter.com/' + tweet.user.screen_name + '" target="_blank" title="' + tweet.user.name + '">';
+	if (tweet.user.profile_image_url) {
+		html += a_user + '<img class="tweet_profile_image" src="' + tweet.user.profile_image_url + '" /></a>';
+	}
+	html += '<h4>' + a_user + '@' + tweet.user.screen_name + '</a></h4><p class="tweet_created_at">' + tweet.created_at + '</p><p>';
+	lastend = 0;
+	txt = '';
+	entities = [];
+	for (var i in tweet.entities.hashtag) {
+	    entities.push({
+	        "start" : tweet.entities.hashtag[i].indices[0],
+	        "end" : tweet.entities.hashtag[i].indices[1],
+	        "html" : '<a href="http://twitter.com/search?q=%23' + tweet.entities.hashtag[i].text + '" target="_blank">#' + tweet.entities.hashtag[i].text + '</a>'
+	    });
+	}
+	for (var i in tweet.entities.urls) {
+	    entities.push({
+	        "start" : tweet.entities.urls[i].indices[0],
+	        "end" : tweet.entities.urls[i].indices[1],
+	        "html" : '<a href="' + tweet.entities.urls[i].expanded_url + '" target="_blank">' + tweet.entities.urls[i].display_url + '</a>'
+	    });
+	}
+	for (var i in tweet.entities.user_mentions) {
+	    entities.push({
+	        "start" : tweet.entities.user_mentions[i].indices[0],
+	        "end" : tweet.entities.user_mentions[i].indices[1],
+	        "html" : '<a href="http://twitter.com/' + tweet.entities.user_mentions[i].screen_name + '" target="_blank" title="' + tweet.entities.user_mentions[i].name + '">@' + tweet.entities.user_mentions[i].screen_name + '</a>'
+	    });
+	}
+ 	entities.sort(function(a, b) { return a.start - b.start });
+    for (var i in entities) {
+ 		txt += tweet.text.substring(lastend, entities[i].start) + entities[i].html;
+        lastend = entities[i].end;
+    }
+	txt += tweet.text.substring(lastend);
+	html += txt + '</p></li>';
+	return html;
+}
+
+function discardTweets() {
+    if (tweets.length) {
+        while (tl.height() - (tc.scrollTop() + tc.height()) > 1000) {
+ 	        tl.children().last().detach();
+            tweets.pop();
+        }
+    }
+}
+
+// function scheduleTweets() {
+// 	var tl = $("#tweetlist"), tc = $("#tweetcontainer");
+// 	if (tweets.length != tl.children().length) {
+// 		console.log("Tweet count error");
+// 	}
+// 	if (tweets.length) {
+// 		while (tl.height() - (tc.scrollTop() + tc.height()) > 1000) {
+// 			tl.children().last().detach();
+// 			tweets.pop();
+// 		}
+// 		if (tl.height() - (tc.scrollTop() + tc.height()) < 120) {
+// 			getTweets({
+// 				before_id : tweets[tweets.length - 1].id,
+// 				limit : 5
+// 			});
+// 		}
+// 		getTweets({
+// 			after_id : tweets[0].id
+// 		});
+// 	} else {
+// 		getTweets({
+// 			limit: 15
+// 		});
+// 	}
+// }
+// 
+// function getTweets(params) {
+// 	$.getJSON("http://" + document.location.hostname + ":8888/?callback=?", params, function(data, a, b) {
+// 		if (data.tweets && data.tweets.length) {
+// 			var tl = $("#tweetlist"), tc = $("#tweetcontainer");
+// 			html = '';
+// 			for (var i in data.tweets) {
+// 				html += tweetToHtml(data.tweets[i]);
+// 			}
+// 			if (params.before_id) {
+// 				tl.append(html);
+// 				tweets = tweets.concat(data.tweets);
+// 			} else {
+// 				var pos = tc.scrollTop(), fixScroll = (pos > 80);
+// 				pos -= tl.height();
+// 				tl.prepend(html);
+// 				tweets = data.tweets.concat(tweets);
+// 				if (fixScroll) {
+// 					tc.scrollTop(tl.height() + pos);
+// 				}
+// 			}
+// 		}
+// 	});
+// }
+
+$(document).ready(function() {
+    tl = $("#tweetlist");
+    tc = $("#tweetcontainer");
+    socket = io.connect('http://' + S_IO_HOST + ':' + S_IO_PORT );
+    socket.on('tweets', function (data) {
+        tweets = data;
+        data.reverse();
+        html = '';
+        for (var i in data) {
+            html += tweetToHtml(data[i]);
+        }
+        $("#tweetlist").html(html);
+        discardTweets();
+    });
+    socket.on('oldtweets', function (data) {
+        tweets = tweets.concat(data);
+        html = '';
+        for (var i = data.length - 1; i >= 0; i--) {
+            html += tweetToHtml(data[i]);
+        }
+        $("#tweetlist").append(html);
+        discardTweets();
+        waitoldtweets = true;
+    });
+    socket.on('newtweet', function (data) {
+        tweets.splice(0,0,data);
+        html = tweetToHtml(data);
+        var scrollpos = tc.scrollTop(),
+            fixScroll = (scrollpos > 80);
+        scrollpos -= tl.height();
+        $("#tweetlist").prepend(html);
+        if (fixScroll) {
+    		tc.scrollTop(tl.height() + scrollpos);
+		}
+        discardTweets();
+    });
+    $("#tweetcontainer").scroll(function() {
+        if ( waitoldtweets && tl.height() - (tc.scrollTop() + tc.height()) < 120 ) {
+            socket.emit('tweetsbefore', tweets[tweets.length-1].id );
+            waitoldtweets = false;
+        }
+    });
+});
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tweetcast/nodejs/server/node-direct.js	Fri Oct 14 17:36:34 2011 +0200
@@ -0,0 +1,74 @@
+var fs = require('fs'),
+    https = require('https'),
+    io = require('socket.io')
+        .listen(8000)
+    keyword = "Bieber",
+    tweets = [],
+    tweet_ids = [],
+    annkw = {
+        'positive' : '++',
+        'negative' : '--',
+        'reference' : '==',
+        'question' : '??'
+    }
+
+function textids(object) {
+    for (var key in object) {
+        if (key.substr(-2) == 'id') {
+            object[key] = object[key + '_str'];
+            delete object[key + '_str'];
+        }
+    }
+}
+
+var fd = fs.createWriteStream('tweets.txt');
+
+req = https.request({
+    host: "stream.twitter.com",
+    path: "/1/statuses/filter.json",
+    method: "POST",
+    headers: {
+        'Authorization': 'Basic cmFwaHY6N3czMzdMZkMyM2dF',
+        'Content-Type': 'application/x-www-form-urlencoded'
+    }
+}, function(res) {
+    console.log('STATUS: ' + res.statusCode);
+    console.log('HEADERS: ' + JSON.stringify(res.headers));
+    res.setEncoding('utf8');
+    res.on('data', function(chunk) {
+        newdata = chunk.split('\r\n');
+        try {
+            for (var i in newdata) {
+                if (newdata[i].length > 0) {
+                    tweet = JSON.parse(newdata[i]);
+                    annotations = [];
+                    for (var a in annkw) {
+                        if (tweet.text.indexOf(annkw[a]) != -1) {
+                            annotations.push(a);
+                        }
+                    }
+                    tweet.annotations = annotations;
+                    tweets.push(tweet);
+                    textids(tweet);
+                    tweet_ids.push(tweet.id_str);
+                    io.sockets.emit('newtweet', tweet);
+                }
+            }
+            fd.write(chunk); 
+        }
+        catch(err) {
+            console.log(err);
+        }
+    });
+});
+
+req.write('track=' + encodeURIComponent(keyword));
+req.end();
+io.set('log level', 0);
+io.sockets.on('connection', function(socket) {
+    socket.emit('tweets', tweets.slice(-10));
+    socket.on('tweetsbefore', function(data) {
+        tweetpos = tweet_ids.indexOf(data);
+        socket.emit('oldtweets', tweets.slice(0, tweetpos).slice(-10));
+    });
+});
\ No newline at end of file