@aspiresys/visor 1.1.9 → 1.1.10
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/dist/app.d.ts +2 -0
- package/dist/app.js +22 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.js +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +78 -0
- package/package.json +1 -1
package/dist/app.d.ts
CHANGED
|
@@ -43,3 +43,5 @@ export declare function openApp(target: string): Promise<void>;
|
|
|
43
43
|
* await closeApp("ms-teams.exe");
|
|
44
44
|
*/
|
|
45
45
|
export declare function closeApp(processName: string): Promise<void>;
|
|
46
|
+
export declare function execCommand(command: string): Promise<string>;
|
|
47
|
+
export declare function execDetached(command: string): Promise<void>;
|
package/dist/app.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.openApp = openApp;
|
|
4
4
|
exports.closeApp = closeApp;
|
|
5
|
+
exports.execCommand = execCommand;
|
|
6
|
+
exports.execDetached = execDetached;
|
|
5
7
|
const child_process_1 = require("child_process");
|
|
6
8
|
const logger_1 = require("./logger");
|
|
7
9
|
function execAsync(command) {
|
|
@@ -98,3 +100,23 @@ async function closeApp(processName) {
|
|
|
98
100
|
});
|
|
99
101
|
});
|
|
100
102
|
}
|
|
103
|
+
async function execCommand(command) {
|
|
104
|
+
(0, logger_1.log)(`[CMD] Executing: ${command}`);
|
|
105
|
+
return new Promise((resolve, reject) => {
|
|
106
|
+
(0, child_process_1.exec)(command, (error, stdout, stderr) => {
|
|
107
|
+
if (error) {
|
|
108
|
+
reject(new Error(stderr || error.message));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
resolve(stdout.trim());
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
async function execDetached(command) {
|
|
116
|
+
(0, logger_1.log)(`[CMD] Starting detached: ${command}`);
|
|
117
|
+
(0, child_process_1.spawn)(command, [], {
|
|
118
|
+
detached: true,
|
|
119
|
+
shell: true,
|
|
120
|
+
stdio: "ignore",
|
|
121
|
+
}).unref();
|
|
122
|
+
}
|
package/dist/config.d.ts
CHANGED
package/dist/config.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export declare class Visor {
|
|
|
4
4
|
keyboard: import("@nut-tree-fork/nut-js").KeyboardClass;
|
|
5
5
|
Key: typeof Key;
|
|
6
6
|
Button: typeof Button;
|
|
7
|
+
private configWarningShown;
|
|
8
|
+
private checkConfig;
|
|
7
9
|
/**
|
|
8
10
|
* Finds an image on screen using OpenCV
|
|
9
11
|
* and performs a left mouse click
|
|
@@ -903,5 +905,23 @@ export declare class Visor {
|
|
|
903
905
|
* await visor.terminateOCR();
|
|
904
906
|
*/
|
|
905
907
|
terminateOCR(): Promise<void>;
|
|
908
|
+
/**
|
|
909
|
+
* Executes a command and returns output.
|
|
910
|
+
*
|
|
911
|
+
* @example
|
|
912
|
+
* const output =
|
|
913
|
+
* await visor.exec("ipconfig");
|
|
914
|
+
*/
|
|
915
|
+
exec(command: string): Promise<string>;
|
|
916
|
+
/**
|
|
917
|
+
* Starts a command without waiting
|
|
918
|
+
* for completion.
|
|
919
|
+
*
|
|
920
|
+
* @example
|
|
921
|
+
* await visor.execDetached(
|
|
922
|
+
* "notepad"
|
|
923
|
+
* );
|
|
924
|
+
*/
|
|
925
|
+
execDetached(command: string): Promise<void>;
|
|
906
926
|
}
|
|
907
927
|
export declare const visor: Visor;
|
package/dist/index.js
CHANGED
|
@@ -12,12 +12,40 @@ const nut_js_1 = require("@nut-tree-fork/nut-js");
|
|
|
12
12
|
const path_1 = require("./path");
|
|
13
13
|
const display_1 = require("./display");
|
|
14
14
|
const logger_1 = require("./logger");
|
|
15
|
+
const console_1 = require("console");
|
|
15
16
|
class Visor {
|
|
16
17
|
constructor() {
|
|
17
18
|
this.mouse = nut_js_1.mouse;
|
|
18
19
|
this.keyboard = nut_js_1.keyboard;
|
|
19
20
|
this.Key = nut_js_1.Key;
|
|
20
21
|
this.Button = nut_js_1.Button;
|
|
22
|
+
this.configWarningShown = false;
|
|
23
|
+
}
|
|
24
|
+
checkConfig() {
|
|
25
|
+
if (this.configWarningShown) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const missing = [];
|
|
29
|
+
if (!config_1.visorConfig.imagePath) {
|
|
30
|
+
missing.push("imagePath");
|
|
31
|
+
}
|
|
32
|
+
if (!config_1.visorConfig.outputPath) {
|
|
33
|
+
missing.push("outputPath");
|
|
34
|
+
}
|
|
35
|
+
if (missing.length > 0) {
|
|
36
|
+
(0, console_1.warn)(`[VISOR] Configuration incomplete.\n` +
|
|
37
|
+
`Missing: ${missing.join(", ")}\n\n` +
|
|
38
|
+
`Relative paths may not work correctly.\n` +
|
|
39
|
+
`Use visor.loadConfig(...) or provide absolute paths directly to functions.`);
|
|
40
|
+
}
|
|
41
|
+
if (!config_1.visorConfig.initialized) {
|
|
42
|
+
config_1.visorConfig.scaleFactor = (0, display_1.getWindowsScaleFactor)();
|
|
43
|
+
(0, console_1.warn)(`[VISOR] Configuration not loaded.\n` +
|
|
44
|
+
`Auto-detected scaleFactor=${config_1.visorConfig.scaleFactor}.\n`);
|
|
45
|
+
}
|
|
46
|
+
if (missing.length > 0 || !config_1.visorConfig.initialized) {
|
|
47
|
+
this.configWarningShown = true;
|
|
48
|
+
}
|
|
21
49
|
}
|
|
22
50
|
/**
|
|
23
51
|
* Finds an image on screen using OpenCV
|
|
@@ -50,6 +78,7 @@ class Visor {
|
|
|
50
78
|
* await visor.click("./images/save.png", 0.9);
|
|
51
79
|
*/
|
|
52
80
|
async click(image, confidence = 0.8) {
|
|
81
|
+
this.checkConfig();
|
|
53
82
|
if (!image) {
|
|
54
83
|
await this.mouse.click(this.Button.LEFT);
|
|
55
84
|
(0, logger_1.log)("[MOUSE] Left click completed");
|
|
@@ -87,6 +116,7 @@ class Visor {
|
|
|
87
116
|
* await visor.rightClick();
|
|
88
117
|
*/
|
|
89
118
|
async rightClick(image, confidence = 0.8) {
|
|
119
|
+
this.checkConfig();
|
|
90
120
|
if (image) {
|
|
91
121
|
const region = await this.find(image, confidence);
|
|
92
122
|
if (!region) {
|
|
@@ -123,6 +153,7 @@ class Visor {
|
|
|
123
153
|
* await visor.doubleClick();
|
|
124
154
|
*/
|
|
125
155
|
async doubleClick(image, confidence = 0.8) {
|
|
156
|
+
this.checkConfig();
|
|
126
157
|
if (image) {
|
|
127
158
|
const region = await this.find(image, confidence);
|
|
128
159
|
if (!region) {
|
|
@@ -163,6 +194,7 @@ class Visor {
|
|
|
163
194
|
* await visor.find("save.png");
|
|
164
195
|
*/
|
|
165
196
|
async find(image, confidence = 0.8) {
|
|
197
|
+
this.checkConfig();
|
|
166
198
|
const start = Date.now();
|
|
167
199
|
const screen = await (0, screen_1.captureScreen)();
|
|
168
200
|
const template = await (0, matcher_1.loadTemplate)((0, path_1.resolveImagePath)(image));
|
|
@@ -196,6 +228,7 @@ class Visor {
|
|
|
196
228
|
* await visor.exists("login.png");
|
|
197
229
|
*/
|
|
198
230
|
async exists(image, confidence = 0.8) {
|
|
231
|
+
this.checkConfig();
|
|
199
232
|
return (await this.find(image, confidence)) !== null;
|
|
200
233
|
}
|
|
201
234
|
/**
|
|
@@ -221,6 +254,7 @@ class Visor {
|
|
|
221
254
|
* await visor.findAll("icon.png");
|
|
222
255
|
*/
|
|
223
256
|
async findAll(image, confidence = 0.8) {
|
|
257
|
+
this.checkConfig();
|
|
224
258
|
const screen = await (0, screen_1.captureScreen)();
|
|
225
259
|
const template = await (0, matcher_1.loadTemplate)((0, path_1.resolveImagePath)(image));
|
|
226
260
|
try {
|
|
@@ -254,6 +288,7 @@ class Visor {
|
|
|
254
288
|
* await visor.previewMatches("button.png");
|
|
255
289
|
*/
|
|
256
290
|
async previewMatches(image, confidence = 0.8) {
|
|
291
|
+
this.checkConfig();
|
|
257
292
|
const matches = await this.findAll(image, confidence);
|
|
258
293
|
(0, logger_1.log)("\n=== MATCH PREVIEW ===\n");
|
|
259
294
|
matches.forEach((m, i) => {
|
|
@@ -301,6 +336,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
301
336
|
* await visor.wait("loading-done.png");
|
|
302
337
|
*/
|
|
303
338
|
async wait(image, { confidence = 0.8, timeout = 5000 } = {}) {
|
|
339
|
+
this.checkConfig();
|
|
304
340
|
const interval = 300;
|
|
305
341
|
const attempts = Math.ceil(timeout / interval);
|
|
306
342
|
for (let i = 0; i < attempts; i++) {
|
|
@@ -337,6 +373,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
337
373
|
* await visor.waitToVanish("spinner.png");
|
|
338
374
|
*/
|
|
339
375
|
async waitToVanish(image, { confidence = 0.8, timeout = 5000 } = {}) {
|
|
376
|
+
this.checkConfig();
|
|
340
377
|
const start = Date.now();
|
|
341
378
|
while (Date.now() - start < timeout) {
|
|
342
379
|
if (!(await this.exists(image, confidence))) {
|
|
@@ -372,6 +409,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
372
409
|
* await visor.waitText("Success");
|
|
373
410
|
*/
|
|
374
411
|
async waitText(text, timeout = 5000) {
|
|
412
|
+
this.checkConfig();
|
|
375
413
|
const start = Date.now();
|
|
376
414
|
while (Date.now() - start < timeout) {
|
|
377
415
|
if (await this.existsText(text)) {
|
|
@@ -405,6 +443,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
405
443
|
* await visor.waitTextToVanish("Loading");
|
|
406
444
|
*/
|
|
407
445
|
async waitTextToVanish(text, timeout = 5000) {
|
|
446
|
+
this.checkConfig();
|
|
408
447
|
const start = Date.now();
|
|
409
448
|
while (Date.now() - start < timeout) {
|
|
410
449
|
if (!(await this.existsText(text))) {
|
|
@@ -428,6 +467,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
428
467
|
* await visor.clickText("Login");
|
|
429
468
|
*/
|
|
430
469
|
async clickText(text, index = 0) {
|
|
470
|
+
this.checkConfig();
|
|
431
471
|
const region = await (0, text_1.findText)(text, index);
|
|
432
472
|
if (!region) {
|
|
433
473
|
throw new Error(`Text not found: ${text}`);
|
|
@@ -449,6 +489,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
449
489
|
* await visor.findText("Submit");
|
|
450
490
|
*/
|
|
451
491
|
async findText(text, index = 0, region) {
|
|
492
|
+
this.checkConfig();
|
|
452
493
|
return await (0, text_1.findText)(text, index, region);
|
|
453
494
|
}
|
|
454
495
|
/**
|
|
@@ -465,6 +506,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
465
506
|
* await visor.existsText("Teams");
|
|
466
507
|
*/
|
|
467
508
|
async existsText(text, region) {
|
|
509
|
+
this.checkConfig();
|
|
468
510
|
return await (0, text_1.existsText)(text, region);
|
|
469
511
|
}
|
|
470
512
|
/**
|
|
@@ -485,6 +527,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
485
527
|
* });
|
|
486
528
|
*/
|
|
487
529
|
async readRegion(region) {
|
|
530
|
+
this.checkConfig();
|
|
488
531
|
return await (0, ocr_1.extractTextFromRegion)(region);
|
|
489
532
|
}
|
|
490
533
|
/**
|
|
@@ -519,6 +562,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
519
562
|
* log(result.text);
|
|
520
563
|
*/
|
|
521
564
|
async readScreen() {
|
|
565
|
+
this.checkConfig();
|
|
522
566
|
return await (0, ocr_1.extractTextFromRegion)();
|
|
523
567
|
}
|
|
524
568
|
/**
|
|
@@ -537,6 +581,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
537
581
|
* );
|
|
538
582
|
*/
|
|
539
583
|
async captureScreenshot(path) {
|
|
584
|
+
this.checkConfig();
|
|
540
585
|
path = config_1.visorConfig.outputPath + "/" + path;
|
|
541
586
|
(0, logger_1.log)(`[VISOR] Saving screenshot: ${path}`);
|
|
542
587
|
await (0, screen_1.saveScreenshot)(path);
|
|
@@ -597,6 +642,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
597
642
|
* );
|
|
598
643
|
*/
|
|
599
644
|
async dragDrop(source, target, confidence = 0.8) {
|
|
645
|
+
this.checkConfig();
|
|
600
646
|
const src = await this.find(source, confidence);
|
|
601
647
|
const dst = await this.find(target, confidence);
|
|
602
648
|
if (!src || !dst) {
|
|
@@ -628,6 +674,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
628
674
|
* await visor.hover("menu.png");
|
|
629
675
|
*/
|
|
630
676
|
async hover(image, confidence = 0.8) {
|
|
677
|
+
this.checkConfig();
|
|
631
678
|
const region = await this.find(image, confidence);
|
|
632
679
|
if (!region) {
|
|
633
680
|
throw new Error(`Image not found: ${image}`);
|
|
@@ -650,6 +697,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
650
697
|
* await visor.scrollDown(1000);
|
|
651
698
|
*/
|
|
652
699
|
async scrollDown(amount = 500) {
|
|
700
|
+
this.checkConfig();
|
|
653
701
|
await this.mouse.scrollDown(amount);
|
|
654
702
|
}
|
|
655
703
|
/**
|
|
@@ -667,6 +715,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
667
715
|
* await visor.scrollUp(1000);
|
|
668
716
|
*/
|
|
669
717
|
async scrollUp(amount = 500) {
|
|
718
|
+
this.checkConfig();
|
|
670
719
|
await this.mouse.scrollUp(amount);
|
|
671
720
|
}
|
|
672
721
|
/**
|
|
@@ -744,6 +793,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
744
793
|
* await visor.moveMouse(500, 300);
|
|
745
794
|
*/
|
|
746
795
|
async moveMouse(x, y) {
|
|
796
|
+
this.checkConfig();
|
|
747
797
|
await this.mouse.move((0, nut_js_1.straightTo)(new nut_js_1.Point(x, y)));
|
|
748
798
|
}
|
|
749
799
|
/**
|
|
@@ -757,6 +807,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
757
807
|
* await visor.getMousePosition();
|
|
758
808
|
*/
|
|
759
809
|
async getMousePosition() {
|
|
810
|
+
this.checkConfig();
|
|
760
811
|
return await this.mouse.getPosition();
|
|
761
812
|
}
|
|
762
813
|
/**
|
|
@@ -923,6 +974,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
923
974
|
if (config.debug !== undefined) {
|
|
924
975
|
this.setDebug(config.debug);
|
|
925
976
|
}
|
|
977
|
+
config_1.visorConfig.initialized = true;
|
|
926
978
|
(0, logger_1.log)("[VISOR] Config loaded");
|
|
927
979
|
}
|
|
928
980
|
/**
|
|
@@ -954,6 +1006,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
954
1006
|
* ]);
|
|
955
1007
|
*/
|
|
956
1008
|
async findAny(images, confidence = 0.8) {
|
|
1009
|
+
this.checkConfig();
|
|
957
1010
|
const screen = await (0, screen_1.captureScreen)();
|
|
958
1011
|
try {
|
|
959
1012
|
for (const image of images) {
|
|
@@ -1005,6 +1058,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
1005
1058
|
* ]);
|
|
1006
1059
|
*/
|
|
1007
1060
|
async existsAny(images, confidence = 0.8) {
|
|
1061
|
+
this.checkConfig();
|
|
1008
1062
|
return (await this.findAny(images, confidence)) !== null;
|
|
1009
1063
|
}
|
|
1010
1064
|
/**
|
|
@@ -1047,6 +1101,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
1047
1101
|
* ]);
|
|
1048
1102
|
*/
|
|
1049
1103
|
async clickAny(images, confidence = 0.8) {
|
|
1104
|
+
this.checkConfig();
|
|
1050
1105
|
const result = await this.findAny(images, confidence);
|
|
1051
1106
|
if (!result) {
|
|
1052
1107
|
throw new Error(`None of the images were found`);
|
|
@@ -1101,6 +1156,7 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
1101
1156
|
* ]);
|
|
1102
1157
|
*/
|
|
1103
1158
|
async waitAny(images, { confidence = 0.8, timeout = 5000 } = {}) {
|
|
1159
|
+
this.checkConfig();
|
|
1104
1160
|
const interval = 300;
|
|
1105
1161
|
const attempts = Math.ceil(timeout / interval);
|
|
1106
1162
|
for (let i = 0; i < attempts; i++) {
|
|
@@ -1133,6 +1189,28 @@ CONF:${m.confidence.toFixed(3)}
|
|
|
1133
1189
|
async terminateOCR() {
|
|
1134
1190
|
await (0, ocr_1.terminateOCR)();
|
|
1135
1191
|
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Executes a command and returns output.
|
|
1194
|
+
*
|
|
1195
|
+
* @example
|
|
1196
|
+
* const output =
|
|
1197
|
+
* await visor.exec("ipconfig");
|
|
1198
|
+
*/
|
|
1199
|
+
async exec(command) {
|
|
1200
|
+
return await (0, app_1.execCommand)(command);
|
|
1201
|
+
}
|
|
1202
|
+
/**
|
|
1203
|
+
* Starts a command without waiting
|
|
1204
|
+
* for completion.
|
|
1205
|
+
*
|
|
1206
|
+
* @example
|
|
1207
|
+
* await visor.execDetached(
|
|
1208
|
+
* "notepad"
|
|
1209
|
+
* );
|
|
1210
|
+
*/
|
|
1211
|
+
async execDetached(command) {
|
|
1212
|
+
await (0, app_1.execDetached)(command);
|
|
1213
|
+
}
|
|
1136
1214
|
}
|
|
1137
1215
|
exports.Visor = Visor;
|
|
1138
1216
|
exports.visor = new Visor();
|