feat(automation): add OS-level screen automation foundation services
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
import { screen, Region } from '@nut-tree-fork/nut-js';
|
||||
import type { ScreenRegion } from '../../../domain/value-objects/ScreenRegion';
|
||||
import type { ScreenCaptureResult } from '../../../application/ports/IScreenAutomation';
|
||||
import type { ILogger } from '../../../application/ports/ILogger';
|
||||
import { NoOpLogAdapter } from '../logging/NoOpLogAdapter';
|
||||
|
||||
/**
|
||||
* Service for capturing screen regions using nut.js.
|
||||
* Provides screen capture functionality for template matching and visual automation.
|
||||
*/
|
||||
export class ScreenRecognitionService {
|
||||
private logger: ILogger;
|
||||
|
||||
constructor(logger?: ILogger) {
|
||||
this.logger = logger ?? new NoOpLogAdapter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture the entire screen.
|
||||
* @returns ScreenCaptureResult with image buffer data
|
||||
*/
|
||||
async captureFullScreen(): Promise<ScreenCaptureResult> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
const width = await screen.width();
|
||||
const height = await screen.height();
|
||||
|
||||
this.logger.debug('Capturing full screen', { width, height });
|
||||
|
||||
const image = await screen.grab();
|
||||
const data = await image.toRGB();
|
||||
|
||||
const durationMs = Date.now() - startTime;
|
||||
this.logger.debug('Screen capture completed', { durationMs, width, height });
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: Buffer.from(data.data),
|
||||
width: data.width,
|
||||
height: data.height,
|
||||
};
|
||||
} catch (error) {
|
||||
const errorMsg = `Screen capture failed: ${error}`;
|
||||
this.logger.error('Screen capture failed', error instanceof Error ? error : new Error(errorMsg));
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: errorMsg,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture a specific region of the screen.
|
||||
* @param region - The rectangular region to capture
|
||||
* @returns ScreenCaptureResult with image buffer data
|
||||
*/
|
||||
async captureRegion(region: ScreenRegion): Promise<ScreenCaptureResult> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
this.logger.debug('Capturing screen region', { region });
|
||||
|
||||
const nutRegion = new Region(region.x, region.y, region.width, region.height);
|
||||
const image = await screen.grabRegion(nutRegion);
|
||||
const data = await image.toRGB();
|
||||
|
||||
const durationMs = Date.now() - startTime;
|
||||
this.logger.debug('Region capture completed', { durationMs, region });
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: Buffer.from(data.data),
|
||||
width: data.width,
|
||||
height: data.height,
|
||||
};
|
||||
} catch (error) {
|
||||
const errorMsg = `Region capture failed: ${error}`;
|
||||
this.logger.error('Region capture failed', error instanceof Error ? error : new Error(errorMsg), { region });
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: errorMsg,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current screen dimensions.
|
||||
* @returns Object with width and height, or null on error
|
||||
*/
|
||||
async getScreenDimensions(): Promise<{ width: number; height: number } | null> {
|
||||
try {
|
||||
const width = await screen.width();
|
||||
const height = await screen.height();
|
||||
return { width, height };
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to get screen dimensions', error instanceof Error ? error : new Error(String(error)));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert ScreenRegion to nut.js Region.
|
||||
* Utility method for internal use.
|
||||
*/
|
||||
toNutRegion(region: ScreenRegion): Region {
|
||||
return new Region(region.x, region.y, region.width, region.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert nut.js Region to ScreenRegion.
|
||||
* Utility method for internal use.
|
||||
*/
|
||||
fromNutRegion(nutRegion: Region): ScreenRegion {
|
||||
return {
|
||||
x: nutRegion.left,
|
||||
y: nutRegion.top,
|
||||
width: nutRegion.width,
|
||||
height: nutRegion.height,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user