From c66cc79e9000af811342d5a456c1ee9e5a4c0a7e Mon Sep 17 00:00:00 2001 From: type-two Date: Tue, 7 Jul 2026 18:42:11 +1000 Subject: [PATCH] =?UTF-8?q?fix:=20'unusual=20activity'=20=3D=20total=20fre?= =?UTF-8?q?eze=20=E2=80=94=2030/60/90=20min=20cease,=20refresh=20only=20on?= =?UTF-8?q?=20resume,=20flag=20outranks=20retries?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- content.js | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/content.js b/content.js index ba89cbd..202a154 100644 --- a/content.js +++ b/content.js @@ -26,8 +26,9 @@ let settings = { taskDelayMs: 20000, // base pause between tasks (jittered up to 2x) restEvery: 15, // after this many gens, take a longer rest restMs: 15 * 60 * 1000, // length of that scheduled rest - autoRefreshOnJam: true, // reload the tab on the abuse flag to clear a stuck session - cooldownUntil: 0 // epoch ms; set on rate-limit/rest, persists across reload + autoRefreshOnJam: true, // refresh WHEN RESUMING after the abuse flag (never during the freeze) + cooldownUntil: 0, // epoch ms; set on rate-limit/rest, persists across reload + reloadOnResume: false // set by the abuse flag: hard-refresh once the freeze ends, then resume }; let pollTimeout = null; @@ -281,6 +282,15 @@ function scheduleNext(immediate = false) { async function pollOnce() { if (!settings.isRunning) return; if (generationInProgress) return scheduleNext(); + if (settings.reloadOnResume) { + // Freeze is over — come back on a FRESH session before touching anything. + settings.reloadOnResume = false; + chrome.storage.local.set({ reloadOnResume: false }); + log('system', 'Abuse-flag freeze over — hard refreshing before resuming.'); + const r = await bg({ type: 'hardReload' }); + if (!r || !r.ok) location.reload(); + return; + } try { const res = await fetch(`${settings.serverUrl}/next-task`); if (res.status === 204) return scheduleNext(); // queue drained @@ -298,6 +308,7 @@ async function pollOnce() { // HARD refresh (cache bypass), not "Try again". Keep the task PENDING server-side, // count attempts in storage (survives the reload), and reload the tab. async function requeueWithReload(task, why) { + if (persistentError()) return handleRateLimit(task); // abuse flag outranks any retry — freeze, don't reload const key = 'requeue_' + task.id; const n = ((await new Promise(r => chrome.storage.local.get({ [key]: 0 }, r)))[key] || 0) + 1; if (n > 3) { @@ -404,14 +415,20 @@ function setCooldown(ms, why) { log('system', `${why} — pausing ${Math.round(ms / 60000)} min.`); } -// Hit the account abuse flag: keep the task PENDING (retry later), back off (growing with -// consecutive hits), and refresh the tab to clear the stuck session. +// Hit the account abuse flag ("unusual activity"). This is an ACTIVE account-level +// flag — worse than "Try again". Any activity while it's up (including reloads) +// feeds it, and it wears off on its own. So: report the task back as pending, +// then CEASE COMPLETELY for a solid 30 min (60/90 on repeat hits). The tab is +// hard-refreshed only when the freeze expires, right before resuming. async function handleRateLimit(task) { consecutiveRateLimits++; - const mins = Math.min(60, 15 * consecutiveRateLimits); // 15 → 30 → 45 → 60 - await reportCompletion(task.id, 'ratelimited', 'unusual activity — backing off', []); - setCooldown(mins * 60 * 1000, `⚠ Abuse flag ("unusual activity") ×${consecutiveRateLimits}`); - if (settings.autoRefreshOnJam) { await sleep(2500); location.reload(); } + const mins = Math.min(90, 30 * consecutiveRateLimits); // 30 → 60 → 90 + await reportCompletion(task.id, 'ratelimited', 'unusual activity — ceasing all activity', []); + if (settings.autoRefreshOnJam) { + settings.reloadOnResume = true; + chrome.storage.local.set({ reloadOnResume: true }); + } + setCooldown(mins * 60 * 1000, `⚠ Abuse flag ("unusual activity") ×${consecutiveRateLimits} — total freeze`); } function log(level, text) {