diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e212594 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ + +node_modules diff --git a/README.md b/README.md new file mode 100644 index 0000000..ef0aa94 --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# 5090 Bot from wbuffetsukdik reddit user +Here's the github repository. It requires a bit of technical knowledge to set up, but not too hard. + +## Install nodeJS and NPM. + 1. Move the files in the repository into a folder on your computer named "GPUMonitor". + 1. Open the command line, navigate to the folder using "cd" to move to the file path + 1. When you are in the correct folder in the terminal, run the command "npm i". This installs a HTTP library that is required for the bot. + 1. Once installed, navigate to the parent directory of your folder. "cd.." if you are inside your folder. + 1. Run the command "node GPUMonitor" and the bot will begin running. + diff --git a/alarm.wav b/alarm.wav new file mode 100644 index 0000000..5ac5603 Binary files /dev/null and b/alarm.wav differ diff --git a/index.js b/index.js index fe86fac..ac0749d 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,8 @@ import fetch from 'node-fetch'; +import Aplay from 'node-aplay'; + + const url = 'https://www.bestbuy.com/gateway/graphql'; const headers = { @@ -22,51 +25,46 @@ const headers = { '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 +const skuIds = ["6614151","6578810","6616096","6617487","6614119","6614120","6616095","6616092","6616096","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: "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" }, + { zip: "97504", store: "2517" }, ]; let lines = 0; let found = false; let winningResult = null; -async function fetchGraphQL(zip, store) { +function playAlarm() { + new Aplay('alarm.wav').play(); +} + +async function fetchGraphQL(zip, store, query) { const body = { query, variables: { zip, store }, @@ -84,7 +82,7 @@ async function fetchGraphQL(zip, store) { } return await response.json(); } catch (err) { - console.error(`Error fetching for zip ${zip}, store ${store}:`, err); + console.error(`Error fetching for zip ${zip}, store ${store} query ${query}:`, err); return null; } } @@ -92,31 +90,34 @@ async function fetchGraphQL(zip, store) { 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; + for (const { skuId, query } of queries) { + const data = await fetchGraphQL(zip, store, query); + 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") { + found = true; + winningResult = { skuId, zip, store, buttonState, data }; + playAlarm() + return winningResult; + } + } else { + console.log(`Incomplete data for zip ${zip}, store ${store}.`); } - } 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'); + lines++ + if(lines > 30) { + lines = 0; + process.stdout.write('\x1B[3J\x1B[2J\x1B[H'); + } + await new Promise(resolve => setTimeout(resolve, 500)); } - await new Promise(resolve => setTimeout(resolve, 500)); } return null; } diff --git a/package-lock.json b/package-lock.json index 53e1744..9f96376 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "node-aplay": "^1.0.3", "node-fetch": "^3.3.2" } }, @@ -56,6 +57,12 @@ "node": ">=12.20.0" } }, + "node_modules/node-aplay": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/node-aplay/-/node-aplay-1.0.3.tgz", + "integrity": "sha512-sZmdPpIxHeAjOdP4lQy7hRfUQYdAabodx4+zedSf5Slpm36yWdnpNTLP3jZEsKBZfIIyvzZlCpRvP32skKjHnw==", + "license": "MIT" + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", diff --git a/package.json b/package.json index 6cf84e4..997b6c9 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "license": "ISC", "description": "", "dependencies": { + "node-aplay": "^1.0.3", "node-fetch": "^3.3.2" } }