rust-rpa 0.2.0-beta.3 → 0.2.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,17 +4,19 @@
4
4
 
5
5
  ## 特性
6
6
 
7
- - 🚀 **高性能**: 使用 Rust 编写,追求极致速度和效率
7
+ - 🚀 **高性能**: 使用 Rust 编写,napi-rs 绑定,追求极致速度和效率
8
8
  - 🔄 **跨平台**: 支持 Windows 和 macOS
9
9
  - 📦 **易于使用**: 简洁的面向对象 API,支持 TypeScript
10
10
  - ⚡ **非阻塞**: 异步操作不会阻塞 Node.js 事件循环
11
11
  - 🔒 **类型安全**: 完整的 TypeScript 类型定义
12
12
  - 🖱️ **输入自动化**: Mouse 和 Keyboard 类,完整的输入控制
13
- - 🪟 **窗口管理**: 基于 XCap 的窗口枚举和信息获取
13
+ - 🪟 **窗口管理**: 基于 XCap 实现窗口枚举和信息获取
14
14
  - 🖥️ **多显示器支持**: Monitor 类,支持多显示器设置
15
- - 📸 **屏幕截图**: 支持全屏和窗口截图,多种图片格式
15
+ - 📸 **屏幕截图**: 基于 XCap 实现全屏和窗口截图,多种图片格式(PNG/JPEG/BMP)
16
16
  - 🔑 **权限管理**: Permission 类,自动检测并弹出系统权限授权对话框
17
- - 🔍 **OCR 文字识别**: 基于 PP-OCRv5_mobile 模型,支持中英日文字识别及文字位置查找
17
+ - 🔍 **OCR 文字识别**: 基于 PP-OCRv5_mobile 模型和 MNN 推理框架,支持中英日文字识别
18
+ - 🎯 **模板匹配**: GPU 加速的图标查找功能,支持阈值和区域搜索
19
+ - 🖼️ **图像处理**: 裁剪、缩放(Lanczos3)、灰度化等,支持 RGBA 原始数据访问
18
20
 
19
21
  ## 安装
20
22
 
@@ -50,13 +52,13 @@ rpa --help
50
52
  rpa permission --prompt
51
53
 
52
54
  # 列出所有窗口
53
- rpa window:list
55
+ rpa window list
54
56
 
55
57
  # 将窗口置于最前
56
- rpa window:focus Chrome
58
+ rpa window focus Chrome
57
59
 
58
60
  # 设置窗口位置和大小
59
- rpa window:bounds Chrome 100 100 800 600
61
+ rpa window bounds Chrome 100 100 800 600
60
62
 
61
63
  # 截取主显示器
62
64
  rpa screenshot -o desktop.png
@@ -65,23 +67,44 @@ rpa screenshot -o desktop.png
65
67
  rpa screenshot --window Chrome -o chrome.png
66
68
 
67
69
  # 鼠标操作
68
- rpa mouse:position
69
- rpa mouse:move 500 300
70
- rpa mouse:click right
71
- rpa mouse:scroll 0 -3
70
+ rpa mouse position
71
+ rpa mouse move 500 300
72
+ rpa mouse move-rel 100 50
73
+ rpa mouse click right
74
+ rpa mouse scroll 0 -3
72
75
 
73
76
  # 键盘操作
74
- rpa keyboard:type "Hello World"
75
- rpa keyboard:press enter
76
- rpa keyboard:press ctrl+c
77
+ rpa keyboard type "Hello World"
78
+ rpa keyboard press enter
79
+ rpa keyboard press ctrl+c
77
80
 
78
81
  # 剪贴板
79
- rpa clipboard:read
80
- rpa clipboard:write "Hello"
81
- rpa clipboard:paste
82
+ rpa clipboard read
83
+ rpa clipboard write "Hello"
84
+ rpa clipboard paste
85
+ rpa clipboard paste-text "直接粘贴的文本"
86
+ rpa clipboard paste-image screenshot.png
82
87
 
