├── .gitignore ├── LICENSE ├── README.md ├── background.html ├── chrome_ex_oauth.html ├── controller.html ├── css ├── controller.css └── options.css ├── exporter.png ├── img ├── ajax-loader.gif ├── csv-icon.gif ├── gmail-logo.jpg ├── icon128.png ├── icon16.png └── icon48.png ├── js ├── content_script.js ├── controller.js ├── csv_exporter.js ├── database.js ├── exporter.js ├── gmail_exporter.js ├── grabber.js ├── lib │ ├── chrome_ex_oauth.js │ ├── chrome_ex_oauthsimple.js │ └── jquery-1.5.2.min.js ├── options.js └── settings.js ├── manifest.json └── options.html /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | *.pyc 10 | 11 | # Logs and databases # 12 | ###################### 13 | *.log 14 | 15 | # OS generated files # 16 | ###################### 17 | .DS_Store* 18 | ehthumbs.db 19 | Icon? 20 | Thumbs.db 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2010 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Facebook Exporter Contact Exporter 2 | ================================== 3 | 4 | ![Screenshot of the Chrome Extension](https://github.com/mohamedmansour/fb-exporter/raw/master/exporter.png) 5 | 6 | Your friends on Facebook made their information public to you, such as their 7 | email, phonenumber, and websites. They want you to know about them! But there 8 | is no way to extract such data and place it in your most used contact book so 9 | you can keep in touch with them. 10 | 11 | fb-exporter extension will allow you to get their contact information so you 12 | can contact them with your favorite email client. You can extract their 13 | information and transfer it to your client. 14 | 15 | Your not stealing their information, your friends are making it public for you 16 | to use them. They want you to contact them. Thats what friends do eh? 17 | 18 | Functionality 19 | ------------------- 20 | - I am reading your Facebook friends all at once in a variable. 21 | That variable allows us to instantly see the users photo in a nice collage, 22 | and export everyone at the same time without any manual process, or you can pick 23 | and choose anyone. 24 | 25 | - Not only exports your friends emails, it exports your contacts phone numbers, 26 | emails, end IM screen names such as Google Talk, Yahoo, ICQ, Skype, QQ, and MSN 27 | (Windows Live Messenger, Hotmail), and your friends birthday! 28 | 29 | - There are error handling routines as well, if Facebook doesn't like what your 30 | doing, it will stop instantaneously! You can start it back again next day or 31 | in a couple of hours. Just open up the log, and you can see errors when it happens. 32 | 33 | - The results are cached, so if you want to continue the process some other time, 34 | then no worries, it will continue from the last processed contact. 35 | 36 | - I have refactored some portions of the code and added comments where applicable 37 | I have added a better UI. For example, a Facbook style dialog instead of the 38 | custom one made before. I have changed the way the process works too. 39 | 40 | How to download 41 | --------------- 42 | - It is currently not available in the Chrome Web Store. I am decided to stop 43 | development to focus on better and more exciting things. 44 | 45 | Facebook 46 | ------------- 47 | They are converting emails into images so you cannot copy it somewhere (say what? 48 | 99% of the people copy the email into their email client). I added mechanism that catches 49 | that instantly. So you don't have to worry if they see something. The process will 50 | stop, and you can start it again the next day. When you start it again, it will pick up 51 | where it left off. 52 | 53 | 54 | Have fun! Feel free to submit patches and fork :) 55 | 56 | 57 | -------------------------------------------------------------------------------- /background.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 178 | 179 | -------------------------------------------------------------------------------- /chrome_ex_oauth.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | OAuth Redirect Page 10 | 16 | 17 | 18 | 23 | 24 | 25 | Redirecting... 26 | 27 | -------------------------------------------------------------------------------- /controller.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Facebook Friend Exporter 4 | 5 | 6 | 7 | 8 | 9 | 13 |
14 | Hi! 15 |

Couple of questions for you.

16 |
    17 |
  1. Does Facebook own your friends?
  2. 18 |
  3. Do you think Facebook owns the data about your friends, such as their 19 | email, their website, their IM name, etc. that they made public for you 20 | to see? 21 |
  4. 22 |
  5. Do you think your Facebook friends would mind if you, oh, we don't know, 23 | decided one day to email them, or visit their website? How about add them 24 | to your address book on your phone? 25 |
  6. 26 |
27 |

28 | If you answered "no" to the above questions, we can help you get your friends' 29 | contact info out of Facebook. We can export the info to your Google Contacts 30 | (GMail), among other things! 31 |

32 |

33 | Finally, this extension is open source. You can fork it now on GitHub! 34 | 35 | https://github.com/mohamedmansour/fb-exporter 36 | 37 |

38 |

39 | THIS CHROME EXTENSION IS NOT AFFILIATED WITH GOOGLE OR FACEBOOK. HERE IS A LINK 40 | TO THE FACEBOOK TERMS OF SERVICE. 41 |

42 |

43 | I have read the Terms of Service. 44 | 45 |

46 |
47 | 51 |
52 |

Fetching friend list... done. See below.

53 |

These are all the frends that will be exported, 54 | 55 | 56 |

57 |
58 | 64 |
65 |

Fetching friend details... this could take a while, especially if you're 66 | really popular!

67 |

IMPORTANT: Please don't touch your Facebook tab 68 | until we're done, thanks! If you really must have your 69 | Facebook fix right now, here you go (this will open in a new window). 71 |

72 |
73 | 77 |
78 |

All done! Please check the list below. Uncheck the friends you want to skip.

79 |

Now the fun part! Pick an export button below, and we'll get started 80 | copying your friend data there!

81 | 94 |
95 | 98 |
99 | 100 |
101 | 102 |
103 | 104 |
  • Processed
  • 105 |
  • Success
  • 106 |
  • Failed
  • 107 |
  • Cached
  • 108 |
    109 |
    110 |
    111 |

    NOTICE

    112 |

    You are logged off the mobile site. The mobile site is where we 113 | check your friends info. Please log back in and restart the process. 114 | The steps to follow are mentioned below:

    115 |
      116 |
    1. Log into http://m.facebook.com
    2. 117 |
    3. Close this window
    4. 118 |
    5. Visit http://facebook.com
    6. 119 |
    7. Click on the "Export Friends" and resume the process!
    8. 120 |
    121 |
    122 |
    124 |
    125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /css/controller.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | font-family: Verdana; 4 | color: #fff; 5 | background-color: #ccc; 6 | } 7 | ::selection { 8 | background:#FF5E99; 9 | color:#fff; 10 | text-shadow: none; 11 | } 12 | a { 13 | color: #FF5E99; 14 | } 15 | .bubble { 16 | background-color: #444; 17 | margin: 15pt; 18 | border: thick solid; 19 | position: relative; 20 | border-radius: 10px; 21 | padding: 15pt; 22 | } 23 | 24 | p { 25 | margin: 10pt; 26 | } 27 | 28 | .friend-row { 29 | position: relative; 30 | } 31 | 32 | #note { 33 | background-color: #FBEC5D; 34 | color: #615E3F; 35 | border: 1px solid #FFE600; 36 | display: none; 37 | margin: 10px 0px; 38 | padding: 0px 10px; 39 | box-shadow: 0 0 5px 5px #333; 40 | } 41 | 42 | #friendlist { 43 | padding-top: 30px; 44 | } 45 | 46 | #friendlist li { 47 | display: inline-block; 48 | position: relative; 49 | } 50 | 51 | #friendlist li span { 52 | position: absolute; 53 | bottom: 0; 54 | left: 5px; 55 | height: 20px; 56 | width: 100px; 57 | background-color: rgba(0,0,0,0.4); 58 | border-radius: 10px; 59 | font-size: 8px; 60 | line-height: 20px; 61 | text-align: center; 62 | font-weight: bold; 63 | } 64 | 65 | #friendlist li.processed span { 66 | background-color: rgba(255,255,0,0.4); 67 | } 68 | 69 | #friendlist li.success span { 70 | background-color: rgba(0,255,0,0.4); 71 | } 72 | 73 | #friendlist li.failed span { 74 | background-color: rgba(255,0,0,0.4); 75 | } 76 | 77 | #friendlist li.cached span { 78 | background-color: rgba(255,0,255,0.4); 79 | } 80 | 81 | #friendlist li.starting span { 82 | background-color: rgba(255,140,0,0.4); 83 | } 84 | 85 | #friendlist li img { 86 | width: 80px; 87 | height: 80px; 88 | margin: 5px; 89 | border: 5px solid #444; 90 | } 91 | 92 | #friendlist li img:hover { 93 | cursor:pointer; 94 | border-color: #fff; 95 | border-radius: 10px; 96 | } 97 | 98 | #friendlist li.processed img:hover { 99 | border-color: #444; 100 | } 101 | 102 | .hilite { 103 | color: #266A2E; 104 | } 105 | 106 | .tos-guarded { 107 | } 108 | 109 | #friendlist, #step2, #step3, #step4 { 110 | display: none; 111 | } 112 | 113 | #ajax-loader { 114 | display: none; 115 | } 116 | 117 | #remaining-friend-count { 118 | font-size: 11pt; 119 | position: absolute; 120 | display: none; 121 | padding: 3pt; 122 | top: 0px; 123 | right: 0px; 124 | } 125 | 126 | .friend-detail { 127 | font-size: 13pt; 128 | } 129 | 130 | .checkbox { 131 | size: 18pt; 132 | position: absolute; 133 | top: 5px; 134 | left: 5px; 135 | } 136 | 137 | .export-method { 138 | font-size: 12pt; 139 | } 140 | 141 | .export-method input { 142 | border: outset; 143 | padding: 0pt; 144 | } 145 | 146 | .export-method input:active { 147 | border: inset; 148 | } 149 | 150 | #csv-popup { 151 | position: absolute; 152 | background-color: gray; 153 | top: 40px; 154 | bottom: 40px; 155 | right: 40px; 156 | left: 40px; 157 | padding: 12pt; 158 | border: thick solid; 159 | } 160 | 161 | #csv-popup a { 162 | position: absolute; 163 | top: 0px; 164 | right: 20px; 165 | } 166 | 167 | #csv-popup span { 168 | position: absolute; 169 | top: 0px; 170 | left: 20px; 171 | } 172 | 173 | #csv-popup textarea { 174 | position: absolute; 175 | top: 30px; 176 | left: 30px; 177 | right: 30px; 178 | bottom: 30px; 179 | 180 | font-size: 10pt; 181 | } 182 | 183 | #controls { 184 | position: absolute; 185 | top: 5px; 186 | left: 30px; 187 | } 188 | 189 | #log { 190 | width: 100%; 191 | height: 200px; 192 | } 193 | -------------------------------------------------------------------------------- /css/options.css: -------------------------------------------------------------------------------- 1 | /* Extension Options Default Style */ 2 | 3 | body { 4 | min-width: 650px; 5 | font-size: 87%; 6 | font-family: Arial, Helvetica, 'Helvetica Neue', Verdana, sans-serif; 7 | margin: 10px; 8 | } 9 | 10 | #header h1 { 11 | background: url("/img/icon48.png") 0px 30px no-repeat; 12 | display: inline; 13 | margin: 0; 14 | padding-bottom: 43px; 15 | padding-left: 55px; 16 | padding-top: 40px; 17 | font-size: 150%; 18 | font-weight: bold; 19 | } 20 | 21 | h3 { 22 | color: #444; 23 | } 24 | 25 | em { 26 | font-size: 50%; 27 | font-weight: normal; 28 | } 29 | 30 | dt { 31 | width: 15em; 32 | padding: .5em; 33 | float: left; 34 | margin: 0; 35 | } 36 | 37 | dd { 38 | margin-left: 16em; 39 | padding: .4em; 40 | } 41 | 42 | a { 43 | color: blue; 44 | font-size: 100%; 45 | } 46 | 47 | p { 48 | margin: 0; 49 | padding: 0; 50 | } 51 | 52 | .extension-template { 53 | border-bottom: 1px solid #cdcdcd; 54 | margin: 10px 0; 55 | } 56 | 57 | .extension-header { 58 | background: #ebeff9; 59 | border-top: 1px solid #b5c7de; 60 | padding: 3px 5px; 61 | font-weight: bold; 62 | } 63 | 64 | .extension-options { 65 | background: #f4f6fc; 66 | border-bottom: 1px solid #edeff5; 67 | font-size: 85%; 68 | padding: 0.8em 10px; 69 | } 70 | 71 | .note { 72 | background-color: #e0f2c0; 73 | border-radius: 5px; 74 | padding: 3px 5px; 75 | margin-right: 30px; 76 | } 77 | 78 | #extension-footer { 79 | text-align: right; 80 | padding: 10px 0px; 81 | } 82 | 83 | #header { 84 | margin-bottom: 1.05em; 85 | overflow: hidden; 86 | padding-bottom: 1.5em; 87 | padding-left: 0; 88 | padding-top: 1.5em; 89 | position: relative; 90 | } 91 | 92 | #info-message { 93 | -webkit-transition-duration: 1s; 94 | display: none; 95 | background:#FDFFBD none repeat scroll 0 0; 96 | border-radius: 5px; 97 | padding: 7px 10px; 98 | margin-right: 30px; 99 | } 100 | 101 | #credits { 102 | font-size: 85%; 103 | margin-top: 1em; 104 | text-align: right; 105 | } -------------------------------------------------------------------------------- /exporter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedmansour/fb-exporter/3939d5809278c3042a5e5cfd84c9635f5783de82/exporter.png -------------------------------------------------------------------------------- /img/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedmansour/fb-exporter/3939d5809278c3042a5e5cfd84c9635f5783de82/img/ajax-loader.gif -------------------------------------------------------------------------------- /img/csv-icon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedmansour/fb-exporter/3939d5809278c3042a5e5cfd84c9635f5783de82/img/csv-icon.gif -------------------------------------------------------------------------------- /img/gmail-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedmansour/fb-exporter/3939d5809278c3042a5e5cfd84c9635f5783de82/img/gmail-logo.jpg -------------------------------------------------------------------------------- /img/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedmansour/fb-exporter/3939d5809278c3042a5e5cfd84c9635f5783de82/img/icon128.png -------------------------------------------------------------------------------- /img/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedmansour/fb-exporter/3939d5809278c3042a5e5cfd84c9635f5783de82/img/icon16.png -------------------------------------------------------------------------------- /img/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedmansour/fb-exporter/3939d5809278c3042a5e5cfd84c9635f5783de82/img/icon48.png -------------------------------------------------------------------------------- /js/content_script.js: -------------------------------------------------------------------------------- 1 | // Polling time. 2 | var PROFILE_POLL_DELAY=2000; 3 | 4 | // Communicate to both worlds, extension and website. 5 | var exportEvent = document.createEvent('Event'); 6 | exportEvent.initEvent('friendExported', true, true); 7 | 8 | // Just draw the export friends link on the top next to the other links. 9 | renderExportFriendsLink(); 10 | 11 | // Listen on extension requests. 12 | chrome.extension.onRequest.addListener(function(request, sender, sendResponse) { 13 | if(request.retrieveFriendsMap) { 14 | exportFacebookContacts(); 15 | } 16 | }); 17 | 18 | // Listen on the real DOM requests to check if friend has been exported. 19 | window.addEventListener('friendExported', function() { 20 | // Save the map to this content script world, so our extension can read it. 21 | var transferDOM = $('#fb-transfer-dom-area'); 22 | var friendsMap = JSON.parse(transferDOM.text()); 23 | 24 | // For testing, lets just view 2 users. 25 | if (0) { 26 | var i = 0; 27 | var testMap = {}; 28 | $.each(friendsMap, function(key, value) { 29 | if (i == 2) { 30 | return false; 31 | } 32 | testMap[key] = value; 33 | i++; 34 | }); 35 | delete friendsMap; 36 | friendsMap = testMap; 37 | } 38 | // Clean up since we no longer need this. 39 | $(transferDOM).remove(); 40 | $('#fb-inject-area').remove(); 41 | 42 | // Count the number of friends. 43 | var i = 0; 44 | $.each(friendsMap, function(key, value) { 45 | i++; 46 | }); 47 | 48 | // Tell the worker tab that we are set! 49 | chrome.extension.sendRequest({friendsListReceived: friendsMap}); 50 | chrome.extension.sendRequest({renderFriendsList: friendsMap, count: i}); 51 | }); 52 | 53 | /** 54 | * Switches back to the worker tab where you can see all your friends being 55 | * processed. 56 | */ 57 | function switchToWorkerTab() { 58 | // The extension will handle the case if the worker tab already exists. 59 | chrome.extension.sendRequest({switchToWorkerTab: 1}); 60 | } 61 | 62 | /** 63 | * Creates a custom Facebook lookalike dialog. 64 | * @param {Object} data A map with the following keys: 65 | * - id: The ID for this dialog. 66 | * - title: The title the appears on the header. 67 | * - message: The description of the dialog, appears middle. 68 | * - yes_text: The text for the yes button. 69 | * - yes_callback: The callback when yes clicked. 70 | * - cancel_callback: The callback when cancel clicked. 71 | * @returns {HTMLElement} The DOM of the dialog returned. 72 | */ 73 | function createFacebookDialog(data) { 74 | // Creates the confirm component. 75 | var lblConfirm = $('