Skip to content

Instantly share code, notes, and snippets.

@azu
Created March 16, 2009 15:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save azu/79915 to your computer and use it in GitHub Desktop.
Save azu/79915 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Nested Twitter Replies
// @namespace pratham.name
// @description Adds nested replies to every Twitter conversation thread.
// @include http://twitter.com/*
// @include http://explore.twitter.com/*
// @include https://twitter.com/*
// ==/UserScript==
// fix https @2009-03-17
twitter_replies = {
html : {},
locate : function () {
var a = document.getElementsByTagName ('a');
for (var i=0; i<a.length; i++) {
if (a [i].innerHTML.substr (0, 11) == 'in reply to') {
var href = a[i].href;
var id = a [i].parentNode.parentNode.parentNode.id;
if (id && id.indexOf ('status_') != -1)
this.get_reply (id, href);
}
}
},
// id is the DOM id - where to draw the reply.
get_reply : function (id, reply) {
if (typeof twitter_replies.html [reply.substr (reply.lastIndexOf ('/') + 1)] == 'undefined') {
GM_xmlhttpRequest ({
method: 'GET',
url: reply,
onload: function (responseDetails) {
// console.log ('Request for '+reply+' returned ' + responseDetails.status + ' ' + responseDetails.statusText);
twitter_replies.process_reply (responseDetails.responseText, id, reply);
}
});
}
else
twitter_replies.process_reply (twitter_replies.html [reply.substr (reply.lastIndexOf ('/') + 1)], id, reply);
},
process_reply : function (html, id, reply) {
twitter_replies.html [reply.substr (reply.lastIndexOf ('/') + 1)] = html;
var descRegex = new RegExp ("<span class=\"entry-content\">([\\s\\S]+?)<\\/span>", "gi");
var desc = descRegex.exec (html);
var desc = desc === null ? ['', 'Sorry, you are not authorized to see this status.'] : desc;
try {
var metaRegex = new RegExp ("<span class=\"meta entry-meta\">([\\s\\S]+?<\\/span>[\\s\\S]+?<\\/span>[\\s\\S]*?)<\\/span>", "gi");
var meta = metaRegex.exec (html);
meta = meta [1];
} catch (e) {
var meta = '';
}
var thumbRegex = new RegExp ("src=\"(https?://s3.amazonaws.com/twitter_production/profile_images/[^\"]*)\"", "gi");
var thumb = thumbRegex.exec (html);
try {
thumb = thumb [1].replace (/bigger/, 'mini');
} catch (e) {
thumb = 'http://static.twitter.com/images/default_profile_mini.png';
}
// var status_id = 'status_' + reply.substr (reply.lastIndexOf ('/')+1);
if (id.indexOf ('status_') != -1)
var status_id = 'reply_' + id.substr (id.lastIndexOf ('_') + 1) + '_' + id.substr (id.lastIndexOf ('_') + 1) + '_' + reply.substr (reply.lastIndexOf ('/') + 1);
else
var status_id = 'reply_' + id.substr (id.indexOf ('_') + 1, id.indexOf ('_', 7) - id.indexOf ('_') - 1) + '_' + id.substr (id.lastIndexOf ('_') + 1) + '_' + reply.substr (reply.lastIndexOf ('/') + 1);
// http://twitter.com/ is 19 chars.
var user_id = reply.substr (19);
user_id = user_id.substring (0, user_id.indexOf ('/'));
// console.log (desc [1] + ' ' + meta [1] + ' ' + thumb [1]);
var node = document.createElement ('li');
node.setAttribute ('id', status_id);
node.setAttribute ('class', 'hentry status reply u-prolificd');
// if status_id exists, then remove the original node to prevent duplication.
// to prevent multiple threading.
try {
var parent_id = 'status_' + reply.substr (reply.lastIndexOf ('/') + 1);
var next = document.getElementById (parent_id).nextSibling;
document.getElementById (parent_id).parentNode.removeChild (document.getElementById (parent_id));
// loop thru all replies and delete them.
while (next.id.indexOf ('reply_') != -1) {
var elem = next;
next = next.nextSibling;
elem.parentNode.removeChild (elem);
}
} catch (e) {
}
// insertAfter hack.
// this will throw an error if element has been deleted.
try {
document.getElementById (id).parentNode.insertBefore (node, document.getElementById (id).nextSibling);
// now edit status_<ID> node.
if (document.location.href.indexOf ('twitter.com/home') != -1 || document.location.href.indexOf ('twitter.com/replies') != -1 || document.location.href.indexOf ('twitter.com/public_timeline') != -1 || document.location.href.indexOf ('twitter.com/account/archive') != -1)
document.getElementById (status_id).innerHTML = '<span class="status-body" style="margin-left:65px"> <a class="url" href="http://twitter.com/'+user_id+'"><img src="'+thumb+'" id="profile-image" class="photo fn" style="width:24px; height:24px; vertical-align:middle"/></a> <strong><a href="http://twitter.com/'+user_id+'">'+user_id+'</a></strong> <span class="entry-content"> '+desc [1]+' </span> <span class="meta entry-meta"> '+meta+' </span></span>';
else
document.getElementById (status_id).innerHTML = '<span class="status-body" style="margin-left:65px"> <a class="url" href="http://twitter.com/'+user_id+'"><img src="'+thumb+'" id="profile-image" class="photo fn" style="width:24px; height:24px; vertical-align:middle"/></a> <strong><a href="http://twitter.com/'+user_id+'">'+user_id+'</a></strong> <span class="entry-content"> '+desc [1]+' </span> <span class="meta entry-meta"> '+meta+' </span> </span>';
// html element created now - could access dom functions.
var a = document.getElementById (status_id).getElementsByTagName ('a');
for (var i=0; i<a.length; i++) {
if (a [i].innerHTML.substr (0, 11) == 'in reply to')
twitter_replies.get_reply (a [i].parentNode.parentNode.parentNode.id, a[i].href);
}
} catch (e) {
}
}
};
if (document.location.href.indexOf ('/status') == -1)
twitter_replies.locate ();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment