From ca4e5244bacc74108366ffcf0ecf6edfb8fa8d76 Mon Sep 17 00:00:00 2001 From: JustEngineer Date: Sun, 12 Oct 2025 08:50:28 +0300 Subject: [PATCH 1/4] Fixed situation, when bot are waiting for charges to restore, when there another acc with charges, by simply switching acc when done with painting --- Extension/scripts/Acc-Switch.js | 63 +++-- Extension/scripts/Auto-Image.js | 436 +++++++++++++++++++------------- 2 files changed, 294 insertions(+), 205 deletions(-) diff --git a/Extension/scripts/Acc-Switch.js b/Extension/scripts/Acc-Switch.js index 536e9be..0bd2e4f 100644 --- a/Extension/scripts/Acc-Switch.js +++ b/Extension/scripts/Acc-Switch.js @@ -7517,38 +7517,16 @@ return; } - swapAccountTrigger(nextToken); - - let maxRetries = 20; - let retryCount = 0; - let swapSuccess = false; - - while (!swapSuccess && retryCount < maxRetries) { - console.log(`⏳ Waiting for account swap... (Attempt ${retryCount + 1}/${maxRetries})`); - - // Wait for a short period before checking. - await new Promise(resolve => setTimeout(resolve, 1000)); - - try { - await fetchAccount(); - - console.log("✅ Account swap confirmed."); - swapSuccess = true; - } catch (error) { - console.warn("❌ Account swap not yet successful. Retrying...", error); - retryCount++; - } - } + const swapSuccess = await swapAccountTrigger(nextToken); if (swapSuccess) { - const { charges, cooldown } = await WPlaceService.getCharges(); state.currentCharges = Math.floor(charges); state.cooldown = cooldown; Utils.performSmartSave(); updateStats(); } else { - console.error("❌ Failed to swap account after multiple retries. Stopping loop."); + console.error("❌ Failed to swap account after confirmation timeout. Stopping loop."); state.stopFlag = true; } } @@ -7800,7 +7778,7 @@ const token = accountsTokens[i]; console.log(`🔄 Refreshing account ${i + 1}/${accountsTokens.length} for data collection only...`); - swapAccountTrigger(token); + await swapAccountTrigger(token); let retries = 0; let swapped = false; @@ -7834,7 +7812,7 @@ if (originalToken) { console.log("🔄 Switching back to original account after data collection..."); - swapAccountTrigger(originalToken); + await swapAccountTrigger(originalToken); } await Utils.sleep(1000); @@ -8486,15 +8464,44 @@ console.error("An error occurred during the purchase:", e); } } - function swapAccountTrigger(token) { + async function waitForCookieSet(timeout = 10000) { + return new Promise((resolve, reject) => { + const onMessage = (event) => { + if (event.source !== window) return; + const data = event.data || {}; + if (data.type === 'cookieSet') { + window.removeEventListener('message', onMessage); + clearTimeout(timer); + resolve(true); + } + }; + const timer = setTimeout(() => { + window.removeEventListener('message', onMessage); + reject(new Error('cookieSet timeout')); + }, timeout); + window.addEventListener('message', onMessage); + }); + } + async function swapAccountTrigger(token) { localStorage.removeItem("lp"); - if (!token) return; + if (!token) { + console.error('❌ Cannot swap account: token is null or undefined'); + return false; + } console.log("Sending token to extension..."); window.postMessage({ source: 'my-userscript', type: 'setCookie', value: token }, '*'); + try { + await waitForCookieSet(10000); + console.log('✅ Cookie set confirmed'); + return true; + } catch (e) { + console.warn('⚠️ No cookieSet confirmation:', e.message); + return false; + } } async function getAccounts() { return new Promise((resolve, reject) => { diff --git a/Extension/scripts/Auto-Image.js b/Extension/scripts/Auto-Image.js index 9436bbf..58f959d 100644 --- a/Extension/scripts/Auto-Image.js +++ b/Extension/scripts/Auto-Image.js @@ -1777,8 +1777,9 @@ function getText(key, params) { async getCharges() { try { - const res = await fetch("https://backend.wplace.live/me", { + const res = await fetch(`https://backend.wplace.live/me?_=${Date.now()}` , { credentials: "include", + cache: 'no-store' }) const data = await res.json() return { @@ -1802,8 +1803,9 @@ function getText(key, params) { async fetchCheck() { try { - const res = await fetch("https://backend.wplace.live/me", { + const res = await fetch(`https://backend.wplace.live/me?_=${Date.now()}` , { credentials: "include", + cache: 'no-store' }) const data = await res.json() return { @@ -8606,72 +8608,19 @@ function getText(key, params) { break; } } else { - // Debug current state - const totalAccounts = accountManager.getAccountCount(); - console.log(`📊 Account Status - Current index: ${accountManager.currentIndex}, Total accounts: ${totalAccounts}`); - - // Check if we're at the last account in the sequence - const isLastAccount = accountManager.currentIndex >= totalAccounts - 1; - console.log(`🔍 Is last account? ${isLastAccount} (index ${accountManager.currentIndex} of ${totalAccounts})`); - - if (!isLastAccount && totalAccounts > 1) { - // Update current account status before switching - console.log('📊 Updating current account status before switch...'); - await updateCurrentAccountInList(); - - // Switch to next account immediately (no cooldown) - only if we have multiple accounts - const nextAccount = accountManager.getNextAccount(); - console.log(`🔄 Switching to next account: ${nextAccount?.displayName} (${accountManager.currentIndex + 2}/${totalAccounts})`); - const switchResult = await switchToNextAccount(accounts); - if (!switchResult) { - console.log('❌ Account switch failed, stopping'); - state.stopFlag = true; - break; - } - // Continue painting with new account immediately - continue; - } else if (totalAccounts === 1) { - // Only one account available - use cooldown and continue with same account - console.log('ℹ️ Only one account available, entering cooldown period'); - const cooldownResult = await executeCooldownPeriod(); - if (cooldownResult === 'stopped') break; - console.log('✅ Cooldown complete, continuing with same account'); - continue; - } else { - // Last account reached - use cooldown then switch to first account - console.log('⏱️ Last account reached, entering cooldown period'); - console.log(`📊 Current account: index ${accountManager.currentIndex}, Last account: index ${totalAccounts - 1}`); - - const cooldownResult = await executeCooldownPeriod(); - if (cooldownResult === 'stopped') break; - - // After cooldown, switch to first account - console.log('🔁 Cooldown complete, switching to first account'); - console.log(`🔄 Before switch - Current index: ${accountManager.currentIndex}, Target: index 0`); - - const firstAccountInfo = accountManager.getAccountByIndex(0); - const firstAccountToken = firstAccountInfo?.token; - - if (!firstAccountToken) { - console.log('❌ First account token not found, stopping'); - state.stopFlag = true; - break; - } - - // Reset to first position - accountManager.setCurrentIndex(0); - - const switchResult = await switchToSpecificAccount(firstAccountToken, firstAccountInfo.displayName); - if (!switchResult) { - console.log('❌ Switch to ID 1 failed, stopping'); - state.stopFlag = true; - break; - } - - console.log(`✅ Successfully switched to ID 1 (${firstAccountInfo.displayName}). Cycle restarted.`); - // Continue painting with first account + // Try to find an account with enough charges to continue painting + const minRequired = Math.max(1, state.cooldownChargeThreshold || 1); + console.log(`🔎 Searching for account with ≥${minRequired} charges...`); + const switched = await selectAndSwitchToAccountWithCharges(minRequired); + if (switched) { + console.log('✅ Switched to an account with sufficient charges, continuing painting immediately'); continue; } + // If none had enough charges, enter cooldown on the best available account + console.log('🕒 No accounts have enough charges. Entering cooldown on the account with the soonest recharge...'); + const cooldownResult = await executeCooldownPeriod(); + if (cooldownResult === 'stopped') break; + continue; } } } @@ -9976,13 +9925,43 @@ function getText(key, params) { type: 'setCookie', value: token }, '*'); - console.log('✅ setCookie message sent successfully'); - return true; } catch (error) { console.error('❌ Failed to send setCookie message:', error); return false; } + + // Wait for background confirmation that cookie was set + const confirmed = await new Promise((resolve) => { + let settled = false; + const timer = setTimeout(() => { + if (!settled) { + settled = true; + console.warn('⚠️ cookieSet confirmation timeout'); + resolve(false); + } + }, 10000); + function onMessage(event) { + if (event.source !== window) return; + const data = event.data || {}; + if (data.type === 'cookieSet') { + if (!settled) { + settled = true; + clearTimeout(timer); + window.removeEventListener('message', onMessage); + resolve(true); + } + } + } + window.addEventListener('message', onMessage); + }); + + if (confirmed) { + console.log('✅ Cookie set confirmed'); + } else { + console.warn('⚠️ Proceeding without cookie confirmation'); + } + return true; } async function getAccounts() { return new Promise((resolve, reject) => { @@ -10114,10 +10093,16 @@ function getText(key, params) { await switchToSpecificAccount(originalCurrentAccount.token, originalCurrentAccount.displayName); //await Utils.sleep(300); - // Mark it as current again + // Mark it as current again and sync index accountManager.updateAccountData(originalCurrentAccount.token, { isCurrent: true }); + const list = accountManager.getAllAccounts(); + const idxOriginal = list.findIndex(acc => acc.token === originalCurrentAccount.token); + if (idxOriginal !== -1 && typeof accountManager.setCurrentIndex === 'function') { + accountManager.setCurrentIndex(idxOriginal); + state.accountIndex = idxOriginal; + } } catch (error) { console.warn(`⚠️ [FETCH] Failed to switch back to original account:`, error); } @@ -10147,95 +10132,78 @@ function getText(key, params) { async function updateCurrentAccountInList() { if (accountManager.getAccountCount() === 0) return; - // Find current account in the list and update its charges - const currentAccount = accountManager.getCurrentAccount(); - if (currentAccount) { - const { charges, cooldown, droplets } = await WPlaceService.getCharges(); - state.displayCharges = Math.floor(charges); - state.preciseCurrentCharges = charges; + try { + // Always trust backend /me and then map by ID to avoid mixing data between tokens + const me = await WPlaceService.getCharges(); + state.displayCharges = Math.floor(me.charges); + state.preciseCurrentCharges = me.charges; await updateStats(); - // Update the current account data in AccountManager - accountManager.updateAccountData(currentAccount.token, { - Charges: Math.floor(state.displayCharges || state.preciseCurrentCharges || 0), - Max: state.maxCharges, - Droplets: Math.floor(droplets) - }); + const accounts = accountManager.getAllAccounts(); + const idx = accounts.findIndex(acc => acc.ID === me.id); + const targetToken = idx !== -1 ? accounts[idx].token : accountManager.getCurrentAccount()?.token; - // Re-render the account list to show updated charges - renderAccountsList(); + if (targetToken) { + accountManager.updateAccountData(targetToken, { + Charges: Math.floor(state.displayCharges || 0), + Max: Math.floor(me.max || state.maxCharges || 0), + Droplets: Math.floor(me.droplets) + }); + + // Keep manager index in sync with reality when possible + if (idx !== -1 && typeof accountManager.setCurrentIndex === 'function') { + accountManager.setCurrentIndex(idx); + state.accountIndex = idx; + } + + // Re-render the account list to show updated charges + renderAccountsList(); + } + } catch (e) { + console.warn('⚠️ updateCurrentAccountInList failed:', e); } } // Function to update current account spotlight when switching during painting async function updateCurrentAccountSpotlight() { if (accountManager.getAccountCount() === 0) return; - // await Utils.sleep(500); // Wait a bit for the switch to take effect try { - const currentAccountData = await WPlaceService.getCharges(); - console.log("Current account after switch:", currentAccountData); - console.log(`🔍 Switched to account with ID: ${currentAccountData.id}`); + const me = await WPlaceService.getCharges(); + console.log("Current account after switch:", me); + console.log(`🔍 Switched to account with ID: ${me.id}`); - // Find the current account in AccountManager and update it const accounts = accountManager.getAllAccounts(); - const currentAccount = accounts.find(acc => acc.ID === currentAccountData.id); + const idx = accounts.findIndex(acc => acc.ID === me.id); - if (currentAccount) { - const currentAccountInfo = await WPlaceService.fetchCheck(); + if (idx !== -1) { + const currentAccount = accounts[idx]; + const info = await WPlaceService.fetchCheck(); + + // Sync manager index and flags to actual account + if (typeof accountManager.setCurrentIndex === 'function') { + accountManager.setCurrentIndex(idx); + } else { + accounts.forEach((acc, i) => (acc.isCurrent = i === idx)); + } - // Update account data in AccountManager accountManager.updateAccountData(currentAccount.token, { isCurrent: true, - Charges: Math.floor(currentAccountData.charges), - Max: Math.floor(currentAccountData.max), - Droplets: Math.floor(currentAccountData.droplets), - displayName: currentAccountInfo.Username || currentAccountInfo.name || currentAccount.displayName + Charges: Math.floor(me.charges), + Max: Math.floor(me.max), + Droplets: Math.floor(me.droplets), + displayName: info.Username || info.name || currentAccount.displayName }); - console.log(`🎯 Updated current account spotlight: ${currentAccount.displayName}`); + // Mirror to UI state for consistency + state.displayCharges = Math.floor(me.charges); + state.preciseCurrentCharges = me.charges; + state.cooldown = me.cooldown; + state.accountIndex = idx; - // Check for autobuy after account is loaded - if (CONFIG.autoBuyToggle && Math.floor(currentAccountData.droplets) > 500) { - console.log(`💰 Account has ${Math.floor(currentAccountData.droplets)} droplets (>500), triggering autobuy...`); - try { - const purchaseResult = await purchase(CONFIG.autoBuy); - if (purchaseResult == 2) { - console.log('✅ Autobuy successful after account switch'); - // Update charges after purchase - const updatedCharges = await WPlaceService.getCharges(); - accountManager.updateAccountData(currentAccount.token, { - Charges: Math.floor(updatedCharges.charges), - Droplets: Math.floor(updatedCharges.droplets) - }); - // Re-render account list to show updated status after purchase - renderAccountsList(); - } else { - console.log('❌ Autobuy failed after account switch'); - } - } catch (error) { - console.error('❌ Error during autobuy after account switch:', error); - } - } else if (CONFIG.autoBuyToggle) { - console.log(`💰 Account has ${Math.floor(currentAccountData.droplets)} droplets (≤500), skipping autobuy`); - } - - // Re-render the account list to show new current account renderAccountsList(); - - console.log(`🔒 PRESERVING currentActiveIndex: ${state.currentActiveIndex} (do not recalculate from isCurrent flag)`); - console.log(`� Account at currentActiveIndex ${state.currentActiveIndex}: ${state.originalAccountOrder[state.currentActiveIndex]?.displayName} (ID ${state.originalAccountOrder[state.currentActiveIndex]?.orderId})`); - - // Update accountIndex to match original array position - const originalArrayIndex = state.allAccountsInfo.findIndex(acc => acc.isCurrent); - if (originalArrayIndex !== -1) { - state.accountIndex = originalArrayIndex; - } - - console.log(`📊 Final state: activeIndex=${state.currentActiveIndex}, accountIndex=${state.accountIndex}, orderId=${newCurrentAccount.orderId}`); - - console.warn(`⚠️ Could not find account ID ${newCurrentAccount.orderId} in switching order`); - - console.warn(`⚠️ Could not find switched account with ID ${currentAccountData.id} in account list`); + console.log(`🎯 Updated current account spotlight: ${currentAccount.displayName}`); + } else { + console.warn(`⚠️ Could not find switched account with ID ${me.id} in account list`); } // Re-render the account list to show new current account @@ -10359,6 +10327,10 @@ function getText(key, params) { return false; } + // Capture the pre-switch (current) account to detect stale reads + const preSwitchAccount = accountManager.getCurrentAccount(); + const previousKnownId = preSwitchAccount?.ID || null; + // Get next account using simplified manager const nextAccount = accountManager.switchToNext(); if (!nextAccount) { @@ -10385,8 +10357,46 @@ function getText(key, params) { console.log(`✅ [SWITCH] Successfully switched to ${nextAccount.displayName}`); - // Wait a moment for the switch to fully complete - // await new Promise(resolve => setTimeout(resolve, 1000)); + // Verify backend reflects the new account to avoid stale reads + // Strategy: poll /me until we see an ID different from the pre-switch account's ID + // Only then accept and (if needed) assign the next account's ID. + let verifiedId = null; + for (let attempt = 1; attempt <= 8 && !verifiedId; attempt++) { + try { + const me = await WPlaceService.getCharges(); + const curId = me?.id; + if (!curId) { + await Utils.sleep(500); + continue; + } + + if (previousKnownId && curId === previousKnownId) { + console.log(`⏳ [SWITCH] Still seeing previous ID ${curId} (attempt ${attempt}/8), waiting...`); + await Utils.sleep(500); + continue; + } + + // If we had a stored ID for the target and it's different from what we see now, + // prefer the live value (curId) and update the stored ID. + if (nextAccount.ID && nextAccount.ID !== curId) { + console.log(`🔁 [SWITCH] Updating stored ID for ${nextAccount.displayName}: ${nextAccount.ID} → ${curId}`); + } + + verifiedId = curId; + break; + } catch (e) { + await Utils.sleep(500); + } + } + + if (!verifiedId) { + console.warn('⚠️ [SWITCH] Could not verify account change via /me after cookie set; skipping ID update but proceeding cautiously.'); + } else { + // Persist verified ID for the next account + if (nextAccount.ID !== verifiedId) { + accountManager.updateAccountData(nextAccount.token, { ID: verifiedId }); + } + } // Update the account status and UI after successful switch await updateCurrentAccountInList(); @@ -10401,54 +10411,77 @@ function getText(key, params) { // SIMPLIFIED helper function for specific account switching async function switchToSpecificAccount(token, accountName) { console.log(`🔄 [SPECIFIC SWITCH] Attempting to switch to account: ${accountName}`); + if (!token) { + console.error('❌ [SPECIFIC SWITCH] Missing token'); + return false; + } console.log(`🔑 [SPECIFIC SWITCH] Using token: ${token.substring(0, 20)}...`); - await swapAccountTrigger(token); + // Capture previous account ID to detect stale responses + let previousId = null; + try { + const prev = await WPlaceService.getCharges(); + previousId = prev?.id || null; + } catch {} - let maxRetries = 20; - let retryCount = 0; - let swapSuccess = false; - - while (!swapSuccess && retryCount < maxRetries) { - console.log(`⏳ [SPECIFIC SWITCH] Waiting for account swap... (Attempt ${retryCount + 1}/${maxRetries})`); - //await new Promise(resolve => setTimeout(resolve, 1000)); + const ok = await swapAccountTrigger(token); + if (!ok) { + console.error('❌ [SPECIFIC SWITCH] Cookie confirmation failed'); + return false; + } + // Poll /me until it reflects a different ID than the previous account + let verifiedId = null; + for (let attempt = 1; attempt <= 8 && !verifiedId; attempt++) { try { - // await fetchAccount(); - console.log('✅ [SPECIFIC SWITCH] Account swap confirmed.'); - swapSuccess = true; - } catch (error) { - console.warn('❌ [SPECIFIC SWITCH] Account swap not yet successful. Retrying...', error); - retryCount++; - - if (retryCount % 5 === 0) { - console.log('🔄 [SPECIFIC SWITCH] Re-triggering account swap...'); - await swapAccountTrigger(token); - await new Promise(resolve => setTimeout(resolve, 2000)); + const me = await WPlaceService.getCharges(); + const curId = me?.id; + if (!curId) { + await Utils.sleep(500); + continue; } + if (previousId && curId === previousId) { + console.log(`⏳ [SPECIFIC SWITCH] Still seeing previous ID ${curId} (attempt ${attempt}/8), waiting...`); + await Utils.sleep(500); + continue; + } + verifiedId = curId; + break; + } catch { + await Utils.sleep(500); } } - if (swapSuccess) { - const { charges, cooldown } = await WPlaceService.getCharges(); - state.displayCharges = Math.floor(charges); - state.preciseCurrentCharges = charges; - state.cooldown = cooldown; - Utils.performSmartSave(); - await updateStats(); - - // Update account data in manager - accountManager.updateAccountData({ charges, cooldown }); - - // Update the account status and UI after successful switch - await updateCurrentAccountSpotlight(); - - console.log(`✅ [SPECIFIC SWITCH] Successfully switched to ${accountName} with ${Math.floor(charges)} charges`); - return true; + if (!verifiedId) { + console.warn('⚠️ [SPECIFIC SWITCH] Could not verify account change via /me; proceeding.'); } else { - console.error(`❌ [SPECIFIC SWITCH] Failed to swap to ${accountName} after multiple retries.`); - return false; + // Persist ID and mark as current in AccountManager + accountManager.updateAccountData(token, { ID: verifiedId, isCurrent: true }); } + + // Sync manager index to the token we explicitly switched to + try { + const list = accountManager.getAllAccounts(); + const idxByToken = list.findIndex(acc => acc.token === token); + if (idxByToken !== -1 && typeof accountManager.setCurrentIndex === 'function') { + accountManager.setCurrentIndex(idxByToken); + state.accountIndex = idxByToken; + } + } catch {} + + // Fetch fresh stats for UI/state + const { charges, cooldown, droplets, max } = await WPlaceService.getCharges(); + state.displayCharges = Math.floor(charges); + state.preciseCurrentCharges = charges; + state.cooldown = cooldown; + Utils.performSmartSave(); + await updateStats(); + + // Update the account status and UI after successful switch + await updateCurrentAccountSpotlight(); + + console.log(`✅ [SPECIFIC SWITCH] Switched to ${accountName} with ${Math.floor(charges)} charges`); + return true; } // Wait for dependencies before initializing UI @@ -10492,6 +10525,55 @@ function getText(key, params) { return createUI(); } + // Helper: iterate over accounts to find one with enough charges; otherwise pick best cooldown + async function selectAndSwitchToAccountWithCharges(minRequired = 1) { + try { + const total = accountManager.getAccountCount(); + if (total <= 1) return false; + + const startIdx = accountManager.currentIndex; + let best = { cooldown: Infinity, token: null, name: null, idx: -1 }; + + for (let step = 1; step <= total - 1; step++) { + const idx = (startIdx + step) % total; + const acc = accountManager.getAccountByIndex(idx); + if (!acc || !acc.token) continue; + + console.log(`🔄 [SEARCH] Switching temporarily to ${acc.displayName} (${idx + 1}/${total}) to check charges...`); + const ok = await switchToSpecificAccount(acc.token, acc.displayName); + if (!ok) { + console.warn(`⚠️ [SEARCH] Failed to switch to ${acc.displayName}, trying next...`); + continue; + } + + const me = await WPlaceService.getCharges(); + const charges = Math.floor(me?.charges || 0); + const cooldown = Math.max(0, Number(me?.cooldown || 0)); + if (charges >= minRequired) { + console.log(`✅ [SEARCH] Found account with sufficient charges: ${acc.displayName} (⚡${charges})`); + return true; + } + + console.log(`⏳ [SEARCH] ${acc.displayName} has no charges (⚡${charges}), cooldown ${cooldown}ms`); + if (cooldown < best.cooldown) { + best = { cooldown, token: acc.token, name: acc.displayName, idx }; + } + } + + // None had enough charges: switch to the one with the soonest recharge and return false + if (best.token && best.idx !== accountManager.currentIndex) { + console.log(`🎯 [SEARCH] Switching to account with soonest recharge: ${best.name} (~${Utils.msToTimeText(best.cooldown)})`); + await switchToSpecificAccount(best.token, best.name); + } else { + console.log('🎯 [SEARCH] Staying on current account for cooldown.'); + } + return false; + } catch (e) { + console.warn('⚠️ selectAndSwitchToAccountWithCharges failed:', e); + return false; + } + } + waitForDependenciesAndInitialize().then(() => { // Generate token automatically after UI is ready setTimeout(initializeTokenGenerator, 1000); From 4fe94b4d07f8a230c06b8ee18085cd561fe4da34 Mon Sep 17 00:00:00 2001 From: JustEngineer Date: Sun, 12 Oct 2025 08:57:23 +0300 Subject: [PATCH 2/4] rename "me" to "currentAccountData" to match original style --- Extension/scripts/Auto-Image.js | 52 ++++++++++++++++----------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/Extension/scripts/Auto-Image.js b/Extension/scripts/Auto-Image.js index 58f959d..8df37c5 100644 --- a/Extension/scripts/Auto-Image.js +++ b/Extension/scripts/Auto-Image.js @@ -10134,20 +10134,20 @@ function getText(key, params) { try { // Always trust backend /me and then map by ID to avoid mixing data between tokens - const me = await WPlaceService.getCharges(); - state.displayCharges = Math.floor(me.charges); - state.preciseCurrentCharges = me.charges; + const currentAccountData = await WPlaceService.getCharges(); + state.displayCharges = Math.floor(currentAccountData.charges); + state.preciseCurrentCharges = currentAccountData.charges; await updateStats(); const accounts = accountManager.getAllAccounts(); - const idx = accounts.findIndex(acc => acc.ID === me.id); + const idx = accounts.findIndex(acc => acc.ID === currentAccountData.id); const targetToken = idx !== -1 ? accounts[idx].token : accountManager.getCurrentAccount()?.token; if (targetToken) { accountManager.updateAccountData(targetToken, { Charges: Math.floor(state.displayCharges || 0), - Max: Math.floor(me.max || state.maxCharges || 0), - Droplets: Math.floor(me.droplets) + Max: Math.floor(currentAccountData.max || state.maxCharges || 0), + Droplets: Math.floor(currentAccountData.droplets) }); // Keep manager index in sync with reality when possible @@ -10168,16 +10168,16 @@ function getText(key, params) { async function updateCurrentAccountSpotlight() { if (accountManager.getAccountCount() === 0) return; try { - const me = await WPlaceService.getCharges(); - console.log("Current account after switch:", me); - console.log(`🔍 Switched to account with ID: ${me.id}`); + const currentAccountData = await WPlaceService.getCharges(); + console.log("Current account after switch:", currentAccountData); + console.log(`🔍 Switched to account with ID: ${currentAccountData.id}`); const accounts = accountManager.getAllAccounts(); - const idx = accounts.findIndex(acc => acc.ID === me.id); + const idx = accounts.findIndex(acc => acc.ID === currentAccountData.id); if (idx !== -1) { const currentAccount = accounts[idx]; - const info = await WPlaceService.fetchCheck(); + const currentAccountInfo = await WPlaceService.fetchCheck(); // Sync manager index and flags to actual account if (typeof accountManager.setCurrentIndex === 'function') { @@ -10188,22 +10188,22 @@ function getText(key, params) { accountManager.updateAccountData(currentAccount.token, { isCurrent: true, - Charges: Math.floor(me.charges), - Max: Math.floor(me.max), - Droplets: Math.floor(me.droplets), - displayName: info.Username || info.name || currentAccount.displayName + Charges: Math.floor(currentAccountData.charges), + Max: Math.floor(currentAccountData.max), + Droplets: Math.floor(currentAccountData.droplets), + displayName: currentAccountInfo.Username || currentAccountInfo.name || currentAccount.displayName }); // Mirror to UI state for consistency - state.displayCharges = Math.floor(me.charges); - state.preciseCurrentCharges = me.charges; - state.cooldown = me.cooldown; + state.displayCharges = Math.floor(currentAccountData.charges); + state.preciseCurrentCharges = currentAccountData.charges; + state.cooldown = currentAccountData.cooldown; state.accountIndex = idx; renderAccountsList(); console.log(`🎯 Updated current account spotlight: ${currentAccount.displayName}`); } else { - console.warn(`⚠️ Could not find switched account with ID ${me.id} in account list`); + console.warn(`⚠️ Could not find switched account with ID ${currentAccountData.id} in account list`); } // Re-render the account list to show new current account @@ -10363,8 +10363,8 @@ function getText(key, params) { let verifiedId = null; for (let attempt = 1; attempt <= 8 && !verifiedId; attempt++) { try { - const me = await WPlaceService.getCharges(); - const curId = me?.id; + const currentAccountData = await WPlaceService.getCharges(); + const curId = currentAccountData?.id; if (!curId) { await Utils.sleep(500); continue; @@ -10434,8 +10434,8 @@ function getText(key, params) { let verifiedId = null; for (let attempt = 1; attempt <= 8 && !verifiedId; attempt++) { try { - const me = await WPlaceService.getCharges(); - const curId = me?.id; + const currentAccountData = await WPlaceService.getCharges(); + const curId = currentAccountData?.id; if (!curId) { await Utils.sleep(500); continue; @@ -10546,9 +10546,9 @@ function getText(key, params) { continue; } - const me = await WPlaceService.getCharges(); - const charges = Math.floor(me?.charges || 0); - const cooldown = Math.max(0, Number(me?.cooldown || 0)); + const currentAccountData = await WPlaceService.getCharges(); + const charges = Math.floor(currentAccountData?.charges || 0); + const cooldown = Math.max(0, Number(currentAccountData?.cooldown || 0)); if (charges >= minRequired) { console.log(`✅ [SEARCH] Found account with sufficient charges: ${acc.displayName} (⚡${charges})`); return true; From 027b06262a5a469edb65379b3e4a0d5b24c1b0f8 Mon Sep 17 00:00:00 2001 From: JustEngineer Date: Mon, 13 Oct 2025 12:41:03 +0300 Subject: [PATCH 3/4] Change paint count behavior from fetching info to predict system --- Extension/scripts/Auto-Image.js | 349 +++++++++++++++++++------------ Extension/scripts/Auto-Repair.js | 5 +- 2 files changed, 220 insertions(+), 134 deletions(-) diff --git a/Extension/scripts/Auto-Image.js b/Extension/scripts/Auto-Image.js index 8df37c5..b18efd6 100644 --- a/Extension/scripts/Auto-Image.js +++ b/Extension/scripts/Auto-Image.js @@ -10,36 +10,6 @@ // ==/UserScript== localStorage.removeItem("lp"); -// Fallback translation function for when utils manager isn't loaded -function getText(key, params) { - // Try to get translation from loadedTranslations - try { - if (window.loadedTranslations && window.loadedTranslations[key]) { - let text = window.loadedTranslations[key]; - if (params) { - Object.keys(params).forEach(paramKey => { - text = text.replace(new RegExp(`{{${paramKey}}}`, 'g'), params[paramKey]); - }); - } - return text; - } - - // Try with state.language if available - if (window.state && window.state.language && window.loadedTranslations && window.loadedTranslations[window.state.language] && window.loadedTranslations[window.state.language][key]) { - let text = window.loadedTranslations[window.state.language][key]; - if (params) { - Object.keys(params).forEach(paramKey => { - text = text.replace(new RegExp(`{{${paramKey}}}`, 'g'), params[paramKey]); - }); - } - return text; - } - } catch (error) { - console.warn('Error in getText fallback:', error); - } - - return key; // Fallback to key if no translation found -} ; (async () => { // Prevent multiple instances of this script from running @@ -952,6 +922,94 @@ function getText(key, params) { // Create global account manager instance const accountManager = new AccountManager(); + // Local Charge Model to minimize API calls and drive account switching + const ChargeModel = (() => { + class Model { + constructor() { + this.map = new Map(); // token -> {charges,max,lastTickAt,lastSyncAt} + this.tickIntervalMs = 30_000; // +1 charge per 30s + this.timer = null; + this.startedAt = Date.now(); + } + seedFromAccounts(accounts) { + const now = Date.now(); + (accounts || []).forEach(acc => { + if (!acc || !acc.token) return; + const existing = this.map.get(acc.token) || {}; + const charges = Number.isFinite(acc.Charges) ? Math.floor(acc.Charges) : (existing.charges || 0); + const max = Number.isFinite(acc.Max) ? Math.floor(acc.Max) : (existing.max || 1); + this.map.set(acc.token, { + charges: Math.max(0, Math.min(charges, max)), + max: Math.max(1, max), + lastTickAt: existing.lastTickAt || now, + lastSyncAt: existing.lastSyncAt || now, + }); + }); + } + ensureToken(token) { + if (!token) return null; + if (!this.map.has(token)) { + this.map.set(token, { charges: 0, max: Math.max(1, state.maxCharges || 1), lastTickAt: Date.now(), lastSyncAt: 0 }); + } + return this.map.get(token); + } + get(token) { return this.ensureToken(token); } + getForCurrent() { return this.get(accountManager.getCurrentAccount()?.token); } + setFromServer(token, charges, max) { + const node = this.ensureToken(token); + if (!node) return; + node.charges = Math.max(0, Math.min(Math.floor(charges || 0), Math.max(1, Math.floor(max || node.max || 1)))); + node.max = Math.max(1, Math.floor(max || node.max || 1)); + node.lastSyncAt = Date.now(); + } + decrement(token, amount) { + const node = this.ensureToken(token); + if (!node) return 0; + const n = Math.max(0, Math.floor(amount || 0)); + node.charges = Math.max(0, node.charges - n); + return node.charges; + } + incrementTickAll() { + const now = Date.now(); + accountManager.getAllAccounts().forEach(acc => { + if (!acc?.token) return; + const node = this.ensureToken(acc.token); + if (!node) return; + // catch-up ticks if tab was inactive + const elapsed = now - (node.lastTickAt || now); + const ticks = Math.floor(elapsed / this.tickIntervalMs); + if (ticks > 0) { + node.charges = Math.min(node.max, node.charges + ticks); + node.lastTickAt = (node.lastTickAt || now) + ticks * this.tickIntervalMs; + } + }); + // Mirror values into AccountManager and UI state + this.syncToAccountManager(); + } + start() { + if (this.timer) return; + this.timer = setInterval(() => this.incrementTickAll(), this.tickIntervalMs); + } + stop() { if (this.timer) { clearInterval(this.timer); this.timer = null; } } + predictTimeToReach(token, target) { + const node = this.get(token); + if (!node) return Infinity; + if (node.charges >= target) return 0; + return (target - node.charges) * this.tickIntervalMs; + } + syncToAccountManager() { + const list = accountManager.getAllAccounts(); + list.forEach(acc => { + const node = this.map.get(acc.token); + if (!node) return; + accountManager.updateAccountData(acc.token, { Charges: node.charges, Max: node.max }); + }); + renderAccountsList(); + } + } + return new Model(); + })(); + // GLOBAL STATE const state = { running: false, @@ -1017,6 +1075,10 @@ function getText(key, params) { notificationIntervalMinutes: CONFIG.NOTIFICATIONS.REPEAT_MINUTES, _lastChargesNotifyAt: 0, _lastChargesBelow: true, + // Switch debouncing state + lastSwitchAt: 0, + paintedSinceSwitch: 0, + minMsBetweenSwitches: 3000, // Smart save tracking _lastSavePixelCount: 0, _lastSaveTime: 0, @@ -8503,9 +8565,20 @@ function getText(key, params) { state.lastPaintedPosition = { x: lastPixel.localX, y: lastPixel.localY }; } + // Track painted pixels since last account switch to avoid flip-flop + state.paintedSinceSwitch = (state.paintedSinceSwitch || 0) + actuallyPaintedCount; + // IMPORTANT: Decrement charges locally to match Acc-Switch.js behavior state.displayCharges = Math.max(0, state.displayCharges - batchSize); state.preciseCurrentCharges = Math.max(0, state.preciseCurrentCharges - batchSize); + // Also update the global local charge model per account with bonus logic + try { + const tok = accountManager.getCurrentAccount()?.token; + const after = ChargeModel.decrement(tok, batchSize); + state.displayCharges = Math.floor(after); + state.preciseCurrentCharges = after; + if (tok) accountManager.updateAccountData(tok, { Charges: state.displayCharges }); + } catch {} state.fullChargeData = { ...state.fullChargeData, @@ -8671,13 +8744,23 @@ function getText(key, params) { // IMPORTANT: Check charges once at start, then paint until depleted console.log('🔋 Checking initial charges for painting session'); - const initialChargeCheck = await WPlaceService.getCharges(); - state.displayCharges = Math.floor(initialChargeCheck.charges); - state.preciseCurrentCharges = initialChargeCheck.charges; - state.cooldown = initialChargeCheck.cooldown; + // Use local charge model to avoid extra API calls + const currentToken = accountManager.getCurrentAccount()?.token; + let node = ChargeModel.get(currentToken); + // One-time sync for current account if never synced (safety) + if (node && !node.lastSyncAt) { + try { + const sync = await WPlaceService.getCharges(); + ChargeModel.setFromServer(currentToken, sync.charges, sync.max); + node = ChargeModel.get(currentToken); + } catch {} + } + state.displayCharges = Math.floor(node?.charges || 0); + state.preciseCurrentCharges = node?.charges || 0; + state.cooldown = CONFIG.COOLDOWN_DEFAULT; await updateStats(); if (state.displayCharges <= 0) { - console.log('⚡ No charges available, skipping painting session'); + console.log('⚡ No charges available (local), skipping painting session'); return 'charges_depleted'; } @@ -9030,55 +9113,38 @@ function getText(key, params) { // const maxChargeChecks = 10; // REMOVED: No limit on API calls during cooldown while (!state.stopFlag) { - chargeCheckCount++; + const threshold = Math.max(1, state.cooldownChargeThreshold || 1); + const accounts = accountManager.getAllAccounts(); + let anyReady = false; + let bestMs = Infinity; + let currentCharges = ChargeModel.getForCurrent()?.charges || 0; - const { charges, cooldown } = await WPlaceService.getCharges(); - state.displayCharges = Math.floor(charges); - state.preciseCurrentCharges = charges; - state.cooldown = cooldown; + for (const acc of accounts) { + const node = ChargeModel.get(acc.token); + if (!node) continue; + if (node.charges >= threshold) { + anyReady = true; + break; + } + const ms = ChargeModel.predictTimeToReach(acc.token, threshold); + if (ms < bestMs) bestMs = ms; + } - if (state.displayCharges >= state.cooldownChargeThreshold) { - console.log(`✅ Cooldown target reached: ${state.displayCharges}/${state.cooldownChargeThreshold}`); + if (anyReady) { + console.log(`✅ Cooldown target reached locally (≥${threshold})`); NotificationManager.maybeNotifyChargesReached(true); await updateStats(); return 'target_reached'; } + const waitMs = Number.isFinite(bestMs) ? Math.max(1000, Math.min(bestMs, 10000)) : 10000; updateUI('noChargesThreshold', 'warning', { - time: Utils.msToTimeText(state.cooldown), - threshold: state.cooldownChargeThreshold, - current: state.displayCharges, + time: Utils.msToTimeText(waitMs), + threshold, + current: currentCharges, }); await updateStats(); - - // Smart delay calculation to reduce API calls - const chargesNeeded = state.cooldownChargeThreshold - state.displayCharges; - const estimatedWaitTime = chargesNeeded * state.cooldown; - - // Use longer delays during cooldown to prevent rate limiting - let delayTime; - if (chargeCheckCount < 3) { - // First few checks - shorter delay - delayTime = Math.max(3000, state.cooldown); // 3 seconds minimum - } else if (estimatedWaitTime > 60000) { - // Long wait expected - check every 15 seconds - delayTime = 10000; - } else if (estimatedWaitTime > 30000) { - // Medium wait - check every 15 seconds - delayTime = 15000; - } else { - // Close to target - check every 5 seconds - delayTime = 5000; - } - - console.log(`⏱️ Cooldown check ${chargeCheckCount}: ${state.displayCharges}/${state.cooldownChargeThreshold} charges, waiting 10s before next check`); - await Utils.sleep(10000); - - // REMOVED: No limit on charge checks - bot will wait infinitely until charges are available - // if (chargeCheckCount >= maxChargeChecks) { - // console.warn('⚠️ Max charge checks reached during cooldown, continuing anyway'); - // break; - // } + await Utils.sleep(waitMs); } return 'stopped'; @@ -9847,9 +9913,10 @@ function getText(key, params) { console.log('✅ Found wasm Module...'); return url.split('/').pop(); } - } catch { } + } catch (e) { /* ignore individual fetch errors */ } } - console.error(`❌ Could not find Pawtect chunk: `, error); + console.error('❌ Could not find Pawtect chunk among preloaded modules'); + return null; } async function purchase(type) { @@ -9993,12 +10060,6 @@ function getText(key, params) { }); } - async function fetchAccount() { - const { ID, Charges, Max, Droplets } = await WPlaceService.fetchCheck(); - console.log("User's ID :", ID); - console.log("User's Charges :", Charges, "/", Max); - console.log("User's Droplets :", Droplets); - } async function fetchAllAccountDetails() { if (state.isFetchingAllAccounts) { @@ -10109,6 +10170,7 @@ function getText(key, params) { } console.log(`🎯 [FETCH] Completed fetching fresh data for all accounts`); + try { ChargeModel.seedFromAccounts(accountManager.getAllAccounts()); } catch {} } // Render the accounts list with fresh data @@ -10131,34 +10193,18 @@ function getText(key, params) { // Function to update current account charges in the account list async function updateCurrentAccountInList() { if (accountManager.getAccountCount() === 0) return; - try { - // Always trust backend /me and then map by ID to avoid mixing data between tokens - const currentAccountData = await WPlaceService.getCharges(); - state.displayCharges = Math.floor(currentAccountData.charges); - state.preciseCurrentCharges = currentAccountData.charges; + const current = accountManager.getCurrentAccount(); + const node = ChargeModel.get(current?.token); + if (!current || !node) return; + state.displayCharges = Math.floor(node.charges || 0); + state.preciseCurrentCharges = node.charges || 0; await updateStats(); - - const accounts = accountManager.getAllAccounts(); - const idx = accounts.findIndex(acc => acc.ID === currentAccountData.id); - const targetToken = idx !== -1 ? accounts[idx].token : accountManager.getCurrentAccount()?.token; - - if (targetToken) { - accountManager.updateAccountData(targetToken, { - Charges: Math.floor(state.displayCharges || 0), - Max: Math.floor(currentAccountData.max || state.maxCharges || 0), - Droplets: Math.floor(currentAccountData.droplets) - }); - - // Keep manager index in sync with reality when possible - if (idx !== -1 && typeof accountManager.setCurrentIndex === 'function') { - accountManager.setCurrentIndex(idx); - state.accountIndex = idx; - } - - // Re-render the account list to show updated charges - renderAccountsList(); - } + accountManager.updateAccountData(current.token, { + Charges: Math.floor(node.charges || 0), + Max: Math.floor(node.max || current.Max || 0) + }); + renderAccountsList(); } catch (e) { console.warn('⚠️ updateCurrentAccountInList failed:', e); } @@ -10321,6 +10367,18 @@ function getText(key, params) { async function switchToNextAccount(accounts) { console.log(`🔄 [SWITCH] Starting account switch`); + // Debounce rapid consecutive switches when no painting happened + try { + const now = Date.now(); + const last = state.lastSwitchAt || 0; + const minGap = state.minMsBetweenSwitches || 3000; + const painted = state.paintedSinceSwitch || 0; + if (now - last < minGap && painted === 0) { + console.log(`⏳ [SWITCH] Debounced rapid switch (Δ${now - last}ms < ${minGap}ms and paintedSinceSwitch=${painted}).`); + return false; + } + } catch {} + // Validate we have accounts if (accountManager.getAccountCount() === 0) { console.error('❌ No accounts available for switching'); @@ -10401,6 +10459,10 @@ function getText(key, params) { // Update the account status and UI after successful switch await updateCurrentAccountInList(); + // Record switch time and reset painted counter to prevent rapid bouncing + state.lastSwitchAt = Date.now(); + state.paintedSinceSwitch = 0; + return true; } catch (error) { console.error('❌ [SWITCH] Account switch failed:', error); @@ -10411,6 +10473,19 @@ function getText(key, params) { // SIMPLIFIED helper function for specific account switching async function switchToSpecificAccount(token, accountName) { console.log(`🔄 [SPECIFIC SWITCH] Attempting to switch to account: ${accountName}`); + + // Debounce rapid consecutive switches when no painting happened + try { + const now = Date.now(); + const last = state.lastSwitchAt || 0; + const minGap = state.minMsBetweenSwitches || 3000; + const painted = state.paintedSinceSwitch || 0; + if (now - last < minGap && painted === 0) { + console.log(`⏳ [SPECIFIC SWITCH] Debounced rapid switch (Δ${now - last}ms < ${minGap}ms and paintedSinceSwitch=${painted}).`); + return false; + } + } catch {} + if (!token) { console.error('❌ [SPECIFIC SWITCH] Missing token'); return false; @@ -10471,6 +10546,7 @@ function getText(key, params) { // Fetch fresh stats for UI/state const { charges, cooldown, droplets, max } = await WPlaceService.getCharges(); + try { ChargeModel.setFromServer(token, charges, max); } catch {} state.displayCharges = Math.floor(charges); state.preciseCurrentCharges = charges; state.cooldown = cooldown; @@ -10530,42 +10606,43 @@ function getText(key, params) { try { const total = accountManager.getAccountCount(); if (total <= 1) return false; + const threshold = Math.max(1, minRequired || 1); const startIdx = accountManager.currentIndex; - let best = { cooldown: Infinity, token: null, name: null, idx: -1 }; + let candidate = null; // {token,name,idx} + let bestWait = Infinity; // ms to reach threshold for (let step = 1; step <= total - 1; step++) { const idx = (startIdx + step) % total; const acc = accountManager.getAccountByIndex(idx); if (!acc || !acc.token) continue; + const node = ChargeModel.get(acc.token); + const localCharges = Math.floor(node?.charges || 0); - console.log(`🔄 [SEARCH] Switching temporarily to ${acc.displayName} (${idx + 1}/${total}) to check charges...`); - const ok = await switchToSpecificAccount(acc.token, acc.displayName); - if (!ok) { - console.warn(`⚠️ [SEARCH] Failed to switch to ${acc.displayName}, trying next...`); - continue; - } - - const currentAccountData = await WPlaceService.getCharges(); - const charges = Math.floor(currentAccountData?.charges || 0); - const cooldown = Math.max(0, Number(currentAccountData?.cooldown || 0)); - if (charges >= minRequired) { - console.log(`✅ [SEARCH] Found account with sufficient charges: ${acc.displayName} (⚡${charges})`); - return true; - } - - console.log(`⏳ [SEARCH] ${acc.displayName} has no charges (⚡${charges}), cooldown ${cooldown}ms`); - if (cooldown < best.cooldown) { - best = { cooldown, token: acc.token, name: acc.displayName, idx }; + console.log(`🔍 [SEARCH] Checking locally ${acc.displayName}: ⚡${localCharges}/${node?.max ?? 0}`); + if (localCharges >= threshold) { + candidate = { token: acc.token, name: acc.displayName, idx }; + break; + } else { + const eta = ChargeModel.predictTimeToReach(acc.token, threshold); + if (eta < bestWait) { + bestWait = eta; + candidate = { token: acc.token, name: acc.displayName, idx }; + } } } - // None had enough charges: switch to the one with the soonest recharge and return false - if (best.token && best.idx !== accountManager.currentIndex) { - console.log(`🎯 [SEARCH] Switching to account with soonest recharge: ${best.name} (~${Utils.msToTimeText(best.cooldown)})`); - await switchToSpecificAccount(best.token, best.name); + if (candidate && ChargeModel.get(candidate.token)?.charges >= threshold) { + console.log(`✅ [SEARCH] Local model found eligible account: ${candidate.name}`); + const ok = await switchToSpecificAccount(candidate.token, candidate.name); + return !!ok; + } + + // None eligible yet – do not switch now. Caller may enter cooldown. + if (candidate) { + console.log(`🕒 [SEARCH] No accounts meet threshold. Best candidate: ${candidate.name} in ~${Utils.msToTimeText(bestWait)}`); } else { - console.log('🎯 [SEARCH] Staying on current account for cooldown.'); + console.log('🕒 [SEARCH] No candidate accounts available.'); } return false; } catch (e) { @@ -10583,6 +10660,14 @@ function getText(key, params) { console.log('🔄 Initial account load from cache...'); try { await accountManager.loadAccounts(); + // Seed and start local charge model regardless of count + try { + state.chargeModel = ChargeModel; + ChargeModel.seedFromAccounts(accountManager.getAllAccounts()); + ChargeModel.start(); + console.log('⚡ Local ChargeModel started (tick +1 per 30s for all accounts)'); + } catch (e) { console.warn('ChargeModel init failed:', e); } + if (accountManager.getAccountCount() > 0) { console.log(`✅ Loaded ${accountManager.getAccountCount()} cached accounts`); renderAccountsList(); diff --git a/Extension/scripts/Auto-Repair.js b/Extension/scripts/Auto-Repair.js index 4f6abed..3942791 100644 --- a/Extension/scripts/Auto-Repair.js +++ b/Extension/scripts/Auto-Repair.js @@ -595,9 +595,10 @@ console.log('✅ Found wasm Module...'); return url.split('/').pop(); } - } catch { } + } catch (e) { /* ignore individual fetch errors */ } } - console.error(`❌ Could not find Pawtect chunk with string: ${str}`); + console.error('❌ Could not find Pawtect chunk among preloaded modules'); + return null; } // Audio notification system From 08acdfc66f1996b1b44e0af358981a98cd80fd94 Mon Sep 17 00:00:00 2001 From: JustEngineer Date: Mon, 13 Oct 2025 13:09:22 +0300 Subject: [PATCH 4/4] removed duplicate message listener --- Extension/background.js | 23 ----------------------- Extension/scripts/Auto-Image.js | 6 +++--- 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/Extension/background.js b/Extension/background.js index fe15f65..0217179 100644 --- a/Extension/background.js +++ b/Extension/background.js @@ -13,29 +13,6 @@ chrome.runtime.onInstalled.addListener(async () => { console.log('📦 Installation resource test:', resources); }); -chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { - if (request.action === 'executeScript') { - // Get tabId from sender or requests - const tabId = request.tabId || sender.tab?.id; - - if (!tabId) { - sendResponse({ success: false, error: 'Could not determine target tab' }); - return; - } - - // Use IIFE for async handlings - (async () => { - try { - await executeLocalScript(request.scriptName, tabId); - sendResponse({ success: true }); - } catch (error) { - sendResponse({ success: false, error: error.message }); - } - })(); - - return true; // Important: indicates async response - } -}); async function executeLocalScript(scriptName, tabId) { try { diff --git a/Extension/scripts/Auto-Image.js b/Extension/scripts/Auto-Image.js index b18efd6..93d5040 100644 --- a/Extension/scripts/Auto-Image.js +++ b/Extension/scripts/Auto-Image.js @@ -4410,7 +4410,7 @@ localStorage.removeItem("lp"); const timeText = Utils.msToTimeText(remainingMs); if (currentChargesEl) { - currentChargesEl.innerHTML = `${state.displayCharges} / ${state.maxCharges}`; + currentChargesEl.innerHTML = `${state.displayCharges} / ${max}`; } if ( @@ -4608,7 +4608,7 @@ localStorage.removeItem("lp"); totalMaxCharges = accounts.reduce((sum, acc) => { if (currentAccount && acc.token === currentAccount.token) { // Use real-time max charges for current account - return sum + Math.floor(state.maxCharges || acc.Max || 0); + return sum + Math.floor((state.fullChargeData?.max ?? state.maxCharges ?? acc.Max ?? 0)); } else { // Use stored data for other accounts return sum + Math.floor(acc.Max || 0); @@ -4633,7 +4633,7 @@ localStorage.removeItem("lp"); ${Utils.t('charges')}
- ${state.displayCharges} / ${state.maxCharges} + ${state.displayCharges} / ${state.fullChargeData?.max ?? state.maxCharges}