Added
- AliExpress bot-flag guard – new config vars
AE_MIN_COINS,AE_FLAG_RETRIES,AE_FLAG_WAIT(default 2, 3, 480s). If check-in offers only 1 coin, bot skips collection and retries instead of wasting the full reward, then notifies you to collect on your phone if it never lifts. - Anti-bot diagnostics in logs –
🔎 Anti-bot diagnosticsline reports actualnavigator.webdriver, automation property leaks, AliExpress risk cookies, and challenge detection;🚧 Blocked app schemesline lists intercepted attempts for troubleshooting. - Per-store notification toggle (
NOTIFY_SKIP_STORES) – silence Discord/Apprise notifications from specific stores while they still run and claim, via a comma-separated denylist of store keys (accepts aliasesae/amazon/gp) — e.g.NOTIFY_SKIP_STORES=aliexpressstops the daily AliExpress summary. Store notifications now route throughBaseClaimer.notify()/cfg.store_notify_enabled(), andmain.pyfilters the summary and crash alerts accordingly.
Fixed
- Captchas suddenly appearing on every store – enabling the
PageCDP domain (needed soaddScriptToEvaluateOnNewDocumentisn't silently ignored) made the old hand-rolled desktop stealth JS actually run for the first time, and its HARD-CODED values (Win32platform,NVIDIA GTX 1650WebGL, fake plugins) don't match the real headful/VNC container (no NVIDIA GPU, Linux) — that inconsistency is a bot tell and started triggering captchas across Steam, Epic, GOG and Prime at once.BaseClaimer.inject_base_stealthnow defaults toFalse, so those stores use nodriver's clean native fingerprint again (verified live: WebGL reports the real renderer,navigator.webdriver === false). - Cloudflare / captcha challenges never sent an alert – a human-check (Cloudflare "Just a moment… / Verify you are human", or an hCaptcha/Arkose login challenge) was either only logged or silently treated as "no games"/"not signed in", with no notification. New shared
BaseClaimer._human_challenge_present()detects them and_wait_out_challenge()first lets a managed challenge auto-pass, then sends a Discord/Apprise push with the VNC link and waits for you to solve it.epic.pychecks for it up front (Cloudflare can gatestore.epicgames.combefore login — otherwise it just looped "attempt 1/3") and again during login;steam.pychecks it on the SteamDB page instead of silently reporting no free games. - Navigator property spoofs threw mid-injection – missing
configurable: trueon base stealth properties caused per-store overrides to throw and abort. All navigator spoofs insrc/core/claimer.pynow useconfigurable: trueso per-store overrides can layer safely. navigator.webdriverspoofed asundefined– real Chrome never reportsundefined, alwaysfalse. Now only patches when it's genuinelytrue, spoofingfalseinstead.- AliExpress login form not detected in non-English locales – the email/phone field (localized placeholder, plain
type=text) and theKontynuuj/Continuesubmit button are now found via locale-agnostic selectors and submitted with a trusted click on the real button element plus an Enter keypress, fixing automated login silently stalling. - AliExpress reported a false "verification required" after a successful login – a successful sign-in redirects to the store homepage (e.g.
pl.aliexpress.com/?gatewayAdapt=glo2pol), which has none of the coin-page markers_is_logged_in()looks for, so the bot wrongly fired a VNC "enter your 6-digit code" alert while actually logged in._is_logged_in()now also recognizes the signed-in store homepage (account/sign-out menu), and_ensure_logged_in()accepts being redirected off the login page onto the aliexpress.com store as success (_left_login_for_store(), mirroring the upstreamwaitForURLcheck). - AliExpress check-in silently reported success on unrendered pages or failed clicks – previously (
v1.3),_verify_check_in()defaulted its status to"checked in / active"before checking for buttons. When the check-in widget failed to render or noCollectbutton was found, the bot silently logged success and sent false notifications (checked in / active), masking missed check-ins and breaking day-streaks. Now, if the widget doesn't render after retries or a collect click cannot be confirmed,aliexpress.pylogs an error, saves failure diagnostics (data/ae_checkin_fail.htmland screenshot), offers manual collection via VNC, and honestly reports failure (⚠️ NOT collected — widget did not render) if uncollected. - Chrome app-scheme confirmation dialogs still appeared –
xdg-openstub only made launches harmless after clicking the dialog. Added ChromeAutoLaunchProtocolsFromOriginspolicy inDockerfileso schemes (aliexpress://,alipay://, etc.) auto-launch without prompting. Extended DOM-blocking JS to cover all vectors (window.open, injected iframes, pre-existing links). - Scheduler crashed when
SCHEDULER_HOURS >= 24(#22) –main.pypreviously passedSCHEDULER_HOURSinto a cron expression (CronTrigger(hour=f"*/{cfg.scheduler_hours}")), causing a crash (ValueError: Error validating expression '*/24': the step value is higher than the total range) when set to 24 hours or more. ReplacedCronTriggerwith APScheduler'sIntervalTrigger(hours=cfg.scheduler_hours)soSCHEDULER_HOURSnow cleanly supports any positive interval (e.g.1,12,24,48,72hours) without range restrictions. - Epic 2FA code screen refreshed in a loop so codes couldn't be entered (#21) –
epic.pyonly auto-handled the authenticator (TOTP) method viaEG_OTPKEY; for email/SMS codes the automated login loop kept re-navigating and re-typing email/password, wiping the code screen every attempt. It now detects the MFA screen (input[name="code-input-0"]/ the/id/login/mfaURL — the same field for email, SMS and authenticator), auto-fills TOTP whenEG_OTPKEYis set, and otherwise STOPS re-driving the page and waits on the code screen with a Discord/Apprise "enter your 2FA code" prompt so you can type it via VNC (a Cloudflare/Talon "One more step" check can appear on the same screen and is included in the prompt). New_mfa_prompt_present()/_fill_totp()helpers. - Amazon Luna / Prime Gaming login clicked the wrong "Sign in with Passkey" button (#13) – login looped ("attempt N/5", "Session lost", "No passkeys for this account") because
_ensure_logged_in()clicked the sign-in button via a fuzzypage.find("Sign in")text search, which also matches "Sign in with a passkey"; and the passkey neutralization only disabled the WebAuthn API without removing Amazon's rendered passkey form.prime.pynow clicks Luna's exactbutton[data-a-target="sign-in-button"], and its injected script strips Amazon'ssignInWithPasskeyButton/signInWithMShopButtonforms so only the password form (form[name="signIn"]→#ap_password+#signInSubmit) can be used. If a passkey error still appears (#passkey-error-alert), the bot stops looping and asks you to finish login via VNC with a notification. - "Failed to connect to browser" after days of running (#19) – every store eventually failed to launch Chrome. Root cause:
close_browser()only ran nodriver'sstop(), which terminates the parent Chrome but leaves its child processes (zygote/renderer/GPU) alive; and a faileduc.start()raises before returning a handle, so the Chrome it already spawned is orphaned and keeps the profile lock. These pile up over scheduled runs until no new browser can start.src/core/claimer.pynow kills the whole Chrome process tree on close (viapsutil), retriesuc.start()up to 3× while sweeping any orphaned Chrome bound to that store's profile and clearing staleSingleton*lock files between attempts, and raises a clear error if it still can't start. No profile/session data is touched, so store logins in the volume are preserved. - Docker build hangs on slow/stuck mirrors – added IPv4 forcing and timeouts to apt configuration so stuck downloads retry instead of hanging indefinitely.
Changed
- AliExpress stealth switched to a real-device fingerprint (
browserforge) – replaced the hand-written UA/WebGL/navigator spoofs (incomplete and internally inconsistent — the very thing Alibaba's risk engine detects) with a COMPLETE Android-phone fingerprint sampled from real devices (UA,Sec-CH-UAclient-hints, screen, navigator, WebGL, codecs), injected as one coherent unit via CDP and cached per profile (fgc_fingerprint.json) so the bot presents the SAME phone every day. Mirrors the proven upstream stealth stack. - AliExpress coin balance now read from the API, not the DOM – the coin page shows the balance only as rotating digit animations, so
aliexpress.pycaptures themtop.aliexpress.coin.executeresponse (via an in-pagefetch/XHRinterceptor intowindow.__fgcCoin, since the CDP network handlers didn't fire) and parsesuserCoinsNumfrom it. - Richer AliExpress check-in notification – after a successful check-in the notification now shows how many coins were collected and the wallet total, e.g.
claimed 70 🪙 (665 total)(day-streak and tomorrow's coints are planned) - Unified VNC "manual action needed" notifications with one-click links – alerts that ask you to act via VNC (login, 2FA/security codes, captcha, Steam Guard, manual coin collection) were worded inconsistently and the link never auto-connected. A single
cfg.vnc_urlnow buildshttp://<VNC_IP>:<NOVNC_PORT>/?autoconnect=true(opens the noVNC session directly), and a sharedBaseClaimer._vnc_notice(title, body)formats every message the same way. All stores (aliexpress,epic,prime,gog,steam) and the base captcha/login helpers use them; the Steam Guard notification now includes the link too. - Unified + hardened Prime/Luna logged-in detection – the "are we signed in?" check in
prime.pywas a single fragile selector (user-dropdown-first-name-text), duplicated by a separateSign in/Try Primeheuristic on game detail pages. A new shared_is_signed_in()now corroborates several account-header signals (amazon-dropdown-header-interactable/amazon-dropdown-header-message) with asign-in-buttonnegative guard, so a single Amazon attribute rename no longer breaks login into an endless loop; the detail-page session-loss watchdog uses the same method. - Desktop base stealth is now opt-in –
BaseClaimer.inject_base_stealthdefaults toFalse; nodriver's native stealth is used unless a store explicitly opts in. This is what fixes the cross-store captcha regression above (see Fixed). AliExpress keeps itFalseand injects its own coherent browserforge fingerprint. - Dockerfile hardening – expanded app-scheme blocklists in Chrome preferences and CDP calls to cover the full AliExpress/Alibaba set.
- Repository & Docker context exclusions (
.dockerignore/.gitignore) – updated.dockerignoreand.gitignoreto exclude AI assistant directories (.gemini/,.claude/,.cursor/), IDE configs, logs, andTEMP_*reference dumps (e.g.TEMP_ORIGINAL_PROJECT/), preventing ~60 MB of local/temporary files from bloating the Docker build context or being accidentally committed. - Documented previously-undocumented settings – added
EMAIL/PASSWORD(global default credentials),VNC_PASSWORD,TIMEOUT,SCREENSHOTS_DIRandNOTIFY_SKIP_STORESto the README config table and.env.example, and aligned the.env.exampleWIDTHexample with the1280default. - Quieter Apprise logging – the app's
Apprise notification sent.line is nowdebug(the apprise library already logs each target at INFO, e.g.Sent ntfy notification to …), so a single successful send no longer looks duplicated.
Removed
- Unused
LOGIN_TIMEOUTconfig – thelogin_timeoutfield insrc/core/config.pywas defined but never read anywhere in the code (distinct from the activeVNC_LOGIN_TIMEOUT); removed.