message-robot/robot/robot.js

123 lines
3.4 KiB
JavaScript

/**
* NOTE: install "dark mode" on browser because tesseract need contract to detect text
* NOTE: zoom 120% on browser because below
*/
const robotjs = require('robotjs')
const tesseract = require('tesseract.js')
const jsdom = require('jsdom')
const Jimp = require('jimp')
const CONFIG = {
SCALE_IMAGE: 1.5,
SCROLL_COUNT: 8,
}
module.exports = async function(keywordSearch, keywordToClick, scale = CONFIG.SCALE_IMAGE, fileScreenshot = 'screenshot.jpg', waitSearch = 2000) {
if(!scale) {
scale = CONFIG.SCALE_IMAGE
}
if(!fileScreenshot) {
fileScreenshot = 'screenshot.jpg'
}
if(!waitSearch) {
waitSearch = 2000
}
const $_randomInteger = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
async function handleToClick() {
let _horc = '';
let _text = '';
let _coorStr = '';
const _captureImage = async () => {
const capture = robotjs.screen.capture()
return new Promise(res => {
new Jimp(
{data: capture.image, width: capture.width, height: capture.height},
(err, image) => {
image.greyscale((err, image) => {
image.scale(scale, (err, image) => {
image.writeAsync(fileScreenshot).then(() => {
res(true)
})
})
});
});
})
}
const _convertImageToDomString = async () => {
await tesseract
.recognize(fileScreenshot)
.then(async ({data: {hocr, text}}) => {
_horc = hocr
_text = text
})
}
const _detectHTML = async () => {
console.log({keywordToClick, _text})
return new Promise(async (resToFinished, rejToAgain) => {
if(_text.includes(keywordToClick)) {
const dom = new jsdom.JSDOM(_horc)
const spanEls = dom.window.document.querySelectorAll('span')
for await(let span of spanEls) {
const textContent = span.textContent.split(' ').join('')
if(textContent.includes(keywordToClick)) {
_coorStr = span.title
return resToFinished(true)
}
}
}
// scroll to 8 times
for (let i = 1; i < CONFIG.SCROLL_COUNT; i++) {
robotjs.keyTap('down')
}
rejToAgain(false)
})
}
async function _handleClick() {
const [type, left, top, right, bottom] = _coorStr.split(' ')
const x = parseInt((parseInt(left) + $_randomInteger(20, 40)) / scale)
const y = parseInt((parseInt(top) - $_randomInteger(0, parseInt(top) - parseInt(bottom))) / scale)
robotjs.moveMouse(x, y)
robotjs.mouseClick('left')
console.log('moveMouse:', {x, y}, {
left, bottom, right, top
})
}
return new Promise(async (res, rej) => {
await _captureImage();
await _convertImageToDomString();
await _detectHTML().then(_handleClick).catch(rej);
})
}
await (async function search() {
robotjs.keyTap('home', ['alt']);
robotjs.typeString(keywordSearch);
robotjs.keyTap('enter')
return new Promise(res => setTimeout(res, waitSearch))
}())
await (async function recusiveScroll(countScroll = 1, limitStopScroll = 20) {
if(countScroll > limitStopScroll) {
return;
}
await handleToClick(keywordToClick, scale)
.catch(async () => {
await recusiveScroll(++countScroll, limitStopScroll)
})
}())
}