@aspiresys/visor 1.2.10 → 1.3.0

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/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Key, Button, Point } from "@nut-tree-fork/nut-js";
2
- import { Region } from "./types";
3
- export declare class Visor {
4
- mouse: import("@nut-tree-fork/nut-js").MouseClass;
5
- keyboard: import("@nut-tree-fork/nut-js").KeyboardClass;
2
+ import { Offset, Region } from "./types";
3
+ declare class Visor {
4
+ private mouse;
5
+ private keyboard;
6
6
  Key: typeof Key;
7
7
  Button: typeof Button;
8
8
  private configWarningShown;
@@ -32,10 +32,7 @@ export declare class Visor {
32
32
  * height: 50
33
33
  * });
34
34
  */
35
- moveToRegion(region: Region, offset?: {
36
- x: number;
37
- y: number;
38
- }): Promise<void>;
35
+ moveToRegion(region: Region, offset?: Offset): Promise<void>;
39
36
  /**
40
37
  * Performs a left mouse click at the
41
38
  * center of a specific screen region.
@@ -61,10 +58,7 @@ export declare class Visor {
61
58
  * height: 50
62
59
  * });
63
60
  */
64
- clickRegion(region: Region, offset?: {
65
- x: number;
66
- y: number;
67
- }): Promise<void>;
61
+ clickRegion(region: Region, offset?: Offset): Promise<void>;
68
62
  /**
69
63
  * Performs a double left mouse click
70
64
  * at the center of a specific
@@ -91,10 +85,7 @@ export declare class Visor {
91
85
  * height: 50
92
86
  * });
93
87
  */
94
- doubleClickRegion(region: Region, offset?: {
95
- x: number;
96
- y: number;
97
- }): Promise<void>;
88
+ doubleClickRegion(region: Region, offset?: Offset): Promise<void>;
98
89
  /**
99
90
  * Performs a right mouse click at the
100
91
  * center of a specific screen region.
@@ -120,10 +111,7 @@ export declare class Visor {
120
111
  * height: 50
121
112
  * });
122
113
  */
123
- rightClickRegion(region: Region, offset?: {
124
- x: number;
125
- y: number;
126
- }): Promise<void>;
114
+ rightClickRegion(region: Region, offset?: Offset): Promise<void>;
127
115
  /**
128
116
  * Finds an image on screen using OpenCV
129
117
  * and performs a left mouse click
@@ -154,10 +142,7 @@ export declare class Visor {
154
142
  * @example
155
143
  * await visor.click("./images/save.png", 0.9);
156
144
  */
157
- click(image?: string, confidence?: number, offset?: {
158
- x: number;
159
- y: number;
160
- }): Promise<void>;
145
+ click(image?: string, confidence?: number, offset?: Offset): Promise<void>;
161
146
  /**
162
147
  * Performs a right mouse click.
163
148
  *
@@ -182,10 +167,7 @@ export declare class Visor {
182
167
  * @example
183
168
  * await visor.rightClick();
184
169
  */
185
- rightClick(image?: string, confidence?: number, offset?: {
186
- x: number;
187
- y: number;
188
- }): Promise<void>;
170
+ rightClick(image?: string, confidence?: number, offset?: Offset): Promise<void>;
189
171
  /**
190
172
  * Performs a double left mouse click.
191
173
  *
@@ -211,10 +193,7 @@ export declare class Visor {
211
193
  * @example
212
194
  * await visor.doubleClick();
213
195
  */
214
- doubleClick(image?: string, confidence?: number, offset?: {
215
- x: number;
216
- y: number;
217
- }): Promise<void>;
196
+ doubleClick(image?: string, confidence?: number, offset?: Offset): Promise<void>;
218
197
  /**
219
198
  * Finds the best matching image on screen
220
199
  * using OpenCV template matching.
@@ -455,12 +434,7 @@ export declare class Visor {
455
434
  * const region =
456
435
  * await visor.findText("Submit");
457
436
  */
458
- findText(text: string, index?: number, region?: {
459
- x: number;
460
- y: number;
461
- width: number;
462
- height: number;
463
- }): Promise<Region>;
437
+ findText(text: string, index?: number, region?: Region): Promise<Region>;
464
438
  /**
465
439
  * Checks whether specific text exists
466
440
  * on screen using OCR.
@@ -474,12 +448,7 @@ export declare class Visor {
474
448
  * const exists =
475
449
  * await visor.existsText("Teams");
476
450
  */
477
- existsText(text: string, region?: {
478
- x: number;
479
- y: number;
480
- width: number;
481
- height: number;
482
- }): Promise<boolean>;
451
+ existsText(text: string, region?: Region): Promise<boolean>;
483
452
  /**
484
453
  * Performs OCR on a specific
485
454
  * screen region.
@@ -497,12 +466,7 @@ export declare class Visor {
497
466
  * height: 300
498
467
  * });
499
468
  */
500
- readRegion(region: {
501
- x: number;
502
- y: number;
503
- width: number;
504
- height: number;
505
- }): Promise<any>;
469
+ readRegion(region: Region): Promise<any>;
506
470
  /**
507
471
  * Performs OCR on the entire screen
508
472
  * using Tesseract OCR.
@@ -622,10 +586,7 @@ export declare class Visor {
622
586
  * @example
623
587
  * await visor.hover("menu.png");
624
588
  */
625
- hover(image?: string, confidence?: number, offset?: {
626
- x: number;
627
- y: number;
628
- }): Promise<void>;
589
+ hover(image: string, confidence?: number, offset?: Offset): Promise<void>;
629
590
  /**
630
591
  * Scrolls the mouse wheel downward.
631
592
  *
@@ -719,11 +680,12 @@ export declare class Visor {
719
680
  *
720
681
  * @param x X coordinate.
721
682
  * @param y Y coordinate.
683
+ * @param inspectorCoords Boolean to represent if the coords are from visor-inspector
722
684
  *
723
685
  * @example
724
686
  * await visor.moveMouse(500, 300);
725
687
  */
726
- moveMouse(x: number, y: number): Promise<void>;
688
+ moveMouse(x: number, y: number, inspectorCoords?: boolean): Promise<void>;
727
689
  /**
728
690
  * Returns the current mouse cursor
729
691
  * position.
@@ -1094,3 +1056,5 @@ export declare class Visor {
1094
1056
  input(message: string, title?: string): Promise<string>;
1095
1057
  }
1096
1058
  export declare const visor: Visor;
1059
+ export { Region } from "./types";
1060
+ export type { Offset } from "./types";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.visor = exports.Visor = void 0;
3
+ exports.Region = exports.visor = void 0;
4
4
  const screen_1 = require("./screen");
5
5
  const matcher_1 = require("./matcher");
6
6
  const mouse_1 = require("./mouse");
@@ -73,10 +73,7 @@ class Visor {
73
73
  * height: 50
74
74
  * });
75
75
  */
76
- async moveToRegion(region, offset = {
77
- x: 0,
78
- y: 0
79
- }) {
76
+ async moveToRegion(region, offset) {
80
77
  await (0, mouse_1.moveToRegion)(region, offset);
81
78
  }
82
79
  /**
@@ -104,10 +101,7 @@ class Visor {
104
101
  * height: 50
105
102
  * });
106
103
  */
107
- async clickRegion(region, offset = {
108
- x: 0,
109
- y: 0
110
- }) {
104
+ async clickRegion(region, offset) {
111
105
  await (0, mouse_1.moveToRegion)(region, offset);
112
106
  await this.mouse.click(this.Button.LEFT);
113
107
  }
@@ -137,10 +131,7 @@ class Visor {
137
131
  * height: 50
138
132
  * });
139
133
  */
140
- async doubleClickRegion(region, offset = {
141
- x: 0,
142
- y: 0
143
- }) {
134
+ async doubleClickRegion(region, offset) {
144
135
  await (0, mouse_1.moveToRegion)(region, offset);
145
136
  await this.mouse.doubleClick(this.Button.LEFT);
146
137
  }
@@ -169,10 +160,7 @@ class Visor {
169
160
  * height: 50
170
161
  * });
171
162
  */
172
- async rightClickRegion(region, offset = {
173
- x: 0,
174
- y: 0
175
- }) {
163
+ async rightClickRegion(region, offset) {
176
164
  await (0, mouse_1.moveToRegion)(region, offset);
177
165
  await this.mouse.click(this.Button.RIGHT);
178
166
  }
@@ -206,10 +194,7 @@ class Visor {
206
194
  * @example
207
195
  * await visor.click("./images/save.png", 0.9);
208
196
  */
209
- async click(image, confidence = 0.8, offset = {
210
- x: 0,
211
- y: 0
212
- }) {
197
+ async click(image, confidence = 0.8, offset) {
213
198
  this.checkConfig();
214
199
  if (!image) {
215
200
  await this.mouse.click(this.Button.LEFT);
@@ -247,10 +232,7 @@ class Visor {
247
232
  * @example
248
233
  * await visor.rightClick();
249
234
  */
250
- async rightClick(image, confidence = 0.8, offset = {
251
- x: 0,
252
- y: 0
253
- }) {
235
+ async rightClick(image, confidence = 0.8, offset) {
254
236
  this.checkConfig();
255
237
  if (image) {
256
238
  const region = await this.find(image, confidence);
@@ -287,10 +269,7 @@ class Visor {
287
269
  * @example
288
270
  * await visor.doubleClick();
289
271
  */
290
- async doubleClick(image, confidence = 0.8, offset = {
291
- x: 0,
292
- y: 0
293
- }) {
272
+ async doubleClick(image, confidence = 0.8, offset) {
294
273
  this.checkConfig();
295
274
  if (image) {
296
275
  const region = await this.find(image, confidence);
@@ -336,8 +315,12 @@ class Visor {
336
315
  const start = Date.now();
337
316
  const screen = await (0, screen_1.captureScreen)();
338
317
  const template = await (0, matcher_1.loadTemplate)((0, path_1.resolveImagePath)(image));
318
+ const scaleFactor = config_1.visorConfig.scaleFactor;
339
319
  try {
340
320
  const result = (0, matcher_1.matchTemplate)(screen, template, confidence);
321
+ if (result) {
322
+ (0, logger_1.log)(`[FIND] Actual coords: (${Math.floor(result.x * scaleFactor)}, ${Math.floor(result.y * scaleFactor)})`);
323
+ }
341
324
  (0, logger_1.log)(`[FIND] Total: ${Date.now() - start} ms`);
342
325
  return result;
343
326
  }
@@ -811,10 +794,7 @@ CONF:${m.confidence.toFixed(3)}
811
794
  * @example
812
795
  * await visor.hover("menu.png");
813
796
  */
814
- async hover(image, confidence = 0.8, offset = {
815
- x: 0,
816
- y: 0
817
- }) {
797
+ async hover(image, confidence = 0.8, offset) {
818
798
  this.checkConfig();
819
799
  const region = await this.find(image, confidence);
820
800
  if (!region) {
@@ -929,13 +909,19 @@ CONF:${m.confidence.toFixed(3)}
929
909
  *
930
910
  * @param x X coordinate.
931
911
  * @param y Y coordinate.
912
+ * @param inspectorCoords Boolean to represent if the coords are from visor-inspector
932
913
  *
933
914
  * @example
934
915
  * await visor.moveMouse(500, 300);
935
916
  */
936
- async moveMouse(x, y) {
917
+ async moveMouse(x, y, inspectorCoords = false) {
937
918
  this.checkConfig();
938
- await this.mouse.move((0, nut_js_1.straightTo)(new nut_js_1.Point(x, y)));
919
+ if (inspectorCoords) {
920
+ await this.mouse.move((0, nut_js_1.straightTo)(new nut_js_1.Point(x, y)));
921
+ return;
922
+ }
923
+ const scaleFactor = config_1.visorConfig.scaleFactor;
924
+ await this.mouse.move((0, nut_js_1.straightTo)(new nut_js_1.Point(Math.floor(x / scaleFactor), Math.floor(y / scaleFactor))));
939
925
  }
940
926
  /**
941
927
  * Returns the current mouse cursor
@@ -1402,5 +1388,6 @@ CONF:${m.confidence.toFixed(3)}
1402
1388
  return await (0, dialog_1.prompt)(message, title);
1403
1389
  }
1404
1390
  }
1405
- exports.Visor = Visor;
1406
1391
  exports.visor = new Visor();
1392
+ var types_1 = require("./types");
1393
+ Object.defineProperty(exports, "Region", { enumerable: true, get: function () { return types_1.Region; } });
package/dist/matcher.d.ts CHANGED
@@ -3,3 +3,6 @@ export declare function loadTemplate(path: string): Promise<any>;
3
3
  export declare function loadScreen(path: string): Promise<any>;
4
4
  export declare function matchTemplate(screen: any, template: any, confidence?: number): Region | null;
5
5
  export declare function findAllMatches(screen: any, template: any, confidence?: number): Region[];
6
+ export declare function findAllInspectorMatches(screen: any, template: any, confidence?: number): Region[];
7
+ export declare function matchInspectorTemplate(screen: any, template: any, confidence?: number, multiScale?: boolean): Region | null;
8
+ export declare function cropMat(screen: any, region: Region): any;
package/dist/matcher.js CHANGED
@@ -7,10 +7,14 @@ exports.loadTemplate = loadTemplate;
7
7
  exports.loadScreen = loadScreen;
8
8
  exports.matchTemplate = matchTemplate;
9
9
  exports.findAllMatches = findAllMatches;
10
+ exports.findAllInspectorMatches = findAllInspectorMatches;
11
+ exports.matchInspectorTemplate = matchInspectorTemplate;
12
+ exports.cropMat = cropMat;
10
13
  const fs_1 = __importDefault(require("fs"));
11
14
  const pngjs_1 = require("pngjs");
12
15
  const cv = require("@techstark/opencv-js");
13
16
  const templateCache = new Map();
17
+ const types_1 = require("./types");
14
18
  const logger_1 = require("./logger");
15
19
  async function loadTemplate(path) {
16
20
  if (templateCache.has(path)) {
@@ -62,13 +66,7 @@ function matchTemplate(screen, template, confidence = 0.8) {
62
66
  (0, logger_1.log)(`[MATCH] Scale ${scale} -> ${maxVal}`);
63
67
  result.delete();
64
68
  if (maxVal >= confidence && (!bestMatch || maxVal > bestMatch.confidence)) {
65
- bestMatch = {
66
- x: maxLoc.x,
67
- y: maxLoc.y,
68
- width: resizedTemplate.cols,
69
- height: resizedTemplate.rows,
70
- confidence: maxVal,
71
- };
69
+ bestMatch = new types_1.Region(maxLoc.x, maxLoc.y, resizedTemplate.cols, resizedTemplate.rows, maxVal);
72
70
  if (maxVal >= 0.98) {
73
71
  resizedTemplate.delete();
74
72
  (0, logger_1.log)(`[MATCH] Total: ${Date.now() - start} ms`);
@@ -88,13 +86,7 @@ function findAllMatches(screen, template, confidence = 0.8) {
88
86
  for (let x = 0; x < result.cols; x++) {
89
87
  const score = result.floatAt(y, x);
90
88
  if (score >= confidence) {
91
- matches.push({
92
- x,
93
- y,
94
- width: template.cols,
95
- height: template.rows,
96
- confidence: score,
97
- });
89
+ matches.push(new types_1.Region(x, y, template.cols, template.rows, score));
98
90
  }
99
91
  }
100
92
  }
@@ -113,3 +105,83 @@ function findAllMatches(screen, template, confidence = 0.8) {
113
105
  result.delete();
114
106
  return filtered;
115
107
  }
108
+ function findAllInspectorMatches(screen, template, confidence = 0.8) {
109
+ const result = new cv.Mat();
110
+ cv.matchTemplate(screen, template, result, cv.TM_CCOEFF_NORMED);
111
+ const matches = [];
112
+ for (let y = 0; y < result.rows; y++) {
113
+ for (let x = 0; x < result.cols; x++) {
114
+ const score = result.floatAt(y, x);
115
+ if (score >= confidence) {
116
+ matches.push(new types_1.Region(x, y, template.cols, template.rows, score));
117
+ }
118
+ }
119
+ }
120
+ const filtered = [];
121
+ for (const match of matches) {
122
+ const tooClose = filtered.some((existing) => {
123
+ const dx = Math.abs(existing.x - match.x);
124
+ const dy = Math.abs(existing.y - match.y);
125
+ return dx < 10 && dy < 10;
126
+ });
127
+ if (!tooClose) {
128
+ filtered.push(match);
129
+ }
130
+ }
131
+ result.delete();
132
+ return filtered;
133
+ }
134
+ function matchInspectorTemplate(screen, template, confidence = 0.8, multiScale = false) {
135
+ if (multiScale) {
136
+ const start = Date.now();
137
+ const scales = [1.0, 0.9, 1.1, 0.8, 1.2, 0.7, 1.3, 0.6, 1.4, 0.5, 1.5];
138
+ let bestMatch = null;
139
+ for (const scale of scales) {
140
+ const resizedTemplate = resizeTemplate(template, scale);
141
+ if (resizedTemplate.cols > screen.cols ||
142
+ resizedTemplate.rows > screen.rows) {
143
+ resizedTemplate.delete();
144
+ continue;
145
+ }
146
+ const result = new cv.Mat();
147
+ cv.matchTemplate(screen, resizedTemplate, result, cv.TM_CCOEFF_NORMED);
148
+ const { maxLoc, maxVal } = cv.minMaxLoc(result);
149
+ (0, logger_1.log)(`[MATCH] Scale ${scale} -> ${maxVal}`);
150
+ result.delete();
151
+ if (maxVal >= confidence && (!bestMatch || maxVal > bestMatch.confidence)) {
152
+ bestMatch = new types_1.Region(maxLoc.x, maxLoc.y, resizedTemplate.cols, resizedTemplate.rows, maxVal);
153
+ if (maxVal >= 0.98) {
154
+ resizedTemplate.delete();
155
+ (0, logger_1.log)(`[MATCH] Total: ${Date.now() - start} ms`);
156
+ return bestMatch;
157
+ }
158
+ }
159
+ resizedTemplate.delete();
160
+ }
161
+ (0, logger_1.log)(`[MATCH] Total: ${Date.now() - start} ms`);
162
+ return bestMatch;
163
+ }
164
+ else {
165
+ const start = Date.now();
166
+ const result = new cv.Mat();
167
+ cv.matchTemplate(screen, template, result, cv.TM_CCOEFF_NORMED);
168
+ const { maxLoc, maxVal } = cv.minMaxLoc(result);
169
+ result.delete();
170
+ if (maxVal >= confidence) {
171
+ return new types_1.Region(maxLoc.x, maxLoc.y, template.cols, template.rows, maxVal);
172
+ }
173
+ (0, logger_1.log)(`[MATCH] Total: ${Date.now() - start} ms`);
174
+ return null;
175
+ }
176
+ }
177
+ function cropMat(screen, region) {
178
+ const x = Math.max(0, Math.floor(region.x));
179
+ const y = Math.max(0, Math.floor(region.y));
180
+ const width = Math.min(Math.floor(region.width), screen.cols - x);
181
+ const height = Math.min(Math.floor(region.height), screen.rows - y);
182
+ const rect = new cv.Rect(x, y, width, height);
183
+ const croppedMat = screen.roi(rect);
184
+ const isolatedMat = croppedMat.clone();
185
+ croppedMat.delete();
186
+ return isolatedMat;
187
+ }
package/dist/mouse.d.ts CHANGED
@@ -1,9 +1,3 @@
1
- import { Region } from "./types";
2
- export declare function moveToRegion(region: Region, offset?: {
3
- x: number;
4
- y: number;
5
- }): Promise<void>;
6
- export declare function clickRegion(region: Region, offset?: {
7
- x: number;
8
- y: number;
9
- }): Promise<void>;
1
+ import { Offset, Region } from "./types";
2
+ export declare function moveToRegion(region: Region, offset?: Offset): Promise<void>;
3
+ export declare function clickRegion(region: Region, offset?: Offset): Promise<void>;
package/dist/mouse.js CHANGED
@@ -10,8 +10,9 @@ async function moveToRegion(region, offset = {
10
10
  y: 0
11
11
  }) {
12
12
  const scaleFactor = config_1.visorConfig.scaleFactor;
13
- const centerX = Math.floor((region.x + region.width / 2 + offset.x) / scaleFactor);
14
- const centerY = Math.floor((region.y + region.height / 2 + offset.y) / scaleFactor);
13
+ const center = region.center();
14
+ const centerX = Math.floor((center.x + offset.x) / scaleFactor);
15
+ const centerY = Math.floor((center.y + offset.y) / scaleFactor);
15
16
  (0, logger_1.log)("[MOUSE] Moving mouse to:", centerX, centerY);
16
17
  await nut_js_1.mouse.move([new nut_js_1.Point(centerX, centerY)]);
17
18
  }
package/dist/ocr.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Region } from "./types";
1
2
  /**
2
3
  * Terminates OCR worker manually.
3
4
  *
@@ -15,9 +16,4 @@ export declare function terminateOCR(): Promise<void>;
15
16
  * - sharp preprocessing
16
17
  * - Tesseract OCR
17
18
  */
18
- export declare function extractTextFromRegion(region?: {
19
- x: number;
20
- y: number;
21
- width: number;
22
- height: number;
23
- }): Promise<any>;
19
+ export declare function extractTextFromRegion(region?: Region): Promise<any>;
@@ -0,0 +1,9 @@
1
+ export declare class Region {
2
+ x: number;
3
+ y: number;
4
+ width: number;
5
+ height: number;
6
+ confidence: number;
7
+ constructor(x: number, y: number, width: number, height: number, confidence?: number);
8
+ center(): void;
9
+ }
package/dist/region.js ADDED
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Region = void 0;
4
+ class Region {
5
+ constructor(x, y, width, height, confidence = 1) {
6
+ this.x = x;
7
+ this.y = y;
8
+ this.width = width;
9
+ this.height = height;
10
+ this.confidence = confidence;
11
+ }
12
+ center() {
13
+ }
14
+ }
15
+ exports.Region = Region;
package/dist/text.d.ts CHANGED
@@ -1,13 +1,3 @@
1
1
  import { Region } from "./types";
2
- export declare function findText(text: string, index?: number, region?: {
3
- x: number;
4
- y: number;
5
- width: number;
6
- height: number;
7
- }): Promise<Region | null>;
8
- export declare function existsText(text: string, region?: {
9
- x: number;
10
- y: number;
11
- width: number;
12
- height: number;
13
- }): Promise<boolean>;
2
+ export declare function findText(text: string, index?: number, region?: Region): Promise<Region | null>;
3
+ export declare function existsText(text: string, region?: Region): Promise<boolean>;
package/dist/text.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.findText = findText;
4
4
  exports.existsText = existsText;
5
5
  const ocr_1 = require("./ocr");
6
+ const types_1 = require("./types");
6
7
  async function findText(text, index = 0, region) {
7
8
  const result = await (0, ocr_1.extractTextFromRegion)(region);
8
9
  const tsv = result.tsv;
@@ -62,13 +63,7 @@ async function findText(text, index = 0, region) {
62
63
  const maxX = Math.max(...regionWords.map((w) => w.x + w.width));
63
64
  const maxY = Math.max(...regionWords.map((w) => w.y + w.height));
64
65
  const avgConfidence = words.reduce((sum, w) => sum + w.confidence, 0) / words.length;
65
- matches.push({
66
- x: minX,
67
- y: minY,
68
- width: maxX - minX,
69
- height: maxY - minY,
70
- confidence: avgConfidence,
71
- });
66
+ matches.push(new types_1.Region(minX, minY, maxX - minX, maxY - minY, avgConfidence));
72
67
  }
73
68
  }
74
69
  matches.sort((a, b) => a.y - b.y || a.x - b.x);