const {SolveCaptcha, TWO_CAPTCHA_CONNECTION_FAILED} = require("./SolveCaptcha"); const ReserveResultPojo = require("../models/ReserveResultPojo"); const appointmentLogger = require("../utiles/LoggerUtils") const OCRResult = require("../models/OCRResult"); const PublishType = require("../models/PublishType"); const puppeteer = require('puppeteer'); const GeoCaptchaSolver = require("./GeoCaptchaSolver"); const SlidingCaptchaSolver = require("./SlidingCaptchaSolver"); const OCRChecker = require("./OCRChecker"); const {exec} = require("child_process"); const {openUrlWithAdb} = require("../utiles/CmdUtils"); // const RDV_URL = "http://192.168.0.44:8000/test_appointment.html" const RDV_URL = "https://rendezvousparis.hermes.com/client/register"; const BLANK_URL = "about:blank" const ERROR_CAPTCHA_UNSOLVABLE = "ERROR_CAPTCHA_UNSOLVABLE"; const COUNTRY_ID = "#phone_country" const PHONE_NUMBER = "#phone_number" const EMAIL_ID = "#email" const PREFER_STORE = "#prefer" const LAST_NAME = "#surname" const FIRST_NAME = "#name" const CGU_ID = "#cgu" const PROCESSING_ID = "#processing" const PASSPORT_ID = "#passport_id" const CAPTCHA_CONTAINER = "#captcha-container"; const TIME_OUT = 60 * 1000 * 4//4 mins const EMPTY_RESPONSE_ERROR = "ERR_EMPTY_RESPONSE" const MESSAGE_URL_VALIDATION_FR = "Nous avons envoyé un lien par e-mail." const MESSAGE_URL_VALIDATION_EN = "Please click on the link we sent by email" const REGEX_RDV_URL = "https:\/\/rendezvousparis\.hermes\.com\/client\/register\/[A-Z0-9]+" const DEFAULT_STORE = 'faubourg'; const timeout = (prom, time) => Promise.race([prom, new Promise((_r, rej) => setTimeout(rej, time))]); function delay(delayInMs) { return new Promise(resolve => { setTimeout(() => { resolve(2); }, delayInMs); }); } function getRandom() { return Math.floor(Math.random() * 3); } function getRandomWaitTime() { return getRandom() * 1000 } function log(message) { appointmentLogger.log({level: "info", message: message}) } async function clearApp(device, packageName) { let cmd = `adb -s ${device.serial()} shell pm clear ${packageName}` logWithDevice("cmd is " + cmd, device) await exec(cmd); } async function exceutShellCmd(device, cmdToExecut) { let cmd = `adb -s ${device.serial()} shell ${cmdToExecut}` logWithDevice("cmd is " + cmd, device) await exec(cmd); } function logWithDevice(message, device) { appointmentLogger.log({level: "info", message: device.model() + ":" + device.serial() + ":" + message}) } const searchTexts = ['hermes+rdv+online+paris', 'hermes+rdv+enligne+paris', 'hermes+rdv+en+ligne+paris', 'hermes+rendezvous+en+ligne+paris', 'hermes+appointment+online+paris', 'hermes+appointment+online+paris', 'appointment+hermes+paris+on+line', 'hermes+rendez+vous+online+paris', 'hermes+rendez+vous+paris+en+ligne', 'hermes+rendez+vous+paris+enligne', 'hermes+rendez+vous+paris+online', 'online+appointment+hermes+paris', 'hermes+online+appointment+paris', 'paris+hermes+online+appointment'] class CommandorPage { constructor(contact, device, sender, mongoManager, selectedStore = DEFAULT_STORE, audioAnalyse = false, alertBeep = false, port = 9000) { this.contact = contact; this.device = device; this.mongoManager = mongoManager; this.selectedStore = selectedStore; this.choosedStore = selectedStore; this.port = port; this.sender = sender; this.ocrChecker = new OCRChecker(this.device, this.contact); this.browserPackageName = "com.brave.browser"; // this.browserPackageName = "com.android.chrome"; this.isFillingFields = false; this.isTerminated = false; this.cguChecked = false; this.isNameInput = false; this.isEmailFilled = false; this.isCountryChoosen = false; this.isPhoneInput = false; this.firstStart = true; this.isAlreadyRefresh = false; } async openGoogle() { const item = searchTexts[Math.floor(Math.random() * searchTexts.length)]; // await this.page.goto("https://www.google.com/search?q=" + item + "&lr=lang_en", {timeout: 30 * 1000}); await openUrlWithAdb("https://www.google.com/search?q=" + item + "&lr=lang_en", this.device) await delay(5 * 1000) await this.acceptCookies(); } async connect_to_browser(ocrResult) { console.log("connect_to_browser() called"); if (this.browser === undefined) { this.isTerminated = true return } console.log("browser.isConnected: " + this.browser.isConnected()); if (!this.browser.isConnected()) { this.browser = await puppeteer.connect({ browserWSEndpoint: "ws://127.0.0.1:" + this.port + "/devtools/browser", headless: false, defaultViewport: null }) } let pages = await this.browser.pages(); // 0 is the last page pages.forEach((currentPage) => { let url = currentPage.url() if (url.includes(RDV_URL)) { this.page = currentPage } }) logWithDevice("pageUrl is " + this.page.url(), this.device) // this.page = pages[pages.length - 1]; switch (ocrResult) { case OCRResult.SUCCESS: // get url and push to server await this.push_message_to_queue(PublishType.SUCCESS) break; case OCRResult.RECAPTCHA_ERROR: // get url and push to server await this.fillFields() break; case OCRResult.SLIDING_CAPTCHA_REFRESH: pages.forEach((currentPage) => { currentPage.close() }) break; case OCRResult.TO_REFRESH: logWithDevice("will reload page", this.device) let cmd = "input swipe 382 682 382 1682" logWithDevice("will send cmd:" + cmd, this.device) this.device.shell(cmd); await delay(3000); await this.clickOnConfirmBtn(); await this.checkResultWithOcr(); break; } } async generateRandomActions() { logWithDevice("will reload page", this.device) let limit = getRandom() + 1 for (let i = 1; i <= limit; i++) { let tapX = 300 + getRandom() * 100 + getRandom() * 10 + getRandom() let tapY = 400 + getRandom() * 100 + getRandom() * 10 + getRandom() await this.tapForDevice(this.device, tapX, tapY) // await this.inputForDevice(this.device, getRandom() + "") await delay(getRandomWaitTime()); } for (let i = 1; i <= limit; i++) { let x = 350 + getRandom() * 100 let y0 = 600 + getRandom() * 100 + getRandom() * 10 + getRandom() * 1 let swipCmd = "input swipe " + x + " " + y0 + " " + x + " 1522" logWithDevice("will send cmd:" + swipCmd, this.device) await this.device.shell(swipCmd); await delay(3 * getRandomWaitTime()); } // await this.openGoogle() // await delay(3 * getRandomWaitTime()); await this.clickOnHomeBtn(); await this.checkResultWithOcr(); } async checkIfSuccessful() { let content = await this.page.content(); if (content.includes(MESSAGE_URL_VALIDATION_FR) || content.includes(MESSAGE_URL_VALIDATION_EN)) { log("successful"); await this.push_message_to_queue(PublishType.SUCCESS); return true; } else { return false } } async loadPage() { logWithDevice(this.device.serial() + ":loadPage() called, with port:" + this.port, this.device); try { // let cmd = 'adb -s ' + device.serial() + " forward tcp:" + attributedPort + " localabstract:chrome_devtools_remote"; await exceutShellCmd(this.device, " forward tcp:" + this.port + " localabstract:chrome_devtools_remote") await delay(1 * 1000); // await this.startPage(this.device, this.browserPackageName + "/com.google.android.apps.chrome.Main") await delay(4 * 1000); } catch (e) { console.log(e) this.isTerminated = true; } // await this.acceptCookies(); await this.enableDisableAirPlanMode(); // await openUrlWithAdb("https://www.google.fr", this.device) // await delay(2 * 1000) await openUrlWithAdb(RDV_URL, this.device) await delay(10 * 1000) await this.checkResultWithOcr() let cancel const intervalTask = setInterval(async () => { if (this.isTerminated) { log(this.device.model() + ":request terminated, send cancel()"); try { if (this.page !== undefined) { await this.page.close() } } catch (e) { console.log(e) } this.disconnectBrowser(); clearInterval(intervalTask) cancel() } else { } }, 10 * 1000)//interval of 10 seconds await new Promise(function (fulfill, reject) { cancel = function () { fulfill(Promise.resolve()) } setTimeout(fulfill, TIME_OUT, 5) }).then(log) } async clickOnlineAppointment() { try { logWithDevice("will click on rdv link", this.device); await this.connectBrowserIfNecessary(); const [button] = await this.page.$x("//a[contains(., 'rendezvousparis')]"); console.log("button is " + button) if (button) { console.log("will click on the button") try { await button.click(); if (this.firstStart) { this.disconnectBrowser() } await delay(2000) await this.checkResultWithOcr(); } catch (e) { console.log(e) } } } catch (e) { console.log(e) await this.checkResultWithOcr(); } } async acceptCookies() { logWithDevice("will accept Cookies", this.device); await this.connectBrowserIfNecessary() if (!this.isTerminated && this.browser.isConnected()) { try { logWithDevice("get pages", this.device) // add listeners let pages = await timeout(this.browser.pages(), 5 * 1000); pages.forEach((currentPage) => { if (currentPage.url().includes("google")) { this.page = currentPage; } else { try { if (!this.isTerminated) currentPage.close() } catch (e) { console.log(e) } } }) logWithDevice("this.page.bringToFront();", this.device) await this.page.bringToFront(); await delay(2 * 1000); await this.page.evaluate(() => { let buttons = document.getElementsByTagName('button'); for (let i = 0; i < buttons.length; i++) { let button = buttons[i]; let txt = button.textContent || button.innerText; if (txt.includes("Tout accepter")) { button.click() } console.log(txt); } }) } catch (e) { console.log(e) } } } async chooseCountry(page) { logWithDevice("chooseCountry", this.device) if (this.browser.isConnected() && !this.isTerminated) { try { if (!this.isCountryChoosen) { // await page.focus(COUNTRY_ID); // await delay(getRandomWaitTime()) // await page.click(COUNTRY_ID); // await delay(getRandomWaitTime()) await page.select(COUNTRY_ID, 'FR'); await delay(getRandomWaitTime()) this.isCountryChoosen = true; } } catch (e) { log(e); this.isTerminated = true; } } } async fillEmail(page) { logWithDevice("fillEmail", this.device) try { if (this.browser.isConnected() && !this.isTerminated) { if (!this.isEmailFilled) { await page.focus(EMAIL_ID); await delay(getRandomWaitTime()) console.log("will clear email field"); await page.evaluate((email) => { let field = document.getElementById("email"); if (field) { field.value = email } }, this.contact.mail) // await page.evaluate(() => { // let field = document.getElementById("email"); // if (field) { // field.value = "" // } // }) // await delay(1000); // await page.keyboard.type(this.contact.mail); this.isEmailFilled = true; } } } catch (e) { log(e) } } async inputPhoneNumber(page) { logWithDevice("inputPhoneNumber", this.device) try { if (this.browser.isConnected() && !this.isTerminated) { if (!this.isPhoneInput) { await page.focus(PHONE_NUMBER); console.log("will clear phone_number field"); await page.evaluate((phone) => { let field = document.getElementById("phone_number"); if (field) { field.value = phone } }, "" + this.contact.phoneNumber) // }, "0" + this.contact.phoneNumber) // 如果需要显示键盘的话,使用下面方法 // await page.evaluate(() => { // let field = document.getElementById("phone_number"); // if (field) { // field.value = "" // } // }) // await delay(1000); // await page.keyboard.type("0" + this.contact.phoneNumber); this.isPhoneInput = true; } } } catch (e) { log(e); this.isTerminated = true; } } async inputName(page) { logWithDevice("inputName", this.device) await delay(getRandomWaitTime()); try { logWithDevice("input name called with this.browser.isConnected=" + this.browser.isConnected(), this.device) logWithDevice("input name called with this.isNameInput=" + this.isNameInput, this.device) if (this.browser.isConnected() && !this.isTerminated && !this.page.isClosed()) { if (!this.isNameInput) { await page.focus(LAST_NAME); await delay(getRandomWaitTime()); console.log("will clear surname field"); await page.evaluate(() => { let field = document.getElementById("surname"); if (field) { field.value = "" } }) await delay(1000); // await page.keyboard.type(this.contact.lastName); await page.evaluate((lastName) => { let field = document.getElementById("surname"); if (field) { field.value = lastName } }, this.contact.lastName) await page.focus(FIRST_NAME); await delay(getRandomWaitTime()); // console.log("will clear name field"); await page.evaluate((firstName) => { let field = document.getElementById("name"); if (field) { field.value = firstName; // field.value = "" } }, this.contact.firstName) // await page.keyboard.type(this.contact.firstName); this.isNameInput = true; } } } catch (e) { logWithDevice("exception while inputting name", this.device) console.log(e); this.isTerminated = true } } async getRawAppointmentInfo(page) { let passportId = await page.evaluate(() => { let field = document.getElementById("passport_id"); return field.value }) let lastName = await page.evaluate(() => { let field = document.getElementById("surname"); return field.value }) let firstName = await page.evaluate(() => { let field = document.getElementById("name"); return field.value }) let phone = await page.evaluate(() => { let field = document.getElementById("phone_number"); return field.value }) let email = await page.evaluate(() => { let field = document.getElementById("email"); return field.value }) return new ReserveResultPojo(email, phone, passportId, email, lastName, firstName, "random", "", PublishType.PENDING) } async inputPassportId(page) { logWithDevice("inputPassportId", this.device) try { if (this.browser.isConnected() && !this.isTerminated) { if (!this.isPasspordInput) { await page.focus(PASSPORT_ID); await delay(getRandomWaitTime()); console.log("will clear passport_id field"); await page.evaluate((passport) => { let field = document.getElementById("passport_id"); if (field) { field.value = passport } }, this.contact.passportNumber.toString()) // await page.evaluate(() => { // let field = document.getElementById("passport_id"); // if (field) { // field.value = "" // } // }) // await delay(1000); // await page.keyboard.type(this.contact.passportNumber.toString()); this.isPasspordInput = true; } } } catch (e) { log(e); this.isTerminated = true; } } async checkCGU(page) { logWithDevice("checkCGU", this.device) try { if (this.browser.isConnected() && !this.isTerminated && !this.page.isClosed()) { if (!this.cguChecked) { await page.focus(CGU_ID); await page.evaluate(() => { if (!document.querySelector("#cgu").checked) { document.querySelector("#cgu").checked = true } }); // await page.click(CGU_ID); await delay(getRandomWaitTime()); await page.focus(PROCESSING_ID); // await page.click(PROCESSING_ID) await page.evaluate(() => { if (!document.querySelector("#processing").checked) { document.querySelector("#processing").checked = true } }); this.cguChecked = true; } } } catch (e) { log(e); this.isTerminated = true; } } async chooseStore(page) { logWithDevice("chooseStore", this.device) await delay(getRandomWaitTime()) try { if (!this.page.isClosed() && !this.isTerminated) { if (this.contact.store === undefined || this.contact.store.length === 0) { this.contact.store = this.selectedStore; } else { this.selectedStore = this.contact.store; } if (this.contact.store !== "random") { // page.focus(PREFER_STORE); await delay(500) // page.click(PREFER_STORE); let stores = this.contact.store.split(":") this.choosedStore = stores[Math.floor(Math.random() * stores.length)] await page.select(PREFER_STORE, this.choosedStore); } } } catch (e) { log(e); // this.isTerminated = true; } } async fillFields(page) { logWithDevice("fillFields called for contact: " + this.contact.mail, this.device) logWithDevice("this.isFillingFields: " + this.isFillingFields, this.device); logWithDevice("this.isTerminated: " + this.isTerminated, this.device); if (!this.isFillingFields && !this.isTerminated && !this.page.isClosed()) { this.isFillingFields = true; await this.chooseStore(page); await this.inputName(page); // await this.chooseCountry(page); await this.inputPhoneNumber(page) await this.fillEmail(page) await this.inputPassportId(page) await this.checkCGU(page) let pageContent = await page.content() let hasCaptcha = pageContent.includes("g-recaptcha-response") if (hasCaptcha) { await this.resolveCaptcha(page); await delay(getRandomWaitTime()); this.isFillingFields = false; } else { await delay(getRandomWaitTime()) try { await this.clickValid(); } catch (e) { this.isTerminated = true; console.log(e) } this.isFillingFields = false } } } async clickValid() { logWithDevice("clickValid() called.", this.device); await delay(getRandomWaitTime()) this.isFillingFields = false try { if (!this.page.isClosed()) { if (!this.page.isClosed()) { try { // remove debug flag // const validElement = await page.$('.btn'); logWithDevice("will click on valid button", this.device); logWithDevice("isTerminated is " + this.isTerminated, this.device); if (!this.isTerminated) { if (!this.page.isClosed()) { let raw = await this.getRawAppointmentInfo(this.page) if (raw.email !== undefined) { this.contact.mail = raw.email } if (raw.passportNumber !== undefined) { this.contact.passportNumber = raw.passportNumber } if (raw.lastName !== undefined) { this.contact.lastName = raw.lastName } if (raw.phoneNumber !== undefined) { this.contact.phoneNumber = raw.phoneNumber } if (raw.firstName !== undefined) { this.contact.firstName = raw.firstName } await this.page.evaluate(() => { document.getElementsByClassName("btn")[0].click(); }) if (this.firstStart) { this.disconnectBrowser(); await delay(3000); await this.checkResultWithOcr(); } } } } catch (e) { log(e); await this.checkResultWithOcr() } } } } catch (e) { logWithDevice("exception received", this.device) log(e) } } async resolveCaptcha(page) { logWithDevice("resolveCaptcha", this.device) if (RDV_URL.includes("192")) { // await this.push_message_to_queue(PublishType.SUCCESS) await delay(100000) return } try { //check whether there is captcha let pageContent = await page.content() let hasCaptcha = pageContent.includes("g-recaptcha-response") logWithDevice("hasCaptcha = " + hasCaptcha, this.device) if (hasCaptcha) { // await this.clickCheckbox() await delay(1000) this.captchaSolver = new SolveCaptcha(page); await this.captchaSolver.start((solution) => { logWithDevice("solution is: " + solution, this.device); if (solution !== ERROR_CAPTCHA_UNSOLVABLE && solution !== TWO_CAPTCHA_CONNECTION_FAILED) { try { if (!page.isClosed() && !this.isTerminated) { if (this.browser.isConnected()) { page.evaluate((solution) => { let element = document.getElementById("g-recaptcha-response"); if (element != null) document.getElementById("g-recaptcha-response").innerHTML = solution; }, solution) this.clickValid(); } } } catch (e) { log(e) this.isTerminated = true; } } else { this.isTerminated = true; } }) } else { await this.clickValid(); } } catch (e) { console.log(e) this.isTerminated = true; } } async onPageLoad(currentPage) { logWithDevice("onPageLoad called with url " + this.page.url(), this.device) try { let content = await this.page.content(); let captcha_url = "geo.captcha-delivery.com/captcha"; // if (content.toString().includes(captcha_url)) { // await this.checkResultWithOcr() // logWithDevice("发现datadome", this.device); // } else if (content.includes("502 Bad Gateway")) { logWithDevice("502 Bad Gateway found", this.device) await this.page.reload() } else if (this.page.url().includes("sorry")) { await this.resetBrowser() } else if (content.includes("PROXY_CONNECTION_FAILED")) { logWithDevice("PROXY_CONNECTION_FAILED, will reload page", this.device); await delay(2000) await this.page.reload() } else if (content.includes("ERR_NETWORK_CHANGED")) { logWithDevice("ERR_NETWORK_CHANGED, will reload page", this.device); await delay(2000) await this.page.reload() } else if (content.includes("ERR_TIMED_OUT")) { logWithDevice("ERR_TIMED_OUT, will reload page", this.device); await delay(2000) await this.page.reload() } else if (content.includes("408 Request Time-out")) { logWithDevice("Request Time-out, will reload page", this.device); await delay(2000) await this.page.reload() } else { if (this.page.url() === RDV_URL) { await this.fillFields(this.page); } else { if (content.includes(MESSAGE_URL_VALIDATION_FR) || content.includes(MESSAGE_URL_VALIDATION_EN)) { log("successful"); await this.push_message_to_queue(PublishType.SUCCESS); } else if (content.includes(EMPTY_RESPONSE_ERROR)) { log("EMPTY_RESPONSE_ERROR error received, will quit") this.isTerminated = true } else { // try to get errors await this.getErrors() } } } } catch (e) { log(e) } } async slidingCaptcha(onResult) { logWithDevice("slidingCaptcha", this.device); if (this.device.model() === "MI 5s" || this.device.model() === "ASUS_X00QD" || this.device.model() === "ASUS_Z012D" || this.device.model() === "HUAWEI NXT-TL00") { let cmd = `adb -s ${this.device.serial()} shell input touchscreen swipe 900 495 900 195` await exec(cmd); await delay(5000); } let slidingCaptchaSolver = new SlidingCaptchaSolver(this.device); await slidingCaptchaSolver.solve(this.page, async (isSuccessful) => { console.log("check isAlwaysBlocked") this.isFillingFields = false onResult(isSuccessful) }) } async onResponse(response) { let rex = new RegExp(REGEX_RDV_URL) // log("onResponse with url:" + response.url()) // log("onResponse with url:" + response.body()) if (rex.test(response.url())) { logWithDevice("rdv url found:" + response.url(), this.device) // save cookies await this.push_message_to_db(PublishType.SUCCESS, response.url()) } } async push_message_to_queue(publishType) { this.isAlreadyRefresh = true; let url = this.page.url(); logWithDevice("successful url is " + url, this.device) await this.push_message_to_db(publishType, url) // this.firstStart = false; } async push_message_to_db(publishType, url) { let splitedUrl = url.split("/"); let id = splitedUrl[splitedUrl.length - 1]; if (id === "register") { id = this.contact.mail; } if (url === "https://rendezvousparis.hermes.com/client/welcome") { return } // save to mongoDb let reserve = ReserveResultPojo.create_from_contact(this.contact, id, url, this.choosedStore, publishType); reserve.source_from = this.device.model(); reserve.serial = this.device.serial(); await this.mongoManager.saveReserveToDb(reserve.to_mongo_dict()) if (!this.page.isClosed()) { try { await this.page.close(); } catch (e) { console.log(e) } } // await this.deleteFromBlackList() this.isTerminated = true } async getErrors() { logWithDevice("getErrors", this.device); await this.checkResultWithOcr(); if (this.page.url() === BLANK_URL) { this.isTerminated = true; } } async clickCheckbox() { logWithDevice("clickCheckbox", this.device); try { // let errorItem = await this.page.click("#recaptcha-anchor > div.recaptcha-checkbox-border") await this.page.waitForSelector("iframe") let elementHandle = await this.page.$('[title="reCAPTCHA"]') const iframe = await elementHandle.contentFrame() await iframe.click("#recaptcha-anchor > div.recaptcha-checkbox-border") } catch (e) { log(e); } } async resetBrowser() { logWithDevice("resetBrowser", this.device); this.isFillingFields = false; this.cguChecked = false; this.isNameInputing = false; this.isEmailFilled = false; this.isCountryChoosen = false; this.isPhoneInput = false; this.isPasspordInput = false; await clearApp(this.device, this.browserPackageName) // await this.device.shell("pm clear " + this.browserPackageName) await delay(1000) this.isTerminated = true; // await this.checkResultWithOcr(); } disconnectBrowser() { try { logWithDevice("will disconnect browser", this.device); if (this.browser !== undefined) { this.browser.disconnect(); } } catch (e) { console.log(e) } } async connectBrowserIfNecessary() { if (this.browser == undefined || !this.browser.isConnected()) { try { this.browser = await puppeteer.connect({ browserWSEndpoint: "ws://127.0.0.1:" + this.port + "/devtools/browser", headless: false, defaultViewport: null }) } catch (e) { console.log(e) this.isTerminated = true; } } } async checkResultWithOcr() { logWithDevice("checkResultWithOcr() called.", this.device) if (this.device.model() === "M2006C3LG") await delay(6000); else { await delay(4000); } let checkResult = await this.ocrChecker.get_result(); console.log(checkResult); while (checkResult === OCRResult.RECHECK || checkResult === OCRResult.NO_INTERNET) { logWithDevice("will recheck OCR", this.device) await delay(4000) logWithDevice("will recheck OCR", this.device) checkResult = await this.ocrChecker.get_result(); } while (checkResult === OCRResult.SLIDING_CAPTCHA) { logWithDevice("will call this.slidingCaptcha()", this.device) await this.slidingCaptcha(async (isSuccessful) => { logWithDevice("SLIDING_CAPTCHA result is " + isSuccessful, this.device) console.log(checkResult); if (isSuccessful) { await delay(5 * 1000) // checkResult = await this.ocrChecker.get_result(); await this.checkResultWithOcr() } else { if (checkResult === OCRResult.SLIDING_CAPTCHA) { checkResult = OCRResult.TERMINAED this.isTerminated = true } } }) await delay(10 * 1000) } switch (checkResult) { case OCRResult.SLIDING_CAPTCHA_LOADING: this.isTerminated = true; break; case OCRResult.SSL_CERT_ERROR: await this.resetBrowser() break; case OCRResult.TERMINAED: this.isTerminated = true; break; case OCRResult.SLIDING_CAPTCHA_REFRESH: await this.connect_to_browser(checkResult) break; case OCRResult.FILL_FIELD: logWithDevice("FILL_FIELD", this.device) if (this.browser === undefined || !this.browser.isConnected()) { logWithDevice("trying to connect to browser", this.device) try { this.browser = await puppeteer.connect({ browserWSEndpoint: "ws://127.0.0.1:" + this.port + "/devtools/browser", headless: false, defaultViewport: null }) try { logWithDevice("get pages", this.device) // add listeners let pages = await timeout(this.browser.pages(), 5 * 1000); pages.forEach((currentPage) => { if (currentPage.url() === RDV_URL) { this.page = currentPage; } else { try { if (!this.isTerminated) currentPage.close() } catch (e) { console.log(e) } } }) logWithDevice("this.page.bringToFront();", this.device) const cookiesSet = await this.page.cookies(); let cookiesString = "" cookiesSet.forEach((cookie) => { cookiesString = cookiesString + cookie.name + "=" + cookie.value + ";" }) console.log(cookiesString); if (this.contact.ipCountry === "DE") this.sender.sendMessage(cookiesString, "REQUEST_DATA_DE") else this.sender.sendMessage(cookiesString) // let content = await this.page.content() // console.log(content) await this.page.bringToFront(); await this.fillFields(this.page) await delay(2 * 1000); } catch (e) { console.log(e) await this.resetBrowser() // this.isTerminated = true; } // try { // for (const currentPage of pages) { // if (currentPage.url() === RDV_URL) { // logWithDevice("get content", this.device) // let pageContent = await currentPage.content() // logWithDevice("content:" + pageContent, this.device) // if (!pageContent.includes("geo.captcha-delivery.com")) { // this.page = currentPage; // break // } else { // try { // await currentPage.close() // } catch (e) { // console.log(e) // } // } // } else { // try { // await currentPage.close() // } catch (e) { // console.log(e) // } // } // } // } catch (e) { // this.isTerminated = true; // console.log(e) // } } catch (e) { console.log(e) this.isTerminated = true } } else { logWithDevice("this.browser.isConnected() is " + this.browser.isConnected(), this.device) try { if (this.browser.isConnected()) { logWithDevice("will use old page", this.device) logWithDevice("this.page.bringToFront();", this.device) await this.page.bringToFront(); // this.page = pages; // this.page.await await this.fillFields(this.page) await delay(2 * 1000); } } catch (e) { console.log(e) this.isTerminated = true } } break; case OCRResult.SUCCESS: // reconnect to page and get url if (!this.isTerminated) { await this.connect_to_browser(OCRResult.SUCCESS) // if (!this.isTerminated) { // logWithDevice("will save success appointment", this.device) // await this.push_message_to_queue(PublishType.SUCCESS); // await this.closePage() // } } break; case OCRResult.RECAPTCHA_ERROR: this.isTerminated = true; break; case OCRResult.BRAVE_SKIP: await this.handleBraveSkipBtn(); await this.checkResultWithOcr(); break; case OCRResult.BRAVE_PRIVACY: let model = this.device.model() if (model === "MI 5s" || this.device.model() === "SM-G965U1" || this.device.model() === "ASUS_Z012D") { await this.tapForDevice(this.device, 530, 970) } else if (model === "HUAWEI NXT-TL00") { await this.tapForDevice(this.device, 530, 950) } else if (this.device.model() === "ONEPLUS A6000") { await this.tapForDevice(this.device, 530, 1064) } else if (this.device.model() === "moto g51 5G") { await this.tapForDevice(this.device, 500, 1080) } else if (this.device.model() === "CPH2469") { await this.tapForDevice(this.device, 360, 820) } else if (this.device.model() === "M2006C3LG" || this.device.model() === "220233L2G") { await this.tapForDevice(this.device, 350, 777) } else if (this.device.model() === "KB2003" || this.device.model() === "DE2117") { await this.tapForDevice(this.device, 500, 1200) await this.tapForDevice(this.device, 500, 1120) } else try { await this.tapForDevice(this.device, 500, 1120) // await this.device.shell("input tap " + 500 + " " + 1120) } catch (e) { console.log(e) } await delay(2000); await this.checkResultWithOcr(); break; case OCRResult.BRAVE_PRIVACY_PUB: if (this.device.model() === "MI 5s" || this.device.model() === "ASUS_Z012D") { await this.tapForDevice(this.device, 60, 1400) } else if (this.device.model() === "HUAWEI NXT-TL00") { await this.tapForDevice(this.device, 530, 950) } else await this.tapForDevice(this.device, 455, 1920) await delay(2000); await this.checkResultWithOcr(); break; case OCRResult.BRAVE_NOTIFICATION: logWithDevice("BRAVE_NOTIFICATION", this.device) if (this.device.model() === "21091116C") { await this.tapForDevice(this.device, 540, 1611) } else if (this.device.model() === "22041219PG") { await this.tapForDevice(this.device, 530, 1600) } else if (this.device.model() === "CPH2469") { await this.tapForDevice(this.device, 322, 1146) } else await this.tapForDevice(this.device, 500, 1680) // await this.device.shell("input tap " + 500 + " " + 1680) await delay(2000); await this.checkResultWithOcr(); break; case OCRResult.CHOOSE_POSITION: logWithDevice("CHOOSE_POSITION", this.device) await this.tapForDevice(this.device, 300, 1300) await delay(2000); await this.tapForDevice(this.device, 300, 1700) await this.checkResultWithOcr(); break; case OCRResult.BRAVE_VPN_SKIP: logWithDevice("BRAVE_VPN_SKIP", this.device) if (this.device.model() === "M2006C3LG") { await this.tapForDevice(this.device, 580, 445) } break; case OCRResult.TO_SKIP : logWithDevice("TO_SKIP", this.device) if (this.device.model() === "21091116C") await this.device.shell("input tap " + 530 + " " + 1742) else await this.device.shell("input tap " + 488 + " " + 1848) await delay(2000); break; case OCRResult.TO_REFRESH : await this.connect_to_browser(OCRResult.TO_REFRESH) break; case OCRResult.BLOCKED : if (this.isAlreadyRefresh) { await this.resetBrowser(); } else { this.isAlreadyRefresh = true; await this.generateRandomActions() } break; case OCRResult.ONLINE_APPOINTMENT : await this.clickOnlineAppointment(); break; case OCRResult.CONFIRM_RESEND_FORM : // logWithDevice("CONFIRM_RESEND_FORM", this.device) // await this.checkResultWithOcr(); break; case OCRResult.PAGE_OPTIMIZATION : logWithDevice("PAGE_OPTIMIZATION", this.device) await this.skipOptimizationPage(); await this.checkResultWithOcr(); break; case OCRResult.GOOGLE_DISCONNECT : logWithDevice("GOOGLE_DISCONNECT", this.device) await this.tapGoogleDisconnectBtn() await this.checkResultWithOcr(); break case OCRResult.NEED_TO_CLICK_LATE_BTN : await this.tapLaterBtn() this.firstStart = true; await this.loadPage() break; case OCRResult.CLOSED : await this.closePage(); // this.isTerminated = true; break; default: await delay(5000); checkResult = this.ocrChecker.get_result(); } if (checkResult === undefined ) { await delay( 5000 ) ; checkResult = this.ocrChecker.get_result(); } } async handleBraveSkipBtn() { let model = this.device.model() if (model === "CPH2219") { await this.device.shell("input tap " + 558 + " " + 1160) } else if (model === "MI 5s" || model === "ASUS_Z012D") { await this.tapForDevice(this.device, 530, 1000) } else if (model === "SM-G965U1") { await this.tapForDevice(this.device, 530, 1000) } else if (model === "HUAWEI NXT-TL00") { await this.tapForDevice(this.device, 530, 950) } else if (model === "M2006C3LG" || model === "220233L2G") { await this.tapForDevice(this.device, 360, 777) } else if (model === "ONEPLUS A6000") { await this.tapForDevice(this.device, 530, 1045) } else if (model === "CPH2469") { await this.tapForDevice(this.device, 360, 820) } else { logWithDevice("handleBraveSkipBtn", this.device) await this.tapForDevice(this.device, 470, 1160) } await delay(2000); await this.tapForDevice(this.device, 455, 1920) await delay(1000); } async tapForDevice(device, x, y) { let cmd = `adb -s ${device.serial()} shell input tap ${x} ${y}` logWithDevice("cmd is " + cmd, this.device) await exec(cmd); } async inputForDevice(device, text) { let cmd = `adb -s ${device.serial()} shell input text ${text}` logWithDevice("cmd is " + cmd, this.device) await exec(cmd); } async clickOnConfirmBtn() { if (this.device.model() === "CPH2219") { this.device.shell("input tap " + 900 + " " + 1532) } else if (this.device.model() === "MI 5s") { this.device.shell("input tap " + 925 + " " + 1325) } else if (this.device.model() === "22041219PG") { this.device.shell("input tap " + 925 + " " + 1430) } else if (this.device.model() === "moto g51 5G") { await this.tapForDevice(this.device, 950, 1434) } else this.device.shell("input tap " + 933 + " " + 1538) await delay(2000); } async clickOnHomeBtn() { // await this.enableDisableAirPlanMode() if (this.device.model() === "22041219PG") { await this.tapForDevice(this.device, 110, 2208) await delay(2000); await openUrlWithAdb(RDV_URL, this.device) } else if (this.device.model() === "KB2003") { await this.tapForDevice(this.device, 100, 2289) await delay(2000); await openUrlWithAdb(RDV_URL, this.device) } else if (this.device.model() === "21091116C") { await this.tapForDevice(this.device, 107, 2193) await delay(2000); await openUrlWithAdb(RDV_URL, this.device) } else if (this.device.model() === "MI 5s") { await this.tapForDevice(this.device, 110, 1842) await delay(2000); await openUrlWithAdb(RDV_URL, this.device) } else if (this.device.model() === "ASUS_X00QD" || this.device.model() === "CPH2219") { await this.tapForDevice(this.device, 112, 2172) await delay(2000); await openUrlWithAdb(RDV_URL, this.device) } else if (this.device.model() === "moto g51 5G") { await this.tapForDevice(this.device, 103, 2283) await delay(2000); await openUrlWithAdb(RDV_URL, this.device) } else if (this.device.model() === "ONEPLUS A6000") { await this.tapForDevice(this.device, 122, 2172) await delay(2000); await openUrlWithAdb(RDV_URL, this.device) } else if (this.device.model() === "DE2117") { await this.tapForDevice(this.device, 122, 2172) await delay(2000); await openUrlWithAdb(RDV_URL, this.device) } await delay(4000); } async closePage() { await this.resetBrowser(); } async skipOptimizationPage() { logWithDevice("skipOptimizationPage", this.device) let model = this.device.model(); if (model === "ASUS_X00QD") { this.device.shell("input tap " + 800 + " " + 2100) await delay(2000); this.device.shell("input tap " + 800 + " " + 2100) await delay(1000); } else if (model === "ONEPLUS A6000") { this.device.shell("input tap " + 818 + " " + 2140) await delay(2000); this.device.shell("input tap " + 818 + " " + 2140) await delay(1000); } else if (model === "CPH2219") { this.device.shell("input tap " + 772 + " " + 2146) await delay(2000); this.device.shell("input tap " + 772 + " " + 2146) } else if (model === "MI 5s") { this.device.shell("input tap " + 786 + " " + 1780) await delay(2000); this.device.shell("input tap " + 790 + " " + 1807) await delay(1000); } else { this.device.shell("input tap " + 800 + " " + 2215) await delay(2000); this.device.shell("input tap " + 800 + " " + 2215) await delay(1000); } } async tapLaterBtn() { logWithDevice("tapLaterBtn", this.device) let model = this.device.model(); log("model is " + model); if (model === "CPH2219") { this.device.shell("input tap " + 385 + " " + 1930) } else if (model === "ASUS_X00QD") { this.device.shell("input tap " + 490 + " " + 1910) } else if (model === "Mi Note 10") { this.device.shell("input tap " + 550 + " " + 1920) } else if (model === "ONEPLUS A6000") { this.device.shell("input tap " + 535 + " " + 1945) } else if (model === "22041219PG") { this.device.shell("input tap " + 540 + " " + 1985) } else if (model === "21091116C") { this.device.shell("input tap " + 510 + " " + 1975) } else if (model === "MI 5s") { this.device.shell("input tap " + 510 + " " + 1615) } else this.device.shell("input tap " + 385 + " " + 2050) await delay(1000); } async enableDisableAirPlanMode() { logWithDevice("will enable/disable airplane mode", this.device) try { // await this.device.shell("cmd connectivity airplane-mode enable") await exceutShellCmd(this.device, "cmd connectivity airplane-mode enable") await delay(1000) await exceutShellCmd(this.device, "cmd connectivity airplane-mode disable") // await this.device.shell("cmd connectivity airplane-mode disable") await delay(2000) } catch (e) { try { await this.device.shell("cmd connectivity airplane-mode disable") } catch (e) { console.log(e) } console.log(e) } } async tapGoogleDisconnectBtn() { if (this.device.model() === "MI 5s") { if (this.browserPackageName.includes("brave")) { await this.tapForDevice(this.device, 535, 1629) } else await this.device.shell("input tap " + 550 + " " + 1740) } else { if (this.browserPackageName.includes("brave") && this.device.model() === "CPH2219") { await this.device.shell("input tap " + 411 + " " + 1977) } else if (this.browserPackageName.includes("brave") && this.device.model() === "RMX3151") { await this.device.shell("input tap " + 411 + " " + 1977) } else if (this.browserPackageName.includes("brave") && this.device.model() === "ONEPLUS A6000") { await this.device.shell("input tap " + 411 + " " + 1970) } else if (this.browserPackageName.includes("brave") && this.device.model() === "ASUS_X00QD") { await this.device.shell("input tap " + 411 + " " + 1970) } else if (this.browserPackageName.includes("brave") && this.device.model() === "22041219PG") { await this.tapForDevice(this.device, 411, 2020) } else if (this.browserPackageName.includes("brave") && this.device.model() === "21091116C") { await this.tapForDevice(this.device, 411, 2020) } else if (this.browserPackageName.includes("brave") && this.device.model() === "M2006C3LG") {//redmi 9a await this.tapForDevice(this.device, 411, 1300) } else if (this.browserPackageName.includes("brave") && this.device.model() === "220233L2G") {//redmi 9a await this.tapForDevice(this.device, 411, 1300) } else { await this.tapForDevice(this.device, 411, 2100) } // await this.device.shell("input tap " + 411 + " " + 2100) } await delay(2000); } async startPage(device, activity) { let cmd = `adb -s ${device.serial()} shell am start -n ${activity}` logWithDevice("cmd is " + cmd, this.device) await exec(cmd); } } module .exports = CommandorPage