Skip to content

Instantly share code, notes, and snippets.

@jbruggem
Last active May 11, 2018 11:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jbruggem/1cdd7a211e6bbdc1b7a3f97b0d4a7208 to your computer and use it in GitHub Desktop.
Save jbruggem/1cdd7a211e6bbdc1b7a3f97b0d4a7208 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name hubic delete
// @version 1
// @grant none
// @include https://hubic.com/home/*
// @require https://cdn.jsdelivr.net/npm/async@2.6.0/dist/async.min.js
// ==/UserScript==
var originalLocation;
// TODO: where does it hang ?
// activityTick ?
var activityTick = Date.now();
function activityHappened(){ activityTick = Date.now(); }
function mainDeleteAll(){
originalLocation = normalUrl(window.location);
window.addEventListener('hashchange', (e) => {
const deleteFirstFolder = e.oldURL.length > e.newURL.length;
console.log("hashchange! Call handleFolder", deleteFirstFolder);
setTimeout(() => handleFolder(originalLocation, deleteFirstFolder), 1000);
return true;
});
setInterval(function checkForActivity(){
// in seconds
if((Date.now() - activityTick)/1000 > 10){
console.log("Activity tick expired ! Restarting.");
activityHappened();
const parentLoc = parentLocation(originalLocation);
if(parentLoc === normalUrl){
console.log("Call handleFolder");
handleFolder(originalLocation, null);
}else{
console.log("Change location to: " + parentLoc);
window.location = parentLoc;
}
}
}, 1000);
handleFolder(originalLocation, null);
}
function handleFolder(rootLocation, deleteFirstFolder=false){
console.log("handleFolder", window.location);
activityHappened();
if(!normalUrl(window.location).startsWith(rootLocation)){
console.error("ERROR OUT OF ORIGINAL LOCATION BOUNDS");
console.error(normalUrl(window.location), rootLocation);
return;
}
const allFiles = Array.from(document.querySelectorAll(".file-line.file"));
const files = allFiles.filter((e) => !e.classList.contains("browser-file-line-operation-doing"));
async.waterfall([
(cb) => {
function wait(){
if(0 < Array.from(document.querySelectorAll("ul.browser")).length){
console.log("Page is loaded !");
cb();
}else{
console.log("Wait for page load.");
setTimeout(wait, 500);
}
}
wait();
},
(cb) => {
console.log("handleFolder: deleteFirstFolder?", deleteFirstFolder);
activityHappened();
const dirs = document.querySelectorAll(".file-line.directory");
const firstDir = dirs.item(0);
if(deleteFirstFolder && dirs.length > 0 && firstDir !== null){
console.log("handleFolder: deleteFile (folder)", firstDir);
deleteFile(firstDir, (err) => setTimeout(cb, 500));
}else{
cb();
}
},
(cb) => {
console.log("handleFolder: deleteFiles");
activityHappened();
deleteFiles(files, rootLocation, cb);
},
(cb) => {
const dirs = document.querySelectorAll(".file-line.directory");
console.log("handleFolder: dirs ", dirs);
activityHappened();
if(0 == dirs.length) {
if(normalUrl(window.location) === rootLocation){
console.log("***********************************");
console.log("FINISHED DELETING EVERYTHING");
console.log("***********************************");
} else {
console.log("handleFolder: go to parent");
window.location = parentLocation(rootLocation);
}
} else {
console.log("handleFolder: go to child");
const nextURL = normalUrl(window.location) + '/' + dirs.item(0).dataset.itemKey;
console.log(nextURL);
window.location = nextURL;
}
cb();
},
]);
}
function deleteFiles(files, rootLocation, cbEndDeleteFiles){
console.log("deleteFiles: ", files);
activityHappened();
if(files.length == 0){
console.log("No files. return.");
return cbEndDeleteFiles();
}
function checkedEnd(){
activityHappened();
if(0 < document.querySelectorAll(".file-line.file").length){
console.log("async.eachSeries ended but files remaining. Restarting.");
deleteFiles(files, rootLocation, cbEndDeleteFiles);
}else{
console.log("deleteFiles ended.");
cbEndDeleteFiles();
}
}
async.eachLimit(files, 10, deleteFile, () => {
console.log("Delete files done, waiting.");
checkedEnd();
});
}
function deleteFile(li, cbFileDeleted){
console.log("deleteFile: ", normalUrl(window.location), li.dataset.itemKey);
activityHappened();
async.waterfall([
(cbRemove) => {
console.log("remove");
async.retry({times: 5, interval: 300},
(cb) => {
activityHappened();
li.querySelector("input").click();
document.querySelector("#browser-action-others").click();
document.querySelector(".browser-other-action.browser-action-remove").click();
const button = document.querySelector(".browser-modal-action.browser-modal-main-action.ui-button.ui-button-text-only")
if(button){
button.click();
cb(null);
}else{
cb('failed');
}
},
cbRemove);
},
(cbWait) => {
console.log("wait");
async.retry({times: 40, interval: 500},
(cb) => {
activityHappened();
// if parentNode is null, deletion was a success
cb(li.parentNode);
},
cbWait);
},
],
(err) => {
activityHappened();
console.log("deleteFile ended ", err === null ? "succcess" : "failure");
cbFileDeleted(err);
}
);
}
function normalUrl(url){
url = url.toString();
if(url.endsWith("/")){
url = url.substr(0, url.length - 1);
}
return url;
}
function parentLocation(rootLocation){
const par = normalUrl(window.location).split("/").slice(0, -1).join("/");
console.log("Estimated parent of", normalUrl(window.location), "is ", par, "(If equal to root, will return: ", normalUrl(rootLocation)," )");
return par.startsWith(normalUrl(rootLocation)) ? par : normalUrl(rootLocation);
}
function prepareUI(){
document.querySelector("body").insertAdjacentHTML("afterbegin",
'<div style="position:fixed; z-index: 1000; background: black; bottom: 0; right: 0">'+
'<a id="mainDeleteAll" style="cursor: pointer; display: block; padding: 1.5em; color:white; font-weight:bold">' +
'RECURSIVE DELETE EVERYTHING</a></div>');
document.querySelector("#mainDeleteAll").addEventListener('click', () => {
console.log("mainDeleteAll");
conf = confirm("sure ?");
console.log(conf);
if(true === conf){
mainDeleteAll();
}
});
}
prepareUI();
console.log("hubic delete loaded");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment