-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcleanup.js
More file actions
51 lines (43 loc) · 1.97 KB
/
Copy pathcleanup.js
File metadata and controls
51 lines (43 loc) · 1.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
* Facebook Saved Items Cleanup Utility - Optimized v1.1.0
*/
(async () => {
const CFG = { scroll: 1000, action: 500, wait: 800, retry: 12 };
console.log("Cleanup Optimized: Running...");
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
const findByText = (tag, txt) => Array.from(document.querySelectorAll(tag)).find(el => el.innerText?.includes(txt));
while (true) {
window.scrollTo(0, 0);
await sleep(CFG.scroll);
const btns = Array.from(document.querySelectorAll('div[role="button"]')).filter(b => {
const r = b.getBoundingClientRect();
const l = (b.getAttribute('aria-label') || "").toLowerCase();
return r.top > 120 && r.width > 0 && r.width < 60 && !l.includes("share") && !l.includes("collection");
});
if (!btns.length) { window.scrollBy(0, 500); continue; }
// Group by Y-axis (rows) and pick the right-most button (the menu)
const rows = btns.reduce((acc, b) => {
const y = Math.round(b.getBoundingClientRect().top / 15) * 15;
acc[y] = [...(acc[y] || []), b];
return acc;
}, {});
for (const y of Object.keys(rows).sort((a,b) => a-b).slice(0, 3)) {
const menu = rows[y].reduce((a, b) => a.getBoundingClientRect().left > b.getBoundingClientRect().left ? a : b);
menu.click();
let unsave;
for (let i = 0; i < CFG.retry && !unsave; i++) {
await sleep(100);
unsave = findByText('span', 'Unsave');
}
if (unsave) {
unsave.click();
await sleep(CFG.action);
const confirm = findByText('span', 'Remove') || findByText('span', 'Unsave');
if (confirm) confirm.click();
} else {
window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
}
await sleep(CFG.wait);
}
}
})();