Skip to content

weston-b/denovnc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation


DenoVNC

Automate remote control over VNC with Deno!

Usage

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

(back to top)

Roadmap

  • 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).

(back to top)

License

Distributed under the Apache 2.0 License. See the LICENSE file in this repo for more information.

(back to top)

Contact

Weston Barnes - [email protected]

Project Link: https://github.com/weston-b/denovnc

(back to top)

Acknowledgments

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.

(back to top)

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published