83
88
  # 列出所有显示器
84
- rpa monitor:list
89
+ rpa monitor list
90
+
91
+ # OCR 文字识别
92
+ rpa monitor recognize-text
93
+ rpa monitor find-text "确定"
94
+ rpa window find-text Chrome "搜索"
95
+
96
+ # 图片处理
97
+ rpa image info screenshot.png
98
+ rpa image crop screenshot.png 0 0 800 600 -o cropped.png
99
+ rpa image find-text screenshot.png "文字"
100
+
101
+ # 快捷命令(顶层)
102
+ rpa click right
103
+ rpa move 500 300
104
+ rpa type "Hello"
105
+ rpa press enter
106
+ rpa paste
107
+ rpa pause 1000
85
108
  ```
86
109
 
87
110
  所有命令支持 `--help` 查看详细用法,如 `rpa screenshot --help`。
@@ -150,41 +173,11 @@ async function main() {
150
173
  main();
151
174
  ```
152
175
 
153
- ### TypeScript
154
-
155
- ```typescript
156
- import { Window, Monitor, Mouse, Keyboard } from 'rust-rpa';
157
-
158
- async function main(): Promise<void> {
159
- try {
160
- // 获取所有窗口
161
- const windows = Window.all();
162
- console.log(`Found ${windows.length} windows`);
163
-
164
- windows.forEach((win) => {
165
- console.log(`${win.appName()}: ${win.title()}`);
166
- });
167
-
168
- // 截图
169
- const monitors = Monitor.all();
170
- const image = await monitors[0].captureImage();
171
-
172
- // 输入控制
173
- await Mouse.moveTo(100, 100);
174
- await Keyboard.typeText('Hello!');
175
- } catch (error) {
176
- console.error('Error:', error);
177
- }
178
- }
179
-
180
- main();
181
- ```
182
-
183
176
  ## API
184
177
 
185
178
  ### Window 类
186
179
 
187
- 窗口管理类,基于 XCap 实现。
180
+ 窗口管理类。
188
181
 
189
182
  #### 静态方法
190
183
 
@@ -222,9 +215,9 @@ const windows = Window.all();
222
215
  - `recognizeText(): Promise<TextRecognitionResult[]>` - 识别窗口截图中的文字(先截图 autoSize=true,再执行 OCR)
223
216
  - `findText(text, options?): Promise<TextRecognitionResult | null>` - 在窗口截图中查找指定文字,找到返回位置信息,未找到返回 null(先截图 autoSize=true,再执行 OCR);`options.regions` 可指定查找区域列表以提升性能
224
217
  - `waitText(text, options?): Promise<TextRecognitionResult>` - 等待指定文字出现,超时抛出错误;`options.timeout` 指定等待时间(默认 3000ms),`options.regions` 可指定查找区域
225
- - `waitIcon(template, options?): Promise<MatchResult>` - 等待指定图标出现,超时抛出错误;`options.timeout` 指定等待时间(默认 3000ms),`options.regions` 可指定查找区域
218
+ - `waitIcon(template, options?): Promise<MatchResult>` - 等待指定图标出现,超时抛出错误;`options.timeout` 指定等待时间(默认 3000ms),`options.regions` 可指定查找区域,`options.threshold` 可指定匹配阈值(默认 0.8)
226
219
  - `clickText(text, options?): Promise<void>` - 点击指定文字,先等待文字出现,然后点击文字中心点
227
- - `clickIcon(template, options?): Promise<void>` - 点击指定图标,先等待图标出现,然后点击图标中心点
220
+ - `clickIcon(template, options?): Promise<void>` - 点击指定图标,先等待图标出现,然后点击图标中心点;`options.threshold` 可指定匹配阈值(默认 0.8)
228
221
 
229
222
  ### Monitor 类
230
223
 
@@ -256,9 +249,9 @@ const primary = monitors.find(m => m.isPrimary());
256
249
  - `recognizeText(): Promise<TextRecognitionResult[]>` - 识别显示器截图中的文字(先截图 autoSize=true,再执行 OCR)
257
250
  - `findText(text, options?): Promise<TextRecognitionResult | null>` - 在显示器截图中查找指定文字,找到返回位置信息,未找到返回 null(先截图 autoSize=true,再执行 OCR);`options.regions` 可指定查找区域列表以提升性能
258
251
  - `waitText(text, options?): Promise<TextRecognitionResult>` - 等待指定文字出现,超时抛出错误;`options.timeout` 指定等待时间(默认 3000ms),`options.regions` 可指定查找区域
259
- - `waitIcon(template, options?): Promise<MatchResult>` - 等待指定图标出现,超时抛出错误;`options.timeout` 指定等待时间(默认 3000ms),`options.regions` 可指定查找区域
252
+ - `waitIcon(template, options?): Promise<MatchResult>` - 等待指定图标出现,超时抛出错误;`options.timeout` 指定等待时间(默认 3000ms),`options.regions` 可指定查找区域,`options.threshold` 可指定匹配阈值(默认 0.8)
260
253
  - `clickText(text, options?): Promise<void>` - 点击指定文字,先等待文字出现,然后点击文字中心点
261
- - `clickIcon(template, options?): Promise<void>` - 点击指定图标,先等待图标出现,然后点击图标中心点
254
+ - `clickIcon(template, options?): Promise<void>` - 点击指定图标,先等待图标出现,然后点击图标中心点;`options.threshold` 可指定匹配阈值(默认 0.8)
262
255
 
263
256
  ### ImageData 类
264
257
 
@@ -286,15 +279,15 @@ const primary = monitors.find(m => m.isPrimary());
286
279
  **图像处理**
287
280
 
288
281
  - `crop(x, y, width, height): Promise<ImageData>` - 裁剪图像
289
- - `resize(width, height): Promise<ImageData>` - 缩放图像(使用 Lanczos3 高质量算法)
290
- - `grayscale(): Promise<ImageData>` - 转换为灰度图(使用标准加权算法:0.299R + 0.587G + 0.114B)
291
- - `findIcon(template, options?): Promise<MatchResult>` - 查找模板图标(模板匹配)
292
- - `recognizeText(): Promise<TextRecognitionResult[]>` - 识别图片中的文字(OCR)
293
- - `findText(text): Promise<TextRecognitionResult | null>` - 查找指定文字,找到返回位置信息,未找到返回 null(OCR)
282
+ - `resize(width, height): Promise<ImageData>` - 缩放图像
283
+ - `grayscale(): Promise<ImageData>` - 转换为灰度图
284
+ - `findIcon(template, options?): Promise<MatchResult>` - 查找模板图标
285
+ - `recognizeText(): Promise<TextRecognitionResult[]>` - 识别图片中的文字
286
+ - `findText(text): Promise<TextRecognitionResult | null>` - 查找指定文字
294
287
 
295
288
  **数据访问**
296
289
 
297
- - `getRawData(): Buffer` - 获取原始像素数据(RGBA 格式,每像素 4 字节)
290
+ - `getRawData(): Buffer` - 获取原始像素数据
298
291
  - `metadata(): ImageMetadata` - 获取图片元信息
299
292
 
300
293
  **findIcon 参数:**
