Initial commit
This commit is contained in:
commit
a337d0ad01
4 changed files with 201 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
package-lock.json
|
||||
node_modules
|
||||
config.json
|
10
config.example.json
Normal file
10
config.example.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"username":"",
|
||||
"password":"",
|
||||
"cv2":"",
|
||||
"item_page":"",
|
||||
"refresh_time":"60",
|
||||
"refresh_tries": "60",
|
||||
"price_limit":"925",
|
||||
"auto_submit":"true"
|
||||
}
|
164
newegg-purchaser.js
Executable file
164
newegg-purchaser.js
Executable file
|
@ -0,0 +1,164 @@
|
|||
#!/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") {
|
||||
await button.click();
|
||||
return true;
|
||||
} 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(),
|
||||
maxVariance = 8;
|
||||
|
||||
let success = true,
|
||||
randomVariance = 0,
|
||||
currentTry = 1;
|
||||
|
||||
log("Started bot");
|
||||
|
||||
while (true) {
|
||||
await page.goto("https://secure.newegg.ca/NewMyAccount/AccountLogin.aspx?nextpage=https%3a%2f%2fwww.newegg.ca%2f", { waitUntil: "load" });
|
||||
|
||||
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);
|
||||
|
||||
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");
|
||||
} catch (err) {
|
||||
log("Fail: Manual authorization code required by Newegg. This should only happen once.");
|
||||
success = false;
|
||||
}
|
||||
} catch (err) {
|
||||
log("Fail: Login form missing");
|
||||
success = false;
|
||||
}
|
||||
|
||||
break;
|
||||
} else {
|
||||
await page.waitForTimeout(1000);
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
await page.waitForTimeout(3500);
|
||||
|
||||
while (true) {
|
||||
await page.goto(`https://www.newegg.ca/${config.item_page}`, { waitUntil: "load" });
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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;
|
||||
} else if (currentTry > config.refresh_tries) {
|
||||
log(`Fail: Maximum number of refresh tries reached (${config.refresh_tries})`);
|
||||
success = false;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
while (true) {
|
||||
log("Navigating to secure checkout");
|
||||
await page.goto("https://secure.newegg.ca/shop/cart", { waitUntil: "load" });
|
||||
|
||||
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) {
|
||||
await browser.close();
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
24
readme.md
Normal file
24
readme.md
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Setup
|
||||
|
||||
## Install Dependencies
|
||||
|
||||
```
|
||||
PUPPETEER_PRODUCT=firefox npm install puppeteer
|
||||
```
|
||||
|
||||
## Setup Configuration
|
||||
|
||||
1. `cp config.example.json config.json`
|
||||
2. Edit `config.json`:
|
||||
* `username`: newegg username
|
||||
* `password`: newegg password
|
||||
* `cv2`: code on the back of your credit card
|
||||
* `item_page`: the part of the URL (starting with a slash) for the product after `https://www.newegg.ca` (eg: `/amd-ryzen-9-5900x/p/N82E16819113664`)
|
||||
* `refresh_time`: amount of time between page refreshes (with a random variance)
|
||||
* `refresh_tries`: the number of times the script will check before quitting (to avoid getting banned)
|
||||
* `auto_submit`: set this to false if you want to do a test run (everything up to the actual purchase)
|
||||
* `price_limit`: set this to a number you don't want your cart total to exceed before checking out
|
||||
|
||||
## Credits
|
||||
|
||||
Inspired by https://github.com/Ataraksia/NeweggBot
|
Loading…
Reference in a new issue