Skip to content
Open
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
116 changes: 87 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# bunbot

[<img src="https://i.imgur.com/iQgEyms.jpg" title="Generated using Craiyon, formerly DALL-E mini" align="right" width="120">]([https://deno.land](https://www.craiyon.com/))

Desktop automation for the Bun runtime. Currently works on Mac.

[![npm (tag)](https://img.shields.io/npm/v/bunbot?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/bunbot) ![NPM](https://img.shields.io/npm/l/bunbot?style=flat&colorA=000000&colorB=000000)

## Requirements

Bunbot uses [RobotGo](https://github.com/go-vgo/robotgo) via `bun:ffi`. Please see RobotGo's requirements [here](https://github.com/go-vgo/robotgo#requirements).
Bunbot uses [bot](https://github.com/go-vgo/bot) via `bun:ffi`. Please see bot's requirements [here](https://github.com/go-vgo/bot#requirements).

## Usage

Expand All @@ -19,46 +17,106 @@ bun add bunbot
### Mouse

```ts
import Bunbot from 'bunbot'

const bb = new Bunbot()

// Click
bb.click()
// Get mouse position coordinates
const mousePosition = bb.getMousePosition()
// Move mouse
bb.moveMouse(200, 400)
// Move mouse smoothly
bb.moveMouseSmooth(200, 400)
// Scroll mouse
bb.scrollMouse(100, 200)
import { CreateBot } from 'bunbot'

const bot = CreateBot()

bot.setMouseSleep(100)

bot.scrollDir(10, 'up')
bot.scrollDir(20, 'right')

bot.scroll(0, -10)
bot.scroll(100, 0)

bot.milliSleep(100)
bot.scrollSmooth(-10, 6)

bot.move(10, 20)
bot.moveRelative(0, -10)
bot.dragSmooth(10, 10)

bot.click('wheelRight')
bot.click('left', true)
bot.moveSmooth(100, 200, 1.0, 10.0)

bot.toggle('left')
bot.toggle('left', 'up')
```

### Keyboard

```ts
import Bunbot from 'bunbot'
import { CreateBot } from 'bunbot'

const bb = CreateBot()

bot.typeStr('Hello World')
bot.typeStr('だんしゃり')
// bot.TypeStr('テストする')

bot.typeStr('Hi, Seattle space needle, Golden gate bridge, One world trade center.')
bot.typeStr('Hi galaxy, hi stars, hi MT.Rainier, hi sea. こんにちは世界.')
bot.sleep(1)

// ustr := uint32(bot.CharCodeAt('Test', 0))
// bot.UnicodeType(ustr)

bot.setKeySleep(100)
bot.keyTap('enter')
// bot.TypeStr('en')
bot.keyTap('i', 'alt', 'cmd')

const bb = new Bunbot()
bot.keyTap('i', 'alt', 'cmd')

// Type a string
bb.type('Hello world!')
// Tap a key
bb.tap('i', 'alt', 'command')
bot.milliSleep(100)
bot.keyToggle('a')
bot.keyToggle('a', 'up')

bot.writeAll('Test')

const text = bot.readAll()
```

### Screen

```ts
import Bunbot from 'bunbot'
import { CreateBot } from 'bunbot'

const bb = CreateBot()

const { x, y } = bb.location()
console.log('pos: ', x, y)

const scaleSize = bb.getPixelColor(100, 200)
console.log('color: ', color)

const { x: sx, y: sy } = bb.getScreenSize()
console.log('get screen size: ', sx, sy)

const num = bot.displaysNum()
for (let i = 0; i < num; i++) {
bot.setDisplayID(i)

const img1 = bot.captureImg()
const path1 = `save_${i}`
bot.save(img1, `${path1}.png`)
bot.saveJpeg(img1, `${path1}.jpeg`, 50)

const img2 = bot.captureImg(10, 10, 20, 20)
bot.save(img2, `test_${i}.png`)
}
```

### Other

```ts
import { CreateBot } from 'bunbot'

const bb = new Bunbot()
const bb = CreateBot()

// Get screen size
const screenSize = bb.getScreenSize()
// Get scale size
const scaleSize = bb.getScaleSize()
// Get the image text using Tesseract OCR.
const text = bb.getText()
```

## License
Expand Down
14 changes: 10 additions & 4 deletions build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ import path from 'node:path'
const output = await Bun.build({
entrypoints: ['./src/index.ts'],
outdir: './dist',
external: ['bun:ffi'],
plugins: [
dts()
],
target: 'node'
})

const XGO = path.join(process.env.HOME, 'go/bin/xgo');
const TARGETS = 'linux/arm64,linux/amd64,darwin/arm64,darwin/amd64';
const TARGETS = [
'linux/arm64',
'linux/amd64',
'darwin/arm64',
'darwin/amd64'
];

if (output.success) {
console.log('Compiling native binaries...')
const proc = Bun.spawnSync([
const proc = Bun.spawn([
XGO,
"-go", "1.20.3",
"-out", "release/bunbot",
Expand All @@ -24,5 +29,6 @@ if (output.success) {
"-buildmode=c-shared",
".",
]);
console.log(proc.stdout.toString())
const text = await new Response(proc.stdout).text();
console.log(text);
}
33 changes: 33 additions & 0 deletions examples/keyboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { CreateBot } from '../src'

const bot = CreateBot()

setTimeout(() => {
bot.typeStr("Hello World")
bot.typeStr("だんしゃり")
// bot.TypeStr("テストする")

bot.typeStr("Hi, Seattle space needle, Golden gate bridge, One world trade center.")
bot.typeStr("Hi galaxy, hi stars, hi MT.Rainier, hi sea. こんにちは世界.")
bot.sleep(1)

// ustr := uint32(bot.CharCodeAt("Test", 0))
// bot.UnicodeType(ustr)

bot.setKeySleep(100)
bot.keyTap("enter")
// bot.TypeStr("en")
bot.keyTap("i", "alt", "cmd")

bot.keyTap("i", 'alt', 'cmd')

bot.milliSleep(100)
bot.keyToggle("a")
bot.keyToggle("a", "up")

bot.writeAll("Test")

const x = bot.readAll()

console.log(x)
}, 1000)
27 changes: 27 additions & 0 deletions examples/mouse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { CreateBot } from '../src'

const bot = CreateBot()

setTimeout(() => {
bot.setMouseSleep(100)

bot.scrollDir(10, 'up')
bot.scrollDir(20, 'right')

bot.scroll(0, -10)
bot.scroll(100, 0)

bot.milliSleep(100)
bot.scrollSmooth(-10, 6)

bot.move(10, 20)
bot.moveRelative(0, -10)
bot.dragSmooth(10, 10)

bot.click('wheelRight')
bot.click('left', true)
bot.moveSmooth(100, 200, 1.0, 10.0)

bot.toggle('left')
bot.toggle('left', 'up')
}, 1000)
19 changes: 19 additions & 0 deletions examples/screen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { CreateBot } from '../src'

const bot = CreateBot()

setTimeout(() => {
const num = bot.displaysNum()

for (let i = 0; i < num; i++) {
bot.setDisplayID(i)

const img1 = bot.captureImg()
const path1 = `save_${i}`
bot.save(img1, `${path1}.png`)
bot.saveJpeg(img1, `${path1}.jpeg`, 50)

const img2 = bot.captureImg(10, 10, 20, 20)
bot.save(img2, `test_${i}.png`)
}
}, 1000)
Loading