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 = '
CAPTCHA Required
Please complete the CAPTCHA below to continue:
'; + + const widgetContainer = document.createElement('div'); + container.appendChild(widgetContainer); + + // Set a timeout for interactive mode + const timeout = setTimeout(() => { + console.warn('โฐ Interactive Turnstile widget timeout'); + container.style.display = 'none'; + resolve(null); + }, 60000); // 60 seconds for user interaction + + const widgetId = window.turnstile.render(widgetContainer, { + sitekey, + action, + size: 'normal', + theme: 'light', + callback: (token) => { + clearTimeout(timeout); + container.style.display = 'none'; + console.log('โœ… Interactive Turnstile completed successfully'); + + if (typeof token === 'string' && token.length > 20) { + resolve(token); + } else { + console.warn('โŒ Invalid token from interactive widget'); + resolve(null); + } + }, + 'error-callback': (error) => { + clearTimeout(timeout); + container.style.display = 'none'; + console.warn('โŒ Interactive Turnstile error:', error); + resolve(null); + }, + }); + + this._turnstileWidgetId = widgetId; + this._lastSitekey = sitekey; + + if (!widgetId) { + clearTimeout(timeout); + container.style.display = 'none'; + console.warn('โŒ Failed to create interactive Turnstile widget'); + resolve(null); + } else { + console.log('โœ… Interactive Turnstile widget created, waiting for user interaction...'); + } + } catch (e) { + console.error('โŒ Interactive Turnstile creation failed:', e); + resolve(null); + } + }); }, async generatePaintToken(sitekey) { @@ -1808,9 +1942,17 @@ detectSitekey(fallback = '0x4AAAAAABpqJe8FO0N84q0F') { // Cache sitekey to avoid repeated DOM queries if (this._cachedSitekey) { + console.log("๐Ÿ” Using cached sitekey:", this._cachedSitekey); return this._cachedSitekey; } + // List of potential sitekeys to try + const potentialSitekeys = [ + '0x4AAAAAABpqJe8FO0N84q0F', // WPlace common sitekey + '0x4AAAAAAAJ7xjKAp6Mt_7zw', // Alternative WPlace sitekey + '0x4AAAAAADm5QWx6Ov2LNF2g', // Another common sitekey + ]; + try { // Try to find sitekey in data attributes const sitekeySel = document.querySelector('[data-sitekey]'); @@ -1831,6 +1973,17 @@ return this._cachedSitekey; } + // Try to find sitekey in meta tags + const metaTags = document.querySelectorAll('meta[name*="turnstile"], meta[property*="turnstile"]'); + for (const meta of metaTags) { + const content = meta.getAttribute('content'); + if (content && content.length > 10) { + this._cachedSitekey = content; + console.log("๐Ÿ” Sitekey detected from meta tag:", this._cachedSitekey); + return this._cachedSitekey; + } + } + // Try global variable if (typeof window !== 'undefined' && window.__TURNSTILE_SITEKEY && window.__TURNSTILE_SITEKEY.length > 10) { this._cachedSitekey = window.__TURNSTILE_SITEKEY; @@ -1842,13 +1995,22 @@ const scripts = document.querySelectorAll('script'); for (const script of scripts) { const content = script.textContent || script.innerHTML; - const sitekeyMatch = content.match(/sitekey['":\s]+(['"0-9a-zA-Z_-]{20,})/i); + const sitekeyMatch = content.match(/sitekey['":\s]+(['"0-9a-zA-X_-]{20,})/i); if (sitekeyMatch && sitekeyMatch[1] && sitekeyMatch[1].length > 10) { this._cachedSitekey = sitekeyMatch[1].replace(/['"]/g, ''); console.log("๐Ÿ” Sitekey detected from script content:", this._cachedSitekey); return this._cachedSitekey; } } + + // If no sitekey found through detection, try the known working sitekeys + console.log("๐Ÿ” No sitekey detected, trying known working sitekeys..."); + for (const testSitekey of potentialSitekeys) { + console.log("๐Ÿ” Trying sitekey:", testSitekey); + this._cachedSitekey = testSitekey; + return testSitekey; + } + } catch (error) { console.warn('Error detecting sitekey:', error); } @@ -2877,18 +3039,23 @@ // Use optimized token generation with automatic sitekey detection const sitekey = Utils.detectSitekey(); console.log("๐Ÿ”‘ Generating Turnstile token for sitekey:", sitekey); - console.log('๐Ÿงญ UA:', navigator.userAgent, 'Platform:', navigator.platform); + console.log('๐Ÿงญ UA:', navigator.userAgent.substring(0, 50) + '...', 'Platform:', navigator.platform); + + // Add additional checks before token generation + if (!window.turnstile) { + throw new Error('Turnstile library not loaded'); + } const token = await Utils.generatePaintToken(sitekey); - console.log(`๐Ÿ” Token received - Type: ${typeof token}, Value: ${token ? (token.length > 50 ? token.substring(0, 50) + '...' : token) : 'null/undefined'}, Length: ${token?.length || 0}`); + console.log(`๐Ÿ” Token received - Type: ${typeof token}, Value: ${token ? (typeof token === 'string' ? (token.length > 50 ? token.substring(0, 50) + '...' : token) : JSON.stringify(token)) : 'null/undefined'}, Length: ${token?.length || 0}`); - if (token && token.length > 20) { + if (typeof token === 'string' && token.length > 20) { const duration = Math.round(performance.now() - startTime); console.log(`โœ… Turnstile token generated successfully in ${duration}ms`); return token; } else { - throw new Error(`Invalid or empty token received - Type: ${typeof token}, Length: ${token?.length || 0}`); + throw new Error(`Invalid or empty token received - Type: ${typeof token}, Value: ${JSON.stringify(token)}, Length: ${token?.length || 0}`); } } catch (error) { const duration = Math.round(performance.now() - startTime); @@ -4198,7 +4365,7 @@
๐Ÿ–ผ๏ธ Image Management
- @@ -4260,7 +4427,7 @@ ${Utils.t("saveData")} - @@ -4270,7 +4437,7 @@ ${Utils.t("saveToFile")} - @@ -4310,42 +4477,88 @@
` - // Modern Settings Container + // Modern Settings Container with Theme Support + // Use the theme variable already declared at the top of createUI function const settingsContainer = document.createElement("div") settingsContainer.id = "wplace-settings-container" + + // Apply theme-based styling + const themeBackground = theme.primary ? + `linear-gradient(135deg, ${theme.primary} 0%, ${theme.secondary || theme.primary} 100%)` : + `linear-gradient(135deg, #667eea 0%, #764ba2 100%)` + settingsContainer.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - border: none; - border-radius: 16px; + background: ${themeBackground}; + border: ${theme.borderWidth || '1px'} ${theme.borderStyle || 'solid'} ${theme.accent || 'rgba(255,255,255,0.1)'}; + border-radius: ${theme.borderRadius || '16px'}; padding: 0; z-index: 10002; display: none; min-width: 420px; max-width: 480px; - color: white; - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; - box-shadow: 0 20px 40px rgba(0,0,0,0.3), 0 0 0 1px rgba(255,255,255,0.1); - backdrop-filter: blur(10px); + color: ${theme.text || 'white'}; + font-family: ${theme.fontFamily || "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif"}; + box-shadow: ${theme.boxShadow || '0 20px 40px rgba(0,0,0,0.3), 0 0 0 1px rgba(255,255,255,0.1)'}; + backdrop-filter: ${theme.backdropFilter || 'blur(10px)'}; overflow: hidden; animation: settingsSlideIn 0.4s ease-out; + ${theme.animations?.glow ? ` + box-shadow: ${theme.boxShadow || '0 20px 40px rgba(0,0,0,0.3)'}, + 0 0 30px ${theme.highlight || theme.neon || '#00ffff'}; + ` : ''} ` settingsContainer.innerHTML = ` -
+
+ ${theme.animations?.scanline ? ` +
+ ` : ''}
-

- +

+ ${Utils.t("settings")}

+ ${theme.animations?.glow ? ` + box-shadow: 0 0 10px ${theme.error || '#ff0000'}33; + ` : ''} + " onmouseover=" + this.style.background='${theme.error || '#ff0000'}66'; + this.style.transform='scale(1.1)'; + ${theme.animations?.glow ? `this.style.boxShadow='0 0 20px ${theme.error || '#ff0000'}';` : ''} + " onmouseout=" + this.style.background='${theme.accent ? `${theme.accent}66` : 'rgba(255,255,255,0.1)'}'; + this.style.transform='scale(1)'; + ${theme.animations?.glow ? `this.style.boxShadow='0 0 10px ${theme.error || '#ff0000'}33';` : ''} + ">โœ•
@@ -4403,26 +4627,56 @@
- -
+ + +
+ + +
+ + +
${CONFIG.PAINTING_SPEED.MAX}
-