- Updated packages
- Cleanup
- Improved message dismissal
- Improved login functionality

With help from @LightZirconite
This commit is contained in:
TheNetsky
2025-04-24 14:50:22 +02:00
parent 325bf65b30
commit 0ddc964878
11 changed files with 96 additions and 41 deletions

View File

@@ -39,7 +39,7 @@ export class Login {
// Check if account is locked
await this.checkAccountLocked(page)
const isLoggedIn = await page.waitForSelector('html[data-role-name="RewardsPortal"]', { timeout: 10_000 }).then(() => true).catch(() => false)
const isLoggedIn = await page.waitForSelector('html[data-role-name="RewardsPortal"]', { timeout: 10000 }).then(() => true).catch(() => false)
if (!isLoggedIn) {
await this.execLogin(page, email, password)
@@ -86,30 +86,80 @@ export class Login {
}
private async enterEmail(page: Page, email: string) {
const emailPrefilled = await page.waitForSelector('#userDisplayName', { timeout: 2_000 }).catch(() => null)
if (emailPrefilled) {
this.bot.log(this.bot.isMobile, 'LOGIN', 'Email already prefilled by Microsoft')
return
}
const emailInputSelector = 'input[type="email"]'
await page.fill('#i0116', email)
await page.click('#idSIButton9')
this.bot.log(this.bot.isMobile, 'LOGIN', 'Email entered successfully')
try {
// Wait for email field
const emailField = await page.waitForSelector(emailInputSelector, { state: 'visible', timeout: 2000 }).catch(() => null)
if (!emailField) {
this.bot.log(this.bot.isMobile, 'LOGIN', 'Email field not found', 'warn')
return
}
await this.bot.utils.wait(1000)
// Check if email is prefilled
const emailPrefilled = await page.waitForSelector('#userDisplayName', { timeout: 5000 }).catch(() => null)
if (emailPrefilled) {
this.bot.log(this.bot.isMobile, 'LOGIN', 'Email already prefilled by Microsoft')
} else {
// Else clear and fill email
await page.fill(emailInputSelector, '')
await this.bot.utils.wait(500)
await page.fill(emailInputSelector, email)
await this.bot.utils.wait(1000)
}
const nextButton = await page.waitForSelector('button[type="submit"]', { timeout: 2000 }).catch(() => null)
if (nextButton) {
await nextButton.click()
await this.bot.utils.wait(2000)
this.bot.log(this.bot.isMobile, 'LOGIN', 'Email entered successfully')
} else {
this.bot.log(this.bot.isMobile, 'LOGIN', 'Next button not found after email entry', 'warn')
}
} catch (error) {
this.bot.log(this.bot.isMobile, 'LOGIN', `Email entry failed: ${error}`, 'error')
}
}
private async enterPassword(page: Page, password: string) {
const passwordInputSelector = 'input[type="password"]'
try {
await page.waitForSelector('#i0118', { state: 'visible', timeout: 2000 })
await this.bot.utils.wait(2000)
await page.fill('#i0118', password)
await page.click('#idSIButton9')
this.bot.log(this.bot.isMobile, 'LOGIN', 'Password entered successfully')
} catch {
this.bot.log(this.bot.isMobile, 'LOGIN', 'Password entry failed or 2FA required')
// Wait for password field
const passwordField = await page.waitForSelector(passwordInputSelector, { state: 'visible', timeout: 5000 }).catch(() => null)
if (!passwordField) {
this.bot.log(this.bot.isMobile, 'LOGIN', 'Password field not found, possibly 2FA required', 'warn')
await this.handle2FA(page)
return
}
await this.bot.utils.wait(1000)
// Clear and fill password
await page.fill(passwordInputSelector, '')
await this.bot.utils.wait(500)
await page.fill(passwordInputSelector, password)
await this.bot.utils.wait(1000)
const nextButton = await page.waitForSelector('button[type="submit"]', { timeout: 2000 }).catch(() => null)
if (nextButton) {
await nextButton.click()
await this.bot.utils.wait(2000)
this.bot.log(this.bot.isMobile, 'LOGIN', 'Password entered successfully')
} else {
this.bot.log(this.bot.isMobile, 'LOGIN', 'Next button not found after password entry', 'warn')
}
} catch (error) {
this.bot.log(this.bot.isMobile, 'LOGIN', `Password entry failed: ${error}`, 'error')
await this.handle2FA(page)
}
}
private async handle2FA(page: Page) {
try {
const numberToPress = await this.get2FACode(page)
@@ -138,7 +188,7 @@ export class Login {
while (true) {
const button = await page.waitForSelector('button[aria-describedby="pushNotificationsTitle errorDescription"]', { state: 'visible', timeout: 2000 }).catch(() => null)
if (button) {
await this.bot.utils.wait(60_000)
await this.bot.utils.wait(60000)
await button.click()
continue
@@ -148,7 +198,7 @@ export class Login {
}
}
await page.click('button[aria-describedby="confirmSendTitle"]').catch(() => {})
await page.click('button[aria-describedby="confirmSendTitle"]').catch(() => { })
await this.bot.utils.wait(2000)
const element = await page.waitForSelector('#displaySign', { state: 'visible', timeout: 2000 })
return await element.textContent()
@@ -162,7 +212,7 @@ export class Login {
this.bot.log(this.bot.isMobile, 'LOGIN', `Press the number ${numberToPress} on your Authenticator app to approve the login`)
this.bot.log(this.bot.isMobile, 'LOGIN', 'If you press the wrong number or the "DENY" button, try again in 60 seconds')
await page.waitForSelector('#i0281', { state: 'detached', timeout: 60_000 })
await page.waitForSelector('#i0281', { state: 'detached', timeout: 60000 })
this.bot.log(this.bot.isMobile, 'LOGIN', 'Login successfully approved!')
break
@@ -203,7 +253,7 @@ export class Login {
}
// Wait for login to complete
await page.waitForSelector('html[data-role-name="RewardsPortal"]', { timeout: 10_000 })
await page.waitForSelector('html[data-role-name="RewardsPortal"]', { timeout: 10000 })
this.bot.log(this.bot.isMobile, 'LOGIN', 'Successfully logged into the rewards portal')
}
@@ -272,7 +322,7 @@ export class Login {
currentUrl = new URL(page.url())
await this.bot.utils.wait(5000)
}
const body = new URLSearchParams()
body.append('grant_type', 'authorization_code')
body.append('client_id', this.clientId)