263 lines
12 KiB
JavaScript
263 lines
12 KiB
JavaScript
const {_android: android} = require('playwright');
|
|
const ExcelUtil = require("./excel/ExcelUtil");
|
|
const CommandorPage = require("./workers/CommandorPage");
|
|
const {MongoManager, formatDate} = require("./workers/mongo_manager");
|
|
const alert = require('alert');
|
|
const schedule = require("node-schedule");
|
|
const DeviceExcludeMode = require("./models/DeviceExcludeMode");
|
|
const Sender = require("./queue/Sender");
|
|
const mongoManager = new MongoManager();
|
|
const SEVEN_DAYS_IN_S = 3600 * 24 * 7;
|
|
// const NINETY_DAYS_IN_S = 3600 * 24 * 30 * 3;
|
|
const NINETY_DAYS_IN_S = 30 * 3;
|
|
let excelUtil = new ExcelUtil();
|
|
let collectionName = formatDate(new Date())
|
|
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"]
|
|
let nine_to_excludes = ["bec11752", "4e8ca027", "hi7ljr5xduyt9pfi", "47e7e36b", "p7d6nbw8cu7duous", "njzxojhim7gedyvw", "fmiz5pa6rsx4u4ts", "fuljaueqguugf6pn", "EPHUT20825001518", "W8GMFELRHIKZS84T"]
|
|
let for_scrpay = ["07fbd156", "47e7e36b", "4f55c3d4", "5ac879a2", "69db59f0", "71a0371d", "774687ff", "7b71fb20", "8f76f9e7", "99cyfiaebqcy6poj", "EPHUT20825001518", "J4AXB761H2322WJ", "W8GMFELRHIKZS84T", "ai9xv8hy599hvkee", "b41c1b72", "bec11752", "becb6e99", "c3ba032e", "d54e946", "fmiz5pa6rsx4u4ts", "fuljaueqguugf6pn", "fy65eqs4wkvcpf9h", "hi7ljr5xduyt9pfi", "njzxojhim7gedyvw", "p7d6nbw8cu7duous"]
|
|
attributedPorts = []
|
|
const device_port_info = new Map();
|
|
startPort = 9000
|
|
|
|
async function filterAlreadyBookedContacts(contactList) {
|
|
let alreadyBookedContacts = await mongoManager.getAllSuccessfulItemsForDay(collectionName);
|
|
let contactsToBook = [];
|
|
contactList.forEach((contact) => {
|
|
if (alreadyBookedContacts.find((bookedContact) => bookedContact.email === contact.mail) === undefined) {
|
|
contactsToBook.push(contact)
|
|
}
|
|
})
|
|
return contactsToBook;
|
|
}
|
|
|
|
async function filterAlreadyAcceptedContacts(contactList) {
|
|
let alreadyBookedContacts = await mongoManager.getAllAcceptedAppointments();
|
|
let contactsToBook = [];
|
|
contactList.forEach((contact) => {
|
|
let needToBook = true;
|
|
alreadyBookedContacts.forEach((acceptedItem) => {
|
|
if (acceptedItem.email === contact.mail) {
|
|
console.log("=====handle already accepted item before booking====");
|
|
console.log("accepted_at is " + acceptedItem.accepted_at);
|
|
console.log("accepted email is " + acceptedItem.email);
|
|
needToBook = acceptedItem.accepted_at + NINETY_DAYS_IN_S <= (new Date()) / 1000;
|
|
if (!needToBook) {
|
|
console.log("already accepted appointment --> skip");
|
|
}
|
|
}
|
|
})
|
|
if (needToBook) {
|
|
contactsToBook.push(contact)
|
|
}
|
|
})
|
|
return contactsToBook;
|
|
}
|
|
|
|
async function filterBlacklistedContacts(contactList) {
|
|
let blackListedContacts = await mongoManager.getAllBlackedListItems();
|
|
let contactsToBook = [];
|
|
contactList.forEach((contact) => {
|
|
let needToBook = true;
|
|
blackListedContacts.forEach((blackListItem) => {
|
|
if (blackListItem.mail === contact.mail) {
|
|
console.log("=====handle blacklist item before booking=====");
|
|
console.log("update_at_s is " + blackListItem.update_at_in_s)
|
|
console.log("black list email is " + blackListItem.mail)
|
|
needToBook = blackListItem.update_at_in_s + SEVEN_DAYS_IN_S <= (new Date()) / 1000;
|
|
if (!needToBook) {
|
|
console.log("contact in blacklist -->skip");
|
|
}
|
|
}
|
|
})
|
|
if (needToBook) {
|
|
contactsToBook.push(contact)
|
|
}
|
|
})
|
|
return contactsToBook;
|
|
}
|
|
|
|
async function needToBook(contact, mongoManager, alreadyBooked) {
|
|
console.log("check contact with email " + contact.mail)
|
|
// let alreadyBooked = await mongoManager.getAllSuccessfulItemsForDay(collectionName);
|
|
// let blackListItems = await mongoManager.getAllBlackedListItems();
|
|
let blackListItems = [];
|
|
// let alreadyAcceptedItems = await mongoManager.getAllAcceptedAppointments();
|
|
let needToBook = true;
|
|
await alreadyBooked.forEach((bookedItem) => {
|
|
if (bookedItem.email === contact.mail) {
|
|
needToBook = false;
|
|
}
|
|
}
|
|
)
|
|
if (needToBook) {
|
|
await blackListItems.forEach((blackListItem) => {
|
|
if (blackListItem.mail === contact.mail) {
|
|
console.log("=====handle blacklist item====");
|
|
console.log("update_at_s is " + blackListItem.update_at_in_s)
|
|
console.log("black list email is " + blackListItem.mail)
|
|
needToBook = blackListItem.update_at_in_s + SEVEN_DAYS_IN_S <= (new Date()) / 1000;
|
|
if (!needToBook) {
|
|
console.log("contact in blacklist -->skip");
|
|
}
|
|
}
|
|
})
|
|
}
|
|
// if (needToBook) {
|
|
// await alreadyAcceptedItems.forEach((acceptedItem) => {
|
|
// if (acceptedItem.email === contact.mail) {
|
|
// console.log("=====handle already accepted item====");
|
|
// console.log("accepted_at is " + acceptedItem.accepted_at);
|
|
// console.log("accepted email is " + acceptedItem.email);
|
|
// needToBook = acceptedItem.accepted_at + NINETY_DAYS_IN_S <= (new Date()) / 1000;
|
|
// if (!needToBook) {
|
|
// console.log("already accepted appointment --> skip");
|
|
// }
|
|
// }
|
|
// })
|
|
// }
|
|
return needToBook
|
|
}
|
|
|
|
async function startBook(contactPojo, device, sender, selectedStore, audioAnalyse, alertBeep, port) {
|
|
console.log(`model: ${device.model()}`);
|
|
console.log(`serial: ${device.serial()}`);
|
|
let alreadyBooked = await mongoManager.getAllSuccessfulItemsForDay(collectionName);
|
|
const d = new Date();
|
|
let hour = d.getHours();
|
|
if (hour >= 19) {
|
|
console.log("do not continue after 19h")
|
|
return
|
|
}
|
|
if (await needToBook(contactPojo, mongoManager, alreadyBooked)) {
|
|
let commandor = new CommandorPage(contactPojo, device, sender, mongoManager, selectedStore, audioAnalyse, alertBeep, port);
|
|
//read contacts form excel
|
|
return await commandor.loadPage();
|
|
} else {
|
|
console.log("do not send request --> skip")
|
|
}
|
|
}
|
|
|
|
async function startWithList(contacts, device, sender, selectedStore, audioAnalyse, alertBeep, port) {
|
|
let duplicatedList = [].concat(contacts).concat(contacts).concat(contacts)
|
|
await duplicatedList.reduce(async (promise, contactPojo) => {
|
|
// This line will wait for the last async function to finish.
|
|
// The first iteration uses an already resolved Promise
|
|
// so, it will immediately continue.
|
|
await promise;
|
|
const contents = await startBook(contactPojo, device, sender, selectedStore, audioAnalyse, alertBeep, port);
|
|
console.log(contents);
|
|
}, Promise.resolve());
|
|
}
|
|
|
|
async function scheduleBookWithNumbers(startNumber, endNumber, selectedStore, pathToExcelFile = '/Users/lpan/Desktop/contact_all.xlsx', audioAnalyse = true, alertBeep = false) {
|
|
console.log("scheduleBookWithNumbers() called")
|
|
alert("定时成功")
|
|
schedule.scheduleJob('30 10 * * *', function () {
|
|
console.log("start startBookWithNumbers")
|
|
startBookWithNumbers(startNumber, endNumber, selectedStore, pathToExcelFile, audioAnalyse, alertBeep)
|
|
})
|
|
}
|
|
|
|
function shuffle(array) {
|
|
let currentIndex = array.length, randomIndex;
|
|
// While there remain elements to shuffle.
|
|
while (currentIndex !== 0) {
|
|
// Pick a remaining element.
|
|
randomIndex = Math.floor(Math.random() * currentIndex);
|
|
currentIndex--;
|
|
// And swap it with the current element.
|
|
[array[currentIndex], array[randomIndex]] = [
|
|
array[randomIndex], array[currentIndex]];
|
|
}
|
|
|
|
return array;
|
|
}
|
|
|
|
async function startBookWithNumbers(startNumber, endNumber, selectedStore, pathToExcelFile = '/Users/lpan/Desktop/contact_all.xlsx', audioAnalyse = true, alertBeep = false) {
|
|
console.log("startBookWithNumbers() called, with alertBeep:" + alertBeep)
|
|
console.log("startBookWithNumbers() called, with audioAnalyse:" + audioAnalyse)
|
|
let allContactList = excelUtil.readContacts(pathToExcelFile);
|
|
let contactList;
|
|
if (endNumber <= allContactList.length) {
|
|
contactList = allContactList.slice(startNumber, endNumber);
|
|
} else {
|
|
contactList = allContactList.slice(startNumber, allContactList.length);
|
|
}
|
|
if (contactList.length === 0) {
|
|
alert("联系人数为0")
|
|
return
|
|
}
|
|
|
|
function startForwordingForDevice(device) {
|
|
console.log("startForwordingForDevice() called")
|
|
const execSync = require('child_process').execSync;
|
|
// get attributed port
|
|
let attributedPort = device_port_info[device.serial()]
|
|
if (attributedPort) {
|
|
let cmd = 'adb -s ' + device.serial() + " forward tcp:" + attributedPort + " localabstract:chrome_devtools_remote";
|
|
console.log("cmd is " + cmd);
|
|
const output = execSync(cmd, {encoding: 'utf-8'}); // the default is 'buffer'
|
|
console.log('Output was:\n', output);
|
|
} else {
|
|
attributedPort = startPort;
|
|
startPort++;
|
|
let cmd = 'adb -s ' + device.serial() + " forward tcp:" + attributedPort + " localabstract:chrome_devtools_remote";
|
|
console.log("cmd is " + cmd);
|
|
const output = execSync(cmd, {encoding: 'utf-8'}); // the default is 'buffer'
|
|
console.log('Output was:\n', output);
|
|
}
|
|
// start chrome
|
|
// device.shell("am start -n com.brave.browser/com.google.android.apps.chrome.Main")
|
|
return attributedPort
|
|
}
|
|
|
|
let sender = new Sender()
|
|
sender.initConnection().then((r) => {
|
|
console.log("queue connected")
|
|
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);
|
|
}
|
|
})
|
|
})
|
|
}
|
|
)
|
|
})
|
|
});
|
|
})
|
|
|
|
}
|
|
|
|
module.exports = {startBookWithNumbers, scheduleBookWithNumbers} |