




if (typeof(disqus_iframe_css) == 'undefined') {
	disqus_iframe_css = '';
}
if (typeof(disqus_def_name) == 'undefined') {
	disqus_def_name = '';
}
if (typeof(disqus_def_email) == 'undefined') {
	disqus_def_email = '';
}
if (typeof(disqus_skip_auth) == 'undefined') {
	disqus_skip_auth = false;
}
if (typeof(disqus_default_text) == 'undefined') {
	disqus_default_text = 'Type your comment here.';
}

(function(){
	
	var ie = document.uniqueID
		&& document.compatMode
		&& !window.XMLHttpRequest
		&& document.execCommand ;

	try {
		if(!!ie) {
			document.execCommand("BackgroundImageCache", false, true);
		}
	} catch(e) {};
})();

var Dsq = new function() {
	this.container = document.getElementById('dsq-content');
	this.jsonData = {"reactions": [{"body": "Does Scoble understand anything? The worst kind of speculative drivel.", "author_name": "Matt Darby", "source_url": "http://www.ubervu.com/conversations/scobleizer.com/2008/05/26/should-services-charge-super-users/", "id": 1067182, "get_service_url": "http://friendfeed.com/", "title": "", "url": "http://friendfeed.com/e/e5909f16-a3b4-3595-55e3-90996b2b1c03#f013d00f-cfe6-4128-b959-755df1963177", "source": "ubervu", "get_service_name": "friendfeed", "avatar_url": "http://friendfeed.com/mxdarby/picture?size=large", "author_url": "", "date_created": "1 year ago", "retweets": []}, {"body": "Facebook generates ~80 million custom newsfeeds for everyone (How often is the update? ...every day? every half-day?)  The computation costs are huge!  It's not just a Twitter problem. It's a whole Web 2.0...\"let's get 100 million users\" issue.  10 active users vs. 100,000 less-active users - both provide value.  Do you want most of your revenue from (1) most-active (2) medium-active (3) less-active users?  It's a financial strategy decision. Personally, I would pay Scoble to be on \"my service\".", "author_name": "Mitchell Tsai", "source_url": "http://www.ubervu.com/conversations/scobleizer.com/2008/05/26/should-services-charge-super-users/", "id": 1067185, "get_service_url": "http://friendfeed.com/", "title": "", "url": "http://friendfeed.com/e/a33b551c-2bb4-11dd-ab90-003048343a40#2e16e9a5-f66c-4aeb-be6a-47d2a8313260", "source": "ubervu", "get_service_name": "friendfeed", "avatar_url": "http://friendfeed.com/mitchelltsai/picture?size=large", "author_url": "", "date_created": "1 year ago", "retweets": []}, {"body": "Exactly. Twitter isnt a chat client.", "author_name": "William Smith", "source_url": "http://www.ubervu.com/conversations/scobleizer.com/2008/05/26/should-services-charge-super-users/", "id": 1067184, "get_service_url": "http://friendfeed.com/", "title": "", "url": "http://friendfeed.com/e/a33b551c-2bb4-11dd-ab90-003048343a40#dbef8de1-499f-4a26-a7e6-2a7adb7c4b64", "source": "ubervu", "get_service_name": "friendfeed", "avatar_url": "http://friendfeed.com/williamsmith/picture?size=large", "author_url": "", "date_created": "1 year ago", "retweets": []}, {"body": "Services should pay to \"super users\" for their hard work.", "author_name": "Burak Arikan", "source_url": "http://www.ubervu.com/conversations/scobleizer.com/2008/05/26/should-services-charge-super-users/", "id": 1067186, "get_service_url": "http://friendfeed.com/", "title": "", "url": "http://friendfeed.com/e/490ef085-9a20-4e1e-0499-09cc6a2a1294#564ed5b4-1042-4775-9cc2-72542c65d971", "source": "ubervu", "get_service_name": "friendfeed", "avatar_url": "http://friendfeed.com/arikan/picture?size=large", "author_url": "", "date_created": "1 year ago", "retweets": []}, {"body": "There has to be a point at which services charge fees for its services or risk going out of business.  The problem with Twitter, as was documented on their blog recently, is that it was not designed to be a messaging system.  The challenge isnt in your 25,000 tweets, its in the 23,000 SMS messages that must go out to the people that follow you each time you post - assuming half the people get the SMS and you tweet 20 times per day, this is 230,000 text messages you are generating at a cost of ??...", "author_name": "Chris Heuer", "source_url": "http://www.ubervu.com/conversations/scobleizer.com/2008/05/26/should-services-charge-super-users/", "id": 1067183, "get_service_url": "http://friendfeed.com/", "title": "", "url": "http://friendfeed.com/e/a33b551c-2bb4-11dd-ab90-003048343a40#36632020-6e09-4ada-aaf2-d01e0baf203a", "source": "ubervu", "get_service_name": "friendfeed", "avatar_url": "http://friendfeed.com/chrisheuer/picture?size=large", "author_url": "", "date_created": "1 year ago", "retweets": []}, {"body": "I feel like I'm back at the Prodigy 25 cent an e-mail moment all over again!", "author_name": "Nancy Babyak", "source_url": "http://www.ubervu.com/conversations/scobleizer.com/2008/05/26/should-services-charge-super-users/", "id": 1067194, "get_service_url": "http://friendfeed.com/", "title": "", "url": "http://friendfeed.com/e/970efce7-4263-36c9-f87d-b426ada1f07b#7449bdd2-da75-4710-87b9-c4c889155818", "source": "ubervu", "get_service_name": "friendfeed", "avatar_url": "http://friendfeed.com/nbabyak/picture?size=large", "author_url": "", "date_created": "1 year ago", "retweets": []}, {"body": "+1 for Paul's comment", "author_name": "Hutch Carpenter", "source_url": "http://www.ubervu.com/conversations/scobleizer.com/2008/05/26/should-services-charge-super-users/", "id": 1067193, "get_service_url": "http://friendfeed.com/", "title": "", "url": "http://friendfeed.com/e/970efce7-4263-36c9-f87d-b426ada1f07b#7ac1ab1d-3109-4863-a1b5-b6f914a6d2f3", "source": "ubervu", "get_service_name": "friendfeed", "avatar_url": "http://friendfeed.com/bhc3/picture?size=large", "author_url": "", "date_created": "1 year ago", "retweets": []}, {"body": "It's a case by case situation.", "author_name": "Mark \"Rizzn\" Hopkins", "source_url": "http://www.ubervu.com/conversations/scobleizer.com/2008/05/26/should-services-charge-super-users/", "id": 1067192, "get_service_url": "http://friendfeed.com/", "title": "", "url": "http://friendfeed.com/e/970efce7-4263-36c9-f87d-b426ada1f07b#b22de807-dea0-4ec4-87f0-2deadf71bd29", "source": "ubervu", "get_service_name": "friendfeed", "avatar_url": "http://friendfeed.com/rizzn/picture?size=large", "author_url": "", "date_created": "1 year ago", "retweets": []}, {"body": "Services should pay the \"influential users\" and be paid by the \"heavy users\".", "author_name": "Amit Patel", "source_url": "http://www.ubervu.com/conversations/scobleizer.com/2008/05/26/should-services-charge-super-users/", "id": 1067191, "get_service_url": "http://friendfeed.com/", "title": "", "url": "http://friendfeed.com/e/970efce7-4263-36c9-f87d-b426ada1f07b#e9582449-3d59-494a-b081-81654a53dad0", "source": "ubervu", "get_service_name": "friendfeed", "avatar_url": "http://friendfeed.com/amitp/picture?size=large", "author_url": "", "date_created": "1 year ago", "retweets": []}, {"body": "Depends on your definition of \"super users.\" Heavy users, maybe. Influential users, definitely in certain cases. ...via twhirl", "author_name": "Mark \"Rizzn\" Hopkins", "source_url": "http://www.ubervu.com/conversations/scobleizer.com/2008/05/26/should-services-charge-super-users/", "id": 1067190, "get_service_url": "http://friendfeed.com/", "title": "", "url": "http://friendfeed.com/e/970efce7-4263-36c9-f87d-b426ada1f07b#dea82f16-162b-4a80-ad20-d9a14662d968", "source": "ubervu", "get_service_name": "friendfeed", "avatar_url": "http://friendfeed.com/rizzn/picture?size=large", "author_url": "", "date_created": "1 year ago", "retweets": []}], "has_more_reactions": true, "users": {"50e2d3401efa8a448483b59397972378": {"username": "pwb", "tumblr": "", "display_name": "pwb", "url": "http://disqus.com/guest/50e2d3401efa8a448483b59397972378/", "registered": false, "linkedin": "", "blog": "", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "2facd380c5bdfbaa1a1e9c657578f135": {"username": "Barry Kelly", "tumblr": "", "display_name": "Barry Kelly", "url": "http://disqus.com/guest/2facd380c5bdfbaa1a1e9c657578f135/", "registered": false, "linkedin": "", "blog": "http://barrkel.blogspot.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/uploads/anonusers/4/2022/avatar92.jpg", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "3efe0002892b76ab1039cce38125626c": {"username": "HvI", "tumblr": "", "display_name": "HvI", "url": "http://disqus.com/guest/3efe0002892b76ab1039cce38125626c/", "registered": false, "linkedin": "", "blog": "", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "17fd339dc782f5adc7f57437e653d2cd": {"username": "Tiago Macedo", "tumblr": "", "display_name": "Tiago Macedo", "url": "http://disqus.com/guest/17fd339dc782f5adc7f57437e653d2cd/", "registered": false, "linkedin": "", "blog": "http://webreakstuff.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "dariosalvelli": {"username": "dariosalvelli", "tumblr": "", "display_name": "Dario Salvelli", "url": "http://disqus.com/dariosalvelli/", "registered": true, "linkedin": "", "blog": "http://www.dariosalvelli.com", "remote_domain": null, "points": 1, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": true, "flickr": "", "twitter": "", "remote_domain_name": ""}, "033c4fe3a6aae69596fee56044f03c32": {"username": "Nick Halstead", "tumblr": "", "display_name": "Nick Halstead", "url": "http://disqus.com/guest/033c4fe3a6aae69596fee56044f03c32/", "registered": false, "linkedin": "", "blog": "http://fav.or.it/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/uploads/anonusers/6/9571/avatar92.jpg", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "5f89d3df08b8dedac1a0fde900a586db": {"username": "Roger Benningfield", "tumblr": "", "display_name": "Roger Benningfield", "url": "http://disqus.com/guest/5f89d3df08b8dedac1a0fde900a586db/", "registered": false, "linkedin": "", "blog": "http://admin.support.journurl.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "3553f5e0db0fd1ec4e40a932a2d8f5b3": {"username": "Robert Scoble", "tumblr": "", "display_name": "Robert Scoble", "url": "http://disqus.com/guest/3553f5e0db0fd1ec4e40a932a2d8f5b3/", "registered": false, "linkedin": "", "blog": "http://scobleizer.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/uploads/anonusers/4069/avatar92.jpg", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "f2181053f629eee77775220dc01b13dc": {"username": "Tim Marman", "tumblr": "", "display_name": "Tim Marman", "url": "http://disqus.com/guest/f2181053f629eee77775220dc01b13dc/", "registered": false, "linkedin": "", "blog": "http://slashstar.com/blogs/tim", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "c13bd49d1c0135cbbc3717270824b22e": {"username": "Kurt", "tumblr": "", "display_name": "Kurt", "url": "http://disqus.com/guest/c13bd49d1c0135cbbc3717270824b22e/", "registered": false, "linkedin": "", "blog": "http://tryingthisagain.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "04444ddd0eb03e7b3caaf196300ad372": {"username": "Mogilny", "tumblr": "", "display_name": "Mogilny", "url": "http://disqus.com/guest/04444ddd0eb03e7b3caaf196300ad372/", "registered": false, "linkedin": "", "blog": "", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "d8bb4623895a9ba01a125d3d7800bead": {"username": "JoeDuck", "tumblr": "", "display_name": "JoeDuck", "url": "http://disqus.com/guest/d8bb4623895a9ba01a125d3d7800bead/", "registered": false, "linkedin": "", "blog": "http://joeduck.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/uploads/anonusers/1372/avatar92.jpg", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "cf3c50189c8448f7d334220334a1118d": {"username": "Craig", "tumblr": "", "display_name": "Craig", "url": "http://disqus.com/guest/cf3c50189c8448f7d334220334a1118d/", "registered": false, "linkedin": "", "blog": "http://thoughtindustry.blogspot.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/uploads/anonusers/76/8352/avatar92.jpg", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "06efcd5ee6ab3b9480acce0eeece731f": {"username": "Geoff", "tumblr": "", "display_name": "Geoff", "url": "http://disqus.com/guest/06efcd5ee6ab3b9480acce0eeece731f/", "registered": false, "linkedin": "", "blog": "http://geoffjones.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/uploads/anonusers/36/6985/avatar92.jpg", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "1865032048cd0d5b606701fd08ffb6ca": {"username": "Jerry", "tumblr": "", "display_name": "Jerry", "url": "http://disqus.com/guest/1865032048cd0d5b606701fd08ffb6ca/", "registered": false, "linkedin": "", "blog": "", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "2402750996746d76cc364ef9de652d3f": {"username": "Ethan Ambabo", "tumblr": "", "display_name": "Ethan Ambabo", "url": "http://disqus.com/guest/2402750996746d76cc364ef9de652d3f/", "registered": false, "linkedin": "", "blog": "http://www.rabidspacedog.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "04bf542065be5c7090319cdca16ffe68": {"username": "geekazine", "tumblr": "", "display_name": "geekazine", "url": "http://disqus.com/guest/04bf542065be5c7090319cdca16ffe68/", "registered": false, "linkedin": "", "blog": "http://www.geekazine.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/uploads/anonusers/11/3258/avatar92.jpg", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "0976088d32ab8aa425f99b9f7fe6fe28": {"username": "BSally", "tumblr": "", "display_name": "BSally", "url": "http://disqus.com/guest/0976088d32ab8aa425f99b9f7fe6fe28/", "registered": false, "linkedin": "", "blog": "", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "ce1d8230da097424bf1a399a7fa4745d": {"username": "RBA", "tumblr": "", "display_name": "RBA", "url": "http://disqus.com/guest/ce1d8230da097424bf1a399a7fa4745d/", "registered": false, "linkedin": "", "blog": "http://www.corank.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "2caa59beafeb0b4fb6ef142a0d1cae8b": {"username": "Tony Fendall", "tumblr": "", "display_name": "Tony Fendall", "url": "http://disqus.com/guest/2caa59beafeb0b4fb6ef142a0d1cae8b/", "registered": false, "linkedin": "", "blog": "http://www.munkiihouse.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "463a381eaf9c0c08bc130a1bea1874ee": {"username": "Michael Foord", "tumblr": "", "display_name": "Michael Foord", "url": "http://disqus.com/guest/463a381eaf9c0c08bc130a1bea1874ee/", "registered": false, "linkedin": "", "blog": "http://www.ironpythoninaction.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "0f30ffbf46ec1241c48e0c435367bab4": {"username": "Oliver Thylmann", "tumblr": "", "display_name": "Oliver Thylmann", "url": "http://disqus.com/guest/0f30ffbf46ec1241c48e0c435367bab4/", "registered": false, "linkedin": "", "blog": "http://blog.thylmann.net/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "c0c69c7b33a7bd03a87f2f9fe558692e": {"username": "Master William", "tumblr": "", "display_name": "Master William", "url": "http://disqus.com/guest/c0c69c7b33a7bd03a87f2f9fe558692e/", "registered": false, "linkedin": "", "blog": "", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "1ccc0cc0f53a2b505e37932c861246b9": {"username": "Omar Shahine", "tumblr": "", "display_name": "Omar Shahine", "url": "http://disqus.com/guest/1ccc0cc0f53a2b505e37932c861246b9/", "registered": false, "linkedin": "", "blog": "http://www.shahine.com/omar", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "e24b825d0765fa4efc1402444f3255a4": {"username": "John Handelaar", "tumblr": "", "display_name": "John Handelaar", "url": "http://disqus.com/guest/e24b825d0765fa4efc1402444f3255a4/", "registered": false, "linkedin": "", "blog": "http://handelaar.org/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "5cdc05de245c195c21a6dc5d7070527f": {"username": "Wolf", "tumblr": "", "display_name": "Wolf", "url": "http://disqus.com/guest/5cdc05de245c195c21a6dc5d7070527f/", "registered": false, "linkedin": "", "blog": "http://www.wolfslittlestore.be/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "25769ac9da72e934b928e636906379c8": {"username": "Sol Young", "tumblr": "", "display_name": "Sol Young", "url": "http://disqus.com/guest/25769ac9da72e934b928e636906379c8/", "registered": false, "linkedin": "", "blog": "http://solyoung.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "f89b745cb3983fb1c02bca74a4f6d077": {"username": "Francine hardaway", "tumblr": "", "display_name": "Francine hardaway", "url": "http://disqus.com/guest/f89b745cb3983fb1c02bca74a4f6d077/", "registered": false, "linkedin": "", "blog": "http://blog.stealthmode.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/uploads/anonusers/13604/avatar92.jpg", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "44c5450cb486d4e4e5b80ef7a01e7017": {"username": "Tom", "tumblr": "", "display_name": "Tom", "url": "http://disqus.com/guest/44c5450cb486d4e4e5b80ef7a01e7017/", "registered": false, "linkedin": "", "blog": "http://www.tomstechblog.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "997c47bdb01fbac133cb7eb4678ef62c": {"username": "Trevor Plantagenent", "tumblr": "", "display_name": "Trevor Plantagenent", "url": "http://disqus.com/guest/997c47bdb01fbac133cb7eb4678ef62c/", "registered": false, "linkedin": "", "blog": "", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "15fd11b2c73ac95c3552e1d3a0c2b40f": {"username": "Alberto", "tumblr": "", "display_name": "Alberto", "url": "http://disqus.com/guest/15fd11b2c73ac95c3552e1d3a0c2b40f/", "registered": false, "linkedin": "", "blog": "http://twitter.com/mask", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "5ea27fefd5d94036b0def62f7cda2c60": {"username": "Jeff Putz", "tumblr": "", "display_name": "Jeff Putz", "url": "http://disqus.com/guest/5ea27fefd5d94036b0def62f7cda2c60/", "registered": false, "linkedin": "", "blog": "http://www.campusfish.com/Jeff", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "7e7d5611762251b7b1939a7c7b01d648": {"username": "Angus McDonald", "tumblr": "", "display_name": "Angus McDonald", "url": "http://disqus.com/guest/7e7d5611762251b7b1939a7c7b01d648/", "registered": false, "linkedin": "", "blog": "http://falkayn.blogspot.com/2008/05/oms-got-wrong-business-model-for.html", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "b1088dbd877c2d7d33e6b3b63ee38081": {"username": "Prokofy Neva", "tumblr": "", "display_name": "Prokofy Neva", "url": "http://disqus.com/guest/b1088dbd877c2d7d33e6b3b63ee38081/", "registered": false, "linkedin": "", "blog": "http://secondthoughts.typepad.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "761378873ebe3b4ad0b10a5e689e13ee": {"username": "Edvin Aghanian", "tumblr": "", "display_name": "Edvin Aghanian", "url": "http://disqus.com/guest/761378873ebe3b4ad0b10a5e689e13ee/", "registered": false, "linkedin": "", "blog": "", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/uploads/anonusers/190/6221/avatar92.jpg", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "16d48334bc778cdb73271c72c953a86f": {"username": "James", "tumblr": "", "display_name": "James", "url": "http://disqus.com/guest/16d48334bc778cdb73271c72c953a86f/", "registered": false, "linkedin": "", "blog": "http://deadnode.org/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "967c7a60693f189f8be9348b7da03dc6": {"username": "sam ism", "tumblr": "", "display_name": "sam ism", "url": "http://disqus.com/guest/967c7a60693f189f8be9348b7da03dc6/", "registered": false, "linkedin": "", "blog": "", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "cdafe501caff10374da4f68277a1ccd7": {"username": "Steve Wilhelm", "tumblr": "", "display_name": "Steve Wilhelm", "url": "http://disqus.com/guest/cdafe501caff10374da4f68277a1ccd7/", "registered": false, "linkedin": "", "blog": "http://siliconvalleymusings.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "9e9ed9c4ef99761f4f3cbefdd985dae1": {"username": "Brian", "tumblr": "", "display_name": "Brian", "url": "http://disqus.com/guest/9e9ed9c4ef99761f4f3cbefdd985dae1/", "registered": false, "linkedin": "", "blog": "", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "6d64d1f44126702d2502b9ced6033fb3": {"username": "Richard Cunningham", "tumblr": "", "display_name": "Richard Cunningham", "url": "http://disqus.com/guest/6d64d1f44126702d2502b9ced6033fb3/", "registered": false, "linkedin": "", "blog": "http://friendbinder.com/users/rythie", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "1178ce2f664a6cee9a05a3e11af5d8d2": {"username": "Aaron Brethorst", "tumblr": "", "display_name": "Aaron Brethorst", "url": "http://disqus.com/guest/1178ce2f664a6cee9a05a3e11af5d8d2/", "registered": false, "linkedin": "", "blog": "http://www.brethorsting.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/uploads/anonusers/130/3184/avatar92.jpg", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "579fbc756c0d918e2244dff914c9bf88": {"username": "Dare Obasanjo", "tumblr": "", "display_name": "Dare Obasanjo", "url": "http://disqus.com/guest/579fbc756c0d918e2244dff914c9bf88/", "registered": false, "linkedin": "", "blog": "http://www.25hoursaday.com/weblog", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "f3b41bc009a402017febfab746770bc5": {"username": "jonas", "tumblr": "", "display_name": "jonas", "url": "http://disqus.com/guest/f3b41bc009a402017febfab746770bc5/", "registered": false, "linkedin": "", "blog": "", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "cc3b90976c1af1ca59fb5eb5603eaf63": {"username": "Larry", "tumblr": "", "display_name": "Larry", "url": "http://disqus.com/guest/cc3b90976c1af1ca59fb5eb5603eaf63/", "registered": false, "linkedin": "", "blog": "", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "7f779ee56ab2c790ead96fc6ef4e55ca": {"username": "Stuart Dallas", "tumblr": "", "display_name": "Stuart Dallas", "url": "http://disqus.com/guest/7f779ee56ab2c790ead96fc6ef4e55ca/", "registered": false, "linkedin": "", "blog": "http://stut.net/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/images/noavatar92.png", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}, "a30e775d1972cd2a2843193faa241a97": {"username": "Paul Short", "tumblr": "", "display_name": "Paul Short", "url": "http://disqus.com/guest/a30e775d1972cd2a2843193faa241a97/", "registered": false, "linkedin": "", "blog": "http://oxalon.com/", "remote_domain": null, "points": null, "facebook": "", "avatar": "http://media.disqus.com/uploads/anonusers/13089/avatar92.jpg", "delicious": "", "is_remote": false, "verified": false, "flickr": "", "twitter": "", "remote_domain_name": ""}}, "forum": {"use_media": true, "name": "Scobleizer", "streaming_realtime": true, "url": "scobleizer", "allow_anon_post": true, "reactions_enabled": true, "reply_position": 1, "show_avatar": true, "allow_anon_votes": false, "disqus_auth_disabled": false}, "realtime_enabled": true, "request": {"username": "", "is_global_moderator": false, "sharing": {}, "sort": 4, "forum": "scobleizer", "is_initial_load": true, "is_authenticated": false, "timestamp": "2009-12-17_04:12:22", "remote_domain": "", "page": 1, "is_moderator": false, "display_username": "", "points": null, "subscribe_on_post": 2, "moderator_can_edit": false, "is_remote": false, "is_verified": false, "missing_perm": "locked"}, "realtime_paused": false, "posts": {"9705749": {"up_voted": false, "ip": "", "has_replies": false, "message": "Spammers are taking up a lot of space on Twitter lately. Sony has a spamming bot.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_15:25:36", "killed": false, "user_key": "f89b745cb3983fb1c02bca74a4f6d077", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705750": {"up_voted": false, "ip": "", "has_replies": false, "message": "Robert: \"By the way, this caused a famous and massive problem inside Microsoft when the database server filled up when someone accidentally emailed something to \u201call.\u201d Email went down for two days, the way I heard it.\"<br><br>I think you're referring to Bedlam DL3, which was quite different from this. It was summarized by the Exchange team back in 2004: <a href=\"http://msexchangeteam.com/archive/2004/04/08/109626.aspx\" rel=\"nofollow\">http://msexchangeteam.com/archive/2004/04/08/10...</a>", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_13:49:24", "killed": false, "user_key": "1178ce2f664a6cee9a05a3e11af5d8d2", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705751": {"up_voted": false, "ip": "", "has_replies": false, "message": "What does Exchange have to do with it? Exchange doesn't scale (yet) to hundreds of millions of users. Mail systems like Hotmail do in fact keep 25,000 copies of an email if that is how many hotmail users receive the same message. Doing anything else would literally saturate and melt the network (if the architecture was built around a single instance store). There is a physical limit to how much network traffic you can have going between clusters (or scale units). Ideally you optimize your IO for the access patterns of your application (lots of writes and many more reads of unique data).<br><br>BTW, the issue you are describing with Exchange failing is documented here:<br><br><a href=\"http://msexchangeteam.com/archive/2004/04/08/109626.aspx\" rel=\"nofollow\">http://msexchangeteam.com/archive/2004/04/08/10...</a><br><br>And it wasn't a failure for the reasons you describe. It has to do with numerous issues and failures unrelated to db scale.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_13:59:40", "killed": false, "user_key": "1ccc0cc0f53a2b505e37932c861246b9", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705752": {"up_voted": false, "ip": "", "has_replies": false, "message": "Om's gotten it totally wrong. Twitter should charge your followers (past perhaps the first 100) for the privilege of getting access to your opinions faster. The website could remain free, but most twitterers I know use desktop clients to keep abreast, and so following someone is the only way to do that.<br><br>Charging 10 cents per month to each follower after the first would reap a far greater income for them, and annoy interesting twitterers less!<br><br>See my blog post for more:<br><a href=\"http://falkayn.blogspot.com/2008/05/oms-got-wrong-business-model-for.html\" rel=\"nofollow\">http://falkayn.blogspot.com/2008/05/oms-got-wro...</a>", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_18:55:14", "killed": false, "user_key": "7e7d5611762251b7b1939a7c7b01d648", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705753": {"up_voted": false, "ip": "", "has_replies": false, "message": "The whole debate is stupid!  Why does no one seem to get it?<br><br>Could a team of competent software engineers build a system which could handle this many users? Yes!<br>Should twitter have a system which can handle this many users? Yes!<br><br>I don't understand why people are so keen to defend poor service. If it's broke, then the twitter guys should fix it.  That means better code, more servers, what ever it takes.<br><br>If the problem is that they can't find a way to monetize it, then that's a different problem, but one where having lots of users should help, not hinder.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_18:26:47", "killed": false, "user_key": "2caa59beafeb0b4fb6ef142a0d1cae8b", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705754": {"up_voted": false, "ip": "", "has_replies": false, "message": "We used to have this thing in the '90s for people who wanted to broadcast to a large audience -- it was called \"television\". And we had this other thing you could use to interact with the broadcaster, called \"the U.S. Postal Service\". The fun part was when a guy like Dave Letterman would read your letter right there on the air, when he was broadcasting.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_18:43:20", "killed": false, "user_key": "b1088dbd877c2d7d33e6b3b63ee38081", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705755": {"up_voted": false, "ip": "", "has_replies": false, "message": "Now who do I believe when it comes to authority on systems architecture.<br><br>Robert Scoble or Dare Obasanjo?<br><br>lol", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_14:28:33", "killed": false, "user_key": "c0c69c7b33a7bd03a87f2f9fe558692e", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705756": {"up_voted": false, "ip": "", "has_replies": false, "message": "Robert,<br>  It isn't clear to me why you are taking my post so personally. Regardless of how Twitter is implemented, allowing a user to have 25,000 followers and 25,000 people they are following will cause scale problems. There are different optimizations you could make (Single Instancing is not the panacea you claim, see my post at for <a href=\"http://www.25hoursaday.com/weblog/2008/05/26/SomeThoughtsOnSingleInstanceStorageAndTwitter.aspx\" rel=\"nofollow\">http://www.25hoursaday.com/weblog/2008/05/26/So...</a> more)  but it doesn't change the fact that Twitter has made some bad design and feature decisions.<br><br> As to whether people who generate massive load on the system should be charged...isn't that a fact of life everywhere else? Internet service providers like Comcast are known to fire customers who use too much bandwidth, in fact your buddy Dave Winer just blogged about that happening to him. Flickr, Y! Mail and a bunch of other services also charge for \"pro\" features. Why would Twitter pursuing such a business model be so wrong? Would you prefer to have ads in your Twitter streams?", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_14:31:47", "killed": false, "user_key": "579fbc756c0d918e2244dff914c9bf88", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705757": {"up_voted": false, "ip": "", "has_replies": false, "message": "Robert, I know Twitter isn't email, why did you bring up Exchange and Bedlam then?<br><br>I'm not sure why you are being so assumptive about their architecture unless some one laid it out to you. Further some of your statements in defense(?) of what they may or may not be doing don't even make sense.<br><br>I'm not being assumptive. I haven't said one way or another what they are doing because I have no idea. I only know of the massive large scale systems we have at Microsoft and the relative pros and cons of each. I also know each is designed to meet one general architecturural need and generally these things don't translate well to serve different kinds of IO. So that you might find is that within any large system you have dozens or more subsystems specifically designed to one scale problem. Some of those will require creating duplicate copies of the data if read performance is required to make your application scale OR be responsive.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_14:57:04", "killed": false, "user_key": "1ccc0cc0f53a2b505e37932c861246b9", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705758": {"up_voted": false, "ip": "", "has_replies": false, "message": "Omar: one problem, Twitter isn't like email. First of all, only a small percentage of Twitter users ever sign into Twitter again. Let's say it's as high as 50% (I think it's lower). That would mean 12,500 copies. Then, not every one of those users signs in every day. Let's say only 50% sign in on a particular day. That's 6,250 copies. But how does Twitter know which users will sign in? It doesn't. It needs to create the pages on the fly, not copy everything to 23,000 (er, two million) separate tables in a big database. If it did that it'd quickly die, and make it extremely hard to maintain, too.<br><br>Also, many users don't even use the Web interface. Most of the time I'm looking at messages coming at me in Google Talk. Those are coming one at a time at me. Are you really seriously expecting me to believe that Twitter copies messages 23,000 times before sending them out to me via the XMPP database?", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_14:38:32", "killed": false, "user_key": "3553f5e0db0fd1ec4e40a932a2d8f5b3", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705759": {"up_voted": false, "ip": "", "has_replies": false, "message": "Master: I wasn't arguing with Dare so much about the architecture. But it's totally ridiculous to say that my messages are copied 23,000 times. If that were true, then Wordpress.com's architecture would be going down left and right cause this blog would be copied 400,000 times. It is, but in your Web browser, not on the server side.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_14:33:36", "killed": false, "user_key": "3553f5e0db0fd1ec4e40a932a2d8f5b3", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705760": {"up_voted": false, "ip": "", "has_replies": false, "message": "\"Sweet how you never had to work with an Exchange server which did exactly that, and then added \u2018All\u2019 as a recipient to the address book of every user.<br><br>Exchange never ever stored a message per user.  If all users are on the same Exchange server and sent a message from someone on the same Exchange server, it it only stored ONCE.  That's been the case since Exchange 4.0.  Bedlam had more to do with people hitting Reply All  to an alias that had users on different servers.  It was the message queue that caused the primary problems during Bedlam.<br><br>In Exchange 2007 there is a deemphasis on SIS--it only applies to attachments.  Not sure what the scaling problems are with Twitter as I have no idea how the system is designed.  But, it would be safe to figure that whether or not they use SIS is not the source of their instability.<br><br>Now, back to your regularly scheduled debate about an non-scalable, useless communication tool.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_21:32:46", "killed": false, "user_key": "9e9ed9c4ef99761f4f3cbefdd985dae1", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705761": {"up_voted": false, "ip": "", "has_replies": false, "message": "Another aspect of the problem is that so many people use twitter in near-constant streams throughout multi-hour events so as to give \"live\" coverage of an event or just their stream of thought (case in point: the owner of this blog). I'm certain that taking all those SMS's in, displaying them, and broadcasting them out to webpages, RSS feeds, and then more phones is taxing to say the least. Look at the times it goes down and I'm sure you'll see a major correlation with tech events. I understand that some have found this useful, but I really don't and it's a sure fire way to get me to unfollow you, and I can guarantee why Twitter's user base hasn't diversified beyond \"social techies.\"<br><br>Solution? Create a new service on top of twitter for twitter-streams, because obviously people don't get the idea behind 120-character limits (by the way, SMS has a 160-character limit) and hold their tweetstorms in a buffer to digest and spew out to followers when the server load can handle it.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_23:14:06", "killed": false, "user_key": "2402750996746d76cc364ef9de652d3f", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705762": {"up_voted": false, "ip": "", "has_replies": false, "message": "With Nick's explanation on why de-normalization is needed to scale, it is clear one of the complex issues Twitter has to solve. The other one mentioned in this post is the business model, or when to charge.<br><br>Angus has the right idea - charging the followers - although I don't agree on the analysis. Still using Robert as the super-user, he should not be charged because of his tweets, but for the number of people he is following. Each tweet sent by the friends Robert is following will be copied on his queue (well the tweet ID) and the size and freshness of this queue (visually the 'With Others') can be used as the factor to charge.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-27_01:03:54", "killed": false, "user_key": "15fd11b2c73ac95c3552e1d3a0c2b40f", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705763": {"up_voted": false, "ip": "", "has_replies": false, "message": "Like they say, you get what you pay for.  You want better SLA's and uptime?  Crack open your wallet.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-27_01:27:39", "killed": false, "user_key": "1865032048cd0d5b606701fd08ffb6ca", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705764": {"up_voted": false, "ip": "", "has_replies": false, "message": "Does anyone *actually* know how Twitter does what is does? Given the 140 byte limit, Twitter seems very \"doable\" with some basic design choices. This is why I think Ruby/Rails may really be a culprit here...it's too high level to support some of the things Twitter needs to do.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-27_01:37:15", "killed": false, "user_key": "50e2d3401efa8a448483b59397972378", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705765": {"up_voted": false, "ip": "", "has_replies": false, "message": "Wow. Lots of interesting comments. Then again, lots of BLAH, BLAH, BLAH.<br><br>Here's a fact that people are overlooking. Traffic brings revenue. Let's say that the 25,000 posts get counted. What does that really amount to?<br><br>That means that 25,000 people are looking at what Robert Scoble is saying. If I was a person that wants to get out my product name, then I think I would pay Twitter to keep the service going. Better yet I might ask and pay Robert to push my wares.<br><br>About a month back I @(replied) Robert on something. I believe it was during one of many Twitters' \"Problems\". The exchange was short and sweet. However, I looked at my Followers an hour later, it jumped up 15 (which it doesn't normally do).<br><br>I tested the water by @ another person. The same thing happened. I gain more followers by replying to high profile twitters.<br><br>Now, apply that all to a marketing model. Communication can mean $$. I guess that's why Twitter was able to raise 20 million on it's own.<br><br>The problem isn't the Twitterflood. If that was the case then sites like MySpace and Facebook would be going down on a daily basis. If it DOES do what OM Malik suggests, then Twitter needs to look at their internal structure. Not at Robert Scoble, or Leo Laporte.<br><br>Limits and subscription fees are a great way to kill the idea. Some will pay for it, while others will say \"See ya\". Twitter will fall like a ball of flame into the Pacific Ocean.<br><br>They keep the idea fresh. To most, Twitter is an \"Oh, I heard of that\". People might know about it, but never signed up. Oncemore, Twitter can easily become a cash cow. The data that comes into Twitter is like when Daffy Duck found the Sultan's cave.<br><br>I'M RICH! I'M WEALTY BEYOND MY WILDEST DREAMS!!!...<br><br>Keep going Scoble. I'm listening...", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-27_03:54:49", "killed": false, "user_key": "04bf542065be5c7090319cdca16ffe68", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705766": {"up_voted": false, "ip": "", "has_replies": false, "message": "I don't see why not to charge the supertweeters, they pay whoever hosts their blogs, don't they?  They're using Twitter as their personal blogging platform, no difference.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-27_03:55:07", "killed": false, "user_key": "997c47bdb01fbac133cb7eb4678ef62c", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705767": {"up_voted": false, "ip": "", "has_replies": false, "message": "&gt;Open up Twitter\u2026 now, did you wait several minutes for your page to appear?<br><br>Open up FriendFeed. Refresh many times. DId the page change? It certainly wasn't pre-cached before I hit the servers.<br><br>Computers now are fast, if you have the right architecture.<br><br>How does Google work? It is always fast and doesn't pre-cache all my pages. To do that it'd have to know what I'm thinking before I actually searched for something.<br><br>One thing you haven't thought about is that even if everything was precached that only a small percentage of my 23,000 followers ever log into Twitter. So, if it's building a page for each of the 23,000 followers it's totally wasting resources.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_14:27:06", "killed": false, "user_key": "3553f5e0db0fd1ec4e40a932a2d8f5b3", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705768": {"up_voted": false, "ip": "", "has_replies": false, "message": "Robert,<br><br>Have you read the article referred by Al3x in Twitter's dev blog: <a href=\"http://www.hueniverse.com/hueniverse/2008/03/on-scaling-a-mi.html\" rel=\"nofollow\">http://www.hueniverse.com/hueniverse/2008/03/on...</a><br><br>It explains why there is a need to duplicate copies, the main reason is the speed for other APIs (i.e. FriendFeed) to read them and one of the reasons why there is not a huge delay (i.e. 10 seconds) when the tweets appear in FriendFeed, without the copying that time will be longer.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_15:05:15", "killed": false, "user_key": "15fd11b2c73ac95c3552e1d3a0c2b40f", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705769": {"up_voted": false, "ip": "", "has_replies": false, "message": "I think Om's point was more along the lines that instead of simply bleeding cash, they could make a little. I don't think he was questioning the architecture.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_15:14:33", "killed": false, "user_key": "5ea27fefd5d94036b0def62f7cda2c60", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705770": {"up_voted": false, "ip": "", "has_replies": false, "message": "Scoble, I think you are fantastic and your enthusiasm for the industry is amazing, but you really should steer clear of the technical arguments.<br><br>You are trying to argue that twitter is using a 'pivot table' - so you have one table for users, one table for messages, and a third table that describes your friend relationships. When a query comes into to see a particular users stream you think they 'mix' this up, so you do a many-to-many lookup, so for every user (25k in your case) you then look in every one of those users message queues for the most recent messages then mash them together.<br><br>Now they may have started with a 'obvious' schema like this about a year ago but I can assure you 1000% that this does NOT scale very far and certainly not up to the point they have got. The reason? because many-to-many lookups in any RDBM are extremely costly and secondly it is very hard to scale across hardware when you build like this, because it is almost impossible to shard because the many-to-many means everyone can potentially be joined together.<br><br>The second methodology described which you laughed at, IS SCALABLE - because you can shard to as many machine as you like for an example lets say each shard owns (10,000) users - each message you send just has to send a tiny signal to each shard of your new message - each shard then looks up within its own local database of 10,000 users to see if any of them are following you. It then adds your message to their queue.<br><br>This is a classic normalization vs de-normalization - you describe normalization in how you think it works - what I hope (and I am sure they are doing a variant of) is de-normalization.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_15:24:52", "killed": false, "user_key": "033c4fe3a6aae69596fee56044f03c32", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705771": {"up_voted": false, "ip": "", "has_replies": false, "message": "I don't believe this, you're making statements that are 100% false.  Yes, every time you tweet, it's copied 25,000 times.  It has to work that way or it wouldn't have scaled as far as it has.  You're setting yourself up for massive humiliation when you're definitively proven wrong.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_15:35:57", "killed": false, "user_key": "997c47bdb01fbac133cb7eb4678ef62c", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705772": {"up_voted": false, "ip": "", "has_replies": false, "message": "I agree with all the commenters saying that Twitter must be copying messages to each follower, but I really hope they're just copying an ID 25k times and the actual text of the message maybe just a few 10's of times (i.e. to multiple caches). There's no way it would perform as well as it does (most of the time) if it were transferring 30 gig of data every time Scoble tweets.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_16:10:13", "killed": false, "user_key": "7f779ee56ab2c790ead96fc6ef4e55ca", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705773": {"up_voted": false, "ip": "", "has_replies": false, "message": "Scratch the 30 gig, misread Om's blog. Even so it would be a huge amount of data being moved about Twitter's internal network given that Scoble is just one of quite a few \"super users\" on there.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_16:13:43", "killed": false, "user_key": "7f779ee56ab2c790ead96fc6ef4e55ca", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705774": {"up_voted": false, "ip": "", "has_replies": false, "message": "I took a different approach than flat out charging users with mass followings:<br><br><a href=\"http://thoughtindustry.blogspot.com/2008/05/twitters-issues-with-scalability.html\" rel=\"nofollow\">http://thoughtindustry.blogspot.com/2008/05/twi...</a>", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_16:19:40", "killed": false, "user_key": "cf3c50189c8448f7d334220334a1118d", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705775": {"up_voted": false, "ip": "", "has_replies": false, "message": "I think the charging issue is irrelevant because there are so few of you.  If Twitter can't find a better way to monetize than smacking the  &lt;500   Superusers with huge monthly fees they are eventually going to be toast anyway.   The Flickr model seems more realistic - charge heavy users a small annual fee and put them on a more robust platform.  Heck, I'll pay just to keep having to hear everybody talk so much about Twitter, the challenges of which seem to have gripped the online community in a dangerously obsessive fashion.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_16:29:58", "killed": false, "user_key": "d8bb4623895a9ba01a125d3d7800bead", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705776": {"up_voted": false, "ip": "", "has_replies": false, "message": "Trevor: well, if every Tweet is copied for every one of its potential readers, that totally explains why Twitter has some scale problems. Most Twitter users don't use the service very often, if at all (I watch).<br><br>In my scenario there ARE copies. Just not automatic ones. Also, Twitter only needs to keep the last 10 Tweets cached on each user's page, to keep the home page fast. Other pages take forever to load, so I doubt those are cached. Even in the home page scenario my Tweets would only be copied to those users who haven't had my Tweets replaced by other users (most of the time my Tweets would be pushed lower, so there wouldn't be 23,000 copies, only, maybe 1,000).<br><br>Either way, if I'm to blame for Twitter going down, why isn't FriendFeed going down? There's a lot more activity on FriendFeed surrounding my messages (and they aren't cached in any obvious way) and it's been down about 1/100th as much as Twitter.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_16:30:01", "killed": false, "user_key": "3553f5e0db0fd1ec4e40a932a2d8f5b3", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705777": {"up_voted": false, "ip": "", "has_replies": false, "message": "Maybe you're both right. Maybe it keeps a single copy of each tweet text and copies a tweet ID to each user's queue. The heavy-lifting of building the queue would be done at write time. To build a page it would look up each tweet ID in a user queue using a simple key-value map (which can easily be replicated and scaled.)", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_17:27:26", "killed": false, "user_key": "cc3b90976c1af1ca59fb5eb5603eaf63", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705778": {"up_voted": false, "ip": "", "has_replies": false, "message": "First, as someone has already noted, any large e-mail system will indeed duplicate messages being sent to a large number of recipients \u2014 typically a single copy per server, with each recipient getting a Unix hard link (or equivalent) to that copy.<br><br>There are several critical differences between Twitter and e-mail, however. The push or notification aspect is one, but message size is a big one. In particular, each of the hard links pointing to a single instance of an e-mail will be bigger than the entire body of a Tweet! Duplicating messages, even in pathological cases like Scoble's, is trivial: 25,000 copies of a 140 byte message represents a mere 3.5 Mbytes, smaller than a single large e-mail body!<br><br>Similarly, I think you're overestimating the burden of keeping pre-calculated per-viewer data around: the default view has about 16 messages, each 140 bytes plus a bit of metadata (sender username/icon URL), total perhaps 3.2K. 10,000 users on the server? 32 Mb! Trivial. Even ten *million* users on a single node would fit on a PC you can buy online from Dell!<br><br>The best architecture is probably a hybrid: keep the recent message queue in RAM for active users (and update realtime when those they follow post messages), built the cache from disk when they log in. Even on a single host, with 15kRPM drives (4ms writes), that's 100 spindle-seconds; a pair of Apple's 16-drive arrays and you're looking at three seconds to process a Scoble-tweet, ignoring both write merging and RAID overhead.<br><br>In reality, of course, you can omit a lot of those write-barriers and re-issue the writes from a redo log in the event of a crash, cutting the write load still further. Mirror the writes and distribute reads consistently, you get failover and gain cache hits to boot (each server only sees half as many active users).<br><br>Or you write it all in Ruby and SQL then throw a kajillion dollars worth of hardware at making it all sort of work most of the time through brute force. Even $15m can only buy you so much brute force, though...", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_17:29:17", "killed": false, "user_key": "16d48334bc778cdb73271c72c953a86f", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705779": {"up_voted": false, "ip": "", "has_replies": false, "message": "Everyone should read Nick Halstead's comment.<br><br>Robert, I'm sure from reading these comments that the people talking about the technical problems understand how a the normalized databases they teach you in Computer Science course work. It just that large system can't use them (flickr for example doesn't it's sharded / de-normalized)<br><br>I don't think is twitter is sharded yet since they weren't at 350,000 users (<a href=\"http://highscalability.com/scaling-twitter-making-twitter-10000-percent-faster\" rel=\"nofollow\">http://highscalability.com/scaling-twitter-maki...</a>)<br>They certainly SHOULD be copying messages around if they are sharded.<br><br>You would think if they could get to 350,000 users on one database they could get to 1 million users by adding some database read-only slave servers.<br><br>Scaling isn't about saving disk space, CPU cycles, memory - that is being efficient it's not the same thing. Microsoft might try that with Exchange to reduce their customers hardware costs (not that it works from what I hear)<br><br>Scaling is knowing you can buy a rack of machines of servers and actually make them reduce your load.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_17:32:20", "killed": false, "user_key": "6d64d1f44126702d2502b9ced6033fb3", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705780": {"up_voted": false, "ip": "", "has_replies": false, "message": "Mr. Scoble,<br><br>  I must say that I have not really cared enough to read your column in the past. After reading this post, however, I will make sure never to read anything else you choose to write. What I see is a person that is clearly ignorant about a complex set of topics related to application design and scalability, speaking sophomorically about them. Perhaps you should take some time, in your case, a great deal of it, and educate yourself about these matters before speaking great volumes of nonsense relating to the technical implementation of this or any other application.<br><br>  Start by reading the comments here and questioning some of the very smart people, who have graciously taken the time to try and educate you. Please, for the sake of the thousands of people that clearly believe you to be an authority on matters of technology, stop this idiocy.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-31_07:53:23", "killed": false, "user_key": "761378873ebe3b4ad0b10a5e689e13ee", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705781": {"up_voted": false, "ip": "", "has_replies": false, "message": "Could not resist typing up my complete thoughts on scaling twitter - <a href=\"http://blog.fav.or.it/2008/05/26/fixing-twitter/\" rel=\"nofollow\">http://blog.fav.or.it/2008/05/26/fixing-twitter/</a>", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_18:13:01", "killed": false, "user_key": "033c4fe3a6aae69596fee56044f03c32", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705782": {"up_voted": false, "ip": "", "has_replies": false, "message": "I just wanted to put in another \"Everyone should read Nick Halstead\u2019s comment\" vote.  Honestly, there are many things I admire about Scoble (getting the obligatory compliment before the insult out of the way) but this post is just ridiculous from at technical perspective.<br><br>As far as \u201ccharging super users\u201d goes it isn\u2019t really worth arguing because its going to be different for every service.<br><br>This is why you need a business model.  To determine which ways of making money will be most effective and execute on them.  Charging super users will be right in some cases while being wrong in others (depending on how much value the company in question can put into the \u201ccharged\u201d scenario)", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_18:16:37", "killed": false, "user_key": "44c5450cb486d4e4e5b80ef7a01e7017", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705783": {"up_voted": false, "ip": "", "has_replies": false, "message": "I don't know if twitter are using a sharded database yet, at 350,000 users they still only had one database and read slave:<br><a href=\"http://highscalability.com/scaling-twitter-making-twitter-10000-percent-faster\" rel=\"nofollow\">http://highscalability.com/scaling-twitter-maki...</a><br>Dare's post would make sense if they have now moved to a sharded structure but my best guess is that they haven't had a chance to do that yet.<br><br>It seems there will be duplication at least in the caching layer (memcached),<br>everytime Scoble sends a message 25,000 per user caches get invalidated and will need repopulating by new SQL queries.<br><br>Twitter are looking to get rid of the \"with others\" tab from a user to avoid at least some of this very type of problem, see here:<br><a href=\"http://groups.google.com/group/twitter-development-talk/browse_thread/thread/89a7292e5a9eee6d\" rel=\"nofollow\">http://groups.google.com/group/twitter-developm...</a><br><br>I think charging heavy users is the wrong model.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_12:47:59", "killed": false, "user_key": "6d64d1f44126702d2502b9ced6033fb3", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705784": {"up_voted": false, "ip": "", "has_replies": false, "message": "Charging is silly.<br><br>- Money won't help twitter right now.<br>- Charging won't deter \"superusers\".<br><br>They shouldn't charge, they should ban.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_13:41:24", "killed": false, "user_key": "04444ddd0eb03e7b3caaf196300ad372", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705785": {"up_voted": false, "ip": "", "has_replies": false, "message": "Robert (Scoble, not the other one) -<br>Twitter does store multiple copies of each message, they've said so repeatedly in various presentations.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_12:10:42", "killed": false, "user_key": "c13bd49d1c0135cbbc3717270824b22e", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705786": {"up_voted": false, "ip": "", "has_replies": false, "message": "Robert: Um, I don't think you understand what Dare was saying. You might wanna calm down a touch. It might be unfair to blame *you* for Twitter's woes, but Dare's analysis of the architecture is probably pretty accurate.<br><br>Open up Twitter... now, did you wait several minutes for your page to appear? If not, then something's being cached on the server side. It could be via memcached, it could be via \"baking\" your page instead of \"frying\" it, or whatever. But the data isn't being collected on the fly as you seem to believe. It's being pushed into the cache when you're not around to ensure UI response times remain tolerable.<br><br>Dare's point was that Twitter was built as a micro-blogging system, and that's how blogging systems work. You cache the hell outta everything, and you make a choice... make some users wait for extended page renders, or burn cycles in the background to ensure that everyone gets equal treatment.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_11:37:10", "killed": false, "user_key": "5f89d3df08b8dedac1a0fde900a586db", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705787": {"up_voted": false, "ip": "", "has_replies": false, "message": "\"First of all, Twitter doesn\u2019t store my Tweets 25,000 times. It stores them once and then it remixes them. This is like saying that Exchange stores each email once for each user. That\u2019s totally not true and shows a lack of understanding how these things work internally.\"<br><br>Robert, as was already pointed out this was once true for Exchange, but regardless I fail to see how you can make this same assumption for Twitter.<br><br>Regardless of how many times it's stored, Twitter also has a tougher routing problem. With Exchange, the sender defines where the message will be received. Twitter is fundamentally different - the sender broadcasts the message, and then the system needs to figure out where to deliver it. This means some of your 25,000 followers - remember, it still has to figure out if I will receive the message based on whether it's an @reply and what my settings are.<br><br>Twitter also has to deliver it to the countless number of tracks. Let's assume that the average word length for English is 5.10 (<a href=\"http://blogamundo.net/lab/wordlengths/\" rel=\"nofollow\">http://blogamundo.net/lab/wordlengths/</a>). On twitter, it's likely less given the 140 char limitation, we tend to use more abbreviations and generally shorter words. Taking out, let's say, 30 chars for punctuation - that means there are 20 distinct words. Twitter in turn needs to figure out who is tracking what, and the track functionality supports tracking word1+word2+word3. Obviously there are a number of ways to implement this more efficiently, but in effect Twitter has to do a fair amount of processing to see if a given message should be delivered to a given person's track queue.<br><br>It's clear that they have a bottleneck somewhere. Given the roots of the service, it's pretty clear the architecture didn't plan for this kind of use - and they admitted it in the link Dario posted. None of us really know what's going on behind the scenes, but based on what little evidence we have Dare's scenario seems plausible and perhaps likely.<br><br>Ignoring some of the differences in how the service is used, the other thing that FriendFeed had was the luxury of architecting their system after they saw how Twitter was being used. Twitter likely would have done things differently with the benefit of hindsight, but it sounds like (from interviews with Blaine) that much of their time was spent fighting fires as opposed to re-engineering the system.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_10:43:08", "killed": false, "user_key": "f2181053f629eee77775220dc01b13dc", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705788": {"up_voted": false, "ip": "", "has_replies": false, "message": "Hi Robert. Do u remember that Twitter was born for other goal? Do u remember the name of <a href=\"http://www.dariosalvelli.com/2006/07/twttr-a-group-send-sms-application\" rel=\"nofollow\">Twttr</a>? It was \"only\" a send SMS group apps, in origin. The team is the same of Odeo. True?<br><br>So, Twitter is a sort of messagging system such as IM but in a public way (but you can also set a protected status, why are u frustated?) and as the team write the system that \"Twitter was not architected as a messaging system\":<br><br><a href=\"http://dev.twitter.com/2008/05/twittering-about-architecture.html\" rel=\"nofollow\">http://dev.twitter.com/2008/05/twittering-about...</a>", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_10:04:03", "killed": false, "user_key": "dariosalvelli", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": false, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705789": {"up_voted": false, "ip": "", "has_replies": false, "message": "There are two basic ways to build a Twitter-like solution. Either you have, (A) per tweet, a single write and, per user, huge joined reads; or, (B) per tweet, huge numbers of writes and, per user, a single cheap read.<br><br>With Twitter, reading generally happens more often than writing, especially when you have desktop clients built around polling. That implies going with solution (B), which has some big problems - most databases aren't set up to deal efficiently with lots of writes.<br><br>So, you can try to work it with solution (A), but then you need lots of muscle for all these joined queries. If you're using database sharding, you'll probably need to issue queries to multiple databases running on multiple machines, and join all the results and sort them by time, per each user page refresh or desktop client poll. That's a lot of work per user.<br><br>It sounds pretty expensive - better cache it. Leads to a hybrid solution; single write, rare combination reads but not too often (i.e. not every poll or page refresh). Some risk of stale updates.<br><br>No matter which way you look at it, though, the scaling isn't quite linear, as some of the old folks will follow new folks as they get added. It should ultimately end up as linear, though with a high constant factor, that constant determined by the average \"noise threshold\" per user.<br><br>Looking at the pure \"unit of work\", lots of writes probably beats lots of reads, because the reading solution requires sorting and, with the addition of caching layers, has cache coherency problems. Writing can be based around appending to queues.<br><br>Also, all the \"extra\" features that Twitter-folks (in their blogs at least) seem to think are so essential, are quite costly to implement.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_10:17:29", "killed": false, "user_key": "2facd380c5bdfbaa1a1e9c657578f135", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705790": {"up_voted": false, "ip": "", "has_replies": false, "message": "Geoff: Google have bought jaiku and so are unlikely to buy Twitter. :-)<br><br>I wonder how much the outages are driving people into Pownce and Jaiku. I know of at least one of my 'Twitter friends' who is going *back* to Jaiku because of the service problems.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_09:42:29", "killed": false, "user_key": "463a381eaf9c0c08bc130a1bea1874ee", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705791": {"up_voted": false, "ip": "", "has_replies": false, "message": "No, services shouldn't charge \"super users.\" (I'd be surprised if \"super users\" don't start receiving significant sponsorships to come and use a service).<br><br>As far as the workflow for Twitter vs. the workflow of FriendFeed, it's impossibly unfair to compare Twitter to FriendFeed (yet). Twitter is pushing updates the moment you send an update. FriendFeed isn't doing instant updates via XMPP (Jabber) or SMS.<br><br>Additionally, Twitter is at the \"oh wow, if I follow 10,000 people I'll probably have 1,000 follow me back and I can spam them.\" This is making a large number of \"super users\", not just you Robert :-) They're getting hammered in traffic compared to FriendFeed.<br><br>Let's compare the numbers in terms of service reliability and overall load (rounded down)... You've got 10,000 followers on FriendFeed and 20,000 on Twitter. If this is a true representation of the population on each service (it's not, but we'll pretend), this means Twitter has double the traffic of users. Double the traffic, in a push based service, does not mean double the load... There are double the updates to double the followers.<br><br>A semi-decent formula for load based on the above:<br>Twitter != FriendFeed x 2<br>Twitter = FriendFeed ^ 2", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_09:27:03", "killed": false, "user_key": "25769ac9da72e934b928e636906379c8", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705792": {"up_voted": false, "ip": "", "has_replies": false, "message": "As far as I'm aware Twitter is the only service that allows posting  and receiving by SMS. The big problem with SMS is it is a untimed service, when I text there is no guarantee when and if it will be delivered this must be a problem for them.<br><br>Robert if you remember in the bad old days :-) when Blogger was crashing all the time they offered a Pro service where you paid in the hope of some reliability - fortunately Google took them out and over a period of a year or two sorted out the problems. I hope that Google do the same with Twitter :-)", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_08:11:51", "killed": false, "user_key": "06efcd5ee6ab3b9480acce0eeece731f", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705793": {"up_voted": false, "ip": "", "has_replies": false, "message": "<em>\"This is like saying that Exchange stores each email once for each user. That\u2019s totally not true\"</em><br><br>Sweet how you never had to work with an Exchange server which did <strong>exactly</strong> that, and then added 'All' as a recipient to the address book of every user.<br><br>I'll grant it doesn't do it now.  But it sure as hell used to.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_07:30:00", "killed": false, "user_key": "e24b825d0765fa4efc1402444f3255a4", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705794": {"up_voted": false, "ip": "", "has_replies": false, "message": "Quote: \"If you unironically regard public comments on an RSS feed as \"conversations\" with \"friends,\" you either need a dictionary or better friends.\" <a href=\"http://textism.com/favrd/favorites/tweet/817323555\" rel=\"nofollow\">http://textism.com/favrd/favorites/tweet/817323555</a>", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_07:31:08", "killed": false, "user_key": "3efe0002892b76ab1039cce38125626c", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705795": {"up_voted": false, "ip": "", "has_replies": false, "message": "&gt;I\u2019ll grant it doesn\u2019t do it now. But it sure as hell used to.<br><br>I know it did. Which is why some people still don't understand the architecture that Exchange uses (which is why I was \"educated\" on the issue).<br><br>By the way, this caused a famous and massive problem inside Microsoft when the database server filled up when someone accidentally emailed something to \"all.\" Email went down for two days, the way I heard it.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_07:34:02", "killed": false, "user_key": "3553f5e0db0fd1ec4e40a932a2d8f5b3", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705796": {"up_voted": false, "ip": "", "has_replies": false, "message": "Michael Foord: nah, the problems would become much much worse as they scaled up. The architecture they chose isn't too far off. It's just that they never did engineer it properly. The fact that just this week they've gotten the ability to turn off features one by one shows me that they never were run professionally until recently. I bet that Twitter starts getting stable very quickly now. Remember, there's only a million or two on Twitter. Facebook keeps up with 80 million. Hotmail 200 million every 30 days. Facebook and Hotmail don't go down, even though they are doing stuff more complex and at a larger scale than Twitter is.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_07:25:44", "killed": false, "user_key": "3553f5e0db0fd1ec4e40a932a2d8f5b3", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705797": {"up_voted": false, "ip": "", "has_replies": false, "message": "Translation: the only scaling problem would be when I started up my Twitter and wanted to see all objects from everyone. Then my object would  have to work harder than, say, your object because your object would only have to find a few Tweets. Mine has to find 23,000. OK, so they have to throw a little extra processor at my account, but only when I'm using the system. If, like right now, I'm not using the system it has absolutely no extra load on the system unless someone calls my object and makes it do work.<br><br>How do I know this? Ask the Exchange team how it keeps stuff from duplicating all over the place and causing server disks from filling up.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_07:18:41", "killed": false, "user_key": "3553f5e0db0fd1ec4e40a932a2d8f5b3", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705798": {"up_voted": false, "ip": "", "has_replies": false, "message": "&gt;&gt;Once you post a Message it gets copied to the streams of all your followers.<br><br>Absolutely wrong.<br><br>Only gets copied if a user instantiates his object and asks for those things. Even then, it's not \"copied\" except to display it, and that copy is temporary and stored in your browser, or in your Google Talk account.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_07:20:13", "killed": false, "user_key": "3553f5e0db0fd1ec4e40a932a2d8f5b3", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705799": {"up_voted": false, "ip": "", "has_replies": false, "message": "\"If this were a straight \u201cn-scale\u201d problem the crashing problems wouldn\u2019t have shown up so early.\"<br><br>Why not? As they scale up their system - the number of users is growing just as fast. If they scale just quick enough to stay one step behind the problem they will continue to have issues.<br><br>I don't blame them - it's a difficult problem and not many sites have to cope with such massive growth so quickly.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_07:21:19", "killed": false, "user_key": "463a381eaf9c0c08bc130a1bea1874ee", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705800": {"up_voted": false, "ip": "", "has_replies": false, "message": "So it is no secret to say that Twitter wasn't created with scalability in mind - like 90% of all \"2.0\" projects. After all, Twitter was born and it stayed completely in the dark for over 8 months until it exploded at the SXSW'07. I don't think it went down during those first 8 months (and if it did, not many people noticed anyway).<br><br>And ever since the first time it went down, chances are they've been patching and optimizing things here and there, when perhaps what Twitter needs is a complete remake - which shouldn't really be THAT hard considering Twitter is above all, a very simple application - that thing doesn't put a spacecraft in Mars - so the main focus should be scalability. Perhaps they're doing that already. If not, they should.<br><br>On the other hand, FF most likely has been created with scalability in mind, and so far, other than throwing hardware at it, as long as they're somewhat ahead of the growth game, it doesn't need anything to stay afloat as it grows. It's not rocket science either - they simply didn't (supposedly) ignore the possibility of growth when they started to write their software. Which is what everyone should do when starting a project, and there's plenty of documentation out there and plenty of great engineers who know how to architect a simple (or complex) app so that it will scale if necessary.<br><br>Leaving that aside, the business model is a very interesting and fair question. No, I don't agree with Om. Not because I don't think super-users shouldn't be charged, but because charging super-users doesn't fix anything, scalability-wise. I also don't think Om understands how Twitter works internally. Ok, *I* don't know how Twitter works, but if it does the way Om describes it, then the folks at Twitter absolutely definitely need to rewrite the whole thing from scratch. Personally I didn't like neither Obasanjo's nor Om's articles at all. You? Well, you're talking about Twitter and FriendFeed, and a bit of Facebook. Thank god for that \"This is why I love the tech industry\" article, because it is for posts like that I'm still reading you. (No offense, I just don't use neither Tw nor FF, so this fun madness you guys have is completely out of my radar...)", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_07:23:40", "killed": false, "user_key": "ce1d8230da097424bf1a399a7fa4745d", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705801": {"up_voted": false, "ip": "", "has_replies": false, "message": "As far as I know this is exactly how Twitter does it. Once you post a Message it gets copied to the streams of all your followers. The problem is that building up the last messages of the people you follow based on their user_id is just not working fast enough. Having a copy of your message is easier and faster to load. so this is exactly how it works, but I am not sure why this means that you need to start paying :)", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_06:59:31", "killed": false, "user_key": "0f30ffbf46ec1241c48e0c435367bab4", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705802": {"up_voted": false, "ip": "", "has_replies": false, "message": "If you're awake for 12 hours a day you have 3.9 seconds to 'interact' with each of your 'friends'.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_07:03:46", "killed": false, "user_key": "5cdc05de245c195c21a6dc5d7070527f", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705803": {"up_voted": false, "ip": "", "has_replies": false, "message": "Wolf: that's assuming that each of my friends actually does anything or wants to be interacted with. I've found that to be not true at all.<br><br>Anyway, here's another really interesting conversation cluster that this post started over on FriendFeed: <a href=\"http://friendfeed.com/e/a2463347-f07a-ab3f-4f41-dba35d38dee9\" rel=\"nofollow\">http://friendfeed.com/e/a2463347-f07a-ab3f-4f41...</a>", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_07:09:39", "killed": false, "user_key": "3553f5e0db0fd1ec4e40a932a2d8f5b3", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705804": {"up_voted": false, "ip": "", "has_replies": false, "message": "Could you elaborate on \"remixes them\"? Because so far Dare Obasanjos thoughts sounds much more plausible.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_07:16:03", "killed": false, "user_key": "f3b41bc009a402017febfab746770bc5", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705805": {"up_voted": false, "ip": "", "has_replies": false, "message": "Tiago: FriendFeed certainly notifies people. It even has an API where you can get messages sent into.<br><br>As to architecture. OK, let's have one object:<br><br>Scoble's Tweets.<br><br>Then let's have another object.<br><br>Jane Smith's Tweets.<br><br>Now let's have a third object:<br><br>John Schmidt's Tweet page that displays both Jane's and Scoble's Tweets.<br><br>Sounds like Scoble's and Jane's Tweets are being copied, right?<br><br>No.<br><br>In fact, if John Schmidt never uses his account, nothing happens at all.<br><br>But, let's say that John Schmidt opened his Web browser and visited Twitter. Well, ONLY THEN does John Schmidt's object (which knows which Tweets it should go look for) talk to the other two objects, and say \"give me your Tweets.\" Then John's object mashes them together and displays them to John. It also, then, closes down and releases all memory and disk space until the next time John asks for something.<br><br>This does not change if there are a million \"objects\" being mashed up. No copies are living permanently. Just the original objects.<br><br>Got it yet? I'll do a video, if you want to understand it more.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_07:16:12", "killed": false, "user_key": "3553f5e0db0fd1ec4e40a932a2d8f5b3", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705806": {"up_voted": false, "ip": "", "has_replies": false, "message": "Robert, Duncan Riley referred me to a plugin for wordpress blogs that automatically adds friendfeed comments to the originating post on your blog + lets people comment on friendfeed items from the blog as well. You can see it in action on his <a href=\"http://Inquisitr.com\" rel=\"nofollow\">Inquisitr.com</a> site. Here's the link to that plugin if you're interested: <a href=\"http://tinyurl.com/2uqa6l\" rel=\"nofollow\">http://tinyurl.com/2uqa6l</a>", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_07:16:55", "killed": false, "user_key": "a30e775d1972cd2a2843193faa241a97", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705807": {"up_voted": false, "ip": "", "has_replies": false, "message": "Actually Dare's post sums it up. It doesn't mean that Twitter's architecture is the one he suggests but given their database problems it's very likely.<br><br>Everytime you update, Twitter has to get a list of your 25k followers, sort out any @ replies, find out what their notification settings are, notify each and everyone individually and add a message to their feed (even if it's still the same one). All this while their feeds are being hit like crazy by desktop clients.<br><br>So, Twitter is a notification system with multiple entries and exit points. Friendfeed is an aggregator. It doesn't, as far as I know, notify anyone.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-26_06:56:54", "killed": false, "user_key": "17fd339dc782f5adc7f57437e653d2cd", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705808": {"up_voted": false, "ip": "", "has_replies": false, "message": "Does it really cost that much to host someone's Tweets, even if they are quite frequent?  If so, that seems like an inefficient model.  I feel like most sites practice some form of economies of scale to where frequent users actually become more affordable (and therefore receive price breaks)... so, for example, Twitter might charge 2 cents for every 10 posts to relatively infrequent users like myself, and 2 cents for every 100 posts to frequent updaters.  Keeping costs low for busy Twitterers would also increase business for them, since people are more likely to check your site frequently when it is frequently updated.  If Twitter has difficulties understanding this, I can recommend a <a href=\"http://www.booksonboard.com/index.php?BODY=viewbook&amp;BOOK=132378\" rel=\"nofollow\">Basic Economics textbook (ebooks version)</a>.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-27_16:35:17", "killed": false, "user_key": "0976088d32ab8aa425f99b9f7fe6fe28", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705809": {"up_voted": false, "ip": "", "has_replies": false, "message": "\"First of all, Twitter doesn\u2019t store my Tweets 25,000 times. It stores them once and then it remixes them.\"<br><br>I do know how Twitter is built. However, \"back in the day,\" I was the development manager for a real-time, stock quote delivery system, so I do have some experience with architectural issues Twitter may be facing.<br><br>Let's look at the procedure Robert refers to as \"remixes them.\" In the simplest architecture, there would be a single list (database, flat file, etc) of all the twitters created by everyone stored in chronological order.  You may, as a storage optimization, just store a user id with the twitter string, and tweet time stamp (aka a tweet).<br><br>In this single architecture, a \"remix\" would require a query across all the tweets for a period of time for all people that a user follows. This query would be fairly fast when the number of tweets in the specified period of time is fairly small, and the number of users a person follows is fairly small. You can see that this type of query becomes more expensive when the number of users you follow increases and the overall number of tweets per period increases.<br><br>So to speed up this query, you could build some kind of index based on users.  But maintaining this  index would become expensive, especially during high incoming tweet periods.<br><br>So one might try to optimize this architecture by breaking up the universal store into list of tweets per person. Now each incoming tweet can be easily added to the user's tweet list.<br><br>Then the \"remix\" of tweets of the people you follow would require a join across each list and then sorted by chronological order.  This would become increasingly more expensive when a user starts to increase the number of people they follow. It would be particularly expensive for super users who follow lots of users.<br><br>A reasonable compromise might be to keep a single universal stream of tweets in chronological order and two lists for each user: a list of pointers of all their tweets, and a list of pointers to all the tweets from the people they follow.<br><br>Maintaining these three lists would look something like: sender publishes a tweet, it is added to the universal store, a pointer is then added to the sender's tweet list, and then \"push the tweet to followers\" by walking sender's list of followers and add a pointer to the tweet to each \"follow\" list.<br><br>This approach scales fairly well. It allows the act of updating the follow lists to be partitioned across multiple servers. Each server can just take (using shared queues) a tweet from the universal store and \"fan it out\" to the appropriate followers. It also can be separates the operation from the inbound tweet processing.<br><br>To optimize the \"fan it out\" process, messaging publish and subscribe product like JMS or TIBCO Rendezvous and broadcast the tweets to the servers that manage follow lists. This would require a universal store process to publish all tweets and a cloud of follow list managers listening (aka subscribing) to tweet broadcasts updates for each followed person.<br><br>This approach also nicely addresses Twitter's need to separate outbound follower queues for users that have requested point to point delivery of messages via Instant Messaging and SMS.<br><br>For further scaling optimzation, you can have several tweet stores instead of one single universal store. You just need to ensure that all incoming tweets from a particular user are added to the same store to maintain ordered delivery to followers.<br><br>So it is quite reasonable to copy (at least references) each of Robert's tweets 25,000 times, just do so in a scalable manner.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-28_02:24:11", "killed": false, "user_key": "cdafe501caff10374da4f68277a1ccd7", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}, "9705810": {"up_voted": false, "ip": "", "has_replies": false, "message": "Life is a very short journey and we are not here to waste it in using Twitter, Facebook, iPhone, Flickr,ETC..  then simple die.I just don't get it how do we benefits the community and the people by using these things what is the meaning of these things in life. people are dying all over the world and we are using Twitter to stay in touch with friends.", "is_last_child": false, "can_reply": false, "down_voted": false, "real_date": "2008-05-30_17:31:47", "killed": false, "user_key": "967c7a60693f189f8be9348b7da03dc6", "has_been_anonymized": false, "edited": false, "author_is_moderator": false, "from_request_user": null, "votable": true, "date": "1 year ago", "approved": true, "num_replies": 0, "is_first_child": false, "email": "", "parent_post_id": null, "depth": 0, "points": 0, "author_is_creator": false, "is_realtime": false}}, "integration": {"receiver_url": "", "theme": 4, "reply_position": true, "disqus_logo": false}, "timer": {"timer_url": "http://localhost:8005", "thread_id": "18349417", "user_id": "anonymous", "forum_id": "125200", "hash": -5534100187428100124}, "thread": {"total_posts": 0, "paginate": false, "per_page": 0, "slug": "should_services_charge_8220super_users8221", "num_pages": 1, "days_alive": 0, "realtime_paused": true, "id": 18349417, "num_posts": 62, "closed": true, "queued": false, "killed": false}, "reactions_limit": 10, "context": {"show_reply": false, "use_fb_connect": true, "forum_facebook_key": "faaf467d0f47abde553c3b8e0e1b3570", "use_yahoo": false, "subscribed": false, "use_twitter_signin": true, "use_openid": false, "realtime_speed": 5000}, "reactions_start": 0, "settings": {"debug": false, "disqus_url": "http://disqus.com", "media_url": "http://media.disqus.com"}, "media_url": "http://media.disqus.com"};
	/* */ this.jsonData.cookie_messages = {"user_created": null, "post_has_profile": null, "post_twitter": null, "post_not_approved": null}; this.jsonData.session = {"url": null, "name": null, "email": null}; /* */

	
	this.curPageId = 'dsq-comments';

	this.frames = {};
};

var disqus_popup_reference = null;

if(typeof DsqLocal == 'undefined') {
	DsqLocal = {};
}



/**
 * Dsq.Strings: UI strings
 */
Dsq.Strings = new function() {
	this.ADD_NEW_COMMENT = "Add New Comment";
	this.LOG_INTO_DISQUS = "Log into DISQUS";
	this.USE_MEDIA = "Use Media";
	this.LOGOUT = "Logout";
	this.SHARING_OPTIONS = "Sharing options";
	this.SHARE_ON = "Share on";
	this.TWEET_THIS_COMMENT = "Tweet this comment";
	this.SHARE_ON_NEWSFEED = "Share on news feed";
	this.SEND_UPDATE_TO_YAHOO = "Send update to Yahoo!";
	this.REBLOG_ON = "Reblog on";
	this.CONFIGURE_OPTIONS = "Configure options";
	this.POST_AS = "Post as";
	this.SORT_BY = "Sort by";
	this.SUBSCRIBE_BY_EMAIL = "Subscribe by email";
	this.SUBSCRIBE_BY_RSS = "Subscribe by RSS";
	this.POPULAR_NOW = "Popular now";
	this.BEST_RATING = "Best Rating";
	this.NEWEST_FIRST = "Newest first";
	this.OLDEST_FIRST = "Oldest first";
	this.HIGHLIGHTED = "Highlighted";
	this.UNSUBSCRIBE = "Unsubscribe";
	this.REQUIRED = "Required";
	this.OPTIONAL = "Optional";
	this.YOU_ARE_COMMENTING_AS_A = "You are commenting as a";
	this.LOGIN_BELOW = "Login below";
	this.PLEASE_LOGIN_BELOW_TO_COMMENT = "Please login below to comment.";
	this.SUBSCRIBE_TO_ALL_COMMENTS_BY_EMAIL = "Subscribe to all comments by email";
	this.DO_NOT_SUBSCRIBE_TO_COMMENTS = "Do not subscribe to comments";
	this.REALTIME_UPDATING_IS = "Real-time updating is";
	this.ENABLED = "enabled";
	this.PAUSED = "paused";
	this.PAUSE = "Pause";
	this.RESUME = "Resume";
	this.SHOW = "Show";
	this.JUST_NOW = "Just now";
	this.REPLY = "Reply";
	this.EDIT = "Edit";
	this.FLAG = "Flag";
	this.MODERATE = "Moderate";
	this.CANCEL = "Cancel";
	this.REPLYING_TO = "Replying to";
	this.REPORT_MISSING_REACTIONS = "Report missing reactions";
	this.POST_A_COMMENT = "Post a comment";
	this.FLAG_INAPPROPRIATE_COMMENT = "Flag inappropriate comment";
	this.FLAGGED = "Flagged";
	this.NO = "No";
	this.YES = "Yes";
	this.NEVER_MIND = "Never mind";
	this.ARE_YOU_SURE_YOU_WOULD_LIKE_TO_REPORT_THIS_COMMENT_TO_A_MODERATOR = "Are you sure you would like to report this comment to a moderator";
	this.THIS_WILL_FLAG_COMMENTS_FOR_MODERATORS_TO_TAKE_ACTION = "This will flag comments for moderators to take action";
	this.TO_RATE_PLEASE_LOG_IN = "To rate, please log in";
	this.JUST_A_MOMENT = "Just a moment...";
	this.GUEST = "Guest";
	this.NAME = "Name";
	this.EMAIL = "Email";
  this.WEBSITE = "Website";
  this.SETTINGS = "Settings";
  this.MODERATOR_OPTIONS = "Moderator options: ";
  this.MODERATE_OPTIONS = "Moderate Options";

  // Thread moderator actions
  this.CLOSE_THREAD = "Close thread";
  this.OPEN_THREAD = "Open thread";
  this.REMOVE_THREAD = "Remove thread";
  this.RESTORE_THREAD = "Restore thread";
  this.ACTIONS = "Actions";
};
// Dsq.Strings

/**
 * Dsq.FmtStrings: functions that return interpolated UI strings
 */
Dsq.FmtStrings = new function() {
	// Seems we have to use named interpolation for Django to translate. Investigate more.
	this.LOGGED_IN_AS = function(username) {
		return Dsq.Utils.interpolate('Logged in as %(username)s', {username:username});
	};

	this.LOGOUT_FROM = function(disqus) {
		return Dsq.Utils.interpolate('Logout from %(disqus)s', {disqus:disqus});
	};

	this.SHOWING_COMMENTS_FULL = function(total, num) {
		if (num === 1) {
			return Dsq.Utils.interpolate("Showing <span id='dsq-num-posts'>%(num)s</span> of <span id='dsq-total-posts'>%(total)s</span> comment", {num:num, total:total});
		} else {
			return Dsq.Utils.interpolate("Showing <span id='dsq-num-posts'>%(num)s</span> of <span id='dsq-total-posts'>%(total)s</span> comments", {num:num, total:total});
		}
	};

	this.SHOWING_COMMENTS_WITHOUT_PAGINATION = function(num) {
		if (num === 1) {
			return Dsq.Utils.interpolate("Showing <span id='dsq-num-posts'>%(num)s</span> comment", {num:num});
		} else {
			return Dsq.Utils.interpolate("Showing <span id='dsq-num-posts'>%(num)s</span> comments", {num:num});
		}
	};

	this.NUMBER_OF_COMMENTS = function(num) {
		return Dsq.Utils.interpolate(
			(num == 1
				? '%(num)s comment'
				: '%(num)s comments'
			), {num:num});
	};

	this.NUMBER_OF_LIKES = function(num) {
		return Dsq.Utils.interpolate(
			(num == 1
				? '%(num)s like'
				: '%(num)s likes'
			), {num:num});
	};

	this.NUMBER_OF_POINTS = function(num) {
		return Dsq.Utils.interpolate(
			(num == 1
				? '%(num)s point'
				: '%(num)s points'
			), {num:num});
	};
};
// Dsq.FmtStrings





Dsq.CSRF_TOKEN = 'a2d140c59df8cd4ce27a20e0829cacd8';
Dsq.COMMENTS_RE = /(<li.*?id="?dsq-comment-(\d+)"?.*?>)((?:.|\s)*?)(<\/li>)/gim;
Dsq.POST_RE = /(<div.*?id="?dsq-comment-header-(\d+)"?.*?>)((?:.|\s)*?)(<\/div>)\s*(<div.*?class="?dsq-comment-body"?.*?>)((?:.|\s)*)(<\/div>)/gim;
Dsq.POST_BODY_RE = /\s*(<div.*?id="?dsq-comment-message-(\d+)"?.*?>)((?:.|\s)*)(<\/div>)/gim;
// HACK: Safari ends with "-->" while other browsers end with "--&gt;" as expected.
Dsq.MEDIA_POST_RE = /&lt;!--\[(.*?)\]--(?:>|&gt;)/gim;



var FragmentPacket = function(reader, writer, writer_url, is_child, receiveCallback) {
	var that = this;
	this.reader = reader;
	this.writer = writer;
	this.writer_url = writer_url;

	this.is_child = is_child || false;
	this.receiveCallback = receiveCallback;

	this._lastHash = null;

	this._accumMsg = '';

	this._lastSeqno = 0;

	this.MAX_DATA_LEN	= 1024;

	this.WAIT_TIME		= 10;

	this.READY		= 0x1;
	this.WRITING	= 0x2;
	this.FIN		= 0x4;
	this.ACK		= 0x8;

};

FragmentPacket.prototype.createListener = function() {
	var that = this;
	var listener = function() {
		that.recv();
	};
	return window.setInterval(listener, 10);
};

FragmentPacket.prototype.log = function(msg) {



};

FragmentPacket.prototype.recv = function() {
	var hash;
	if (/MSIE/.test(navigator.userAgent)) {

		hash = this.reader.name;
	} else {

		var hashIndex = this.reader.location.href.indexOf('#');
		if (hashIndex == -1) {
			return;
		}
		hash = this.reader.location.href.substring(hashIndex+1);
	}
	var flags = parseInt(hash.substring(0, 4), 10);
	var seqno = parseInt(hash.substring(4, 24), 10);
	var data  = hash.substring(24);

	if (this._lastHash !== hash) {
		this._lastHash = hash;
		this.log('recv: ' + hash);

		this.log(' flags: ' + flags);
		this.log(' seqno: ' + seqno + ' len: ' + hash.substring(4, 24).length + ' (' + hash.substring(4, 24) + ')');
		this.log(' data: ' + data + ' len: ' + data.length);

		this._lastSeqno = seqno;

		if (flags & this.WRITING) {
			this._accumMsg += data;
			this.sendFlag(this.ACK, seqno);
			if (flags & this.FIN) {
				this.log('recv finished: ' + decodeURIComponent(this._accumMsg));
				this.receiveCallback(decodeURIComponent(this._accumMsg));

				this._accumMsg = '';

				this.sendFlag(this.READY | this.ACK, this._lastSeqno);
			}
		}
	}

	return {
		flags: flags,
		seqno: seqno,
		data: data
	};
};

FragmentPacket.prototype.sendRawPacket = function(packet) {
	if (/MSIE/.test(navigator.userAgent)) {
		this.writer.name = packet;
	} else {

		this.writer.location.href = this.writer_url + '#' + packet;
	}

};

FragmentPacket.prototype.sendFlag = function(flag, seqno) {
	this.sendRawPacket(this._zerofill(flag, 4) + this._zerofill(seqno, 20));
};

FragmentPacket.prototype.send = function(msg) {
	this._send(0, encodeURIComponent(msg));
};

FragmentPacket.prototype._send = function(packetNum, msg) {
	var that = this;
	var recvBuf = this.recv();

	if (packetNum === 0) {

		if (!(recvBuf.flags & this.READY)) {
			this.log('client is not ready, waiting...');
			window.setTimeout(function() { that._send(packetNum, msg); }, this.WAIT_TIME);
			return;
		}
	} else {

		if (!( (recvBuf.flags & this.ACK) && (recvBuf.seqno === this._lastSeqno) )) {
			this.log('waiting for ack from client...');
			window.setTimeout(function() { that._send(packetNum, msg); }, this.WAIT_TIME);
			return;
		} else {
			this.log('received ack: ' + this._lastSeqno + ' ' + recvBuf.seqno);
		}
	}

	var flags = this.WRITING;
	var num_packets = Math.ceil(msg.length / this.MAX_DATA_LEN);
	this.log('num_packets: ' + num_packets);

	if (num_packets === packetNum) {

		this.log('message successfully sent!');
		this.sendFlag(this.READY | this.ACK, this._lastSeqno);
		return true;
	}

	this._lastSeqno++;

	if (packetNum == num_packets-1) {
		flags |= this.FIN;
	}

	var data = msg.substring(packetNum * this.MAX_DATA_LEN, (packetNum+1) * this.MAX_DATA_LEN);
	var packet = this._zerofill(flags, 4) + this._zerofill(this._lastSeqno, 20) + data;

	this.log('sending raw packet: ' + packet);
	this.sendRawPacket(packet);

	return this._send(packetNum + 1, msg);
};

FragmentPacket.prototype._zerofill = function(num, width) {
	var retval = num.toString();
	var retval_len = retval.length;
	for (var i = 0; i < width - retval_len; i++) {
		retval = '0' + retval;
	}
	return retval;
};

var PostMessagePacket = function(receiver, receiveCallback, id, receiverId) {
	var that = this;
	this.receiver = receiver;
	this.receiveCallback = receiveCallback;
	this.id = id;


	this.receiverId = receiverId;
};

PostMessagePacket.prototype.createListener = function() {
	var that = this;

	var listener = function(e) {

		if (!that.id) {
			that.id = e.data;
			return;
		}


		var id = e.data.split(';')[0];
		if (id !== that.id) {
			return;
		}
		var data = e.data.substring(e.data.indexOf(';') + 1);

		that.receiveCallback(data);
	};

	if (typeof window.attachEvent == 'function') {
		window.attachEvent('onmessage', listener);
	} else if (typeof window.addEventListener == 'function') {
		window.addEventListener('message', listener, false);
	} else {
		throw new Error('No method found to create event listener for PostMessagePacket.');
	}
};

PostMessagePacket.prototype.send = function(msg) {



	var needs_reget = false;
	try {
		if (typeof this.receiver.id == 'undefined' || typeof this.receiver.postMessage == 'undefined') {
			needs_reget = true;
		}
	} catch(e) {


	}
	if (needs_reget && typeof this.receiverId != 'undefined') {
		this.receiver = document.getElementById(this.receiverId).contentWindow;
	}

	var packet;
	if (!msg) {

		packet = this.id;
	} else {
		packet = this.id + ';' + msg;
	}
	this.receiver.postMessage(packet, '*');
};

PostMessagePacket._last_unique_id = null;
PostMessagePacket._get_unique_id = function() {
	var id = (new Date()).getTime();
	if (id == PostMessagePacket._last_unique_id) {
		id++;
	}
	PostMessagePacket._last_unique_id = id;
	return id.toString();
};

var JsonRpc = function() {

	this.ids = {};

	this.objectToJSON = function(obj) {
		var json = '';
		var results = [];

		if (obj === undefined || obj === null) {
			return 'null';
		}

		switch (obj.constructor) {
			case Object:
				for (var property in obj) {
					if (obj.hasOwnProperty(property)) {
						results.push(this.objectToJSON(property) + ': ' + this.objectToJSON(obj[property]));
					}
				}
				json = '{' + results.join(', ') + '}';
				break;
			case Array:
				for (var i = 0; i < obj.length; i++) {
					results.push(this.objectToJSON(obj[i]));
				}
				json = '[' + results.join(', ') + ']';
				break;
			case Number:
			case Boolean:
				json = obj.toString();
				break;
			case String:

				var specialChars = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\\': '\\\\'};

				json = obj.replace(/[\x00-\x1f\\]/g, function(match) {
					var ch = specialChars[match];
					return ch ? ch : '\\u00' + match.charCodeAt().toPaddedString(2, 16);
				});

				json = '"' + json.replace(/"/g, '\\"') + '"';
				break;
			default:

				json = 'null';
				break;
		}

		return json;
	};

	this.createHandler = function(send_func, registered_funcs) {
		var that = this;
		var handler = function(message) {

			try {
				var rpc = eval('(' + message + ')');
			} catch(e) {
				alert('bad JSON: ' + message);
				return;
			}
			if (rpc.method) {

				if (!registered_funcs[rpc.method]) {
					return;
				}

				var retval = registered_funcs[rpc.method].apply(null, rpc.params);
				if (rpc.id) {
					var response = {
						result: retval,
						error: null,	// TODO
						id: rpc.id
					};
					send_func(that.objectToJSON(response));
				}
			} else if(rpc.result) {

				if (!that.ids[rpc.id]) {
					return;
				}

				that.ids[rpc.id](rpc.result);
				delete that.ids[rpc.id];
			}
		};
		return handler;
	};

	this.execute = function(send_func, method, params, response_callback) {
		response_callback = response_callback || null;
		var id = (response_callback) ? (new Date()).getTime() : null;

		var request = {
			method: method,
			params: params,
			id: id
		};

		send_func(this.objectToJSON(request));

		if (id) {
			this.ids[id] = response_callback;
		}
	};
};
JsonRpc = new JsonRpc();

var ParentMessenger = function(childUrl, receiverUrl, container, receiveCallback) {


	if (navigator.userAgent.indexOf('Safari') >= 0 && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf('Version/') + 8), 10) == 3) {
		throw new Error("unsupported.");
	} else if (window.opera) {
		throw new Error("unsupported.");
	}



	if (!receiverUrl &&
		navigator.userAgent.indexOf('Gecko') >= 0 &&
		parseFloat(navigator.userAgent.slice(navigator.userAgent.indexOf('rv:') + 3, navigator.userAgent.indexOf('rv:') + 6)) < 1.9) {
		throw new Error("unsupported.");
	}


	if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {


		if (document.domain == window.location.hostname) {
			receiverUrl = '';
		}
	}

	var that = this;
	this.childUrl = childUrl;
	this.receiverUrl = receiverUrl;
	this.container = container || document.body;

	this.packetHandler = null;


	this._ready = false;
	this._error = false;


	var _createReceiverForFragmentPacket = function() {

		that.receiver = document.createElement('iframe');
		that.receiver.src = receiverUrl;
		that.receiver.id = 'receiver_' + (new Date()).getTime();
		that.receiver.name = that.receiver.id;

		that.receiver.frameBorder = '0';
		that.receiver.frameSpacing = '0';
		that.receiver.style.borderStyle = 'none';

		var receiver_onload = function() {
			var receiver = document.getElementById(that.receiver.id).contentWindow;

			try {
				receiver.document.body.innerHTML = '';
			} catch(e) {

				that._error = true;
			}
			receiver.document.body.style.padding = '0px';
			receiver.document.body.style.margin = '0px';

			var child = receiver.document.createElement('iframe');
			child.id = 'child';
			child.name = 'child';
			child.src = that.childUrl;

			child.frameBorder = '0';
			child.frameSpacing = '0';
			child.style.borderStyle = 'none';
			child.style.width = '100%';
			child.style.height = '100%';
			receiver.document.body.appendChild(child);

			that.child = receiver.document.getElementById('child').contentWindow;
			that.receiver = receiver;

			that.packetHandler = new FragmentPacket(that.receiver, that.child, that.childUrl, false, receiveCallback);

			that._listener = that.packetHandler.createListener();

			that.packetHandler.sendFlag(that.packetHandler.READY, 0);

			that._ready = true;
		};

		that.receiver.onreadystatechange = function() {
			if (this.readyState == 'complete') {
				receiver_onload();
			}
		};

		that.receiver.onload = receiver_onload;







		if (Dsq.Utils.ie) {
			if (that.container.clientWidth === 0) {

				var _waitForWidth = function() {
					if (that.container.clientWidth > 0) {
						Dsq.Utils.fixIframesIE(that.container.id);
					} else {
						window.setTimeout(_waitForWidth, 100);
					}
				};
				_waitForWidth();

				that._once = false;
				that.receiver.onresize = function() {
					if (!that._once) {
						Dsq.Utils.fixIframesIE(that.container.id);
					}
					that._once = true;
				};
			}
		}

		that.container.appendChild(that.receiver);
	};


	var _createReceiverForPostMessage = function() {

		var receiver_onload = function() {

			that.packetHandler.send();
			that._ready = true;
		};

		var id = PostMessagePacket._get_unique_id();
		var receiverId = 'child_' + id;


		ParentMessenger['_receiver_onload_' + receiverId] = receiver_onload;

		that.container.innerHTML += '<iframe ' +
			'src="' + childUrl + '" ' +
			'id="' + receiverId + '" ' +
			'name="' + receiverId + '" ' +
			'onload="ParentMessenger._receiver_onload_' + receiverId +'();" ' +
			'></iframe>';

		that.receiver = document.getElementById(receiverId).contentWindow;
		that.packetHandler = new PostMessagePacket(that.receiver, receiveCallback, id, receiverId);
		that._listener = that.packetHandler.createListener();
	};

	if (typeof window.postMessage == 'function') {
		_createReceiverForPostMessage();
	} else {
		_createReceiverForFragmentPacket();
	}

};

ParentMessenger.prototype.sendMessage = function(message) {
	var that = this;
	if (!this._ready) {

		window.setTimeout(function() { that.sendMessage(message); }, 10);
		return;
	}
	this.packetHandler.send(message);
	return true;
};

Dsq.NewFrames = function(url) {
	this.url = url;
};

Dsq.NewFrames.prototype.init = function(onFailure) {
	var that = this;

	try {
		this.messenger = new ParentMessenger(this.url, Dsq.jsonData.integration.receiver_url, this.container, this.receive_callback);
	} catch(e) {
		if (typeof onFailure == 'function') {
			onFailure();
		}
	}

	if (typeof onFailure == 'function') {
		var iId = window.setInterval(function() {
			if (typeof that.messenger == 'undefined') {
				window.clearInterval(iId);
				return;
			}
			if (that.messenger._ready) {
				window.clearInterval(iId);
			} else if (that.messenger._error) {
				window.clearInterval(iId);
				onFailure();
			}
		}, 10);
	}
};

Dsq.NewFrames.prototype._execute = function(method, args, callback) {
	var that = this;
	if (typeof that.messenger == 'undefined') {
		return false;
	}
	JsonRpc.execute(
		function(msg) { that.messenger.sendMessage(msg); },
		method,
		args || [],
		callback);
	return true;
};

Dsq.ReplyFrame = function(container, parent_post_id) {
	var that = this;
	this.container = container;
	this.parent_post_id = parent_post_id;

	var sendFunc = function(msg) {

		Dsq.Debug.log('Dsq.ReplyFrame.sendFunc');
		that.messenger.sendMessage(msg);
	};


	var postComment_onSuccess = function(response) {
		Dsq.jsonData.posts[response.message.id] = response.message.post_meta;
		if (!Dsq.jsonData.users[response.message.post_meta.user_key]) {
			Dsq.jsonData.users[response.message.post_meta.user_key] = response.message.user_meta;
		}


		var reply_position = (typeof(disqus_insert_wrt_sort) == 'undefined' 
			? (Dsq.jsonData.forum.reply_position ? -1 : null) 
			: (Dsq.jsonData.request.sort == 2 ? null : -1));
		
		if (response.message.post_meta.approved) {
			Dsq.Post.insert(response.message.post_meta.parent_post_id || reply_position, response.message.id, response.message.post_meta.message);
		}

		Dsq.Templates.postComment_onSuccess(response, parent_post_id, response.message.id);
	};

	var postComment_onFailure = function(response) {
		Dsq.Popup.popModal(response.message, 'Error');
		Dsq.Templates.postComment_onFailure(response, parent_post_id, response.message.id);
	};

	var editComment_onSuccess = function(response) {
		var post_id = parent_post_id;
		var message = Dsq.$('dsq-comment-message-' + post_id);
		
		message.innerHTML = response.message;
		Dsq.Templates.toggleEdit(post_id);
		Dsq.Templates.setLoadingButton(false);
	};
	
	var editComment_onFailure = function(response) {
		var post_id = parent_post_id;
		
		Dsq.Popup.popModal('Sorry, there was an error editing this comment.', 'Edit Error');
		Dsq.Templates.toggleEdit(post_id);
		Dsq.Templates.setLoadingButton(false);
	};

	var getUserByEmail_onSuccess = function(response) {
		var msg = response.message;
		var fields = Dsq.Templates.getFormFields(parent_post_id);

		if (msg.username) {

			Dsq.Templates.lightboxAuthenticate(parent_post_id, 'login', {
				'username': msg.username,
				'display_name': msg.display_name,
				'avatar_url': msg.avatar_url,
				'verified': msg.verified,
				'email': fields.email.value
			});
		} else {

			Dsq.Templates.lightboxAuthenticate(parent_post_id, 'register');
		}
	};

	var validateAuth_onSuccess = function(response, auth_choice) {
		Dsq.Templates.postComment(parent_post_id, null, true, auth_choice);
	};

	var validateAuth_onFailure = function(response, auth_choice) {
		var pid = parent_post_id ? '-' + parent_post_id : '';
		var msg = response.message;

		if (auth_choice == 'register') {
			var fields = ['email', 'username', 'password'];

			for (var i = 0; i < fields.length; i++) {
				var field = fields[i];
				var errorDiv = Dsq.$('dsq-' + field + '-errors' + pid);

				if (msg[field]) {
					errorDiv.innerHTML = msg[field];
				} else {
					errorDiv.innerHTML = '';
				}
			}
		} else if (auth_choice == 'login') {
			Dsq.$('dsq-lightbox-errors' + pid).innerHTML = '<p>We couldn\'t log you in. Please verify your login.</p>';
		}
		
		Dsq.Templates.setLoadingButton(false);
	};

	this.receive_callback = JsonRpc.createHandler(sendFunc, {
		'postComment.onSuccess': postComment_onSuccess,
		'postComment.onFailure': postComment_onFailure,
		'editComment.onSuccess': editComment_onSuccess,
		'editComment.onFailure': editComment_onFailure,		
		'getUserByEmail.onSuccess': getUserByEmail_onSuccess,
		'validateAuth.onSuccess': validateAuth_onSuccess,
		'validateAuth.onFailure': validateAuth_onFailure,
		'reload': function() { window.location.reload(); }
	});

	this.url = Dsq.Urls.REPLY +
		'?' + (new Date()).getTime() +
		'&f=scobleizer' +
		'&t=should_services_charge_8220super_users8221' +
		'&ff=' + Dsq.Thread.ff +
		'&default_text=' + encodeURIComponent(disqus_default_text) +
		'&ifrs=' + encodeURIComponent(disqus_iframe_css);
	if (this.parent_post_id) {
		this.url += '&parent_post=' + this.parent_post_id;
	}
};

Dsq.ReplyFrame.prototype = new Dsq.NewFrames(Dsq.ReplyFrame.url);

Dsq.ReplyFrame.prototype.post = function(author_name, author_email, author_url, authenticate, sharing_services, subscribe) {
	this._execute('postComment', [author_name, author_email, author_url, authenticate, sharing_services, subscribe]);
};

Dsq.ReplyFrame.prototype.edit = function(post_id, message) {
	this._execute('editComment', [post_id, message]);
};

Dsq.ReplyFrame.prototype.setState = function(parent_post_id, depth) {
	this._execute('setState', [parent_post_id, depth]);
};

Dsq.ReplyFrame.prototype.getUserByEmail = function(email) {
	this._execute('getUserByEmail', [email]);
};

Dsq.ReplyFrame.prototype.validateAuth = function(auth_choice, email, username, password) {
	this._execute('validateAuth', [auth_choice, email, username, password]);
};

Dsq.ReplyFrame.prototype.authenticateFacebook = function(session, forum_url) {
	this._execute('authenticateFacebook', [session, forum_url]);
};

	Dsq.Facebook = function() {
	var that = this;

	var handleSessionData = function(session) {

		var forum_url = Dsq.jsonData.forum.url;




		if (typeof disqus_facebook_forum != 'undefined') {
			forum_url = disqus_facebook_forum;
		}
		Dsq.frames.reply_0.authenticateFacebook(session, forum_url);
	};

	var onLogin = function() {
		FB.Connect.getSignedPublicSessionData(handleSessionData);
	};

	this.login = function() {
		FB.Connect.requireSession(onLogin, true);
	};
};
Dsq.Facebook = new Dsq.Facebook();


	






Dsq.Themes = {};

Dsq.Themes.narcissus = new function() {
	this.addPostContainer = 'dsq-form-area';
	this.textareaContainer = 'dsq-textarea-wrapper';



	
	this.header = function() {
		var comments_count, total_posts, num_posts;
		var html = '';
		var missing_perm_tmpl;

		if (Dsq.jsonData.request.missing_perm) {
			missing_perm_tmpl = Dsq.Templates.missingPermissions();
			if (missing_perm_tmpl) {
				html += '<div class="dsq-missing-permissions">' + missing_perm_tmpl + '</div>';
			}
		}

		total_posts = Dsq.jsonData.thread.total_posts;
		num_posts = Dsq.jsonData.thread.num_posts;

		if (total_posts) {
			comments_count = Dsq.FmtStrings.SHOWING_COMMENTS_FULL(total_posts, num_posts);
		} else {
			comments_count = Dsq.FmtStrings.SHOWING_COMMENTS_WITHOUT_PAGINATION(num_posts);
		}

		html += ' \
		<div id="dsq-comments-title"> \
			<h3>' + comments_count + '</h3> \
		</div> \
		';

		html += ' \
		<div class="dsq-options"> \
			<span class="dsq-item-sort">'
				+ Dsq.Strings.SORT_BY + ' \
				<select id="dsq-sort-select" onchange="Dsq.Thread.sortBy(this.value);"> \
					<option value="hot" ' + (Dsq.jsonData.request.sort == 4 ? 'selected="selected"' : '') + '>' + Dsq.Strings.POPULAR_NOW + '</option> \
					<option value="best" ' + (Dsq.jsonData.request.sort == 3 ? 'selected="selected"' : '') + '>' + Dsq.Strings.BEST_RATING + '</option> \
					<option value="newest" ' + (Dsq.jsonData.request.sort == 2 ? 'selected="selected"' : '') + '>' + Dsq.Strings.NEWEST_FIRST + '</option> \
					<option value="oldest" ' + (Dsq.jsonData.request.sort == 1 ? 'selected="selected"' : '') + '>' + Dsq.Strings.OLDEST_FIRST + '</option> \
				</select> \
				&nbsp; \
			</span> \
			<span class="dsq-subscribe-email"> \
				<img src="http://media.disqus.com/images/embed/email.png" style="width:12px;height:12px;vertical-align:middle"> \
				<span id="dsq-subscribe">'
					+ (Dsq.jsonData.context.subscribed
						? '<a href="#" onclick="Dsq.Thread.subscribe(0); return false">' + Dsq.Strings.UNSUBSCRIBE + '</a>'
						: '<a href="#" onclick="Dsq.Thread.subscribe(1); return false">' + Dsq.Strings.SUBSCRIBE_BY_EMAIL + '</a>')
				+ '</span> \
			</span> \
			<span class="dsq-subscribe-rss" style="width:12px;height:12px;vertical-align:middle"> \
				<img src="http://media.disqus.com/images/embed/bullet-feed.png" alt="" /> \
				<a href="http://scobleizer.disqus.com/should_services_charge_8220super_users8221/latest.rss">' + Dsq.Strings.SUBSCRIBE_BY_RSS + '</a> \
			</span> \
		</div> \
		';

		
		

		return html;

	};
	
	this.footer = function() {
		var html = '';

		html += Dsq.Templates.pagination();

		
		
			html += Dsq.Templates.realtime();
			html += Dsq.Templates.showThreadSettings();
			html += Dsq.Templates.postBox();

		html += Dsq.Templates.reactions();

		
			html += Dsq.Templates.trackbacks();
		


		if (Dsq.jsonData.request.is_global_moderator) {
 			html += ' \
				<div class="dsq-global-moderator-extras">'
					+ '<strong>shortname:</strong> ' + Dsq.jsonData.forum.url
					+ '<strong>thread id:</strong> ' + Dsq.jsonData.thread.id
					+ '<strong>thread slug:</strong> ' + Dsq.jsonData.thread.slug
				+ '</div> \
			';
		}

		return html;
	};
	
	this.realtime = function() {
		var html = '';
		
		if (Dsq.jsonData.realtime_enabled) {
			html += '<div id="dsq-realtime-options" class="dsq-options">'
					 + Dsq.Strings.REALTIME_UPDATING_IS + ' <strong id="dsq-realtime-status" style="text-transform: lowercase">' + Dsq.Strings.ENABLED + '</strong>. \
					 <a href="#" id="dsq-realtime-toggle" style="text-transform: capitalize"></a> \
					</div>';
		}

		if (!Dsq.jsonData.forum.streaming_realtime) {
			html += ' \
				<div style="display: none" id="dsq-realtime-alert" class="dsq-realtime-alert"><span id="dsq-realtime-queued"></span> <a href="#" id="dsq-realtime-show"></a></div> \
			';
		}
		
		return html;
	};

	this.showThreadSettings = function() {
		if (!Dsq.jsonData.request.is_moderator) {
			return '';
		}

		html = '<div id="dsq-thread-settings" class="dsq-thread-settings">' + Dsq.Strings.MODERATOR_OPTIONS;
		html += '<a href="#" onclick="Dsq.Thread.showSettings(); return false;">' + Dsq.Strings.SETTINGS + '</a>';
		html += '<a href="#" onclick="Dsq.Thread.showModeratorActions(); return false;">' + Dsq.Strings.MODERATE + '</a>';
		if (Dsq.jsonData.forum.reactions_enabled && Dsq.jsonData.reactions.length === 0) {
			html += '<a href="#" onclick="Dsq.Reaction.reportMissingReactions(); return false;">'
						+ Dsq.Strings.REPORT_MISSING_REACTIONS
						+ '</a>';
		}
		html +='</div>';

		return html;
	};

	this.postBox = function(post_id, use_fallback_iframe) {


		var html;
		var display_sharing_options = Dsq.jsonData.request.is_authenticated;

		if (!Dsq.jsonData.request.is_authenticated && Dsq.jsonData.forum.disqus_auth_disabled && !Dsq.jsonData.forum.allow_anon_post) {
			return '';
		}
		
		if (Dsq.jsonData.request.is_remote) {


			if (!Dsq.jsonData.request.sharing.hasOwnProperty(Dsq.jsonData.request.remote_domain)) {
				display_sharing_options = false;
			}
		}
		
		if (post_id) {
			var _meta = Dsq.jsonData.posts[post_id];
			var userData = Dsq.jsonData['users'][_meta.user_key];				
		}
		
		var pid = post_id ? '-' + post_id : '';

		var _requestUserInfo = function() {
			var html;



			var user_has_email = false;

			html = '<div class="dsq-request-user-info"> <!-- // If authenticated --> \
				<a href="' + Dsq.jsonData.settings.disqus_url + Dsq.Urls.LOGOUT + '?ctkn=' + Dsq.CSRF_TOKEN + '" class="dsq-request-user-logout">' + Dsq.Strings.LOGOUT + '</a> \
				<table> \
					<tr> \
						<td rowspan="2">'
							+ (!Dsq.jsonData.forum.disqus_auth_disabled ? '<a href="' + Dsq.jsonData.settings.disqus_url + Dsq.Urls.REQUEST_USER_PROFILE + '">' : '')
								+ '<img src="' + Dsq.Urls.REQUEST_USER_AVATAR + '" width="48" height="48" class="dsq-request-user-avatar">'
							+ (!Dsq.jsonData.forum.disqus_auth_disabled ? '</a>' : '')
						+ '</td> \
						<td class="dsq-request-user-name">'
								+ (Dsq.jsonData.request.is_remote
									 ? '<span class="dsq-badge-small dsq-badge-' + Dsq.jsonData.request.remote_domain + '">' + Dsq.jsonData.request.remote_domain + '</span>'
									 : (Dsq.jsonData.request.is_verified
											? '<span class="dsq-badge-small dsq-badge-verified">Verified</span>'
											: '<span class="dsq-badge-small dsq-badge-registered">Registered</span>'))
							+ (!Dsq.jsonData.forum.disqus_auth_disabled ? ' <a href="' + Dsq.jsonData.settings.disqus_url + Dsq.Urls.REQUEST_USER_PROFILE + '">' : '') 
								+ Dsq.jsonData.request.display_username 
							+ (!Dsq.jsonData.forum.disqus_auth_disabled ? '</a>' : '')
							+  (Dsq.jsonData.request.is_remote && user_has_email ? ' <small>(<a href="#" onclick="Dsq.Popup.remoteAccountSettings(); return false;">change settings</a>)</small>' : '')
							+  (!Dsq.jsonData.request.is_remote && !Dsq.jsonData.forum.disqus_auth_disabled ? ' <small>(<a href="' + Dsq.jsonData.settings.disqus_url + '/profile/info/" target="_blank">change name</a> or <a href="' + Dsq.jsonData.settings.disqus_url + '/profile/avatar/" target="_blank">picture</a>)</small>' : '')
						+ '</td> \
					</tr> \
					<tr> \
						<td class="dsq-request-user-stats"> \
							<span><big>' + Dsq.jsonData.request.comments_count + '</big> ' + (Dsq.jsonData.request.comments_count == 1 ? 'comment' : 'comments') + '</span> \
							<span><big>' + Dsq.jsonData.request.likes_count + '</big> ' + (Dsq.jsonData.request.likes_count == 1 ? 'like' : 'likes') + '</span> \
							<span><big>' + Dsq.jsonData.request.points + '</big> ' + (Dsq.jsonData.request.points == 1 ? 'point' : 'points') + '</span> \
						</td> \
					</tr> \
				</table> \
			</div> \
			';
			return html;
		};

		var _loginOptions = function() {
			var html;
			html = ' \
			<div class="dsq-authenticate"> \
				<p class="dsq-autheneticate-copy">'
				+ (Dsq.jsonData.forum.allow_anon_post
					? Dsq.Strings.YOU_ARE_COMMENTING_AS_A + ' <a class="dsq-help" title="Click for more information" href="#" onclick="Dsq.Popup.helpBadges(); return false">Guest</a>. ' + Dsq.Strings.OPTIONAL + ': ' + Dsq.Strings.LOGIN_BELOW + '.'
					: Dsq.Strings.REQUIRED + ': ' + Dsq.Strings.PLEASE_LOGIN_BELOW_TO_COMMENT + '.')
				+ '</p> \
				<ul class="dsq-login-buttons">'
					+ (!Dsq.jsonData.forum.disqus_auth_disabled ? '<li class="dsq-login-button"><a href="#" onclick="Dsq.Popup.login(); return false"><img src="http://media.disqus.com/images/themes/narcissus/login-disqus.gif" /></a></li>' : '')
					+ (Dsq.jsonData.context.use_fb_connect ? '<li class="dsq-login-button"><a href="#" onclick="Dsq.Facebook.login(); return false;"><img src="http://media.disqus.com/images/themes/narcissus/login-facebook.gif" /></a></li>' : '')
					+ (Dsq.jsonData.context.use_twitter_signin ? '<li class="dsq-login-button"><a href="#" onclick="Dsq.Twitter.startTwitterConnect(); return false"><img src="http://media.disqus.com/images/themes/narcissus/login-twitter.gif" /></a></li>' : '')
					+ (Dsq.jsonData.context.use_openid ? '<li class="dsq-login-button"><a href="#" onclick="Dsq.OpenID.requestURL(); return false" ><img src="http://media.disqus.com/images/themes/narcissus/login-openid.gif" /></a></li>' : '')
					+ (Dsq.jsonData.context.use_yahoo ? '<li class="dsq-login-button"><a href="#" onclick="Dsq.Yahoo.startYahooConnect(); return false"><img src="http://media.disqus.com/images/themes/narcissus/login-yahoo.gif" /></a></li>' : '')
				+ '</ul> \
			</div> \
			';
			return html;
		};

		if (!Dsq.jsonData.context.show_reply) {


			if (!Dsq.jsonData.request.is_authenticated) {



				return '<div id="dsq-form-area" style="display:none"><div id="dsq-textarea-wrapper"></div></div>' + _loginOptions();
			} else {
				return '';
			}
		}

		html = ' \
		<div id="' + (post_id 
			? 'dsq-reply-post-' + post_id
			: 'dsq-new-post')
		 	+ '" class="dsq-post-area"> \
			<div class="dsq-dc-logo"> \
				<a href="http://disqus.com/comments" target="_blank"><img src="http://media.disqus.com/images/themes/narcissus/disqus-logo.png"></a> \
			</div>'
			+ (post_id 
				? '<h3>' + Dsq.Strings.REPLYING_TO + ' ' + userData.display_name + '</h3>'
				: '<h3>' + Dsq.Strings.ADD_NEW_COMMENT + '</h3>')
			+ (Dsq.jsonData.request.is_authenticated 
				? _requestUserInfo()
				: _loginOptions() )
			+ '<div id="dsq-form-area' + pid + '">'
			+ '<div class="dsq-textarea"> \
				<div class="dsq-textarea-wrapper" id="dsq-textarea-wrapper' + pid + '"></div> \
			</div>'
			+ (!Dsq.jsonData.request.is_authenticated
			? ' \
			<div class="dsq-post-fields"> \
				<table> \
					<tr> \
						<td class="dsq-post-fields-left"><div class="dsq-input-wrapper"><input id="dsq-field-name' + pid + '" type="text" value="' + (disqus_def_name ? disqus_def_name : (Dsq.jsonData.session.name ? Dsq.jsonData.session.name : Dsq.Strings.NAME + '" class="dsq-placeholder')) + '" onfocus="Dsq.Templates.handlePlaceholder(event, this, \'name\')" onblur="Dsq.Templates.handlePlaceholder(event, this, \'name\')" /></div></td> \
						<td class="dsq-post-fields-right"><div class="dsq-input-wrapper"><input id="dsq-field-website' + pid + '" type="text" value="' + (Dsq.jsonData.session.url ? Dsq.jsonData.session.url : Dsq.Strings.WEBSITE + ' (' + Dsq.Strings.OPTIONAL.toLowerCase() + ')" class="dsq-placeholder') + '" onfocus="Dsq.Templates.handlePlaceholder(event, this, \'website\')" onblur="Dsq.Templates.handlePlaceholder(event, this, \'website\')" /></div></td> \
					</tr> \
					<tr> \
						<td class="dsq-post-fields-left"><div class="dsq-input-wrapper"><input id="dsq-field-email' + pid + '" type="text" value="' + (disqus_def_email ? disqus_def_email : (Dsq.jsonData.session.email ? Dsq.jsonData.session.email : Dsq.Strings.EMAIL + '" class="dsq-placeholder')) + '" onfocus="Dsq.Templates.handlePlaceholder(event, this, \'email\')" onblur="Dsq.Templates.handlePlaceholder(event, this, \'email\')" /></div></td> \
						<td class="dsq-post-fields-right"> \
							<div class="dsq-subscribe"> \
								<a href="#" onclick="Dsq.Templates.chooseSubscribe(' + post_id + '); return false" class="dsq-subscribe-menu"><span id="dsq-subscribe-select' + pid + '">' + (Dsq.jsonData.request.subscribe_on_post ? Dsq.Strings.SUBSCRIBE_TO_ALL_COMMENTS_BY_EMAIL : Dsq.Strings.DO_NOT_SUBSCRIBE_TO_COMMENTS) + '</span> <small>&#9660;</small></a> \
								<ul class="dsq-panel" id="dsq-subscribe-menu' + pid + '"> \
									<li><a href="#" onclick="Dsq.Templates.setSubscribe(2, this, ' + post_id + '); return false">' + Dsq.Strings.SUBSCRIBE_TO_ALL_COMMENTS_BY_EMAIL + '</a></li> \
									<li><a href="#" onclick="Dsq.Templates.setSubscribe(0, this, ' + post_id + '); return false">' + Dsq.Strings.DO_NOT_SUBSCRIBE_TO_COMMENTS + '</a></li> \
								</ul> \
								<input id="dsq-subscribe-on-post' + pid + '" type="hidden" value="' + Dsq.jsonData.request.subscribe_on_post + '" /> \
							</div> \
						</td> \
					</tr> \
				</table> \
			</div>'
			: '')
			+ '<div class="dsq-post-footer"> \
				<div class="dsq-sharing-options" ' + (!display_sharing_options ? 'style="display:none;"' : '') + '> \
					<button type="button" class="dsq-button-small" onfocus="document.getElementById(\'dsq-post-button' + pid + '\').focus();"><span>' + Dsq.Strings.SHARING_OPTIONS + ' <small>&#9660;</small></span></button> \
					<div class="dsq-panel"> '
						+ (Dsq.jsonData.request.sharing.twitter !== undefined
								&& Dsq.jsonData.request.sharing.twitter.enabled === true
							? '<div><input type="checkbox" id="dsq-sharing-twitter' + pid + '"'
								  + (Dsq.jsonData.request.sharing.twitter.auto === true ? 'checked=true' : '') + '/> \
									<label for="dsq-sharing-twitter' + pid + '">' + Dsq.Strings.SHARE_ON + ' Twitter</label> \
								 </div>'
							: '')
						+ (Dsq.jsonData.request.sharing.facebook
								&& (Dsq.jsonData.request.sharing.facebook.enabled === true ||
										(Dsq.jsonData.request.is_remote && Dsq.jsonData.request.remote_domain == 'facebook'))
							? '<div><input type="checkbox" id="dsq-sharing-facebook' + pid + '"'
									+ (Dsq.jsonData.request.sharing.facebook.auto === true ? 'checked=true' : '') + '/> \
									<label for="dsq-sharing-facebook' + pid + '">' + Dsq.Strings.SHARE_ON + ' Facebook</label> \
								 </div>'
							: '')
						+ (Dsq.jsonData.request.sharing.yahoo !== undefined
								&& Dsq.jsonData.request.sharing.yahoo.enabled === true
							? '<div><input type="checkbox" id="dsq-sharing-yahoo' + pid + '"'
									+ (Dsq.jsonData.request.sharing.yahoo.auto === true ? 'checked=true' : '') + '/> \
									<label for="dsq-sharing-yahoo' + pid + '">' + Dsq.Strings.SHARE_ON + ' Yahoo!</label> \
								</div>'
							: '')
						+ (Dsq.jsonData.request.sharing.tumblr !== undefined
								&& Dsq.jsonData.request.sharing.tumblr.enabled === true
							? '<div><input type="checkbox" id="dsq-sharing-tumblr' + pid + '"'
									+ (Dsq.jsonData.request.sharing.tumblr.auto === true ? 'checked=true' : '') + '/> \
									<label for="dsq-sharing-tumblr' + pid + '">' + Dsq.Strings.SHARE_ON + ' Tumblr</label> \
								 </div>'
							: '')
						+ (Dsq.jsonData.request.sharing.wordpress !== undefined
								&& Dsq.jsonData.request.sharing.wordpress.enabled === true
							? '<div><input type="checkbox" id="dsq-sharing-wordpress' + pid + '"'
									+ (Dsq.jsonData.request.sharing.wordpress.auto === true ? 'checked=true' : '') + '/> \
									<label for="dsq-sharing-wordpress' + pid + '">' + Dsq.Strings.SHARE_ON + ' Wordpress</label> \
								 </div>'
							: '')
						+ (Dsq.jsonData.request.sharing.movabletype !== undefined
							  && Dsq.jsonData.request.sharing.movabletype.enabled === true
							? '<div><input type="checkbox" id="dsq-sharing-movabletype' + pid + '"'
									+ (Dsq.jsonData.request.sharing.movabletype.auto === true ? 'checked=true' : '') + '/> \
									<label for="dsq-sharing-movabletype' + pid + '">' + Dsq.Strings.SHARE_ON + ' Movable Type</label> \
							   </div>'
							: '')
						+ (Dsq.jsonData.request.sharing.typepad !== undefined
							  && Dsq.jsonData.request.sharing.typepad.enabled === true
							? '<div><input type="checkbox" id="dsq-sharing-typepad' + pid + '"'
									+ (Dsq.jsonData.request.sharing.typepad.auto === true ? 'checked=true' : '') + '/> \
								  <label for="dsq-sharing-typepad' + pid + '">' + Dsq.Strings.SHARE_ON + ' TypePad</label> \
							   </div>'
							: '')
						+ '<div><a href="' + Dsq.jsonData.settings.disqus_url + '/profile/connections/" target="_blank" class="dsq-configure-options">' + Dsq.Strings.CONFIGURE_OPTIONS + '</a></div>'
					+ '</div> \
				</div>'
				+ '<button type="button" class="dsq-button" id="dsq-post-button' + pid + '" onclick="Dsq.Templates.postComment(' + post_id + ', this, false)"><span>' + Dsq.Strings.POST_AS + ' '
				+ (Dsq.jsonData.request.display_username
					? Dsq.jsonData.request.display_username
					: Dsq.Strings.GUEST)
				+ '</span></button>'
				+ (post_id
					? '<button type="button" class="dsq-button" id="dsq-cancel-button' + pid + '" onclick="Dsq.Post.toggleReply(' + post_id +', this)"><span>' + Dsq.Strings.CANCEL + '</span></button>'
					: '')
			+ '</div>'
			+ '</div>' // end dsq-form-area
		+ '</div> \
		';
		
		return html;
	};




	this.appendPost = function(post_id) {
		var html = '<div id="dsq-append-post-' + post_id + '"></div>';
		return html;
	};

	this.postPrependHeader = function(post_id) {
		var html;
		var _meta = Dsq.jsonData.posts[post_id];
		var userData = Dsq.jsonData['users'][_meta.user_key];
		
		html = ' \
		<table> \
			<tr> \
				<td id="dsq-header-avatar-' + post_id + '" class="dsq-header-avatar" onmouseover="Dsq.Post.dropProfile(' + post_id + ')"> \
					<a id="dsq-avatar-' + post_id + '" class="dsq-avatar" href="' + userData.url + '" onclick="Dsq.Popup.popProfile(' + post_id + '); return false;">'
					+ (Dsq.jsonData.forum.show_avatar
					? '<img src="' + Dsq.jsonData.users[_meta.user_key].avatar + '" alt="" />'
					: '')
				+ '</a> \
				</td> \
				<td class="dsq-comment-header-meta"> \
		';

		
		return html;
	};
	
	this.postAppendHeader = function(post_id) {
		var _meta = Dsq.jsonData.posts[post_id];
		var html;
		var parent_display_name = '';
		
		if(_meta.parent_post_id) {

			var _parent_meta = Dsq.jsonData.posts[_meta.parent_post_id];

			if (_parent_meta) {
				var parentUserData = Dsq.jsonData['users'][_parent_meta.user_key];
				parent_display_name = parentUserData.display_name;
			}
		}

		html = ' \
		<img src="http://media.disqus.com/images/themes/narcissus/moderator.png" class="dsq-moderator-star" title="Moderator" /> \
		<span class="dsq-comment-header-time"><a href="#comment-' + post_id + '" onclick="Dsq.Popup.permalink(' + post_id + ')" title="Permalink">' + (_meta.is_realtime ? Dsq.Strings.JUST_NOW : _meta.date) + '</a></span> '
		+ (_meta.parent_post_id && parent_display_name
			? '<a href="#comment-' + _meta.parent_post_id + '" title="Jump to comment">in reply to ' + parent_display_name + '</a>'
			: '')
		+ '</td> \
		<td id="dsq-like-pts-' + post_id + '" class="dsq-comment-header-likes">'
		+ (_meta.points
			? _meta.points + Dsq.Utils.pluralize(_meta.points, ' person', ' people') + ' liked this.'
			: '')
		+ '</td> \
		</tr> \
		</table> \
		';
		return html;
	};

	this.preBody = function(post_id) {
		var html = '';
		return html;
	};

	this.postFooter = function(post_id) {
		var html;
		var _meta = Dsq.jsonData.posts[post_id];
		if(_meta.killed || !_meta.approved) { return ''; }
		
		html = ' \
		<div class="dsq-comment-footer" id="dsq-comment-footer-' + post_id + '"> \
			<div class="dsq-comment-footer-left">'
				+ (Dsq.jsonData.request.is_moderator || Dsq.jsonData.request.is_global_moderator
					? '<a href="#" onclick="Dsq.Templates.moderateOptions(' + post_id+ '); return false">' + Dsq.Strings.MODERATE + '</a>'
					: '')
				+ '<a href="#" id="dsq-post-report-' + post_id + '" class="dsq-post-report" onclick="Dsq.Post.report(' + post_id + ', false); return false;">' + Dsq.Strings.FLAG + '</a> \
			</div> \
			<div class="dsq-comment-footer-right">'
				+ (_meta.votable 
					? '<span id="dsq-like-' + post_id + '" class="dsq-like">'
					+ (!_meta.up_voted
						? '<button type="button" class="dsq-button-small" onclick="Dsq.Post.rate(this, ' + post_id + ', 1)" >Like</button>'
						: 'You liked this.&nbsp;&nbsp;')
					+ '</span>'
					: '')
				+ (_meta.can_reply && !_meta.has_replies && _meta.from_request_user
					? '<button type="button" class="dsq-button-small dsq-post-edit" onclick="Dsq.Post.edit(this, ' + post_id + ')" >' + Dsq.Strings.EDIT + '</button>'
					: '')
				+ (_meta.can_reply
					? '<span class="dsq-comment-footer-reply" id="dsq-comment-footer-reply-' + post_id + '" onclick="Dsq.Post.toggleReply(' + post_id +', this)"> \
						<button type="button" class="dsq-button-small">' + Dsq.Strings.REPLY + '</button> \
						<button type="button" class="dsq-comment-footer-reply-tab">' + Dsq.Strings.REPLY + '</button><span></span> \
					</span>'
					: '')
			+ '</div> \
		</div> \
		';
		
		return html;
	};



	
	this.showRetweets = function(id, limit, element_id /* Optional */) {
		var source, html = '';

		for (var i = 0, reaction; reaction = Dsq.jsonData.reactions[i]; i++) {
			if (reaction.id === id) {
				source = reaction.retweets;
			}
		}

		if (source) {
			if (limit === 0) {
				limit = source.length;
			}

			for (var j = 0; j < limit; j++) {
				var rt = source[j];
				html += '<a href="' + rt.url + '">' + rt.author_name + '</a>'	+ ((j === (limit - 1)) ? '.' : ', ');
			}
		}

		if (element_id === undefined) {
			return html;
		}

		var element = document.getElementById(element_id);
		element.innerHTML = html;
		return element;
	};

	this.showMoreReactions = function(reactions, has_more, start, limit) {
		var link = document.getElementById('dsq-show-more-reactions');
		var container = link.parentNode;
		container.removeChild(link);

		for (var i = 0, reaction; reaction = reactions[i]; i++) {
			var el = Dsq.Templates.generateReactionHTML(reaction);
			if (el) {
				container.innerHTML += el;
			}
		}

		if (has_more) {
			var d = Dsq.jsonData.settings.disqus_url;
			var f = Dsq.jsonData.forum.url;
			var t = Dsq.jsonData.thread.id;
			var s = start;
			var l = limit;

			var handler = 'Dsq.Utils.execScript(\'' + d + '/forums/' + f + '/more_reactions.js?t=' + t + '&s=' + s + '&l=' + l + '\', true); return false;';
			container.innerHTML += '<li id="dsq-show-more-reactions" class="dsq-show-more-reactions"><button type="button" class="dsq-button-small" onclick="' + handler + '">Show more reactions</button></li>';
		}
	};

	this.generateReactionHTML = function(reaction) {
		if (reaction.body === null || reaction.body == '') {
			return;
		}

		if (reaction.author_name === '') {
			reaction.author_name = '&nbsp;';
		}

		if (reaction.url === '') {
			reaction.url = reaction.get_service_url;
		}

		var item = '<li class="dsq-comment dsq-reaction" id="dsq-reaction-' + reaction.id + '">'
			+ '<div class="dsq-comment-header"> \
			<table> \
			<tr> \
			<td class="dsq-header-avatar"> \
			';

		if (reaction.author_url && reaction.author_url !== '') {
			item += '<a target="_blank" href="' + reaction.author_url +'" class="dsq-avatar">';
		}

		if (reaction.avatar_url && reaction.avatar_url !== '') {
			item += '<img src="' + reaction.avatar_url + '"/>';
		} else {

			item += '<img src="' + Dsq.jsonData.media_url + '/images/noavatar92.png"/>';
		}

		var service_icon = (reaction.get_service_name == 'trackback' || reaction.get_service_name == 'pingback' ? 'rss' : reaction.get_service_name.replace(' ', ''));
		item += (reaction.author_url && reaction.author_url !== ''
				? '</a>'
				: '')
			+ '</td>'
			+ '<td><cite class="dsq-comment-cite">' + reaction.author_name + '</cite> <span class="dsq-comment-header-time">' + reaction.date_created + '</span></td>'
			+ '<td class="dsq-comment-header-likes"></td>'
			+ '</tr></table></div>' // end dsq-comment-header
			+ '<div class="dsq-reaction-header" \
				<table> \
					<tr> \
						<td class="dsq-reaction-header-left">'
							+ '<img class="dsq-service-icon" src="' + Dsq.jsonData.media_url + '/images/reactions/services/' + service_icon + '.png" />'
							+ ' From <a class="dsq-service-name" target="_blank" href="' + reaction.url + '">' + reaction.get_service_name + '</a> '
							+ 'via <a href="' + reaction.source_url + '">' + (reaction.source == 'backtype' ? 'BackType' : 'UberVU') + '</a>'
						+ '</td>'
						+ '<td class="dsq-reaction-header-right">';

			if(reaction.retweets) {
				var num_retweets = reaction.retweets.length;
				if (num_retweets > 0) {
					if (num_retweets == 1) {
						item += 'One more retweet from <a href="' + reaction.retweets[0].url + '">'  + reaction.retweets[0].author_name + '</a>';
					} else {
						item += (num_retweets + ' more retweets from ');
						item += '<span id="dsq-reaction-retweets-' + reaction.id + '">';
						var n_tweets = (num_retweets > 3) ? 3 : num_retweets;
						item += Dsq.Templates.showRetweets(reaction.id, n_tweets);
						if (n_tweets != num_retweets) {
							item += '</span> <a onclick="Dsq.Templates.showRetweets(' + reaction.id + ', 0, \'dsq-reaction-retweets-' + reaction.id + '\');'
								+ 'this.parentNode.removeChild(this); return false;" href="#">Show all</a>';
						}
					}
				}
			}	
			item += '</td></tr> \
			</table> \
			</div>' // end dsq-reaction-header
			+ '<div class="dsq-comment-body"> \
				<div class="dsq-comment-message">' + reaction.body + '</div>'
			+ '</div> \
			<div class="dsq-comment-footer"> \
				<div class="dsq-comment-footer-left"> \
				</div>'
				+ (Dsq.jsonData.request.is_moderator || Dsq.jsonData.request.is_global_moderator 
					? ' \
					<div class="dsq-comment-footer-right"> \
						<button type="button" class="dsq-button-small dsq-hide-reaction" onclick="Dsq.Reaction.hide(' + reaction.id + ')">Hide</button> \
					</div>'
					: '')
			+ '</div>'
		item += '</li>'; /* Reaction HTML ends */
		return item;
	};

	this.reactions = function() {
		var html, reaction;

		if (Dsq.jsonData.reactions === undefined || Dsq.jsonData.reactions.length === 0) {
			return '';
		}

		html = '';
		for (var i = 0; reaction = Dsq.jsonData.reactions[i]; i++) {
			var item = Dsq.Templates.generateReactionHTML(reaction);
			if (item) {
				html += item;
			}
		}

		if (Dsq.jsonData.has_more_reactions) {
			var d = Dsq.jsonData.settings.disqus_url;
			var f = Dsq.jsonData.forum.url;
			var t = Dsq.jsonData.thread.id;
			var s = Dsq.jsonData.reactions_start;
			var l = Dsq.jsonData.reactions_limit;

			var handler = 'Dsq.Utils.execScript(\'' + d + '/forums/' + f + '/more_reactions.js?t=' + t + '&s=' + s + '&l=' + l + '\', true); return false;';
			html += '<li id="dsq-show-more-reactions" class="dsq-show-more-reactions"><button type="button" class="dsq-button-small" onclick="' + handler + '">Show more reactions</button></li>';
		}

		return '<h3 id="dsq-reactions-title" class="dsq-h3-reactions">Reactions</h3><ul id="dsq-reactions" class="dsq-reactions">' + html + '</ul>';
	};
	
	this._popupGeneric = function(content) {
		return ' \
		<div class="dsq-popup-container"> \
			<table> \
				<tbody> \
					<tr> \
						<td class="dsq-popup-tl"></td><td class="dsq-popup-b"></td><td class="dsq-popup-tr"></td> \
					</tr> \
					<tr> \
						<td class="dsq-popup-b"></td> \
						<td class="dsq-popup-body"> \
							<div class="dsq-popup-content"> \
								<div class="dsq-popup-title"> \
									<button type="button" class="dsq-button-small" style="float:right" onclick="Dsq.Popup._closePopup(null, true)">Close</button>'
									+ content['header'] 
								+ '</div>'
								+ content['body']
							+ '</div> \
							<div class="powered-by"><a href="http://disqus.com/comments/">Powered by <img src="http://media.disqus.com/images/embed/disqus-logo.png" alt="Disqus Comments" style="margin-bottom:-5px" /></a></div> \
						</td> \
						<td class="dsq-popup-b"></td> \
					</tr> \
					<tr> \
						<td class="dsq-popup-bl"></td><td class="dsq-popup-b"></td><td class="dsq-popup-br"></td> \
					</tr> \
				</tbody> \
			</table> \
		</div> \
		';
	};



	
	this.chooseSubscribe = function(post_id) {

		var pid = post_id ? '-' + post_id : '';
		var menu = Dsq.$('dsq-subscribe-menu' + pid);
		
		menu.style.display = menu.style.display == 'block' ? 'none' : 'block';
		
	};
	
	this.setSubscribe = function(value, el, post_id) {

		var pid = post_id ? '-' + post_id : '';
		var input = Dsq.$('dsq-subscribe-on-post' + pid);
		var select = Dsq.$('dsq-subscribe-select' + pid);
		var menu = Dsq.$('dsq-subscribe-menu' + pid);
		
		select.innerHTML = el.innerHTML;
		input.value = value;
		this.chooseSubscribe(post_id);
	};
	
	this.getFormFields = function(post_id) {

		var fields = {};
		var pid = post_id ? '-' + post_id : '';
		var name = Dsq.$('dsq-field-name' + pid);
		var email = Dsq.$('dsq-field-email' + pid);
		var website = Dsq.$('dsq-field-website' + pid);
		var username = Dsq.$('dsq-field-username' + pid);
		var password = Dsq.$('dsq-field-password' + pid);

		fields = {
			'name': name,
			'email': email,
			'website': website,
			'username': username,
			'password': password
		}
		
		return fields;
	}
	
	this.validateFields = function(post_id) {
		
		if(Dsq.jsonData.request.is_authenticated) { return true; }
		
		var fields = Dsq.Templates.getFormFields(post_id);
		
		var nameField = fields.name;
		var websiteField = fields.website;
		var emailField = fields.email;
		
		websiteField.value = (websiteField.value == Dsq.Templates.placeholder['website']) ? '' : websiteField.value;
		
		var v = [{

			validator: Dsq.Validators.name,
			value: nameField.value
		}, {

			validator: Dsq.Validators.email,
			value: emailField.value
		}, {

			validator: Dsq.Validators.url,
			value: websiteField.value
		}];
		
		return Dsq.Validators.validate(v, function(e) { Dsq.Popup.popModal(e, 'Oops...') } );
	};
	
	this.checkExistingUser = function(post_id) {
		var fields = Dsq.Templates.getFormFields(post_id);		
		Dsq.Popup.loading(post_id);
		
		if (post_id) {
			Dsq.frames['reply_' + post_id].getUserByEmail(fields.email.value);
		} else {
			Dsq.frames['reply_0'].getUserByEmail(fields.email.value);
		}
	};

	this.validateAuth = function(el_clicked, post_id, auth_choice) {
		var fields = Dsq.Templates.getFormFields(post_id);
		var email = fields.email ? fields.email.value : '';
		var username = fields.username ? fields.username.value : '';
		var password = fields.password ? fields.password.value : '';
		
		Dsq.Templates.setLoadingButton(el_clicked, post_id);
		
		if (post_id) {
			Dsq.frames['reply_' + post_id].validateAuth(auth_choice, email, username, password);
		} else {
			Dsq.frames['reply_0'].validateAuth(auth_choice, email, username, password);
		}
	};

	this.lightboxUpdateEmail = function(post_id, new_email) {
		var fields = Dsq.Templates.getFormFields(post_id);
		fields.email.value = new_email;
	};

	this.lightboxAuthenticate = function(post_id, auth_choice, auth_data) {
		var title, body;
		var pid = post_id ? '-' + post_id : '';

		if(typeof(auth_data) == 'undefined') {
			var auth_data = Dsq.Templates.getFormFields(post_id);
		}

		d = auth_data;

		switch(auth_choice) {
			case 'register':
				var suggestedUsername = d.name.value.replace(/[^a-zA-Z0-9-]/g,'').toLowerCase();
			
				title = Dsq.jsonData.forum.allow_anon_post ? 'Optional:' : 'Required:';
				title += ' Register a <img src="http://media.disqus.com/images/embed/disqus-profile.png" alt=Disqus Profile" />';

				body = ' \
				<ul class="dsq-lightbox-register-reasons"> \
				<li>Verify your comments</li> \
				<li>Edit and delete comments</li> \
				<li>Manage comments and replies</li> \
				</ul> \
				';

				body += ' \
				<div class="dsq-lightbox-auth-fields"> \
					<table> \
						<tr> \
							<td>Email</td> \
							<td><input type="text" value="' + d.email.value + '" onchange="Dsq.Templates.lightboxUpdateEmail(' + post_id + ', this.value)" /><div id="dsq-email-errors' + pid + '"></div></td> \
						</tr> \
						<tr> \
							<td>Username</td> \
							<td><input id="dsq-field-username' + pid + '" type="text" value="' + suggestedUsername + '"/><div id="dsq-username-errors' + pid + '"></div></td> \
						</tr> \
						<tr> \
							<td>Password</td> \
							<td><input id="dsq-field-password' + pid + '" type="password" /><div id="dsq-password-errors' + pid + '"></div></td> \
						</tr> \
					</table> \
					<div class="dsq-lightbox-switch-auth"><a href="#" onclick="Dsq.Templates.lightboxAuthenticate(' + post_id + ',\'login\'); return false">Login instead</a></div> \
				</div> \
				<div id="dsq-lightbox-errors' + pid + '" class="dsq-lightbox-errors"></div> \
				<div class="dsq-lightbox-submit"> \
					<div class="dsq-lightbox-auth-post"><button type="button" class="dsq-button" onclick="Dsq.Templates.validateAuth(this, ' + post_id + ',\'' + auth_choice + '\')">Register and Post comment</button></div>'
					+ (Dsq.jsonData.forum.allow_anon_post
						? '<div class="dsq-lightbox-auth-skip"><button type="button" class="dsq-button-small" onclick="Dsq.Templates.postComment(' + post_id + ', this, true)">Just post as a Guest</button></div>'
						: '')
				+ '</div> \
				';
				break;
			case 'login':
				title = Dsq.jsonData.forum.allow_anon_post ? 'Optional:' : 'Required:';
				title += ' Login to your <img src="http://media.disqus.com/images/embed/disqus-profile.png" alt=Disqus Profile" />';
				body = '';
				
				if(d.avatar_url) {
					body += '<div class="dsq-lightbox-recognized"><table><tr>';
					body += '<td><img src="' + d.avatar_url + '" alt="" /></td>';
					body += '<td><span class="dsq-badge ' + (d.verified ? 'dsq-badge-verified' : 'dsq-badge-registered') + '">' + (d.verified ? 'Verified' : 'Registered') + '</span></td>';
					body += '<td>Hey <strong>' + d.display_name + '</strong>, is that you? Login below to claim this comment.';
					body += '</tr></table></div>';
				}

				body += ' \
				<div class="dsq-lightbox-auth-fields"> \
					<table> \
						<tr> \
							<td>Username or Email</td> \
							<td><input id="dsq-field-username' + pid + '" type="text" value="' + (d.avatar_url ? d.username : '') + '" /></td> \
						</tr> \
						<tr> \
							<td>Password <a href="http://disqus.com/forgot" target="_blank">(cannot log in?)</a></td> \
							<td><input id="dsq-field-password' + pid + '" type="password" /></td> \
						</tr> \
					</table> \
					<div class="dsq-lightbox-switch-auth"><a href="#" onclick="Dsq.Templates.lightboxAuthenticate(' + post_id + ',\'register\'); return false">Register instead</a></div> \
				</div> \
				<div id="dsq-lightbox-errors' + pid + '" class="dsq-lightbox-errors"></div> \
				<div class="dsq-lightbox-submit"> \
					<div class="dsq-lightbox-auth-post"><button type="button" class="dsq-button" onclick="Dsq.Templates.validateAuth(this, ' + post_id + ',\'' + auth_choice + '\')">Login and Post comment</button></div>'
					+ (Dsq.jsonData.forum.allow_anon_post
						? '<div class="dsq-lightbox-auth-skip"><button type="button" class="dsq-button-small" onclick="Dsq.Templates.postComment(' + post_id + ', this, true)">Just post as a Guest</button></div>'
						: '')
				+ '</div> \
				';
				break;
			default:
				break;
		}
		Dsq.Popup.lightbox(body, title, post_id);
		Dsq.$('dsq-field-username' + pid).focus();
	};
	
	this.buttonsToRestore = [];
	this.setLoadingButton = function(btn, post_id) {
		var pid = post_id ? '-' + post_id : '';
		if (btn) {

			var loadingBtn = document.createElement('button');
			loadingBtn.id = btn.id + '-loading';
			loadingBtn.innerHTML = '<img src="http://media.disqus.com/images/loading-lite.gif" alt="" /> ' + Dsq.Strings.JUST_A_MOMENT;
			loadingBtn.className = btn.className + ' dsq-post-loading';
			btn.parentNode.appendChild(loadingBtn);
			btn.style.display = 'none';
			var cancelBtn = Dsq.$('dsq-cancel-button' + pid);
			if(cancelBtn) { cancelBtn.style.display = 'none'; this.buttonsToRestore.push(cancelBtn); }
			this.buttonsToRestore.push(btn);
		} else {

			var buttons = this.buttonsToRestore;
			for(var i = 0; i < buttons.length; i++) {
				buttons[i].style.display = 'inline';
				Dsq.Utils.deleteNode(Dsq.$(buttons[i].id + '-loading'));
			}
		}
		
	};

	this.postComment = function(post_id, el_clicked, force, auth_choice) {
		var append_id = post_id ? '-' + post_id : '';
		var fields = Dsq.Templates.getFormFields(post_id);

		if (Dsq.Templates.validateFields(post_id)) {

			if (!Dsq.jsonData.request.is_authenticated && !force &&
				((!Dsq.Utils.readCookie('skipped_auth') && !disqus_skip_auth && !Dsq.jsonData.forum.disqus_auth_disabled) || !Dsq.jsonData.forum.allow_anon_post)) {
				Dsq.Templates.checkExistingUser(post_id);
				return false;
			}
			var params = [];
			if (!Dsq.jsonData.request.is_authenticated) {
				params.push(fields.name.value,
					fields.email.value,
					fields.website.value);

				if (auth_choice == 'login' || auth_choice == 'register') {
					params.push({
						auth_choice: auth_choice,
						username: fields.username.value,
						password: fields.password.value,
						email: fields.email.value
					});
				} else {
					params.push(null);
				}

				params.push(null /* sharing options */, Dsq.$('dsq-subscribe-on-post' + append_id).value);
			} else {
				var service_checked = function(name) {
					var el = Dsq.$('dsq-sharing-' + name + append_id);
					return (el !== null && el.checked === true) ? '1' : '0';
				};
				params.push(null, null, null, null, {
					tw: service_checked('twitter'),
					fb: service_checked('facebook'),
					tr: service_checked('tumblr'),
					wp: service_checked('wordpress'),
					mt: service_checked('movabletype'),
					tp: service_checked('typepad'),
					yh: service_checked('yahoo')
				});
			}

			var frame = Dsq.frames['reply_' + (post_id ? post_id : 0)];
			frame.post.apply(frame, params);

			if (el_clicked) {
				Dsq.Templates.setLoadingButton(el_clicked, post_id);
			}
			
			if (force) {
				Dsq.Utils.createCookie('skipped_auth', true);	
			}
			
		} else {
			return false;
		}
	};

	this.editComment = function(el_clicked, post_id) {
		var edited_message = Dsq.$('dsq-edit-textarea-' + post_id).value;

		Dsq.Templates.setLoadingButton(el_clicked, post_id);
		Dsq.frames['edit_' + post_id].edit(post_id, edited_message);
	};

	this.toggleEdit = function(post_id) {
		var body = Dsq.$('dsq-comment-body-' + post_id);
		var message = Dsq.$('dsq-comment-message-' + post_id);

		if (!Dsq.Post.stateEditToggled[post_id]) {


			message.style.display = 'none';
			if (Dsq.$('dsq-edit-' + post_id)) {
				Dsq.$('dsq-edit-' + post_id).style.display = 'block';
			} else {

				var edit_area = document.createElement('div');
				edit_area.id = 'dsq-edit-' + post_id;
				edit_area.className = 'dsq-edit dsq-textarea';
				edit_area.innerHTML = ' \
				<div class="dsq-textarea-wrapper"> \
					<textarea class="dsq-edit-textarea" id="dsq-edit-textarea-' + post_id + '">' + message.innerHTML + '</textarea> \
				</div> \
				<div class="dsq-save-edit"> \
					<button type="button" onclick="Dsq.Templates.editComment(this, ' + post_id + ')" class="dsq-button-small">Save Edit</button> \
				</div> \
				<div id="dsq-edit-iframe-' + post_id + '" style="display: none"></div> \
				';

				body.appendChild(edit_area);

				if (!Dsq.frames['edit_' + post_id]) {
					var _meta = Dsq.jsonData.posts[post_id];
					Dsq.frames['edit_' + post_id] = new Dsq.ReplyFrame(Dsq.$('dsq-edit-iframe-' + post_id), post_id);
					Dsq.frames['edit_' + post_id].init();
					Dsq.frames['edit_' + post_id].setState(post_id, _meta.depth);
				}
			}
		} else {

			message.style.display = 'block';
			Dsq.$('dsq-edit-' + post_id).style.display = 'none';
		}
		
		Dsq.Post.stateEditToggled[post_id] = !Dsq.Post.stateEditToggled[post_id];
	};
	
	this.edit = function(el, post_id) {

		Dsq.Templates.toggleEdit(post_id);
	};

	this.toggleReply = function(post_id, button) {
		
		if(!this.stateReplyToggled[post_id]) {

			if (Dsq.$('dsq-reply-post-' + post_id)) {
				Dsq.$('dsq-append-post-' + post_id).style.display = 'block';
			} else {
				Dsq.$('dsq-append-post-' + post_id).innerHTML = Dsq.Templates.postBox(post_id);
				var container = Dsq.$('dsq-textarea-wrapper-' + post_id);
				if (!Dsq.frames['reply_' + post_id] && container) {
					var _meta = Dsq.jsonData.posts[post_id];
					Dsq.frames['reply_' + post_id] = new Dsq.ReplyFrame(container, post_id);
					Dsq.frames['reply_' + post_id].init(function() {

						Dsq.$('dsq-append-post-' + post_id).innerHTML = Dsq.Templates.postBox(post_id, true);
						Dsq.$('dsq-form-area-' + post_id).innerHTML = '';

						var theme = (typeof disqus_frame_theme == 'undefined') ? 'default' : disqus_frame_theme;
						Dsq.Iframes.showReplyIframeInContainer(Dsq.$('dsq-form-area-' + post_id), post_id, {theme: theme});

					});
					Dsq.frames['reply_' + post_id].setState(post_id, _meta.depth);
				}
			}
			Dsq.$('dsq-append-post-' + post_id).className = 'dsq-append-post';
			Dsq.$('dsq-comment-footer-reply-' + post_id).className = 'dsq-comment-footer-reply-active';
			
		} else {

			Dsq.$('dsq-append-post-' + post_id).style.display = 'none';
			Dsq.$('dsq-append-post-' + post_id).className = '';
			Dsq.$('dsq-comment-footer-reply-' + post_id).className = 'dsq-comment-footer-reply';
		}
		
		this.stateReplyToggled[post_id] = !this.stateReplyToggled[post_id];

		if(Dsq.Utils.ie && this.stateReplyToggled[post_id]) {

		}

		Dsq.Events.fire(Dsq.Events.REPLY_IFRAME_TOGGLED, {
			postId: post_id,
			opened: this.stateReplyToggled[post_id]
		});
	};
	
	this.moderateOptions = function(post_id) {
		var _meta = Dsq.jsonData.posts[post_id];
		var userData = Dsq.jsonData['users'][_meta.user_key];
		
		if(!Dsq.jsonData.request.is_moderator && !Dsq.jsonData.request.is_global_moderator) { return false; }

		var html;
		
		html = ' \
		<div class="dsq-moderate-options"> \
		<table>'
		+ (_meta.email ? '<tr><td>Email</td><td>' + _meta.email + '</td></tr>' : '')
		+ (_meta.ip ? '<tr><td>IP address</td><td>' + _meta.ip + '</td></tr>' : '')
		+ '<tr> \
			<td>Actions</td> \
			<td><ul>'
			+ (Dsq.jsonData.request.moderator_can_edit
				? '<li><a href="#" onclick="Dsq.Post.edit(this, ' + post_id + '); Dsq.Popup._closePopup(null, true); return false;">Edit Comment</a></li>'
				: '')
			+ '<li><a href="#" onclick="Dsq.Post.removePost(' + post_id + ', 1); Dsq.Popup._closePopup(null, true); return false;">Delete Comment</a></li> \
			<li><a href="#" onclick="Dsq.Post.reportSpam(' + post_id + '); Dsq.Popup._closePopup(null, true); return false;">Mark Spam</a></li> \
			<li><a href="#" onclick="Dsq.Popup.blacklist(' + post_id + '); return false">Block User</a></li> \
			</ul></td> \
			</table> \
		</div> \
		';
		
		html += '<p>Go to the full <a href="http://disqus.com/comments/moderate/" target="_blank">moderate panel</a> for more options.</p>';
		
		return Dsq.Popup.popModal(html, 'Moderate Options', post_id);
	};
	
	this.placeholder = {
		'class': 'dsq-placeholder',
		'name': Dsq.Strings.NAME,
		'email': Dsq.Strings.EMAIL,
		'website': Dsq.Strings.WEBSITE + ' (' + Dsq.Strings.OPTIONAL.toLowerCase() + ')'
	};
	
	this.handlePlaceholder = function(evt, el, key) {
		var placeholder = Dsq.Templates.placeholder[key];
		var className = Dsq.Templates.placeholder['class'];
		
		switch(evt.type) {
			case 'focus':
				if(el.value == placeholder) {
					el.value = '';
					el.className = '';
				}
				break;

			case 'blur':
				if(el.value == '') {
					el.value = placeholder;
					el.className = className;
				}
				break;
			default:
				break;
		}
	};
	
	this.paginate = function(page, el_clicked) {

		var extra_params = '';

		if(typeof disqus_per_page != 'undefined') {
			extra_params += '&per_page=' + disqus_per_page;
		}
		if(typeof disqus_sort != 'undefined') {
			extra_params += '&sort=' + disqus_sort;
		}

		Dsq.$('dsq-pagination').innerHTML += '<img src="http://media.disqus.com/images/loading-small.gif">';
		
		if(el_clicked) {
			Dsq.Templates.setLoadingButton(el_clicked);
		}
		
		Dsq.Utils.execScript('http://disqus.com/forums/scobleizer/thread.js'
			+ '?slug='	+ 'should_services_charge_8220super_users8221'
			+ '&p='		+ page
			+ extra_params);
	};
	
	
	this.rate = function(el, id, vote) {


		if(Dsq.jsonData.request.is_authenticated || Dsq.jsonData.forum.allow_anon_votes) {
			if(vote == 1) {
				Dsq.$('dsq-like-' + id).innerHTML = '<img src="http://media.disqus.com/images/loading-small.gif">';
			}
			Dsq.Utils.execScript('http://disqus.com/forums/scobleizer/vote.js'
				+ '?post_id='    + id
				+ '&vote='        + vote);
		} else {
			Dsq.Popup.login('To rate, please log in');
		}
	};

	this.voted = function(post_id, points, vote) {

		Dsq.$('dsq-like-pts-' + post_id).innerHTML = points + Dsq.Utils.pluralize(points, ' person', ' people') + ' liked this.';

		if(vote) {
			Dsq.$('dsq-like-' + post_id).innerHTML = 'You liked this.&nbsp;&nbsp;';
		}
	};




	this.postComment_onSuccess = function(response, parent_post_id, post_id) {
		var approved = response.message.post_meta.approved;

		if (parent_post_id) {
			Dsq.Post.toggleReply(parent_post_id);
		}

		Dsq.Popup._closePopup(null, true);
		
		if (approved) {
			Dsq.Post.incrementPostCount();
			Dsq.Post.outlineComment(post_id);
		} else {			
			var unapproved_msg = 'Thanks for posting!\
	 Your comment must be approved by a moderator before appearing here.\
			';
			Dsq.Popup.popModal(unapproved_msg, 'Comment awaiting approval', post_id);
		}

		var sharing_results = response.message.sharing_results;
		var sharing_errors = '';
		for (var service in sharing_results) {
			if (sharing_results.hasOwnProperty(service) === true) {
				if (sharing_results[service].error === true) {
					sharing_errors += service + ', ';
				}
			}
		}

		if (sharing_results.facebook && sharing_results.facebook.callback) {
			FB.ensureInit(function() {
				FB.Connect.streamPublish('', sharing_results.facebook.attachment);
			});
		}

		if (sharing_errors !== '') {
			var message = 'Your comment was posted, but there were errors sharing with the following connections: ';
			message += sharing_errors.replace(/,\s$/, '');
			message += '<p><a href="' + Dsq.jsonData.settings.disqus_url + '/profile/connections" target="_blank">Configure your connections here</a></p>'
			Dsq.Popup.popModal(message, 'Sharing options');
		}

		Dsq.Templates.setLoadingButton(false);
	};

	this.postComment_onFailure = function(response, parent_post_id, post_id) {

		Dsq.Templates.setLoadingButton(false);
	};
};




// TODO: It might be faster to use string methods to find all <li (...) </li> blocks and pass to Dsq.PostHandler manually.
Dsq.CommentsHandler = function(str, head, post_id, content, tail, offset, s) {
	var prepend_post = Dsq.Templates.prependPost(post_id);
	var append_post = Dsq.Templates.appendPost(post_id);

	content = content.replace(Dsq.POST_RE, Dsq.PostHandler);
	Dsq.Templates.postLoopCounter++;
	head = Dsq.Templates.Filters.commentContainer(post_id, head);
	return prepend_post + head + content + tail + append_post;
};

Dsq.PostHandler = function(str, h_head, post_id, h_content, h_tail, b_head, b_content, b_tail, offset, s) {
	var prepend_header = Dsq.Templates.postPrependHeader(post_id);
	var append_header = Dsq.Templates.postAppendHeader(post_id);
	var prepend_body = Dsq.Templates.preBody(post_id);
	var append_body = Dsq.Templates.postBody(post_id);
	var append_footer = Dsq.Templates.postFooter(post_id);

	b_content = b_content.replace(Dsq.POST_BODY_RE, Dsq.PostBodyHandler);
	return h_head + prepend_header + h_content + append_header + h_tail + b_head + prepend_body + b_content + append_body + b_tail + append_footer;
};

Dsq.PostBodyHandler = function(str, head, post_id, content, tail, offset, s) {
	content = Dsq.Templates.Filters.commentContent(post_id, content);
	return head + content + tail;
};

Dsq.MediaPostHandler = function(str, args, offset, s) {
	args = args.split(' ');
	if(args[0] == 'seesmic') {
		return '<br />' + Dsq.Templates.mediaSeesmic(args[1], args[2]);
	}
	return '';
};


/**
 * Shorcuts
 */
Dsq.$ = function(element) { return document.getElementById(element); };
Dsq.$b = document.body || document.getElementsByTagName('body')[0];


/**
 * Dsq.Debug: Logging functions.
 */

Dsq.Debug = new function() {this.log=function(s){};this.profile=function(f){if(typeof f == 'function')return f();else return eval(f);};};


/**
 * Dsq.Urls: URL paths
 */
Dsq.Urls = new function() {
	this.LOGIN = '/profile/login/';
	this.LOGOUT = '/logout/';
	this.REPLY = 'http://scobleizer.disqus.com/should_services_charge_8220super_users8221/reply.html';
	this.REQUEST_USER_PROFILE = '/AnonymousUser/';
	this.REQUEST_USER_AVATAR = 'http://media.disqus.com/images/noavatar92.png';
};
// Dsq.Urls

/**
 * Dsq.Validators: Validation for form fields
 */
Dsq.Validators = new function() {
	this.VALID_EMAIL_RE = /^[a-z0-9\-\_\+]+(\.[a-z0-9\-\_\+]+)*\@(([a-z0-9\-\_\+]+(\.[a-z0-9\-\_\+]+)*)+\.[a-z]{2,}|([0-9]+\.){3}[0-9]+)$/i;
	this.name = function(name) {
		var error = false;

		if(typeof Dsq.Templates.placeholder !== 'undefined' &&
		   name == Dsq.Templates.placeholder.name) {
			error = true;
		}
		if(name.length <= 1) {
			error = true;
		}

		if(error) {
			return "Please enter a name to comment.";
		} else {
			return true;
		}
	};
	this.email = function(addr) {
		if(Dsq.Validators.VALID_EMAIL_RE.test(addr)) {
			return true;
		} else {
			return "Please enter a valid email to comment.";
		}
	};
	this.url = function(addr) {
		if(!addr || addr.indexOf('.') != -1) {
			return true;
		} else {
			return "Please check your website URL (this field is optional).";
		}
	};

	this.validate = function(bulk_validation, failure_callback) {
		failure_callback = failure_callback || function(e){ alert(e); };

		for(var i = 0; i < bulk_validation.length; i++) {
			v = bulk_validation[i];
			ret = v.validator(v.value);
			if(ret !== true) {
				failure_callback(ret);
				return false;
			}
		}
		return true;
	};
};

/**
 * Dsq.Utils: Generic utility functions.
 */
Dsq.Utils = new function() {
	this.ie = /msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent);
	this.ie7 = (document.all && !window.opera && window.XMLHttpRequest) ? true : false;
	this.ie6 = (!window.XMLHttpRequest) ? true: false;
	this.webkit = navigator.userAgent.indexOf('AppleWebKit/') >= 0;
	this.gebiFromElementCollectionCache = {};
	this._styleSheet = null;

	this.gebiFromElement = function(el, id, tag) {
		// This only method only helps IE.
		if(!this.ie) {
			return Dsq.$(id);
		} else {
			var cacheKey = el.id + '-' + tag;
			tag = tag || 'div';
			if(typeof this.gebiFromElementCollectionCache[cacheKey] != 'undefined') {
				collection = this.gebiFromElementCollectionCache[cacheKey];
			} else {
				collection = el.getElementsByTagName(tag);
				this.gebiFromElementCollectionCache[cacheKey] = collection;
			}

			for(var i = 0; i < collection.length; i++) {
				if(collection[i].id == id) {
					return collection[i];
				}
			}
			return null;
		}
	};

	this.execOnReady = function(func) {
		var node = document.createElement('document:ready');
		try {
			node.doScroll('left');
			func();
			node = null;
		} catch(err) {
			setTimeout(function() { Dsq.Utils.execOnReady(func); }, 10);
		}
	};


	// Courtesy of http://www.quirksmode.org/js/cookies.html
	this.createCookie = function(name,value,days) {
		if (days) {
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			var expires = "; expires="+date.toGMTString();
		}
		else var expires = "";
		document.cookie = name+"="+value+expires+"; path=/";
	};

	this.readCookie = function(name) {
		var nameEQ = name + "=";
		var ca = document.cookie.split(';');
		for(var i=0;i < ca.length;i++) {
			var c = ca[i];
			while (c.charAt(0)==' ') c = c.substring(1,c.length);
			if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
		}
		return null;
	};

	this.eraseCookie = function(name) {
		Dsq.Utils.createCookie(name,"",-1);
	};

	this.deleteNode = function(node) {
		if(node) {
			this.deleteChildren(node);
			if(typeof node.outerHTML != 'undefined') { node.outerHTML = ''; }
			else if(node.parentNode) { node.parentNode.removeChild(node); }
			delete node;
		}
	};

	this.deleteChildren = function(node) {
		if(node) {
			for(var x = node.childNodes.length-1; x >= 0; x--) {
				var childNode = node.childNodes[x];
				if(childNode.hasChildNodes()) { this.deleteChildren(childNode); }
				if(typeof childNode.outerHTML != 'undefined') { childNode.outerHTML = ''; }
				else node.removeChild(childNode);
				delete childNode;
			}
		}
	};

	this.findPos = function(obj) {
		var curleft = 0;
		var curtop = 0;
		if (obj.offsetParent) {
			do {
				curleft += obj.offsetLeft;
				curtop += obj.offsetTop;
			} while (obj = obj.offsetParent);
		}
		return [curleft,curtop];
	};

	this.getWindowSize = function() {
		var windowWidth = -1;
		var windowHeight = -1;

		if(typeof(window.innerWidth) == 'number') { //Non-IE
			windowWidth = window.innerWidth;
			windowHeight = window.innerHeight;
		} else if(document.documentElement) { // IE 6+ in 'standards compliant mode'
			windowWidth = document.documentElement.clientWidth || document.body.clientWidth;
			windowHeight = document.documentElement.clientHeight || document.body.clientHeight;
		}

		return [windowWidth, windowHeight];
	}

	this.getScrollPos = function() {
		var scrollWidth, scrollTop;

		if(document.documentElement && (document.documentElement.scrollTop || document.documentElement.scrollWidth)) {
			scrollWidth = document.documentElement.scrollWidth;
			// IE is weird here.  If no doctype is provided, document.body.scrollTop is 0,
			// otherwise document.documentElement.scrollTop is 0.
			scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
		} else if(document.body.scrollTop && document.body.scrollWidth) {
			scrollWidth = document.body.scrollWidth;
			scrollTop = document.body.scrollTop;
		}

		return [scrollWidth, scrollTop];
	}

	this.addEventListener = function(instance, eventName, listener) {
		var listenerFn = listener;
		if (instance.addEventListener) {
			instance.addEventListener(eventName, listenerFn, false);
		} else if (instance.attachEvent) {
			listenerFn = function() {
				listener(window.event);
			};
			instance.attachEvent("on" + eventName, listenerFn);
		} else {
			throw new Error("Event registration not supported");
		}
		return {
			instance: instance,
			name: eventName,
			listener: listenerFn
		};
	};

	this.removeEventListener = function(event) {
		var instance = event.instance;
		if (instance.removeEventListener) {
			instance.removeEventListener(event.name, event.listener, false);
		} else if (instance.detachEvent) {
			instance.detachEvent("on" + event.name, event.listener);
		}
	};

	this.fixIframesIE = function(id) {
		var disqusThread = Dsq.$(disqus_container_id);
		var iframes = disqusThread.getElementsByTagName('iframe');

		if(id) {
			var container = Dsq.$(id);
		} else {
			var container = Dsq.$('dsq-content');
		}

		for(i = 0; i < iframes.length; i++) {
			if (container) {
				iframes[i].style.width = container.offsetWidth;
			}
		}
	};

	this.getElementsByClassName = function(oElm, strTagName, strClassName) {
	/* Credit: Jonathan Snook [http://www.snook.ca/jonathan], Robert Nyman [http://www.robertnyman.com] */
		var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
		var arrReturnElements = new Array();
		strClassName = strClassName.replace(/\-/g, "\\-");
		var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
		var oElement;
		for(var i = 0; i < arrElements.length; i++) {
			oElement = arrElements[i];
			if(oRegExp.test(oElement.className)) {
				arrReturnElements.push(oElement);
			}
		}
		return (arrReturnElements);
	};

	this.postToUrl = function(url, post_data, opt_redirect) {
		var form = document.createElement('form');
		var iframe_container = document.createElement('div');
		var id = 'dsq-temp-iframe-' + (new Date()).getTime();

		form.method = 'POST';
		form.action = url;
		if (!opt_redirect) {
			form.target = id;
		}
		iframe_container.innerHTML = '<iframe style="display:none" name="' + id + '" id="' + id + '"></iframe>';

		for(var key in post_data) {
			if(post_data.hasOwnProperty(key)) {
				var input = document.createElement('input');
				input.name = key;
				input.type = 'hidden';
				input.value = post_data[key];

				form.appendChild(input);
			}
		}

		Dsq.$b.appendChild(iframe_container);
		Dsq.$b.appendChild(form);
		form.submit();
	};

	// Strips integer id from id of element in the form ('some-id-###')
	this.extractId = function(e) {
		var chunks = e.id.split('-');
		if(chunks.length <= 1) {
			return 0;
		} else {
			var retval = parseInt(chunks[chunks.length-1]);
			return !isNaN(retval) ? retval : null;
		}
	};

	this.getStyle = function(el, styleProp) {
		if(el.currentStyle) {
			var y = el.currentStyle[styleProp];
		} else if(window.getComputedStyle) {
			var y = document.defaultView.getComputedStyle(el, null).getPropertyValue(styleProp);
		}

		if(y == 'transparent' || y == '') {
			this.getStyle(el.parentNode, styleProp);
		} else {
			return y;
		}
	};

	this.execScript = function(url, append_qs, container) {
		var script = document.createElement('script');
		append_qs = typeof append_qs == 'undefined' ? true : append_qs;
		container = container || Dsq.container;

		if(append_qs) {
			var j = (url.indexOf('?') >= 0) ? '&' : '?';
			url += j + (new Date()).getTime();
		}
		script.type = 'text/javascript';
		script.charset = 'UTF-8';
		script.src = url;
		container.appendChild(script);
		return script;
	};

	this.pluralize = function(num, singular, plural) {
		return (num != 1) ? plural || 's' : singular || '';
	};

	this.getRequestParams = function(queryString /* optional */) {
		var pairs, tuple;
		var params = {};

		queryString = queryString || window.location.search.substring(1);
		pairs = queryString.split('&');

		for (var i = 0, pair; pair = pairs[i]; i++) {
			tuple = pair.split('=');
			params[tuple[0]] = (tuple[1] || true);
		}

		return params;
	};

	this.addCssRule = function(selector, styleText, index) {
		var stylesheet;
		index = index || 0;

		if(!this._styleSheet) {
			var styleEl = document.createElement('style');
			document.getElementsByTagName('head')[0].appendChild(styleEl);
			this._styleSheet = styleEl.sheet;
			if(!this._styleSheet) {
				// IE does not like our newly created stylesheet.
				this._styleSheet = document.styleSheets[document.styleSheets.length-1];
			}
		}
		stylesheet = this._styleSheet;

		if(stylesheet.insertRule) {
			var ruleText = selector + ' { ' + styleText + ' }';
			if(index == -1) {
				index = stylesheet.cssRules.length;
			}
			stylesheet.insertRule(ruleText, index);
		} else if(stylesheet.addRule) {
			stylesheet.addRule(selector, styleText, index);
		}
	};

	this.forEachIn = function(obj, callback) {
		for(var key in obj) {
			if(obj.hasOwnProperty(key)) {
				callback(key, obj[key]);
			}
		}
	};

	this._interpolateGlobalContext = {
		// values that get used a lot and are global to the request
		'profile_url': Dsq.Urls.REQUEST_USER_PROFILE,

		'disqus_url': Dsq.jsonData.settings.disqus_url,
		'media_url': Dsq.jsonData.settings.media_url,
		'request_username': Dsq.jsonData.request.username,
		'request_display_username': Dsq.jsonData.request.display_username,
		'forum_name': Dsq.jsonData.forum.name
	};

	this.renderFromContextStack = function(key, contexts) {
		// Returns the first instance of `key` in the array of objects `contexts` or else ''
		for (var i=0; i<contexts.length; i++) {
			if (contexts[i][key] !== undefined) {
				return String(contexts[i][key]);
			}
		}
		throw new Error('key ' + key + ' not found in context');
	};

	var that = this;
	this.interpolate = function(fmt, opt_localContext) {
		// Interpolate `fmt` named-format string with an assumed global context.
		// Based on `interpolate` in django.views.i18n
		var contextStack = [opt_localContext || {}, that._interpolateGlobalContext];
		return fmt.replace(/%\(\w+\)s/g, function(match){
			return that.renderFromContextStack(match.slice(2,-2), contextStack);
		});
	};

	this.stripTags = function(s) {
		// Removes HTML tags from `s`
		return s.replace(/(<([^>]+)>)/g,"");

	};

	this.assert = function(b) {
		if (!b) {
			throw new Error('Assertion error.');
		}
	};

};
// Dsq.Utils

/**
 * Dsq.Popup: Popup helper functions.
 */
Dsq.Popup = new function() {
	this.timeHide = new Array();
	this.timeShow = new Array();
	this.activePopup = {};
	this.profileCache = {};
	this.statusCache = {};

	this.showTimer = function(post_id) {
		// clear the hide timer
		clearTimeout(this.timeHide[post_id]);

		// start the timer
		if(!Dsq.Popup.profileIsOn && !Dsq.Thread.adminIsOn) {
			this.timeShow[post_id] = setTimeout("Dsq.Popup.popProfile(\"" + post_id + "\")", 400);
		}
	};

	this.hideTimer = function(post_id) {
		// clear the show timer
		clearTimeout(this.timeShow[post_id]);
	};

	this.updateProfile = function(username) {
		// Callback from /embed/profile.js
		if (this.statusCache[username]) {
			var statusEl = Dsq.$('dsq-profile-status-' + username);
			statusEl.innerHTML = this.statusCache[username];
			statusEl.style.display = 'block';
		}

		if (this.profileCache[username]) {
			var _cache = this.profileCache[username];

			var _genhtml = function(text) { return '<span><big>' + text + '</big></span>'; };
			var _no_comments = _genhtml(Dsq.FmtStrings.NUMBER_OF_COMMENTS(_cache.comments_count));
			var _no_likes = _genhtml(Dsq.FmtStrings.NUMBER_OF_LIKES(_cache.likes_count));
			var _no_points = _genhtml(Dsq.FmtStrings.NUMBER_OF_POINTS(_cache.points));

			var statsEl = Dsq.$('dsq-popup-profile-user-stats-' + username);
			statsEl.innerHTML = '';

			if (Dsq.jsonData.users[username].registered) {
				statsEl.innerHTML = _no_comments + _no_likes;
			}
			statsEl.innerHTML += _no_points;

			var activeSites = '';
			for (var i = 0; i < _cache.active_sites.length; i++) {
				var site = _cache.active_sites[i];
				activeSites += '<li><a href="' + site.url + '"> \
					<img src="' + site.favicon + '"/ width="16" height="16"/></a>\
					<a href="' + site.url + '">' + site.name + '</a></li>';
			}
			if (activeSites !== '') {
				Dsq.$('dsq-popup-profile-active-sites-' + username).innerHTML = activeSites;
			} else {
				Dsq.$('dsq-popup-profile-active-sites-' + username).innerHTML = 'This site.';
			}

			var moderatedSites = '';
			for (var i = 0; i < _cache.moderated_sites.length; i++) {
				var site = _cache.moderated_sites[i];
				moderatedSites += '<li><a href="' + site.url + '"> \
					<img src="' + site.favicon + '"/ width="16" height="16"/></a>\
					<a href="' + site.url + '">' + site.name + '</a></li>';
			}
			if (moderatedSites !== '') {
				Dsq.$('dsq-popup-profile-moderated-' + username).innerHTML = moderatedSites;
			} else {
				Dsq.$('dsq-popup-profile-moderated-wrapper-' + username).innerHTML = '';
			}
		}

		// Reposition popup after full HTML is rendered
		if(Dsq.Popup.activePopup && Dsq.Popup.activePopup.el) {
			Dsq.Popup.initPopup(Dsq.Popup.activePopup.el, Dsq.Popup.activePopup.id, Dsq.Popup.activePopup.type);
		}

	};

	this.showCookieMsgs = function() {
		var title = '';
		var message = '';
		var numAlerts = 0;

		Dsq.Utils.forEachIn(Dsq.jsonData.cookie_messages, function(k, v) {
			if (!v) return;

			switch(k) {
				// Cookie: Twitter
				case 'post_twitter':
					if (v === 'error') {
						title = 'Twitter Error!';
						message += '<li id="dsq-msg-twitter-error">Oops, we couldn\'t tweet this comment. Please check your <a href="http://disqus.com/account/services">account settings</a>.</li>';
					} else {
						var _msg = v.split(':');
						title = 'Tweeted!';
						message += '<li id="dsq-msg-twitter-success">Your comment was successfully tweeted. <a href="http://twitter.com/' + _msg[0] + '/status/' + _msg[1] + '">Click here to view the tweet</a>.</li>';
					}
					break;
				// Cookie: Unapproved Post
				case 'post_not_approved':
					title = 'Comment awaiting approval by a moderator';
					message += '<li id="dsq-msg-post-not-approved">Your comment must be approved by a moderator before appearing here.</li>';
					break;
				// Cookie: Profile Found
				case 'post_has_profile':
					title = 'Use your existing commenter profile';
					message += '<li id="dsq-msg-post-has-profile">You have just posted your commment as a <span class="dsq-badge-guest">Guest</span>, but you may already have a <span class="logo-disqus">Disqus</span> Profile.<br /><br /><a href="http://disqus.com/claim">Log in and claim this comment!</a></li>';
					break;
				case 'user_created':
					var _data = v.split(':');
					title = 'Profile created!';
					message += '<li id="dsq-msg-user-created">You have just created a <span class="logo-disqus">Disqus</span> Profile, the best way to claim, manage, and track your comments all over the web. \
					<br /><br />A confirmation is being sent to <strong>' + _data[1] + '</strong>. Please check for this email in order to verify your profile. \
					<ul class="dsq-list-tick"> \
						<li>Your username is <strong>' + _data[0] +'</strong>. <a href="http://disqus.com/people/' + _data[0] + '/" target="_blank">Click here to view your public profile</a>.</li> \
						<li>Be sure to set your profile picture, as well as connect your <span class="dsq-badge-facebook">Facebook</span> and <span class="dsq-badge-twitter">Twitter</span> accounts. <a href="http://disqus.com/account/" target="_blank">Click here for account settings</a>.</li> \
					</ul> \
					</li>'
					break;
				default:
					break;
			}
			numAlerts++;
		});

		if(numAlerts > 1) {
			message = '<ul class="dsq-list-bluebullet">' + message;
			message += '</ul>';
			title = 'Thanks for posting!';
		}
		if(numAlerts > 0) {
			if(typeof(disqus_cookie_msgs) == 'function') {
				disqus_cookie_msgs(message, title);
			} else {
				Dsq.Popup.popModal(message, title);
			}
		}
	};

	this.helpBadges = function(post_id) {
		var html = ' \
			<ul class="dsq-popup-help"> \
				<li><span class="dsq-badge dsq-badge-verified">Verified</span> has a <span class="logo-disqus">Disqus</span> Profile with a confirmed email address.</li> \
				<li><span class="dsq-badge dsq-badge-registered">Registered</span> has a <span class="logo-disqus">Disqus</span> Profile, but has not yet confirmed his or her email address.</li> \
				<li><span class="dsq-badge dsq-badge-guest">Guest</span> is not logged in with any account and has not claimed his or her comments.</li> \
				<li class="dsq-help-otheraccts">Other accounts</li> \
				<li><span class="dsq-badge dsq-badge-facebook">Facebook</span> is using his or her Facebook profile via Facebook Connect.</li> \
				<li><span class="dsq-badge dsq-badge-twitter">Twitter</span> is using his or her Twitter profile via Twitter Sign-in.</li> \
				<li><span class="dsq-badge dsq-badge-openid">OpenID</span> is using his or her OpenID.</li> \
			</ul> \
		';

		this.popModal(html, 'Help: Types of Commenters', post_id);
		return;
	};

	this.permalink = function(post_id) {
		var header = 'Link to this comment';
		var body = '<strong>You are anchored to</strong>:<br />' + document.location.protocol + '//' + document.location.host + document.location.pathname + document.location.search + '#comment-' + post_id;

		this.popModal(body, header, post_id);
	};

	this.login = function(header, body) {
		var h = header || 'Login or Register';
		var b = body || '';
		b += Dsq.Templates.frameLogin({id: 'dsq-popup-login'});
		b += '</iframe>'; // HACK: Sometimes there is something funky with the IFRAME SRC that causes no end tag
		this.popModal(b, h, null, true, 'dsq-popup-login');
	};

	this.blacklist = function(id) {
		var _meta = Dsq.jsonData.posts[id];
		var userData = Dsq.jsonData['users'][_meta.user_key];
		var title = 'Add to Blacklist';
		var message = ' \
		Adding this person to the blacklist will block him or her from commenting on this site. Check the following types that you would like to add to the blacklist:'
		+ (userData['registered'] ?
			'<div class="dsq-blacklist-option"> \
				<input id="dsq-blacklist-username" type="checkbox" checked> \
				<label for="dsq-blacklist-username"><strong>Username</strong>: ' + userData['username'] + '</label> \
			</div>'
			: '')
		+ (_meta.email ?
			'<div class="dsq-blacklist-option"> \
				<input id="dsq-blacklist-email" type="checkbox" checked> \
				<label for="dsq-blacklist-email"><strong>Email address</strong>: ' + _meta.email + '</label> \
			</div>'
			: '')
		+ '<div class="dsq-blacklist-option"> \
			<input id="dsq-blacklist-ip" type="checkbox" onclick="Dsq.$(\'dsq-blacklist-ip-warning\').style.display=\'block\'"> \
			<label for="dsq-blacklist-ip"><strong>IP address</strong>: ' + _meta.ip + '</label> \
		</div> \
		';

		message += ' \
			<p id="dsq-blacklist-ip-warning" style="display:none">	\
				Note: Blocking this person\'s IP address may also unintentionally prevent others, who share his/her IP address, from commenting on this site. \
				This may include people who are sharing the same computer, living in the same house, or using the same Internet provider. Only block an IP address as a last resort. \
			</p> \
		';

		message += ' \
			<p style="text-align:center"><button type="button" onclick="Dsq.Post.blockUser(' + id + '); this.disabled=true; this.innerHTML=\'Just one moment...\'">Add to Blacklist</button></p> \
		';

		Dsq.Popup.popModal(message, title);
	};

	this.remoteAccountSettings = function() {
		var body = '';
		// Set up IFrame.
		var params = {};
		var base_url = 'http://disqus.com/forums/scobleizer/_auth/embed/remote_settings/';
		var attributes = {id: 'dsq-popup-account-settings'};
		if (typeof disqus_frame_theme != 'undefined') {
			params['theme'] = disqus_frame_theme;
		}

		body = Dsq.Templates._frameGeneric(base_url, params, attributes);
		this.popModal(body, 'Account Settings', null, true, 'dsq-popup-account-settings');
	};

	this.popModal = function(message, title, post_id, use_listener, extra_classes) {
		var container = document.createElement('div');
		var header, body;

		Dsq.Popup._closePopup(null, true);

		if(typeof(title) == 'undefined') { title = ''; }
		if(typeof(use_listener) == 'undefined') { use_listener = true; }

		if(post_id) {
			container.id = 'dsq-popup-message-' + post_id;
		} else {
			container.id = 'dsq-popup-message';
		}

		header = title;
		body = message;

		container.innerHTML = Dsq.Templates.popupModal(header, body);
		Dsq.Popup.initPopup(container, post_id, 'message', extra_classes);
		if(use_listener) {
			Dsq.Popup.popupListener = Dsq.Utils.addEventListener(document, 'mouseup', Dsq.Popup._closePopup);
		}
	};

	this.popAlert = this.popModal;

	this.loading = function(post_id) {
		var title = Dsq.Strings.JUST_A_MOMENT;
		var body = '<div style="text-align:center; padding: 5px 0 10px 0"><img src="http://media.disqus.com/images/loading.gif" alt="" /></div>'
		Dsq.Popup.lightbox(body, title, post_id);
	};

	this.lightbox = function(message, title, post_id) {
		// Wraps Dsq.Popup.popModal

		var overlay = document.createElement('div');
		overlay.id = 'dsq-overlay';
		overlay.className = 'dsq-overlay';
		Dsq.$b.appendChild(overlay);
		
		Dsq.Popup.popModal(message, title, post_id, false, 'dsq-lightbox');
	};

	this.popProfile = function(post_id, userKey) {
		var post = Dsq.jsonData['posts'][post_id];
		if (post && post.has_been_anonymized) {
			Dsq.Popup.popModal('This message was anonymized by its previous owner.', 'Anonymized', post_id);
			return;
		}

		if(post_id) {
			userKey = Dsq.jsonData['posts'][post_id].user_key;	
		}
		var userData = Dsq.jsonData['users'][userKey];
		var elId = 'dsq-popup-profile-' + userKey;
		var container = document.createElement('div');

		if(this.activePopup.el) {
			this._closePopup(null, true);
			if(this.activePopup.linkClicked) {
				this.activePopup.linkClicked = false;
				return;
			}
		}

		container.id = elId;
		container.innerHTML = Dsq.Templates.popupProfile(userKey);

		this.initPopup(container, post_id, 'profile');
		this.popupListener = Dsq.Utils.addEventListener(document, 'mouseup', this._closePopup);

		if(!this.profileCache[userKey]) {
			Dsq.Utils.execScript('http://disqus.com/embed/profile.js'
				+ '?username=' + userKey
				+ '&anon=' + (userData['registered'] ? 0 : 1)
				+ '&f=' + Dsq.jsonData['request'].forum);
		} else {
			this.updateProfile(userKey);
		}
	};

	this._closePopup = function(e, force) {
		var activePopup = Dsq.Popup.activePopup.el;
		var id = Dsq.Popup.activePopup.id;
		var link = 'dsq-avatar-' + id; // HACK: Specific to profile toggle target

		// HACK: This event should be gone if there is no active popup.
		if(!activePopup) {
			return;
		}
		if(force || !Dsq.Popup.isClicked(e, activePopup.id)) {
			// TODO: This is breaking iE?
			if(Dsq.Popup.popupListener) {
				Dsq.Utils.removeEventListener(Dsq.Popup.popupListener);
			}
			
			// Kill overlay
			var overlay = Dsq.$('dsq-overlay');
			if(overlay) { Dsq.Utils.deleteNode(overlay); }
			
			try {
				Dsq.Utils.deleteNode(activePopup);
			} catch(e) {
				// HACK: IE6 throws an error when using deleteNode() with a node containing a <table> in the html.
				activePopup.parentNode.removeChild(activePopup);
			}
			Dsq.Popup.activePopup = {};
		}

		if(!force && Dsq.Popup.isClicked(e, link)) {
 			Dsq.Popup.activePopup.linkClicked = true;
		}

	};

	this.initPopup = function(popup, post_id, type, extra_classes) {
		popup.className = 'dsq-popup dsq-popup-' + type + ' ' + (extra_classes ? extra_classes : '');
		if(Dsq.Utils.ie6 || Dsq.Utils.ie7) {
			// HACK: We can't modify the body before it's ready, so we need
			//       to use an IE-safe "DOMReady" workaround before loading
			//       our popup.
			Dsq.Utils.execOnReady(function() {Dsq.$b.appendChild(popup); });
		} else {
			Dsq.$b.appendChild(popup);
		}

		popup.style.display = 'block';

		var xPos = (Dsq.Utils.getWindowSize()[0] - popup.offsetWidth) / 2;
		var yPos = (Dsq.Utils.getWindowSize()[1] - popup.offsetHeight) / 2;

		if(Dsq.Utils.ie6) {
			yPos += Dsq.Utils.getScrollPos()[1];
		}

		popup.style.left = xPos + 'px';
		popup.style.top = yPos + 'px';

		Dsq.Popup.activePopup = {
			'el' : popup,
			'id' : post_id,
			'type': type,
			'linkClicked' : false
		};
	};

	this.isClicked = function(e, id) {
		var t = e.target || e.srcElement;
		while(t && t.parentNode) {
			if(t.id == id) {
				return true;
			}

			t = t.parentNode;
		}
		return false;
	};
};
// Dsq.Popup

/**
 * Dsq.Templates
 */
Dsq.Templates = new function() {
	/*
	 * Counter keeping track of the number of posts iterated over.
	 */
	this.postLoopCounter = 0;
	this.filters = {};
	this.addPostContainer = 'dsq-post-add';
	this.textareaContainer = 'dsq-post-add';

	this.registerTemplate = function(name, func) {
		this['$$_' + name] = func;

		if(typeof DsqLocal.Filters != 'undefined'
		&& typeof DsqLocal.Filters[name] == 'function') {
			// Push filters to this.filters to unify code.
			this.filters[name] = this.filters[name] || [];
			this.filters[name].push(DsqLocal.Filters[name]);
		}

		this[name] = function() {
			var ret;

			if(typeof DsqLocal.Templates != 'undefined'
			&& typeof DsqLocal.Templates[name] == 'function') {
				ret = DsqLocal.Templates[name].apply(this, arguments);
			}

			if(ret === undefined) {
				ret = this['$$_' + name].apply(this, arguments);
			}

			if(this.filters[name]) {
				var args = [ret];

				args.push.apply(args, arguments);
				for(var i = 0; i < this.filters[name].length; i++) {
					ret = this.filters[name][i].apply(this, args);
				}
			}

			return ret;
		};
	};

	this.registerFilter = function(name, func) {
		this.filters[name] = this.filters[name] || [];
		this.filters[name].push(func);
	};

	/**
	 * Dsq.Templates.Filters
	 */
	this.Filters = new function() {
		this.commentContainer = function(post_id, s) {
			var _meta = Dsq.jsonData.posts[post_id];
			var classes = [];
			if(Dsq.jsonData.request.page > 1) {
				classes.push('dsq-append');
			}

			//
			// Extra classes used for custom themes
			//

			if(_meta.depth) {
				classes.push('dsq-comment-child', 'dsq-depth-' + _meta.depth, 'dsq-parent-is-' + _meta.parent_post_id);
			}


			//

			if(_meta.author_is_creator) {
				// TODO: We need to deprecate the "special" class since it is not properly prefixed.
				classes.push('special', 'dsq-special');
			}
			if(_meta.author_is_moderator) {
				classes.push('dsq-moderator');
			}
			classes.push(['dsq-odd', 'dsq-even'][Dsq.Templates.postLoopCounter % 2]);

			s = s.substring(0, s.lastIndexOf('>'));
			return s + ' class="dsq-comment ' + classes.join(' ') + '" style="margin-left:' + _meta.depth*30 + 'px">';
		};

		this.commentContent = function(post_id, s) {
			var _meta = Dsq.jsonData.posts[post_id];
			if (_meta.killed) {
				return '<em>Comment removed.</em>';
			} else if (!_meta.approved) {
				return '<em>This comment was flagged for review.</em>';
			}

			s = s.replace(Dsq.MEDIA_POST_RE, Dsq.MediaPostHandler);
			return s;
		};
	};

	//
	// Thread
	//
	// TODO: These need to be stripped of all Django template tags.

	this.authPost = function() {
		if (!Dsq.jsonData.context.show_reply) {
			return '';
		}
		var result = [];
		result = result.concat([
				'<div id="dsq-auth"',
						Dsq.jsonData.integration.reply_position ? 'class="dsq-auth-bottom"' : '',
						'>',
					'<div class="dsq-by">',
						'<a href="http://disqus.com" target="_blank">',
							(Dsq.jsonData.integration.disqus_logo ?
								Dsq.Utils.interpolate('<img src="%(media_url)s/images/embed/by-disqus.png" alt="discussion by DISQUS">') :
								Dsq.Utils.interpolate('<img src="%(media_url)s/images/embed/dsq-button-120x19.png" alt="discussion by DISQUS">')
							),
						'</a>',
					'</div>',
					'<div class="dsq-auth-header">',
						'<h3 id="dsq-add-new-comment" class="dsq-h3-addcomment">',
								Dsq.Strings.ADD_NEW_COMMENT,
						'</h3>',
						'<div id="dsq-login">',
						(!Dsq.jsonData.request.is_authenticated && Dsq.jsonData.forum.allow_anon_post
								? '<p class="dsq-login-message" id="dsq-login-message">You are commenting as a <a class="dsq-help" title="Click for more information" href="#" onclick="Dsq.Popup.helpBadges(); return false">Guest</a>. You may select one to log into:</p>'
								: '')
		]);
		if (!Dsq.jsonData.request.is_authenticated) {
			result = result.concat([
							Dsq.Utils.interpolate(
								'<a id="dsq-login-toggle" href="%(disqus_url)s%(login_url)s?next=article:%(thread_id)s" onclick="Dsq.Popup.login(); return false"><img class="dsq-login-icon" src="%(media_url)s/images/dsq-profile-btn.png" title="%(log_into)s" alt="%(log_into)s"/></a>',
								{login_url: Dsq.Urls.LOGIN, thread_id: Dsq.jsonData.thread.id, log_into: Dsq.Strings.LOG_INTO_DISQUS}
								),
							'&nbsp; ',
							(Dsq.jsonData.context.use_fb_connect ?
								'<div id="dsq-fbc-login" onlogin="DisqusFbcParentController.onLogin()" size="medium" background="light" length="short" style="display:inline; margin-right:7px"></div>' :
								''
							),
							(Dsq.jsonData.context.use_twitter_signin ?
								Dsq.Utils.interpolate(
									'<div id="dsq-twitter-login" class="dsq-twitter-login" onclick="Dsq.Twitter.startTwitterConnect();" style="display:inline; cursor: pointer"><img src="%(media_url)s/images/twitter-signin-short.png" style="margin-right:7px" /></div>', {}) : ''),
							(Dsq.jsonData.context.use_openid ?
								Dsq.Utils.interpolate(
									'<div id="dsq-openid-login" class="dsq-openid-login" onclick="Dsq.OpenID.requestURL();" style="display:inline; cursor:pointer;"><img src="%(media_url)s/images/openid-login-button.png"/></div>', {}
								) : '')
			]);
		}
		result = result.concat([
						'</div>', // dsq-login
					'</div>', // dsq-auth-header
					'<div id="dsq-authenticated" class="dsq-authenticated" ',
						Dsq.jsonData.request.is_authenticated ? 'style="display:block"' : '',
						'>',
						'<div class="dsq-authenticated-pic">',
								Dsq.Utils.interpolate('<a href="%(url)s" title="%(request_display_username)s">' +
																			'<img class="dsq-post-avatar" src="%(avatar_url)s" alt="" /></a>',
																			{avatar_url: Dsq.Urls.REQUEST_USER_AVATAR,
																			url: (Dsq.jsonData.request.is_remote
																					 ? Dsq.jsonData.request.url
																					 : Dsq.jsonData.settings.disqus_url + Dsq.Urls.REQUEST_USER_PROFILE) }),
						'</div>',
						'<div class="dsq-authenticated-info">',
							'<ul>',
								'<li>',
									(Dsq.jsonData.request.is_remote
										? Dsq.FmtStrings.LOGGED_IN_AS(
												Dsq.Utils.interpolate('<a href="%(url)s" title="%(request_display_username)s">%(request_display_username)s</a>', {url:Dsq.jsonData.request.url})
										  )
										: Dsq.FmtStrings.LOGGED_IN_AS(
												Dsq.Utils.interpolate('<a href="%(disqus_url)s%(profile_url)s" title="%(request_display_username)s">%(request_display_username)s</a>')
											)
									),
								'</li>',
								'<li class="logout">',
									(!Dsq.jsonData.request.is_remote
										? Dsq.Utils.interpolate('<img class="dsq-login-icon" src="%(media_url)s/images/dsqicon12.png" alt="%(logged_in_as)s"/>&nbsp',
											{logged_in_as: Dsq.FmtStrings.LOGGED_IN_AS(Dsq.jsonData.request.display_username)})
										: ''),

									(!Dsq.jsonData.request.is_remote
										? Dsq.Utils.interpolate('<a href="%(disqus_url)s%(logout_url)s?ctkn=%(csrf_token)s" title="%(logout_from_disqus)s">',
											{logout_url: Dsq.Urls.LOGOUT, csrf_token: Dsq.CSRF_TOKEN, logout_from_disqus: Dsq.FmtStrings.LOGOUT_FROM('DISQUS')})
										: ((Dsq.jsonData.request.remote_domain == 'twitter')
												? Dsq.Utils.interpolate('using Twitter (<a href="%(disqus_url)s%(logout_url)s?ctkn=%(csrf_token)s" title="Logout">Logout</a>)',
												 {logout_url: Dsq.Urls.LOGOUT, csrf_token: Dsq.CSRF_TOKEN})
												: ((Dsq.jsonData.request.remote_domain == 'openid')
													 ? Dsq.Utils.interpolate('using OpenID (<a href="%(disqus_url)s%(logout_url)s?ctkn=%(csrf_token)s" title="Logout">Logout</a>)',
													 {logout_url: Dsq.Urls.LOGOUT, csrf_token: Dsq.CSRF_TOKEN})
													 : ''
													)
											)
									),

									(!Dsq.jsonData.request.is_remote ? Dsq.FmtStrings.LOGOUT_FROM('<span class="logo-disqus">DISQUS</span>') : ''),
									'</a>',
								'</li>',
							'</ul>',
						'</div>',
					'</div>'
		]);
		if (Dsq.jsonData.context.use_fb_connect) {
			result = result.concat([
					'<div id="dsq-fbc-authenticated" class="dsq-authenticated">',
						'<div id="dsq-fbc-profilepic" class="dsq-authenticated-pic" uid="loggedinuser" type="FB.XFBML.ProfilePic" size="square" facebook-logo="true"></div>',
						'<div class="dsq-authenticated-info">',
							'<ul>',
								'<li>',
									'Logged in as <span id="dsq-fbc-name" uid="loggedinuser" type="FB.XFBML.Name" linked="true" useyou="false"></span>',
								'</li>',
								'<li class="logout">using Facebook Connect <a href="#" onclick="javascript:DisqusFbcParentController.logout();return false;">(Logout)</a></li>',
							'</ul>',
						'</div>',
					'</div>'
			]);
		}
		result = result.concat([
				'</div>', // dsq-auth
				'<div id="dsq-toolbar-items">',
				'</div>'
		]);
		result = result.concat([
					//
					//
					//
				((!Dsq.jsonData.forum.allow_anon_post && !Dsq.jsonData.request.is_authenticated) ?
					// Needs to be translated:
					('<p id="dsq-no-anon-msg">Required: Please log into <span class="logo-disqus">Disqus</span> ' +
					(Dsq.jsonData.context.use_fb_connect ? 'or connect with Facebook ' : '') +
					(Dsq.jsonData.context.use_twitter_signin ? 'or sign in with Twitter ' : '') +
					(Dsq.jsonData.context.use_openid ? 'or sign in using OpenID ' : '') +
					Dsq.Utils.interpolate('to comment on <strong>%(forum_name)s</strong>.</p>')) :
					''
				),
				'<div id="dsq-post-add"></div>',
				'<div style="margin:10px 0">',
				((Dsq.jsonData.forum.use_media) ?
						'<a href="#" id="dsq-media-link" onclick="Dsq.Post.showMenu(this, false, \'media\'); return false">' + Dsq.Strings.USE_MEDIA + ' <small>&#9660;</small></a>' :
						''),
				'</div>'
		]);
		return result.join('');
	};


	this.header = function() {

		var html = '\<h3 id="dsq-comments-count" class="dsq-h3-commentcount">\
	 <span id="dsq-num-posts">62</span> Comments\
	 &nbsp;\
	 <span class="dsq-item-feed">\
	 <a href="http://scobleizer.disqus.com/should_services_charge_8220super_users8221/latest.rss"><img src="http://media.disqus.com/images/embed/bullet-feed.png"></a>\
	 </span>\
	 </h3>\
	 <div id="dsq-options" style="margin:15px 0">\
	 <span class="dsq-item-sort">\
	 Sort by\
	 <select id="dsq-sort-select" onchange="Dsq.Thread.sortBy(this.value);">\
	 <option value="hot" selected="selected">Popular now</option>\
	 <option value="best" >Best Rating</option>\
	 <option value="newest" >Newest first</option>\
	 <option value="oldest" >Oldest first</option>\
	 </select>\
	 &nbsp;\
	 </span>\
	 <span class="dsq-item-cp"><a href="http://scobleizer.disqus.com/should_services_charge_8220super_users8221/">Community Page</a>&nbsp;&nbsp;&nbsp;</span>\
	 <span class="dsq-item-subscribe">\
	 <img src="http://media.disqus.com/images/embed/email.png" style="width:12px;height:12px;vertical-align:middle">\
	 <span id="dsq-subscribe">\
	 <a href="#" onclick="Dsq.Thread.subscribe(1); return false">Subscribe by email</a>\
	 </span>\
	 </span>\
	 </div>\
	 <div id="dsq-alerts">\
	 <p>Comments for this page are closed.</p>\
	 </div>\
		';

		

		
		if (Dsq.jsonData.request.is_moderator) { 
			html = ' \
			<div class="dsq-alert-message dsq-upgrade-message"> \
				<strong>Disqus upgrade available.</strong> Hi ' + Dsq.jsonData.request.display_username + ', this message is being displayed to you because you are a moderator of this site. <a href="#" onclick="Dsq.$(\'dsq-upgrade-message\').style.display=\'block\';this.style.display=\'none\';return false">Click here for details.</a> \
				<div style="display:none; margin-top:10px;" id="dsq-upgrade-message"> \
					A new theme is available with added features. <a href="http://disqus.com/comments/settings/' + Dsq.jsonData.forum.url + '/?p=customize">To change your theme, click here</a> and choose the theme Narcissus. \
					If you do not upgrade, you are missing out on features such as: real-time commenting, new sign-in integrations, and an upgrade interface. \
					<strong>This message will automatically go away in one week.</strong> \
				</div> \
			</div> \
			' + html; 
		}
		return html;
	};

	this.footer = function() {
		var html = Dsq.Templates.pagination();

		
			html += Dsq.Templates.authPost();
		

		html += Dsq.Templates.reactions();

		
			html += Dsq.Templates.trackbacks();
		

		return html;
	};

	this.pagination = function() {
		var html = '';
		
		if (Dsq.$('dsq-pagination')) { Dsq.$('dsq-pagination').innerHTML = ''; }
		if (!Dsq.jsonData.thread.paginate) { return ''; }

		//
		// TODO: num_paginator still uses the template tag for pagination, 
		// 		while append_paginator does it all in JavaScript.
		//		This should all be in JavaScript.
		//

		if (Dsq.jsonData.thread.num_pages > 1 && Dsq.jsonData.request.page < Dsq.jsonData.thread.num_pages) {
			html = ' \<a class="dsq-paginate-append-text" href="#" onclick="Dsq.Thread.paginate(Dsq.jsonData.request.page + 1, this); return false">Show more comments...</a>\
	 <button type="button" class="dsq-button-small dsq-paginate-append-button" onclick="Dsq.Thread.paginate(Dsq.jsonData.request.page + 1, this);">Load more comments</button>\
			';
		}
		
		if (Dsq.$('dsq-pagination')) {
			Dsq.$('dsq-pagination').innerHTML = html;
			return '';
		} else {
			return '<div id="dsq-pagination" class="dsq-pagination">' + html + '</div>';
		}
	};

	this.trackbacks = function() {
		var html = '';

		if(typeof DsqLocal != 'undefined' && DsqLocal.trackback_url && DsqLocal.trackbacks) {
			var trackbacks = DsqLocal.trackbacks;
			var trackback_url = DsqLocal.trackback_url;
		} else {
			var trackbacks = [
			
			
			];
			var trackback_url = 'http://scobleizer.disqus.com/should_services_charge_8220super_users8221/trackback/';
		}

		html += '<div class="dsq-item-trackback">Trackback URL&nbsp;&nbsp;<input class="dsq-trackback-url" onclick="this.select()" readonly="true" value="' + trackback_url + '"></div>';

		if(trackbacks.length) {
			html += '<ul id="dsq-references">'
			for(var i = 0; i < trackbacks.length; i++) {
				var trackback = trackbacks[i];
				html += '<li><cite><a href="' + trackback.author_url + '" rel="nofollow">' + trackback.author_name + '</a></cite> \
						<p class="dsq-meta">' + trackback.date + '</p> \
						<p class="dsq-content">' + trackback.excerpt + '</p></li>';
			}
			html += '</ul>';
			html = '<h3 class="dsq-h3-trackbacks">Trackbacks</h3>' + html;
		}

		return html;
	}

	this.showRetweets = function(id, limit, element_id /* Optional */) {
		var source, html = '';

		for (var i = 0, reaction; reaction = Dsq.jsonData.reactions[i]; i++) {
			if (reaction.id === id) {
				source = reaction.retweets;
			}
		}

		if (source) {
			if (limit === 0) {
				limit = source.length;
			}

			for (var j = 0; j < limit; j++) {
				var rt = source[j];
				html += '<a href="' + rt.url + '">' + rt.author_name + '</a>'	+ ((j === (limit - 1)) ? '.' : ', ');
			}
		}

		if (element_id === undefined) {
			return html;
		}

		var element = document.getElementById(element_id);
		element.innerHTML = html;
		return element;
	};

	this.showMoreReactions = function(reactions, has_more, start, limit) {
		var link = document.getElementById('dsq-show-more-reactions');
		var container = link.parentNode;
		container.removeChild(link);

		for (var i = 0, reaction; reaction = reactions[i]; i++) {
			var el = Dsq.Templates.generateReactionHTML(reaction);
			if (el) {
				container.innerHTML += el;
			}
		}

		if (has_more) {
			var d = Dsq.jsonData.settings.disqus_url;
			var f = Dsq.jsonData.forum.url;
			var t = Dsq.jsonData.thread.id;
			var s = start;
			var l = limit;

			var handler = 'Dsq.Utils.execScript(\'' + d + '/forums/' + f + '/more_reactions.js?t=' + t + '&s=' + s + '&l=' + l + '\', true); return false;';
			container.innerHTML += '<li id="dsq-show-more-reactions"><a href="#" onclick="' + handler + '">Show more reactions</a></li>';
		}
	};

	this.generateReactionHTML = function(reaction) {
		if (reaction.body === null || reaction.body == '') {
			return;
		}

		if (reaction.author_name === '') {
			reaction.author_name = '&nbsp;';
		}

		if (reaction.url === '') {
			reaction.url = reaction.get_service_url;
		}

		/* Reaction HTML begins */
		var item = '<li class="dsq-reaction" id="dsq-reaction-' + reaction.id + '">'
			+ '<div class="dsq-reaction-header">'
			+ '<div class="dsq-header-avatar">';

		if (reaction.author_url && reaction.author_url !== '') {
			item += '<a target="_blank" href="' + reaction.author_url +'">';
		} else {
			item += '<a target="_blank" href="#" onclick="return false;">';
		}

		if (reaction.avatar_url && reaction.avatar_url !== '') {
			item += '<img src="' + reaction.avatar_url + '"/>';
		} else {
			item += '<img src="' + Dsq.jsonData.media_url + '/images/noavatar32.png"/>';
		}

		var service_icon = (reaction.get_service_name == 'trackback' || reaction.get_service_name == 'pingback' ? 'rss' : reaction.get_service_name.replace(' ', ''));
		item += '<img class="dsq-service-icon" src="' + Dsq.jsonData.media_url + '/images/reactions/services/' + service_icon + '.png"/>'
			+ '</a></div>'
			+ '<cite><span>' + reaction.author_name + '</span></cite>'
			+ '<span class="dsq-header-meta"><a class="dsq-header-time">' + reaction.date_created + '</a></span>'
			+ '</div><div class="dsq-reaction-body">'
			+ '<div class="dsq-reaction-message">' + reaction.body + '</div>'
			+ '<div class="dsq-reaction-footer">From <a class="dsq-service-name" target="_blank" href="' + reaction.url + '">' + reaction.get_service_name + '</a> '
			+ 'via <a href="' + reaction.source_url + '">' + (reaction.source == 'backtype' ? 'BackType' : 'UberVU') + '</a>'
			+ (Dsq.jsonData.request.is_moderator || Dsq.jsonData.request.is_global_moderator ? '&nbsp;&bull;&nbsp;<a class="dsq-hide-reaction" href="#" onclick="Dsq.Reaction.hide(' + reaction.id + '); return false;">Hide</a>' : '') + '</div></div>';

		if(reaction.retweets) {
			var num_retweets = reaction.retweets.length;
			if (num_retweets > 0) {
				item += '<div class="dsq-reaction-retweets">';
				if (num_retweets == 1) {
					item += 'One more retweet from <a href="' + reaction.retweets[0].url + '">'  + reaction.retweets[0].author_name + '</a>';
				} else {
					item += (num_retweets + ' more retweets from ');

					item += '<span id="dsq-reaction-retweets-' + reaction.id + '">';
					var n_tweets = (num_retweets > 15) ? 15 : num_retweets;
					item += Dsq.Templates.showRetweets(reaction.id, n_tweets);

					if (n_tweets != num_retweets) {
						item += '</span> <a onclick="Dsq.Templates.showRetweets(' + reaction.id + ', 0, \'dsq-reaction-retweets-' + reaction.id + '\');'
							+ 'this.parentNode.removeChild(this); return false;" href="#">Show all</a>';
					}
				}
				item += '</div>';
			}
		}

		item += '</li>'; /* Reaction HTML ends */
		return item;
	};

	this.reactions = function() {
		var html, reaction;

		if (Dsq.jsonData.reactions === undefined || Dsq.jsonData.reactions.length === 0) {
			return '';
		}

		html = '';
		for (var i = 0; reaction = Dsq.jsonData.reactions[i]; i++) {
			var item = Dsq.Templates.generateReactionHTML(reaction);
			if (item) {
				html += item;
			}
		}

		if (Dsq.jsonData.has_more_reactions) {
			var d = Dsq.jsonData.settings.disqus_url;
			var f = Dsq.jsonData.forum.url;
			var t = Dsq.jsonData.thread.id;
			var s = Dsq.jsonData.reactions_start;
			var l = Dsq.jsonData.reactions_limit;

			var handler = 'Dsq.Utils.execScript(\'' + d + '/forums/' + f + '/more_reactions.js?t=' + t + '&s=' + s + '&l=' + l + '\', true); return false;';
			html += '<li id="dsq-show-more-reactions"><a href="#" onclick="' + handler + '">Show more reactions</a></li>';
		}

		return '<h3 class="dsq-h3-reactions">Reactions</h3><ul id="dsq-reactions" class="dsq-reactions">' + html + '</ul>';
	};
	
	this.missingPermissions = function() {
		return '	<p>Comments for this page are closed.</p>\n';
	};

	//
	// Post
	//

	this.prependPost = function(post_id) {
		var html = '<div id="comment-' + post_id + '"></div>';
		return html;
	};

	this.appendPost = function(post_id) {
		var html = '<div id="dsq-comment-reply-' + post_id + '"></div>';
		return html;
	};

	this.postPrependHeader = function(post_id) {
		var _meta = Dsq.jsonData.posts[post_id];
		var userData = Dsq.jsonData['users'][_meta.user_key];

		var _includeServices = function() {
			var userServices = Dsq.Post.getUserServices(null, post_id);
			var html = '';
			var hiddenThreshold = 3; // Define # of services to show before stuffing them in hidden div

			for(var i = 0; i < userServices.length; i++) {
				html +=
				(i == hiddenThreshold
					? '<li id="dsq-drop-hidden-' + post_id +'" class="dsq-drop-hidden"><ul>'
					: '')
				+ '<li class="dsq-drop-services"> \
					<a class="dsq-service-' + userServices[i].name.toLowerCase() + '" href="' + userServices[i].url + '" target="_blank"> \
						<img src="' + Dsq.jsonData.media_url + '/images/embed/services/' + userServices[i].name.toLowerCase() + '.png" alt="' + userServices[i].name.toLowerCase() + '">'
					+ userServices[i].name
					+ '</a> \
				</li>';
			}

			if(i >= hiddenThreshold) {
				html += '</ul></li> \
				<li id="dsq-drop-more-' + post_id + '" class="dsq-drop-more"><a href="#" onclick="Dsq.Post.dropProfileMore(this, '+ post_id + '); return false"><small>&#9660;</small></a></li> \
				';
			}
			return html;
		};

		return ' \
			<div class="dsq-header-avatar" id="dsq-header-avatar-' + post_id + '" onmouseover="Dsq.Post.dropProfile(' + post_id + ')"> \
				<a id="dsq-avatar-' + post_id + '" class="dsq-avatar" href="' + userData.url + '" onclick="Dsq.Popup.popProfile(' + post_id + '); return false;">'
			+ (Dsq.jsonData.forum.show_avatar
				? '<img src="' + Dsq.jsonData.users[_meta.user_key].avatar + '" alt="" />'
				: '')
			+ '</a>'
			+ '</div> \
		';
	};

	this.postAppendHeader = function(post_id) {
		var _meta = Dsq.jsonData.posts[post_id];

		return ''
			+ (_meta.author_is_moderator
				? '<img class="dsq-mod-star" src="http://media.disqus.com/images/bullet-star.png" title="Moderator" alt="" />'
				: '')
			+ '<span class="dsq-header-meta"> \
				<a id="dsq-time-' + post_id + '" class="dsq-header-time" href="#comment-' + post_id + '" title="Permalink">' + _meta.date + '</a> \
			</span>';
	};

	this.preBody = function(post_id) {
		return '';
	}

	this.postBody = function(post_id) {
		// TODO: Deprecate flagging conditional
		var _meta = Dsq.jsonData.posts[post_id];
		return ''
			+ (_meta.edited
				? '<p class="dsq-editedtxt">(Edited by a moderator)</p>'
				: '')
			;
	};

	this.postFooter = function(post_id) {
		// TODO: Use media should be conditional
		var _meta = Dsq.jsonData.posts[post_id];
		if(_meta.killed) { return ''; }

		return ' \
			<div class="dsq-comment-footer" id="dsq-comment-footer-' + post_id + '"> \
				<div id="dsq-points-' + post_id + '" class="dsq-likedtxt">'
				+ (_meta.points
					? _meta.points + Dsq.Utils.pluralize(_meta.points, ' person', ' people') + ' liked this comment.'
					: '')
				+ '</div>'
				+ '<ul class="dsq-comment-options dsq-list-style">'
				+ (_meta.votable
					? '<li class="dsq-list-first dsq-rate" id="dsq-rate-cont-' + post_id + '">'
					+ (!_meta.up_voted
						? '<a href="#" onclick="Dsq.Post.rate(this, ' + post_id + ', 1); return false;">Like</a>'
						: 'You liked this.') + '</li>'
					: '')
				+ '<li class="dsq-report' + (!_meta.votable ? ' dsq-list-first' : '') + '" id="dsq-post-report-' + post_id + '"><a href="#" class="dsq-post-report" onclick="Dsq.Post.report(' + post_id + ', false); return false;">Report</a></li> \
				</ul> \
				<ul class="dsq-list-style">'
				+ (_meta.can_reply
					? '<li class="dsq-list-first"><a href="#" id="dsq-reply-link-' + post_id +'" onclick="Dsq.Post.toggleReply(this, ' + post_id +'); return false;">Reply</a></li>'
					: '')
				+ (_meta.can_reply && !_meta.has_replies && _meta.from_request_user
					? '<li id="dsq-edit-el-' + post_id + '"><a id="dsq-edit-link-' + post_id + '" href="#" onclick="Dsq.Post.edit(this, ' + post_id + '); return false;">Edit</a></li>'
					: '')
				+ '<li class="' + (!_meta.can_reply ? 'dsq-list-first' : '') + '" id="dsq-more-el-' + post_id + '"><a id="dsq-more-link-' + post_id + '" href="#" onclick="Dsq.Post.showMenu(this, ' + post_id + ', \'more\'); return false">More <small>&#9660;</small></a></li>'
				+ (Dsq.jsonData.forum.use_media
					? '<li id="dsq-media-el-' + post_id +'" style="display:none"><a id="dsq-media-link-' + post_id + '" href="#" onclick="Dsq.Post.showMenu(this, ' + post_id + ', \'media\'); return false">Use Media <small>&#9660;</small></a></li>'
					: '')
				+ '</ul>'
				+ '<div id="dsq-reply-bar-' + post_id + '" class="dsq-reply-bar" style="display:none"> \
						<div id="dsq-reply-bar-items-' + post_id + '" class="dsq-reply-bar-items"> \
						</div> \
						<div id="dsq-reply-bar-auth-' + post_id + '" class="dsq-reply-bar-auth"> \
							 \
								 \
								 	<a href="#" class="dsq-help dsq-reply-req-opt" title="You are commenting as a Guest. You may choose to log into an existing DISQUS Profile, your Facebook, Twitter or OpenID account to comment on Scobleizer" onclick="Dsq.Popup.helpBadges(); return false">Optional:</a> \
								 \
								<img class="dsq-login-icon" src="http://media.disqus.com/images/dsq-favicon-16x16.png" alt="" /> \
								<a id="dsq-reply-login-' + post_id + '" href="http://disqus.com/profile/login/?next=article:18349417" onclick="Dsq.Popup.login(); return false">Login</a> \
								 \
									&nbsp;or&nbsp; \
									<img class="fb_login_image" src="http://static.ak.fbcdn.net/images/fbconnect/login-buttons/connect_light_small_short.gif" alt="Facebook Connect"/> \
									<a href="#" onclick="FB.Connect.requireSession(DisqusFbcParentController.onLogin); return false;">Connect</a> \
								 \
								&nbsp;or&nbsp; \
									<img src="http://media.disqus.com/images/twitter-signin-icon.png" alt="" /> \
									<a href="#" onclick="Dsq.Twitter.startTwitterConnect(); return false">Sign-in</a> \
								 \
								 \
							 \
						</div> \
					</div> \
					<div id="dsq-reply-' + post_id + '"></div> \
			</div> \
		';
	};

	//
	// Iframes
	//

	this._makeAttributes = function(attributes) {
		// Makes a tag attributes string out of an object.
		// Caller is responsible for making sure nothing needs to be escaped.
		var result = [];
		for (key in attributes) {
			result.push(' ' + key + '="' + attributes[key] + '"');
		}
		result = result.join('');
		return result;
	};

	this._frameGeneric = function(base_url, params, attributes) {
		if(typeof(disqus_callback_params) == 'undefined') {
			disqus_callback_params = '';
		}

		var default_params = {
			// TODO: These should be moved to Dsq.jsonData.
			'f'				: 'scobleizer',
			't'				: 'should_services_charge_8220super_users8221',
			// Do we need encodeURIComponent here?
			'ifrs'			: encodeURIComponent(disqus_iframe_css),
			'to_redirect'	: encodeURIComponent(window.location),
			'cbp'			: disqus_callback_params,
			'ff'			: Dsq.Thread.ff,
			'fc'			: Dsq.Thread.fc,
			'ac'			: Dsq.Thread.ac,
			'default_text'	: disqus_default_text
		};

		base_url += '?' + (new Date()).getTime();
		// Add params to default_params.
		if(params) {
			for(var key in params) {
				if(params.hasOwnProperty(key)) {
					default_params[key] = encodeURIComponent(params[key]);
				}
			}
		}
		// Build querystring.
		for(var key in default_params) {
			if(default_params[key] && default_params.hasOwnProperty(key)) {
				base_url += '&' + key + '=' + default_params[key];
			}
		}

		return [
			'<iframe marginwidth="0" marginheight="0" hspace="0" vspace="0" frameborder="0"',
			(' allowtransparency="true" src="' + base_url + '"'),
			this._makeAttributes(attributes),
			'</iframe>'].join('');
	};

	this.frameLogin = function(opt_attributes) {
		var params = {};
		var base_url = 'http://disqus.com/embed/login.html';
		var attributes = opt_attributes || {};
		attributes['class'] = 'dsq-post-login';

		if(typeof disqus_frame_theme != 'undefined') {
			params['theme'] = disqus_frame_theme;
		}
		return this._frameGeneric(base_url, params, attributes);
	};

	this.frameReply = function(post_id, extra_params, attributes) {
		// Returns the HTML for a reply iframe. Called by Dsq.Iframes.setReplyIframeToContainer
		var _meta = (typeof post_id != 'undefined') ? Dsq.jsonData.posts[post_id] : false;
		var base_url = Dsq.Urls.REPLY;
		var params = {
			'def_email'		: disqus_def_email,
			'def_name'		: disqus_def_name
		};
		if(extra_params) {
			for(var key in extra_params) {
				if(extra_params.hasOwnProperty(key)) {
					params[key] = extra_params[key];
				}
			}
		}
		if(_meta) {
			params['parent_post'] = post_id;
		}
		if(typeof disqus_per_page != 'undefined') {
			params['per_page'] = disqus_per_page;
		}
		if(typeof disqus_frame_theme != 'undefined') {
			params['theme'] = disqus_frame_theme;
		}
		if(Dsq.jsonData.request.is_authenticated) {
			attributes['class'] += '-authenticated';
		}
		return this._frameGeneric(base_url, params, attributes);
	};

	this.frameEdit = function(post_id) {
		var _meta = (typeof post_id != 'undefined') ? Dsq.jsonData.posts[post_id] : false;
		var base_url = 'http://disqus.com/embed/edit.html';
		var params = {
			'p' : post_id
		};
		return this._frameGeneric(base_url, params, {'class': 'dsq-post-edit', 'name': 'dsq-edit_' + post_id + '-frame'});
	};

	//
	// Menus
	//

	this.menuMore = function(post_id) {
		// TODO: "Remove post" button should hide menu.
		var _meta = Dsq.jsonData.posts[post_id];
		var userData = Dsq.jsonData['users'][_meta.user_key];
		return ' \
			<li><a href="#comment-' + post_id + '" onclick="Dsq.Popup.permalink(' + post_id + ')">Link</a></li> \
			<li><a href="#" onclick="Dsq.Popup.popProfile(' + post_id + '); return false;">Profile</a></li>'
	+ (Dsq.jsonData.request.is_moderator || Dsq.jsonData.request.is_global_moderator
		? '	<li class="dsq-menu-sep"></li>' + (_meta.email ? '<li class="dsq-admin-email">' + _meta.email + '</li>' : '')
		+ '	<li class="dsq-admin-ip">' + _meta.ip + '</li> \
			<li class="dsq-menu-sep"></li>'
		+ (Dsq.jsonData.request.moderator_can_edit
			? ' <li class="dsq-admin-edit"><a href="#" onclick="Dsq.Post.edit(this, ' + post_id + '); return false;">Edit Comment</a></li>'
			: '')
		+ ' <li class="dsq-remove"><a href="#" onclick="Dsq.Post.removePost(' + post_id + ', 1); return false;">Remove Comment</a></li> \
			<li class="dsq-report-spam"><a href="#" onclick="Dsq.Post.reportSpam(' + post_id + '); return false;">Mark Spam</a></li> \
			<li class="dsq-block-user"><a href="#" onclick="Dsq.Popup.blacklist(' + post_id + '); return false">Block User</a></li>'
		: '');
	};

	this.menuMedia = function(post_id) {
		return ' \
			<li><a href="#" onclick="Dsq.Post.toggleMediaReply(this, ' + post_id + ', \'seesmic\'); return false;">Record video</a></li> \
		';
	};

	this.dropProfile = function(post_id) {
		var _meta = Dsq.jsonData.posts[post_id];
		var userData = Dsq.jsonData['users'][_meta.user_key];

		var _includeServices = function() {
			var userServices = Dsq.Post.getUserServices(null, post_id);
			var html = '';
			var hiddenThreshold = 3; // Define # of services to show before stuffing them in hidden div

			for(var i = 0; i < userServices.length; i++) {
				html +=
				(i == hiddenThreshold
					? '<li id="dsq-drop-hidden-' + post_id +'" class="dsq-drop-hidden"><ul>'
					: '')
				+ '<li class="dsq-drop-services"> \
					<a class="dsq-service-' + userServices[i].name.toLowerCase() + '" href="' + userServices[i].url + '" target="_blank"> \
						<img src="' + Dsq.jsonData.media_url + '/images/embed/services/' + userServices[i].name.toLowerCase() + '.png" alt="' + userServices[i].name.toLowerCase() + '">'
					+ userServices[i].name
					+ '</a> \
				</li>';
			}

			if(i >= hiddenThreshold) {
				html += '</ul></li> \
				<li id="dsq-drop-more-' + post_id + '" class="dsq-drop-more"><a href="#" onclick="Dsq.Post.dropProfileMore(this, '+ post_id + '); return false"><small>&#9660;</small></a></li> \
				';
			}
			return html;
		};


		var menu = '<li class="dsq-drop-showlnk"><a href="#" onclick="Dsq.Popup.popProfile(' + post_id + '); return false;">Expand &#8663;</a></li>';
		var pointsMessage = '';
		if (userData['registered']) {
			pointsMessage = 'with ' + userData['points'] + ' points (more points are better).';
		}

		if (userData['is_remote']) {
			var domain = userData['remote_domain_name'];
			menu += '<li class="dsq-drop-badge" title="' + userData['display_name'] + ' is a ' + domain + ' user ' + pointsMessage + '" onclick="Dsq.Popup.helpBadges()">';
			menu += '<span class="dsq-badge-' + domain.toLowerCase() + '">' + domain + '</span></li>';
		} else if (userData['registered']) {
			if (userData['verified']) {
				menu += '<li class="dsq-drop-badge" title="' + userData['display_name'] + ' has a verified commenter profile ' + pointsMessage + '" onclick="Dsq.Popup.helpBadges()">';
				menu += '<span class="dsq-badge-verified">Verified</span></li>';
			} else {
				menu += '<li class="dsq-drop-badge" title="' + userData['display_name'] + ' has a registered, but unverified, commenter profile ' + pointsMessage + '" onclick="Dsq.Popup.helpBadges()">';
				menu += '<span class="dsq-badge-registered">Registered</span></li>';
			}
		} else {
			menu += '<li class="dsq-drop-badge" title="' + userData['display_name'] + ' has not claimed this commenter profile." onclick="Dsq.Popup.helpBadges()"><span class="dsq-badge-guest">Guest</span></li>';
		}

		menu += _includeServices();
		return menu;
	};

	//
	// Popups
	//

	this._popupGeneric = function(content) {
		return ' \
		<div class="dsq-popup-content"> \
			<div class="dsq-popup-top"></div> \
			<div class="dsq-popup-body" class="clearfix"> \
				<div class="dsq-popup-body-padding"> \
					<div class="dsq-popup-header"> \
						<a class="dsq-close-link" href="#" onclick="Dsq.Popup._closePopup(null, true); return false"><img src="http://media.disqus.com/images/modal-close.png" alt="" /></a>'
						+ content['header']
					+ '</div>'
					+ content['body']
					+ '<div class="powered-by"><a href="http://disqus.com/comments/">Powered by <img src="http://media.disqus.com/images/embed/disqus-logo.png" alt="Disqus Comments" style="margin-bottom:-5px" /></a></div> \
				</div> <!-- padding --> \
			</div> <!-- body --> \
			<div class="dsq-popup-bottom"></div> \
		</div> \
		';
	};

	this.popupProfile = function(user_key) {
		var userServices = Dsq.Post.getUserServices(user_key, null);
		var userData = Dsq.jsonData['users'][user_key];
		var headerHtml = '';
		var bodyHtml = '';
		var content = {};

		var _includeServices = function() {
			var html = '';
			for(var i = 0; i < userServices.length; i++) {
				html +=
				(i == 0
					? '<h4>Connections</h4><ul>'
					: '')
				+ '<li> \
					<img src="' + Dsq.jsonData.media_url + '/images/embed/services/' + userServices[i].name.toLowerCase() + '.png" alt="' + userServices[i].name.toLowerCase() + '" title="' + userServices[i].name.toLowerCase() + '" /> \
					<a class="dsq-service-' + userServices[i].name.toLowerCase() + '" href="' + userServices[i].url + '" target="_blank">'
					+ userServices[i].name
					+ '</a> \
				</li>'
				+ (i+1 == userServices.length ? '</ul>' : '');
			}
			return html;
		};

		headerHtml = ' \
			<table> \
				<tr> \
					<td> \
						<a class="dsq-profile-userurl" href="' + userData.url + '"><img class="dsq-popup-profile-avatar" src="' + userData['avatar'] + '" alt="" /></a> \
					</td> \
					<td> \
						<div class="dsq-popup-profile-user"> \
							<h3>' + userData['display_name'] + '</h3> \
							<div class="dsq-popup-profile-user-stats" id="dsq-popup-profile-user-stats-' + user_key + '">Loading...</div> \
						</div> \
					</td> \
				</tr> \
			</table> \
		';

		bodyHtml = ' \
			<div class="dsq-popup-profile-state"> \
				This is a&nbsp;<span class="'
					+ (userData['registered']
						? (userData['verified']
							? ' dsq-badge-verified'
							: (userData['is_remote']
								? ' dsq-badge-' + userData['remote_domain_name'].toLowerCase()
								: ' dsq-badge-registered')
							)
							: ' dsq-badge-guest') + '">'
			+ (userData['registered']
				? (userData['verified']
					? 'Verified'
					: (userData['is_remote']
						 ? userData['remote_domain_name']
						 : 'Registered')
					)
				: 'Guest')
			+ '</span>&nbsp;commenter profile.'
			+ '&nbsp;<a class="dsq-profile-userurl" href="' + userData.url + '"><strong>View more comments </strong></a>'
			+ (!userData['points']
				? '<p class="dsq-popup-notice">If this is you, <a href="http://disqus.com/profile" target="_blank">claim it now</a> to manage your comments.</p>'
				: '')
			+ ((userData['registered'] && !userData['verified'] && (Dsq.jsonData.request.username && (Dsq.jsonData.request.username == userData['username'])) && !userData['is_remote'])
				? '<p class="dsq-popup-notice"><strong>Alert</strong>: You have not verified this account. <a href="http://disqus.com/verify">Verify it now.</a></p>'
				: '')
			+ '</div> \
			<div id="dsq-profile-status-' + user_key + '" class="dsq-popup-profile-status" style="display:none"></div> \
			<div class="dsq-popup-profile-snapshot"> \
				<table> \
					<tr> \
						<td> \
							<div id="dsq-popup-profile-active-sites-wrapper-' + user_key + '"> \
								<h4>Most active sites</h4> \
								<ul id="dsq-popup-profile-active-sites-' + user_key + '"> \
									<li>Loading...</li> \
								</ul> \
							</div> \
						</td> \
						<td>'
							+ _includeServices()
							+ '<div id="dsq-popup-profile-moderated-wrapper-' + user_key + '"> \
								<h4>Moderator of</h4> \
								<ul id="dsq-popup-profile-moderated-' + user_key + '"> \
									<li>Loading...</li> \
								</ul> \
							</div> \
						</td> \
					</tr> \
				</table> \
			</div> \
			';

		content = {
			'header': headerHtml,
			'body': bodyHtml
		};

		return this._popupGeneric(content);
	};

	this.popupReblog = function() {
		var headerHtml = '';
		var bodyHtml = '';
		var content = {};

		headerHtml = ' \
			<cite><span>Reblog this comment</span></cite> \
		';

		bodyHtml = ' \
			<div id="dsq-reblog-form" class="dsq-reblog-form"> \
			</div> \
		';

		content = {
			'header': headerHtml,
			'body': bodyHtml
		};

		return this._popupGeneric(content);
	};

	this.popupModal = function(title, message) {
		var headerHtml = '';
		var bodyHtml = '';
		var content = {};

		headerHtml = ' \
			<h3>' + title + '</h3> \
		';

		bodyHtml = message;

		content = {
			'header': headerHtml,
			'body': bodyHtml
		};

		return this._popupGeneric(content);
	};

	this.alertContent = function(name, post_id) {
		var alert = {
			'post_not_approved': {
				'title': 'Comment awaiting approval by a moderator',
				'message': 'Thanks for posting. Your comment must be approved by a moderator before appearing here.'
			},
			'post_has_profile': {
				'title': 'Use your existing commenter profile',
				'message': 'You have just posted your commment as a <span class="dsq-badge dsq-badge-guest">Guest</span>, but you may already have a <span class="dsq-badge dsq-badge-registered">Registered</span> commenter profile.<br /><br /><a href="http://disqus.com/claim">Log in and claim this comment!</a>'
			}
		};
		return alert[name] || false;
	};

	//
	// Actions
	//

	this.voted = function(post_id, points, vote) {
		// Update number of points
		Dsq.$('dsq-points-' + post_id).innerHTML = points + Dsq.Utils.pluralize(points, ' person', ' people') + ' liked this comment.';

		// Update link text
		if(vote) {
			Dsq.$('dsq-rate-cont-' + post_id).innerHTML = 'You liked this.';
		}
	};

	this.subscribed = function(status) {
		var title, message;

		if(status) {
			title = 'Subscribed!';
			message = 'You have subscribed to this comment thread. New comments will be sent directly to your email inbox, where you may read and respond by email.';
			Dsq.$('dsq-subscribe').innerHTML = ' \
				<a href="#" onclick="Dsq.Thread.subscribe(0); return false">Unsubscribe</a> \
			';
		} else {
			title = 'Unsubscribed';
			message = 'You have unsubscribed to this comment thread. New comments will no longer be sent to your email inbox.';
			Dsq.$('dsq-subscribe').innerHTML = ' \
				<a href="#" onclick="Dsq.Thread.subscribe(1); return false">Subscribe by email</a> \
			';
		}

		Dsq.Popup.popModal(message, title);

	};
	
	this.highlighted = function() {
		Dsq.Popup.popModal('This comment has been highlighted.', 'Highlighted comment');
	};

	//
	// Media
	//

	this.mediaSeesmic = function(id, thumb) {
		return ' \
			<div id="dsq-seesmic-' + id + '_preview" class="dsq-seesmic-preview"><a href="http://www.seesmic.com/video/' + id + '" target="_blank" class="see_link">&nbsp;</a> \
				<div style="display:block;width:160px; height:120px; border:none; background-image:url(http://t.seesmic.com/thumbnail/' + thumb + ')"> \
					<div id="dsq-seesmic-' + id + '_hide" class="seePlayOverlay" style="display:none;"><img onclick="see_play_video(\'' + id + '\',false)" src="http://media.disqus.com/images/seesmic/stopOverlay.png" width="50" height="50" style="cursor:pointer; cursor:hand; padding-top: 30px; padding-left: 50px" alt="" /></div> \
					<div id="dsq-seesmic-' + id + '_show" class="seePlayOverlay"><img onclick="see_play_video(\'' + id + '\',true)" src="http://media.disqus.com/images/seesmic/playOverlay.png" width="50" height="50" style="cursor:pointer; cursor:hand; border:none; padding-top: 30px; padding-left: 50px" alt="" /></div> \
				</div> \
			</div> \
			<div id="' + id + '_content" style="display:block; width:100%; padding-top:5px"></div> \
		';
	};

	//
	// Callbacks
	//

	this.postComment_onSuccess = function(parent_post_id) {
		// Increment post count
		var num_posts = Dsq.$('dsq-num-posts');
		var total_posts = Dsq.$('dsq-total-posts');
		
		if (num_posts) { 
			num_posts.innerHTML = parseInt(num_posts.innerHTML) + 1;
		}
		if (total_posts) { 
			total_posts.innerHTML = parseInt(total_posts.innerHTML) + 1;
		}
	};
};
// Dsq.Templates


/**
 * Dsq.Post
 */
Dsq.Post = new function() {
	this.openedMenu = {};
	this.menuEventListener = null;
	this.stateReplyToggled = {};
	this.stateEditToggled = {};
	this.stateRecordLink = {};

	/**
	 * Inserts a new post into the document.
	 *
	 * @param after_id {Number}	Insert a post before specified id.  If after_id
	 *							evaluates to false, then post in the front.  If
	 *							after_id is -1, post at the end.
	 */
	this.insert = function(after_id, id, message, author) {
		// Skeleton template from thread_posts.html.
		var skeleton = ' \
			<li id="dsq-comment-%(id)s"> \
				<div id="dsq-comment-header-%(id)s" class="dsq-comment-header"> \
					<cite id="dsq-cite-%(id)s" class="dsq-comment-cite"> \
						<a id="dsq-author-user-%(id)s" href="%(author_url)s" target="_blank" rel="nofollow">%(author_name)s</a> \
					</cite> \
				</div> \
				<div id="dsq-comment-body-%(id)s" class="dsq-comment-body"> \
					<div id="dsq-comment-message-%(id)s" class="dsq-comment-message">%(message)s</div> \
				</div> \
			</li> \
		';
		var _meta = Dsq.jsonData.posts[id];
		var _user_meta = Dsq.jsonData.users[_meta.user_key];
		var markup = Dsq.Utils.interpolate(skeleton, {
			id: id,
			message: message,
			author_url: _user_meta.blog,
			author_name: _user_meta.display_name
		});
		var div = document.createElement('div');
		markup = markup.replace(Dsq.COMMENTS_RE, Dsq.CommentsHandler);
		div.innerHTML = markup;

		if (after_id === -1) {
			Dsq.$('dsq-comments').appendChild(div);
		} else if (!after_id) {
			Dsq.$('dsq-comments').insertBefore(div, Dsq.$('dsq-comments').firstChild);
		} else if (Dsq.$('dsq-comment-' + after_id)) {
			// Get next node after "after_id", so we can insert before it.
			// If "after_id" is the last comment, the target node is the
			// last node.
			
			// var append_post_id = Dsq.Templates.appendPost(after_id).replace('<div id="','').replace('"></div>', '');
			var append_post_id = 'dsq-append-post-' + after_id;
			var node = Dsq.$(append_post_id);
			while (node = node.nextSibling) {
				if (!node || node.nodeType == 1) { // 1 == Node.ELEMENT_NODE
					break;
				}
			}
			if (!node) {
				node = Dsq.$(append_post_id);
			}
			node.parentNode.insertBefore(div, node);
		}
	};

	this.incrementPostCount = function() {
		
		var num_posts = Dsq.$('dsq-num-posts');
		var total_posts = Dsq.$('dsq-total-posts');

		if (num_posts) {
			num_posts.innerHTML = parseInt(num_posts.innerHTML, 10) + 1;
		}
		if (total_posts) {
			total_posts.innerHTML = parseInt(total_posts.innerHTML, 10) + 1;
		}
	}
	
	this.outlineComment = function(post_id) {
		Dsq.$('dsq-comment-' + post_id).className += ' dsq-comment-outline';
		setTimeout("(function () { Dsq.Post.clearOutlineComment(" + post_id + ") })()", 3000);
	};
	
	this.clearOutlineComment = function(post_id) {
		Dsq.$('dsq-comment-' + post_id).className = Dsq.$('dsq-comment-' + post_id).className.replace('dsq-comment-outline', '');
	};

	this.showMenu = function(el, id, name) {
		var anchorPos = Dsq.Utils.findPos(el);
		var menu = document.createElement('ul');

		if(this.openedMenu) {
			if(this.openedMenu.linkClicked) {
				this.openedMenu.linkClicked = false;
				return;
			}
		}

		switch(name) {
			case 'more':
				menu.innerHTML = Dsq.Templates.menuMore(id);
				break;
			case 'media':
				menu.innerHTML = Dsq.Templates.menuMedia(id);
				break;
			default:
				break;
		}

		// Add menu to document body
		menu.id = 'dsq-menu-' + id;
		menu.className = 'dsq-menu';
		Dsq.$b.appendChild(menu);

		// Position and show
		anchorPos[1] += 15;
		menu.style.left = anchorPos[0] + 'px';
		menu.style.top = anchorPos[1] + 'px';
		menu.style.display = 'block';

		// Set global reference
		this.openedMenu = {
			'el' : menu,
			'id' : id,
			'name' : name,
			'linkClicked' : false
		};

		// Set listener
		this.menuEventListener = Dsq.Utils.addEventListener(document, 'mouseup', this._hideMenu);
	};

	this._hideMenu = function(e) {
		var el = e.target || e.srcElement;
		var openedMenu = Dsq.Post.openedMenu.el;
		var id = Dsq.Post.openedMenu.id;

		if(!id) {
			var link = 'dsq-' + Dsq.Post.openedMenu.name + '-link';
		} else {
			var link = 'dsq-' + Dsq.Post.openedMenu.name + '-link-' + id;
		}

		if(!openedMenu) {
			return;
		}

		if(!Dsq.Popup.isClicked(e, openedMenu.id)) {
			openedMenu.style.display = 'none';
			Dsq.Utils.removeEventListener(Dsq.Post.menuEventListener);
			Dsq.Utils.deleteNode(openedMenu);

		} else {
			// Hide the menu if a link was clicked inside the menu.  We can't
			// completely remove the menu until the onclick event on the link
			// fires, but the menuEventListener will prevent multiple menus
			// from polluting the DOM.
			if(el && typeof el.href != 'undefined') {
				openedMenu.style.display = 'none';
				Dsq.Post.openedMenu.el = null;
			}
		}

		if(Dsq.Popup.isClicked(e, link)) {
 			Dsq.Post.openedMenu.linkClicked = true;
		}
	};


	this.getUserServices = function(user_key, id) {
		if(!user_key && id) {
			var _meta = Dsq.jsonData.posts[id];
			user_key = _meta.user_key;
		}
		var userData = Dsq.jsonData['users'][user_key];
		var userServices = [];

		// Keep a full list of supported services. This is the order they will display in the drop-profile.
		// Each service must have a corresponding case in _buildServiceUrl()
		var supportedServices = ['blog', 'twitter', 'facebook', 'tumblr'];

		function _buildServiceUrl(serviceName) {
			var data = userData[serviceName];
			var services = {
				blog:		function(d) { return d; },
				twitter:	function(d) { return d; },
				facebook:	function(d) { return d; },
				tumblr:		function(d) { return 'http://' + d + '.tumblr.com'; }
			};
			return services[serviceName](data);
		}

		for(var i = 0; i < supportedServices.length; i++) {
			if(userData[supportedServices[i]]) {
				var serviceUrl = _buildServiceUrl(supportedServices[i]);
				userServices.push({'name' : supportedServices[i], 'url' : serviceUrl});
			}
		}
		return userServices;
	}

	this.dropProfile = function(id) {
		var dp = Dsq.$('dsq-drop-profile-' + id);

		// IE6 needs JS to display/hide. All other browsers use CSS.
		if(dp) {
			if(Dsq.Utils.ie6) dp.style.display = (dp.style.display == 'inline') ? 'none' : 'inline';
			return false;
		} else {
			dp = document.createElement('ul');
		}

		dp.id = 'dsq-drop-profile-' + id;
		dp.className = 'dsq-drop-profile';

		if(Dsq.Utils.ie6) { dp.style.display = 'inline'; }

		var container = Dsq.$('dsq-header-avatar-' + id);
		dp.innerHTML = Dsq.Templates.dropProfile(id);
		container.appendChild(dp);
	};

	this.dropProfileMore = function(el, id) {
		var hiddenItems = Dsq.$('dsq-drop-hidden-' + id);

		hiddenItems.style.display = 'inline';
		el.parentNode.style.display = 'none';
	};

	this._updateReplyLinks = function(el, id) {
		// Update "reply / cancel" links based on state.
		var displayDict = {};

		if(id) {
			if(this.stateReplyToggled[id]) {
				el.innerHTML = 'Cancel';
				displayDict['media'] = 'inline';
				displayDict['edit'] = 'none';
			} else {
				el.innerHTML = 'Reply';
				displayDict['media'] = 'none';
				displayDict['edit'] = 'inline';
			}
		}

		for(var key in displayDict) {
			if(displayDict.hasOwnProperty(key)) {
				var	linkEl = Dsq.$('dsq-' + key + '-el-' + id),
					spacer = Dsq.$('dsq-' + key + '-spacer-' + id);

				if(linkEl) {
					linkEl.style.display = displayDict[key];
					if(spacer) spacer.style.display = displayDict[key];
				}
			}
		}
	};

	this._updateMediaLinks = function(el, id) {
		// Update "use media / cancel" links based on state.
		var appendId = (id) ? ('-' + id) : '';
		var link = Dsq.$('dsq-media-link' + appendId);

		if(this.stateRecordLink[id]) {
			link.innerHTML = 'Cancel Media';
			link.onclick = function() { Dsq.Post.toggleMediaReply(link, id); return false; };
		} else {
			link.innerHTML = 'Use Media <small>&#9660;</small>';
			link.onclick = function() { Dsq.Post.showMenu(link, id, 'media'); return false; };
		}
	};

	this.toggleReply = function(el, id) {
		// Create reply IFrame
		if (window.disqus_use_postmessage) {
			if (!this.stateReplyToggled[id]) {
				Dsq.$('dsq-reply-' + id).style.display = 'block';
				Dsq.$('dsq-reply-bar-' + id).style.display = 'block';
				// Create IFrame if it doesn't exist.
				if (!Dsq.frames['reply_' + id]) {
					var _meta = Dsq.jsonData.posts[id];
					Dsq.frames['reply_' + id] = new Dsq.ReplyFrame(Dsq.$('dsq-reply-frame-' + id), id);
					Dsq.frames['reply_' + id].init();
					Dsq.frames['reply_' + id].setState(id, _meta.depth);
				}
			} else {
				Dsq.$('dsq-reply-' + id).style.display = 'none';
				Dsq.$('dsq-reply-bar-' + id).style.display = 'none';
			}
		} else {
			// DEPRECATED
			if(!this.stateReplyToggled[id]) {
				// Reply toolbar
				Dsq.$('dsq-reply-bar-' + id).style.display = 'block';
				Dsq.Iframes.showReplyIframeInContainerIfAllowed(Dsq.$('dsq-reply-' + id), id);
			} else {
				Dsq.$('dsq-reply-bar-' + id).style.display = 'none';
				Dsq.Iframes.hideAllInContainer(Dsq.$('dsq-reply-' + id));
				if(this.stateRecordLink[id]) {
					// HACK: Cancel media before canceling self.
					this.toggleMediaReply(Dsq.$('dsq-media-link-' + id), id);
				}
			}
		}

		this.stateReplyToggled[id] = !this.stateReplyToggled[id];
		this._updateReplyLinks(el, id);

		if(Dsq.Utils.ie) { Dsq.Utils.fixIframesIE('dsq-reply-' + id); }

		Dsq.Events.fire(Dsq.Events.REPLY_IFRAME_TOGGLED, {
			postId: id,
			opened: this.stateReplyToggled[id]
		});
	};

	this.toggleMediaReply = function(el, id, xtype) {
		id = id || 0;
		if(id) {
			var container = Dsq.$('dsq-reply-' + id);
		} else {
			var container = Dsq.$('dsq-post-add');
		}

		if(!this.stateRecordLink[id]) {
			Dsq.Iframes.showReplyIframeInContainer(container, id, {xtype:xtype}, 'dsq-post-video');
		} else {
			Dsq.Iframes.showReplyIframeInContainer(container, id);
		}
		this.stateRecordLink[id] = !this.stateRecordLink[id];
		this._updateMediaLinks(el, id);

		if(Dsq.Utils.ie) { Dsq.Utils.fixIframesIE(); }
	};

	this.edit = function(el, id) {
		Dsq.$('dsq-comment-message-' + id).innerHTML = Dsq.Templates.frameEdit(id);
		el.parentNode.style.display = 'none';
		if(Dsq.Utils.ie) { Dsq.Utils.fixIframesIE('dsq-comment-message-' + id); }
	};

    this.rate = function(el, id, vote) {
		if(Dsq.jsonData.request.is_authenticated || Dsq.jsonData.forum.allow_anon_votes) {
			if(vote == 1) {
                Dsq.$('dsq-rate-cont-' + id).innerHTML = '<img src="http://media.disqus.com/images/loading-small.gif">';
            }

            Dsq.Utils.execScript('http://disqus.com/forums/scobleizer/vote.js'
                + '?post_id='    + id
                + '&vote='        + vote);

		} else {
			Dsq.Popup.login(Dsq.Strings.TO_RATE_PLEASE_LOG_IN);
		}
    };

	this.report = function(id, confirmed) {
		if(confirmed) {
			Dsq.Utils.postToUrl('http://disqus.com/forums/scobleizer/should_services_charge_8220super_users8221/post_report/', {'post_id': id});
			Dsq.Popup.popModal('Thank you. This comment has been flagged for moderator attention.', 'Successfully flagged');
			Dsq.Utils.deleteNode(Dsq.$('dsq-post-report-' + id));
		} else {
			var title = Dsq.Strings.FLAG_INAPPROPRIATE_COMMENT;
			var message = Dsq.Strings.ARE_YOU_SURE_YOU_WOULD_LIKE_TO_REPORT_THIS_COMMENT_TO_A_MODERATOR + '? \
			<br /><br /> \
			<button type="button" onclick="Dsq.Popup._closePopup(null, true)"><strong>' + Dsq.Strings.NO + '</strong>, ' + Dsq.Strings.NEVER_MIND + '</button>&nbsp;&nbsp;&nbsp;<button type="button" onclick="Dsq.Post.report(' + id + ', true);"><strong>' + Dsq.Strings.YES + '</strong>, ' + Dsq.Strings.FLAG_INAPPROPRIATE_COMMENT + '</button><br /><br />'
			+ Dsq.Strings.THIS_WILL_FLAG_COMMENTS_FOR_MODERATORS_TO_TAKE_ACTION + '. \
			';

			Dsq.Popup.popModal(message, title, id);
		}
	};



	this.showAlert = function(id, msg) {
		var msgEl = Dsq.$('dsq-comment-message-' + id);
		var alert = '<div class="dsq-comment-alert">' + msg + '</div>';

		msgEl.innerHTML = alert + msgEl.innerHTML;
	};

};
// Dsq.Post


/**
 * Dsq.Thread
 */
Dsq.Thread = new function() {
	this.fc = null;
	this.ff = null;
	this.ac = null;

	
	this.adminIsOn = false;

	
	
	

	this.hlComment = null;
	this.hlCommentClass = null;

	this.getNextComment = function(el) {
		var start_id = el.id;
		while(el = el.nextSibling) {
			if(el.id && el.id.indexOf('dsq-comment-') != -1 && el.id != start_id) {
				return el;
			}
		}
		return null;
	};

	this.getActiveCommentId = function() {
		if (document.URL.indexOf('#comment-') >= 0) {
			var anchor = document.URL.slice(document.URL.indexOf('#') + 1);
			return anchor.replace('comment-', '');
		}
		return null;
	};

	this.highlightAnchor = function() {
		var i = this.getActiveCommentId();
		if (i == null) return false;
		var id = 'dsq-comment-' + i;
		var hash = window.location.hash;

		// Toggle the hash incase the comment isn't available when the page loads
		// for WebKit-based browsers.
		if (Dsq.Utils.webkit) {
			window.location.hash = '';
			window.location.hash = hash;
		}

		this.hlComment = Dsq.$(id);
		// Adding this conditional guard pending #289
		if (!this.hlComment) {
			return;
		}
		this.hlCommentClass = this.hlComment.className;
		this.hlComment.className += ' dsq-hl-anchor';

		setTimeout("Dsq.Thread.highlightClear()", 3000);
	};

	this.highlightClear = function() {
		if (!this.hlComment) {
			return;
		}
		this.hlComment.className = this.hlCommentClass;
	};

	this.login = function(toggle) {
		// toggle id is #dsq-reply-login-[id]
		var postId;
		if(toggle.id.indexOf('dsq-reply-login') != -1) {
			postId = toggle.id.slice(16);
			var container = Dsq.$('dsq-reply-' + postId);
		} else {
			var container = Dsq.$('dsq-post-add');
		}

		if(toggle) {
			if(toggle.className == 'dsq-login-active') {
				Dsq.Iframes.showReplyIframeInContainerIfAllowed(container, postId);
				toggle.className = '';
			} else {
				Dsq.Iframes.showLoginIframeInContainer(container, postId);
				toggle.className = 'dsq-login-active';
			}
		} else {
			Dsq.Iframes.showLoginIframeInContainer(container, postId);
		}

		if(Dsq.Utils.ie) { Dsq.Utils.fixIframesIE(); }
	};


	this.paginate = function(page, el_clicked, per_page) {
		// Use extra_params to pass any override parameters that we need to persist.
		var extra_params = '';

		// "Per page" can either be overriden by providing it as an argument
		// (per-call) or setting the disqus_per_page override variable (global).
		if(typeof per_page == 'undefined') {
			per_page = null;
		}
		if(typeof disqus_per_page != 'undefined' && per_page === null) {
			per_page = disqus_per_page;
		}

		if(typeof disqus_sort != 'undefined') {
			extra_params += '&sort=' + disqus_sort;
		}
		if(per_page !== null) {
			extra_params += '&per_page=' + per_page;
		}

		Dsq.$('dsq-pagination').innerHTML += '<img src="http://media.disqus.com/images/loading-small.gif">';
		
		if(el_clicked) {
			el_clicked.style.display = 'none';
		}
		
		Dsq.Utils.execScript('http://disqus.com/forums/scobleizer/thread.js'
			+ '?slug='	+ 'should_services_charge_8220super_users8221'
			+ '&p='		+ page
			+ extra_params);
	};

	this.sortBy = function(sort) {
		var disqus_script = document.createElement('script');
		var disqus_date = new Date();

		if (location.hash != '') {
			location.hash = '#disqus_thread';
		}

		if(typeof(disqus_url) == 'undefined') {
			disqus_url = disqus_href;
		}
		disqus_script.type = 'text/javascript';
		disqus_script.src = 'http://disqus.com/forums/scobleizer/thread.js'
			+ '?slug='	+ 'should_services_charge_8220super_users8221'
			+ '&sort='	+ sort
			+ '&title='
			+ '&'		+ disqus_date.getTime();

		Dsq.$('dsq-comments').innerHTML = '<img src="http://media.disqus.com/images/loading.gif">';
		Dsq.container.appendChild(disqus_script);
	};

	this.subscribe = function(status, email) {
		// `status` is an int -- 1 to subscribe, 0 to unsubscribe
		if(Dsq.jsonData.request.is_authenticated || email) {
			// If authenticated user OR anonymous email provided

			if(email) {
				Dsq.Popup._closePopup(null, true);
			}

			Dsq.Utils.execScript('http://disqus.com/forums/scobleizer/subscribe.js'
				+'?status=' 	+ status
				+ '&slug='		+ 'should_services_charge_8220super_users8221'
				+ '&email=' 	+ encodeURIComponent(email));

		} else if(!email) {
			// If anonymous user and no email has been provided yet, prompt for email

			var title = 'Subscribe to this comment thread';
			var message = ' \
				New comments will be sent directly to your email inbox! \
				<div class="dsq-subscribe-submit"> \
					<p><strong>Enter your email address below.</strong></p> \
					<input type="text" id="dsq-subscribe-email"> \
					<button type="button" onclick="Dsq.Thread.subscribe(1, Dsq.$(\'dsq-subscribe-email\').value)">Subscribe</button> \
				</div> \
			';

			Dsq.Popup.popModal(message, title);
		}
	};

	this.showSettings = function() {
		if (!Dsq.jsonData.request.is_moderator) {
			return;
		}

		/* The form has to be re-designed when more options will come out. */
		var html = 'Automatically close comments after <input size="3" id="dsq-thread-days-alive" value="' + Dsq.jsonData.thread.days_alive + '" type="text" /> days. Existing comments will still be displayed.<br /><br />(Using 0 days will disable this feature)<br /><br />'
								 + '<button type="button" onclick="Dsq.Thread.updateDaysAlive();" class="dsq-button-small"><span>Save</span></button>'
								 + '<span id="dsq-thread-settings-status" class="dsq-options-status"></span>';

		Dsq.Popup.popModal(html, 'Settings');
	};

  this.showModeratorActions = function() {
      if (!Dsq.jsonData.request.is_moderator) {
          return;
      }

      var html = '<div class="dsq-moderate-options"><table><tr>' +
                 '<td>' + Dsq.Strings.ACTIONS + '</td><td><ul>';
      html += '<li><a href="#" onclick="Dsq.Thread.toggleClosed(); return false;">' +
              (Dsq.jsonData.thread.closed ? Dsq.Strings.OPEN_THREAD : Dsq.Strings.CLOSE_THREAD) +
              '</a></li>';
      html += '<li><a href="#" onclick="Dsq.Thread.toggleKilled(); return false;">' +
              (Dsq.jsonData.thread.killed ? Dsq.Strings.RESTORE_THREAD : Dsq.Strings.REMOVE_THREAD) +
              '</a></li>';
      html += '</ul></td></tr></table></div>' +
              '<p>Go to the full <a href="http://disqus.com/comments/moderate-threads/" target="_blank">moderate panel</a> for more options.</p>';
      Dsq.Popup.popModal(html, Dsq.Strings.MODERATE_OPTIONS);
  };

	this.updateDaysAlive = function() {
		  var days = Dsq.$('dsq-thread-days-alive').value;
		  var status = Dsq.$('dsq-thread-settings-status');
		  Dsq.Utils.postToUrl('http://disqus.com/forums/scobleizer/update_days_alive.js', {days:days,thread:Dsq.jsonData.thread.id});
		  status.innerHTML = 'Saved!';
		  window.setTimeout(function() { status.innerHTML = ''; }, 1000);
	};

  this.toggleClosed = function() {
      Dsq.Utils.postToUrl('http://disqus.com/forums/scobleizer/toggle_thread_closed.js', {thread:Dsq.jsonData.thread.id});
      window.setTimeout(function() { window.location.reload(); }, 500);
  };

  this.toggleKilled = function() {
      Dsq.Utils.postToUrl('http://disqus.com/forums/scobleizer/toggle_thread_killed.js', {thread:Dsq.jsonData.thread.id});
      window.setTimeout(function() { window.location.reload(); }, 500);
  };
};
// Dsq.Thread

Dsq.Events = function() {
	var obj = {};

	// Private
	var handlers = {};
	var getHandlers = function(event) {
		if (handlers[event] === undefined) {
			handlers[event] = [];
		}
		return handlers[event];
	};

	// Public
	// Value keys : postId, node, xtype
	obj.REPLY_IFRAME_CREATED = 1;
	// Value keys : postId, opened
	obj.REPLY_IFRAME_TOGGLED = 2;
	obj.fire = function(event, opt_value) {
		if (!event) {
			throw new Error('Unknown event');
		}
		var value = opt_value || {};
		for (var i=0; i<getHandlers(event).length; i++) {
			getHandlers(event)[i](value);
		}
	};
	obj.addHandler = function(event, callback) {
		getHandlers(event).push(callback);
	};

	return obj;
}();

/**
 * Dsq.Realtime
 */
Dsq.Realtime = new function() {
	var initialized = false;
	var interval = null;
	var last_checked = Dsq.jsonData.request.timestamp;
	var new_posts = [];
	var ongoing_request = false;
	var prev_script = null;

	function updateNewPostCount() {
		Dsq.$('dsq-realtime-alert').style.display = new_posts.length ? 'block' : 'none';

		Dsq.$('dsq-realtime-queued').innerHTML = new_posts.length
		+ ' new '
		+ Dsq.Utils.pluralize(new_posts.length, 'comment', 'comments')
		+ Dsq.Utils.pluralize(new_posts.length, ' was', ' were')
		+ ' just posted.';

		Dsq.$('dsq-realtime-show').innerHTML = '(' + Dsq.Strings.SHOW + ')';
	}

	function insertNewPosts() {
		var post_id = null;
		var after_id = Dsq.$('dsq-sort-select').value === 'oldest' ? -1 : null;

		for (var i=0; i<new_posts.length; i++) {
			post_id = new_posts[i];
			Dsq.Post.insert(after_id, post_id, Dsq.jsonData.posts[post_id].message);
			Dsq.Post.incrementPostCount();
			Dsq.Post.outlineComment(post_id);
		}
		new_posts = [];
	}

	this.enableInterval = function() {
		interval = setInterval(Dsq.Realtime.check, Dsq.jsonData.context.realtime_speed);
		Dsq.$('dsq-realtime-status').innerHTML = Dsq.Strings.ENABLED;
		Dsq.$('dsq-realtime-toggle').innerHTML = '(' + Dsq.Strings.PAUSE + ')';
	}

	this.disableInterval = function() {
		if (interval) {
			clearInterval(interval);
			interval = null;
		}
		Dsq.$('dsq-realtime-status').innerHTML = Dsq.Strings.PAUSED;
		Dsq.$('dsq-realtime-toggle').innerHTML = '(' + Dsq.Strings.RESUME + ')';
	}

	this.toggleInterval = function() {
		if (!interval) {
			Dsq.Realtime.enableInterval();
		} else {
			Dsq.Realtime.disableInterval();
		}
		return false;
	}

	this.initialize = function() {
		if (!initialized) {
			initialized = true;
			Dsq.$('dsq-realtime-toggle').onclick = this.toggleInterval;
			if (!Dsq.jsonData.forum.streaming_realtime) {
				Dsq.$('dsq-realtime-show').onclick = this.show;
				updateNewPostCount();
			}
			if (Dsq.jsonData.thread.realtime_paused) {
				Dsq.Realtime.disableInterval();
			} else {
				Dsq.Realtime.enableInterval();
			}
		}
	}

	this.show = function() {
		insertNewPosts();
		updateNewPostCount();
		return false;
	}

	this.check = function() {
		if (!ongoing_request && Dsq.jsonData.realtime_enabled) {
			if (prev_script) {
				prev_script.parentNode.removeChild(prev_script);
			}
			ongoing_request = true;
			prev_script = Dsq.Utils.execScript('http://disqus.com/forums/18349417/realtime.js?timestamp=' + last_checked);
		}
	};

	this.update = function(timestamp, posts, users) {
		ongoing_request = false;
		last_checked = timestamp;

		if (users) {
			for (var user_id in users) {
				if (users.hasOwnProperty(user_id)) {
					if (!Dsq.jsonData.users[user_id]) {
						Dsq.jsonData.users[user_id] = users[user_id];
					}
				}
			}
		}

		if (posts) {
			for (var post_id in posts) {
				if (posts.hasOwnProperty(post_id)) {
					if (!Dsq.jsonData.posts[post_id]) {
						Dsq.jsonData.posts[post_id] = posts[post_id];
						new_posts.push(post_id);
					}
				}
			}

			if (Dsq.jsonData.forum.streaming_realtime) {
				insertNewPosts();
			} else {
				updateNewPostCount();
			}
		}
	};

}();

// DEPRECATED
Dsq.Iframes = function() {
	// Different style of object from the above. Hoping to switch to this for some reason.
	var obj = {};

	// Private
	var showIframeInContainer = function(container, id, markup) {
		// Look through container for iframes, hiding them, except show one that matches id
		// If none of them matched id, create a new iframe using markup and insert it.
		// Returns the iframe node if and only if it was newly created.
		var found = false;
		for (var i=0; i<container.childNodes.length; i++) {
			var child = container.childNodes[i];
			if (child.nodeName == 'IFRAME') {
				if (child.id == id) {
					child.style.display = 'block';
					found = true;
				} else {
					child.style.display = 'none';
				}
			}
		}
		if (found) {
			return;
		}
		// The iframe wasn't found, so construct it and add it to the container.
		// Don't use innerHTML because it might reload iframes
		var div = document.createElement('div');
		div.innerHTML = markup;
		var iframe = div.childNodes[0];
		div.removeChild(iframe);
		container.appendChild(iframe);
		return iframe;
	};

	// Public
	obj.makeReplyIframeId = function(opt_postId, opt_xtype) {
		var id = 'dsq-post-add-iframe';
		if (opt_xtype) {
			id += '-' + opt_xtype;
		}
		if (opt_postId) {
			id += '-' + opt_postId;
		}
		return id;
	};
	obj.makeLoginIframeId = function(opt_postId) {
		if (!opt_postId) {
			return 'dsq-login-iframe';
		}
		return 'dsq-login-iframe-' + opt_postId;
	};
	obj.makeReplyIframeName = function(opt_postId, opt_xtype) {
		var name = 'dsq-reply-frame';
		if (opt_xtype) {
			name += '-' + opt_xtype;
		}
		if (opt_postId) {
			name += '-' + opt_postId;
		}
		return name;
	};
	obj.showReplyIframeInContainer = function(container, opt_postId, opt_extraParams, opt_className) {
		// Construct the id so we can check if it's already present.
		// Hide any other iframes we find, and show this one if it's found.
		var params = opt_extraParams || {};
		// use xtype in the id and name so we can distinguish media replies from text replies:
		var id = Dsq.Iframes.makeReplyIframeId(opt_postId, params.xtype);
		var name = Dsq.Iframes.makeReplyIframeName(opt_postId, params.xtype);
		var attributes = {
			'id': id,
			'name': name,
			'class': opt_className || 'dsq-post-reply'
			};
		var markup = Dsq.Templates.frameReply(opt_postId, opt_extraParams, attributes);
		var iframe = showIframeInContainer(container, id, markup);
		// It was newly created
		if (iframe) {
			Dsq.Events.fire(Dsq.Events.REPLY_IFRAME_CREATED, {
				postId: opt_postId,
				node: iframe,
				xtype: params.xtype
			});
		}
	};
	obj.showLoginIframeInContainer = function(container, opt_postId) {
		var id = Dsq.Iframes.makeLoginIframeId(opt_postId);
		var markup = Dsq.Templates.frameLogin({id: id});
		showIframeInContainer(container, id, markup);
	};
	obj.showReplyIframeInContainerIfAllowed = function(container, opt_postId) {
		if (Dsq.jsonData.context.show_reply) {
			obj.showReplyIframeInContainer(container, opt_postId);
		} else {
			obj.hideAllInContainer(container);
		}
	};
	obj.hideAllInContainer = function(container) {
		for (var i=0; i<container.childNodes.length; i++) {
			var child = container.childNodes[i];
			if (child.nodeName == 'IFRAME') {
				child.style.display = 'none';
			}
		}
	};

	return obj;
}();

Dsq.Twitter = new function() {
	var that = this;

	this.startTwitterConnect = function() {
		var popupParams = 'location=0,status=0,width=800,height=400';
		that._twitterWindow = window.open(Dsq.jsonData.settings.disqus_url + '/_ax/twitter/begin/', 'twitterWindow', popupParams);
		that._twitterInterval = window.setInterval(that.completeTwitterConnect, 1000);
	};

	this.completeTwitterConnect = function() {
		if (that._twitterWindow.closed) {
			window.clearInterval(that._twitterInterval);
			window.location.reload();
		}
	};
};

Dsq.Yahoo = new function() {
	var that = this;

	this.startYahooConnect = function() {
		var popupParams = 'location=0,status=0,width=800,height=400';
		that._yahooWindow = window.open(Dsq.jsonData.settings.disqus_url + '/_ax/yahoo/begin/', 'yahooWindow', popupParams);
		that._yahooInterval = window.setInterval(that.completeYahooConnect, 1000);
	};

	this.completeYahooConnect = function() {
		if (that._yahooWindow.closed) {
			window.clearInterval(that._yahooInterval);
			window.location.reload();
		}
	};
};

Dsq.OpenID = new function() {
	var that = this;

	this.requestURL = function() {
		var message = '<table class="dsq-openid-form"><tr><td style="vertical-align:top;" rowspan="2"><img src="' + Dsq.jsonData.settings.media_url + '/images/openid-icon-100x100.png" /></td>';
		message += '<td><label for="dsq-openid-url">OpenID URL:</label></td><td><input type="text" id="dsq-openid-url" /></td></tr>';
		message += '<tr><td><label for="dsq-openid-username">Display name:</label></td><td><input type="text" id="dsq-openid-username" /></td></tr>';
		message += '<tr><td class="dsq-openid-submit" colspan="3"><input type="button" value="Sign in" onclick="Dsq.OpenID.startConnect();" /></td></tr>';
		message += "</table>";

		Dsq.Popup.popModal(message, 'Sign in using OpenID');
	};

	this.startConnect = function() {
		var isblank = function(str) {
			return /^\s*$/.test(str);
		};

		var openid_url = Dsq.$('dsq-openid-url').value;
		var username = Dsq.$('dsq-openid-username').value;

		if (isblank(openid_url)) {
			return;
		}

		var popupParams = 'location=0,status=0,width=800,height=500';
		var url = Dsq.jsonData.settings.disqus_url + '/_ax/openid/begin/' + '?url=' + encodeURIComponent(openid_url) + '&username=' + encodeURIComponent(username);
		that._openidWindow = window.open(url, 'openidWindow', popupParams);
		that._openidInterval = window.setInterval(that.completeConnect, 1000);
	};

	this.completeConnect = function() {
		if (that._openidWindow.closed) {
			window.clearInterval(that._openidInterval);
			window.location.reload();
		}
	};
};

Dsq.Reaction = new function() {
	var that = this;

	this.hide = function(id) {
		Dsq.Utils.execScript('http://disqus.com/forums/scobleizer/hidereaction.js?' + 'reaction_id=' + id);
	};

	this.reportMissingReactions = function() {
		if (!Dsq.jsonData.request.is_moderator || !Dsq.jsonData.forum.reactions_enabled) {
			return;
		}

		if (Dsq.jsonData.thread.queued) {
			Dsq.Popup.popModal('Your report has been received. The system will automatically search for new reactions; if any are found, they will be displayed on this comment thread.<br/><br/>Thank&nbsp;you.',
												 'Reported missing reactions');
			return;
		}

		Dsq.Utils.execScript(Dsq.jsonData.settings.disqus_url + '/forums/scobleizer/queueurl.js');
	};
};

Dsq.CNN = function() {
	var obj = {};

	obj.authenticate = function() {
		var url = Dsq.jsonData.settings.disqus_url + "/saml/cnn/try/";
		Dsq.Utils.postToUrl(url, {'target': document.location}, true);
	};

	return obj;
}();


if(Dsq.Utils.ie6) {
	(function() {
		DSQ_HEADER_AVATAR_RE = /<div class="dsq-header-avatar"(.*?)>/gim;
		Dsq.Templates.registerFilter('postPrependHeader', function(html, post_id) {
			// Add "onmouseout" for dsq-header-avatar for dropProfile
			// functionality since IE6 cannot use :hover.
			function _headerAvatarReplace(content, inner, _unused, html) {
				return '<div class="dsq-header-avatar" '
					+ inner
					+ ' onmouseout="Dsq.Post.dropProfile(' + post_id + ')">';
			}
			html = html.replace(DSQ_HEADER_AVATAR_RE, _headerAvatarReplace);
			return html;
		});
	})();
}





	// TODO: Move Seesmic code outside of the main script.  Don't let this script clobber the global namespace.
	if(typeof seesmic == 'undefined') { var seesmic = {}; }
	seesmic.widget = new function () {
		this.callback = function (data) {
			playerVersion = data.disqusplayer;
		};
	};

	
	var scriptEl = document.createElement('script');
	scriptEl.setAttribute('type', 'text/javascript');
	scriptEl.setAttribute('src', 'http://seesmic.com/version.js?callback=seesmic.widget.callback');
	document.getElementsByTagName('head')[0].appendChild(scriptEl);

	
	var scriptEl = document.createElement('script');
	scriptEl.setAttribute('type', 'text/javascript');
	scriptEl.setAttribute('src', 'http://media.disqus.com/javascript/library/swfobject.js');
	document.getElementsByTagName('head')[0].appendChild(scriptEl);

	function see_play_video(_videoUri, _add) {
		var swf = !!playerVersion ? playerVersion : 'http://seesmic.com/embeds/StandalonePlayer.swf';

		flashcontentDiv = Dsq.$(_videoUri + '_content');
		previewDiv = Dsq.$('dsq-seesmic-' + _videoUri + '_preview');
		hideDiv = Dsq.$('dsq-seesmic-' + _videoUri + '_hide');
		showDiv = Dsq.$('dsq-seesmic-' + _videoUri + '_show');
		if(_add) {
			// push flash widget
			var so = new SWFObject(swf, 'sotester', '300', '270', '9', '#000000');
			so.addVariable('video', _videoUri);
			so.addParam('allowFullScreen', 'true');
			so.addParam('allowScriptAccess','always');
			so.useExpressInstall('swfobject/expressinstall.swf');
			so.write(_videoUri + '_content');

			previewDiv.style.display = 'none';
			hideDiv.style.display = 'block';
			showDiv.style.display = 'none';
		}
		else {
			flashcontentDiv.innerHTML = '';
			previewDiv.style.display = 'block';
			hideDiv.style.display = 'none';
			showDiv.style.display = 'block';
		}
	};





(function() {
	//
	// Load theme.  This overrides the base templates with template functions
	// from the respective themes.
	//
	if (Dsq.jsonData.integration.theme == 4) {
		var theme = 'narcissus';
		// HACK: Set variable on window to use post message.
		window.disqus_use_postmessage = true;

		
		for(var prop in Dsq.Themes[theme]) {
			if(Dsq.Themes[theme] && Dsq.Themes[theme].hasOwnProperty(prop)) {
				Dsq.Templates[prop] = Dsq.Themes[theme][prop];
			}
		}
		
		for(var prop in Dsq.Post) {
			if(Dsq.Themes[theme] && Dsq.Themes[theme].hasOwnProperty(prop)) {
				Dsq.Post[prop] = Dsq.Themes[theme][prop];
			}
		}
	}

	//
	// Register templates.  This must be done after all themes are loaded.
	//
	Dsq.Templates.registerTemplate('authPost', Dsq.Templates.authPost);
	Dsq.Templates.registerTemplate('header', Dsq.Templates.header);
	Dsq.Templates.registerTemplate('footer', Dsq.Templates.footer);
	Dsq.Templates.registerTemplate('trackbacks', Dsq.Templates.trackbacks);
	Dsq.Templates.registerTemplate('reactions', Dsq.Templates.reactions);
	Dsq.Templates.registerTemplate('prependPost', Dsq.Templates.prependPost);
	Dsq.Templates.registerTemplate('appendPost', Dsq.Templates.appendPost);
	Dsq.Templates.registerTemplate('postPrependHeader', Dsq.Templates.postPrependHeader);
	Dsq.Templates.registerTemplate('postAppendHeader', Dsq.Templates.postAppendHeader);
	Dsq.Templates.registerTemplate('preBody', Dsq.Templates.preBody);
	Dsq.Templates.registerTemplate('postBody', Dsq.Templates.postBody);
	Dsq.Templates.registerTemplate('postFooter', Dsq.Templates.postFooter);
	Dsq.Templates.registerTemplate('_popupGeneric', Dsq.Templates._popupGeneric);
	Dsq.Templates.registerTemplate('voted', Dsq.Templates.voted);
	Dsq.Templates.registerTemplate('popupProfile', Dsq.Templates.popupProfile);
	Dsq.Templates.registerTemplate('postBox', Dsq.Templates.postBox);
	Dsq.Templates.registerTemplate('pagination', Dsq.Templates.pagination);
	Dsq.Templates.registerTemplate('postComment_onSuccess', Dsq.Templates.postComment_onSuccess);

})();

Dsq.container.className = "clearfix";
Dsq.container.innerHTML = ' \
<ul id="dsq-comments">\
	 <li id="dsq-comment-9705807">\
	 <div id="dsq-comment-header-9705807" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705807" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705807" href="http://webreakstuff.com/" target="_blank" rel="nofollow">Tiago Macedo</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705807" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705807" class="dsq-comment-message">Actually Dare\'s post sums it up. It doesn\'t mean that Twitter\'s architecture is the one he suggests but given their database problems it\'s very likely.<br><br>Everytime you update, Twitter has to get a list of your 25k followers, sort out any @ replies, find out what their notification settings are, notify each and everyone individually and add a message to their feed (even if it\'s still the same one). All this while their feeds are being hit like crazy by desktop clients.<br><br>So, Twitter is a notification system with multiple entries and exit points. Friendfeed is an aggregator. It doesn\'t, as far as I know, notify anyone.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705801">\
	 <div id="dsq-comment-header-9705801" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705801" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705801" href="http://blog.thylmann.net/" target="_blank" rel="nofollow">Oliver Thylmann</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705801" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705801" class="dsq-comment-message">As far as I know this is exactly how Twitter does it. Once you post a Message it gets copied to the streams of all your followers. The problem is that building up the last messages of the people you follow based on their user_id is just not working fast enough. Having a copy of your message is easier and faster to load. so this is exactly how it works, but I am not sure why this means that you need to start paying :)</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705802">\
	 <div id="dsq-comment-header-9705802" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705802" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705802" href="http://www.wolfslittlestore.be/" target="_blank" rel="nofollow">Wolf</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705802" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705802" class="dsq-comment-message">If you\'re awake for 12 hours a day you have 3.9 seconds to \'interact\' with each of your \'friends\'.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705803">\
	 <div id="dsq-comment-header-9705803" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705803" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705803" href="http://scobleizer.com/" target="_blank" rel="nofollow">Robert Scoble</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705803" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705803" class="dsq-comment-message">Wolf: that\'s assuming that each of my friends actually does anything or wants to be interacted with. I\'ve found that to be not true at all.<br><br>Anyway, here\'s another really interesting conversation cluster that this post started over on FriendFeed: <a href="http://friendfeed.com/e/a2463347-f07a-ab3f-4f41-dba35d38dee9" rel="nofollow">http://friendfeed.com/e/a2463347-f07a-ab3f-4f41...</a></div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705804">\
	 <div id="dsq-comment-header-9705804" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705804" class="dsq-comment-cite">\
	 <span id="dsq-author-user-9705804">jonas</span>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705804" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705804" class="dsq-comment-message">Could you elaborate on "remixes them"? Because so far Dare Obasanjos thoughts sounds much more plausible.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705805">\
	 <div id="dsq-comment-header-9705805" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705805" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705805" href="http://scobleizer.com/" target="_blank" rel="nofollow">Robert Scoble</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705805" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705805" class="dsq-comment-message">Tiago: FriendFeed certainly notifies people. It even has an API where you can get messages sent into.<br><br>As to architecture. OK, let\'s have one object:<br><br>Scoble\'s Tweets.<br><br>Then let\'s have another object.<br><br>Jane Smith\'s Tweets.<br><br>Now let\'s have a third object:<br><br>John Schmidt\'s Tweet page that displays both Jane\'s and Scoble\'s Tweets.<br><br>Sounds like Scoble\'s and Jane\'s Tweets are being copied, right?<br><br>No.<br><br>In fact, if John Schmidt never uses his account, nothing happens at all.<br><br>But, let\'s say that John Schmidt opened his Web browser and visited Twitter. Well, ONLY THEN does John Schmidt\'s object (which knows which Tweets it should go look for) talk to the other two objects, and say "give me your Tweets." Then John\'s object mashes them together and displays them to John. It also, then, closes down and releases all memory and disk space until the next time John asks for something.<br><br>This does not change if there are a million "objects" being mashed up. No copies are living permanently. Just the original objects.<br><br>Got it yet? I\'ll do a video, if you want to understand it more.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705806">\
	 <div id="dsq-comment-header-9705806" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705806" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705806" href="http://oxalon.com/" target="_blank" rel="nofollow">Paul Short</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705806" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705806" class="dsq-comment-message">Robert, Duncan Riley referred me to a plugin for wordpress blogs that automatically adds friendfeed comments to the originating post on your blog + lets people comment on friendfeed items from the blog as well. You can see it in action on his <a href="http://Inquisitr.com" rel="nofollow">Inquisitr.com</a> site. Here\'s the link to that plugin if you\'re interested: <a href="http://tinyurl.com/2uqa6l" rel="nofollow">http://tinyurl.com/2uqa6l</a></div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705797">\
	 <div id="dsq-comment-header-9705797" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705797" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705797" href="http://scobleizer.com/" target="_blank" rel="nofollow">Robert Scoble</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705797" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705797" class="dsq-comment-message">Translation: the only scaling problem would be when I started up my Twitter and wanted to see all objects from everyone. Then my object would  have to work harder than, say, your object because your object would only have to find a few Tweets. Mine has to find 23,000. OK, so they have to throw a little extra processor at my account, but only when I\'m using the system. If, like right now, I\'m not using the system it has absolutely no extra load on the system unless someone calls my object and makes it do work.<br><br>How do I know this? Ask the Exchange team how it keeps stuff from duplicating all over the place and causing server disks from filling up.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705798">\
	 <div id="dsq-comment-header-9705798" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705798" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705798" href="http://scobleizer.com/" target="_blank" rel="nofollow">Robert Scoble</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705798" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705798" class="dsq-comment-message">&gt;&gt;Once you post a Message it gets copied to the streams of all your followers.<br><br>Absolutely wrong.<br><br>Only gets copied if a user instantiates his object and asks for those things. Even then, it\'s not "copied" except to display it, and that copy is temporary and stored in your browser, or in your Google Talk account.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705799">\
	 <div id="dsq-comment-header-9705799" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705799" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705799" href="http://www.ironpythoninaction.com/" target="_blank" rel="nofollow">Michael Foord</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705799" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705799" class="dsq-comment-message">"If this were a straight “n-scale” problem the crashing problems wouldn’t have shown up so early."<br><br>Why not? As they scale up their system - the number of users is growing just as fast. If they scale just quick enough to stay one step behind the problem they will continue to have issues.<br><br>I don\'t blame them - it\'s a difficult problem and not many sites have to cope with such massive growth so quickly.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705800">\
	 <div id="dsq-comment-header-9705800" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705800" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705800" href="http://www.corank.com/" target="_blank" rel="nofollow">RBA</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705800" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705800" class="dsq-comment-message">So it is no secret to say that Twitter wasn\'t created with scalability in mind - like 90% of all "2.0" projects. After all, Twitter was born and it stayed completely in the dark for over 8 months until it exploded at the SXSW\'07. I don\'t think it went down during those first 8 months (and if it did, not many people noticed anyway).<br><br>And ever since the first time it went down, chances are they\'ve been patching and optimizing things here and there, when perhaps what Twitter needs is a complete remake - which shouldn\'t really be THAT hard considering Twitter is above all, a very simple application - that thing doesn\'t put a spacecraft in Mars - so the main focus should be scalability. Perhaps they\'re doing that already. If not, they should.<br><br>On the other hand, FF most likely has been created with scalability in mind, and so far, other than throwing hardware at it, as long as they\'re somewhat ahead of the growth game, it doesn\'t need anything to stay afloat as it grows. It\'s not rocket science either - they simply didn\'t (supposedly) ignore the possibility of growth when they started to write their software. Which is what everyone should do when starting a project, and there\'s plenty of documentation out there and plenty of great engineers who know how to architect a simple (or complex) app so that it will scale if necessary.<br><br>Leaving that aside, the business model is a very interesting and fair question. No, I don\'t agree with Om. Not because I don\'t think super-users shouldn\'t be charged, but because charging super-users doesn\'t fix anything, scalability-wise. I also don\'t think Om understands how Twitter works internally. Ok, *I* don\'t know how Twitter works, but if it does the way Om describes it, then the folks at Twitter absolutely definitely need to rewrite the whole thing from scratch. Personally I didn\'t like neither Obasanjo\'s nor Om\'s articles at all. You? Well, you\'re talking about Twitter and FriendFeed, and a bit of Facebook. Thank god for that "This is why I love the tech industry" article, because it is for posts like that I\'m still reading you. (No offense, I just don\'t use neither Tw nor FF, so this fun madness you guys have is completely out of my radar...)</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705796">\
	 <div id="dsq-comment-header-9705796" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705796" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705796" href="http://scobleizer.com/" target="_blank" rel="nofollow">Robert Scoble</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705796" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705796" class="dsq-comment-message">Michael Foord: nah, the problems would become much much worse as they scaled up. The architecture they chose isn\'t too far off. It\'s just that they never did engineer it properly. The fact that just this week they\'ve gotten the ability to turn off features one by one shows me that they never were run professionally until recently. I bet that Twitter starts getting stable very quickly now. Remember, there\'s only a million or two on Twitter. Facebook keeps up with 80 million. Hotmail 200 million every 30 days. Facebook and Hotmail don\'t go down, even though they are doing stuff more complex and at a larger scale than Twitter is.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705793">\
	 <div id="dsq-comment-header-9705793" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705793" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705793" href="http://handelaar.org/" target="_blank" rel="nofollow">John Handelaar</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705793" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705793" class="dsq-comment-message"><em>"This is like saying that Exchange stores each email once for each user. That’s totally not true"</em><br><br>Sweet how you never had to work with an Exchange server which did <strong>exactly</strong> that, and then added \'All\' as a recipient to the address book of every user.<br><br>I\'ll grant it doesn\'t do it now.  But it sure as hell used to.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705794">\
	 <div id="dsq-comment-header-9705794" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705794" class="dsq-comment-cite">\
	 <span id="dsq-author-user-9705794">HvI</span>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705794" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705794" class="dsq-comment-message">Quote: "If you unironically regard public comments on an RSS feed as "conversations" with "friends," you either need a dictionary or better friends." <a href="http://textism.com/favrd/favorites/tweet/817323555" rel="nofollow">http://textism.com/favrd/favorites/tweet/817323555</a></div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705795">\
	 <div id="dsq-comment-header-9705795" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705795" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705795" href="http://scobleizer.com/" target="_blank" rel="nofollow">Robert Scoble</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705795" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705795" class="dsq-comment-message">&gt;I’ll grant it doesn’t do it now. But it sure as hell used to.<br><br>I know it did. Which is why some people still don\'t understand the architecture that Exchange uses (which is why I was "educated" on the issue).<br><br>By the way, this caused a famous and massive problem inside Microsoft when the database server filled up when someone accidentally emailed something to "all." Email went down for two days, the way I heard it.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705792">\
	 <div id="dsq-comment-header-9705792" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705792" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705792" href="http://geoffjones.com/" target="_blank" rel="nofollow">Geoff</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705792" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705792" class="dsq-comment-message">As far as I\'m aware Twitter is the only service that allows posting  and receiving by SMS. The big problem with SMS is it is a untimed service, when I text there is no guarantee when and if it will be delivered this must be a problem for them.<br><br>Robert if you remember in the bad old days :-) when Blogger was crashing all the time they offered a Pro service where you paid in the hope of some reliability - fortunately Google took them out and over a period of a year or two sorted out the problems. I hope that Google do the same with Twitter :-)</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705791">\
	 <div id="dsq-comment-header-9705791" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705791" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705791" href="http://solyoung.com/" target="_blank" rel="nofollow">Sol Young</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705791" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705791" class="dsq-comment-message">No, services shouldn\'t charge "super users." (I\'d be surprised if "super users" don\'t start receiving significant sponsorships to come and use a service).<br><br>As far as the workflow for Twitter vs. the workflow of FriendFeed, it\'s impossibly unfair to compare Twitter to FriendFeed (yet). Twitter is pushing updates the moment you send an update. FriendFeed isn\'t doing instant updates via XMPP (Jabber) or SMS.<br><br>Additionally, Twitter is at the "oh wow, if I follow 10,000 people I\'ll probably have 1,000 follow me back and I can spam them." This is making a large number of "super users", not just you Robert :-) They\'re getting hammered in traffic compared to FriendFeed.<br><br>Let\'s compare the numbers in terms of service reliability and overall load (rounded down)... You\'ve got 10,000 followers on FriendFeed and 20,000 on Twitter. If this is a true representation of the population on each service (it\'s not, but we\'ll pretend), this means Twitter has double the traffic of users. Double the traffic, in a push based service, does not mean double the load... There are double the updates to double the followers.<br><br>A semi-decent formula for load based on the above:<br>Twitter != FriendFeed x 2<br>Twitter = FriendFeed ^ 2</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705790">\
	 <div id="dsq-comment-header-9705790" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705790" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705790" href="http://www.ironpythoninaction.com/" target="_blank" rel="nofollow">Michael Foord</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705790" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705790" class="dsq-comment-message">Geoff: Google have bought jaiku and so are unlikely to buy Twitter. :-)<br><br>I wonder how much the outages are driving people into Pownce and Jaiku. I know of at least one of my \'Twitter friends\' who is going *back* to Jaiku because of the service problems.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705788">\
	 <div id="dsq-comment-header-9705788" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705788" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705788" href="http://www.dariosalvelli.com" target="_blank" rel="nofollow">Dario Salvelli</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705788" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705788" class="dsq-comment-message">Hi Robert. Do u remember that Twitter was born for other goal? Do u remember the name of <a href="http://www.dariosalvelli.com/2006/07/twttr-a-group-send-sms-application" rel="nofollow">Twttr</a>? It was "only" a send SMS group apps, in origin. The team is the same of Odeo. True?<br><br>So, Twitter is a sort of messagging system such as IM but in a public way (but you can also set a protected status, why are u frustated?) and as the team write the system that "Twitter was not architected as a messaging system":<br><br><a href="http://dev.twitter.com/2008/05/twittering-about-architecture.html" rel="nofollow">http://dev.twitter.com/2008/05/twittering-about...</a></div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705789">\
	 <div id="dsq-comment-header-9705789" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705789" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705789" href="http://barrkel.blogspot.com/" target="_blank" rel="nofollow">Barry Kelly</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705789" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705789" class="dsq-comment-message">There are two basic ways to build a Twitter-like solution. Either you have, (A) per tweet, a single write and, per user, huge joined reads; or, (B) per tweet, huge numbers of writes and, per user, a single cheap read.<br><br>With Twitter, reading generally happens more often than writing, especially when you have desktop clients built around polling. That implies going with solution (B), which has some big problems - most databases aren\'t set up to deal efficiently with lots of writes.<br><br>So, you can try to work it with solution (A), but then you need lots of muscle for all these joined queries. If you\'re using database sharding, you\'ll probably need to issue queries to multiple databases running on multiple machines, and join all the results and sort them by time, per each user page refresh or desktop client poll. That\'s a lot of work per user.<br><br>It sounds pretty expensive - better cache it. Leads to a hybrid solution; single write, rare combination reads but not too often (i.e. not every poll or page refresh). Some risk of stale updates.<br><br>No matter which way you look at it, though, the scaling isn\'t quite linear, as some of the old folks will follow new folks as they get added. It should ultimately end up as linear, though with a high constant factor, that constant determined by the average "noise threshold" per user.<br><br>Looking at the pure "unit of work", lots of writes probably beats lots of reads, because the reading solution requires sorting and, with the addition of caching layers, has cache coherency problems. Writing can be based around appending to queues.<br><br>Also, all the "extra" features that Twitter-folks (in their blogs at least) seem to think are so essential, are quite costly to implement.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705787">\
	 <div id="dsq-comment-header-9705787" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705787" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705787" href="http://slashstar.com/blogs/tim" target="_blank" rel="nofollow">Tim Marman</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705787" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705787" class="dsq-comment-message">"First of all, Twitter doesn’t store my Tweets 25,000 times. It stores them once and then it remixes them. This is like saying that Exchange stores each email once for each user. That’s totally not true and shows a lack of understanding how these things work internally."<br><br>Robert, as was already pointed out this was once true for Exchange, but regardless I fail to see how you can make this same assumption for Twitter.<br><br>Regardless of how many times it\'s stored, Twitter also has a tougher routing problem. With Exchange, the sender defines where the message will be received. Twitter is fundamentally different - the sender broadcasts the message, and then the system needs to figure out where to deliver it. This means some of your 25,000 followers - remember, it still has to figure out if I will receive the message based on whether it\'s an @reply and what my settings are.<br><br>Twitter also has to deliver it to the countless number of tracks. Let\'s assume that the average word length for English is 5.10 (<a href="http://blogamundo.net/lab/wordlengths/" rel="nofollow">http://blogamundo.net/lab/wordlengths/</a>). On twitter, it\'s likely less given the 140 char limitation, we tend to use more abbreviations and generally shorter words. Taking out, let\'s say, 30 chars for punctuation - that means there are 20 distinct words. Twitter in turn needs to figure out who is tracking what, and the track functionality supports tracking word1+word2+word3. Obviously there are a number of ways to implement this more efficiently, but in effect Twitter has to do a fair amount of processing to see if a given message should be delivered to a given person\'s track queue.<br><br>It\'s clear that they have a bottleneck somewhere. Given the roots of the service, it\'s pretty clear the architecture didn\'t plan for this kind of use - and they admitted it in the link Dario posted. None of us really know what\'s going on behind the scenes, but based on what little evidence we have Dare\'s scenario seems plausible and perhaps likely.<br><br>Ignoring some of the differences in how the service is used, the other thing that FriendFeed had was the luxury of architecting their system after they saw how Twitter was being used. Twitter likely would have done things differently with the benefit of hindsight, but it sounds like (from interviews with Blaine) that much of their time was spent fighting fires as opposed to re-engineering the system.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705786">\
	 <div id="dsq-comment-header-9705786" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705786" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705786" href="http://admin.support.journurl.com/" target="_blank" rel="nofollow">Roger Benningfield</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705786" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705786" class="dsq-comment-message">Robert: Um, I don\'t think you understand what Dare was saying. You might wanna calm down a touch. It might be unfair to blame *you* for Twitter\'s woes, but Dare\'s analysis of the architecture is probably pretty accurate.<br><br>Open up Twitter... now, did you wait several minutes for your page to appear? If not, then something\'s being cached on the server side. It could be via memcached, it could be via "baking" your page instead of "frying" it, or whatever. But the data isn\'t being collected on the fly as you seem to believe. It\'s being pushed into the cache when you\'re not around to ensure UI response times remain tolerable.<br><br>Dare\'s point was that Twitter was built as a micro-blogging system, and that\'s how blogging systems work. You cache the hell outta everything, and you make a choice... make some users wait for extended page renders, or burn cycles in the background to ensure that everyone gets equal treatment.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705785">\
	 <div id="dsq-comment-header-9705785" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705785" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705785" href="http://tryingthisagain.com/" target="_blank" rel="nofollow">Kurt</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705785" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705785" class="dsq-comment-message">Robert (Scoble, not the other one) -<br>Twitter does store multiple copies of each message, they\'ve said so repeatedly in various presentations.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705783">\
	 <div id="dsq-comment-header-9705783" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705783" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705783" href="http://friendbinder.com/users/rythie" target="_blank" rel="nofollow">Richard Cunningham</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705783" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705783" class="dsq-comment-message">I don\'t know if twitter are using a sharded database yet, at 350,000 users they still only had one database and read slave:<br><a href="http://highscalability.com/scaling-twitter-making-twitter-10000-percent-faster" rel="nofollow">http://highscalability.com/scaling-twitter-maki...</a><br>Dare\'s post would make sense if they have now moved to a sharded structure but my best guess is that they haven\'t had a chance to do that yet.<br><br>It seems there will be duplication at least in the caching layer (memcached),<br>everytime Scoble sends a message 25,000 per user caches get invalidated and will need repopulating by new SQL queries.<br><br>Twitter are looking to get rid of the "with others" tab from a user to avoid at least some of this very type of problem, see here:<br><a href="http://groups.google.com/group/twitter-development-talk/browse_thread/thread/89a7292e5a9eee6d" rel="nofollow">http://groups.google.com/group/twitter-developm...</a><br><br>I think charging heavy users is the wrong model.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705784">\
	 <div id="dsq-comment-header-9705784" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705784" class="dsq-comment-cite">\
	 <span id="dsq-author-user-9705784">Mogilny</span>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705784" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705784" class="dsq-comment-message">Charging is silly.<br><br>- Money won\'t help twitter right now.<br>- Charging won\'t deter "superusers".<br><br>They shouldn\'t charge, they should ban.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705750">\
	 <div id="dsq-comment-header-9705750" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705750" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705750" href="http://www.brethorsting.com/" target="_blank" rel="nofollow">Aaron Brethorst</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705750" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705750" class="dsq-comment-message">Robert: "By the way, this caused a famous and massive problem inside Microsoft when the database server filled up when someone accidentally emailed something to “all.” Email went down for two days, the way I heard it."<br><br>I think you\'re referring to Bedlam DL3, which was quite different from this. It was summarized by the Exchange team back in 2004: <a href="http://msexchangeteam.com/archive/2004/04/08/109626.aspx" rel="nofollow">http://msexchangeteam.com/archive/2004/04/08/10...</a></div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705751">\
	 <div id="dsq-comment-header-9705751" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705751" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705751" href="http://www.shahine.com/omar" target="_blank" rel="nofollow">Omar Shahine</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705751" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705751" class="dsq-comment-message">What does Exchange have to do with it? Exchange doesn\'t scale (yet) to hundreds of millions of users. Mail systems like Hotmail do in fact keep 25,000 copies of an email if that is how many hotmail users receive the same message. Doing anything else would literally saturate and melt the network (if the architecture was built around a single instance store). There is a physical limit to how much network traffic you can have going between clusters (or scale units). Ideally you optimize your IO for the access patterns of your application (lots of writes and many more reads of unique data).<br><br>BTW, the issue you are describing with Exchange failing is documented here:<br><br><a href="http://msexchangeteam.com/archive/2004/04/08/109626.aspx" rel="nofollow">http://msexchangeteam.com/archive/2004/04/08/10...</a><br><br>And it wasn\'t a failure for the reasons you describe. It has to do with numerous issues and failures unrelated to db scale.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705767">\
	 <div id="dsq-comment-header-9705767" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705767" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705767" href="http://scobleizer.com/" target="_blank" rel="nofollow">Robert Scoble</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705767" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705767" class="dsq-comment-message">&gt;Open up Twitter… now, did you wait several minutes for your page to appear?<br><br>Open up FriendFeed. Refresh many times. DId the page change? It certainly wasn\'t pre-cached before I hit the servers.<br><br>Computers now are fast, if you have the right architecture.<br><br>How does Google work? It is always fast and doesn\'t pre-cache all my pages. To do that it\'d have to know what I\'m thinking before I actually searched for something.<br><br>One thing you haven\'t thought about is that even if everything was precached that only a small percentage of my 23,000 followers ever log into Twitter. So, if it\'s building a page for each of the 23,000 followers it\'s totally wasting resources.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705755">\
	 <div id="dsq-comment-header-9705755" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705755" class="dsq-comment-cite">\
	 <span id="dsq-author-user-9705755">Master William</span>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705755" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705755" class="dsq-comment-message">Now who do I believe when it comes to authority on systems architecture.<br><br>Robert Scoble or Dare Obasanjo?<br><br>lol</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705756">\
	 <div id="dsq-comment-header-9705756" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705756" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705756" href="http://www.25hoursaday.com/weblog" target="_blank" rel="nofollow">Dare Obasanjo</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705756" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705756" class="dsq-comment-message">Robert,<br>  It isn\'t clear to me why you are taking my post so personally. Regardless of how Twitter is implemented, allowing a user to have 25,000 followers and 25,000 people they are following will cause scale problems. There are different optimizations you could make (Single Instancing is not the panacea you claim, see my post at for <a href="http://www.25hoursaday.com/weblog/2008/05/26/SomeThoughtsOnSingleInstanceStorageAndTwitter.aspx" rel="nofollow">http://www.25hoursaday.com/weblog/2008/05/26/So...</a> more)  but it doesn\'t change the fact that Twitter has made some bad design and feature decisions.<br><br> As to whether people who generate massive load on the system should be charged...isn\'t that a fact of life everywhere else? Internet service providers like Comcast are known to fire customers who use too much bandwidth, in fact your buddy Dave Winer just blogged about that happening to him. Flickr, Y! Mail and a bunch of other services also charge for "pro" features. Why would Twitter pursuing such a business model be so wrong? Would you prefer to have ads in your Twitter streams?</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705759">\
	 <div id="dsq-comment-header-9705759" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705759" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705759" href="http://scobleizer.com/" target="_blank" rel="nofollow">Robert Scoble</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705759" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705759" class="dsq-comment-message">Master: I wasn\'t arguing with Dare so much about the architecture. But it\'s totally ridiculous to say that my messages are copied 23,000 times. If that were true, then Wordpress.com\'s architecture would be going down left and right cause this blog would be copied 400,000 times. It is, but in your Web browser, not on the server side.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705758">\
	 <div id="dsq-comment-header-9705758" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705758" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705758" href="http://scobleizer.com/" target="_blank" rel="nofollow">Robert Scoble</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705758" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705758" class="dsq-comment-message">Omar: one problem, Twitter isn\'t like email. First of all, only a small percentage of Twitter users ever sign into Twitter again. Let\'s say it\'s as high as 50% (I think it\'s lower). That would mean 12,500 copies. Then, not every one of those users signs in every day. Let\'s say only 50% sign in on a particular day. That\'s 6,250 copies. But how does Twitter know which users will sign in? It doesn\'t. It needs to create the pages on the fly, not copy everything to 23,000 (er, two million) separate tables in a big database. If it did that it\'d quickly die, and make it extremely hard to maintain, too.<br><br>Also, many users don\'t even use the Web interface. Most of the time I\'m looking at messages coming at me in Google Talk. Those are coming one at a time at me. Are you really seriously expecting me to believe that Twitter copies messages 23,000 times before sending them out to me via the XMPP database?</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705757">\
	 <div id="dsq-comment-header-9705757" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705757" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705757" href="http://www.shahine.com/omar" target="_blank" rel="nofollow">Omar Shahine</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705757" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705757" class="dsq-comment-message">Robert, I know Twitter isn\'t email, why did you bring up Exchange and Bedlam then?<br><br>I\'m not sure why you are being so assumptive about their architecture unless some one laid it out to you. Further some of your statements in defense(?) of what they may or may not be doing don\'t even make sense.<br><br>I\'m not being assumptive. I haven\'t said one way or another what they are doing because I have no idea. I only know of the massive large scale systems we have at Microsoft and the relative pros and cons of each. I also know each is designed to meet one general architecturural need and generally these things don\'t translate well to serve different kinds of IO. So that you might find is that within any large system you have dozens or more subsystems specifically designed to one scale problem. Some of those will require creating duplicate copies of the data if read performance is required to make your application scale OR be responsive.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705768">\
	 <div id="dsq-comment-header-9705768" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705768" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705768" href="http://twitter.com/mask" target="_blank" rel="nofollow">Alberto</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705768" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705768" class="dsq-comment-message">Robert,<br><br>Have you read the article referred by Al3x in Twitter\'s dev blog: <a href="http://www.hueniverse.com/hueniverse/2008/03/on-scaling-a-mi.html" rel="nofollow">http://www.hueniverse.com/hueniverse/2008/03/on...</a><br><br>It explains why there is a need to duplicate copies, the main reason is the speed for other APIs (i.e. FriendFeed) to read them and one of the reasons why there is not a huge delay (i.e. 10 seconds) when the tweets appear in FriendFeed, without the copying that time will be longer.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705769">\
	 <div id="dsq-comment-header-9705769" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705769" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705769" href="http://www.campusfish.com/Jeff" target="_blank" rel="nofollow">Jeff Putz</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705769" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705769" class="dsq-comment-message">I think Om\'s point was more along the lines that instead of simply bleeding cash, they could make a little. I don\'t think he was questioning the architecture.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705770">\
	 <div id="dsq-comment-header-9705770" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705770" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705770" href="http://fav.or.it/" target="_blank" rel="nofollow">Nick Halstead</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705770" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705770" class="dsq-comment-message">Scoble, I think you are fantastic and your enthusiasm for the industry is amazing, but you really should steer clear of the technical arguments.<br><br>You are trying to argue that twitter is using a \'pivot table\' - so you have one table for users, one table for messages, and a third table that describes your friend relationships. When a query comes into to see a particular users stream you think they \'mix\' this up, so you do a many-to-many lookup, so for every user (25k in your case) you then look in every one of those users message queues for the most recent messages then mash them together.<br><br>Now they may have started with a \'obvious\' schema like this about a year ago but I can assure you 1000% that this does NOT scale very far and certainly not up to the point they have got. The reason? because many-to-many lookups in any RDBM are extremely costly and secondly it is very hard to scale across hardware when you build like this, because it is almost impossible to shard because the many-to-many means everyone can potentially be joined together.<br><br>The second methodology described which you laughed at, IS SCALABLE - because you can shard to as many machine as you like for an example lets say each shard owns (10,000) users - each message you send just has to send a tiny signal to each shard of your new message - each shard then looks up within its own local database of 10,000 users to see if any of them are following you. It then adds your message to their queue.<br><br>This is a classic normalization vs de-normalization - you describe normalization in how you think it works - what I hope (and I am sure they are doing a variant of) is de-normalization.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705749">\
	 <div id="dsq-comment-header-9705749" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705749" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705749" href="http://blog.stealthmode.com/" target="_blank" rel="nofollow">Francine hardaway</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705749" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705749" class="dsq-comment-message">Spammers are taking up a lot of space on Twitter lately. Sony has a spamming bot.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705771">\
	 <div id="dsq-comment-header-9705771" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705771" class="dsq-comment-cite">\
	 <span id="dsq-author-user-9705771">Trevor Plantagenent</span>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705771" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705771" class="dsq-comment-message">I don\'t believe this, you\'re making statements that are 100% false.  Yes, every time you tweet, it\'s copied 25,000 times.  It has to work that way or it wouldn\'t have scaled as far as it has.  You\'re setting yourself up for massive humiliation when you\'re definitively proven wrong.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705772">\
	 <div id="dsq-comment-header-9705772" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705772" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705772" href="http://stut.net/" target="_blank" rel="nofollow">Stuart Dallas</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705772" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705772" class="dsq-comment-message">I agree with all the commenters saying that Twitter must be copying messages to each follower, but I really hope they\'re just copying an ID 25k times and the actual text of the message maybe just a few 10\'s of times (i.e. to multiple caches). There\'s no way it would perform as well as it does (most of the time) if it were transferring 30 gig of data every time Scoble tweets.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705773">\
	 <div id="dsq-comment-header-9705773" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705773" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705773" href="http://stut.net/" target="_blank" rel="nofollow">Stuart Dallas</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705773" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705773" class="dsq-comment-message">Scratch the 30 gig, misread Om\'s blog. Even so it would be a huge amount of data being moved about Twitter\'s internal network given that Scoble is just one of quite a few "super users" on there.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705774">\
	 <div id="dsq-comment-header-9705774" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705774" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705774" href="http://thoughtindustry.blogspot.com/" target="_blank" rel="nofollow">Craig</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705774" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705774" class="dsq-comment-message">I took a different approach than flat out charging users with mass followings:<br><br><a href="http://thoughtindustry.blogspot.com/2008/05/twitters-issues-with-scalability.html" rel="nofollow">http://thoughtindustry.blogspot.com/2008/05/twi...</a></div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705775">\
	 <div id="dsq-comment-header-9705775" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705775" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705775" href="http://joeduck.com/" target="_blank" rel="nofollow">JoeDuck</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705775" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705775" class="dsq-comment-message">I think the charging issue is irrelevant because there are so few of you.  If Twitter can\'t find a better way to monetize than smacking the  &lt;500   Superusers with huge monthly fees they are eventually going to be toast anyway.   The Flickr model seems more realistic - charge heavy users a small annual fee and put them on a more robust platform.  Heck, I\'ll pay just to keep having to hear everybody talk so much about Twitter, the challenges of which seem to have gripped the online community in a dangerously obsessive fashion.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705776">\
	 <div id="dsq-comment-header-9705776" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705776" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705776" href="http://scobleizer.com/" target="_blank" rel="nofollow">Robert Scoble</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705776" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705776" class="dsq-comment-message">Trevor: well, if every Tweet is copied for every one of its potential readers, that totally explains why Twitter has some scale problems. Most Twitter users don\'t use the service very often, if at all (I watch).<br><br>In my scenario there ARE copies. Just not automatic ones. Also, Twitter only needs to keep the last 10 Tweets cached on each user\'s page, to keep the home page fast. Other pages take forever to load, so I doubt those are cached. Even in the home page scenario my Tweets would only be copied to those users who haven\'t had my Tweets replaced by other users (most of the time my Tweets would be pushed lower, so there wouldn\'t be 23,000 copies, only, maybe 1,000).<br><br>Either way, if I\'m to blame for Twitter going down, why isn\'t FriendFeed going down? There\'s a lot more activity on FriendFeed surrounding my messages (and they aren\'t cached in any obvious way) and it\'s been down about 1/100th as much as Twitter.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705777">\
	 <div id="dsq-comment-header-9705777" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705777" class="dsq-comment-cite">\
	 <span id="dsq-author-user-9705777">Larry</span>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705777" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705777" class="dsq-comment-message">Maybe you\'re both right. Maybe it keeps a single copy of each tweet text and copies a tweet ID to each user\'s queue. The heavy-lifting of building the queue would be done at write time. To build a page it would look up each tweet ID in a user queue using a simple key-value map (which can easily be replicated and scaled.)</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705778">\
	 <div id="dsq-comment-header-9705778" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705778" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705778" href="http://deadnode.org/" target="_blank" rel="nofollow">James</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705778" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705778" class="dsq-comment-message">First, as someone has already noted, any large e-mail system will indeed duplicate messages being sent to a large number of recipients — typically a single copy per server, with each recipient getting a Unix hard link (or equivalent) to that copy.<br><br>There are several critical differences between Twitter and e-mail, however. The push or notification aspect is one, but message size is a big one. In particular, each of the hard links pointing to a single instance of an e-mail will be bigger than the entire body of a Tweet! Duplicating messages, even in pathological cases like Scoble\'s, is trivial: 25,000 copies of a 140 byte message represents a mere 3.5 Mbytes, smaller than a single large e-mail body!<br><br>Similarly, I think you\'re overestimating the burden of keeping pre-calculated per-viewer data around: the default view has about 16 messages, each 140 bytes plus a bit of metadata (sender username/icon URL), total perhaps 3.2K. 10,000 users on the server? 32 Mb! Trivial. Even ten *million* users on a single node would fit on a PC you can buy online from Dell!<br><br>The best architecture is probably a hybrid: keep the recent message queue in RAM for active users (and update realtime when those they follow post messages), built the cache from disk when they log in. Even on a single host, with 15kRPM drives (4ms writes), that\'s 100 spindle-seconds; a pair of Apple\'s 16-drive arrays and you\'re looking at three seconds to process a Scoble-tweet, ignoring both write merging and RAID overhead.<br><br>In reality, of course, you can omit a lot of those write-barriers and re-issue the writes from a redo log in the event of a crash, cutting the write load still further. Mirror the writes and distribute reads consistently, you get failover and gain cache hits to boot (each server only sees half as many active users).<br><br>Or you write it all in Ruby and SQL then throw a kajillion dollars worth of hardware at making it all sort of work most of the time through brute force. Even $15m can only buy you so much brute force, though...</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705779">\
	 <div id="dsq-comment-header-9705779" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705779" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705779" href="http://friendbinder.com/users/rythie" target="_blank" rel="nofollow">Richard Cunningham</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705779" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705779" class="dsq-comment-message">Everyone should read Nick Halstead\'s comment.<br><br>Robert, I\'m sure from reading these comments that the people talking about the technical problems understand how a the normalized databases they teach you in Computer Science course work. It just that large system can\'t use them (flickr for example doesn\'t it\'s sharded / de-normalized)<br><br>I don\'t think is twitter is sharded yet since they weren\'t at 350,000 users (<a href="http://highscalability.com/scaling-twitter-making-twitter-10000-percent-faster" rel="nofollow">http://highscalability.com/scaling-twitter-maki...</a>)<br>They certainly SHOULD be copying messages around if they are sharded.<br><br>You would think if they could get to 350,000 users on one database they could get to 1 million users by adding some database read-only slave servers.<br><br>Scaling isn\'t about saving disk space, CPU cycles, memory - that is being efficient it\'s not the same thing. Microsoft might try that with Exchange to reduce their customers hardware costs (not that it works from what I hear)<br><br>Scaling is knowing you can buy a rack of machines of servers and actually make them reduce your load.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705781">\
	 <div id="dsq-comment-header-9705781" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705781" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705781" href="http://fav.or.it/" target="_blank" rel="nofollow">Nick Halstead</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705781" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705781" class="dsq-comment-message">Could not resist typing up my complete thoughts on scaling twitter - <a href="http://blog.fav.or.it/2008/05/26/fixing-twitter/" rel="nofollow">http://blog.fav.or.it/2008/05/26/fixing-twitter/</a></div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705782">\
	 <div id="dsq-comment-header-9705782" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705782" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705782" href="http://www.tomstechblog.com/" target="_blank" rel="nofollow">Tom</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705782" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705782" class="dsq-comment-message">I just wanted to put in another "Everyone should read Nick Halstead’s comment" vote.  Honestly, there are many things I admire about Scoble (getting the obligatory compliment before the insult out of the way) but this post is just ridiculous from at technical perspective.<br><br>As far as “charging super users” goes it isn’t really worth arguing because its going to be different for every service.<br><br>This is why you need a business model.  To determine which ways of making money will be most effective and execute on them.  Charging super users will be right in some cases while being wrong in others (depending on how much value the company in question can put into the “charged” scenario)</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705753">\
	 <div id="dsq-comment-header-9705753" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705753" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705753" href="http://www.munkiihouse.com/" target="_blank" rel="nofollow">Tony Fendall</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705753" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705753" class="dsq-comment-message">The whole debate is stupid!  Why does no one seem to get it?<br><br>Could a team of competent software engineers build a system which could handle this many users? Yes!<br>Should twitter have a system which can handle this many users? Yes!<br><br>I don\'t understand why people are so keen to defend poor service. If it\'s broke, then the twitter guys should fix it.  That means better code, more servers, what ever it takes.<br><br>If the problem is that they can\'t find a way to monetize it, then that\'s a different problem, but one where having lots of users should help, not hinder.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705754">\
	 <div id="dsq-comment-header-9705754" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705754" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705754" href="http://secondthoughts.typepad.com/" target="_blank" rel="nofollow">Prokofy Neva</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705754" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705754" class="dsq-comment-message">We used to have this thing in the \'90s for people who wanted to broadcast to a large audience -- it was called "television". And we had this other thing you could use to interact with the broadcaster, called "the U.S. Postal Service". The fun part was when a guy like Dave Letterman would read your letter right there on the air, when he was broadcasting.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705752">\
	 <div id="dsq-comment-header-9705752" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705752" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705752" href="http://falkayn.blogspot.com/2008/05/oms-got-wrong-business-model-for.html" target="_blank" rel="nofollow">Angus McDonald</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705752" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705752" class="dsq-comment-message">Om\'s gotten it totally wrong. Twitter should charge your followers (past perhaps the first 100) for the privilege of getting access to your opinions faster. The website could remain free, but most twitterers I know use desktop clients to keep abreast, and so following someone is the only way to do that.<br><br>Charging 10 cents per month to each follower after the first would reap a far greater income for them, and annoy interesting twitterers less!<br><br>See my blog post for more:<br><a href="http://falkayn.blogspot.com/2008/05/oms-got-wrong-business-model-for.html" rel="nofollow">http://falkayn.blogspot.com/2008/05/oms-got-wro...</a></div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705760">\
	 <div id="dsq-comment-header-9705760" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705760" class="dsq-comment-cite">\
	 <span id="dsq-author-user-9705760">Brian</span>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705760" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705760" class="dsq-comment-message">"Sweet how you never had to work with an Exchange server which did exactly that, and then added ‘All’ as a recipient to the address book of every user.<br><br>Exchange never ever stored a message per user.  If all users are on the same Exchange server and sent a message from someone on the same Exchange server, it it only stored ONCE.  That\'s been the case since Exchange 4.0.  Bedlam had more to do with people hitting Reply All  to an alias that had users on different servers.  It was the message queue that caused the primary problems during Bedlam.<br><br>In Exchange 2007 there is a deemphasis on SIS--it only applies to attachments.  Not sure what the scaling problems are with Twitter as I have no idea how the system is designed.  But, it would be safe to figure that whether or not they use SIS is not the source of their instability.<br><br>Now, back to your regularly scheduled debate about an non-scalable, useless communication tool.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705761">\
	 <div id="dsq-comment-header-9705761" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705761" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705761" href="http://www.rabidspacedog.com/" target="_blank" rel="nofollow">Ethan Ambabo</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705761" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705761" class="dsq-comment-message">Another aspect of the problem is that so many people use twitter in near-constant streams throughout multi-hour events so as to give "live" coverage of an event or just their stream of thought (case in point: the owner of this blog). I\'m certain that taking all those SMS\'s in, displaying them, and broadcasting them out to webpages, RSS feeds, and then more phones is taxing to say the least. Look at the times it goes down and I\'m sure you\'ll see a major correlation with tech events. I understand that some have found this useful, but I really don\'t and it\'s a sure fire way to get me to unfollow you, and I can guarantee why Twitter\'s user base hasn\'t diversified beyond "social techies."<br><br>Solution? Create a new service on top of twitter for twitter-streams, because obviously people don\'t get the idea behind 120-character limits (by the way, SMS has a 160-character limit) and hold their tweetstorms in a buffer to digest and spew out to followers when the server load can handle it.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705762">\
	 <div id="dsq-comment-header-9705762" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705762" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705762" href="http://twitter.com/mask" target="_blank" rel="nofollow">Alberto</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705762" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705762" class="dsq-comment-message">With Nick\'s explanation on why de-normalization is needed to scale, it is clear one of the complex issues Twitter has to solve. The other one mentioned in this post is the business model, or when to charge.<br><br>Angus has the right idea - charging the followers - although I don\'t agree on the analysis. Still using Robert as the super-user, he should not be charged because of his tweets, but for the number of people he is following. Each tweet sent by the friends Robert is following will be copied on his queue (well the tweet ID) and the size and freshness of this queue (visually the \'With Others\') can be used as the factor to charge.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705763">\
	 <div id="dsq-comment-header-9705763" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705763" class="dsq-comment-cite">\
	 <span id="dsq-author-user-9705763">Jerry</span>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705763" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705763" class="dsq-comment-message">Like they say, you get what you pay for.  You want better SLA\'s and uptime?  Crack open your wallet.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705764">\
	 <div id="dsq-comment-header-9705764" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705764" class="dsq-comment-cite">\
	 <span id="dsq-author-user-9705764">pwb</span>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705764" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705764" class="dsq-comment-message">Does anyone *actually* know how Twitter does what is does? Given the 140 byte limit, Twitter seems very "doable" with some basic design choices. This is why I think Ruby/Rails may really be a culprit here...it\'s too high level to support some of the things Twitter needs to do.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705765">\
	 <div id="dsq-comment-header-9705765" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705765" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705765" href="http://www.geekazine.com/" target="_blank" rel="nofollow">geekazine</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705765" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705765" class="dsq-comment-message">Wow. Lots of interesting comments. Then again, lots of BLAH, BLAH, BLAH.<br><br>Here\'s a fact that people are overlooking. Traffic brings revenue. Let\'s say that the 25,000 posts get counted. What does that really amount to?<br><br>That means that 25,000 people are looking at what Robert Scoble is saying. If I was a person that wants to get out my product name, then I think I would pay Twitter to keep the service going. Better yet I might ask and pay Robert to push my wares.<br><br>About a month back I @(replied) Robert on something. I believe it was during one of many Twitters\' "Problems". The exchange was short and sweet. However, I looked at my Followers an hour later, it jumped up 15 (which it doesn\'t normally do).<br><br>I tested the water by @ another person. The same thing happened. I gain more followers by replying to high profile twitters.<br><br>Now, apply that all to a marketing model. Communication can mean $$. I guess that\'s why Twitter was able to raise 20 million on it\'s own.<br><br>The problem isn\'t the Twitterflood. If that was the case then sites like MySpace and Facebook would be going down on a daily basis. If it DOES do what OM Malik suggests, then Twitter needs to look at their internal structure. Not at Robert Scoble, or Leo Laporte.<br><br>Limits and subscription fees are a great way to kill the idea. Some will pay for it, while others will say "See ya". Twitter will fall like a ball of flame into the Pacific Ocean.<br><br>They keep the idea fresh. To most, Twitter is an "Oh, I heard of that". People might know about it, but never signed up. Oncemore, Twitter can easily become a cash cow. The data that comes into Twitter is like when Daffy Duck found the Sultan\'s cave.<br><br>I\'M RICH! I\'M WEALTY BEYOND MY WILDEST DREAMS!!!...<br><br>Keep going Scoble. I\'m listening...</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705766">\
	 <div id="dsq-comment-header-9705766" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705766" class="dsq-comment-cite">\
	 <span id="dsq-author-user-9705766">Trevor Plantagenent</span>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705766" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705766" class="dsq-comment-message">I don\'t see why not to charge the supertweeters, they pay whoever hosts their blogs, don\'t they?  They\'re using Twitter as their personal blogging platform, no difference.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705808">\
	 <div id="dsq-comment-header-9705808" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705808" class="dsq-comment-cite">\
	 <span id="dsq-author-user-9705808">BSally</span>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705808" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705808" class="dsq-comment-message">Does it really cost that much to host someone\'s Tweets, even if they are quite frequent?  If so, that seems like an inefficient model.  I feel like most sites practice some form of economies of scale to where frequent users actually become more affordable (and therefore receive price breaks)... so, for example, Twitter might charge 2 cents for every 10 posts to relatively infrequent users like myself, and 2 cents for every 100 posts to frequent updaters.  Keeping costs low for busy Twitterers would also increase business for them, since people are more likely to check your site frequently when it is frequently updated.  If Twitter has difficulties understanding this, I can recommend a <a href="http://www.booksonboard.com/index.php?BODY=viewbook&amp;BOOK=132378" rel="nofollow">Basic Economics textbook (ebooks version)</a>.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705809">\
	 <div id="dsq-comment-header-9705809" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705809" class="dsq-comment-cite">\
	 <a id="dsq-author-user-9705809" href="http://siliconvalleymusings.com/" target="_blank" rel="nofollow">Steve Wilhelm</a>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705809" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705809" class="dsq-comment-message">"First of all, Twitter doesn’t store my Tweets 25,000 times. It stores them once and then it remixes them."<br><br>I do know how Twitter is built. However, "back in the day," I was the development manager for a real-time, stock quote delivery system, so I do have some experience with architectural issues Twitter may be facing.<br><br>Let\'s look at the procedure Robert refers to as "remixes them." In the simplest architecture, there would be a single list (database, flat file, etc) of all the twitters created by everyone stored in chronological order.  You may, as a storage optimization, just store a user id with the twitter string, and tweet time stamp (aka a tweet).<br><br>In this single architecture, a "remix" would require a query across all the tweets for a period of time for all people that a user follows. This query would be fairly fast when the number of tweets in the specified period of time is fairly small, and the number of users a person follows is fairly small. You can see that this type of query becomes more expensive when the number of users you follow increases and the overall number of tweets per period increases.<br><br>So to speed up this query, you could build some kind of index based on users.  But maintaining this  index would become expensive, especially during high incoming tweet periods.<br><br>So one might try to optimize this architecture by breaking up the universal store into list of tweets per person. Now each incoming tweet can be easily added to the user\'s tweet list.<br><br>Then the "remix" of tweets of the people you follow would require a join across each list and then sorted by chronological order.  This would become increasingly more expensive when a user starts to increase the number of people they follow. It would be particularly expensive for super users who follow lots of users.<br><br>A reasonable compromise might be to keep a single universal stream of tweets in chronological order and two lists for each user: a list of pointers of all their tweets, and a list of pointers to all the tweets from the people they follow.<br><br>Maintaining these three lists would look something like: sender publishes a tweet, it is added to the universal store, a pointer is then added to the sender\'s tweet list, and then "push the tweet to followers" by walking sender\'s list of followers and add a pointer to the tweet to each "follow" list.<br><br>This approach scales fairly well. It allows the act of updating the follow lists to be partitioned across multiple servers. Each server can just take (using shared queues) a tweet from the universal store and "fan it out" to the appropriate followers. It also can be separates the operation from the inbound tweet processing.<br><br>To optimize the "fan it out" process, messaging publish and subscribe product like JMS or TIBCO Rendezvous and broadcast the tweets to the servers that manage follow lists. This would require a universal store process to publish all tweets and a cloud of follow list managers listening (aka subscribing) to tweet broadcasts updates for each followed person.<br><br>This approach also nicely addresses Twitter\'s need to separate outbound follower queues for users that have requested point to point delivery of messages via Instant Messaging and SMS.<br><br>For further scaling optimzation, you can have several tweet stores instead of one single universal store. You just need to ensure that all incoming tweets from a particular user are added to the same store to maintain ordered delivery to followers.<br><br>So it is quite reasonable to copy (at least references) each of Robert\'s tweets 25,000 times, just do so in a scalable manner.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705810">\
	 <div id="dsq-comment-header-9705810" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705810" class="dsq-comment-cite">\
	 <span id="dsq-author-user-9705810">sam ism</span>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705810" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705810" class="dsq-comment-message">Life is a very short journey and we are not here to waste it in using Twitter, Facebook, iPhone, Flickr,ETC..  then simple die.I just don\'t get it how do we benefits the community and the people by using these things what is the meaning of these things in life. people are dying all over the world and we are using Twitter to stay in touch with friends.</div>\
	 </div>\
	 </li>\
	 <li id="dsq-comment-9705780">\
	 <div id="dsq-comment-header-9705780" class="dsq-comment-header">\
	 <cite id="dsq-cite-9705780" class="dsq-comment-cite">\
	 <span id="dsq-author-user-9705780">Edvin Aghanian</span>\
	 </cite>\
	 </div>\
	 <div id="dsq-comment-body-9705780" class="dsq-comment-body">\
	 <div id="dsq-comment-message-9705780" class="dsq-comment-message">Mr. Scoble,<br><br>  I must say that I have not really cared enough to read your column in the past. After reading this post, however, I will make sure never to read anything else you choose to write. What I see is a person that is clearly ignorant about a complex set of topics related to application design and scalability, speaking sophomorically about them. Perhaps you should take some time, in your case, a great deal of it, and educate yourself about these matters before speaking great volumes of nonsense relating to the technical implementation of this or any other application.<br><br>  Start by reading the comments here and questioning some of the very smart people, who have graciously taken the time to try and educate you. Please, for the sake of the thousands of people that clearly believe you to be an authority on matters of technology, stop this idiocy.</div>\
	 </div>\
	 </li>\
	 </ul>\
';

(function() {
	
	





Dsq.Debug.profile(function() {
	if(Dsq.jsonData.request.page == 1 && Dsq.jsonData.request.is_initial_load) {
		Dsq.container.innerHTML = Dsq.Templates.header() + Dsq.container.innerHTML + Dsq.Templates.footer();
	}
	Dsq.$(Dsq.curPageId).innerHTML = Dsq.$(Dsq.curPageId).innerHTML.replace(Dsq.COMMENTS_RE, Dsq.CommentsHandler);
}); // Dsq.Debug.Profile

// HACK: Resetting cache because we're done with.
Dsq.Utils.gebiFromElementCollectionCache = null;


	
	
	var dsq_styleEl = document.getElementById(disqus_container_id);
	var dsq_anchorEl = document.getElementsByTagName('a')[0];
	
	Dsq.Thread.fc = Dsq.Utils.getStyle(dsq_styleEl, 'color');
	if(dsq_anchorEl) { Dsq.Thread.ac = Dsq.Utils.getStyle(dsq_anchorEl, 'color'); }
	Dsq.Thread.ff = Dsq.Utils.getStyle(dsq_styleEl, (Dsq.Utils.ie || window.opera ? 'fontFamily' : 'font-family'));
	// For Safari / Opera: strip quotes.
	Dsq.Thread.ff = Dsq.Thread.ff.replace(/['"]/g, '');
	Dsq.Thread.fc = encodeURIComponent(Dsq.Thread.fc);
	Dsq.Thread.ac = encodeURIComponent(Dsq.Thread.ac);
	Dsq.Thread.ff = encodeURIComponent(Dsq.Thread.ff);

	
	
	
	if(Dsq.$(Dsq.Templates.addPostContainer)) {
		// TODO: Check to see if theme uses postmessage.
		if (window.disqus_use_postmessage) {
			Dsq.frames['reply_0'] = new Dsq.ReplyFrame(Dsq.$(Dsq.Templates.textareaContainer));
			Dsq.frames['reply_0'].init(function() {
				// Use fallback iframe
				Dsq.$(Dsq.Templates.addPostContainer).innerHTML = '';
				var theme = (typeof disqus_frame_theme == 'undefined') ? 'default' : disqus_frame_theme;
				Dsq.Iframes.showReplyIframeInContainer(Dsq.$(Dsq.Templates.addPostContainer), null, {theme: theme});
				// if(Dsq.Utils.ie) { Dsq.Utils.fixIframesIE(); }
			});
		} else {
			// DEPRECATED
			Dsq.Iframes.showReplyIframeInContainer(Dsq.$('dsq-post-add'));
		}
	}

	
	

	
	if(document.location.hash != '') {
		document.location.hash = document.location.hash.substring(1);
	}

	Dsq.Popup.showCookieMsgs();

	
	if(document.location.search != '' && location.hash != '#disqus_thread') {
		var reply_id = Dsq.Utils.getRequestParams().dsq;
		if(reply_id) { document.location.hash = 'comment-' + reply_id; }
	}

	
	if((typeof OB_Script != 'undefined') && (typeof OB_versionNum != 'undefined')) {
		if(navigator.userAgent.indexOf("Firefox") != -1) {
			if(window.frames['dsq-reply-frame']) {
				window.frames['dsq-reply-frame'].location = Dsq.Urls.REPLY + (new Date()).getTime() + '&f=scobleizer&t=should_services_charge_8220super_users8221&to_redirect=' + encodeURIComponent(window.location) + '&ifrs=' + encodeURIComponent(disqus_iframe_css);
			}
		}
	}

	if (Dsq.jsonData.integration.theme == 4) {
		if (Dsq.jsonData.realtime_enabled) {
			Dsq.Realtime.initialize();
		}
	}

	



	window.ExecuteWhen = (function () {
	var obj = {}
	
	// Private
	var running = false;
	var timer = null;
	var pending = [];
	var startTimer = function() {
		running = true;
		timer = setInterval(obj.heartBeat, 100);
	};
	var stopTimer = function() {
		running = false;
		clearInterval(timer);
	};
	
	// Public
	obj.add = function (condition, code) {
		pending.push([condition,code]);
		this.heartBeat(); //!
		if (!running) {
			startTimer();
		}
	};
	obj.heartBeat = function() {
		if (!pending.length) {
			stopTimer();
		}
		var newPending = [];
		for (var i=0; i<pending.length; i++) {
			var cond = pending[i][0];
			var code = pending[i][1];
			// FIXME: if cond or code throw an error, they never get removed from pending
			if (cond()){
				code();
			}
			else {
				newPending.push([cond, code]);
			}
		}
		pending = newPending;
	};
	return obj;
})();

// also used in embed_thread.js:
window.fbIsReady = function () {return window.FB && FB.init;};
// NOTE: This script gets executed again without threadEl
//       set when we are loaded again as the fbc_receiver.
//       In this case, we don't need the hidden container.

if(!window.FB || !FB.init) {
	if(window.Dsq && Dsq.container) {
		// container is not present when init.js is loaded from an xd-receiver iframe; in this case,
		// we don't need the FB_HiddenContainer anyway.
		var fbDiv = document.createElement('div');
		fbDiv.id = "FB_HiddenContainer";	// Required or else FeatureLoader will execute a document.write.
		fbDiv.style.position = 'absolute';	// This is intentionally not setting display to none as this breaks
		fbDiv.style.top = '-10000px';		// Flash in Safari.
		fbDiv.style.left = '-10000px';
		fbDiv.style.width = '0px';
		fbDiv.style.height = '0px';
		Dsq.container.appendChild(fbDiv);
	}
	var fbJS = document.createElement('script');
	fbJS.type = "text/javascript";
	fbJS.src = "http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php";
	document.getElementsByTagName('head')[0].appendChild(fbJS);

	ExecuteWhen.add(window.fbIsReady,
		function () {
			// HACK: This is a workaround FBC's single domain limitation by
			//		 allowing sites to create multiple forums with different
			//		 Facebook API keys.  This must be used in conjunction with
			//		 disqus_facebook_forum (see authenticateFacebook).
			var facebook_api_key = 'faaf467d0f47abde553c3b8e0e1b3570';
			if (typeof disqus_facebook_api_key != 'undefined') {
				facebook_api_key = disqus_facebook_api_key;
			}

			FB.init(facebook_api_key, window.facebookXdReceiverPath || null,
				{fetchSignedPublicSessionData: true});
		});
}


	


if(typeof(disqus_callback) == 'function') {
	var callback_params = Dsq.Utils.getRequestParams()['dsq_cbp'] || null;

	// We don't care about any errors in third-party code
	try {
		disqus_callback(callback_params);
	} catch (x) {
		if (typeof(console) != 'undefined' && typeof(console.log) == 'function') {
			// But it would be nice to let developers know about them
			console.log(x);
		}
		// pass
	}

	// HACK: We don't know if the callback wraps our container, which may
	// possibly result in a new DOM element.
	Dsq.container = document.getElementById('dsq-content');
}

// Global event handler for narcissus.
if (Dsq.jsonData.integration.theme == 4) {
	var g = Dsq.Utils.ie ? document : window;
	Dsq.Utils.addEventListener(g, 'keydown', function(event) {
		// Handle "enter" key on input for post box.
		if ((event.keyCode || event.which) == 13) {
			var target = Dsq.Utils.ie ? event.srcElement : event.target;
			// For Safari bug, detect text node.
			if (target.nodeType == 3) {
				target = target.parentNode;
			}

			if (target.nodeName == 'INPUT' &&
				target.parentNode.className == 'dsq-input-wrapper') {
				var postId = Dsq.Utils.extractId(target);
				Dsq.Templates.postComment(postId, this, false);
			}
		}
	});
}

})();




