Skip to content

Commit 3296af6

Browse files
committed
Separate out pyppeteer and playwright modules
1 parent a25fd1e commit 3296af6

File tree

11 files changed

+97
-72
lines changed

11 files changed

+97
-72
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,6 @@ dmypy.json
135135
.pytype/
136136

137137
# Cython debug symbols
138-
cython_debug/
138+
cython_debug/
139+
140+
.vscode

pyppeteer_ghost_cursor/__init__.py

+24-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,28 @@
11
import logging
22

3-
from pyppeteer_ghost_cursor.spoof import createCursor, get_path as path
4-
from pyppeteer_ghost_cursor.mouseHelper import installMouseHelper
5-
63
_logger = logging.getLogger(__name__)
74
_logger.setLevel(logging.DEBUG)
5+
6+
from .shared import path
7+
8+
# To support deprecations
9+
def createCursor(*args, **kwargs):
10+
from .pyppeteer import create_cursor
11+
12+
_logger.warning(
13+
"""DEPRECATION WARNING: 'createCursor' has been moved, please use the new version: 'from python_ghost_cursor.pyppeteer import create_cursor'.
14+
This method will be removed in a future release.
15+
"""
16+
)
17+
return create_cursor(*args, **kwargs)
18+
19+
20+
def installMouseHelper(*args, **kwargs):
21+
from .pyppeteer import install_mouse_helper
22+
23+
_logger.warning(
24+
"""DEPRECATION WARNING: 'installMouseHelper' has been moved, please use the new version: 'from python_ghost_cursor.pyppeteer import install_mouse_helper'.
25+
This method will be removed in a future release.
26+
"""
27+
)
28+
return install_mouse_helper(*args, **kwargs)

pyppeteer_ghost_cursor/mouseHelper.py

-9
This file was deleted.

pyppeteer_ghost_cursor/playwright/async_api/__init__.py

Whitespace-only changes.

pyppeteer_ghost_cursor/playwright/sync_api/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from pyppeteer_ghost_cursor import _logger
2+
from .spoof import create_cursor
3+
from .mouse_helper import install_mouse_helper
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from pyppeteer.page import Page
2+
from typing import Coroutine
3+
from pathlib import Path
4+
5+
6+
async def install_mouse_helper(page: Page) -> Coroutine[None, None, None]:
7+
await page.evaluateOnNewDocument(
8+
Path(__file__).parent.joinpath("../js/mouseHelper.js").read_text()
9+
)

pyppeteer_ghost_cursor/spoof.py renamed to pyppeteer_ghost_cursor/pyppeteer/spoof.py

+4-59
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
1-
# TODO:
2-
# - Add click and moveTo
3-
# - Double check for completion
4-
# - Actually make a repo
5-
# - Publish
6-
71
import asyncio
82
import logging
93
import math
10-
import numpy as np
114
import random
125
from typing import Union, Coroutine, Optional, Dict, List
136
from pyppeteer.page import Page
@@ -21,26 +14,17 @@
2114
# https://github.com/pyppeteer/pyppeteer/blob/dev/pyppeteer/element_handle.py
2215
from pyppeteer.element_handle import ElementHandle
2316

