<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>{5} Setfive - Talking to the World &#187; walled garden</title>
	<atom:link href="http://shout.setfive.com/tag/walled-garden/feed/" rel="self" type="application/rss+xml" />
	<link>http://shout.setfive.com</link>
	<description></description>
	<lastBuildDate>Wed, 18 Jan 2012 21:09:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Use Greasemonkey to extract your Facebook Phonebook</title>
		<link>http://shout.setfive.com/2009/03/06/use-greasemonkey-to-extract-your-facebook-phonebook/</link>
		<comments>http://shout.setfive.com/2009/03/06/use-greasemonkey-to-extract-your-facebook-phonebook/#comments</comments>
		<pubDate>Fri, 06 Mar 2009 08:34:20 +0000</pubDate>
		<dc:creator>anonymous</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[fbconnect]]></category>
		<category><![CDATA[greasemonkey]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[walled garden]]></category>

		<guid isPermaLink="false">http://shout.setfive.com/?p=120</guid>
		<description><![CDATA[7/19/2010 UPDATE: There is a BRAND NEW version of the script available on Userscripts here. 10/12/2009 UPDATE: Added fixes from Marcel Chastain UPDATE: It looks like the version that got uploaded was missing a * in the trigger URL! That might be the issue everyone is having. UPDATE: Video of the process: fbimport Facebook&#8217;s API [...]]]></description>
			<content:encoded><![CDATA[<p style="font-size: 20px; font-weight: bold; line-height: 2px; color: red">
7/19/2010 UPDATE: There is a BRAND NEW version of the script available on Userscripts <a href="http://userscripts.org/scripts/show/43681" target="_blank">here</a>.
</p>
<p style="font-size: 18px; color: red">
10/12/2009 UPDATE: Added fixes from <a href="http://twitter.com/MarcelChastain" target="_blank">Marcel Chastain</a></p>
<p>UPDATE: It looks like the version that got uploaded was missing a * in the trigger URL! That might be the issue everyone is having. <br/> <br/><br />
UPDATE: Video of the process: <a href='http://shout.setfive.com/wp-content/uploads/2009/03/fbimport.swf'>fbimport</a><br />
<br/>
</p>
<p>Facebook&#8217;s API + FBConnect is great but it has some severe limitations. Notably, it doesn&#8217;t expose all the functionality available on the Facebook  site. Tonight in particular, I wanted to be able to copy a dump of my friends&#8217; names and phone numbers off the site to load into a fresh cell phone. Unfortunately, looking at the API this isn&#8217;t possible.</p>
<p>Never fear &#8211; Greasemonkey provides enough of a hook into Firefox that it would be possible to write a UserScript to accomplish this.</p>
<p>Continuing beyond this point is probably against the Facebook TOS and will probably severely void your warranty.</p>
<p>You have been warned.</p>
<p>The following describes how to use this userscript to extract your Facebook &#8220;Phonebook&#8221;. It produces of a CSV of your friends&#8217; names and phone numbers. Fair warning &#8211; this is a rough prototype and does almost no error handling. Also, since the &#8220;Phone&#8221; field is a free text field I can&#8217;t promise people will have formatted their numbers in any sane fashion. But either way it&#8217;s a good start to revering lost numbers.</p>
<p>So here is what you need to do to use the script:</p>
<p>1. Install Greasemonkey &#8211; <a href="https://addons.mozilla.org/en-US/firefox/addon/748">https://addons.mozilla.org/en-US/firefox/addon/748</a></p>
<p>2. Follow these instructions to install the script &#8211; <a href="http://userscripts.org/about/installing">http://userscripts.org/about/installing</a></p>
<p>Edit: The script is also on Userscripts at <a href="http://userscripts.org/scripts/show/43681">http://userscripts.org/scripts/show/43681</a></p>
<p>3. Navigate over to http://m.facebook.com/friends.php? (You&#8217;ll have to login)</p>
<p>4. Answer yes to the prompt and sit back &#8211; the script will move through your phonebook and eventually dump you a CSV of the results.</p>
<p>5. Copy/Paste the CSV wherever you want.</p>
<p>6. Un-install the Greasemonkey script.</p>
<p>So that&#8217;s it, one less walled garden to worry about. And hopefully one less &#8220;I lost my cellphone!&#8221; event/group on facebook!</p>
<p>The script:</p>
<p><a href="http://shout.setfive.com/wp-content/uploads/2009/03/fb_phonebookuser.js">Facebook Phonebook Exporter</a></p>
<pre name='code' class='javascript'>
// ==UserScript==
// @name           fb phonebook
// @namespace      setfivefb
// @description    Scrapes your Facebook friend's phone #s and optionally email addresses. Login to http://m.facebook.com/ and navigate to http://m.facebook.com/friends.php?a&#038;rf6e4c397&#038;refid=5
// @include        http://m.facebook.com/*
// ==/UserScript==

var s = document.createElement('script');
s.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js';
s.type = 'text/javascript';

document.getElementsByTagName('body')[0].appendChild(s);

s.addEventListener('load', function(){
  jQuery = unsafeWindow['jQuery'];
  jQuery.noConflict();

  var queryString = unsafeWindow["window"].location.search;

  if( queryString.indexOf("sfScraper") > 0 ){

	  var localStorage = unsafeWindow['localStorage'];
	  var scrapeWhat = JSON.parse( localStorage.getItem("sfScrapeWhat") );

	  if( scrapeWhat.emailsDone ){
		  extractEmailandPhones();
		  return false;
	  }

	  if( scrapeWhat.phone ){
		  scrapePhoneContacts();
		  return false;
	  }

	  if( scrapeWhat.email ){
		  scrapeEmailContacts();
		  return false;
	  }

	  return false;
  }

  if( jQuery("b:contains('Everyone')").length ){

	  var localStorage = unsafeWindow['localStorage'];
	  localStorage.removeItem("sfStoredContacts");
	  localStorage.removeItem("sfScrapeWhat");
	  localStorage.removeItem("sfContactLinks");

	  jQuery("#title").after("
<div style='background-color: #E6EFC2; color:#264409; border-color:#C6D880; font-weight: bold; padding: 10px; font-size: 18px'>"
							+ "What do you want to save?
<form id='sf-scraperFrm'>
<input name='sf-scrapeWhat' type='radio' value='p' id='sf-phoneNumbers' /> Phonenumbers
<input name='sf-scrapeWhat' type='radio' value='e' /> Phonenumbers and Emails"
							+ "&nbsp;&nbsp;
<input type='button' id='sf-scrapeBtn' value='Start' style='font-size: 18px' /></form>

"
							+ "</div>

");

	  jQuery("#sf-scrapeBtn").click( function(){

		var scrapeWhat = { phone: false, email: false, emailsDone: false };

		jQuery("#sf-scraperFrm input:checked").each( function(){

				if( jQuery(this).val() == "p" ){
					scrapeWhat.phone = true;
				}else if( jQuery(this).val() == "e" ){
					scrapeWhat.email = true;
				}
		});

		localStorage.setItem("sfScrapeWhat", JSON.stringify(scrapeWhat));

		if( scrapeWhat.phone ){ scrapePhoneContacts(); }
		if( scrapeWhat.email ){ scrapeEmailContacts(); }

		return false;
	  });

  }else{
	  jQuery("#marquee_tabs").after("
<div style='background-color: #FFF6BF;color:#514721;border-color:#FFD324; font-weight: bold; padding: 10px; font-size: 18px'>You need to switch to the Friends -&gt; 'Everyone' tab for the scrapper to become active.</div>

");
  }

}, false);

function extractEmailandPhones(){

	var contacts = localStorage.getItem("sfStoredContacts");
	var contactLinks = JSON.parse( localStorage.getItem("sfContactLinks") );

	if( contacts == null ){
		contacts = [ ];
	}else{
		contacts = JSON.parse( contacts );
	}

	var name = jQuery(".section_title:first").text();
	var email = jQuery("td:contains('Email:')").next("td:first").text();
	var phone = jQuery("td:contains('Mobile Number:')").next("td:first").text();

	contacts.push( {"n": name, "p": phone, "e": email} );

	localStorage.setItem("sfStoredContacts", JSON.stringify(contacts) );

	jQuery(".section_title:first").after("
<div style='background-color: #FFF6BF;color:#514721;border-color:#FFD324; font-weight: bold; padding: 10px; font-size: 18px'>"
								+ "Links left: " + contactLinks.length + "</div>

");

	if( contactLinks.length ){
		unsafeWindow["window"].location = contactLinks.pop();
		localStorage.setItem("sfContactLinks", JSON.stringify(contactLinks) );
		return false;
	}

	var textArea = "Name,Phone,Email \n";
	jQuery.each(contacts, function(i, val){ textArea += val.n + "," + val.p + "," + val.e + "\n"; });

	jQuery("body").append("<textarea style='width: 500px; height: 1000px' id='sf-fbContacts'></textarea>");
	jQuery("#sf-fbContacts").val( textArea );

}

function scrapeEmailContacts(){

	var localStorage = unsafeWindow['localStorage'];
	var contactLinks = localStorage.getItem("sfContactLinks");

	if( contactLinks == null ){
		contactLinks = [ ];
	}else{
		contactLinks = JSON.parse( contacts );
	}

	jQuery("tr[valign='top']").each( function(){
		var url = "http://m.facebook.com" + jQuery(this).find("a:first").attr("href") + "&#038;v=info&#038;sfScraper=true";
		contactLinks.push( url );
	});	

	jQuery("#title").after("
<div style='background-color: #FFF6BF;color:#514721;border-color:#FFD324; font-weight: bold; padding: 10px; font-size: 18px'>"
								+ "Saved: " + contactLinks.length + "</div>

");

	localStorage.setItem("sfContactLinks", JSON.stringify(contactLinks) );

	if( jQuery("a:contains('Next')").length ){
		var nextLink = jQuery("a:contains('Next')").attr("href") + "&#038;sfScraper=true";
		unsafeWindow["window"].location = "http://m.facebook.com" + nextLink;
	}else{

		var scrapeWhat = JSON.parse( localStorage.getItem("sfScrapeWhat") );
		scrapeWhat.emailsDone = true;

		localStorage.setItem("sfScrapeWhat", JSON.stringify(scrapeWhat) );

		unsafeWindow["window"].location = contactLinks.pop();
		localStorage.setItem("sfContactLinks", JSON.stringify(contactLinks) );
	}

	return false;
}

function scrapePhoneContacts(){
		var localStorage = unsafeWindow['localStorage'];
		var contacts = localStorage.getItem("sfStoredContacts");

		if( contacts == null ){
			contacts = [ ];
		}else{
			contacts = JSON.parse( contacts );
		}

		jQuery("tr[valign='top']").each( function(){
				var name = jQuery(this).find("a:first").text();

				if( jQuery(this).find("a:contains('Call')").length ){
					var number = jQuery(this).find("a:contains('Call')")
											 .attr("href").replace("tel:", "");
					contacts.push( {"n": name, "p": number, "e": ""} );
				}
		});

		jQuery("#title").after("
<div style='background-color: #FFF6BF;color:#514721;border-color:#FFD324; font-weight: bold; padding: 10px; font-size: 18px'>"
								+ "Saved: " + contacts.length + "</div>

");

		localStorage.setItem("sfStoredContacts", JSON.stringify(contacts) );

		if( jQuery("a:contains('Next')").length ){
			var nextLink = jQuery("a:contains('Next')").attr("href") + "&#038;sfScraper=true";
			unsafeWindow["window"].location = "http://m.facebook.com" + nextLink;
		}else{
			var textArea = "Name,Phone \n";
			jQuery.each(contacts, function(i, val){ textArea += val.n + "," + val.p + "\n"; });

			jQuery("body").append("<textarea style='width: 500px; height: 1000px' id='sf-fbContacts'></textarea>");
			jQuery("#sf-fbContacts").val( textArea );
		}

		return false;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://shout.setfive.com/2009/03/06/use-greasemonkey-to-extract-your-facebook-phonebook/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
	</channel>
</rss>

