UNPKG

@corellium/corellium-api

Version:

Supported nodejs library for interacting with the Corellium service and VMs

180 lines (165 loc) 5.03 kB
'use strict' const BUTTONS = { home: 4, power: 8, 'volume-up': 16, 'volume-down': 32, ringer: 64 } function buttonId (button) { if (!(button in BUTTONS)) throw new Error(`invalid button ${button}`) return BUTTONS[button] } const TOUCH = 1 /** * An input to send to an instance. * * Inputs consist of a series of steps. Each method in this class adds a step * to the current input, and returns the current input to allow chaining. To * run the input, send it to an instance with {@link Instance#sendInput}. * * A global, `{@link I}`, is provided as a convenience. `I.doThing()` is a * shorthand for `new Input().doThing()`. * * @see {@link Instance#sendInput} * @example * const input = new Input().pressRelease('home').tap(100, 100); * await instance.sendInput(input); * // using the I shortcut * const input2 = I.pressRelease('home').tap(100, 100); * await instance.sendInput(input2); */ class Input { /** * The name of a button. Possible values are: * * Button|Description * -|- * `'home'`|Home button * `'power'`|Power button * `'volume-up'`|Volume up button * `'volume-down'`|Volume down button * `'ringer'`|Ringer switch * @typedef {string} Input~ButtonName */ /** * Creates a new input with no steps. It's usually more convenient to use * `{@link I}` instead. */ constructor () { this.points = [] this.pressed = 0 this._delay = 0 } _addPoint (point = {}) { point.buttons = this.pressed if (this._delay !== 0) point.delay = this._delay this.points.push(point) this._delay = 0 return this } /** * Add a step to press and hold the specified buttons. * @param {...Input~ButtonName} buttonNames - Names of buttons to press. * @returns this */ press (...buttonNames) { buttonNames.forEach((button) => { this.pressed |= buttonId(button) }) return this._addPoint() } /** * Add a step to release the specified buttons. * @param {...Input~ButtonName} buttonNames - Names of buttons to release. * @returns this */ release (...buttonNames) { buttonNames.forEach((button) => { this.pressed &= ~buttonId(button) }) return this._addPoint() } /** * Add a step to delay by the specified number of milliseconds. * @param {number} [delay=100] - The number of milliseconds to delay. * @returns this */ delay (delay) { this._delay = delay return this } /** * Add steps to press the specified button, delay for an interval * defaulting to 100 milliseconds, and release the specified button. * @param {Input~ButtonName} button - The button to press and release. * @param {number} [delay=100] The number of milliseconds to hold down the button. * @returns this */ pressRelease (button, delay = 100) { return this.press(button).delay(delay).release(button) } /** * Add a step to set the current touch position and start touching the screen. * @param {number} x - The x coordinate. * @param {number} y - The y coordinate. * @return this */ touch (x, y) { this.pressed |= TOUCH return this._addPoint({ pos: [x, y] }) } /** * Add a step to release the touchscreen. * @return this */ touchUp () { this.pressed &= ~TOUCH return this._addPoint() } /** * Add a step to swipe from the current touch position to the specified * position. Bezier control points may be specified. If there is a delay * step immediately before this one, the swipe will take place over the * delay; otherwise it will happen instantly. * @param {number} x - The x coordinate to swipe to. * @param {number} y - The y coordinate to swipe to. * @param {point[]} [curve] - An array of Bezier control points. Each * point is a two-element array containing an x coordinate and a y * coordinate. */ swipeTo (x, y, curve) { if (!(this.pressed & TOUCH)) throw new Error('touch must be down to swipe') return this._addPoint({ pos: [x, y], curve }) } /** * Add steps to touch the screen at the given position, delay for an * interval defaulting to 100 milliseconds, and release the touchscreen. * @param {number} x - The x coordinate. * @param {number} y - The y coordinate. * @param {number} [delay=100] The number of milliseconds to hold down the touch. */ tap (x, y, delay = 100) { return this.touch(x, y).delay(delay).touchUp() } } /** * A magic object that can be used as a shortcut for `new Input()` in * expressions like `new Input().pressRelease('home')`. * @see Input * @constant * @example * I.press('home').delay(250).release('home') * I.touch(100, 100).delay(250).swipeTo(200, 200).touchUp() */ const I = new Proxy( {}, { get (_target, prop) { return function (...args) { return new Input()[prop](...args) } } } ) module.exports = { Input, I }