Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

style: add prettier for whitespace formatting #142

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"scripts": {
"prepare": "husky && yarn lint && yarn build",
"build": "tsc -p tsconfig.build.json",
"lint": "yarn ts-standard --fix",
"lint": "yarn ts-standard --fix && yarn prettier src --write",
"test": "jest"
},
"keywords": [
Expand All @@ -34,6 +34,7 @@
"husky": "9",
"jest": "29",
"jest-puppeteer": "10",
"prettier": "^3.2.5",
"puppeteer": "22",
"ts-standard": "12",
"typescript": "5"
Expand All @@ -52,5 +53,11 @@
"transform": {
"^.+\\.(t|j)sx?$": "@swc/jest"
}
},
"prettier":{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this config seemed to be what resulted in the least changes from existing code

"printWidth": 100,
"singleQuote": true,
"semi": false,
"trailingComma": "none"
}
}
18 changes: 4 additions & 14 deletions src/math.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ export const add = (a: Vector, b: Vector): Vector => ({ x: a.x + b.x, y: a.y + b

export const direction = (a: Vector, b: Vector): Vector => sub(b, a)
export const perpendicular = (a: Vector): Vector => ({ x: a.y, y: -1 * a.x })
export const magnitude = (a: Vector): number =>
Math.sqrt(Math.pow(a.x, 2) + Math.pow(a.y, 2))
export const magnitude = (a: Vector): number => Math.sqrt(Math.pow(a.x, 2) + Math.pow(a.y, 2))
export const unit = (a: Vector): Vector => div(a, magnitude(a))
export const setMagnitude = (a: Vector, amount: number): Vector =>
mult(unit(a), amount)
export const setMagnitude = (a: Vector, amount: number): Vector => mult(unit(a), amount)

export const randomNumberRange = (min: number, max: number): number =>
Math.random() * (max - min) + min
Expand All @@ -29,21 +27,13 @@ export const randomVectorOnLine = (a: Vector, b: Vector): Vector => {
return add(a, mult(vec, multiplier))
}

const randomNormalLine = (
a: Vector,
b: Vector,
range: number
): [Vector, Vector] => {
const randomNormalLine = (a: Vector, b: Vector, range: number): [Vector, Vector] => {
const randMid = randomVectorOnLine(a, b)
const normalV = setMagnitude(perpendicular(direction(a, randMid)), range)
return [randMid, normalV]
}

export const generateBezierAnchors = (
a: Vector,
b: Vector,
spread: number
): [Vector, Vector] => {
export const generateBezierAnchors = (a: Vector, b: Vector, spread: number): [Vector, Vector] => {
const side = Math.round(Math.random()) === 1 ? 1 : -1
const calc = (): Vector => {
const [randMid, normalV] = randomNormalLine(a, b, spread)
Expand Down
4 changes: 2 additions & 2 deletions src/mouse-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { Page } from 'puppeteer'
* This injects a box into the page that moves with the mouse.
* Useful for debugging.
*/
async function installMouseHelper (page: Page): Promise<void> {
async function installMouseHelper(page: Page): Promise<void> {
await page.evaluateOnNewDocument(() => {
const attachListener = (): void => {
const box = document.createElement('p-mouse-pointer')
Expand Down Expand Up @@ -97,7 +97,7 @@ async function installMouseHelper (page: Page): Promise<void> {
},
true
)
function updateButtons (buttons): void {
function updateButtons(buttons): void {
for (let i = 0; i < 5; i++) {
box.classList.toggle('button-' + String(i), Boolean(buttons & (1 << i)))
}
Expand Down
139 changes: 62 additions & 77 deletions src/spoof.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
import type { ElementHandle, Page, BoundingBox, CDPSession } from 'puppeteer'
import debug from 'debug'
import {
type Vector,
bezierCurve,
direction,
magnitude,
origin,
overshoot
} from './math'
import { type Vector, bezierCurve, direction, magnitude, origin, overshoot } from './math'
export { default as installMouseHelper } from './mouse-helper'

const log = debug('ghost-cursor')
Expand Down Expand Up @@ -81,14 +74,17 @@ export interface PathOptions {
readonly moveSpeed?: number
}

export interface RandomMoveOptions extends Pick<MoveOptions, 'moveDelay' | 'randomizeMoveDelay' | 'moveSpeed'> {
export interface RandomMoveOptions
extends Pick<MoveOptions, 'moveDelay' | 'randomizeMoveDelay' | 'moveSpeed'> {
/**
* @default 2000
*/
readonly moveDelay?: number
}

export interface MoveToOptions extends PathOptions, Pick<MoveOptions, 'moveDelay' | 'randomizeMoveDelay'> {
export interface MoveToOptions
extends PathOptions,
Pick<MoveOptions, 'moveDelay' | 'randomizeMoveDelay'> {
/**
* @default 0
*/
Expand All @@ -97,14 +93,8 @@ export interface MoveToOptions extends PathOptions, Pick<MoveOptions, 'moveDelay

export interface GhostCursor {
toggleRandomMove: (random: boolean) => void
click: (
selector?: string | ElementHandle,
options?: ClickOptions
) => Promise<void>
move: (
selector: string | ElementHandle,
options?: MoveOptions
) => Promise<void>
click: (selector?: string | ElementHandle, options?: ClickOptions) => Promise<void>
move: (selector: string | ElementHandle, options?: MoveOptions) => Promise<void>
moveTo: (destination: Vector, options?: MoveToOptions) => Promise<void>
getLocation: () => Vector
}
Expand All @@ -128,10 +118,7 @@ const fitts = (distance: number, width: number): number => {
}

/** Get a random point on a box */
const getRandomBoxPoint = (
{ x, y, width, height }: BoundingBox,
options?: BoxOptions
): Vector => {
const getRandomBoxPoint = ({ x, y, width, height }: BoundingBox, options?: BoxOptions): Vector => {
let paddingWidth = 0
let paddingHeight = 0

Expand All @@ -151,15 +138,13 @@ const getRandomBoxPoint = (
}

/** The function signature to access the internal CDP client changed in puppeteer 14.4.1 */
const getCDPClient = (page: any): CDPSession => typeof page._client === 'function' ? page._client() : page._client
const getCDPClient = (page: any): CDPSession =>
typeof page._client === 'function' ? page._client() : page._client

/** Get a random point on a browser window */
export const getRandomPagePoint = async (page: Page): Promise<Vector> => {
const targetId: string = (page.target() as any)._targetId
const window = await getCDPClient(page).send(
'Browser.getWindowForTarget',
{ targetId }
)
const window = await getCDPClient(page).send('Browser.getWindowForTarget', { targetId })
return getRandomBoxPoint({
x: origin.x,
y: origin.y,
Expand Down Expand Up @@ -192,9 +177,7 @@ const getElementBox = async (
if (!relativeToMainFrame) {
const elementFrame = await element.contentFrame()
const iframes =
elementFrame != null
? await elementFrame.parentFrame()?.$$('xpath/.//iframe')
: null
elementFrame != null ? await elementFrame.parentFrame()?.$$('xpath/.//iframe') : null
let frame: ElementHandle<Node> | undefined
if (iframes != null) {
for (const iframe of iframes) {
Expand All @@ -203,10 +186,8 @@ const getElementBox = async (
}
if (frame != null) {
const boundingBox = await frame.boundingBox()
elementBox.x =
boundingBox !== null ? elementBox.x - boundingBox.x : elementBox.x
elementBox.y =
boundingBox !== null ? elementBox.y - boundingBox.y : elementBox.y
elementBox.x = boundingBox !== null ? elementBox.x - boundingBox.x : elementBox.x
elementBox.y = boundingBox !== null ? elementBox.y - boundingBox.y : elementBox.y
}
}

Expand All @@ -217,28 +198,35 @@ const getElementBox = async (
}
}

export function path (point: Vector, target: Vector, optionsOrSpread?: number | PathOptions)
export function path (point: Vector, target: BoundingBox, optionsOrSpread?: number | PathOptions)
export function path (start: Vector, end: BoundingBox | Vector, optionsOrSpread?: number | PathOptions): Vector[] {
const optionsResolved: PathOptions = typeof optionsOrSpread === 'number'
? { spreadOverride: optionsOrSpread }
: { ...optionsOrSpread }
export function path(point: Vector, target: Vector, optionsOrSpread?: number | PathOptions)
export function path(point: Vector, target: BoundingBox, optionsOrSpread?: number | PathOptions)
export function path(
start: Vector,
end: BoundingBox | Vector,
optionsOrSpread?: number | PathOptions
): Vector[] {
const optionsResolved: PathOptions =
typeof optionsOrSpread === 'number'
? { spreadOverride: optionsOrSpread }
: { ...optionsOrSpread }

const DEFAULT_WIDTH = 100
const MIN_STEPS = 25
const width = 'width' in end && end.width !== 0 ? end.width : DEFAULT_WIDTH
const curve = bezierCurve(start, end, optionsResolved.spreadOverride)
const length = curve.length() * 0.8

const speed = optionsResolved.moveSpeed !== undefined && optionsResolved.moveSpeed > 0
? (25 / optionsResolved.moveSpeed)
: Math.random()
const speed =
optionsResolved.moveSpeed !== undefined && optionsResolved.moveSpeed > 0
? 25 / optionsResolved.moveSpeed
: Math.random()
const baseTime = speed * MIN_STEPS
const steps = Math.ceil((Math.log2(fitts(length, width) + 1) + baseTime) * 3)
const re = curve.getLUT(steps)
return clampPositive(re)
}

// prettier-ignore
const clampPositive = (vectors: Vector[]): Vector[] => vectors.map((vector) => ({
x: Math.max(0, vector.x),
y: Math.max(0, vector.y)
Expand All @@ -247,24 +235,20 @@ const clampPositive = (vectors: Vector[]): Vector[] => vectors.map((vector) => (
const shouldOvershoot = (a: Vector, b: Vector, threshold: number): boolean =>
magnitude(direction(a, b)) > threshold

const intersectsElement = (vec: Vector, box: BoundingBox): boolean => {
return (
vec.x > box.x &&
vec.x <= box.x + box.width &&
vec.y > box.y &&
vec.y <= box.y + box.height
)
}
const intersectsElement = (vec: Vector, box: BoundingBox): boolean =>
// prettier-ignore
vec.x > box.x &&
vec.x <= box.x + box.width &&
vec.y > box.y &&
vec.y <= box.y + box.height

const boundingBoxWithFallback = async (
page: Page,
elem: ElementHandle<Element>
): Promise<BoundingBox> => {
let box = await getElementBox(page, elem)
if (box == null) {
box = (await elem.evaluate((el: Element) =>
el.getBoundingClientRect()
)) as BoundingBox
box = (await elem.evaluate((el: Element) => el.getBoundingClientRect())) as BoundingBox
}

return box
Expand Down Expand Up @@ -350,7 +334,9 @@ export const createCursor = (
await tracePath(path(previous, rand, optionsResolved), true)
previous = rand
}
await delay(optionsResolved.moveDelay * (optionsResolved.randomizeMoveDelay ? Math.random() : 1))
await delay(
optionsResolved.moveDelay * (optionsResolved.randomizeMoveDelay ? Math.random() : 1)
)
randomMove(options).then(
(_) => {},
(_) => {}
Expand All @@ -361,18 +347,15 @@ export const createCursor = (
}

const actions: GhostCursor = {
toggleRandomMove (random: boolean): void {
toggleRandomMove(random: boolean): void {
moving = !random
},

getLocation (): Vector {
getLocation(): Vector {
return previous
},

async click (
selector?: string | ElementHandle,
options?: ClickOptions
): Promise<void> {
async click(selector?: string | ElementHandle, options?: ClickOptions): Promise<void> {
const optionsResolved = {
moveDelay: 2000,
hesitate: 0,
Expand Down Expand Up @@ -402,15 +385,14 @@ export const createCursor = (
log('Warning: could not click mouse, error message:', error)
}

await delay(optionsResolved.moveDelay * (optionsResolved.randomizeMoveDelay ? Math.random() : 1))
await delay(
optionsResolved.moveDelay * (optionsResolved.randomizeMoveDelay ? Math.random() : 1)
)

actions.toggleRandomMove(wasRandom)
},

async move (
selector: string | ElementHandle,
options?: MoveOptions
): Promise<void> {
async move(selector: string | ElementHandle, options?: MoveOptions): Promise<void> {
const optionsResolved = {
moveDelay: 0,
maxTries: 10,
Expand All @@ -423,7 +405,7 @@ export const createCursor = (
const wasRandom = !moving

const go = async (iteration: number): Promise<void> => {
if (iteration > (optionsResolved.maxTries)) {
if (iteration > optionsResolved.maxTries) {
throw Error('Could not mouse-over element within enough tries')
}

Expand Down Expand Up @@ -480,17 +462,16 @@ export const createCursor = (
destination,
optionsResolved.overshootThreshold
)
const to = overshooting
? overshoot(destination, OVERSHOOT_RADIUS)
: destination
const to = overshooting ? overshoot(destination, OVERSHOOT_RADIUS) : destination

await tracePath(path(previous, to, optionsResolved))

if (overshooting) {
const correction = path(to, { ...dimensions, ...destination }, {
...optionsResolved,
spreadOverride: OVERSHOOT_SPREAD
})
const correction = path(
to,
{ ...dimensions, ...destination },
{ ...optionsResolved, spreadOverride: OVERSHOOT_SPREAD }
)

await tracePath(correction)
}
Expand All @@ -512,10 +493,12 @@ export const createCursor = (

actions.toggleRandomMove(wasRandom)

await delay(optionsResolved.moveDelay * (optionsResolved.randomizeMoveDelay ? Math.random() : 1))
await delay(
optionsResolved.moveDelay * (optionsResolved.randomizeMoveDelay ? Math.random() : 1)
)
},

async moveTo (destination: Vector, options?: MoveToOptions): Promise<void> {
async moveTo(destination: Vector, options?: MoveToOptions): Promise<void> {
const optionsResolved = {
moveDelay: 0,
randomizeMoveDelay: true,
Expand All @@ -528,7 +511,9 @@ export const createCursor = (
await tracePath(path(previous, destination, optionsResolved))
actions.toggleRandomMove(wasRandom)

await delay(optionsResolved.moveDelay * (optionsResolved.randomizeMoveDelay ? Math.random() : 1))
await delay(
optionsResolved.moveDelay * (optionsResolved.randomizeMoveDelay ? Math.random() : 1)
)
}
}

Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3960,6 +3960,11 @@ prelude-ls@^1.2.1:
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==

prettier@^3.2.5:
version "3.2.5"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368"
integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==

pretty-format@^29.0.0, pretty-format@^29.7.0:
version "29.7.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812"
Expand Down