Skip to content

Instantly share code, notes, and snippets.

@moderation
Created July 9, 2010 03:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moderation/468983 to your computer and use it in GitHub Desktop.
Save moderation/468983 to your computer and use it in GitHub Desktop.
body { font-family: Helvetica; text-rendering: optimizeLegibility; }
section { display: block; width: 24.5%; float: left; border-left: 1px dotted #dcdcdc; }
a { text-decoration: none; }
img { border: 0; }
#tweets, #retweets, #favorites, #conversations { font-size: 14px; padding: 0; margin: 0; }
#tweets a, #retweets a, #favorites a, #conversations a { color: #2277bb; }
#tweets .meta a, #retweets .meta a, #favorites .meta a, #conversations .meta a { color: #999; background: #f7f7f7; }
.hentry { margin-left: 58px; margin-right: 29px; }
.hentry .meta { color: #dcdcdc; font-size: 11px; margin: 3px 0 0; display: block; }
.content { clear: left; min-height: 48px; padding: 9px; line-height: 1.1; position: relative; }
.content:hover { background-color: #F7F7F7; }
.vcard { float: left; }
a.at { background: #fcfebf; }
a.li { background: #ffe6ff; }
a.ha { background: #e6ffff; }
.conv { background-image: url(conversation.png); background-repeat: no-repeat; background-position: left center; padding-left: 20px; margin: auto 3px auto 5px; }
.retw { background-image: url(retweet.png); background-repeat: no-repeat; background-position: left center; padding-left: 20px; margin: auto 3px auto 5px; }
.veri { background-image: url(verified.png); background-repeat: no-repeat; background-position: left center; padding-left: 15px; margin: auto 3px auto 5px; }
.fvrt { background-image: url(star14.png); background-repeat: no-repeat; background-position: left center; padding-left: 20px; margin: auto 3px auto 5px; }
var twat = false, retweet = false, favorite = false, conversation = false, retweeter, favoriter, ENTITIES = { '&quot;': '"','&lt;': '<','&gt;': '>' }, entries;
var ify = function() {
return {
entities: function(t) { return t.replace(/(&[a-z0-9]+;)/g, function(m) { return ENTITIES[m]; }); },
link: function(t) { return t.replace(/[a-z]+:\/\/[a-z0-9-_✪]+\.[a-z0-9-_:~\+#%&\?\/.=]+[^:\.,\)\s*$]/ig, function(m) { return '<a target=_blank class=li href=' + m + ' title=' + m + '>' + ((m.length > 35) ? m.substr(0, 34) + '...' : m) + '</a>'; }); },
at: function(t) { return t.replace(/(^|[^\w]+)\@([a-zA-Z0-9_]{1,15}(\/[a-zA-Z0-9-_]+)*)/g, function(m, m1, m2) { return m1 + '@<a target=_blank class=at href=https://twitter.com/' + m2 + '>' + m2 + '</a>'; }); },
hash: function(t) { return t.replace(/(^|[^&\w'"]+)\#([a-zA-Z0-9_]+)/g, function(m, m1, m2) { return m1 + '#<a target=_blank class=ha href=https://search.twitter.com/search?q=%23' + m2 + '>' + m2 + '</a>'; }); },
clean: function(tweet) { return this.hash(this.at(this.link(tweet))); }
};
}();
function modifyText() { this.style.borderRight = "2px solid red"; }
$(document).ready(function(){
if(!("WebSocket" in window)) { alert("Sorry, the build of your browser does not support WebSockets."); return; }
// var ws = new WebSocket("ws://127.0.0.1:8000/");
// var ws = new WebSocket("ws://192.168.1.100:8000/");
var ws = new WebSocket("ws://localhost:8000/");
ws.onmessage = function (evt) {
var tweet = JSON.parse(evt.data);
if (tweet.error) { console.log('Error: ' + tweet.error); }
if (tweet.retweeted_status) { // reload tweet with retweet
retweet = true;
retweeter = tweet.user.screen_name;
tweet = tweet.retweeted_status;
}
else if (tweet.target_object) { // reload tweet with favorite
favorite = true;
favoriter = tweet.source.screen_name;
tweet = tweet.target_object;
}
else if (tweet.in_reply_to_screen_name != null) { // conversation
conversation = true;
}
else {
twat = true;
}
var html = '<div class=content><div class=vcard><a target=_blank class=url href=https://twitter.com/' + tweet.user.screen_name + '><img style=height:48px;width:48px; alt="' + tweet.user.name + '" class="photo fn" height=48 src=' + tweet.user.profile_image_url + ' width=48></a></div><div class=hentry><strong>';
if (tweet.user.verified) { html += '<span class=veri>'; }
html += '<a target=_blank href=https://twitter.com/' + tweet.user.screen_name + ' title="' + tweet.user.name + '">' + tweet.user.screen_name + '</a></strong> ';
if (tweet.user.verified) { html += '</span>'; }
html += ify.clean(tweet.text) + '<span class=meta><a target=_blank href=https://twitter.com/' + tweet.user.screen_name;
html += '/status/' + tweet.id + ' class=entry-date rel=bookmark><span class=published title="';
html += tweet.created_at + '">' + tweet.created_at.replace(" +0000 2010","") + '</span></a>';
if (tweet.source) { html += ' | ' + tweet.source.replace("Twitter for iPhone","iTwitter"); }
if (tweet.in_reply_to_screen_name != null) { html += ' <a target=_blank href=https://twitter.com/' + tweet.in_reply_to_screen_name + '/status/' + tweet.in_reply_to_status_id + '><span class=conv>' + tweet.in_reply_to_screen_name + '</span></a> | <a target=_blank href=http://www.exquisitetweets.com/generate?end=' + tweet.id + '>thread</a>'; }
if (retweet) { html += ' @<a target=_blank class=url href=https://twitter.com/' + retweeter + '><span class=retw>' + retweeter + '</span></a>'; }
if (favorite) { html += ' via @<a target=_blank class=url href=https://twitter.com/' + favoriter + '><span class=fvrt>' + favoriter + '</span></a>'; }
html += '</span></div></div>';
var p = $(html);
/*
if( $('#tweets > .tweet').length > 999) {
$('#tweets >li:last').slideDown(1000, function() {
$(this).remove();
});
}
*/
if (retweet) {
$('#retweets').prepend(p);
} else if (favorite) {
$('#favorites').prepend(p);
} else if (conversation) {
$('#conversations').prepend(p);
} else {
$('#tweets').prepend(p);
}
p.bind('click', modifyText);
p.slideDown(140);
if (window.webkitNotifications && !conversation) {
if (window.webkitNotifications.checkPermission() == 0) {
var popup = window.webkitNotifications.createNotification(tweet.user.profile_image_url, tweet.user.screen_name, tweet.text); // note the show()
popup.show();
setTimeout(function(){ popup.cancel(); }, '15000'); // 15 seconds
} else {
window.webkitNotifications.requestPermission();
}
}
favorite = false; retweet = false; twat = false; conversation = false;
};
ws.onopen = function() { console.log("Socket opened"); };
ws.onclose = function() { console.log("Socket closed"); };
});
<!DOCTYPE html>
<head>
<meta charset=utf-8>
<title>@hartley userstream</title>
<link rel=stylesheet href=twitter.css media=all>
<script src=http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js></script>
<script src=twitter.js></script>
</head>
<body>
<section id=tweets><div class=content><p>tweets</p></div></section>
<section id=retweets><div class=content><p>retweets</p></div></section>
<section id=conversations><div class=content><p>conversations</p></div></section>
<section id=favorites><div class=content><p>favorites</p></div></section>
</body>
var USERNAME = 'XXXXXX'
, PASSWORD = 'XXXXXX'
, sys = require('sys')
, http = require('http')
, ws = require('./vendor/ws')
, base64 = require('./vendor/base64')
, logger = require("./vendor/logger");
var a, wait = false;
// Authentication Headers for Twitter
var auth = base64.encode(USERNAME + ':' + PASSWORD)
, headers = {'authorization':'Basic ' + auth, 'host':'betastream.twitter.com', 'content-type':'application/json'};
// Connection to Twitter's streaming API
var twitter = http.createClient(443, "betastream.twitter.com", true)
// , request = twitter.request("GET", "/2b/user.json", headers);
, request = twitter.request("GET", "/2b/user.json?replies=all", headers);
request.on('response', function (response) {
sys.debug("STATUS: " + response.statusCode);
sys.debug("HEADER: " + JSON.stringify(response.headers));
response.setEncoding("utf8");
response.on("data", function (chunk) {
if ( chunk.substr(0,8) == "{\"friend" && lastchar != '}') { sys.debug("FRIEND: " + chunk); return; } // check for friends header and abort
if ( chunk.length < 3 ) { return; } // check for heartbeat and abort
if ( chunk.substr(0,8) == "{\"delete" ) { sys.debug("Delete ####"); return; } // check for delete and abort
var firstchar = chunk.charAt(0), lastchar = chunk.charAt(chunk.length - 3);
// START
if ( firstchar == '{' && lastchar != '}' ) { // looking for partial sends and then combining them
a = chunk;
wait = true;
sys.debug('firstchar ####: ' + firstchar + ' | lastchar ####: ' + lastchar);
// sys.debug("START ####: " + a);
sys.debug( "START: " + chunk );
sys.debug( "AAAAA: " + a );
return;
}
// MIDDLE
if ( wait && firstchar != '{' && lastchar != '}' ) {
a += chunk;
sys.debug('firstchar ####: ' + firstchar + ' | lastchar ####: ' + lastchar);
// sys.debug("MDDLE ####: " + a);
sys.debug( "MDDLE: " + chunk );
sys.debug( "AAAAA: " + a );
return;
}
// FINISH
if ( wait && firstchar != '{' && lastchar == '}' ) {
a += chunk;
sys.debug('firstchar ####: ' + firstchar + ' | lastchar ####: ' + lastchar);
// sys.debug("FINSH ####: " + a);
sys.debug( "FINSH: " + chunk );
sys.debug( "AAAAA: " + a );
wait = false;
}
// sys.debug( "Length: " + chunk.length + " ####" );
// sys.debug( "Chunk: " + chunk );
try {
var check = JSON.parse(chunk);
if ( check.event == "follow" ) { sys.debug("Follow ####"); return; } // check for follow and abort
if ( check.event == "list_member_added" ) { sys.debug("List ####"); return; } // check for list and abort
}
catch (e) {
sys.debug("WRONG ###");
}
server.broadcast(chunk);
});
});
request.end();
// Websockets server setup
var server = ws.createServer({
debug: true
, version: "auto"
});
server.on("listening", function(){
sys.debug("Listening for connections.");
});
// Handle WebSocket Requests
server.on("connection", function(conn){
function log(data){
sys.debug((+new Date())+" \033[0;32m<"+conn.id+"> "+data.toString()+"\033[0m");
};
log("connected");
server.broadcast("<"+conn.id+"> connected");
conn.on("close", function(){
log("onClose");
server.broadcast("<"+conn.id+"> disconnected");
});
conn.on("message", function(message){
log([message.length, JSON.stringify(message)].join(" | "));
server.broadcast("<"+conn.id+"> "+message);
});
});
// Handle HTTP Requests:
server.on("request", function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('This is, infact a websocket server, but we can do http!\n');
});
server.listen(8000);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment