File size: 2,017 Bytes
a920dd4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Human-like mouse movement: bezier curve with jitter + variable step delays.
// Used by turnstile.js and exported for any code that wants natural cursor paths.

function bezier(p0, p1, p2, p3, t) {
  const u = 1 - t;
  return {
    x: u * u * u * p0.x + 3 * u * u * t * p1.x + 3 * u * t * t * p2.x + t * t * t * p3.x,
    y: u * u * u * p0.y + 3 * u * u * t * p1.y + 3 * u * t * t * p2.y + t * t * t * p3.y,
  };
}

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function humanMove(page, fromX, fromY, toX, toY, opts = {}) {
  const { steps = 25, jitter = 4, baseDelayMs = 8 } = opts;
  // Two control points slightly off the straight line — gives a curved path
  const dx = toX - fromX;
  const dy = toY - fromY;
  const c1 = {
    x: fromX + dx * 0.3 + (Math.random() - 0.5) * 80,
    y: fromY + dy * 0.3 + (Math.random() - 0.5) * 80,
  };
  const c2 = {
    x: fromX + dx * 0.7 + (Math.random() - 0.5) * 80,
    y: fromY + dy * 0.7 + (Math.random() - 0.5) * 80,
  };
  for (let i = 0; i <= steps; i++) {
    const t = i / steps;
    const p = bezier({ x: fromX, y: fromY }, c1, c2, { x: toX, y: toY }, t);
    const jx = (Math.random() - 0.5) * jitter;
    const jy = (Math.random() - 0.5) * jitter;
    await page.mouse.move(p.x + jx, p.y + jy);
    await sleep(baseDelayMs + Math.random() * 12);
  }
}

async function humanClick(page, x, y, opts = {}) {
  const { holdMs = 60 + Math.random() * 80 } = opts;
  await page.mouse.move(x + (Math.random() - 0.5) * 2, y + (Math.random() - 0.5) * 2);
  await sleep(80 + Math.random() * 120);
  await page.mouse.down();
  await sleep(holdMs);
  await page.mouse.up();
}

// Move from current position (or center if unknown) to (x,y) and click
async function humanMoveAndClick(page, x, y, opts = {}) {
  const cur = page._lastMousePos || { x: 200, y: 200 };
  await humanMove(page, cur.x, cur.y, x, y, opts);
  await humanClick(page, x, y, opts);
  page._lastMousePos = { x, y };
}

module.exports = { humanMove, humanClick, humanMoveAndClick };