mirror of
https://github.com/LightZirconite/Microsoft-Rewards-Bot.git
synced 2026-01-10 01:06:17 +00:00
fix: Enhance referral URL handling and improve diagnostic logging for account creation
This commit is contained in:
@@ -1399,13 +1399,47 @@ Features:
|
|||||||
|
|
||||||
### "Browser launch failed"
|
### "Browser launch failed"
|
||||||
|
|
||||||
**Problem**: Chromium not installed
|
**Problem**: Chromium not installed or missing system dependencies
|
||||||
|
|
||||||
**Solution**:
|
**Solution**:
|
||||||
|
|
||||||
|
**Windows/Mac:**
|
||||||
```bash
|
```bash
|
||||||
npx playwright install chromium
|
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
|
### "Module not found" errors
|
||||||
|
|
||||||
**Problem**: Dependencies not installed
|
**Problem**: Dependencies not installed
|
||||||
|
|||||||
@@ -791,6 +791,13 @@ export class AccountCreator {
|
|||||||
private async navigateToSignup(): Promise<void> {
|
private async navigateToSignup(): Promise<void> {
|
||||||
if (this.referralUrl) {
|
if (this.referralUrl) {
|
||||||
log(false, 'CREATOR', '🔗 Navigating to referral link...', 'log', 'cyan')
|
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.page.goto(this.referralUrl, { waitUntil: 'networkidle', timeout: 60000 })
|
||||||
|
|
||||||
await this.waitForPageStable('REFERRAL_PAGE', 10000)
|
await this.waitForPageStable('REFERRAL_PAGE', 10000)
|
||||||
|
|||||||
@@ -30,15 +30,19 @@ async function main(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AUTO-FIX: Clean up URL if it contains & parameters that might cause issues
|
// AUTO-FIX: Ensure referral URL has &new=1 parameter (REQUIRED for referral to work)
|
||||||
// Only keep the part up to the first & to ensure compatibility even without quotes
|
if (referralUrl) {
|
||||||
if (referralUrl && referralUrl.includes('&')) {
|
// Remove any existing &new=1 to avoid duplication
|
||||||
const originalUrl = referralUrl
|
referralUrl = referralUrl.replace(/&new=1/g, '')
|
||||||
referralUrl = referralUrl.split('&')[0] // Keep only base URL + first parameter (rh=CODE)
|
|
||||||
log(false, 'CREATOR-CLI', '<27> Auto-cleaned URL (removed optional tracking parameters)', 'log', 'gray')
|
// Add &new=1 at the end (CRITICAL for referral linking)
|
||||||
log(false, 'CREATOR-CLI', ` Original: ${originalUrl}`, 'log', 'gray')
|
if (!referralUrl.includes('?')) {
|
||||||
log(false, 'CREATOR-CLI', ` Using: ${referralUrl}`, 'log', 'cyan')
|
referralUrl += '?new=1'
|
||||||
log(false, 'CREATOR-CLI', '', 'log')
|
} else {
|
||||||
|
referralUrl += '&new=1'
|
||||||
|
}
|
||||||
|
|
||||||
|
log(false, 'CREATOR-CLI', '✅ Referral URL configured with &new=1 parameter', 'log', 'green')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Banner
|
// Banner
|
||||||
|
|||||||
@@ -144,29 +144,41 @@ export default class BrowserFunc {
|
|||||||
throw new Error('Account has been suspended!')
|
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) {
|
if (iteration <= 2) {
|
||||||
try {
|
try {
|
||||||
const diagnosticInfo = await page.evaluate(() => {
|
const diagnosticInfo = await page.evaluate(() => {
|
||||||
const elementsWithActivitiesId = document.querySelectorAll('[id*="activit"]')
|
const elementsWithActivitiesId = document.querySelectorAll('[id*="activit"]')
|
||||||
const meeCardGroups = document.querySelectorAll('mee-card-group')
|
const meeCardGroups = document.querySelectorAll('mee-card-group')
|
||||||
const hasRoleList = document.querySelectorAll('[role="list"]')
|
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 {
|
return {
|
||||||
activitiesIdCount: elementsWithActivitiesId.length,
|
activitiesIdCount: elementsWithActivitiesId.length,
|
||||||
activitiesIds: Array.from(elementsWithActivitiesId).map(el => el.id).slice(0, 5),
|
activitiesIds: Array.from(elementsWithActivitiesId).map(el => el.id).slice(0, 5),
|
||||||
meeCardGroupCount: meeCardGroups.length,
|
meeCardGroupCount: meeCardGroups.length,
|
||||||
roleListCount: hasRoleList.length,
|
roleListCount: hasRoleList.length,
|
||||||
|
dailySetsCount: dailySets.length,
|
||||||
|
rewardsElementsCount: rewardsElements.length,
|
||||||
|
hasMainContent: !!mainContent,
|
||||||
pageTitle: document.title,
|
pageTitle: document.title,
|
||||||
bodyClasses: document.body.className
|
bodyClasses: document.body.className,
|
||||||
|
url: window.location.href
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.bot.log(this.bot.isMobile, 'GO-HOME-DEBUG',
|
this.bot.log(this.bot.isMobile, 'GO-HOME-DEBUG',
|
||||||
`DOM Diagnostic - Elements with 'activit': ${diagnosticInfo.activitiesIdCount}, ` +
|
`DOM Diagnostic - ` +
|
||||||
`IDs: [${diagnosticInfo.activitiesIds.join(', ')}], ` +
|
`URL: ${diagnosticInfo.url}, ` +
|
||||||
|
`Title: "${diagnosticInfo.pageTitle}", ` +
|
||||||
|
`Elements with 'activit': ${diagnosticInfo.activitiesIdCount} [${diagnosticInfo.activitiesIds.join(', ')}], ` +
|
||||||
`mee-card-group: ${diagnosticInfo.meeCardGroupCount}, ` +
|
`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) {
|
} catch (error) {
|
||||||
this.bot.log(this.bot.isMobile, 'GO-HOME-DEBUG', `Diagnostic failed: ${error}`, 'warn')
|
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')
|
this.bot.log(this.bot.isMobile, 'GO-HOME', 'On correct URL but activities missing - forcing page reload to trigger DOM render', 'warn')
|
||||||
|
|
||||||
try {
|
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, {
|
await waitForPageReady(page, {
|
||||||
timeoutMs: 10000,
|
timeoutMs: 10000,
|
||||||
logFn: (msg) => this.bot.log(this.bot.isMobile, 'GO-HOME', msg, 'log')
|
logFn: (msg) => this.bot.log(this.bot.isMobile, 'GO-HOME', msg, 'log')
|
||||||
|
|||||||
@@ -93,14 +93,19 @@ export const SELECTORS = {
|
|||||||
// FIXED: Use more specific selector to avoid strict mode violation (2 elements with id='more-activities')
|
// 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
|
// Target the mee-card-group element specifically, not the div wrapper
|
||||||
MORE_ACTIVITIES: 'mee-card-group#more-activities[role="list"]',
|
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_FALLBACKS: [
|
||||||
'#more-activities', // ID only (most permissive)
|
|
||||||
'mee-card-group#more-activities', // Without role attribute
|
'mee-card-group#more-activities', // Without role attribute
|
||||||
|
'#more-activities', // ID only (most permissive)
|
||||||
'[id="more-activities"]', // Attribute selector
|
'[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
|
'.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',
|
SUSPENDED_ACCOUNT: '#suspendedAccountHeader',
|
||||||
QUIZ_COMPLETE: '#quizCompleteContainer',
|
QUIZ_COMPLETE: '#quizCompleteContainer',
|
||||||
|
|||||||
Reference in New Issue
Block a user