123 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			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)
 | |
|       })
 | |
|   }())
 | |
| }
 |