commit 276d74fac73a7a70674597df9fb70b21f54d4565 Author: YonkaDingo Date: Sun Feb 2 19:57:53 2025 -0800 Add files via upload diff --git a/index.js b/index.js new file mode 100644 index 0000000..fe86fac --- /dev/null +++ b/index.js @@ -0,0 +1,132 @@ +import fetch from 'node-fetch'; + +const url = 'https://www.bestbuy.com/gateway/graphql'; + +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', + 'mode': 'cors', + 'Origin': 'https://www.bestbuy.com', + 'Connection': 'keep-alive', + 'Sec-Fetch-Dest': 'empty', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Site': 'same-origin', + 'Priority': 'u=4', + 'TE': 'trailers' +}; + +const query = ` + query AOS_fetchButtonStateData($zip: String!, $store: String!) { + productBySkuId(skuId: "6614151") { + 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: "80487", store: "382" }, + { zip: "80487", store: "1079" }, + { zip: "80487", store: "693" }, + { zip: "80487", store: "164" }, + { zip: "80487", store: "1224" }, + { zip: "80487", store: "210" }, + { zip: "80487", store: "1416" }, + { zip: "80487", store: "211" }, + { zip: "80487", store: "225" }, + { zip: "80487", store: "1124" }, + { zip: "80487", store: "1194" }, + { zip: "80487", store: "298" }, + { zip: "80487", store: "212" }, + { zip: "80487", store: "1171" }, + { zip: "80487", store: "1031" }, + ]; + +let lines = 0; +let found = false; +let winningResult = null; + +async function fetchGraphQL(zip, store) { + 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}:`, err); + return null; + } +} + +async function pollStore(zip, store) { + console.log(`Starting poll for zip ${zip} and store ${store}...`); + while (!found) { + const data = await fetchGraphQL(zip, store); + 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(`Store: ${store} Ship to: ${zip} -> buttonState: ${buttonState}`); + if (buttonState !== "SOLD_OUT") { + found = true; + winningResult = { zip, store, buttonState, data }; + 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)); + process.exit(0); +} + +runAllPollers(); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..53e1744 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,106 @@ +{ + "name": "gpumonitor", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "gpumonitor", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "node-fetch": "^3.3.2" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6cf84e4 --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "gpumonitor", + "version": "1.0.0", + "main": "index.js", + "type": "module", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "node-fetch": "^3.3.2" + } +}