diff --git a/Auto-Image.js b/Auto-Image.js index 3c9a29a..89e49c1 100644 --- a/Auto-Image.js +++ b/Auto-Image.js @@ -10,6 +10,11 @@ MAX: 1000, // Maximum 1000 pixels batch size DEFAULT: 5, // Default 5 pixels batch size }, + BATCH_MODE: "normal", // "normal" or "random" - default to normal + RANDOM_BATCH_RANGE: { + MIN: 3, // Random range minimum + MAX: 20, // Random range maximum + }, PAINTING_SPEED_ENABLED: false, // Off by default AUTO_CAPTCHA_ENABLED: true, // Turnstile generator enabled by default TOKEN_SOURCE: "generator", // "generator", "manual", or "hybrid" - default to generator @@ -1059,8 +1064,12 @@ estimatedTime: 0, language: "en", paintingSpeed: CONFIG.PAINTING_SPEED.DEFAULT, // pixels batch size + batchMode: CONFIG.BATCH_MODE, // "normal" or "random" + randomBatchMin: CONFIG.RANDOM_BATCH_RANGE.MIN, // Random range minimum + randomBatchMax: CONFIG.RANDOM_BATCH_RANGE.MAX, // Random range maximum cooldownChargeThreshold: CONFIG.COOLDOWN_CHARGE_THRESHOLD, tokenSource: CONFIG.TOKEN_SOURCE, // "generator" or "manual" + initialSetupComplete: false, // Track if initial startup setup is complete (only happens once) overlayOpacity: CONFIG.OVERLAY.OPACITY_DEFAULT, blueMarbleEnabled: CONFIG.OVERLAY.BLUE_MARBLE_DEFAULT, ditheringEnabled: true, @@ -1689,44 +1698,83 @@ async executeTurnstile(sitekey, action = 'paint') { await this.loadTurnstile(); - if (this._turnstileWidgetId && this._lastSitekey === sitekey && window.turnstile?.execute) { - try { - console.log("๐ Reusing existing Turnstile widget..."); - const token = await Promise.race([ - window.turnstile.execute(this._turnstileWidgetId, { action }), - new Promise((_, reject) => setTimeout(() => reject(new Error('Execute timeout')), 15000)) - ]); - if (token && token.length > 20) { - console.log("โ Token generated via widget reuse"); - return token; + // Try multiple sitekeys if the first one fails + const sitekeys = [ + sitekey, + '0x4AAAAAABpqJe8FO0N84q0F' + ]; + + for (let i = 0; i < sitekeys.length; i++) { + const currentSitekey = sitekeys[i]; + console.log(`๐ง Trying sitekey ${i + 2}/${sitekeys.length}:`, currentSitekey); + + // Try reusing existing widget first + if (this._turnstileWidgetId && this._lastSitekey === currentSitekey && window.turnstile?.execute) { + try { + console.log("๐ Reusing existing Turnstile widget..."); + const token = await Promise.race([ + window.turnstile.execute(this._turnstileWidgetId, { action }), + new Promise((_, reject) => setTimeout(() => reject(new Error('Execute timeout')), 15000)) + ]); + if (token && typeof token === 'string' && token.length > 20) { + console.log("โ Token generated via widget reuse"); + return token; + } + } catch (err) { + console.warn('๐ Widget reuse failed:', err.message); } - } catch (err) { - console.warn('๐ Widget reuse failed, will create a fresh widget:', err.message); } + + // Try invisible widget + const invisible = await this.createNewTurnstileWidgetInvisible(currentSitekey, action); + if (invisible && typeof invisible === 'string' && invisible.length > 20) { + console.log(`โ Token generated with sitekey ${i + 1}: ${currentSitekey}`); + return invisible; + } + + console.warn(`โ Sitekey ${i + 1} failed:`, currentSitekey); + + // Clean up failed widget before trying next sitekey + if (this._turnstileWidgetId && window.turnstile?.remove) { + try { window.turnstile.remove(this._turnstileWidgetId); } catch {} + } + this._turnstileWidgetId = null; } - const invisible = await this.createNewTurnstileWidgetInvisible(sitekey, action); - if (invisible && invisible.length > 20) return invisible; - - console.log('๐ Falling back to interactive Turnstile (visible).'); + console.log('๐ All sitekeys failed for invisible widgets, trying interactive...'); return await this.createNewTurnstileWidgetInteractive(sitekey, action); }, async createNewTurnstileWidgetInvisible(sitekey, action) { return new Promise((resolve) => { try { + // Force cleanup of any existing widget if (this._turnstileWidgetId && window.turnstile?.remove) { - try { window.turnstile.remove(this._turnstileWidgetId); } catch {} + try { + window.turnstile.remove(this._turnstileWidgetId); + console.log('๐งน Cleaned up existing Turnstile widget'); + } catch (e) { + console.warn('โ ๏ธ Widget cleanup warning:', e.message); + } } + const container = this.ensureTurnstileContainer(); container.innerHTML = ''; + // Verify Turnstile is available + if (!window.turnstile?.render) { + console.error('โ Turnstile not available for rendering'); + resolve(null); + return; + } + // Set a timeout to resolve with null if no token is received const timeout = setTimeout(() => { - console.warn('โฐ Turnstile widget timeout - no token received'); + console.warn('โฐ Turnstile widget timeout - no token received in 15s'); resolve(null); }, 15000); + console.log('๐ง Creating invisible Turnstile widget...'); const widgetId = window.turnstile.render(container, { sitekey, action, @@ -1735,8 +1783,22 @@ 'retry-interval': 8000, callback: (token) => { clearTimeout(timeout); - console.log('โ Turnstile token received from hidden widget:', token ? 'Valid token' : 'Invalid token'); - resolve(token); + console.log('๐ Turnstile callback received:', { + type: typeof token, + value: token, + length: token?.length || 0, + isString: typeof token === 'string', + isValid: typeof token === 'string' && token.length > 20 + }); + + // Ensure we have a valid string token + if (typeof token === 'string' && token.length > 20) { + console.log('โ Valid token received from hidden widget'); + resolve(token); + } else { + console.warn('โ Invalid token received from hidden widget - resolving with null'); + resolve(null); + } }, 'error-callback': (error) => { clearTimeout(timeout); @@ -1745,7 +1807,7 @@ }, 'timeout-callback': () => { clearTimeout(timeout); - console.warn('โฐ Turnstile timeout callback'); + console.warn('โฐ Turnstile timeout callback triggered'); resolve(null); }, }); @@ -1755,30 +1817,102 @@ if (!widgetId) { clearTimeout(timeout); - console.warn('โ Failed to create Turnstile widget'); + console.warn('โ Failed to create Turnstile widget - render returned invalid ID'); resolve(null); + } else { + console.log('โ Turnstile widget created with ID:', widgetId); } } catch (e) { - console.warn('โ Invisible Turnstile failed:', e); + console.error('โ Invisible Turnstile creation failed:', e); resolve(null); } }); }, async createNewTurnstileWidgetInteractive(sitekey, action) { - // Since we want purely background token generation, attempt invisible again - // or fallback to manual pixel placement automation - console.log('๐ Interactive widget requested - falling back to invisible or manual automation'); + // Create a visible widget that users can interact with if needed + console.log('๐ Creating interactive Turnstile widget (visible)'); - // Try invisible one more time - const invisibleToken = await this.createNewTurnstileWidgetInvisible(sitekey, action); - if (invisibleToken && invisibleToken.length > 20) { - return invisibleToken; - } - - // If invisible fails, return null to trigger manual automation fallback - console.log('โ ๏ธ All Turnstile methods exhausted, manual fallback will be used'); - return null; + return new Promise((resolve) => { + try { + // Force cleanup of any existing widget + if (this._turnstileWidgetId && window.turnstile?.remove) { + try { + window.turnstile.remove(this._turnstileWidgetId); + } catch (e) { + console.warn('โ ๏ธ Widget cleanup warning:', e.message); + } + } + + const container = this.ensureTurnstileContainer(); + container.innerHTML = ''; + + // Make container visible for interactive mode + container.style.display = 'block'; + container.style.position = 'fixed'; + container.style.top = '50%'; + container.style.left = '50%'; + container.style.transform = 'translate(-50%, -50%)'; + container.style.zIndex = '10000'; + container.style.backgroundColor = 'white'; + container.style.padding = '20px'; + container.style.borderRadius = '8px'; + container.style.boxShadow = '0 4px 20px rgba(0,0,0,0.3)'; + + // Add instruction text + container.innerHTML = '