diff --git a/src/appointment.js b/src/appointment.js index 244a81c..c3a3077 100644 --- a/src/appointment.js +++ b/src/appointment.js @@ -12,8 +12,8 @@ const SEVEN_DAYS_IN_S = 3600 * 24 * 7; const NINETY_DAYS_IN_S = 30 * 3; let excelUtil = new ExcelUtil(); let collectionName = formatDate(new Date()) -let excludeMode = DeviceExcludeMode.SIX -let three_to_excludes = ["bec11752", "4e8ca027", "hi7ljr5xduyt9pfi", "EPHUT20825001518"] +let excludeMode = DeviceExcludeMode.THREE +let three_to_excludes = [] let four_to_excludes = ["bec11752", "4e8ca027", "hi7ljr5xduyt9pfi", "EPHUT20825001518"] let seven_to_excludes = ["4e8ca027", "hi7ljr5xduyt9pfi", "EPHUT20825001518", "bec11752", "fuljaueqguugf6pn", "EPHUT20825001518"] let six_to_excludes = ["4e8ca027", "hi7ljr5xduyt9pfi", "EPHUT20825001518", "bec11752", "07fbd156", "NFD669QK8XNFSCNN", "6X494TTWQGFALB79", "71a0371d", "YP6HVKLFE67T598L"] @@ -193,6 +193,7 @@ async function startBookWithNumbers(startNumber, endNumber, selectedStore, pathT } function startForwordingForDevice(device) { + console.log("startForwordingForDevice() called") const execSync = require('child_process').execSync; // get attributed port let attributedPort = device_port_info[device.serial()] @@ -217,41 +218,44 @@ async function startBookWithNumbers(startNumber, endNumber, selectedStore, pathT let sender = new Sender() sender.initConnection().then((r) => { console.log("queue connected") - mongoManager.connect().then(r => { - filterAlreadyBookedContacts(contactList).then((listToBook) => { - filterAlreadyAcceptedContacts(listToBook).then(notAcceptedContacts => { - filterBlacklistedContacts(notAcceptedContacts).then(listWithoutBlackContact => { - console.log("number of contacts to book:" + listWithoutBlackContact.length) - android.devices().then((devices) => { - if (devices.length === 0) { - alert("未找到连接的设备"); - return - } - let device_to_excludes = three_to_excludes; - if (excludeMode === DeviceExcludeMode.FOUR) { - device_to_excludes = four_to_excludes; - } else if (excludeMode === DeviceExcludeMode.NINE) { - device_to_excludes = nine_to_excludes; - } else if (excludeMode === DeviceExcludeMode.SEVEN) { - device_to_excludes = seven_to_excludes - } else if (excludeMode === DeviceExcludeMode.SIX) { - device_to_excludes = six_to_excludes - } - filteredDeviceList = devices.filter(device => !device_to_excludes.includes(device.serial())) - let segmentNumber = listWithoutBlackContact.length / filteredDeviceList.length; - console.log("connected device number:" + filteredDeviceList.length) - console.log("segmentNumber:" + segmentNumber) - for (let i = 0; i < filteredDeviceList.length; i++) { - let device = filteredDeviceList[i]; - let port = startForwordingForDevice(device) - startWithList(listWithoutBlackContact.slice(i * segmentNumber, segmentNumber * (i + 1)), device, sender, selectedStore, audioAnalyse, alertBeep, port); - } - }) + console.log("connect to mongodb") + mongoManager.connect().then(r => { + console.log("successfully connected to mongodb") + + filterAlreadyBookedContacts(contactList).then((listToBook) => { + filterAlreadyAcceptedContacts(listToBook).then(notAcceptedContacts => { + filterBlacklistedContacts(notAcceptedContacts).then(listWithoutBlackContact => { + console.log("number of contacts to book:" + listWithoutBlackContact.length) + android.devices().then((devices) => { + if (devices.length === 0) { + alert("未找到连接的设备"); + return + } + let device_to_excludes = three_to_excludes; + if (excludeMode === DeviceExcludeMode.FOUR) { + device_to_excludes = four_to_excludes; + } else if (excludeMode === DeviceExcludeMode.NINE) { + device_to_excludes = nine_to_excludes; + } else if (excludeMode === DeviceExcludeMode.SEVEN) { + device_to_excludes = seven_to_excludes + } else if (excludeMode === DeviceExcludeMode.SIX) { + device_to_excludes = six_to_excludes + } + filteredDeviceList = devices.filter(device => !device_to_excludes.includes(device.serial())) + let segmentNumber = listWithoutBlackContact.length / filteredDeviceList.length; + console.log("connected device number:" + filteredDeviceList.length) + console.log("segmentNumber:" + segmentNumber) + for (let i = 0; i < filteredDeviceList.length; i++) { + let device = filteredDeviceList[i]; + let port = startForwordingForDevice(device) + startWithList(listWithoutBlackContact.slice(i * segmentNumber, segmentNumber * (i + 1)), device, sender, selectedStore, audioAnalyse, alertBeep, port); + } }) - } - ) - }) - }); + }) + } + ) + }) + }); }) } diff --git a/src/models/OCRResult.js b/src/models/OCRResult.js index 6586681..b5d7be6 100644 --- a/src/models/OCRResult.js +++ b/src/models/OCRResult.js @@ -1,5 +1,6 @@ const OCRResult = { SUCCESS: Symbol("SUCCESS"), + WRONG_PHONE_NUMBER: Symbol("WRONG_PHONE_NUMBER"), TO_REFRESH: Symbol("TO_REFRESH"), BLOCKED: Symbol("BLOCKED"), SLIDING_CAPTCHA: Symbol("SLIDING_CAPTCHA"), diff --git a/src/models/ReserveResultPojo.js b/src/models/ReserveResultPojo.js index b3a2f58..219a896 100644 --- a/src/models/ReserveResultPojo.js +++ b/src/models/ReserveResultPojo.js @@ -15,6 +15,7 @@ class ReserveResultPojo { this.email = mail; this.type = type; this.source_from = "" + this.serial = "" this.hostName = hostName this.created_at = new Date().toLocaleString() } @@ -30,6 +31,7 @@ class ReserveResultPojo { url: this.url, store_type: this.storeType, source_from: this.source_from, + serial: this.serial, created_at: this.created_at, hostName: this.hostName } diff --git a/src/queue/Sender.js b/src/queue/Sender.js index 3cccd6e..e665617 100644 --- a/src/queue/Sender.js +++ b/src/queue/Sender.js @@ -9,7 +9,9 @@ class Sender { connection; async initConnection() { - this.connection = await amqp.connect(QUEUE_HOST); + this.connection = await amqp.connect(QUEUE_HOST, { + timeout: 15000 + }); this.channel = await this.connection.createChannel(); await this.channel.assertQueue(REQUEST_DATA_QUEUE_FR, {persistent: true}); } diff --git a/src/workers/CommandorPage.js b/src/workers/CommandorPage.js index 0d8a290..3c888fd 100644 --- a/src/workers/CommandorPage.js +++ b/src/workers/CommandorPage.js @@ -71,6 +71,8 @@ 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; @@ -91,6 +93,16 @@ class CommandorPage { 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) { @@ -142,6 +154,31 @@ class CommandorPage { } } + 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.swipeForDevice(this.device, x, y0, x, 1522) + // 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)) { @@ -167,7 +204,9 @@ class CommandorPage { } // await this.acceptCookies(); await this.enableDisableAirPlanMode(); - // await delay(10 * 1000); + // 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() @@ -225,8 +264,27 @@ class CommandorPage { async acceptCookies() { logWithDevice("will accept Cookies", this.device); - if (this.browser.isConnected() && !this.page.isClosed()) { + 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++) { @@ -241,7 +299,6 @@ class CommandorPage { } catch (e) { console.log(e) } - } } @@ -697,6 +754,7 @@ class CommandorPage { } 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) @@ -715,6 +773,7 @@ class CommandorPage { // 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 { @@ -778,7 +837,7 @@ class CommandorPage { } async connectBrowserIfNecessary() { - if (!this.browser.isConnected()) { + if (this.browser == undefined || !this.browser.isConnected()) { try { this.browser = await puppeteer.connect({ browserWSEndpoint: "ws://127.0.0.1:" + this.port + "/devtools/browser", @@ -1037,10 +1096,19 @@ class CommandorPage { : await this.connect_to_browser(OCRResult.TO_REFRESH) break; + case OCRResult.WRONG_PHONE_NUMBER + : + this.isTerminated = true + break; case OCRResult.BLOCKED : - await this.resetBrowser(); + if (this.isAlreadyRefresh) { + await this.resetBrowser(); + } else { + this.isAlreadyRefresh = true; + await this.generateRandomActions() + } break; case OCRResult.ONLINE_APPOINTMENT @@ -1133,6 +1201,19 @@ class CommandorPage { await exec(cmd); } + async swipeForDevice(device, x0, y0, x1, y1) { + // let swipCmd = "input swipe " + x + " " + y0 + " " + x + " 1522" + let cmd = `adb -s ${device.serial()} shell input swipe ${x0} ${y0} ${x1} ${y1}` + 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) @@ -1147,6 +1228,44 @@ class CommandorPage { 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(); } @@ -1206,21 +1325,21 @@ class CommandorPage { 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) - // } + 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() { diff --git a/src/workers/OCRChecker.js b/src/workers/OCRChecker.js index 9d8c0ca..3064f2b 100644 --- a/src/workers/OCRChecker.js +++ b/src/workers/OCRChecker.js @@ -19,6 +19,7 @@ const MESSAGE_URL_VALIDATION_FR = "Vous recevrez un email de validation" const MESSAGE_URL_VALIDATION_FR_2 = "Merci de votre intérêt pour notre Maison" const SSL_CERT_ERROR = " Votre connexion n'est pas privée" const MESSAGE_URL_VALIDATION_EN = "Please click on the link we sent by email" +const WRONG_PHONE_NUMBER = "Veuillez renseigner vote numéro de téléphone" const CHOOSE_POSITION_GOOGLE_FR = " Choisir la position pour les résultats de recherche" const CAPTCHA_ERROR_MESSAGE = "Error verifying captcha, please try again" const CAPTCHA_ERROR_MESSAGE_FR = "La vérification du captcha a échoué" @@ -109,11 +110,17 @@ class OCRChecker { } else if (result.includes(SSL_CERT_ERROR)) { await this.deleteFile(fileName) return OCRResult.SSL_CERT_ERROR + } else if (result.includes(WRONG_PHONE_NUMBER)) { + await this.deleteFile(fileName) + return OCRResult.WRONG_PHONE_NUMBER } else if (result.includes(MESSAGE_FILL_FIELD_FR) || result.includes(MESSAGE_FILL_FIELD_FR_2) || result.includes(MESSAGE_FILL_FIELD_FR_3) || result.includes(MESSAGE_FILL_FIELD_FR_4) || result.includes(MESSAGE_FILL_FIELD_FR_5) || result.includes(MESSAGE_FILL_FIELD_FR_6)) { await this.deleteFile(fileName) return OCRResult.FILL_FIELD } else if (result.includes(CAPTCHA_ERROR_MESSAGE) || result.includes(CAPTCHA_ERROR_MESSAGE_FR)) { return OCRResult.RECAPTCHA_ERROR + } else if (result.includes(BRAVE_SKIP_PUB) || result.includes(BRAVE_SKIP_PUB_2) || result.includes(BRAVE_SKIP_PUB_3) || result.includes(BRAVE_SKIP_PUB_4) || result.includes(BRAVE_SKIP_PUB_5)) { + await this.deleteFile(fileName) + return OCRResult.BRAVE_PRIVACY_PUB } else if (result.includes(BLOCKED_MSG_EN) || result.includes(BLOCKED_MSG_FR) || result.includes(BLOCKED_MSG_FR_2) || result.includes(BLOCKED_MSG_FR_3)) { await this.deleteFile(fileName) return OCRResult.BLOCKED @@ -127,9 +134,6 @@ class OCRChecker { } else if (result.includes(BRAVE_NOTIFICATION)) { await this.deleteFile(fileName) return OCRResult.BRAVE_NOTIFICATION - } else if (result.includes(BRAVE_SKIP_PUB) || result.includes(BRAVE_SKIP_PUB_2) || result.includes(BRAVE_SKIP_PUB_3) || result.includes(BRAVE_SKIP_PUB_4) || result.includes(BRAVE_SKIP_PUB_5)) { - await this.deleteFile(fileName) - return OCRResult.BRAVE_PRIVACY_PUB } else if (result.includes(SLIDING_CAPTCHA_FR) || result.includes(SLIDING_CAPTCHA_FR_2) || result.includes(SLIDING_CAPTCHA_FR_3) || result.includes(SLIDING_CAPTCHA_FR_4) || result.includes(SLIDING_CAPTCHA_FR_5) || result.includes(SLIDING_CAPTCHA_FR_6)) { await this.deleteFile(fileName) if (result.includes(SLIDING_CAPTCHA_LOADING_FR)) {