Skip to content

Instantly share code, notes, and snippets.

@cocoabox
Last active July 12, 2020 10:36
Show Gist options
  • Save cocoabox/a8416de35fd86263497d61f110235691 to your computer and use it in GitHub Desktop.
Save cocoabox/a8416de35fd86263497d61f110235691 to your computer and use it in GitHub Desktop.
batch convert all FetLife photos to private
// fetLife batch change all photos to private ("friends only")
//
// usage:
//
// 1. open your first photo , URL should be https://fetlife.com/users/xxxxx/pictures/yyyyy
// 2. copy paste this code to your Javascript console and hit Return
// - a new tab (window) will open; do not close this tab
// - to terminate the process, close the newly-opened tab, then reload the current window/tab
// 3. this script doesn't work all the time; to make sure every pic is now private, repeat 1~2 again
//
(function(){
const doAndWait = function (doWhat, waitSec, confirmFunc, maxRetry) {
if (! maxRetry) maxRetry = 10;
return new Promise((resolve, reject) => {
let attempt = 1;
let timer = win.setInterval(()=>{
doWhat();
let confirmed = ! confirmFunc || (typeof confirmFunc == 'function' && confirmFunc());
if (confirmed) {
win.clearInterval(timer);
resolve();
}
else {
if (++attempt > maxRetry) {
win.clearInterval(timer);
console.error(`max attempt reached while doing :`, doWhat.toString());
reject();
}
else {
// console.warn(`retrying ${attempt}/${maxRetry} :`, doWhat.toString());
}
}
}, waitSec*1000);
});
};
const sleep = function(ms) {
return new Promise(reso => {
window.setTimeout(reso, ms);
});
};
const changeToFriendsOnly = function(win_){
return new Promise((res, rej) => {
let win = win_ ? win_ : window;
let $ = win_.jQuery;
function gotoNext() {
let $nextButton = $('a[data-next-button=""]');
win.location = $nextButton.attr("href");
}
let isFriendsOnly = $("span[data-privacy-status='']").text().trim() == "Just Friends";
if (isFriendsOnly) {
gotoNext();
res({done: "already friends only"});
return;
}
// first action
doAndWait(async ()=>{
// click [edit privacy]
if ($('a[href="#cancel_edit_privacy"]').is(":visible")) {
$('a[href="#cancel_edit_privacy"]').trigger("click");
await sleep(500);
}
$("a[href='#edit_privacy']").trigger("click");
}, 0.5, // wait 0.5 sec
()=>{
// then test if the "edit privacy" combobox is visible
return $('#picture_only_friends').length == 1
&& $('#picture_only_friends:first').is(":visible")
}).then(()=>{
// next action :
let $comboBox = $('#picture_only_friends');
doAndWait(()=>{
// set the "edit privacy" combobox value to "true"
$comboBox.val("true").trigger("change");
}, 2, // wait 2 seconds
() => {
// confirm it's now just friends
let isVisible = $("span[data-privacy-status='']").is(":visible");
// TODO : isVisible ^ is not always set to True; WHY?
let isFriendsOnly = $("span[data-privacy-status='']").text().trim() == "Just Friends";
return isVisible && isFriendsOnly;
}).then(async ()=>{
// next action: changed to just friends; wait 1 sec then go to next page
console.log("zzZ... before done");
await sleep(1000);
gotoNext();
res({done: "changed"});
}, () => {
// failure
rej({error: "couldnt confirm it's now just friends"});
});
}, ()=> {
rej({error: "couldnt confirm combo box visibility"});
});
}); // Promise(res, rej)
};
const windowIsReady = function(win) {
return win
&& win.document
&& (win.document.readyState === "complete" || win.document.readyState === "interactive");
};
const waitUntilWindowIsReady = function (win, maxTime) {
if (! maxTime) maxTime = 10;
return new Promise((reso, reje) => {
let elasped = 0;
let timer = setInterval(()=>{
if (++elasped > maxTime) {
clearInterval(timer);
reje({error:"timeout"});
}
if (windowIsReady(win)) {
clearInterval(timer);
reso({done: true});
}
}, 1000);
});
};
const waitUntilLocationChanged = function (win, maxTime) {
if (! maxTime) maxTime = 10;
let oldLocation = window.location.href;
return new Promise((reso, reje) => {
let elasped = 0;
let timer = setInterval(()=>{
if (++elasped > maxTime) {
clearInterval(timer);
reje({error:"timeout"});
}
let isReady = windowIsReady(win);
let locationChanged = win && win.location
&& win.location.href !== oldLocation;
if (isReady && locationChanged) {
clearInterval(timer);
reso({done: true});
}
}, 1000);
});
};
//
// MAIN
//
let win = window.open(window.location.href);
waitUntilWindowIsReady(win).then(async function () {
while(true) {
try {
let res = await changeToFriendsOnly(win);
console.log("✔", win.location.href, ":", res);
try {
await waitUntilLocationChanged(win);
}
catch (e) {
alert("page took forever to load");
break;
}
} catch(e) {
alert(e.error);
break;
}
}
}, function() {
alert("new window never loaded ; exiting");
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment