Skip to content

Instantly share code, notes, and snippets.

@nemec
Created March 14, 2021 20:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nemec/b3586e41ca33ea49acb52146bdf5b931 to your computer and use it in GitHub Desktop.
Save nemec/b3586e41ca33ea49acb52146bdf5b931 to your computer and use it in GitHub Desktop.
javascript:(function()%7Bif%20(document.location.hostname%20!%3D%3D%20%22www.facebook.com%22)%20%7Balert(%22This%20script%20only%20works%20on%20www.facebook.com%22)%3Breturn%3B%7Dlet%20profileMatch%20%3D%20document.location.pathname.match(%2F%5E%5C%2F((%5Cw%7C%5C.)%2B)%5C%2Ffriends%2F)%3Blet%20username%20%3D%20null%3Bif%20(profileMatch%20%3D%3D%3D%20null)%20%7Bif%20(document.location.pathname%20%3D%3D%3D%20%22%2Fprofile.php%22%20%26%26document.location.search.indexOf(%22sk%3Dfriends%22)%20%3E%3D%200)%20%7BprofileMatch%20%3D%20document.location.search.match(%2Fid%3D(%5Cd%2B)%2F)%3B%7Dif%20(profileMatch%20%3D%3D%3D%20null)%20%7Balert(%22This%20script%20only%20works%20on%20a%20user's%20friends%20page%20%22%20%2B%22(facebook.com%2Fxxxxx%2Ffriends%20or%20%22%20%2B%22facebook.com%2Fprofile.php%3Fid%3Dxxxxx%26sk%3Dfriends)%22)%3Breturn%3B%7D%7Dusername%20%3D%20profileMatch%5B1%5D%3B%2F*%20https%3A%2F%2Fstackoverflow.com%2Fa%2F24922761%20*%2F%2F*%20by%20Xavier%20John%2C%20edited%20to%20fix%20linting%20errors%20and%20add%20multiline%20comments%20*%2Ffunction%20exportToCsv(filename%2C%20rows)%20%7Blet%20processRow%20%3D%20function%20(row)%20%7Blet%20finalVal%20%3D%20''%3Bfor%20(let%20j%20%3D%200%3B%20j%20%3C%20row.length%3B%20j%2B%2B)%20%7Blet%20innerValue%20%3D%20row%5Bj%5D%20%3D%3D%3D%20null%20%3F%20''%20%3A%20row%5Bj%5D.toString()%3Bif%20(row%5Bj%5D%20instanceof%20Date)%20%7BinnerValue%20%3D%20row%5Bj%5D.toLocaleString()%3B%7D%3Blet%20result%20%3D%20innerValue.replace(%2F%22%2Fg%2C%20'%22%22')%3Bif%20(result.search(%2F(%22%7C%2C%7C%5Cn)%2Fg)%20%3E%3D%200)result%20%3D%20'%22'%20%2B%20result%20%2B%20'%22'%3Bif%20(j%20%3E%200)finalVal%20%2B%3D%20'%2C'%3BfinalVal%20%2B%3D%20result%3B%7Dreturn%20finalVal%20%2B%20'%5Cn'%3B%7D%3Blet%20csvFile%20%3D%20''%3Bfor%20(let%20i%20%3D%200%3B%20i%20%3C%20rows.length%3B%20i%2B%2B)%20%7BcsvFile%20%2B%3D%20processRow(rows%5Bi%5D)%3B%7Dlet%20blob%20%3D%20new%20Blob(%5BcsvFile%5D%2C%20%7B%20type%3A%20'text%2Fcsv%3Bcharset%3Dutf-8%3B'%20%7D)%3Bif%20(navigator.msSaveBlob)%20%7B%20%2F*%20IE%2010%2B%20*%2Fnavigator.msSaveBlob(blob%2C%20filename)%3B%7D%20else%20%7Blet%20link%20%3D%20document.createElement(%22a%22)%3Bif%20(link.download%20!%3D%3D%20undefined)%20%7B%20%2F*%20feature%20detection%20*%2F%2F*%20Browsers%20that%20support%20HTML5%20download%20attribute%20*%2Flet%20url%20%3D%20URL.createObjectURL(blob)%3Blink.setAttribute(%22href%22%2C%20url)%3Blink.setAttribute(%22download%22%2C%20filename)%3Blink.style.visibility%20%3D%20'hidden'%3Bdocument.body.appendChild(link)%3Blink.click()%3Bdocument.body.removeChild(link)%3B%7D%7D%7Dlet%20userElems%20%3D%20document.querySelectorAll('.bp9cbjyn.ue3kfks5.pw54ja7n.uo3d90p7.l82x9zwi.n1f8r23x.rq0escxv.j83agx80.bi6gxh9e.discj3wi.hv4rvrfc.ihqw7lf3.dati1w0a.gfomwglr')%3Blet%20users%20%3D%20%5B%5B%22uid%22%2C%20%22name%22%2C%20%22url%22%5D%5D%3Bfor(let%20i%3D0%3B%20i%3CuserElems.length%3B%20i%2B%2B)%20%7Blet%20linkElem%20%3D%20userElems%5Bi%5D.querySelector('a')%3Blet%20url%20%3D%20linkElem%20%3D%3D%3D%20null%20%3F%20''%20%3A%20linkElem.href%3Blet%20userId%20%3D%20null%3Blet%20name%20%3D%20userElems%5Bi%5D.querySelector('span.oo9gr5id').innerText%3Bfor%20(const%20%5Bkey%2C%20val%5D%20of%20Object.entries(userElems%5Bi%5D))%20%7Bif(!key.startsWith('__reactProps'))%20continue%3BuserId%20%3D%20val.children%5B0%5D.props.timelineAppCollectionItem.node.id%3B%7Dusers.push(%5BuserId%2Cname%2Curl%5D)%3B%7Dif%20(users.length%20%3D%3D%3D%200)%20%7Balert('No%20friends%20found.')%3Breturn%3B%7Dfilename%20%3D%20'friends.csv'%3Bif%20(username%20!%3D%3D%20null%20%26%26%20username%20!%3D%3D%20undefined)%20%7Bfilename%20%3D%20username%20%2B%20'_'%20%2B%20filename%3B%7DexportToCsv(filename%2C%20users)%7D)()
javascript: (function() {
if (document.location.hostname !== "www.facebook.com") {
alert("This script only works on www.facebook.com");
return;
}
let profileMatch = document.location.pathname.match(/^\/((\w|\.)+)\/friends/);
let username = null;
if (profileMatch === null) {
if (document.location.pathname === "/profile.php" && document.location.search.indexOf("sk=friends") >= 0) {
profileMatch = document.location.search.match(/id=(\d+)/);
}
if (profileMatch === null) {
alert("This script only works on a user's friends page " + "(facebook.com/xxxxx/friends or " + "facebook.com/profile.php?id=xxxxx&sk=friends)");
return;
}
}
username = profileMatch[1];
/* https://stackoverflow.com/a/24922761 */ /* by Xavier John, edited to fix linting errors and add multiline comments */
function exportToCsv(filename, rows) {
let processRow = function(row) {
let finalVal = '';
for (let j = 0; j < row.length; j++) {
let innerValue = row[j] === null ? '' : row[j].toString();
if (row[j] instanceof Date) {
innerValue = row[j].toLocaleString();
};
let result = innerValue.replace(/"/g, '""');
if (result.search(/("|,|\n)/g) >= 0) result = '"' + result + '"';
if (j > 0) finalVal += ',';
finalVal += result;
}
return finalVal + '\n';
};
let csvFile = '';
for (let i = 0; i < rows.length; i++) {
csvFile += processRow(rows[i]);
}
let blob = new Blob([csvFile], {
type: 'text/csv;charset=utf-8;'
});
if (navigator.msSaveBlob) {
/* IE 10+ */
navigator.msSaveBlob(blob, filename);
} else {
let link = document.createElement("a");
if (link.download !== undefined) {
/* feature detection */ /* Browsers that support HTML5 download attribute */
let url = URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
}
let userElems = document.querySelectorAll('.bp9cbjyn.ue3kfks5.pw54ja7n.uo3d90p7.l82x9zwi.n1f8r23x.rq0escxv.j83agx80.bi6gxh9e.discj3wi.hv4rvrfc.ihqw7lf3.dati1w0a.gfomwglr');
let users = [
["uid", "name", "url"]
];
for (let i = 0; i < userElems.length; i++) {
let linkElem = userElems[i].querySelector('a');
let url = linkElem === null ? '' : linkElem.href;
let userId = null;
let name = userElems[i].querySelector('span.oo9gr5id').innerText;
for (const [key, val] of Object.entries(userElems[i])) {
if (!key.startsWith('__reactProps')) continue;
userId = val.children[0].props.timelineAppCollectionItem.node.id;
}
users.push([userId, name, url]);
}
if (users.length === 0) {
alert('No friends found.');
return;
}
filename = 'friends.csv';
if (username !== null && username !== undefined) {
filename = username + '_' + filename;
}
exportToCsv(filename, users)
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment