您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Gabungan auto perbarui & relist Marketplace FB dengan logika retry final, auto start, dan UI kontrol
// ==UserScript== // @name AutoBot FBMP Enhanced // @namespace http://tampermonkey.net/ // @version 4.5 // @description Gabungan auto perbarui & relist Marketplace FB dengan logika retry final, auto start, dan UI kontrol // @author Behesty // @match https://www.facebook.com/marketplace/selling/* // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; // ⚙️ Konfigurasi yang bisa diubah: let retryInterval = 500; // ms antar percobaan let maxTriesPerRound = 60; // jumlah percobaan per round let maxRetryRounds = 3; // jumlah maksimal round let maxLoops = 100; // maksimal jumlah siklus utama let running = true; let loopCounter = 0; let isLooping = false; // ✅ untuk mencegah mainLoop dipanggil ganda // 📦 Log Box const logBox = document.createElement('div'); Object.assign(logBox.style, { position: 'fixed', bottom: '10px', right: '10px', background: 'rgba(0,0,0,0.8)', color: '#fff', padding: '10px', maxHeight: '300px', overflowY: 'auto', fontSize: '12px', zIndex: '9999', borderRadius: '8px', whiteSpace: 'pre-line' }); logBox.innerText = '📢 FB Marketplace Auto Bot\n'; document.body.appendChild(logBox); function log(msg) { const now = new Date(); const time = now.toLocaleTimeString('id-ID', { hour12: false }); const fullMsg = `[${time}] ${msg}`; console.log('[FBMBot] ' + fullMsg); logBox.innerText += fullMsg + '\n'; logBox.scrollTop = logBox.scrollHeight; } function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } function randomDelay(min = 500, max = 1500) { return delay(Math.floor(Math.random() * (max - min + 1)) + min); } async function waitForElement(selector) { for (let round = 1; round <= maxRetryRounds; round++) { log(`🔄 Percobaan ${round}`); for (let i = 1; i <= maxTriesPerRound; i++) { //log(`🔄 Pengecekan tombol: "${selector}" (Round ${round}, Try ${i})`); const el = document.querySelector(selector); if (el && el.offsetHeight > 0) return el; await delay(retryInterval); } } return null; } async function waitForVisibleElements(selector) { for (let round = 1; round <= maxRetryRounds; round++) { log(`🔄 Percobaan ${round}`); for (let i = 1; i <= maxTriesPerRound; i++) { //log(`🔄 Pengecekan tombol: "${selector}" (Round ${round}, Try ${i})`); const els = Array.from(document.querySelectorAll(selector)).filter(e => e.offsetHeight > 0); if (els.length > 0) return els; await delay(retryInterval); } } return []; } async function findAndClickRelistButton() { log('🔎 Mencari tombol "Untuk dihapus & ditawarkan ulang"...'); for (let round = 1; round <= maxRetryRounds; round++) { log(`🔍 Percobaan ${round}`); const links = Array.from(document.querySelectorAll('a[role="link"]')).filter(a => a.offsetHeight > 0); for (const link of links) { const text = link.innerText; if (text.includes('Untuk dihapus & ditawarkan ulang')) { const count = parseInt(text.match(/\d+/)?.[0] || '0'); log(`ℹ️ Ditemukan "Untuk dihapus & ditawarkan ulang" (${count} listing)`); if (count < 2) { log('✅ "Untuk dihapus & ditawarkan ulang" <= 1. Lewati.'); return false; // ⛔ Tidak perlu delay } log(`📌 Klik "Untuk dihapus & ditawarkan ulang" (${count} listing)`); link.scrollIntoView({ behavior: 'smooth', block: 'center' }); link.click(); return true; } } await delay(retryInterval); // ⏳ Tunggu tombol muncul di round berikutnya } log('❌ Tidak menemukan tombol "Untuk dihapus & ditawarkan ulang" setelah retry.'); return false; } async function findAndClickUpdateButton() { log('🔎 Mencari tombol "Untuk diperbarui"...'); for (let round = 1; round <= maxRetryRounds; round++) { log(`🔍 Percobaan ${round}`); const links = Array.from(document.querySelectorAll('a[role="link"]')).filter(a => a.offsetHeight > 0); for (const link of links) { const text = link.innerText; if (text.includes('Untuk diperbarui')) { const count = parseInt(text.match(/\d+/)?.[0] || '0'); log(`ℹ️ Ditemukan "Untuk diperbarui" (${count} listing)`); if (count < 2) { log('✅ "Untuk diperbarui" <= 1. Lewati.'); return false; } log(`📌 Klik "Untuk diperbarui" (${count} listing)`); link.scrollIntoView({ behavior: 'smooth', block: 'center' }); link.click(); return true; } } await delay(retryInterval); // ⏳ Tunggu tombol muncul di round berikutnya } log('❌ Tidak menemukan tombol "Untuk diperbarui" setelah retry.'); return false; } async function clickRelistButtons() { log('🔎 Menunggu tombol "Hapus & Tawarkan Ulang"...'); const buttons = await waitForVisibleElements('div[aria-label="Hapus & Tawarkan Ulang"]'); if (buttons.length === 0) { log('❌ ERROR: Tidak menemukan tombol "Hapus & Tawarkan Ulang".'); return false; } log(`🔧 Menemukan ${buttons.length} tombol "Hapus & Tawarkan Ulang"`); for (const btn of buttons) { btn.scrollIntoView({ behavior: 'smooth', block: 'center' }); log('🔁 Klik tombol "Hapus & Tawarkan Ulang"...'); btn.click(); await randomDelay(); } return true; } async function clickUpdateButtons() { log('🔎 Menunggu tombol "Perbarui"...'); const buttons = await waitForVisibleElements('div[aria-label="Perbarui"]'); if (buttons.length === 0) { log('❌ ERROR: Tidak menemukan tombol "Perbarui".'); return false; } log(`🔧 Menemukan ${buttons.length} tombol "Perbarui"`); for (const btn of buttons) { btn.scrollIntoView({ behavior: 'smooth', block: 'center' }); log('🔁 Klik tombol "Perbarui"...'); btn.click(); await randomDelay(); } return true; } async function clickDoneButton() { log('🔎 Mencari tombol "Selesai"...'); const btn = await waitForElement('div[aria-label="Selesai"]'); if (btn) { btn.scrollIntoView({ behavior: 'smooth', block: 'center' }); log('✅ Klik tombol "Selesai"'); btn.click(); return true; } log('⚠️ Tombol "Selesai" tidak ditemukan.'); return false; } async function countdown(seconds) { for (let i = seconds; i > 0; i--) { if (!running) { log('⏹ Dihentikan saat countdown.'); return; } log(`⏳ Menunggu ${i} detik...`); await delay(1000); } } async function checkErrorMessage(selector, expectedText, context) { log(`🔎 Mencari pesan khusus untuk ${context}...`); const el = Array.from(document.querySelectorAll(selector)).find(e => e.textContent.trim().includes(expectedText)); if (el) { log(`⚠️ Ditemukan pesan error untuk ${context}: "${expectedText}"`); await countdown(5); window.location.href = 'https://www.facebook.com/marketplace/selling/'; return true; } log(`ℹ️ Tidak ditemukan pesan khusus untuk ${context}`); return false; } async function runCycle() { if (!running) return; loopCounter++; log(`🚀 Mulai siklus ${loopCounter}`); let didSomething = false; let relistClickCounter = 0; let updateClickCounter = 0; let shouldReload = false; // 1. Proses relist dulu const relistClicked = await findAndClickRelistButton(); if (relistClicked) { await delay(2000); const buttons = await waitForVisibleElements('div[aria-label="Hapus & Tawarkan Ulang"]'); if (buttons.length === 0) { log('❌ ERROR: Tidak menemukan tombol "Hapus & Tawarkan Ulang".'); const found = await checkErrorMessage( 'span[dir="auto"]', 'Ini tidak bisa diperbarui lagi, tetapi Anda bisa menawarkan ulang dan menghapus tawaran asli.', 'Relist' ); if (found) return; } else { log(`🔧 Menemukan ${buttons.length} tombol "Hapus & Tawarkan Ulang"`); for (const btn of buttons) { btn.scrollIntoView({ behavior: 'smooth', block: 'center' }); log('🔁 Klik tombol "Hapus & Tawarkan Ulang"...'); btn.click(); relistClickCounter++; await randomDelay(); } await clickDoneButton(); await delay(2000); didSomething = true; } if (relistClickCounter < 20) { log(`⚠️ Tombol "Hapus & Tawarkan Ulang" yang diklik (${relistClickCounter}). Akan reload.`); shouldReload = true; } } // 2. Proses update const updateClicked = await findAndClickUpdateButton(); if (updateClicked) { await delay(2000); const buttons = await waitForVisibleElements('div[aria-label="Perbarui"]'); if (buttons.length === 0) { log('❌ ERROR: Tidak menemukan tombol "Perbarui".'); const found = await checkErrorMessage( 'span[dir="auto"]', 'Anda tidak lagi memiliki tawaran yang memenuhi syarat untuk diperbarui.', 'Update' ); if (found) return; } else { log(`🔧 Menemukan ${buttons.length} tombol "Perbarui"`); for (const btn of buttons) { btn.scrollIntoView({ behavior: 'smooth', block: 'center' }); log('🔁 Klik tombol "Perbarui"...'); btn.click(); updateClickCounter++; await randomDelay(); } await clickDoneButton(); didSomething = true; } if (updateClickCounter < 20) { log(`⚠️ Tombol "Perbarui" yang diklik (${updateClickCounter}). Akan reload.`); shouldReload = true; } } log(`📊 Ringkasan siklus ${loopCounter} → Relist: ${relistClickCounter}x klik | Update: ${updateClickCounter}x klik`); if (shouldReload) { log('🔁 Kondisi reload terpenuhi (jumlah klik < 20). Countdown sebelum reload...'); await countdown(20); // atau countdown(20); window.location.href = 'https://www.facebook.com/marketplace/selling/'; return; } if (!didSomething) { log('✅ Tidak ada tombol tersisa. Proses selesai.'); running = false; return; } } async function mainLoop() { if (isLooping) return; // ⛔ mencegah dua loop berjalan bersamaan isLooping = true; while (running && loopCounter < maxLoops) { await runCycle(); await countdown(20); } isLooping = false; if (loopCounter >= maxLoops) { log(`🔄 Maksimum ${maxLoops} siklus tercapai. Reload halaman...`); await delay(2000); window.location.href = 'https://www.facebook.com/marketplace/selling/'; } } // 🔘 UI: Tombol Start/Stop + input maxLoops function createUIControls() { const wrapper = document.createElement('div'); Object.assign(wrapper.style, { position: 'fixed', bottom: '35px', left: '20px', zIndex: 10000, display: 'flex', gap: '10px', alignItems: 'center' }); const btn = document.createElement('button'); btn.innerText = '⏹ STOP'; Object.assign(btn.style, { padding: '15px 80px', background: '#333', color: '#fff', border: 'none', borderRadius: '8px', cursor: 'pointer' }); const input = document.createElement('input'); input.type = 'number'; input.value = maxLoops; input.min = 1; input.max = 1000; input.style.fontSize = '15px'; input.style.width = '60px'; input.style.height = '35px'; input.title = 'Max Loop'; input.onchange = () => { maxLoops = parseInt(input.value) || 100; log(`🔧 maxLoops diubah menjadi ${maxLoops}`); }; btn.onclick = () => { running = !running; btn.innerText = running ? '⏹ STOP' : '▶️ START'; if (running) mainLoop(); // ✅ hanya panggil mainLoop satu kali }; wrapper.appendChild(btn); wrapper.appendChild(input); document.body.appendChild(wrapper); } // ▶️ Mulai otomatis setTimeout(() => { createUIControls(); mainLoop(); }, 2000); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址