// ==UserScript==
// @name FBMP Listing Manager
// @namespace http://tampermonkey.net/
// @version 3.9
// @description The ultimate Facebook Marketplace listing deletion machine - now with AI-powered evasion and ninja-like stealth
// @author The Phantom Deleter
// @match https://www.facebook.com/marketplace/you/selling?order=*
// @grant none
// @license MIT
// ==/UserScript==
console.log("🧪 [FBMP Terminator] Script loaded.");
(function() {
'use strict';
// Mission Control Configuration
const config = {
running: false,
cycle: 0,
maxCycles: 50,
coolDown: 5,
stealthMode: true,
aiBehavior: "random", // "random", "sold", "unsold", "no_answer"
maxFailures: 3,
version: "3.9"
};
// AI Response Bank
const aiResponses = {
deletion: [
"Terminating listing with extreme prejudice",
"Making listing disappear like magic",
"Sending listing to the shadow realm",
"Executing order 66 on this listing"
],
failure: [
"Target evaded deletion!",
"The listing fought back!",
"Mission failed, we'll get 'em next time",
"Facebook countermeasures detected!"
],
waiting: [
"Maintaining operational security",
"Hiding from Facebook's watchful eyes",
"Simulating human browsing patterns",
"Calculating next move..."
]
};
// Stealth Operations
function getRandomDelay() {
return config.stealthMode ?
1000 + Math.random() * 2000 : // Random delay between 1-5s in stealth mode
500 + Math.random() * 700; // Faster operation when stealth is off
}
function getAIResponse(type) {
const responses = aiResponses[type];
return responses[Math.floor(Math.random() * responses.length)];
}
// Tactical UI Elements
function createTerminatorUI() {
const panel = document.createElement('div');
panel.id = 'terminator-panel';
panel.style.cssText = `
position: fixed;
bottom: 10px;
left: 10px;
z-index: 9999;
padding: 15px;
background: linear-gradient(135deg, #1a1a1a 0%, #000 100%);
border-radius: 10px;
color: #ffffff;
font-family: 'Courier New', monospace;
font-size: 13px;
border: 1px solid #00ff00;
box-shadow: 0 0 15px rgba(0, 255, 0, 0.3);
`;
panel.innerHTML = `
<h3 style="margin-top:0;border-bottom:1px solid #fff;padding-bottom:5px;color:#fff;text-align: center;">
Listing Manager v${config.version}
</h3>
<div style="margin-bottom:10px;">
<label style="color:#fff;">Listing yang dihapus: <input type="number" id="maxCycles" value="${config.maxCycles}" style="width:60px;background:#111;color:#0f0;border:1px solid #333;"></label><br>
<label style="color:#fff;">Cool Down: <input type="number" id="coolDown" value="${config.coolDown}" style="width:60px;background:#111;color:#0f0;border:1px solid #333;">s</label><br>
<label style="display:block;margin-top:5px;color:#fff;">
<input type="checkbox" id="stealthMode" ${config.stealthMode ? 'checked' : ''}> Stealth Mode
</label>
<select id="aiBehavior" style="margin-top:5px;background:#111;color:#0f0;border:1px solid #333;width:100%">
<option value="random">Random Behavior</option>
<option value="sold">Mark as Sold</option>
<option value="unsold">Mark as Unsold</option>
<option value="no_answer">No Answer</option>
</select>
<select id="operationMode" style="margin-top:5px;background:#111;color:#0f0;border:1px solid #333;width:100%">
<option value="terminator">TERMINATOR MODE</option>
<option value="update">UPDATE MODE</option>
<option value="repost">REPOST MODE</option>
</select>
</div>
<button id="toggleButton" style="background:linear-gradient(180deg, #00cc00 0%, #009900 100%);border:none;color:white;padding:5px 10px;border-radius:3px;cursor:pointer;font-weight:bold;">
▶ START
</button>
<div style="margin-top:10px;font-size:12px;">
Status: <span id="statusIndicator" style="color:#ff0;">STANDBY</span>
</div>
<textarea id="terminator-log" rows="10" cols="35" readonly style="width:100%;resize:none;background:#111;color:#fff;border:1px solid #333;margin-top:10px;font-family:monospace;"></textarea>
`;
const style = document.createElement('style');
style.textContent = `
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(0.98); }
100% { transform: scale(1); }
}
`;
document.body.appendChild(panel);
document.getElementById('toggleButton').addEventListener('click', () => {
config.running = !config.running;
const status = document.getElementById('statusIndicator');
const button = document.getElementById('toggleButton');
if (config.running) {
button.innerHTML = '⏹ HENTIKAN';
button.style.background = 'linear-gradient(180deg, #ff3300 0%, #cc0000 100%)';
status.textContent = 'ACTIVE';
status.style.color = '#0f0';
log('DIAKTIFKAN ULANG');
const mode = document.getElementById('operationMode').value;
log(`MODE: ${mode.toUpperCase()}`);
if (mode === 'terminator') {
startTerminationSequence();
} else if (mode === 'repost') {
startRepostSequence(); // ← pastikan kamu membuat fungsi ini
}else if (mode === 'update') {
startUpdateSequence(); // ← pastikan kamu membuat fungsi ini
}
}else {
button.innerHTML = '▶ START';
button.style.background = 'linear-gradient(180deg, #00cc00 0%, #009900 100%)';
status.textContent = 'STANDBY';
status.style.color = '#ff0';
log('SCRIPT DIJEDA');
}
});
document.getElementById('stealthMode').addEventListener('change', (e) => {
config.stealthMode = e.target.checked;
log(`STEALTH MODE ${config.stealthMode ? 'ENABLED' : 'DISABLED'}`);
});
document.getElementById('aiBehavior').addEventListener('change', (e) => {
config.aiBehavior = e.target.value;
log(`AI BEHAVIOR SET TO: ${e.target.value.toUpperCase()}`);
});
// Perbarui coolDown secara langsung saat input berubah
document.getElementById('coolDown').addEventListener('input', (e) => {
const val = parseInt(e.target.value);
if (!isNaN(val) && val > 0) {
config.coolDown = val;
log(`⏳ CoolDown diubah menjadi: ${val} detik`);
}
});
}
// Mission Logging System
function log(message) {
const logBox = document.getElementById('terminator-log');
if (logBox) {
const timestamp = new Date().toLocaleTimeString();
logBox.value += `[${timestamp}] ${message}\n`;
logBox.scrollTop = logBox.scrollHeight;
}
}
async function sleep(ms) {
for (let i = 0; i < ms; i += 200) {
if (!config.running) throw new Error("TERMINATED");
await new Promise(resolve => setTimeout(resolve, 200));
}
}
// Tactical Element Location
function isVisible(elem) {
return !!(elem && (elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length));
}
function humanLikeClick(elem) {
if (!elem) return false;
const rect = elem.getBoundingClientRect();
const x = rect.left + rect.width / 2;
const y = rect.top + rect.height / 2;
const options = {
bubbles: true,
cancelable: true,
composed: true,
clientX: x,
clientY: y,
pointerType: 'mouse'
};
elem.dispatchEvent(new PointerEvent('pointerdown', options));
elem.dispatchEvent(new PointerEvent('pointerup', options));
elem.dispatchEvent(new PointerEvent('click', options));
return true;
}
// ====== START OF startTerminationSequence() ====== //
async function startTerminationSequence() {
try {
config.maxCycles = parseInt(document.getElementById("maxCycles").value) || 50;
config.coolDown = parseInt(document.getElementById("coolDown").value) || 5;
log("Cooldown dari input:", config.coolDown);
log(`Memulai Urutan Penghapusan - ${config.maxCycles} TARGETS`);
log(`STRATEGY: ${config.aiBehavior.toUpperCase()} | STEALTH: ${config.stealthMode ? 'ON' : 'OFF'}`);
// Beralih ke Tampilan Daftar (List View)
const listButton = [...document.querySelectorAll('div[aria-label="Tampilan Daftar"]')].find(isVisible);
if (listButton && listButton.getAttribute('aria-pressed') === 'false') {
humanLikeClick(listButton);
log("📃 Beralih ke Tampilan Daftar...");
await sleep(1000);
}
let consecutiveFailures = 0;
for (config.cycle = 1; config.cycle <= config.maxCycles; config.cycle++) {
if (!config.running) break;
log(`MISSION ${config.cycle} OF ${config.maxCycles}`);
// Phase 1: Engage ellipsis
if (!await engageEllipsis()) {
consecutiveFailures++;
log(`WARNING: TARGET MENGHINDAR (${consecutiveFailures}/${config.maxFailures})`);
if (consecutiveFailures >= config.maxFailures) {
log("CRITICAL FAILURE - MEMULAI PENGELAKAN");
window.location.href = "/marketplace/you/selling";
return;
}
continue;
} else {
consecutiveFailures = 0;
}
await sleep(500);
// Phase 2: Engage deletion
if (!await engageElement("Hapus tawaran")) {
log("DIHENTIKAN - TARGET TERTUTUP");
continue;
}
await sleep(500);
// Phase 3: Confirm deletion
if (!await engageDeleteConfirmation("Hapus")) {
log("KONFIRMASI GAGAL - MUNGKIN MASIH AKTIF");
continue;
}
// Phase 4: AI Reason Step (conditional)
await sleep(300);
const reasonExists = Array.from(document.querySelectorAll('span'))
.some(span => ["Ya, terjual di Facebook", "Ya, terjual di tempat lain", "Tidak, belum terjual", "Memilih tidak menjawab"]
.includes(span.textContent.trim()));
if (reasonExists) {
const responseText = getStrategicResponse();
await engageElement(responseText);
await engageElement("Berikutnya");
} else {
const nextBtn = Array.from(document.querySelectorAll('span'))
.find(span => span.textContent.trim() === "Berikutnya" && isVisible(span));
if (nextBtn) {
executeClick(nextBtn);
log("KONFIRMASI : TERHAPUS");
await sleep(getRandomDelay());
} else {
log("⚠️ Tidak ada alasan penawaran. Menganggap listing sudah dihapus.");
}
}
await sleep(1000);
// Phase 5: AI Response (lagi, jika muncul ulang)
const responseText = getStrategicResponse();
if (await engageElement(responseText)) {
await engageElement("Berikutnya");
} else {
const confirmBtn = Array.from(document.querySelectorAll('span'))
.find(span => span.textContent.trim() === "Berikutnya" && isVisible(span));
if (confirmBtn) {
executeClick(confirmBtn);
log("KONFIRMASI : TERHAPUS");
await sleep(getRandomDelay());
}
}
// Cool down period
const waitingMsg = getAIResponse('waiting');
log(`${waitingMsg} (${config.coolDown} detik)...`);
for (let s = 1; s <= config.coolDown; s++) {
if (!config.running) {
log("🛑 PROSES Dihentikan oleh pengguna.");
return;
}
log(`🕒 ${s}`);
await sleep(1000);
}
}
log("PROSES HAPUS BERHASIL");
// log("ALL TARGETS NEUTRALIZED OR MISSION ABORTED");
} catch (e) {
if (e.message === "TERMINATED") {
log("🛑 PROSES DIHENTIKAN LANGSUNG OLEH PENGGUNA");
} else {
log(`❌ ERROR: ${e.message}`);
}
}
}
// ====== HELPER FUNCTIONS startTerminationSequence() ====== //
function findZeroClickListingButton() {
// Temukan semua elemen yang berisi teks "0 klik tawaran"
const zeroClickElements = Array.from(document.querySelectorAll("div.x78zum5.x1q0g3np.xg7h5cd"))
.filter(el => el.textContent.includes("0 klik tawaran"));
for (const el of zeroClickElements) {
// Naik ke atas sampai container listing
let current = el;
for (let i = 0; i < 10; i++) {
if (!current) break;
if (current.querySelector("div[aria-label^='Opsi lainnya untuk']")) {
const ellipsisBtn = current.querySelector("div[aria-label^='Opsi lainnya untuk']");
if (ellipsisBtn) return ellipsisBtn;
}
current = current.parentElement;
}
}
// Jika tidak ada tombol ⋯ ditemukan dalam listing dengan 0 klik tawaran
return null;
}
// Advanced Click Simulation
function executeClick(elem) {
if (!elem) return false;
const rect = elem.getBoundingClientRect();
const mouseEventInit = {
bubbles: true,
cancelable: true,
view: window,
clientX: rect.left + rect.width/2,
clientY: rect.top + rect.height/2
};
['mousedown', 'mouseup', 'click'].forEach(type => {
elem.dispatchEvent(new MouseEvent(type, mouseEventInit));
});
return true;
}
async function engageDeleteConfirmation() {
// Cari semua tombol "Hapus" yang terlihat
const candidates = Array.from(document.querySelectorAll('div[role="dialog"] span'))
.filter(span => span.textContent.trim() === "Hapus" && isVisible(span));
if (candidates.length === 0) {
log("❌ Tidak menemukan tombol 'Hapus' di dalam dialog.");
return false;
}
// Ambil yang paling bawah (biasanya tombol konfirmasi biru)
const button = candidates[candidates.length - 1];
button.scrollIntoView({ behavior: "smooth", block: "center" });
await sleep(getRandomDelay());
executeClick(button);
log(`🧨 Konfirmasi 'Hapus' dieksekusi.`);
await sleep(1000);
return true;
}
// Strategic Element Engagement
async function engageElement(text, tag = 'span') {
const elements = Array.from(document.querySelectorAll(tag));
const lowerText = text.toLowerCase();
const target = elements.find(el => {
const match = el.textContent.trim().toLowerCase() === lowerText;
const visible = isVisible(el);
return match && visible;
});
if (target) {
target.scrollIntoView({ behavior: "smooth", block: "center" });
await sleep(getRandomDelay());
executeClick(target);
log(`${getAIResponse('deletion')}: "${text}"`);
await sleep(getRandomDelay());
return true;
} else {
log(`${getAIResponse('failure')} - Target tidak ditemukan: "${text}"`);
return false;
}
}
// Special Ops: Ellipsis Engagement
async function engageEllipsis() {
const target = findZeroClickListingButton();
if (!target) {
log("❌ Tidak ada listing dengan '0 klik tawaran' ditemukan.");
return false;
}
target.scrollIntoView({ behavior: "smooth", block: "center" });
await sleep(1000);
executeClick(target);
log("🎯 Target '0 klik tawaran' ditemukan dan diserang.");
await sleep(getRandomDelay());
return true;
}
// AI-Powered Response Selection
function getStrategicResponse() {
switch(config.aiBehavior) {
case "sold":
return Math.random() > 0.5 ? "Ya, terjual di Facebook" : "Ya, terjual di tempat lain";
case "unsold":
return "Tidak, belum terjual";
case "no_answer":
return "Memilih tidak menjawab";
default:{
const options = [
"Memilih tidak menjawab",
"Ya, terjual di Facebook",
"Ya, terjual di tempat lain",
"Tidak, belum terjual",
];
return options[Math.floor(Math.random() * options.length)];
}
}
}
// ====== END OF startTerminationSequence() ====== //
// ====== START OF startRepostSequence() ====== //
async function startRepostSequence() {
try {
log("🔄 MEMULAI REPOST SEQUENCE - Mencari listing dengan 'Hapus & Tawarkan Ulang'");
// Switch to list view for better scanning
if (!(await switchToListViewRepost())) {
log("⚠️ Gagal beralih ke tampilan daftar, melanjutkan dengan tampilan saat ini");
}
let totalProcessed = 0;
let scrollAttempts = 0;
const maxScrollAttempts = 50;
let consecutiveFails = 0;
const maxConsecutiveFails = 5;
let lastButtonCount = 0;
let sameButtonCountOccurrences = 0;
// Initial load wait
await sleep(5000);
while (scrollAttempts < maxScrollAttempts && consecutiveFails < maxConsecutiveFails) {
// Find all unprocessed buttons with fresh scan
const allButtons = await comprehensiveButtonScanRepost();
const unprocessedButtons = allButtons.filter(btn =>
isVisibleRepost(btn) &&
isClickableRepost(btn) &&
!btn.hasAttribute('data-processed')
);
// Check if we're seeing the same number of buttons repeatedly (possible infinite loop)
if (unprocessedButtons.length === lastButtonCount) {
sameButtonCountOccurrences++;
if (sameButtonCountOccurrences > 3) {
log("⚠️ Deteksi kemungkinan infinite loop, melakukan reset...");
sameButtonCountOccurrences = 0;
await reloadPage();
continue;
}
} else {
sameButtonCountOccurrences = 0;
lastButtonCount = unprocessedButtons.length;
}
if (unprocessedButtons.length === 0) {
log(`ℹ️ Tidak menemukan tombol baru (scroll ${scrollAttempts + 1}/${maxScrollAttempts})`);
// Special handling when no buttons found
if (totalProcessed === 0 && scrollAttempts > 10) {
log("⚠️ Tidak menemukan tombol sama sekali setelah beberapa scroll");
break;
}
let prevListingCount = await countListingsRepost();
await aggressiveScrollRepost();
await sleep(1000); // beri waktu loading
let newListingCount = await countListingsRepost();
if (newListingCount > prevListingCount) {
log(`📈 Ditemukan ${newListingCount - prevListingCount} listing baru setelah scroll`);
continue; // skip ke atas untuk scan ulang
} else {
log("📉 Tidak ada listing baru setelah scroll");
}
// await aggressiveScrollRepost();
// scrollAttempts++;
// consecutiveFails++;
// await sleep(4000);
// continue;
}
log(`🔍 Ditemukan ${unprocessedButtons.length} tombol aktif yang belum diproses`);
consecutiveFails = 0; // Reset fail counter
// Process all unprocessed buttons in this batch
for (let i = 0; i < unprocessedButtons.length; i++) {
const button = unprocessedButtons[i];
// Verify button still exists and is clickable
if (!document.contains(button) || !isClickableRepost(button)) {
log("ℹ️ Tombol tidak valid lagi, melanjutkan...");
continue;
}
const listing = findParentListingRepost(button);
if (!listing) {
log("⚠️ Tidak dapat menemukan parent listing, menandai tombol sebagai gagal");
button.setAttribute('data-processed', 'failed');
continue;
}
log(`🔄 Memproses listing ${totalProcessed + 1}`);
highlightButtonRepost(button, 'processing');
// More robust clicking with multiple fallbacks
const success = await robustButtonClickRepost(button, listing);
if (success) {
totalProcessed++;
highlightButtonRepost(button, 'success');
// More permanent marking of processed buttons
button.setAttribute('data-processed', 'true');
button.setAttribute('data-processed-time', Date.now());
log(`✅ Berhasil memproses (Total: ${totalProcessed})`);
// After successful processing, check if listing disappeared
if (!document.contains(listing)) {
log("ℹ️ Listing menghilang setelah diproses");
}
} else {
highlightButtonRepost(button, 'failed');
button.setAttribute('data-processed', 'failed');
log("⚠️ Gagal memproses tombol ini");
}
// Randomized delay between buttons (1-4 seconds)
await sleep(1000 + Math.random() * 3000);
}
await sleep(2000);
// Final verification scan
const remainingButtons = (await comprehensiveButtonScanRepost()).filter(btn =>
isVisibleRepost(btn) &&
isClickableRepost(btn) &&
!btn.hasAttribute('data-processed')
);
if (remainingButtons.length > 0) {
log(`ℹ️ Masih ada ${remainingButtons.length} tombol yang belum diproses`);
// More aggressive scroll if we still have unprocessed buttons
await aggressiveScrollRepost();
scrollAttempts++;
await sleep(3000);
} else {
log("✔️ Semua tombol telah diproses");
break;
}
}
log(`🎉 Selesai! Total tombol berhasil diklik: ${totalProcessed}`);
} catch (e) {
log(`❌ ERROR: ${e.message}`);
console.error(e);
}
}
// ====== HELPER FUNCTIONS startRepostSequence() ====== //
async function reloadPage() {
log("🔄 Memuat ulang halaman...");
window.scrollTo(0, 0);
await sleep(2000);
window.location.reload();
}
async function robustButtonClickRepost(button, listing) {
try {
// Double-check button state
if (!isVisibleRepost(button) || !isClickableRepost(button)) {
return false;
}
// Store initial state
const initialButtonState = isClickableRepost(button);
const initialListingExists = document.contains(listing);
const initialButtonText = button.textContent;
const initialButtonHTML = button.outerHTML;
// Scroll to button with offset to account for headers
const yOffset = -100; // Adjust for fixed headers
const buttonRect = button.getBoundingClientRect();
window.scrollTo({
top: window.scrollY + buttonRect.top + yOffset,
behavior: 'smooth'
});
await sleep(800);
// Try multiple click methods with visual feedback
const clickMethods = [
() => {
button.style.transform = 'scale(0.98)';
button.click();
},
() => humanLikeClickRepost(button),
() => simulateMouseClickRepost(button),
() => {
const rect = button.getBoundingClientRect();
const clickEvent = new MouseEvent('click', {
bubbles: true,
cancelable: true,
clientX: rect.left + rect.width/2,
clientY: rect.top + rect.height/2
});
button.dispatchEvent(clickEvent);
}
];
let clickSuccess = false;
for (const method of clickMethods) {
if (clickSuccess) break;
try {
method();
await sleep(300 + Math.random() * 700); // Vary delay between attempts
// Immediate verification
if (verifyClickSuccessRepost(button, listing, initialButtonState, initialListingExists, initialButtonText)) {
clickSuccess = true;
break;
}
} catch (e) {
console.log(`Click method failed: ${e.message}`);
}
}
// Reset button style
button.style.transform = '';
if (!clickSuccess) return false;
// Progressive verification with multiple checks
const verificationChecks = [
// Immediate check
() => verifyClickSuccessRepost(button, listing, initialButtonState, initialListingExists, initialButtonText),
// Delayed check
async () => {
await sleep(1500);
return verifyClickSuccessRepost(button, listing, initialButtonState, initialListingExists, initialButtonText);
},
// DOM change check
() => button.outerHTML !== initialButtonHTML
];
for (const check of verificationChecks) {
if (await check()) {
return true;
}
}
return false;
} catch (e) {
log(`⚠️ Click error: ${e.message}`);
return false;
}
}
function verifyClickSuccessRepost(button, listing, initialButtonState, initialListingExists, initialButtonText) {
return (
(initialButtonState && !isClickableRepost(button)) ||
(initialListingExists && !document.contains(listing)) ||
(button.textContent !== initialButtonText) ||
(window.getComputedStyle(button).opacity < 0.5) ||
(button.getAttribute('aria-disabled') === 'true')
);
}
async function aggressiveScrollRepost() {
// Scroll further than viewport height to ensure loading
const scrollDistance = window.innerHeight * 2;
window.scrollBy({
top: scrollDistance,
behavior: 'smooth'
});
// Additional micro-scrolls to trigger loading
await sleep(1000);
window.scrollBy(0, 300);
await sleep(500);
window.scrollBy(0, 100);
}
async function comprehensiveButtonScanRepost() {
const scanMethods = [
() => document.querySelectorAll('div[aria-label="Hapus & Tawarkan Ulang"]'),
() => document.querySelectorAll('span:contains("Hapus & Tawarkan Ulang")'),
() => {
const xpath = "//*[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'hapus & tawarkan ulang')]";
const result = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
const elements = [];
for (let i = 0; i < result.snapshotLength; i++) {
elements.push(result.snapshotItem(i));
}
return elements;
},
() => document.querySelectorAll('div.x1i10hfl.xjbqb8w.x6umtig') // Common FB button class
];
const allButtons = new Set();
const now = Date.now();
for (const method of scanMethods) {
try {
const buttons = method();
for (const btn of buttons) {
try {
// Skip buttons processed in the last 5 minutes to handle Facebook re-rendering
const processedTime = btn.getAttribute('data-processed-time');
if (processedTime && (now - parseInt(processedTime)) < 300000) {
continue;
}
if (btn.textContent &&
btn.textContent.toLowerCase().includes('hapus') &&
btn.textContent.toLowerCase().includes('tawarkan ulang')) {
allButtons.add(btn);
}
} catch (e) {
console.log('Error processing button:', e);
}
}
} catch (e) {
console.log(`Scan method error: ${e.message}`);
}
}
return Array.from(allButtons);
}
async function xpathFindButtonsRepost() {
const buttons = [];
const xpathResult = document.evaluate(
"//*[contains(text(), 'Hapus & Tawarkan Ulang')]",
document,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
for (let i = 0; i < xpathResult.snapshotLength; i++) {
const element = xpathResult.snapshotItem(i);
if (isVisibleRepost(element) && isClickableRepost(element)) {
buttons.push(element);
}
}
return buttons;
}
async function scrollToVeryBottomRepost() {
const startPosition = window.pageYOffset;
window.scrollTo({
top: document.body.scrollHeight,
behavior: 'smooth'
});
await sleep(3000);
// Additional check to ensure we're not stuck
if (window.pageYOffset <= startPosition + 500) {
log("⚠️ Scroll tidak berpengaruh, mencoba alternatif...");
// Alternative scroll method
for (let i = 0; i < 5; i++) {
window.scrollBy(0, window.innerHeight * 2);
await sleep(1000);
}
}
}
function simulateMouseClickRepost(element) {
if (!element || !isVisibleRepost(element)) return false;
try {
const rect = element.getBoundingClientRect();
const mouseEventInit = {
bubbles: true,
cancelable: true,
view: window,
clientX: rect.left + rect.width/2,
clientY: rect.top + rect.height/2
};
['mouseover', 'mousedown', 'mouseup', 'click'].forEach(type => {
element.dispatchEvent(new MouseEvent(type, mouseEventInit));
});
return true;
} catch (e) {
console.error('Mouse simulation failed:', e);
return false;
}
}
function hasVisualChangeRepost(element) {
if (!element) return false;
try {
// Store current visual properties
const currentStyle = window.getComputedStyle(element);
const currentProps = {
backgroundColor: currentStyle.backgroundColor,
borderColor: currentStyle.borderColor,
color: currentStyle.color,
opacity: currentStyle.opacity
};
// Wait briefly for potential changes
return new Promise(resolve => {
setTimeout(() => {
const newStyle = window.getComputedStyle(element);
const changed = (
newStyle.backgroundColor !== currentProps.backgroundColor ||
newStyle.borderColor !== currentProps.borderColor ||
newStyle.color !== currentProps.color ||
newStyle.opacity !== currentProps.opacity
);
resolve(changed);
}, 500);
});
} catch (e) {
console.error('Visual change check failed:', e);
return false;
}
}
async function findRepostButtonsDeepScanRepost() {
// Try multiple scanning methods
const buttons = [];
// Method 1: Standard selector search
buttons.push(...await findClickableRepostButtons());
// Method 2: Visual scanning for button text
if (buttons.length < 5) {
buttons.push(...await visualScanForButtonsRepost());
}
// Method 3: XPath search as fallback
if (buttons.length < 5) {
buttons.push(...await xpathFindButtonsRepost());
}
// Filter out duplicates and failed buttons
const uniqueButtons = [];
const seen = new Set();
for (const button of buttons) {
if (!seen.has(button) &&
isVisibleRepost(button) &&
isClickableRepost(button) &&
!button.hasAttribute('data-processed')) {
seen.add(button);
uniqueButtons.push(button);
}
}
return uniqueButtons;
}
async function visualScanForButtonsRepost() {
const buttons = [];
const textNodes = document.evaluate(
"//text()[contains(., 'Hapus') and contains(., 'Tawarkan Ulang')]",
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
null
);
for (let i = 0; i < textNodes.snapshotLength; i++) {
const node = textNodes.snapshotItem(i);
let element = node.parentElement;
// Walk up the DOM to find clickable container
while (element && element !== document.body) {
if (element.getAttribute('role') === 'button' ||
element.tagName === 'BUTTON' ||
element.onclick) {
buttons.push(element);
break;
}
element = element.parentElement;
}
}
return buttons.filter(btn => isVisibleRepost(btn) && isClickableRepost(btn));
}
async function enhancedClickAndVerifyRepost(button, listing) {
try {
// Store initial state
const initialHtml = listing.innerHTML;
const initialButtonText = button.textContent;
// Scroll to center the button
button.scrollIntoView({ behavior: 'smooth', block: 'center' });
await sleep(800);
// Try different click methods
const clickMethods = [
() => button.click(),
() => humanLikeClickRepost(button),
() => simulateMouseClickRepost(button)
];
let clickSuccess = false;
for (const method of clickMethods) {
try {
method();
clickSuccess = true;
break;
} catch (e) {
console.log(`Click method failed: ${e.message}`);
}
}
if (!clickSuccess) return false;
// Wait for changes
await sleep(2000);
// Verification methods
const verificationChecks = [
// Button became disabled
!isClickableRepost(button),
// Listing disappeared
!document.contains(listing),
// Listing HTML changed significantly
listing.innerHTML !== initialHtml,
// Button text changed
button.textContent !== initialButtonText,
// Button visually changed (color, etc)
hasVisualChangeRepost(button)
];
return verificationChecks.some(check => check);
} catch (e) {
log(`⚠️ Verification error: ${e.message}`);
return false;
}
}
// Modified smart scroll to be more aggressive when needed
async function smartScrollRepost(processedCount, scrollAttempts) {
// Base scroll distance
let scrollDistance = window.innerHeight * 1.8; // Increased from 1.5
// Increase scroll distance based on progress
if (processedCount > 15) scrollDistance *= 1.3;
if (scrollAttempts > 8) scrollDistance *= 1.5;
// Add random variation
scrollDistance *= 0.9 + Math.random() * 0.2;
window.scrollBy({
top: scrollDistance,
behavior: 'smooth'
});
// Additional micro-scrolls with random delays
await sleep(800 + Math.random() * 1000);
window.scrollBy(0, 200 + Math.random() * 100);
await sleep(400 + Math.random() * 500);
window.scrollBy(0, 50 + Math.random() * 50);
}
// Enhanced button highlighting
function highlightButtonRepost(button, state) {
const colors = {
processing: 'hsl(30, 100%, 50%)', // Orange
success: 'hsl(120, 100%, 40%)', // Green
failed: 'hsl(0, 100%, 45%)' // Red
};
button.style.border = `2px solid ${colors[state]}`;
button.style.borderRadius = '6px';
button.style.transition = 'all 0.3s ease';
button.style.padding = '2px';
if (state === 'processing') {
button.style.boxShadow = '0 0 0 3px rgba(255,165,0,0.3)';
button.style.animation = 'pulse 0.5s 2';
} else {
button.style.boxShadow = 'none';
button.style.animation = 'none';
}
// Create temporary highlight effect
const highlight = document.createElement('div');
highlight.style.position = 'absolute';
highlight.style.backgroundColor = state === 'success' ? 'rgba(76, 175, 80, 0.2)' :
state === 'failed' ? 'rgba(244, 67, 54, 0.2)' :
'rgba(255, 165, 0, 0.2)';
highlight.style.borderRadius = 'inherit';
highlight.style.inset = '0';
highlight.style.pointerEvents = 'none';
highlight.style.zIndex = '9999';
button.style.position = 'relative';
button.appendChild(highlight);
setTimeout(() => {
highlight.style.opacity = '0';
highlight.style.transition = 'opacity 0.5s';
setTimeout(() => {
button.removeChild(highlight);
button.style.border = '';
button.style.borderRadius = '';
button.style.padding = '';
}, 500);
}, 1000);
}
// ======== ESSENTIAL HELPER FUNCTIONS ======== //
async function switchToListViewRepost() {
try {
const listButton = [...document.querySelectorAll('div[aria-label="Tampilan Daftar"]')]
.find(btn => isVisibleRepost(btn) && btn.getAttribute('aria-pressed') === 'false');
if (listButton) {
humanLikeClickRepost(listButton);
log("📃 Beralih ke Tampilan Daftar...");
await sleep(2000);
return true;
}
return false;
} catch (e) {
log(`⚠️ Gagal beralih ke tampilan daftar: ${e.message}`);
return false;
}
}
async function clickAndVerifyRepost(button, listing) {
try {
// Scroll to ensure visibility
if (listing && listing.scrollIntoView) {
listing.scrollIntoView({ behavior: 'auto', block: 'center' });
await sleep(800);
}
// Store initial state
const initialButtonState = isClickableRepost(button);
const initialListingExists = document.contains(listing);
const initialButtonText = button.textContent;
// Perform click
let clickSuccess = false;
try {
if (typeof button.click === 'function') {
button.click();
clickSuccess = true;
} else if (humanLikeClickRepost(button)) {
clickSuccess = true;
} else if (executeClickRepost(button)) {
clickSuccess = true;
}
} catch (e) {
log(`⚠️ Click error: ${e.message}`);
}
await sleep(1500);
// Verification
const isSuccessful =
(initialButtonState && !isClickableRepost(button)) ||
(initialListingExists && !document.contains(listing)) ||
(initialButtonText !== button.textContent);
return clickSuccess && isSuccessful;
} catch (e) {
log(`⚠️ Verification error: ${e.message}`);
return false;
}
}
function isVisibleRepost(elem) {
if (!elem) return false;
const style = window.getComputedStyle(elem);
return style.display !== 'none' &&
style.visibility !== 'hidden' &&
elem.offsetWidth > 0 &&
elem.offsetHeight > 0 &&
elem.getClientRects().length;
}
function isClickableRepost(element) {
if (!element || !isVisibleRepost(element)) return false;
try {
const style = window.getComputedStyle(element);
return !(style.pointerEvents === 'none' ||
style.cursor === 'not-allowed' ||
parseFloat(style.opacity) < 0.6 ||
element.disabled);
} catch (e) {
console.log('Error checking clickable:', e);
return false;
}
}
// ======== OTHER REQUIRED FUNCTIONS ======== //
function humanLikeClickRepost(elem) {
if (!elem) return false;
const rect = elem.getBoundingClientRect();
const x = rect.left + rect.width/2;
const y = rect.top + rect.height/2;
const events = [
new MouseEvent('mouseover', { bubbles: true }),
new MouseEvent('mousedown', { bubbles: true }),
new MouseEvent('mouseup', { bubbles: true }),
new MouseEvent('click', { bubbles: true })
];
events.forEach(evt => {
elem.dispatchEvent(evt);
});
return true;
}
function executeClickRepost(elem) {
if (!elem) return false;
const rect = elem.getBoundingClientRect();
const mouseEventInit = {
bubbles: true,
cancelable: true,
view: window,
clientX: rect.left + rect.width/2,
clientY: rect.top + rect.height/2
};
['mousedown', 'mouseup', 'click'].forEach(type => {
elem.dispatchEvent(new MouseEvent(type, mouseEventInit));
});
return true;
}
async function findRepostButtonsWithRetry() {
let buttons = [];
let attempts = 0;
while (attempts < 3 && buttons.length === 0) {
buttons = await findClickableRepostButtons();
if (buttons.length > 0) break;
attempts++;
await sleep(1000);
}
return buttons;
}
async function findClickableRepostButtons() {
const selectors = [
'div[aria-label="Hapus & Tawarkan Ulang"]',
'span[dir="auto"]',
'div.x1i10hfl.xjbqb8w.x6umtig'
];
const allButtons = [];
for (const selector of selectors) {
try {
const buttons = Array.from(document.querySelectorAll(selector))
.filter(btn => {
if (!isVisibleRepost(btn)) return false;
const text = btn.textContent?.trim() || '';
if (!text.includes("Hapus") || !text.includes("Tawarkan Ulang")) return false;
return isClickableRepost(btn);
});
allButtons.push(...buttons);
} catch (e) {
console.log(`Selector error: ${e.message}`);
}
}
return [...new Set(allButtons)];
}
async function scrollDownRepost() {
window.scrollBy({
top: window.innerHeight * 1.5,
behavior: 'smooth'
});
await sleep(1000);
window.scrollBy(0, 100);
}
async function countListingsRepost() {
const selectors = [
'[data-testid="marketplace_your_listing_card"]',
'div.x1lliihq.x1n2onr6.x1jchvi3',
'div[role="article"]'
];
for (const selector of selectors) {
const listings = document.querySelectorAll(selector);
if (listings.length > 0) return listings.length;
}
return 0;
}
function findParentListingRepost(element) {
const selectors = [
'div[data-testid="marketplace_your_listing_card"]',
'div.x1lliihq.x1n2onr6.x1jchvi3',
'div[role="article"]',
'div.x1qjc9v5.x78zum5.x1q0g3np.x1a02dak.x1qughib'
];
for (const selector of selectors) {
const parent = element.closest(selector);
if (parent) return parent;
}
return element.closest('div[role="button"]') ||
element.closest('a[href*="/marketplace/item/"]');
}
// ====== END OF startRepostSequence() ====== //
// ====== START OF startUpdateSequence() ====== //
async function startUpdateSequence() {
try {
log("🔄 MEMULAI UPDATE MODE - Memindai dan memperbarui listing...");
// Verify correct page
if (!window.location.href.includes('/marketplace/you/selling')) {
window.location.href = 'https://www.facebook.com/marketplace/you/selling?order=CREATION_TIMESTAMP';
await sleep(3000);
return;
}
// Switch to grid view
const gridButton = [...document.querySelectorAll('div[aria-label="Tampilan Kisi"]')].find(isVisibleUpdate);
if (gridButton && gridButton.getAttribute('aria-pressed') === 'false') {
humanLikeClickUpdate(gridButton);
log("Beralih ke Tampilan Kisi...");
await sleep(1000);
}
let totalProcessed = 0;
let scrollAttempts = 0;
const maxScrollAttempts = 50;
let consecutiveFails = 0;
const maxConsecutiveFails = 5;
// Main processing loop
while (scrollAttempts < maxScrollAttempts && consecutiveFails < maxConsecutiveFails) {
// Find listings with tips text
const listingsWithTips = await findListingsWithTipsText();
if (listingsWithTips.length === 0) {
log(`ℹ️ Tidak menemukan listing dengan tips (scroll ${scrollAttempts + 1}/${maxScrollAttempts})`);
if (totalProcessed === 0 && scrollAttempts > 10) {
log("⚠️ Tidak menemukan listing dengan tips sama sekali");
break;
}
await smartScrollUpdate();
scrollAttempts++;
consecutiveFails++;
await sleep(3000);
continue;
}
log(`🔍 Ditemukan ${listingsWithTips.length} listing dengan tips`);
consecutiveFails = 0;
// Process each listing
for (let i = 0; i < listingsWithTips.length; i++) {
const listing = listingsWithTips[i];
log(`🔄 Memproses listing (${totalProcessed + 1}${listingsWithTips.length})`);
// log(`🔄 Memproses listing ${totalProcessed + 1}/${listingsWithTips.length}`);
try {
const success = await processListing(listing);
if (success) {
totalProcessed++;
log(`✅ Berhasil memproses (Total: ${totalProcessed}/${listingsWithTips.length})`);
} else {
log("⚠️ Gagal memproses listing ini");
}
} catch (e) {
log(`❌ Error: ${e.message}`);
}
await sleep(500 + Math.random() * 2000);
}
await sleep(1000);
}
log(`🎉 Selesai! Total listing berhasil diperbarui: ${totalProcessed}`);
} catch (e) {
log(`❌ FATAL ERROR: ${e.message}`);
}
}
// ====== MISSING FUNCTION NOW INCLUDED ====== //
async function findListingsWithTipsText() {
// Find all elements containing the tips text
const tipElements = Array.from(document.querySelectorAll('div'))
.filter(div => div.textContent.includes("Tips: Perbarui tawaran Anda?") && isVisibleUpdate(div));
// Get unique parent listings
const listings = [];
const seen = new Set();
for (const tipElement of tipElements) {
const listing = findParentListingUpdate(tipElement);
if (listing && !seen.has(listing) && !listing.hasAttribute('data-processed')) {
seen.add(listing);
listings.push(listing);
}
}
return listings;
}
async function processListing(listing) {
try {
// 1. Highlight and scroll to listing
highlightListingUpdate(listing, 'processing');
listing.scrollIntoView({ behavior: 'smooth', block: 'center' });
await sleep(1000);
// 2. Click to open listing
// const listingLink = listing.querySelector('a[href*="/marketplace/item/"]') ||
// listing.querySelector('div[role="button"]');
// if (!listingLink) {
// throw new Error("Tidak bisa menemukan link listing");
// }
const mainDiv = listing.querySelector('div[role="button"]') ||
listing.querySelector('a[href*="/marketplace/item/"]');
if (!mainDiv || !isVisibleUpdate(mainDiv)) {
log("⚠️ Gagal menemukan area yang bisa diklik pada listing");
return false;
}
humanLikeClickUpdate(mainDiv);
log("Mencoba membuka listing...");
await sleep(3000);
// 3. Find and click update button
const updateBtn = await findAndClickUpdateButton();
await sleep(1000);
if (!updateBtn) {
throw new Error("Tombol update tidak ditemukan");
}
await sleep(1000);
// 4. Close dialog if still open
closeAllDialogs();
highlightListingUpdate(listing, 'success');
listing.setAttribute('data-processed', 'true');
return true;
} catch (e) {
highlightListingUpdate(listing, 'failed');
closeAllDialogs();
throw e;
}
}
async function findAndClickUpdateButton() {
// Try multiple ways to find the update button
const updateBtn = [...document.querySelectorAll('div[aria-label="Perbarui penawaran"]')]
.find(isVisibleUpdate);
if (updateBtn) {
// let success = false;
humanLikeClickUpdate(updateBtn);
log("✅ Berhasil klik 'Perbarui penawaran'");
await sleep(500);
return true;
} else {
log("⚠️ Gagal menemukan tombol perbarui setelah membuka listing");
return false;
}
}
function closeAllDialogs() {
const closeBtns = [...document.querySelectorAll('div[aria-label="Tutup"], svg[aria-label="Tutup"]')];
closeBtns.forEach(btn => {
if (isVisibleUpdate(btn)) humanLikeClickUpdate(btn);
});
}
async function smartScrollUpdate() {
window.scrollBy({
top: window.innerHeight * 1.5,
behavior: 'smooth'
});
await sleep(1000);
window.scrollBy(0, 200);
}
function findParentListingUpdate(element) {
const selectors = [
'div[data-testid="marketplace_your_listing_card"]',
'div.x1lliihq.x1n2onr6.x1jchvi3',
'div.x9f619.x78zum5.x1r8uery',
'div[role="article"]',
'div.x1qjc9v5.x78zum5.x1q0g3np.x1a02dak.x1qughib'
];
for (const selector of selectors) {
const parent = element.closest(selector);
if (parent) return parent;
}
return element.closest('div[style*="position: relative"]')||
element.closest('div.x1lliihq.x1n2onr6.x1jchvi3') ||
element.closest('div[role="button"]') ||
element.closest('a[href*="/marketplace/item/"]') ||
element.closest('div.x9f619.x78zum5.x1r8uery') ||
element.closest('div[style*="position: relative"]');
}
function isVisibleUpdate(element) {
if (!element) return false;
const style = window.getComputedStyle(element);
return style.display !== 'none' &&
style.visibility !== 'hidden' &&
element.offsetWidth > 0;
}
function isClickableUpdate(element) {
if (!element || !isVisibleUpdate(element)) return false;
const style = window.getComputedStyle(element);
return !(style.pointerEvents === 'none' ||
style.cursor === 'not-allowed' ||
parseFloat(style.opacity) < 0.6);
}
function highlightListingUpdate(element, state) {
const colors = {
processing: 'orange',
success: 'green',
failed: 'red'
};
element.style.border = `2px solid ${colors[state]}`;
element.style.borderRadius = '8px';
setTimeout(() => {element.style.border = ''}, 2000);
}
function humanLikeClickUpdate(element) {
if (!element || !isVisibleUpdate(element)) return false;
const rect = element.getBoundingClientRect();
const clickEvent = new MouseEvent('click', {
bubbles: true,
clientX: rect.left + rect.width/2,
clientY: rect.top + rect.height/2
});
element.dispatchEvent(clickEvent);
return true;
}
// Activation Protocol
(function waitForPageReady() {
if (document.readyState !== 'complete') {
return setTimeout(waitForPageReady, 500);
}
createTerminatorUI();
log("SYSTEM ONLINE");
log("MENUNGGU PERINTAH");
})();
window.createTerminatorUI = createTerminatorUI;
window.startTerminationSequence = startTerminationSequence;
window.startUpdateSequence = startUpdateSequence;
window.startRepostSequence = startRepostSequence;
window.log = log;
})();