2020-12-16 20:44:37 -05:00
|
|
|
#!/usr/bin/env node
|
|
|
|
|
|
|
|
const puppeteer = require("puppeteer"),
|
|
|
|
config = require("./config.json");
|
|
|
|
|
|
|
|
function log(message) {
|
|
|
|
console.log(`${new Date().toString().replace(/ GMT.*/, "")}: ${message}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function clickButtonWithText(page, text) {
|
|
|
|
const [ button ] = await page.$x(`//button[contains(., '${text}')]`);
|
|
|
|
|
|
|
|
if (typeof button !== "undefined") {
|
2021-01-04 19:48:11 -05:00
|
|
|
try {
|
|
|
|
await button.click();
|
|
|
|
return true;
|
|
|
|
} catch (err) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-12-16 20:44:37 -05:00
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function run() {
|
|
|
|
const browser = await puppeteer.launch({
|
|
|
|
headless: false,
|
|
|
|
product: "firefox",
|
|
|
|
defaultViewport: { width: 1440, height: 724 }
|
|
|
|
});
|
|
|
|
|
|
|
|
const page = await browser.newPage(),
|
2021-01-03 00:35:29 -05:00
|
|
|
maxVariance = 8,
|
2021-01-03 21:52:53 -05:00
|
|
|
refreshTries = Number(config.refresh_tries),
|
2021-01-03 00:35:29 -05:00
|
|
|
startTime = Number(config.start_time.replace(/:.*/, "")) + Number(config.start_time.replace(/^[^:]*:/, "")) / 60,
|
|
|
|
endTime = Number(config.end_time.replace(/:.*/, "")) + Number(config.end_time.replace(/^[^:]*:/, "")) / 60;
|
2020-12-16 20:44:37 -05:00
|
|
|
|
|
|
|
let success = true,
|
|
|
|
randomVariance = 0,
|
2021-01-03 00:35:29 -05:00
|
|
|
currentTry = 1,
|
|
|
|
date,
|
|
|
|
timeNow;
|
|
|
|
|
|
|
|
async function navigateToPage(url) {
|
|
|
|
try {
|
|
|
|
await page.goto(url, { waitUntil: "load" });
|
|
|
|
} catch (err) {
|
|
|
|
log(`Failed to navigate to ${url}, retrying in 30 seconds...`);
|
|
|
|
await page.waitForTimeout(30000);
|
|
|
|
await navigateToPage(url);
|
|
|
|
}
|
|
|
|
}
|
2020-12-16 20:44:37 -05:00
|
|
|
|
|
|
|
log("Started bot");
|
|
|
|
|
|
|
|
while (true) {
|
2021-01-03 00:35:29 -05:00
|
|
|
await navigateToPage("https://secure.newegg.ca/NewMyAccount/AccountLogin.aspx?nextpage=https%3a%2f%2fwww.newegg.ca%2f");
|
2020-12-16 20:44:37 -05:00
|
|
|
|
|
|
|
if (page.url().includes("signin")) {
|
|
|
|
try {
|
|
|
|
await page.waitForSelector("button.btn.btn-orange", { timeout: 2500 });
|
|
|
|
await page.type("#labeled-input-signEmail", config.username);
|
|
|
|
await page.click("button.btn.btn-orange");
|
|
|
|
await page.waitForTimeout(1500);
|
|
|
|
|
2020-12-31 20:35:51 -05:00
|
|
|
while (true) {
|
|
|
|
try {
|
|
|
|
await page.waitForSelector("#labeled-input-password", { timeout: 2500 });
|
|
|
|
await page.waitForSelector("button.btn.btn-orange");
|
|
|
|
await page.type("#labeled-input-password", config.password);
|
|
|
|
await page.click("button.btn.btn-orange");
|
|
|
|
log("Successfully logged in");
|
|
|
|
break;
|
|
|
|
} catch (err) {
|
|
|
|
try {
|
|
|
|
await page.waitForSelector(".nav-complex-inner .fa-caret-down", { timeout: 2500 });
|
|
|
|
log("Successfully logged in");
|
|
|
|
break;
|
|
|
|
} catch (err) {
|
|
|
|
log("Waiting for authorization");
|
|
|
|
await page.waitForTimeout(5000);
|
|
|
|
}
|
|
|
|
}
|
2020-12-16 20:44:37 -05:00
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
log("Fail: Login form missing");
|
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
await page.waitForTimeout(1000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
await page.waitForTimeout(3500);
|
|
|
|
|
|
|
|
while (true) {
|
2021-01-03 00:35:29 -05:00
|
|
|
date = new Date();
|
|
|
|
timeNow = date.getHours() + date.getMinutes() / 60;
|
2020-12-16 20:44:37 -05:00
|
|
|
|
2021-01-03 00:35:29 -05:00
|
|
|
if (timeNow >= startTime && timeNow <= endTime) {
|
|
|
|
await navigateToPage(`https://www.newegg.ca/${config.item_page}`);
|
2020-12-16 20:44:37 -05:00
|
|
|
|
2021-01-03 00:35:29 -05:00
|
|
|
if (await clickButtonWithText(page, "Add to cart")) {
|
|
|
|
log("Adding the product the to cart");
|
|
|
|
await page.waitForSelector(".modal-content", { timeout: 5000 });
|
|
|
|
await page.waitForTimeout(1000);
|
|
|
|
|
|
|
|
if (await clickButtonWithText(page, "No, thanks")) {
|
|
|
|
log("Rejected product coverage option");
|
|
|
|
}
|
2020-12-16 20:44:37 -05:00
|
|
|
|
2021-01-03 00:35:29 -05:00
|
|
|
try {
|
|
|
|
await page.waitForSelector(".message-title", { timeout: 5000 });
|
|
|
|
log("Successfully added the item to the cart!");
|
|
|
|
} catch (error) {
|
|
|
|
log("Fail: Added to cart but no success window appeared");
|
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2021-01-03 21:52:53 -05:00
|
|
|
} else if (refreshTries !== 0 && currentTry > refreshTries) {
|
|
|
|
log(`Fail: Maximum number of refresh tries reached (${refreshTries})`);
|
2020-12-16 20:44:37 -05:00
|
|
|
success = false;
|
2021-01-03 00:35:29 -05:00
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
randomVariance = Math.floor(Math.random() * maxVariance);
|
|
|
|
log(`(${currentTry}) Product currently unavailable, retrying in ${Number(config.refresh_time) + randomVariance} seconds...`);
|
|
|
|
currentTry++;
|
|
|
|
await page.waitForTimeout((Number(config.refresh_time) + randomVariance) * 1000);
|
2020-12-16 20:44:37 -05:00
|
|
|
}
|
|
|
|
} else {
|
2021-01-03 00:35:29 -05:00
|
|
|
log(`${date.getHours()}:${date.getMinutes()} is outside the active time period between ${config.start_time} and ${config.end_time}`);
|
|
|
|
await page.waitForTimeout(60000);
|
2020-12-16 20:44:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
while (true) {
|
|
|
|
log("Navigating to secure checkout");
|
2021-01-03 00:35:29 -05:00
|
|
|
await navigateToPage("https://secure.newegg.ca/shop/cart");
|
2020-12-16 20:44:37 -05:00
|
|
|
|
|
|
|
const totalPriceElement = await page.$(".summary-content-total span strong"),
|
|
|
|
totalPrice = await page.evaluate(totalPriceElement => totalPriceElement.textContent, totalPriceElement);
|
|
|
|
|
|
|
|
if (typeof totalPrice === "undefined" || totalPrice === "" || totalPrice === null) {
|
|
|
|
log("Fail: Unable to determine total price");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Number(totalPrice) > config.price_limit) {
|
|
|
|
log(`Fail: Total price of "${totalPrice}" exceeds price limit`);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (await clickButtonWithText(page, "Secure Checkout")) {
|
|
|
|
await page.waitForTimeout(3000);
|
|
|
|
|
|
|
|
if (await clickButtonWithText(page, "Continue to payment")) {
|
|
|
|
log("Continuing to payment...");
|
|
|
|
await page.waitForSelector("[placeholder=\"CVV2\"]", { timeout: 2500 });
|
|
|
|
await page.waitForTimeout(1000);
|
|
|
|
log("Filling out the cv2...");
|
|
|
|
await page.type("[placeholder=\"CVV2\"]", config.cv2);
|
|
|
|
|
|
|
|
if (await clickButtonWithText(page, "Review your order")) {
|
|
|
|
log("Reviewing order...");
|
|
|
|
|
|
|
|
if (config.auto_submit === "true") {
|
|
|
|
if (await clickButtonWithText(page, "Place Order")) {
|
|
|
|
log("Order placed!!!");
|
|
|
|
} else {
|
|
|
|
log("Fail: Unable to press the Place Order button");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log("The auto_submit config value is set to false");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log("Fail: Unable to click the 'Review your order' button");
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
await page.waitForTimeout(1000);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
await page.waitForTimeout(1000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!success) {
|
2020-12-31 20:35:51 -05:00
|
|
|
// await browser.close();
|
2020-12-16 20:44:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
run();
|