diff --git a/Auto-Farm.js b/Auto-Farm.js index eb5a554..e1824d2 100644 --- a/Auto-Farm.js +++ b/Auto-Farm.js @@ -26,11 +26,33 @@ language: 'en' }; + // [NEW CODE] Global variable to store the captured CAPTCHA token. + let capturedCaptchaToken = null; + + // [NEW CODE] Intercept window.fetch to capture the 't' token from manual paints. + const originalFetch = window.fetch; + window.fetch = async (url, options) => { + if (typeof url === 'string' && url.includes('https://backend.wplace.live/s0/pixel/')) { + try { + const payload = JSON.parse(options.body); + if (payload.t) { + console.log("✅ CAPTCHA Token Captured:", payload.t); + capturedCaptchaToken = payload.t; + if (document.querySelector('#statusText')?.textContent.includes('CAPTCHA')) { + updateUI("Token captured! Ready to start.", "success"); + } + } + } catch (e) { /* Ignore non-JSON bodies */ } + } + return originalFetch(url, options); + }; + const sleep = ms => new Promise(r => setTimeout(r, ms)); + // Modified the original fetchAPI to use the new overridden fetch const fetchAPI = async (url, options = {}) => { try { - const res = await fetch(url, { + const res = await fetch(url, { // 'fetch' here is now our overridden version credentials: 'include', ...options }); @@ -45,13 +67,32 @@ y: Math.floor(Math.random() * CONFIG.PIXELS_PER_LINE) }); + // [MODIFIED] The paintPixel function now includes the CAPTCHA token. const paintPixel = async (x, y) => { const randomColor = Math.floor(Math.random() * 31) + 1; - return await fetchAPI(`https://backend.wplace.live/s0/pixel/${CONFIG.START_X}/${CONFIG.START_Y}`, { + + // Construct the payload with the token + const payload = { + coords: [x, y], + colors: [randomColor], + t: capturedCaptchaToken + }; + + const res = await fetch(`https://backend.wplace.live/s0/pixel/${CONFIG.START_X}/${CONFIG.START_Y}`, { method: 'POST', - headers: { 'Content-Type': 'text/plain;charset=UTF-8' }, - body: JSON.stringify({ coords: [x, y], colors: [randomColor] }) + headers: { 'Content-Type': 'text/plain;charset=UTF-8', 'credentials': 'include' }, + body: JSON.stringify(payload) }); + + // If we get a 403 Forbidden error, our token is likely expired. + if (res.status === 403) { + console.error("❌ 403 Forbidden. CAPTCHA token might be invalid or expired."); + capturedCaptchaToken = null; // Invalidate the token. + state.running = false; // Stop the bot. + return { painted: 'token_error' }; // Return a special status. + } + + return await res.json(); }; const getCharge = async () => { @@ -74,18 +115,13 @@ try { const response = await fetch('https://ipapi.co/json/'); const data = await response.json(); - if (data.country === 'BR') { - state.language = 'pt'; - } else if (data.country === 'US') { - state.language = 'en'; - } else { - state.language = 'en'; - } + state.language = (data.country === 'BR') ? 'pt' : 'en'; } catch { state.language = 'en'; } }; + // [MODIFIED] The main loop now handles the token error case. const paintLoop = async () => { while (state.running) { const { count, cooldownMs } = state.charges; @@ -100,6 +136,16 @@ const randomPos = getRandomPosition(); const paintResult = await paintPixel(randomPos.x, randomPos.y); + // Handle the special token error status + if (paintResult?.painted === 'token_error') { + updateUI(state.language === 'pt' ? '❗ Token CAPTCHA inválido. Por favor, pinte um pixel manualmente.' : '❗ Invalid CAPTCHA token. Please paint one pixel manually.', 'error'); + const toggleBtn = document.getElementById('toggleBtn'); + toggleBtn.innerHTML = ` ${state.language === 'pt' ? 'Iniciar' : 'Start'}`; + toggleBtn.classList.add('wplace-btn-primary'); + toggleBtn.classList.remove('wplace-btn-stop'); + break; // Exit the loop + } + if (paintResult?.painted === 1) { state.paintedCount++; state.lastPixel = { @@ -370,11 +416,17 @@ const toggleBtn = panel.querySelector('#toggleBtn'); const minimizeBtn = panel.querySelector('#minimizeBtn'); - const statusText = panel.querySelector('#statusText'); const content = panel.querySelector('.wplace-content'); - const statsArea = panel.querySelector('#statsArea'); + // [MODIFIED] The start/stop button now checks for a token before starting. toggleBtn.addEventListener('click', () => { + if (!state.running) { // When trying to start + if (!capturedCaptchaToken) { + updateUI(state.language === 'pt' ? '❗ Pinte um pixel manualmente primeiro!' : '❗ Paint a pixel manually first!', 'error'); + return; // Do not start + } + } + state.running = !state.running; if (state.running) { @@ -462,4 +514,4 @@ createUI(); await getCharge(); updateStats(); -})(); +})(); \ No newline at end of file