diff --git a/docs/getting-started.md b/docs/getting-started.md index 2eb9a1e..43bf182 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -1399,13 +1399,47 @@ Features: ### "Browser launch failed" -**Problem**: Chromium not installed +**Problem**: Chromium not installed or missing system dependencies **Solution**: + +**Windows/Mac:** ```bash npx playwright install chromium ``` +**Linux (Ubuntu/Debian):** +```bash +# Install Chromium + system dependencies +npx playwright install-deps chromium +npx playwright install chromium + +# Alternative manual installation: +sudo apt-get install -y \ + libnss3 \ + libnspr4 \ + libatk1.0-0 \ + libatk-bridge2.0-0 \ + libcups2 \ + libdrm2 \ + libxkbcommon0 \ + libxcomposite1 \ + libxdamage1 \ + libxfixes3 \ + libxrandr2 \ + libgbm1 \ + libasound2 +``` + +**Linux (Other distributions):** +```bash +# Red Hat/CentOS/Fedora +sudo yum install -y atk cups-libs libXdamage libXrandr libgbm alsa-lib + +# Arch +sudo pacman -S nss atk cups libdrm libxkbcommon libxcomposite libxdamage libxfixes libxrandr alsa-lib +``` + ### "Module not found" errors **Problem**: Dependencies not installed diff --git a/src/account-creation/AccountCreator.ts b/src/account-creation/AccountCreator.ts index 6cc707b..902c8ea 100644 --- a/src/account-creation/AccountCreator.ts +++ b/src/account-creation/AccountCreator.ts @@ -791,6 +791,13 @@ export class AccountCreator { private async navigateToSignup(): Promise { if (this.referralUrl) { log(false, 'CREATOR', '🔗 Navigating to referral link...', 'log', 'cyan') + + // CRITICAL: Verify &new=1 parameter is present + if (!this.referralUrl.includes('new=1')) { + log(false, 'CREATOR', '⚠️ Warning: Referral URL missing &new=1 parameter', 'warn', 'yellow') + log(false, 'CREATOR', ' Referral linking may not work correctly', 'warn', 'yellow') + } + await this.page.goto(this.referralUrl, { waitUntil: 'networkidle', timeout: 60000 }) await this.waitForPageStable('REFERRAL_PAGE', 10000) diff --git a/src/account-creation/cli.ts b/src/account-creation/cli.ts index 4ee3087..8947846 100644 --- a/src/account-creation/cli.ts +++ b/src/account-creation/cli.ts @@ -30,15 +30,19 @@ async function main(): Promise { } } - // AUTO-FIX: Clean up URL if it contains & parameters that might cause issues - // Only keep the part up to the first & to ensure compatibility even without quotes - if (referralUrl && referralUrl.includes('&')) { - const originalUrl = referralUrl - referralUrl = referralUrl.split('&')[0] // Keep only base URL + first parameter (rh=CODE) - log(false, 'CREATOR-CLI', '� Auto-cleaned URL (removed optional tracking parameters)', 'log', 'gray') - log(false, 'CREATOR-CLI', ` Original: ${originalUrl}`, 'log', 'gray') - log(false, 'CREATOR-CLI', ` Using: ${referralUrl}`, 'log', 'cyan') - log(false, 'CREATOR-CLI', '', 'log') + // AUTO-FIX: Ensure referral URL has &new=1 parameter (REQUIRED for referral to work) + if (referralUrl) { + // Remove any existing &new=1 to avoid duplication + referralUrl = referralUrl.replace(/&new=1/g, '') + + // Add &new=1 at the end (CRITICAL for referral linking) + if (!referralUrl.includes('?')) { + referralUrl += '?new=1' + } else { + referralUrl += '&new=1' + } + + log(false, 'CREATOR-CLI', '✅ Referral URL configured with &new=1 parameter', 'log', 'green') } // Banner diff --git a/src/browser/BrowserFunc.ts b/src/browser/BrowserFunc.ts index 0cf4818..afab3b5 100644 --- a/src/browser/BrowserFunc.ts +++ b/src/browser/BrowserFunc.ts @@ -144,29 +144,41 @@ export default class BrowserFunc { throw new Error('Account has been suspended!') } - // IMPROVED: Diagnostic logging to identify DOM structure changes + // IMPROVED: Enhanced diagnostic logging to identify DOM structure changes if (iteration <= 2) { try { const diagnosticInfo = await page.evaluate(() => { const elementsWithActivitiesId = document.querySelectorAll('[id*="activit"]') const meeCardGroups = document.querySelectorAll('mee-card-group') const hasRoleList = document.querySelectorAll('[role="list"]') + const dailySets = document.querySelectorAll('.daily-sets, [data-bi-name="daily-set"]') + const rewardsElements = document.querySelectorAll('[class*="rewards"], [id*="rewards"]') + const mainContent = document.querySelector('main') return { activitiesIdCount: elementsWithActivitiesId.length, activitiesIds: Array.from(elementsWithActivitiesId).map(el => el.id).slice(0, 5), meeCardGroupCount: meeCardGroups.length, roleListCount: hasRoleList.length, + dailySetsCount: dailySets.length, + rewardsElementsCount: rewardsElements.length, + hasMainContent: !!mainContent, pageTitle: document.title, - bodyClasses: document.body.className + bodyClasses: document.body.className, + url: window.location.href } }) this.bot.log(this.bot.isMobile, 'GO-HOME-DEBUG', - `DOM Diagnostic - Elements with 'activit': ${diagnosticInfo.activitiesIdCount}, ` + - `IDs: [${diagnosticInfo.activitiesIds.join(', ')}], ` + + `DOM Diagnostic - ` + + `URL: ${diagnosticInfo.url}, ` + + `Title: "${diagnosticInfo.pageTitle}", ` + + `Elements with 'activit': ${diagnosticInfo.activitiesIdCount} [${diagnosticInfo.activitiesIds.join(', ')}], ` + `mee-card-group: ${diagnosticInfo.meeCardGroupCount}, ` + - `role=list: ${diagnosticInfo.roleListCount}`, 'warn') + `role=list: ${diagnosticInfo.roleListCount}, ` + + `daily-sets: ${diagnosticInfo.dailySetsCount}, ` + + `rewards elements: ${diagnosticInfo.rewardsElementsCount}, ` + + `main content: ${diagnosticInfo.hasMainContent}`, 'warn') } catch (error) { this.bot.log(this.bot.isMobile, 'GO-HOME-DEBUG', `Diagnostic failed: ${error}`, 'warn') } @@ -217,7 +229,24 @@ export default class BrowserFunc { this.bot.log(this.bot.isMobile, 'GO-HOME', 'On correct URL but activities missing - forcing page reload to trigger DOM render', 'warn') try { - await page.reload({ waitUntil: 'domcontentloaded', timeout: 15000 }) + // IMPROVED: Try alternative reload strategies based on iteration + if (iteration === 1) { + // First attempt: Simple reload + await page.reload({ waitUntil: 'domcontentloaded', timeout: 15000 }) + } else if (iteration === 2) { + // Second attempt: Navigate to full dashboard URL (not just base) + this.bot.log(this.bot.isMobile, 'GO-HOME', 'Trying full dashboard URL: /rewards/dashboard', 'log') + await page.goto(`${this.bot.config.baseURL}/rewards/dashboard`, { waitUntil: 'domcontentloaded', timeout: 15000 }) + } else if (iteration === 3) { + // Third attempt: Clear localStorage and reload + this.bot.log(this.bot.isMobile, 'GO-HOME', 'Clearing localStorage and reloading', 'log') + await page.evaluate(() => localStorage.clear()) + await page.reload({ waitUntil: 'domcontentloaded', timeout: 15000 }) + } else { + // Final attempts: Hard reload with cache bypass + await page.reload({ waitUntil: 'networkidle', timeout: 20000 }) + } + await waitForPageReady(page, { timeoutMs: 10000, logFn: (msg) => this.bot.log(this.bot.isMobile, 'GO-HOME', msg, 'log') diff --git a/src/constants.ts b/src/constants.ts index 8bed2e4..1032229 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -93,14 +93,19 @@ export const SELECTORS = { // FIXED: Use more specific selector to avoid strict mode violation (2 elements with id='more-activities') // Target the mee-card-group element specifically, not the div wrapper MORE_ACTIVITIES: 'mee-card-group#more-activities[role="list"]', - // IMPROVED: Fallback selectors for MORE_ACTIVITIES in case Microsoft changes structure + // IMPROVED: Expanded fallback selectors to handle Microsoft's frequent HTML structure changes MORE_ACTIVITIES_FALLBACKS: [ - '#more-activities', // ID only (most permissive) 'mee-card-group#more-activities', // Without role attribute + '#more-activities', // ID only (most permissive) '[id="more-activities"]', // Attribute selector - 'mee-card-group[role="list"]', // Element type with role + 'mee-card-group[role="list"]', // Element type with role (catches any list-type card group) + 'mee-card-group', // Ultra-permissive: any mee-card-group element '.daily-sets', // Class-based fallback - 'main[data-bi-name="dashboard"]' // Dashboard root element + '[data-bi-name="daily-set"]', // Data attribute fallback + 'main#daily-sets', // Main content area + 'main[data-bi-name="dashboard"]', // Dashboard root element + '.mee-card', // Individual card element + '[class*="rewards"]' // Any element with rewards in class name ], SUSPENDED_ACCOUNT: '#suspendedAccountHeader', QUIZ_COMPLETE: '#quizCompleteContainer',