fakebrowser
Version:
🤖 Fake fingerprints to bypass anti-bot systems. Simulate mouse and keyboard operations to make behavior like a real person.
400 lines • 32.5 kB
JavaScript
"use strict";
// noinspection JSUnusedGlobalSymbols,JSUnusedLocalSymbols,PointlessArithmeticExpressionJS
Object.defineProperty(exports, "__esModule", { value: true });
exports.FakeUserAction = void 0;
const assert_1 = require("assert");
const helper_1 = require("./helper");
const PptrToolkit_1 = require("./PptrToolkit");
class FakeUserAction {
constructor(fb) {
this._mouseCurrPos = { x: helper_1.helper.rd(0, 1280), y: helper_1.helper.rd(0, 700) };
// this._fakeBrowser = new WeakRef<FakeBrowser>(fb)
this._fakeBrowser = fb;
}
/**
* Fake mouse movement track
* @param startPos
* @param endPos
* @param maxPoints
* @param cpDelta
*/
static mouseMovementTrack(startPos, endPos, maxPoints = 30, cpDelta = 1) {
// reference: https://github.com/mtsee/Bezier/blob/master/src/bezier.js
let nums = [];
let maxNum = 0;
let moveStep = 1;
// Simulates the user's mouse movement acceleration / constant speed / deceleration
for (let n = 0; n < maxPoints; ++n) {
nums.push(maxNum);
// noinspection PointlessArithmeticExpressionJS
if (n < maxPoints * 1 / 10) {
moveStep += helper_1.helper.rd(60, 100);
}
else if (n >= maxPoints * 9 / 10) {
moveStep -= helper_1.helper.rd(60, 100);
moveStep = Math.max(20, moveStep);
}
maxNum += moveStep;
}
const result = [];
const p1 = [
startPos.x,
startPos.y,
];
const cp1 = [
(startPos.x + endPos.x) / 2 + helper_1.helper.rd(30, 100, true) * cpDelta,
(startPos.y + endPos.y) / 2 + helper_1.helper.rd(30, 100, true) * cpDelta,
];
const cp2 = [
(startPos.x + endPos.x) / 2 + helper_1.helper.rd(30, 100, true) * cpDelta,
(startPos.y + endPos.y) / 2 + helper_1.helper.rd(30, 100, true) * cpDelta,
];
const p2 = [
endPos.x,
endPos.y,
];
for (let num of nums) {
const [x, y] = helper_1.helper.threeBezier(num / maxNum, p1, cp1, cp2, p2);
result.push({ x, y });
}
return result;
}
/**
* Simulate mouse movement
* @param page
* @param options
*/
static async simMouseMove(page, options) {
const points = this.mouseMovementTrack(options.startPos, options.endPos, options.maxPoints || helper_1.helper.rd(15, 30), options.cpDelta || 1);
for (let n = 0; n < points.length; n += 1) {
const point = points[n];
await page.mouse.move(point.x, point.y, { steps: helper_1.helper.rd(1, 2) });
await helper_1.helper.sleep((options.timestamp || helper_1.helper.rd(300, 800)) / points.length);
}
}
get fakeBrowser() {
// @ts-ignore
if (!this._fakeBrowser || this._fakeBrowser._zombie) {
return null;
}
// WeakRef:
// const fb: FakeBrowser | undefined = this._fakeBrowser.deref()
const fb = this._fakeBrowser;
if (!fb) {
this._fakeBrowser = null;
return null;
}
return fb;
}
async simMouseMoveTo(endPos, maxPoints, timestamp, cpDelta) {
const fb = this.fakeBrowser;
if (!fb) {
return false;
}
if (fb.isMobileBrowser) {
// We don't need to simulate mouse slide.
await helper_1.helper.sleepRd(300, 800);
return true;
}
// Get the current page of the browser
const currPage = await fb.getActivePage();
(0, assert_1.strict)(currPage);
// first move to a close position, then finally move to the target position
const closeToEndPos = {
x: endPos.x + helper_1.helper.rd(5, 30, true),
y: endPos.y + helper_1.helper.rd(5, 20, true),
};
await FakeUserAction.simMouseMove(currPage, {
startPos: this._mouseCurrPos,
endPos: closeToEndPos,
maxPoints,
timestamp,
cpDelta,
});
// The last pos must correction
await currPage.mouse.move(endPos.x, endPos.y, { steps: helper_1.helper.rd(5, 13) });
this._mouseCurrPos = endPos;
return true;
}
async simRandomMouseMove() {
const fb = this.fakeBrowser;
if (!fb) {
return false;
}
if (fb.isMobileBrowser) {
// We don't need to simulate mouse slide.
await helper_1.helper.sleepRd(200, 500);
return true;
}
const fakeDD = fb.driverParams.fakeDeviceDesc;
(0, assert_1.strict)(fakeDD);
const innerWidth = fakeDD.window.innerWidth;
const innerHeight = fakeDD.window.innerHeight;
// -----------------
// | 1/6 |
// | 1/4 1/4 |
// | 1/6 |
// -----------------
const startX = innerWidth / 4;
const startY = innerHeight / 6;
const endX = innerWidth * 3 / 4;
const endY = innerHeight * 5 / 6;
const endPos = { x: helper_1.helper.rd(startX, endX), y: helper_1.helper.rd(startY, endY) };
await this.simMouseMoveTo(endPos);
await helper_1.helper.sleepRd(300, 800);
return true;
}
async simClick(options = {
pauseAfterMouseUp: true,
}) {
const fb = this.fakeBrowser;
if (!fb) {
return false;
}
const currPage = await fb.getActivePage();
(0, assert_1.strict)(currPage);
if (fb.isMobileBrowser) {
// We can't use mouse obj, we have to use touchscreen
await currPage.touchscreen.tap(this._mouseCurrPos.x, this._mouseCurrPos.y);
}
else {
await currPage.mouse.down();
await helper_1.helper.sleepRd(30, 80);
await currPage.mouse.up();
}
if (options && options.pauseAfterMouseUp) {
await helper_1.helper.sleepRd(150, 600);
}
return true;
}
async simMoveToAndClick(endPos, options = {
pauseAfterMouseUp: true,
}) {
const fb = this.fakeBrowser;
if (!fb) {
return false;
}
const currPage = await fb.getActivePage();
(0, assert_1.strict)(currPage);
if (!fb.isMobileBrowser) {
await this.simMouseMoveTo(endPos);
await currPage.mouse.move(endPos.x + helper_1.helper.rd(-10, 10), endPos.y, { steps: helper_1.helper.rd(8, 20) });
}
this._mouseCurrPos = endPos;
await helper_1.helper.sleepRd(300, 800);
return this.simClick(options);
}
async simMouseMoveToElement(eh) {
const fb = this.fakeBrowser;
if (!fb) {
return false;
}
const fakeDD = fb.driverParams.fakeDeviceDesc;
(0, assert_1.strict)(fakeDD);
const currPage = await fb.getActivePage();
(0, assert_1.strict)(currPage);
let box;
if (fb.isMobileBrowser) {
box = await FakeUserAction.adjustElementPositionWithTouchscreen(eh, currPage, fakeDD);
}
else {
box = await FakeUserAction.adjustElementPositionWithMouse(eh, currPage, fakeDD);
}
if (box) {
// The position of each element click should not be the center of the element
// size of the clicked element must larger than 10 x 10
const endPos = {
x: box.x + box.width / 2 + helper_1.helper.rd(0, 5, true),
y: box.y + box.height / 2 + helper_1.helper.rd(0, 5, true),
};
await this.simMouseMoveTo(endPos);
// Pause
await helper_1.helper.sleepRd(300, 800);
return true;
}
return false;
}
async simClickElement(eh, options = {
pauseAfterMouseUp: true,
}) {
const moveToEl = await this.simMouseMoveToElement(eh);
if (!moveToEl) {
return false;
}
// click
if (await this.simClick(options)) {
return true;
}
else {
return false;
}
}
static async adjustElementPositionWithMouse(eh, currPage, fakeDD) {
let box = null;
for (;;) {
box = await PptrToolkit_1.PptrToolkit.boundingBox(eh);
if (box) {
// Check the node is in the visible area
// @ts-ignore
let deltaX = 0;
let deltaY = 0;
let viewportAdjust = false;
// If the top of the node is less than 0
if (box.y <= 0) {
// deltaY always positive
// ---------------------
// 30px |
// [ ] |
// .. Distance to be moved
// .. |
// .. |
// ---------------------body top
deltaY = Math.min(-(box.y - 30) - 0, helper_1.helper.rd(150, 300));
deltaY = -deltaY;
viewportAdjust = true;
}
else if (box.y + box.height >= fakeDD.window.innerHeight) {
// If the bottom is beyond
deltaY = Math.min(box.y + box.height + 30 - fakeDD.window.innerHeight, helper_1.helper.rd(150, 300));
viewportAdjust = true;
}
// if (box.x <= 0) {
// // If the top of the button is less than 0
// deltaX = Math.min(-box.x + 30, sh.rd(100, 400))
// deltaX = -deltaX
// viewportAdjust = true
// } else if (box.x + box.width >= fakeDD.window.innerWidth) {
// // If the bottom is beyond
// deltaX = Math.min(box.x + box.width - fakeDD.window.innerWidth + 30, sh.rd(100, 400))
// viewportAdjust = true
// }
if (viewportAdjust) {
// await currPage.mouse.wheel({deltaX})
await currPage.mouse.wheel({ deltaY });
await helper_1.helper.sleepRd(100, 400);
}
else {
break;
}
}
else {
break;
}
}
return box;
}
static async adjustElementPositionWithTouchscreen(eh, currPage, fakeDD) {
let box = null;
for (;;) {
box = await PptrToolkit_1.PptrToolkit.boundingBox(eh);
if (box) {
// @ts-ignore
let deltaX = 0;
let deltaY = 0;
let viewportAdjust = false;
if (box.y <= 0) {
deltaY = Math.min(-box.y + 30, helper_1.helper.rd(100, 300));
deltaY = -deltaY;
viewportAdjust = true;
}
else if (box.y + box.height >= fakeDD.window.innerHeight) {
deltaY = Math.min(box.y + box.height - fakeDD.window.innerHeight + 30, helper_1.helper.rd(100, 300));
viewportAdjust = true;
}
if (viewportAdjust) {
// noinspection TypeScriptValidateTypes
const _patchTouchscreenDesc = Object.getOwnPropertyDescriptor(currPage, '_patchTouchscreen');
(0, assert_1.strict)(_patchTouchscreenDesc);
const touchscreen = _patchTouchscreenDesc.value;
(0, assert_1.strict)(touchscreen);
// if deltaY is negative, drop down, otherwise drop up
const startX = fakeDD.window.innerWidth / 2 + helper_1.helper.rd(0, fakeDD.window.innerWidth / 6);
const endX = fakeDD.window.innerWidth / 2 + helper_1.helper.rd(0, fakeDD.window.innerWidth / 6);
let startY;
let endY;
if (deltaY < 0) {
startY = helper_1.helper.rd(0, fakeDD.window.innerHeight - (-deltaY));
endY = startY + deltaY;
}
else {
startY = helper_1.helper.rd(deltaY, fakeDD.window.innerHeight);
endY = startY - deltaY;
}
await touchscreen.drag({
x: startX, y: startY,
}, {
x: endX, y: endY,
});
await helper_1.helper.sleepRd(100, 300);
}
else {
break;
}
}
else {
break;
}
}
return box;
}
async simKeyboardPress(text, options = {
pauseAfterKeyUp: true,
}) {
const fb = this.fakeBrowser;
if (!fb) {
return false;
}
const currPage = await fb.getActivePage();
(0, assert_1.strict)(currPage);
await currPage.keyboard.press(text);
if (options && options.pauseAfterKeyUp) {
await helper_1.helper.sleepRd(300, 1000);
}
return true;
}
async simKeyboardEnter(options = {
pauseAfterKeyUp: true,
}) {
return await this.simKeyboardPress('Enter', options);
}
async simKeyboardEsc(options = {
pauseAfterKeyUp: true,
}) {
return await this.simKeyboardPress('Escape', options);
}
async simKeyboardType(text, options = {
pauseAfterLastKeyUp: true,
}) {
const fb = this.fakeBrowser;
if (!fb) {
return false;
}
const currPage = await fb.getActivePage();
(0, assert_1.strict)(currPage);
const needsShiftKey = '~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:"ZXCVBNM<>?';
// TODO: check if shiftKey, alt, ctrl can be fired in mobile browsers
for (let ch of text) {
let needsShift = false;
if (needsShiftKey.includes(ch)) {
needsShift = true;
await currPage.keyboard.down('ShiftLeft');
await helper_1.helper.sleepRd(500, 1000);
}
// if a Chinese character
const isCh = ch.match(/^[\u4e00-\u9fa5]/);
const delay = isCh ? helper_1.helper.rd(200, 800) : helper_1.helper.rd(30, 100);
await currPage.keyboard.type('' + ch, { delay });
if (needsShift) {
await helper_1.helper.sleepRd(150, 450);
await currPage.keyboard.up('ShiftLeft');
}
await helper_1.helper.sleepRd(30, 100);
}
if (options && options.pauseAfterLastKeyUp) {
await helper_1.helper.sleepRd(300, 1000);
}
return true;
}
}
exports.FakeUserAction = FakeUserAction;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmFrZVVzZXJBY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29yZS9GYWtlVXNlckFjdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMEZBQTBGOzs7QUFFMUYsbUNBQXVDO0FBSXZDLHFDQUErQjtBQUUvQiwrQ0FBeUM7QUFJekMsTUFBYSxjQUFjO0lBUXZCLFlBQVksRUFBZTtRQUN2QixJQUFJLENBQUMsYUFBYSxHQUFHLEVBQUMsQ0FBQyxFQUFFLGVBQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxlQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBQyxDQUFBO1FBQ2xFLG1EQUFtRDtRQUNuRCxJQUFJLENBQUMsWUFBWSxHQUFHLEVBQUUsQ0FBQTtJQUMxQixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ssTUFBTSxDQUFDLGtCQUFrQixDQUM3QixRQUFlLEVBQ2YsTUFBYSxFQUNiLFNBQVMsR0FBRyxFQUFFLEVBQ2QsT0FBTyxHQUFHLENBQUM7UUFFWCx1RUFBdUU7UUFFdkUsSUFBSSxJQUFJLEdBQUcsRUFBRSxDQUFBO1FBQ2IsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFBO1FBQ2QsSUFBSSxRQUFRLEdBQUcsQ0FBQyxDQUFBO1FBRWhCLG1GQUFtRjtRQUNuRixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxFQUFFLEVBQUUsQ0FBQyxFQUFFO1lBQ2hDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUE7WUFFakIsK0NBQStDO1lBQy9DLElBQUksQ0FBQyxHQUFHLFNBQVMsR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFO2dCQUN4QixRQUFRLElBQUksZUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUE7YUFDakM7aUJBQU0sSUFBSSxDQUFDLElBQUksU0FB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