feat: implement HumanTyping module to enhance typing simulation and avoid bot detection

This commit is contained in:
2025-12-06 15:02:08 +01:00
parent 067c1989e2
commit b783f7c1fa
6 changed files with 196 additions and 18 deletions

View File

@@ -4,6 +4,7 @@ import type { Page } from 'playwright'
import { MicrosoftRewardsBot } from '../index'
import { OAuth } from '../interface/OAuth'
import { HumanTyping } from '../util/browser/HumanTyping'
import { waitForElementSmart, waitForPageReady } from '../util/browser/SmartWait'
import { Retry } from '../util/core/Retry'
import { logError } from '../util/notifications/Logger'
@@ -622,8 +623,8 @@ export class Login {
})
if (!prefilledResult.found) {
await page.fill(SELECTORS.emailInput, '')
await page.fill(SELECTORS.emailInput, email)
// FIXED: Use HumanTyping instead of .fill() to avoid bot detection
await HumanTyping.typeEmail(page.locator(SELECTORS.emailInput), email)
} else {
this.bot.log(this.bot.isMobile, 'LOGIN', 'Email prefilled')
}
@@ -684,8 +685,8 @@ export class Login {
const blocked = await this.securityDetector.detectSignInBlocked(page)
if (blocked) return
await page.fill(SELECTORS.passwordInput, '')
await page.fill(SELECTORS.passwordInput, password)
// FIXED: Use HumanTyping instead of .fill() to avoid bot detection
await HumanTyping.typePassword(page.locator(SELECTORS.passwordInput), password)
const submitResult = await waitForElementSmart(page, SELECTORS.submitBtn, {
initialTimeoutMs: 500,

View File

@@ -6,6 +6,7 @@ import { Workers } from '../Workers'
import { AxiosRequestConfig } from 'axios'
import { Counters, DashboardData } from '../../interface/DashboardData'
import { GoogleSearch } from '../../interface/Search'
import { HumanTyping } from '../../util/browser/HumanTyping'
import { waitForElementSmart } from '../../util/browser/SmartWait'
type GoogleTrendsResponse = [
@@ -232,15 +233,18 @@ export class Search extends Workers {
let navigatedDirectly = false
try {
// Try focusing and filling instead of clicking (more reliable on mobile)
// FIXED: Use HumanTyping instead of .fill() to avoid bot detection
await box.focus({ timeout: 2000 }).catch(() => { /* ignore focus errors */ })
await box.fill('')
await this.bot.utils.wait(200)
// Clear field using keyboard (natural)
await searchPage.keyboard.down(platformControlKey)
await searchPage.keyboard.press('A')
await searchPage.keyboard.press('Backspace')
await searchPage.keyboard.up(platformControlKey)
await box.type(query, { delay: 20 })
// FIXED: Use HumanTyping for natural search query entry
await HumanTyping.type(box, query, 1.5) // Fast typing (familiar search action)
await searchPage.keyboard.press('Enter')
} catch (typeErr) {
// As a robust fallback, navigate directly to the search results URL

View File

@@ -3,6 +3,7 @@ import path from 'path'
import type { Page } from 'playwright'
import { DELAYS } from '../../constants'
import { HumanTyping } from '../../util/browser/HumanTyping'
import { Workers } from '../Workers'
import { MorePromotion, PromotionalItem } from '../../interface/DashboardData'
@@ -27,9 +28,10 @@ export class SearchOnBing extends Workers {
await this.bot.utils.wait(DELAYS.SEARCH_ON_BING_FOCUS)
try {
await box.focus({ timeout: DELAYS.THIS_OR_THAT_START }).catch(() => { /* ignore */ })
await box.fill('')
await this.bot.utils.wait(DELAYS.SEARCH_ON_BING_FOCUS)
await page.keyboard.type(query, { delay: DELAYS.TYPING_DELAY })
// FIXED: Use HumanTyping instead of .fill() to avoid bot detection
await HumanTyping.type(box, query, 1.5) // Fast typing (familiar search action)
await page.keyboard.press('Enter')
} catch {
const url = `https://www.bing.com/search?q=${encodeURIComponent(query)}`

View File

@@ -1,6 +1,7 @@
import type { Locator, Page } from 'playwright'
import readline from 'readline'
import { MicrosoftRewardsBot } from '../../index'
import { HumanTyping } from '../../util/browser/HumanTyping'
import { logError } from '../../util/notifications/Logger'
import { generateTOTP } from '../../util/security/Totp'
@@ -190,8 +191,8 @@ export class TotpHandler {
return
}
// Fill code and submit
await page.fill('input[name="otc"]', code)
// FIXED: Use HumanTyping instead of .fill() to avoid bot detection
await HumanTyping.typeTotp(page.locator('input[name="otc"]'), code)
await page.keyboard.press('Enter')
this.bot.log(this.bot.isMobile, 'LOGIN', '2FA code submitted')
} catch (error) {
@@ -248,8 +249,8 @@ export class TotpHandler {
this.bot.log(this.bot.isMobile, 'LOGIN', 'TOTP input unexpectedly hidden', 'warn')
return
}
await input.fill('')
await input.fill(code)
// FIXED: Use HumanTyping instead of .fill() to avoid bot detection
await HumanTyping.typeTotp(input, code)
// Use unified selector system
const submit = await this.findFirstVisibleLocator(page, TotpHandler.TOTP_SELECTORS.submit)
if (submit) {