@@ -372,6 +365,7 @@ interface CaptureImageOptions {
372
365
  #### 静态方法
373
366
 
374
367
  - `Mouse.moveTo(x, y, duration?): Promise<void>` - 移动鼠标到指定坐标。**duration** 可选,移动动画持续时间(秒),默认为 0(瞬间移动)。如果设置 > 0,鼠标将以平滑动画的方式移动到目标点,动画过程中会触发 mouseMove 事件
368
+ - `Mouse.moveRel(dx, dy, duration?): Promise<void>` - 相对移动鼠标。**dx** X 轴偏移量(正数向右,负数向左);**dy** Y 轴偏移量(正数向下,负数向上);**duration** 可选,移动动画持续时间(秒),默认为 0
375
369
  - `Mouse.click(button?): Promise<void>` - 点击鼠标。**button** 可选,可用枚举 `MouseButton.Left` / `MouseButton.Right` 或字符串 `'left'` / `'right'` 等,默认左键
376
370
  - `Mouse.doubleClick(button?): Promise<void>` - 双击鼠标,button 同上
377
371
  - `Mouse.down(button?): Promise<void>` - 按下鼠标按钮,button 同上
@@ -595,6 +589,7 @@ const { Mouse, MouseButton, Keyboard, Key } = require('rust-rpa');
595
589
  // 鼠标操作
596
590
  await Mouse.moveTo(100, 200); // 瞬间移动鼠标
597
591
  await Mouse.moveTo(100, 200, 0.5); // 平滑动画移动,持续 0.5 秒
592
+ await Mouse.moveRel(50, 30); // 相对移动(从当前位置向右 50、向下 30)
598
593
  await Mouse.click(MouseButton.Left); // 左键点击
599
594
  await Mouse.click(MouseButton.Right); // 右键点击
600
595
  await Mouse.doubleClick(); // 双击
@@ -711,107 +706,6 @@ interface TextRecognitionResult {
711
706
  }
712
707
  ```
713
708
 
714
- > **注意**: OCR 功能需要预先下载模型文件到 `models/` 目录下。模型文件分别为:
715
- > - `PP-OCRv5_mobile_det.mnn` — 文字检测模型(4.7M)
716
- > - `PP-OCRv5_mobile_rec.mnn` — 文字识别模型(16M)
717
- > - `ppocr_keys_v5.txt` — 字符集
718
-
719
-
720
-
721
- // 方式 1: 从截图获取图片
722
- const monitors = Monitor.all();
723
- const screenshot = await monitors[0].captureImage();
724
-
725
- // 方式 2: 从文件加载图片
726
- const image = await ImageData.fromFile('input.png');
727
-
728
- // 方式 3: 从 Buffer 加载图片
729
- const buffer = fs.readFileSync('input.png');
730
- const imageFromBuffer = await ImageData.fromBuffer(buffer);
731
-
732
- // 缩放图片
733
- const resized = await image.resize(800, 600);
734
-
735
- // 裁剪图片
736
- const cropped = await image.crop(100, 100, 400, 300);
737
-
738
- // 转换为灰度图
739
- const grayscale = await image.grayscale();
740
-
741
- // 保存图片(自动根据扩展名识别格式)
742
- await resized.toFile('output.png'); // 保存为 PNG
743
- await grayscale.toFile('gray.jpg'); // 保存为 JPEG
744
- await cropped.toFile('cropped.bmp'); // 保存为 BMP
745
-
746
- // 转换为 Buffer(用于进一步处理)
747
- const pngBuffer = await image.toPng();
748
- fs.writeFileSync('screenshot.png', pngBuffer);
749
-
750
- const jpegBuffer = await image.toJpeg();
751
- fs.writeFileSync('screenshot.jpg', jpegBuffer);
752
-
753
- // 获取原始像素数据
754
- const rawData = image.getRawData(); // Buffer,RGBA 格式
755
- console.log(`Data size: ${rawData.length} bytes`);
756
- console.log(`First pixel: R=${rawData[0]}, G=${rawData[1]}, B=${rawData[2]}, A=${rawData[3]}`);
757
-
758
- // 获取图片元信息
759
- const meta = image.metadata();
760
- console.log(`Size: ${meta.width}x${meta.height}`);
761
- console.log(`Channels: ${meta.channels}, Data: ${meta.dataSize} bytes`);
762
-
763
- // 链式操作
764
- const processed = await ImageData.fromFile('input.png')
765
- .then(img => img.resize(800, 600))
766
- .then(img => img.grayscale())
767
- .then(img => img.crop(100, 100, 400, 300));
768
- await processed.toFile('processed.png');
769
-
770
- // 查找图标(模板匹配)
771
- const template = await ImageData.fromFile('icon.png');
772
-
773
- // 使用默认参数(threshold=0.8,全图搜索)
774
- const result = await image.findIcon(template);
775
-
776
- if (result.found) {
777
- console.log(`找到匹配!`);
778
- console.log(` 相似度: ${(result.score * 100).toFixed(2)}%`);
779
- console.log(` 位置: (${result.x}, ${result.y})`);
780
- } else {
781
- console.log('未找到匹配');
782
- }
783
-
784
- // 自定义阈值
785
- const result1 = await image.findIcon(template, { threshold: 0.9 });
786
-
787
- // 在指定区域内查找
788
- const result2 = await image.findIcon(template, {
789
- threshold: 0.8,
790
- regions: [
791
- { x: 0, y: 0, width: 800, height: 600 } // 只在左上角区域搜索
792
- ]
793
- });
794
- ```
795
-
796
- 更多示例请查看 `examples/` 和 `test/` 目录:
797
-
798
- ```bash
799
- # 运行截屏示例
800
- node examples/screenshot-demo.js
801
-
802
- # 运行窗口列表示例
803
- node examples/list-windows.js
804
-
805
- # 运行剪贴板示例
806
- node examples/clipboard-demo.js
807
-
808
- # 运行图像处理示例
809
- node examples/image-processing-demo.js
810
-
811
- # 运行测试
812
- npm test
813
- ```
814
-
815
709
  ## 平台支持
816
710
 
817
711
  | 平台 | 架构 | 状态 | 备注 |
@@ -882,6 +776,17 @@ npm test
882
776
  - `Monitor.waitIcon(template, options?)` - 等待指定图标出现,超时抛出错误
883
777
  - `Monitor.clickText(text, options?)` - 点击指定文字
884
778
  - `Monitor.clickIcon(template, options?)` - 点击指定图标
779
+ - **Mouse 类增强**: 新增 `moveRel()` 方法
780
+ - `Mouse.moveRel(dx, dy, duration?)` - 基于当前鼠标位置进行相对移动
781
+ - 支持可选的 `duration` 参数实现平滑动画移动
782
+ - **CLI 命令增强**: 新增多个便捷命令
783
+ - `rpa mouse move-rel <dx> <dy>` - 相对移动鼠标
784
+ - `rpa clipboard paste-text` / `rpa clipboard paste-image` - 粘贴文本/图片并自动恢复剪贴板
785
+ - `rpa image find-text` / `rpa image recognize-text` - 图片 OCR 操作
786
+ - 顶层快捷命令: `rpa click`, `rpa move`, `rpa type`, `rpa press`, `rpa paste`, `rpa pause`
787
+ - **npm 包优化**: 子模块迁移至 `@alibot` scoped package
788
+ - 更清晰的包命名空间管理
789
+ - 自动同步子模块版本与主包版本
885
790
 
886
791
  #### BREAKCHANGE
887
792
 
@@ -889,15 +794,13 @@ npm test
889
794
  - 现在默认自动将图像缩放到逻辑像素尺寸,与 `getBounds()`/`getSize()` 返回的坐标一致
890
795
  - 如需物理像素图像,需显式传入 `autoSize: false`
891
796
  - 影响范围:所有依赖截图尺寸的逻辑(OCR、模板匹配等)现在默认使用逻辑坐标
797
+ - rpa部分命令简化
892
798
 
893
799
  #### 技术详情
894
800
 
895
- - 使用 `ocr-rs` crate 提供 PaddleOCR 功能
896
801
  - 使用 MNN 推理框架,提供高性能本地推理
897
802
  - 支持 GPU 加速(如果可用)
898
- - 模型文件需要自行下载放置在 `models/` 目录
899
-
900
- ## 更新日志
803
+ - OCR 模型内置于 npm 包中,开箱即用
901
804
 
902
805
  ### 0.1.7
903
806
 
package/bin/rpa.js CHANGED
@@ -153,6 +153,13 @@ mouse.command('move').description('移动鼠标到指定坐标')
153
153
  console.log(c.green(`鼠标已移动到 (${x}, ${y})`));
154
154
  });
