--- /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