24-
from pyppeteer_ghost_cursor.math import (
17+
from pyppeteer_ghost_cursor.shared.math import (
2518
Vector,
26-
magnitude,
27-
direction,
2819
origin,
29-
bezierCurve,
3020
overshoot,
3121
)
22+
from pyppeteer_ghost_cursor.shared.spoof import path, shouldOvershoot
3223

3324

3425
logger = logging.getLogger(__name__)
3526

3627

37-
def fitts(distance: float, width: float) -> float:
38-
a = 0
39-
b = 2
40-
id_ = math.log2(distance / width + 1)
41-
return a + b * id_
42-
43-
4428
def getRandomBoxPoint(box: Dict, paddingPercentage: Optional[float] = None) -> Vector:
4529
"""Get a random point on a box"""
4630
paddingWidth = paddingHeight = 0
@@ -124,40 +108,6 @@ async def getElementBox(
124108
return elementBox
125109

126110

127-
def path(
128-
start: Vector, end: Union[Dict, Vector], spreadOverride: Optional[float] = None
129-
) -> List[Vector]:
130-
defaultWidth = 100
131-
minSteps = 25
132-
if isinstance(end, dict):
133-
width = end["width"]
134-
end = Vector(end["x"], end["y"])
135-
else:
136-
width = defaultWidth
137-
curve = bezierCurve(start, end, spreadOverride)
138-
length = curve.length * 0.8
139-
baseTime = random.random() * minSteps
140-
steps = math.ceil((math.log2(fitts(length, width) + 1) + baseTime) * 3)
141-
s_vals = np.linspace(0.0, 1.0, steps)
142-
points = curve.evaluate_multi(s_vals)
143-
vectors = []
144-
for i in range(steps):
145-
vectors.append(Vector(points[0][i], points[1][i]))
146-
return clampPositive(vectors)
147-
148-
149-
def clampPositive(vectors: List[Vector]) -> List[Vector]:
150-
clamp0 = lambda elem: max(0, elem)
151-
return [Vector(clamp0(el.x), clamp0(el.y)) for el in vectors]
152-
153-
154-
overshootThreshold = 500
155-
156-
157-
def shouldOvershoot(a: Vector, b: Vector) -> bool:
158-
return magnitude(direction(a, b)) > overshootThreshold
159-
160-
161111
class GhostCursor:
162112
def __init__(self, page, start: Vector):
163113
self.page = page
@@ -294,18 +244,13 @@ async def moveTo(self, destination: dict) -> Coroutine[None, None, None]:
294244
self.toggleRandomMove(True)
295245

296246

297-
def createCursor(
247+
def create_cursor(
298248
page, start: Union[Vector, Dict] = origin, performRandomMoves: bool = False
299-
) -> Coroutine[None, None, GhostCursor]:
249+
) -> GhostCursor:
300250
if isinstance(start, dict):
301251
start = Vector(**start)
302252
cursor = GhostCursor(page, start)
303253
if performRandomMoves:
304254
# Start random mouse movements. Do not await the promise but return immediately
305255
asyncio.ensure_future(cursor.randomMove()) # fire and forget
306256
return cursor
307-
308-
309-
def get_path(start: Dict, end: Dict) -> List[Dict]:
310-
vectors = path(Vector(**start), Vector(**end))
311-
return [el.__dict__ for el in vectors]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .spoof import get_path as path
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import math
2+
import random
3+
import numpy as np
4+
from typing import Union, Optional, Dict, List
5+
from pyppeteer_ghost_cursor.shared.math import (
6+
Vector,
7+
magnitude,
8+
direction,
9+
bezierCurve,
10+
)
11+
12+
def fitts(distance: float, width: float) -> float:
13+
a = 0
14+
b = 2
15+
id_ = math.log2(distance / width + 1)
16+
return a + b * id_
17+
18+
def path(
19+
start: Vector, end: Union[Dict, Vector], spreadOverride: Optional[float] = None
20+
) -> List[Vector]:
21+
defaultWidth = 100
22+
minSteps = 25
23+
if isinstance(end, dict):
24+
width = end["width"]
25+
end = Vector(end["x"], end["y"])
26+
else:
27+
width = defaultWidth
28+
curve = bezierCurve(start, end, spreadOverride)
29+
length = curve.length * 0.8
30+
baseTime = random.random() * minSteps
31+
steps = math.ceil((math.log2(fitts(length, width) + 1) + baseTime) * 3)
32+
s_vals = np.linspace(0.0, 1.0, steps)
33+
points = curve.evaluate_multi(s_vals)
34+
vectors = []
35+
for i in range(steps):
36+
vectors.append(Vector(points[0][i], points[1][i]))
37+
return clampPositive(vectors)
38+
39+
40+
def clampPositive(vectors: List[Vector]) -> List[Vector]:
41+
clamp0 = lambda elem: max(0, elem)
42+
return [Vector(clamp0(el.x), clamp0(el.y)) for el in vectors]
43+
44+
45+
overshootThreshold = 500
46+
47+
48+
def shouldOvershoot(a: Vector, b: Vector) -> bool:
49+
return magnitude(direction(a, b)) > overshootThreshold
50+
51+
def get_path(start: Dict, end: Dict) -> List[Dict]:
52+
vectors = path(Vector(**start), Vector(**end))
53+
return [el.__dict__ for el in vectors]

0 commit comments

Comments
 (0)