mirror of
https://github.com/TheNetsky/Microsoft-Rewards-Script.git
synced 2026-01-19 14:33:58 +00:00
v3.1.0 initial
This commit is contained in:
129
src/browser/auth/methods/GetACodeLogin.ts
Normal file
129
src/browser/auth/methods/GetACodeLogin.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import type { Page } from 'patchright'
|
||||
import type { MicrosoftRewardsBot } from '../../../index'
|
||||
import { getErrorMessage, getSubtitleMessage, promptInput } from './LoginUtils'
|
||||
|
||||
export class CodeLogin {
|
||||
private readonly textInputSelector = '[data-testid="codeInputWrapper"]'
|
||||
private readonly secondairyInputSelector = 'input[id="otc-confirmation-input"], input[name="otc"]'
|
||||
private readonly maxManualSeconds = 60
|
||||
private readonly maxManualAttempts = 5
|
||||
|
||||
constructor(private bot: MicrosoftRewardsBot) {}
|
||||
|
||||
private async fillCode(page: Page, code: string): Promise<boolean> {
|
||||
try {
|
||||
const visibleInput = await page
|
||||
.waitForSelector(this.textInputSelector, { state: 'visible', timeout: 500 })
|
||||
.catch(() => null)
|
||||
|
||||
if (visibleInput) {
|
||||
await page.keyboard.type(code, { delay: 50 })
|
||||
this.bot.logger.info(this.bot.isMobile, 'LOGIN-CODE', 'Filled code input')
|
||||
return true
|
||||
}
|
||||
|
||||
const secondairyInput = await page.$(this.secondairyInputSelector)
|
||||
if (secondairyInput) {
|
||||
await page.keyboard.type(code, { delay: 50 })
|
||||
this.bot.logger.info(this.bot.isMobile, 'LOGIN-CODE', 'Filled code input')
|
||||
return true
|
||||
}
|
||||
|
||||
this.bot.logger.warn(this.bot.isMobile, 'LOGIN-CODE', 'No code input field found')
|
||||
return false
|
||||
} catch (error) {
|
||||
this.bot.logger.warn(
|
||||
this.bot.isMobile,
|
||||
'LOGIN-CODE',
|
||||
`Failed to fill code input: ${error instanceof Error ? error.message : String(error)}`
|
||||
)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async handle(page: Page): Promise<void> {
|
||||
try {
|
||||
this.bot.logger.info(this.bot.isMobile, 'LOGIN-CODE', 'Code login authentication requested')
|
||||
|
||||
const emailMessage = await getSubtitleMessage(page)
|
||||
if (emailMessage) {
|
||||
this.bot.logger.info(this.bot.isMobile, 'LOGIN-CODE', `Page message: "${emailMessage}"`)
|
||||
} else {
|
||||
this.bot.logger.warn(this.bot.isMobile, 'LOGIN-CODE', 'Unable to retrieve email code destination')
|
||||
}
|
||||
|
||||
for (let attempt = 1; attempt <= this.maxManualAttempts; attempt++) {
|
||||
const code = await promptInput({
|
||||
question: `Enter the 6-digit code (waiting ${this.maxManualSeconds}s): `,
|
||||
timeoutSeconds: this.maxManualSeconds,
|
||||
validate: code => /^\d{6}$/.test(code)
|
||||
})
|
||||
|
||||
if (!code || !/^\d{6}$/.test(code)) {
|
||||
this.bot.logger.warn(
|
||||
this.bot.isMobile,
|
||||
'LOGIN-CODE',
|
||||
`Invalid or missing code (attempt ${attempt}/${this.maxManualAttempts}) | input length=${code?.length}`
|
||||
)
|
||||
|
||||
if (attempt === this.maxManualAttempts) {
|
||||
throw new Error('Manual code input failed or timed out')
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
const filled = await this.fillCode(page, code)
|
||||
if (!filled) {
|
||||
this.bot.logger.error(
|
||||
this.bot.isMobile,
|
||||
'LOGIN-CODE',
|
||||
`Unable to fill code input (attempt ${attempt}/${this.maxManualAttempts})`
|
||||
)
|
||||
|
||||
if (attempt === this.maxManualAttempts) {
|
||||
throw new Error('Code input field not found')
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
await this.bot.utils.wait(500)
|
||||
await page.waitForLoadState('networkidle', { timeout: 5000 }).catch(() => {})
|
||||
|
||||
// Check if wrong code was entered
|
||||
const errorMessage = await getErrorMessage(page)
|
||||
if (errorMessage) {
|
||||
this.bot.logger.warn(
|
||||
this.bot.isMobile,
|
||||
'LOGIN-CODE',
|
||||
`Incorrect code: ${errorMessage} (attempt ${attempt}/${this.maxManualAttempts})`
|
||||
)
|
||||
|
||||
if (attempt === this.maxManualAttempts) {
|
||||
throw new Error(`Maximum attempts reached: ${errorMessage}`)
|
||||
}
|
||||
|
||||
// Clear the input field before retrying
|
||||
const inputToClear = await page.$(this.textInputSelector).catch(() => null)
|
||||
if (inputToClear) {
|
||||
await inputToClear.click()
|
||||
await page.keyboard.press('Control+A')
|
||||
await page.keyboard.press('Backspace')
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
this.bot.logger.info(this.bot.isMobile, 'LOGIN-CODE', 'Code authentication completed successfully')
|
||||
return
|
||||
}
|
||||
|
||||
throw new Error(`Code input failed after ${this.maxManualAttempts} attempts`)
|
||||
} catch (error) {
|
||||
this.bot.logger.error(
|
||||
this.bot.isMobile,
|
||||
'LOGIN-CODE',
|
||||
`Error occurred: ${error instanceof Error ? error.message : String(error)}`
|
||||
)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user