import fetch from 'node-fetch'; import { playAudioFile } from 'audic'; import open from 'open'; import puppeteer from 'puppeteer-extra'; import StealthPlugin from 'puppeteer-extra-plugin-stealth'; import AnonymizeUAPlugin from 'puppeteer-extra-plugin-anonymize-ua'; import AdblockerPlugin from 'puppeteer-extra-plugin-adblocker'; import fs from 'fs'; const url = 'https://www.bestbuy.com/gateway/graphql'; // toggle browser for platform. const browser_path = 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'; //const browser_path = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome'; puppeteer.use(StealthPlugin()); puppeteer.use(AnonymizeUAPlugin()); puppeteer.use( AdblockerPlugin({ blockTrackers: true, } )); const headers = { 'Host': 'www.bestbuy.com', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0', 'Accept': 'application/json', 'Accept-Language': 'en-US,en;q=0.5', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Referer': 'https://www.bestbuy.com/site/nvidia-geforce-rtx-5090-32gb-gddr7-graphics-card-dark-gun-metal/6614151.p?skuId=6614151', 'X-REQUEST-ID': 'add-on-selector', 'X-CLIENT-ID': 'ATTACH-accessories-in-variations', 'Content-Type': 'application/json', 'Origin': 'https://www.bestbuy.com', 'Connection': 'keep-alive', }; const skuIds = ["6614151","6616096","6617487","6614119","6614120","6616095","6616092","6614122","6616093","6616090","6616091","6615930","6615929","6615931"] const queries = skuIds.map(skuId => ({ skuId, query: ` query AOS_fetchButtonStateData($zip: String!, $store: String!) { productBySkuId(skuId: "${skuId}") { fulfillmentOptions( input: { buttonState: {context: PDP, destinationZipCode: $zip, storeId: $store}, shipping: {destinationZipCode: $zip}, inStorePickup: {storeId: $store} } ) { buttonStates { buttonState planButtonState displayText skuId } } } } ` })); //CHANGE YOUR STORES HERE const params = [ { zip: "97504", store: "2517" }, ]; let lines = 0; let found = false; let winningResult = null; function getProductUrl(skuId) { return `https://www.bestbuy.com/site/${skuId}.p?skuId=${skuId}`; } async function addToCart(productUrl) { const browser = await puppeteer.launch({ headless: false, defaultViewport: null, ignoreDefaultArgs: ["--disable-extensions"], dumpio: true, args: ["--start-maximized", "--no-sandbox", "--disable-setuid-sandbox"], executablePath: browser_path, }); const page = await browser.newPage(); // Load cookies try{ const cookies = JSON.parse(fs.readFileSync('./cookies.json', 'utf8')); await page.setCookie(...cookies); }catch (error){ console.error('An error occurred:',error) } // Load local storage data try{ const localStorageData = JSON.parse(fs.readFileSync('./localStorage.json', 'utf8')); await page.evaluateOnNewDocument((data) => { for (const key in data) { localStorage.setItem(key, data[key]); } }, localStorageData); }catch (error){ console.error('An error occurred:',error) } await page.goto(productUrl); // Wait for the "Add to Cart" button to be available and click it try{ await page.waitForSelector('.add-to-cart-button',{ timeout: 300000 }); await page.click('.add-to-cart-button'); console.log('Item added to cart'); await page.waitForSelector('button.btn-primary[data-track="Checkout - Top"]',{ timeout: 300000 }); await page.click('button.btn-primary[data-track="Checkout - Top"]'); console.log('Checkout button clicked'); }catch (error){ console.error('An error occurred:',error) } } async function fetchGraphQL(zip, store, query) { const body = { query, variables: { zip, store }, operationName: "AOS_fetchButtonStateData" }; try { const response = await fetch(url, { method: 'POST', headers, body: JSON.stringify(body) }); if (!response.ok) { throw new Error(`HTTP error: ${response.status}`); } return await response.json(); } catch (err) { console.error(`Error fetching for zip ${zip}, store ${store} query ${query}:`, err); return null; } } async function pollStore(zip, store) { console.log(`Starting poll for zip ${zip} and store ${store}...`); const batchSize = 5; while (!found) { const queryBatches = []; for (let i = 0; i < queries.length; i += batchSize) { queryBatches.push(queries.slice(i, i + batchSize)); } for (const batch of queryBatches) { const fetchPromises = batch.map(({ skuId, query }) => fetchGraphQL(zip, store, query).then(data => ({ skuId, data }))); const results = await Promise.all(fetchPromises); for (const { skuId, data } of results) { if ( data && data.data && data.data.productBySkuId && data.data.productBySkuId.fulfillmentOptions && data.data.productBySkuId.fulfillmentOptions.buttonStates && data.data.productBySkuId.fulfillmentOptions.buttonStates.length > 0 ) { const buttonState = data.data.productBySkuId.fulfillmentOptions.buttonStates[0].buttonState; console.log(`skuId: ${skuId} Store: ${store} Ship to: ${zip} -> buttonState: ${buttonState}`); if (buttonState !== "SOLD_OUT" && buttonState !== "NOT_AVAILABLE") { found = true; const productUrl = getProductUrl(skuId); console.log(productUrl); winningResult = { skuId, zip, store, buttonState, data }; const openPromise = open(productUrl); const addToCartPromise = addToCart(productUrl); await open('./alarm.wav'); await addToCartPromise; return winningResult; } } else { console.log(`Incomplete data for zip ${zip}, store ${store}.`); } lines++; if (lines > 30) { lines = 0; process.stdout.write('\x1B[3J\x1B[2J\x1B[H'); } await new Promise(resolve => setTimeout(resolve, 500)); } } } return null; } async function runAllPollers() { const pollers = params.map(({ zip, store }) => pollStore(zip, store)); const result = await Promise.race(pollers); console.log("Found a store with available button state:"); console.log(JSON.stringify(result, null, 2)); } runAllPollers();