155
155
 
156
+ mouse.command('move-rel').description('相对移动鼠标')
157
+ .argument('<dx>', 'X 轴偏移量').argument('<dy>', 'Y 轴偏移量')
158
+ .action(async (dx, dy) => {
159
+ await Mouse.moveRel(+dx, +dy);
160
+ console.log(c.green(`鼠标已相对移动 (${dx}, ${dy})`));
161
+ });
162
+
156
163
  mouse.command('click').description('点击鼠标')
157
164
  .argument('[button]', '按钮 (left/right/middle)', 'left')
158
165
  .option('--double', '双击')
package/index.d.ts CHANGED
@@ -45,6 +45,8 @@ export interface WaitOptions {
45
45
  regions?: Array<MatchRegion>
46
46
  /** 等待超时时间(毫秒),默认 3000 */
47
47
  timeout?: number
48
+ /** 匹配阈值 (0.0-1.0),低于此值视为未找到,默认 0.8(仅用于 waitIcon/clickIcon) */
49
+ threshold?: number
48
50
  }
49
51
  /** 图标匹配结果 */
50
52
  export interface MatchResult {
@@ -196,6 +198,13 @@ export declare class Mouse {
196
198
  * @param duration - 可选,移动动画持续时间(秒)。默认为 0,表示瞬间移动。如果设置 > 0,鼠标将以平滑动画的方式移动到目标点
197
199
  */
198
200
  static moveTo(x: number, y: number, duration?: number | null): Promise<void>
201
+ /**
202
+ * 相对移动鼠标
203
+ * @param dx - X 轴偏移量(正数向右,负数向左)
204
+ * @param dy - Y 轴偏移量(正数向下,负数向上)
205
+ * @param duration - 可选,移动动画持续时间(秒)。默认为 0,表示瞬间移动
206
+ */
207
+ static moveRel(dx: number, dy: number, duration?: number | null): Promise<void>
199
208
  /** 点击鼠标按钮。button 可选,可用 MouseButton.Left / 'left' 等,默认左键 */
200
209
  static click(button?: MouseButtonType | null): Promise<void>
201
210
  /** 双击鼠标按钮。button 取值同 click */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rust-rpa",
3
- "version": "0.2.0-beta.3",
3
+ "version": "0.2.0-beta.4",
4
4
  "description": "Rust-based RPA automation library for Node.js",
5
5
  "type": "commonjs",
6
6
  "main": "index.js",
@@ -69,9 +69,9 @@
69
69
  "commander": "^14.0.3"
70
70
  },
71
71
  "optionalDependencies": {
72
- "@alibot/rust-rpa-win32-x64-msvc": "0.2.0-beta.3",
73
- "@alibot/rust-rpa-win32-ia32-msvc": "0.2.0-beta.3",
74
- "@alibot/rust-rpa-darwin-x64": "0.2.0-beta.3",
75
- "@alibot/rust-rpa-darwin-arm64": "0.2.0-beta.3"
72
+ "@alibot/rust-rpa-win32-x64-msvc": "0.2.0-beta.4",
73
+ "@alibot/rust-rpa-win32-ia32-msvc": "0.2.0-beta.4",
74
+ "@alibot/rust-rpa-darwin-x64": "0.2.0-beta.4",
75
+ "@alibot/rust-rpa-darwin-arm64": "0.2.0-beta.4"
76
76
  }
77
77
  }