A basic example:
import { createConnection, Key } from 'https://deno.land/x/[email protected]/mod.ts'
const client = await createConnection({
host : '127.0.0.1',
port : 5900
});
await client.key(Key.Super)
await client.type('about')
await client.key(Key.Enter)
await client.key(Key.Up, Key.Super)
await client.matchText(400, 0, 600, 100, 'About')
? await client.click(50, 50)
: console.log("The text does not match!")
await client.end()
More examples:
import { createConnection, MouseButton, Key } from 'https://deno.land/x/[email protected]/mod.ts'
const host = '127.0.0.1'
const port = 5900
const password = 'pass'
const client = await createConnection({
host, port, password,
onerror: (error: any) => {
throw new Error(error)
},
onclose: () => {
console.log('Connection closed.')
},
onconnected: () => {
console.log('Successfully connected and authorised.')
console.log(`Remote screen name: ${client.name} Width: ${client.width()} Height: ${client.height()}`)
},
onresize: () => {
console.log(`Window size has been resized! Width: ${client.width()}, Height: ${client.height()}`)
},
onclipboard: (newPasteBufData: any) => {
console.log('Remote clipboard updated!', newPasteBufData)
},
onbell: () => {
console.log('Bell!')
},
});
const routine1 = async (client: any) => {
const { text, capture } = await client.read(400, 400, 600, 450) // request & wait for update, then OCR rect
switch (text.toLowerCase()) {
case 'ready':
await client.click(425, 425) // same as leftclick, mouse down, then mouse up
break
case 'loading':
await client.rightclick(425, 425) // mouse down, then mouse up
await client.leftclick(450, 450) // same as click
break
default:
console.log('Unknown text from routine1: ', text, capture)
}
}
const drawSineWave = async (client: any) => {
const a = 150
const b = -0.2
for (let step = 0; step < 111; step++) {
await client.pointerDown(400 + step * 10, 750 + (Math.sin(step * b ) * a))
}
await client.pointerUp(1500, 750)
}
const { text } = await client.framebufferUpdateRequest(20, 20, 140, 70)
console.log(text)
await client.key(Key.Super)
await client.type('term')
await client.key(Key.Enter)
await client.key(Key.Up, Key.Super)
await client.type('ping 127.0.0.1')
await client.key(Key.Enter)
await client.updateClipboard('Hello!') // update server clipboard
await client.pause(1000) // timeout helper
await client.pointerDown(600, 600) // x, y
await client.pointerUp(600, 600) // x, y
await client.click(800, 800) // x, y - same as leftclick unless button number specified
await client.doubleClick(100, 100) // x, y - two clicks, 100ms apart
await client.leftClick(100, 100) // x, y
await client.rightClick(300, 400) // x, y
await client.middleClick(100, 100) // x, y
await client.keyDown(Key.Control) // keycode - sends keydown
await client.key(44) // keycode - sends keydown, then keyup
await client.key('4') // keycode - sends keydown, then keyup
await client.keyUp(Key.Control) // keycode - sends keyup
await client.type('Hello!', 100) // sends key events, optionally set pause between characters
await client.cad() // sends control + alt + delete
await routine1(client) // call a routine within a regular flow
await drawSineWave()
const { text } = await client.read(400, 400, 600, 450) // request & wait for update, then OCR rect
const { capture } = await client.capture(400, 400, 600, 450) // request & wait for update
const color = await client.sampleColor(700, 600) // returns the hex color at x,y
await client.matchIcon(700, 600, 'path/to/icon.png') // request & wait for update, then try to match icon
? await client.middleClick(100, 100)
: console.log("The icon does not match!")
await client.matchText(200, 100, 400, 200 'username') // request & wait for update, then ocr & try to match text
? await client.click(100, 100)
: console.log('The text does not match!')
await client.end() // close connection
- Add Tesseract.js OCR
- Add Tesseract.js position detection
- Add universal implicit .pause()
- Add .matchText()
- Add .matchIcon()
- Add .sampleColor()
- Add tests - integration w/ different servers?
- Support different framebuffer encodings
- Support incremental framebuffer updates
- Add changelog
- Web-based visual config and debugging
- Multi-language support
- Typescript throughout
- Add comprehensive examples
- List on deno.land/x/
See the open issues for a full list of proposed features (and known issues).
Distributed under the Apache 2.0 License. See the LICENSE
file in this repo for more information.
Weston Barnes - [email protected]
Project Link: https://github.com/weston-b/denovnc
This is inspired by the work done by Andrey Sidorov on node-rfb2. Also, thank you to T. Richardson & J. Levine for RFC 6143 - an invaluable reference.