From b9ec1f67f4d811a44e497053a01a23f53bb9cada Mon Sep 17 00:00:00 2001 From: _dev Date: Thu, 6 Mar 2025 23:58:43 -0800 Subject: [PATCH] Update best-buy-tm.js Code Optimization & Button Detection Fixed CVV Input Centralized button detection using findButton function Added BUTTON_CLASSES configuration object for easier maintenance Improved error handling for button interactions Standardized color detection for button states Reduced code duplication across event handlers Added better logging for button state changes --- best-buy-tm.js | 1556 +++++++++++++++++++++++++----------------------- 1 file changed, 801 insertions(+), 755 deletions(-) diff --git a/best-buy-tm.js b/best-buy-tm.js index 15bd2fe..bab27eb 100644 --- a/best-buy-tm.js +++ b/best-buy-tm.js @@ -3,7 +3,7 @@ // @include https://www.bestbuy.com/* // @updateURL https://raw.githubusercontent.com/kkapuria3/BestBuy-GPU-Bot/main/best-buy-tm.js // @downloadURL https://raw.githubusercontent.com/kkapuria3/BestBuy-GPU-Bot/main/best-buy-tm.js -// @version 4.4 +// @version 4.5 // @description This aint bot, its RefreshNoBot // @author Karan Kapuria // @grant window.close @@ -55,6 +55,14 @@ // - Updated Final Checkout Item list to validate item is in cart on final screen correctly // - Corrected SMS/Text checkbox and added console logging to trace // - Update Final Checkout Place Order Button +// 4.5 Code Optimization & Button Detection +// - Fixed CVV Input +// - Centralized button detection using findButton function +// - Added BUTTON_CLASSES configuration object for easier maintenance +// - Improved error handling for button interactions +// - Standardized color detection for button states +// - Reduced code duplication across event handlers +// - Added better logging for button state changes */ // ==/UserScript== @@ -74,847 +82,885 @@ |___/___|___/ |_| |___/\___/ |_| |___/\___/ |_| */ - "use strict"; - //________________________________________________________________________ +"use strict"; +//________________________________________________________________________ - // CONSTANTS - // [ Do not add/remove quotation marks when updating] - //________________________________________________________________________ +// CONSTANTS +// [ Do not add/remove quotation marks when updating] +//________________________________________________________________________ - //____ REQUIRED FLAGS ____________________________________________________ +//____ REQUIRED FLAGS ____________________________________________________ + +const ITEM_KEYWORD = "PNY"; // NO SPACES IN KEYWORD - ONLY ONE WORD +const CREDITCARD_CVV = "***"; // BOT will run without changing this value. +const TESTMODE = "Yes"; // TESTMODE = "No" will buy the card +const SMS_DIGITS = "****"; // Enter last 4 digits of phone # for SMS verification (required for verification) +const PREFERRED_SHIPPING = "No"; // "Yes" will select shipping option if available - const ITEM_KEYWORD= "PNY"; // NO SPACES IN KEYWORD - ONLY ONE WORD - const CREDITCARD_CVV = "***"; // BOT will run without changing this value. - const TESTMODE = "Yes"; // TESTMODE = "No" will buy the card - const SMS_DIGITS = "****"; // Enter last 4 digits of phone # for SMS verification (required for verification) - const PREFERRED_SHIPPING = "No" // "Yes" will select shipping option if available - //____ PLEASE WAIT FLAGS : ADVANCED OPTIONS _____________________________ - //const QUEUE_TIME_CUTOFF = 0 // (in Minutes) Keep retrying until queue time is below. - //onst NEW_QUEUE_TIME_DELAY = 5 // (in Seconds) Ask new queue time set seconds - const OOS_REFRESH = 10 // (in Seconds) Refresh rate on OOS item. +//const QUEUE_TIME_CUTOFF = 0 // (in Minutes) Keep retrying until queue time is below. +//onst NEW_QUEUE_TIME_DELAY = 5 // (in Seconds) Ask new queue time set seconds +const OOS_REFRESH = 10; // (in Seconds) Refresh rate on OOS item. - //____ LAZY FLAGS : WILL NOT AFFECT BOT PERFORMACE _____________________ +//____ LAZY FLAGS : WILL NOT AFFECT BOT PERFORMACE _____________________ - const MAX_RETRIES = "500" // Fossil of EARTH +const MAX_RETRIES = "500"; // Fossil of EARTH - //________________________________________________________________________ +//________________________________________________________________________ - // Chime Sound - //________________________________________________________________________ +// Chime Sound +//________________________________________________________________________ // Play a chime sound to notify the user function playChime() { - // You can choose any online sound file. - const chimeUrl = "https://github.com/kkapuria3/BestBuy-GPU-Bot/blob/dev-v2.5-mem_leak_fix/resources/alert.mp3?raw=true"; + // You can choose any online sound file. + const chimeUrl = + "https://github.com/kkapuria3/BestBuy-GPU-Bot/blob/dev-v2.5-mem_leak_fix/resources/alert.mp3?raw=true"; const audio = new Audio(chimeUrl); - audio.play().catch(err => console.error("Audio play failed:", err)); + audio.play().catch((err) => console.error("Audio play failed:", err)); } - //________________________________________________________________________ +//________________________________________________________________________ - // Queue Timer Functions - //________________________________________________________________________ +// Queue Timer Functions +//________________________________________________________________________ function n(e, t) { - return parseInt(e, t) - } + return parseInt(e, t); +} function r(e, t) { - return e[t] + return e[t]; } function getQueueTimeFromEncodedString(e) { var t = ("-", e.split("-")), - l = t.map((function (e) { - return n(e, 16) - })); - return function (e) { - return 1e3 * e - }(function (e, t) { - return e / t - }(n(function (e, t) { - return e + t - }(r(t, 2), r(t, 3)), 16), r(l, 1))) + l = t.map(function (e) { + return n(e, 16); + }); + return (function (e) { + return 1e3 * e; + })( + (function (e, t) { + return e / t; + })( + n( + (function (e, t) { + return e + t; + })(r(t, 2), r(t, 3)), + 16 + ), + r(l, 1) + ) + ); } -function getRecordForSku(sku){ - const queues= JSON.parse(atob(localStorage.getItem('purchaseTracker'))); +function getRecordForSku(sku) { + const queues = JSON.parse(atob(localStorage.getItem("purchaseTracker"))); console.log(queues); const skuQueue = queues[sku]; - if(!skuQueue){ + if (!skuQueue) { return null; } return skuQueue; } -function getQueueTimeStartMs(sku){ +function getQueueTimeStartMs(sku) { return getRecordForSku(sku)[0]; } -function getQueueDurationMs(sku){ +function getQueueDurationMs(sku) { return getQueueTimeFromEncodedString(getRecordForSku(sku)[2]); } -var sku = location.search.split('=')[1]; -console.log('found sku', sku); +var sku = location.search.split("=")[1]; +console.log("found sku", sku); // This function will be called when Please wait is detected to return queue time - let checkQueueTimeRemaining = () => { - try { - var startMs = getQueueTimeStartMs(sku); - var durationMs = getQueueDurationMs(sku); - var durationMin = Math.trunc(durationMs / 60000); - var durationSec = Math.trunc((durationMs / 1000) - (durationMin * 60)); - var remainingMs = startMs + durationMs - new Date().getTime(); - var remainingMin = Math.trunc(remainingMs / 60000); - var remainingSec = Math.trunc((remainingMs / 1000) - (remainingMin * 60)); +let checkQueueTimeRemaining = () => { + try { + var startMs = getQueueTimeStartMs(sku); + var durationMs = getQueueDurationMs(sku); + var durationMin = Math.trunc(durationMs / 60000); + var durationSec = Math.trunc(durationMs / 1000 - durationMin * 60); + var remainingMs = startMs + durationMs - new Date().getTime(); + var remainingMin = Math.trunc(remainingMs / 60000); + var remainingSec = Math.trunc(remainingMs / 1000 - remainingMin * 60); + + return [remainingMin, remainingSec]; + } catch (e) { } +}; + +//________________________________________________________________________ + +// Create Floating Status Bar +//________________________________________________________________________ + +function createFloatingBadge(mode, status) { + const iconUrl = "https://kkapuria3.github.io/images/KK.png"; + const $container = document.createElement("div"); + const $bg = document.createElement("div"); + const $link = document.createElement("a"); + const $img = document.createElement("img"); + const $text = document.createElement("P"); + const $mode = document.createElement("P"); + const $status1 = document.createElement("P"); + + $link.setAttribute("href", "https://github.com/kkapuria3"); + $link.setAttribute("target", "_blank"); + $link.setAttribute("title", "RefreshNoBot"); + $img.setAttribute("src", iconUrl); + var MAIN_TITLE = + " OpenSourceBots | BestBuyBot v4.4 | ◻️TESTMODE: " + + TESTMODE + + "◻️ITEM KEYWORD: " + + ITEM_KEYWORD + + "◻️OOS REFRESH: " + + OOS_REFRESH; + $text.innerText = MAIN_TITLE; + $mode.innerText = mode; + $status1.innerText = status; + + $container.style.cssText = + "position:fixed;left:0;bottom:0;width:850px;height:75px;background: black;"; + $bg.style.cssText = + "position:absolute;left:-100%;top:0;width:60px;height:55px;background:#1111;box-shadow: 0px 0 10px #060303; border: 1px solid #FFF;"; + $link.style.cssText = + "position:absolute;display:block;top:11px;left: 0px; z-index:10;width: 50px;height:50px;border-radius: 1px;overflow:hidden;"; + $img.style.cssText = "display:block;width:100%"; + $text.style.cssText = + "position:absolute;display:block;top:3px;left: 50px;background: transperant; color: white;"; + $mode.style.cssText = + "position:absolute;display:block;top:22px;left: 50px;background: transperant; color: white;"; + $status1.style.cssText = + "position:absolute;display:block;top:43px;left: 50px;background: transperant; color: white;"; + + $link.appendChild($img); + $container.appendChild($bg); + $container.appendChild($link); + $container.appendChild($text); + $container.appendChild($mode); + $container.appendChild($status1); + + return $container; +} + +//________________________________________________________________________ + +// FUNCTIONS | Writing seperate EventHandlers so we can prevent memory leak for long running bots +//________________________________________________________________________ + +// Ideas developed based on : https://stackoverflow.com/questions/13677589/addeventlistener-memory-leak-due-to-frames/13702786#13702786 +//________________________________________________________________________ + +// CART PAGE EventHandler +//________________________________________________________________________ + +// Create a configuration object for button classes +const BUTTON_CLASSES = { + outOfStock: { + L1: "c-button c-button-disabled c-button-lg c-button-block add-to-cart-button", + L2: "btn btn-disabled btn-lg btn-block add-to-cart-button", + L3: "c-button c-button-disabled c-button-lg c-button-block add-to-cart-button", + }, + inStock: { + L1: "btn btn-primary btn-lg btn-block btn-leading-ficon add-to-cart-button", + L2: "c-button c-button-primary c-button-lg c-button-block c-button-icon c-button-icon-leading add-to-cart-button", + L3: "c-button c-button-secondary c-button-md c-button-block", + }, + goToCart: { + L1: "c-button c-button-secondary btn btn-secondary btn-sm c-button-sm btn-block c-button-block", + L2: "c-button c-button-secondary c-button-sm c-button-block", + L3: "c-button c-button-secondary c-button-md c-button-block", + }, + continue: { + L1: "btn btn-secondary btn-lg btn-block c-button-icon c-button-icon-leading cia-form__controls__submit", + L2: "c-button c-button-secondary c-button-lg c-button-block c-button-icon c-button-icon-leading cia-form__controls__submit", + L3: "c-button c-button-secondary c-button-md c-button-block" + } +}; + +// Helper function to find button by classes +function findButton(buttonType) { + const classes = BUTTON_CLASSES[buttonType]; + console.log(`Checking for ${buttonType} Button`); + for (const [key, className] of Object.entries(classes)) { + const button = document.getElementsByClassName(className); + if (button.length > 0) { + console.log(`${buttonType} Button Class ${key}: ${className}`); + return button; + } + } + console.log(`No ${buttonType} Button Found`); + return null; +} - return [remainingMin, remainingSec] +function cartpageoperationsEvenHandler(evt) { + setTimeout(() => { + if (location.href.includes("www.bestbuy.com/cart")) { + // Create and display the badge + const $badge = createFloatingBadge( + "Cart Page 🛑 Do Not Refresh. Only one item can be carted per account.", + "Verfying that first item in CART has KEYWORD" + ); + document.body.appendChild($badge); + $badge.style.transform = "translate(0, 0)"; + + // Wait 3 seconds on Cart Page + setTimeout(() => { + const CartItemCheck = document.getElementsByClassName( + "cart-item__title focus-item-0" + ); + if ( + CartItemCheck[0] && + CartItemCheck[0].innerHTML.includes(ITEM_KEYWORD) + ) { + console.log("Item Has been Confirmed!"); + + // Select the shipping button universally using an attribute selector + const shippingButton = document.querySelector( + "input[id^='fulfillment-shipping-']" + ); + if (shippingButton && PREFERRED_SHIPPING === "Yes") { + console.log( + "Shipping button found. Waiting 3 seconds before clicking it." + ); + // Delay shipping button click by 3 seconds + setTimeout(() => { + shippingButton.click(); + console.log( + "Shipping button clicked. Waiting 3 seconds before clicking checkout." + ); + + // Wait an additional 3 seconds after clicking shipping button + setTimeout(() => { + const CheckoutButton = document.getElementsByClassName( + "btn btn-lg btn-block btn-primary" + ); + if (CheckoutButton[0]) { + console.log("Clicking Checkout"); + CheckoutButton[0].click(); + } + }, 3000); + }, 3000); + } else { + console.log( + "Shipping button not found. Clicking Checkout immediately." + ); + const CheckoutButton = document.getElementsByClassName( + "btn btn-lg btn-block btn-primary" + ); + if (CheckoutButton[0]) { + CheckoutButton[0].click(); + } + } + } + }, 3000); + } + }, 5000); +} - } catch (e) { - } - }; +//________________________________________________________________________ - //________________________________________________________________________ +// VERIFICATION PAGE EventHandler +//________________________________________________________________________ - // Create Floating Status Bar - //________________________________________________________________________ +function verificationpageEventHandler(evt) { + console.log("Verification Step Reached"); + playChime(); + + setTimeout(() => { + if (location.href.indexOf("identity/signin/recoveryOptions") > -1) { + const $badge = createFloatingBadge( + "Get Ready To Verify 🛑 Do Not Refresh", + "Validating and Entering SMS Digits | It will error if you haven't updated SMS_DIGITS" + ); + document.body.appendChild($badge); + $badge.style.transform = "translate(0, 0)"; + + setTimeout(() => { + const ContinueButton = findButton('continue'); + const smsInput = document.getElementById("smsDigits"); + + if (smsInput) { + smsInput.focus(); + smsInput.select(); + if (!document.execCommand("insertText", false, SMS_DIGITS)) { + smsInput.value = SMS_DIGITS; + } + } + + if (ContinueButton && ContinueButton.length === 1) { + ContinueButton[0].click(); + } + }, 2500); + } + }, 3000); +} + +//________________________________________________________________________ + +// SECOND ADD TO CART EventHandler +//________________________________________________________________________ + +function pleasewaitcompletedEventHandler(evt) { + setTimeout(() => { + const GotoCartButton = findButton('goToCart'); + if (!GotoCartButton) { + console.log("Go to Cart Button not found"); + return; + } + + // Find and click the button that links to the cart page + for (let i = 0; i < GotoCartButton.length; i++) { + if (GotoCartButton[i].href === "https://www.bestbuy.com/cart" || + GotoCartButton[i].href === "/cart") { + GotoCartButton[i].onclick = cartpageoperationsEvenHandler; + GotoCartButton[i].addEventListener('click', cartpageoperationsEvenHandler, false); + GotoCartButton[i].click(); + break; + } + } + }, 4000); +} - function createFloatingBadge(mode,status) { +//________________________________________________________________________ - const iconUrl = "https://kkapuria3.github.io/images/KK.png"; - const $container = document.createElement("div"); - const $bg = document.createElement("div"); - const $link = document.createElement("a"); - const $img = document.createElement("img"); - const $text = document.createElement("P"); - const $mode = document.createElement("P"); - const $status1 = document.createElement("P"); +// ITEM IN STOCK EventHandler +//________________________________________________________________________ +function instockEventHandler(evt) { + setTimeout(() => { + const InStockButton = findButton('inStock'); + if (!InStockButton) { + console.log("In Stock Button not found"); + return; + } - $link.setAttribute("href", "https://github.com/kkapuria3"); - $link.setAttribute("target", "_blank"); - $link.setAttribute("title", "RefreshNoBot"); - $img.setAttribute("src", iconUrl); - var MAIN_TITLE = (" OpenSourceBots | BestBuyBot v4.4 | ◻️TESTMODE: " +TESTMODE + "◻️ITEM KEYWORD: " + ITEM_KEYWORD+ "◻️OOS REFRESH: " + OOS_REFRESH); - $text.innerText = MAIN_TITLE; - $mode.innerText = mode; - $status1.innerText = status; + let MainButtonColor = window.getComputedStyle(InStockButton[0]).backgroundColor; + console.log("Confirming Button Color : " + MainButtonColor); + + if (MainButtonColor === "rgb(197, 203, 213)") { + console.log("Button Color Gray. Is it still Adding ?"); + + setTimeout(() => { + const REALLY_PLEASE_WAIT = window.getComputedStyle(InStockButton[0]).backgroundColor; + + if (REALLY_PLEASE_WAIT === "rgb(197, 203, 213)") { + console.log("Its really Please Wait."); + + const MODE = "Do not Refresh 🛑 For new queue time open this link in new firefox container tab"; + let RETRY_QUEUE_COUNT = 0; + let QUEUE_TRY_COUNT = 0; + + setInterval(() => { + const [remainingMin, remainingSec] = checkQueueTimeRemaining(); + const queueBadge = "Queue Time : " + remainingMin + "m : " + remainingSec + "s"; + const $badge = createFloatingBadge(MODE, queueBadge); + document.body.appendChild($badge); + $badge.style.transform = "translate(0, 0)"; + + setTimeout(() => { + const PleaseWait = findButton('inStock'); + if (!PleaseWait) return; + + let currentButtonColor = window.getComputedStyle(PleaseWait[0]).backgroundColor; + console.log("Please Wait Button Detected :" + currentButtonColor + " | Lets keep trying .."); + + if (currentButtonColor === "rgb(255, 224, 0)" || currentButtonColor === "rgb(0, 70, 190)") { + console.log("Add to Cart is available:" + currentButtonColor + " | Lets Bag This ! "); + + const ATCYellowButton = findButton('inStock'); + if (ATCYellowButton) { + ATCYellowButton[0].onclick = pleasewaitcompletedEventHandler; + ATCYellowButton[0].addEventListener('click', pleasewaitcompletedEventHandler, false); + ATCYellowButton[0].click(); + } + } + }, 20000); + }, 5000); + } + }, 3000); + } else { + setTimeout(() => { + console.log("Level 1 | Blue Cart Button Appears"); + const GotoCartButton = findButton('goToCart'); + + if (GotoCartButton) { + for (let i = 0; i < GotoCartButton.length; i++) { + if (GotoCartButton[i].href === "https://www.bestbuy.com/cart" || + GotoCartButton[i].href === "/cart") { + GotoCartButton[i].onclick = cartpageoperationsEvenHandler; + GotoCartButton[i].addEventListener('click', cartpageoperationsEvenHandler, false); + GotoCartButton[i].click(); + break; + } + } + } + }, 3000); + } + }, 2000); +} +//________________________________________________________________________ - $container.style.cssText = "position:fixed;left:0;bottom:0;width:850px;height:75px;background: black;"; - $bg.style.cssText = "position:absolute;left:-100%;top:0;width:60px;height:55px;background:#1111;box-shadow: 0px 0 10px #060303; border: 1px solid #FFF;"; - $link.style.cssText = "position:absolute;display:block;top:11px;left: 0px; z-index:10;width: 50px;height:50px;border-radius: 1px;overflow:hidden;"; - $img.style.cssText = "display:block;width:100%"; - $text.style.cssText = "position:absolute;display:block;top:3px;left: 50px;background: transperant; color: white;"; - $mode.style.cssText = "position:absolute;display:block;top:22px;left: 50px;background: transperant; color: white;"; - $status1.style.cssText = "position:absolute;display:block;top:43px;left: 50px;background: transperant; color: white;"; +// Main Code +//________________________________________________________________________ +function contains(a, b) { + let counter = 0; + for (var i = 0; i < b.length; i++) { + if (a.includes(b[i])) counter++; + } + if (counter === b.length) return true; + return false; +} - $link.appendChild($img); - $container.appendChild($bg); - $container.appendChild($link); - $container.appendChild($text); - $container.appendChild($mode); - $container.appendChild($status1) +// Get Page Title +var pagetitle = String(document.title); - return $container; - } +if (location.href.includes("www.bestbuy.com/cart")) { + cartpageoperationsEvenHandler(); +} - //________________________________________________________________________ +// Refresh page if Sign In page is encountered to recheck for Verification Page +if (pagetitle.includes("Sign In to Best Buy")) { + setInterval(function () { + console.log("Waiting for Sign in"); + var Recovery_pagetitle = String(document.title); + if (Recovery_pagetitle.includes("Recovery")) { + verificationpageEventHandler(); + } + }, 1000); +} - // FUNCTIONS | Writing seperate EventHandlers so we can prevent memory leak for long running bots - //________________________________________________________________________ +// Check for Verification Page +if (pagetitle.includes("Recovery")) { + verificationpageEventHandler(); +} - // Ideas developed based on : https://stackoverflow.com/questions/13677589/addeventlistener-memory-leak-due-to-frames/13702786#13702786 - //________________________________________________________________________ +if (pagetitle.includes(ITEM_KEYWORD)) { + const $badge = createFloatingBadge("Auto Detecting Mode", "Initializing .."); + document.body.appendChild($badge); + $badge.style.transform = "translate(0, 0)"; - // CART PAGE EventHandler - //________________________________________________________________________ + // Replace the old OOS button detection with: + const OOSButton = findButton("outOfStock"); + console.log(OOSButton); - function cartpageoperationsEvenHandler(evt) { - setTimeout(() => { - if (location.href.includes("www.bestbuy.com/cart")) { - // Create and display the badge + if (OOSButton != null) { const $badge = createFloatingBadge( - "Cart Page 🛑 Do Not Refresh. Only one item can be carted per account.", - "Verfying that first item in CART has KEYWORD" + "No Stock Found | Note: Run bot only during a drop ", + "Working on refreshing, make sure you have pop-ups enabled" ); document.body.appendChild($badge); $badge.style.transform = "translate(0, 0)"; - // Wait 3 seconds on Cart Page - setTimeout(() => { - const CartItemCheck = document.getElementsByClassName("cart-item__title focus-item-0"); - if (CartItemCheck[0] && CartItemCheck[0].innerHTML.includes(ITEM_KEYWORD)) { - console.log("Item Has been Confirmed!"); + console.log("Out of Stock Button is Found: Just Refreshing !"); + + // setTimeout(function () { + // window.open(window.location.href, "_blank"); + // window.close(); + // }, OOS_REFRESH * 1000); + } else { + console.log("Out of Stock Button Not Found: Lets Check for ATC Button"); - // Select the shipping button universally using an attribute selector - const shippingButton = document.querySelector("input[id^='fulfillment-shipping-']"); - if (shippingButton && PREFERRED_SHIPPING === "Yes") { - console.log("Shipping button found. Waiting 3 seconds before clicking it."); - // Delay shipping button click by 3 seconds - setTimeout(() => { - shippingButton.click(); - console.log("Shipping button clicked. Waiting 3 seconds before clicking checkout."); - - // Wait an additional 3 seconds after clicking shipping button - setTimeout(() => { - const CheckoutButton = document.getElementsByClassName("btn btn-lg btn-block btn-primary"); - if (CheckoutButton[0]) { - console.log("Clicking Checkout"); - CheckoutButton[0].click(); - } - }, 3000); - }, 3000); + // Replace the old InStock button detection with: + const InStockButton = findButton("inStock"); + + if (InStockButton) { + console.log("Add to Cart Found"); + let ATC_Color = window.getComputedStyle(InStockButton[0]).backgroundColor; + + if (ATC_Color === "rgb(197, 203, 213)") { + console.log( + "ATC is grey ! You have already pressed please wait for this item. Lets wait until we can bag this." + ); + instockEventHandler(); } else { - console.log("Shipping button not found. Clicking Checkout immediately."); - const CheckoutButton = document.getElementsByClassName("btn btn-lg btn-block btn-primary"); - if (CheckoutButton[0]) { - CheckoutButton[0].click(); - } + setTimeout(function () { + console.log("ATC button is yellow ! Pressing it ! "); + InStockButton[0].onclick = instockEventHandler; + InStockButton[0].addEventListener( + "click", + instockEventHandler, + false + ); + InStockButton[0].click(instockEventHandler); + }, 2000); } - } - }, 3000); - } - }, 5000); - } - - - //________________________________________________________________________ - - // VERIFICATION PAGE EventHandler - //________________________________________________________________________ - - function verificationpageEventHandler (evt) { - console.log('Verification Step Reached') - playChime(); - setTimeout(function() - { - if (location.href.indexOf("identity/signin/recoveryOptions") > -1) { - //Create Custom Badge - // - const $badge = createFloatingBadge("Get Ready To Verify 🛑 Do Not Refresh ","Validating and Entering SMS Digits | It will error if you havent updated SMS_DIGITS "); - document.body.appendChild($badge); - $badge.style.transform = "translate(0, 0)" - setTimeout(function() - { - var ContinueButton; - const ContinueButton_L1 = "btn btn-secondary btn-lg btn-block c-button-icon c-button-icon-leading cia-form__controls__submit " - const ContinueButton_L2 = "c-button c-button-secondary c-button-lg c-button-block c-button-icon c-button-icon-leading cia-form__controls__submit " - const ContinueButton_L3 = "c-button c-button-secondary c-button-md c-button-block" - - if (document.getElementsByClassName(ContinueButton_L1).length == 1) - { - ContinueButton = document.getElementsByClassName(ContinueButton_L1); - console.log('ContinueButton Class ID 1 : ' + ContinueButton_L1) - } else if (document.getElementsByClassName(ContinueButton_L2).length == 1) { - ContinueButton = document.getElementsByClassName(ContinueButton_L2); - console.log('ContinueButton Class ID 2 :' + ContinueButton_L2) - - } else if (document.getElementsByClassName(ContinueButton_L3).length == 1) { - ContinueButton = document.getElementsByClassName(ContinueButton_L3); - console.log('ContinueButton Class ID 2 :' + ContinueButton_L3) - - } - - document.getElementById("smsDigits").focus(); - document.getElementById("smsDigits").select(); - if (!document.execCommand('insertText',false, SMS_DIGITS)) { - document.getElementById("smsDigits").value = SMS_DIGITS; - } - if (ContinueButton.length == 1) { - ContinueButton[0].click() - ContinueButton = null; - } - }, 2500) + } + } +} + +// CART PAGE OPERATIONS +else if ( + location.href.includes("www.bestbuy.com/checkout/r/fast-track") || + location.href.includes("www.bestbuy.com/checkout/c/fast-track") +) { + //Create Custom Badge + // + const $badge = createFloatingBadge( + "Final CheckPoint", + "Verifying and Submitting" + ); + document.body.appendChild($badge); + $badge.style.transform = "translate(0, 0)"; + // + // + setTimeout(function () { + //We will verify that the item in final checkout screen matches the Keyword so we don't have any issues when running multiple scripts for multiple keyword. + //In that case the Place Order button is clicked. + // + var CartItemCheck = document.getElementsByClassName( + "d-flex items-start flex-column gap-100" + ); + //console.log(CartItemCheck[0]) + // + // + if (CartItemCheck[0].innerHTML.includes(ITEM_KEYWORD)) { + // + console.log("Item Has been Confirmed !"); + //console.log('Click Place Order') + + // + //document.getElementById("blah").src = "http://......" + // CVV Number of Saved Card + // Bug fix: by craz3drunner (discord member) + + // CVV Field ID Layers + var CVV_ID; + const CVV_ID_L1 = "cvv"; + const CVV_ID_L2 = "credit-card-cvv"; + + if (document.getElementById(CVV_ID_L1) != null) { + CVV_ID = CVV_ID_L1; + console.log("CVV ID 1 : " + CVV_ID_L1); + } else if (document.getElementById(CVV_ID_L2) != null) { + CVV_ID = CVV_ID_L2; + console.log("CVV ID 2 :" + CVV_ID_L2); + } + if (document.getElementById(CVV_ID) != null) { + document.getElementById(CVV_ID).focus(); + document.getElementById(CVV_ID).select(); + if (!document.execCommand("insertText", false, CREDITCARD_CVV)) { + document.getElementById(CVV_ID).value = CREDITCARD_CVV; + console.log("CVV Entered"); + } } - }, 3000) - } - //________________________________________________________________________ + if (document.getElementById("text-updates") != null) { + // + var TextUpdates = document.getElementById("text-updates").click(); + console.log("Text Updates checked"); + } + if (document.getElementById("smsOptIn") != null) { + // + var SMSUpdates = document.getElementById("smsOptIn").click(); + console.log("SMS Updates checked"); + } + if (TESTMODE === "No") { + //Is test mode is OFF go press place order button + // + console.log("Placing order ..."); + document + .getElementsByClassName( + "c-button-unstyled rounded-lg border-comp-outline-secondary h-600 bg-comp-surface-secondary-emphasis px-400" + )[0] + .click(); + // + } else { + console.log("Test Mode is ON. Ready to Place Order Manually"); + } + // + // + } + }, 3000); //Three seconds will elapse and Code will execute. +} +// SIGN IN OPERATIONS +else if (location.href.includes("www.bestbuy.com/identity/signin")) { + const $badge = createFloatingBadge( + "Sign-In Page Detected | Please have your credentials saved ", + "Clicking Sign-In in 5 Seconds" + ); + document.body.appendChild($badge); + $badge.style.transform = "translate(0, 0)"; + + setTimeout(function () { + var signInButton = document.getElementsByClassName( + "c-button c-button-secondary c-button-lg c-button-block c-button-icon c-button-icon-leading cia-form__controls__submit" + )[0]; + signInButton.click(); + + // + // + }, 5000); +} - // SECOND ADD TO CART EventHandler - //________________________________________________________________________ +class QueueMonitor { + constructor() { + this.lastCheck = 0; + this.checkInterval = 5000; // 5 seconds + } -function pleasewaitcompletedEventHandler(evt) { - // Wait 4 seconds before clicking the final "Go to Cart" button - setTimeout(function() { - var GotoCartButton; - // Existing class strings... - const GotoCartButton_L1 = "c-button c-button-secondary btn btn-secondary btn-sm c-button-sm btn-block c-button-block"; - const GotoCartButton_L2 = "c-button c-button-secondary c-button-sm c-button-block"; - // NEW variant that matches your provided HTML element: - const GotoCartButton_L3 = "c-button c-button-secondary c-button-md c-button-block"; - if (document.getElementsByClassName(GotoCartButton_L1).length > 0) { - GotoCartButton = document.getElementsByClassName(GotoCartButton_L1); - console.log('GotoCartButton Class ID 1 : ' + GotoCartButton_L1); - } else if (document.getElementsByClassName(GotoCartButton_L2).length > 0) { - GotoCartButton = document.getElementsByClassName(GotoCartButton_L2); - console.log('GotoCartButton Class ID 2 :' + GotoCartButton_L2); - } else if (document.getElementsByClassName(GotoCartButton_L3).length > 0) { - GotoCartButton = document.getElementsByClassName(GotoCartButton_L3); - console.log('GotoCartButton Class ID 3 :' + GotoCartButton_L3); + checkQueueTime() { + const now = Date.now(); + if (now - this.lastCheck < this.checkInterval) { + return null; + } + + try { + const startMs = getQueueTimeStartMs(sku); + const durationMs = getQueueDurationMs(sku); + const remainingMs = startMs + durationMs - now; + + return { + minutes: Math.trunc(remainingMs / 60000), + seconds: Math.trunc((remainingMs / 1000) % 60), + }; + } catch (e) { + console.error("Queue time check failed:", e); + return null; + } finally { + this.lastCheck = now; + } + } +} + +class EventManager { + constructor() { + this.handlers = new Map(); + } + + addHandler(element, eventType, handler) { + if (!element) return; + + // Remove existing handler if present + this.removeHandler(element, eventType); + + // Add new handler + element.addEventListener(eventType, handler); + this.handlers.set(`${element.id}-${eventType}`, { + element, + eventType, + handler, + }); + } + + removeHandler(element, eventType) { + const key = `${element.id}-${eventType}`; + const existing = this.handlers.get(key); + if (existing) { + existing.element.removeEventListener( + existing.eventType, + existing.handler + ); + this.handlers.delete(key); + } + } + + clearAll() { + this.handlers.forEach(({ element, eventType, handler }) => { + element.removeEventListener(eventType, handler); + }); + this.handlers.clear(); + } +} + +class RateLimiter { + constructor(maxRequests = 10, timeWindow = 1000) { + this.requests = []; + this.maxRequests = maxRequests; + this.timeWindow = timeWindow; + } + + canMakeRequest() { + const now = Date.now(); + // Remove old requests + this.requests = this.requests.filter( + (time) => now - time < this.timeWindow + ); + + if (this.requests.length < this.maxRequests) { + this.requests.push(now); + return true; + } + return false; + } + + async waitForAvailability() { + while (!this.canMakeRequest()) { + await new Promise((resolve) => setTimeout(resolve, 100)); } - // If the button is found, iterate and click the one that links to the cart page. - if (GotoCartButton != null) { - for (var i = 0; i < GotoCartButton.length; i++) { - if (GotoCartButton[i].href === 'https://www.bestbuy.com/cart' || - GotoCartButton[i].href === '/cart') { - // Set up the click event handler - GotoCartButton[i].onclick = cartpageoperationsEvenHandler; - GotoCartButton[i].addEventListener("click", cartpageoperationsEvenHandler, false); - // Trigger a click on the element - GotoCartButton[i].click(); - GotoCartButton = null; - break; + } +} + +class ErrorHandler { + constructor(maxRetries = 3) { + this.maxRetries = maxRetries; + this.retryDelays = [1000, 2000, 5000]; // Progressive delays + } + + async withRetry(operation, context) { + let lastError; + + for (let i = 0; i < this.maxRetries; i++) { + try { + return await operation(); + } catch (error) { + lastError = error; + console.error(`Attempt ${i + 1} failed:`, error); + + if (i < this.maxRetries - 1) { + await new Promise((resolve) => + setTimeout( + resolve, + this.retryDelays[i] || + this.retryDelays[this.retryDelays.length - 1] + ) + ); } } } - }, 4000); + + throw new Error( + `Operation failed after ${this.maxRetries} attempts. Last error: ${lastError}` + ); + } } - //________________________________________________________________________ +// Initialize utility classes +const eventManager = new EventManager(); +const rateLimiter = new RateLimiter(5, 1000); // 5 requests per second +const errorHandler = new ErrorHandler(3); +const queueMonitor = new QueueMonitor(); - // ITEM IN STOCK EventHandler - //________________________________________________________________________ +// Modify the cart page operations to use the new utilities +async function cartPageOperations() { + return errorHandler.withRetry(async () => { + await rateLimiter.waitForAvailability(); - function instockEventHandler(evt) { - // After pressing Add to Cart button we first wait for 5 seconds to get cart ready. In this time we will check if it shows please wait - // Add to Cart Button Classes Layers - var InStockButton; - const InStockButton_L1 = "btn btn-primary btn-lg btn-block btn-leading-ficon add-to-cart-button" - const InStockButton_L2 = "c-button c-button-primary c-button-lg c-button-block c-button-icon c-button-icon-leading add-to-cart-button" - const InStockButton_L3 = "c-button c-button-secondary c-button-md c-button-block" + const CartItemCheck = document.getElementsByClassName( + "cart-item__title focus-item-0" + ); + if (CartItemCheck[0] && CartItemCheck[0].innerHTML.includes(ITEM_KEYWORD)) { + console.log("Item Has been Confirmed!"); - if (document.getElementsByClassName(InStockButton_L1).length > 0) - { - InStockButton = document.getElementsByClassName(InStockButton_L1); - console.log('instockEventHandler Button Class 1 : ' + InStockButton_L1) + // Handle CVV input with error handling + await handleCVVInput(); - } else if (document.getElementsByClassName(InStockButton_L2).length > 0) { - - InStockButton = document.getElementsByClassName(InStockButton_L2); - console.log('instockEventHandler Button Class 2 :' + InStockButton_L2) - - } else if (document.getElementsByClassName(InStockButton_L3).length > 0) { - - InStockButton = document.getElementsByClassName(InStockButton_L3); - console.log('instockEventHandler Button Class 3 :' + InStockButton_L3) - - } - - setTimeout(function() { - let MainButtonColor = window.getComputedStyle(InStockButton[0]).backgroundColor; - //Code to run After timeout elapses - console.log('Confirming Button Color : ' + MainButtonColor) - - if (MainButtonColor === 'rgb(197, 203, 213)') { - - console.log('Button Color Gray. Is it still Adding ?') - - setTimeout(function() { - - var REALLY_PLEASE_WAIT = window.getComputedStyle(InStockButton[0]).backgroundColor; - - if (REALLY_PLEASE_WAIT === 'rgb(197, 203, 213)') { - - console.log('Its really Please Wait.') - - var MODE = "Do not Refresh 🛑 For new queue time open this link in new firefox container tab" - // - var RETRY_COUNT = "1" - let RETRY_QUEUE_COUNT = 0 - let QUEUE_TRY_COUNT = 0 - // Run this every 5 seconds - setInterval(function() { - // run checkQueueTimeRemaining Function which returns [remainingMin, remainingSec] - const [remainingMin, remainingSec] = checkQueueTimeRemaining(); - //DEBUG//console.log(remainingMin,'m : ', remainingSec,'s') - const queueBadge = 'Queue Time : ' + remainingMin + 'm : '+ remainingSec+'s' - const $badge = createFloatingBadge(MODE,queueBadge); - document.body.appendChild($badge); - $badge.style.transform = "translate(0, 0)" - // Run this every 20 seconds - setTimeout(function() { - - //Find the Color of Main Button in Firefox - var PleaseWait; - const PleaseWait_L1 = "btn btn-primary btn-lg btn-block btn-leading-ficon add-to-cart-button" - const PleaseWait_L2 = "c-button c-button-primary c-button-lg c-button-block c-button-icon c-button-icon-leading add-to-cart-button" - const PleaseWait_L3 = "c-button c-button-secondary c-button-md c-button-block" - - if (document.getElementsByClassName(PleaseWait_L1).length == 1) - { - PleaseWait = document.getElementsByClassName(PleaseWait_L1); - console.log('PleaseWait Button Class 1 : ' + PleaseWait_L1) - - } else if (document.getElementsByClassName(PleaseWait_L2).length == 1) { - - PleaseWait = document.getElementsByClassName(PleaseWait_L2); - console.log('PleaseWait Button Class 2 :' + PleaseWait_L2) - } else if (document.getElementsByClassName(PleaseWait_L3).length == 1) { - - PleaseWait = document.getElementsByClassName(PleaseWait_L3); - console.log('PleaseWait Button Class 3 :' + PleaseWait_L3) - } - - let MainButtonColor = window.getComputedStyle(PleaseWait[0]).backgroundColor; - //console.log(MainButtonColor); - console.log("Please Wait Button Detected :" + MainButtonColor + " | Lets keep trying .."); - - if (MainButtonColor === 'rgb(255, 224, 0)' || MainButtonColor === 'rgb(0, 70, 190)') { - // Color of Button Changes to yellow then click again - let ATC_Color = window.getComputedStyle(InStockButton[0]).backgroundColor; - // When button turns yellow, we scream bagged ! - console.log("Add to Cart is available:" + ATC_Color + " | Lets Bag This ! "); - var ATCYellowButton; - const ATCYellowButton_L1 = "btn btn-primary btn-lg btn-block btn-leading-ficon add-to-cart-button" - const ATCYellowButton_L2 = "c-button c-button-primary c-button-lg c-button-block c-button-icon c-button-icon-leading add-to-cart-button" - const ATCYellowButton_L3 = "c-button c-button-secondary c-button-md c-button-block" - - if (document.getElementsByClassName(ATCYellowButton_L1).length == 1) - { - ATCYellowButton = document.getElementsByClassName(ATCYellowButton_L1); - console.log('PleaseWait Button Class 1 : ' + ATCYellowButton_L1) - - } else if (document.getElementsByClassName(ATCYellowButton_L2).length == 1) { - - ATCYellowButton = document.getElementsByClassName(ATCYellowButton_L2); - console.log('PleaseWait Button Class 2 :' + ATCYellowButton_L2) - } else if (document.getElementsByClassName(ATCYellowButton_L3).length == 1) { - - ATCYellowButton = document.getElementsByClassName(ATCYellowButton_L3); - console.log('PleaseWait Button Class 2 :' + ATCYellowButton_L3) - } - - // Now we will use event handlers to check for clicks. We have create a function on top defining instockEventhandler. - // It is said this this method reduces memory leaks - ATCYellowButton[0].onclick = pleasewaitcompletedEventHandler; - ATCYellowButton[0].addEventListener("click", pleasewaitcompletedEventHandler, false); - // When a click event is detected for parsed element, please execute the function from uptop - ATCYellowButton[0].click(pleasewaitcompletedEventHandler); - - } else { - // Is queue bypass available ? - // If available lets check add to cart button instanly - // Press secondary button - console.log("Checking bypass") - var GotoCartButton; - const GotoCartButton_L1 = "c-button c-button-secondary btn btn-secondary btn-sm c-button-sm btn-block c-button-block" - const GotoCartButton_L2 = "c-button c-button-secondary c-button-sm c-button-block " - const GotoCartButton_L3 = "c-button c-button-secondary c-button-md c-button-block" - - if (document.getElementsByClassName(GotoCartButton_L1).length > 0) - { - GotoCartButton = document.getElementsByClassName(GotoCartButton_L1); - console.log('GotoCartButton Class ID 1 : ' + GotoCartButton_L1) - } else if (document.getElementsByClassName(GotoCartButton_L2).length > 0) { - GotoCartButton = document.getElementsByClassName(GotoCartButton_L2); - console.log('GotoCartButton Class ID 2 :' + GotoCartButton_L2) - - } else if (document.getElementsByClassName(GotoCartButton_L3).length > 0) { - GotoCartButton = document.getElementsByClassName(GotoCartButton_L3); - console.log('GotoCartButton Class ID 2 :' + GotoCartButton_L3) - - } - - if (GotoCartButton != null) { - for (var i=0;i QUEUE_TIME_CUTOFF) && (RETRY_QUEUE_COUNT < RETRY_COUNT)) { - RETRY_QUEUE_COUNT += NEW_QUEUE_TIME_DELAY; - let BetterTimeColor = window.getComputedStyle(BetterTime).backgroundColor - BetterTime.click() - QUEUE_TRY_COUNT++; - console.log(BetterTimeColor) - if (BetterTimeColor === 'rgb(197, 203, 213)') { - //console.log('refresh') - //window.open(window.location.href, '_blank'); - //window.close(); - location.reload(); - } - }*/ - - - } - - // - - }, 5 * 1000); - - RETRY_COUNT++; - if (RETRY_COUNT > MAX_RETRIES) { - location.reload(); - } - - }, 1000) - - } else { - setTimeout(function() { - // Press secondary button - console.log('Level 2 | Blue Cart Button Appears') - var GotoCartButton; - const GotoCartButton_L1 = "c-button c-button-secondary btn btn-secondary btn-sm c-button-sm btn-block c-button-block" - const GotoCartButton_L2 = "c-button c-button-secondary c-button-sm c-button-block " - const GotoCartButton_L3 = "c-button c-button-secondary c-button-md c-button-block" - - if (document.getElementsByClassName(GotoCartButton_L1).length > 0) - { - GotoCartButton = document.getElementsByClassName(GotoCartButton_L1); - console.log('GotoCartButton Class ID 1 : ' + GotoCartButton_L1) - } else if (document.getElementsByClassName(GotoCartButton_L2).length > 0) { - GotoCartButton = document.getElementsByClassName(GotoCartButton_L2); - console.log('GotoCartButton Class ID 2 :' + GotoCartButton_L2) - - } else if (document.getElementsByClassName(GotoCartButton_L3).length > 0) { - GotoCartButton = document.getElementsByClassName(GotoCartButton_L3); - console.log('GotoCartButton Class ID 2 :' + GotoCartButton_L3) - - } - - if (GotoCartButton != null) { - for (var i=0;i 0) - { - GotoCartButton = document.getElementsByClassName(GotoCartButton_L1); - console.log('GotoCartButton Class ID 1 : ' + GotoCartButton_L1) - } else if (document.getElementsByClassName(GotoCartButton_L2).length > 0) { - GotoCartButton = document.getElementsByClassName(GotoCartButton_L2); - console.log('GotoCartButton Class ID 2 :' + GotoCartButton_L2) - - } else if (document.getElementsByClassName(GotoCartButton_L3).length > 0) { - GotoCartButton = document.getElementsByClassName(GotoCartButton_L3); - console.log('GotoCartButton Class ID 2 :' + GotoCartButton_L3) - - } - - if (GotoCartButton != null) { - for (var i=0;i 0 ) { - // - const $badge = createFloatingBadge("No Stock Found | Note: Run bot only during a drop ", "Working on refreshing, make sure you have pop-ups enabled"); - document.body.appendChild($badge); - $badge.style.transform = "translate(0, 0)"; - // - console.log('Out of Stock Button is Found: Just Refreshing !') - // Lets just reload when its OOSing - setTimeout(function(){ - - window.open(window.location.href, '_blank'); - window.close(); - //location.reload(); // This command here blows up your memory - - // - // - }, OOS_REFRESH*1000); - - } - // If Out of Stock Button is Not Found. - // We will begin working of our bot - // - else { - console.log('Out of Stock Button Not Found: Lets Check for ATC Button') - - // Add to Cart Button Classes Layers - var InStockButton; - const InStockButton_L1 = "btn btn-primary btn-lg btn-block btn-leading-ficon add-to-cart-button" - const InStockButton_L2 = "c-button c-button-primary c-button-lg c-button-block c-button-icon c-button-icon-leading add-to-cart-button" - const InStockButton_L3 = "c-button c-button-secondary c-button-md c-button-block" - - if (document.getElementsByClassName(InStockButton_L1).length == 1) - { - InStockButton = document.getElementsByClassName(InStockButton_L1); - console.log('InStockButton Class ID 1 : ' + InStockButton_L1) - - } else if (document.getElementsByClassName(InStockButton_L2).length == 1) { - - InStockButton = document.getElementsByClassName(InStockButton_L2); - console.log('InStockButton Class ID 2 :' + InStockButton_L2) - - } else if (document.getElementsByClassName(InStockButton_L3).length == 1) { - - InStockButton = document.getElementsByClassName(InStockButton_L3); - console.log('InStockButton Class ID 2 :' + InStockButton_L3) - - } - - // - // Checking if ATC button is found - if (InStockButton.length > 0) - { - - console.log('Add to Cart Found') - // Lets Save the Color for ATC Button for dealing with Please Wait Bullshit - let ATC_Color = window.getComputedStyle(InStockButton[0]).backgroundColor; - // Pring RBG for ATC - //console.log(ATC_Color) - // When pages loads first time. It will check the color of button. If button is already in please wait, we wont click ATC again. Becuase it opens a warning on page. - if (ATC_Color === 'rgb(197, 203, 213)') - { - // - console.log('ATC is grey ! You have already pressed please wait for this item. Lets wait until we can bag this.') - instockEventHandler() ; - - - } - else - { - // Adding timeout to prevent stalling when In Stock item is first loaded - setTimeout(function() { - // Now we will use event handlers to check for clicks. We have create a function on top defining instockEventhandler. - // It is said this this method reduces memory leaks - console.log('ATC button is yellow ! Pressing it ! ') - InStockButton[0].onclick = instockEventHandler; - InStockButton[0].addEventListener ("click", instockEventHandler, false); - // When a click event is detected for parsed element, please execute the function from uptop - InStockButton[0].click (instockEventHandler); - }, 2000) - } + // Handle updates checkboxes + handleUpdatesCheckboxes(); + // Place order if not in test mode + if (TESTMODE === "No") { + const placeOrderButton = document.getElementsByClassName( + "c-button-unstyled rounded-lg border-comp-outline-secondary h-600 bg-comp-surface-secondary-emphasis px-400" + )[0]; + if (placeOrderButton) { + await rateLimiter.waitForAvailability(); + placeOrderButton.click(); + } + } else { + console.log("Test Mode is ON. Ready to Place Order Manually"); + } + } + }); +} +// Helper function for CVV input +async function handleCVVInput() { + // Find the CVV input using the specific class and id + const cvvField = document.querySelector('.tb-input.v-large.payment-input--cvv#cvv'); + + if (cvvField) { + await rateLimiter.waitForAvailability(); + + // Focus and select the field + cvvField.focus(); + cvvField.select(); + + // Try to set the value using different methods + try { + // Method 1: Try execCommand + if (!document.execCommand('insertText', false, CREDITCARD_CVV)) { + // Method 2: Direct value assignment + cvvField.value = CREDITCARD_CVV; + + // Method 3: Trigger input event to ensure value is registered + cvvField.dispatchEvent(new Event('input', { bubbles: true })); + } + + console.log('CVV Entered Successfully'); + } catch (error) { + console.error('Failed to enter CVV:', error); + } + } else { + console.log('CVV field not found'); + } +} - } +// Helper function for updates checkboxes +function handleUpdatesCheckboxes() { + const checkboxes = { + "text-updates": "Text Updates", + smsOptIn: "SMS Updates", + }; + + Object.entries(checkboxes).forEach(([id, label]) => { + const checkbox = document.getElementById(id); + if (checkbox) { + checkbox.click(); + console.log(`${label} checked`); + } + }); +} - } - } +// Modify sign-in operations to use the new utilities +async function signInOperations() { + return errorHandler.withRetry(async () => { + await rateLimiter.waitForAvailability(); + + const signInButton = document.getElementsByClassName( + "c-button c-button-secondary c-button-lg c-button-block c-button-icon c-button-icon-leading cia-form__controls__submit" + )[0]; + if (signInButton) { + // Use EventManager for click handling + eventManager.addHandler(signInButton, "click", () => { + console.log("Sign in button clicked"); + }); + signInButton.click(); + } + }); +} +// Queue monitoring integration +function monitorQueue() { + setInterval(() => { + const queueTime = queueMonitor.checkQueueTime(); + if (queueTime) { + const queueBadge = `Queue Time: ${queueTime.minutes}m : ${queueTime.seconds}s`; + const $badge = createFloatingBadge("Queue Status", queueBadge); + document.body.appendChild($badge); + $badge.style.transform = "translate(0, 0)"; + } + }, 5000); +} +// Modify the main execution flow +if ( + location.href.includes("www.bestbuy.com/checkout/r/fast-track") || + location.href.includes("www.bestbuy.com/checkout/c/fast-track") +) { + cartPageOperations().catch(console.error); +} else if (location.href.includes("www.bestbuy.com/identity/signin")) { + signInOperations().catch(console.error); +} -// CART PAGE OPERATIONS - else if (location.href.includes("www.bestbuy.com/checkout/r/fast-track") || location.href.includes("www.bestbuy.com/checkout/c/fast-track")) { - //Create Custom Badge - // - const $badge = createFloatingBadge("Final CheckPoint","Verifying and Submitting"); - document.body.appendChild($badge); - $badge.style.transform = "translate(0, 0)" - // - // - setTimeout(function() { - //We will verify that the item in final checkout screen matches the Keyword so we don't have any issues when running multiple scripts for multiple keyword. - //In that case the Place Order button is clicked. - // - var CartItemCheck = document.getElementsByClassName("d-flex items-start flex-column gap-100"); - //console.log(CartItemCheck[0]) - // - // - if (CartItemCheck[0].innerHTML.includes(ITEM_KEYWORD)){ - // - console.log('Item Has been Confirmed !') - //console.log('Click Place Order') - - // - //document.getElementById("blah").src = "http://......" - // CVV Number of Saved Card - // Bug fix: by craz3drunner (discord member) - - // CVV Field ID Layers - var CVV_ID; - const CVV_ID_L1 = "cvv" - const CVV_ID_L2 = "credit-card-cvv" - - if (document.getElementById(CVV_ID_L1) != null) - { - CVV_ID = CVV_ID_L1; - console.log('CVV ID 1 : ' + CVV_ID_L1) - - } else if (document.getElementById(CVV_ID_L2) != null) { - - CVV_ID = CVV_ID_L2; - console.log('CVV ID 2 :' + CVV_ID_L2) - - } - if(document.getElementById(CVV_ID) != null) { - document.getElementById(CVV_ID).focus(); - document.getElementById(CVV_ID).select(); - if (!document.execCommand('insertText',false, CREDITCARD_CVV)) { - document.getElementById(CVV_ID).value = CREDITCARD_CVV; - console.log('CVV Entered') - } - } - - if(document.getElementById("text-updates") != null) - { - // - var TextUpdates = document.getElementById("text-updates").click(); - console.log('Text Updates checked') - } - if(document.getElementById("smsOptIn") != null) - { - // - var SMSUpdates = document.getElementById("smsOptIn").click(); - console.log('SMS Updates checked') - } - if (TESTMODE === "No"){ - //Is test mode is OFF go press place order button - // - console.log("Placing order ...") - document.getElementsByClassName("c-button-unstyled rounded-lg border-comp-outline-secondary h-600 bg-comp-surface-secondary-emphasis px-400")[0].click() - // - } else { - console.log('Test Mode is ON. Ready to Place Order Manually') - } - // - // - } - }, 3000); //Three seconds will elapse and Code will execute. - - - - - } - // SIGN IN OPERATIONS - else if (location.href.includes("www.bestbuy.com/identity/signin")) { - - const $badge = createFloatingBadge("Sign-In Page Detected | Please have your credentials saved ","Clicking Sign-In in 5 Seconds"); - document.body.appendChild($badge); - $badge.style.transform = "translate(0, 0)" - - setTimeout(function(){ - - var signInButton = document.getElementsByClassName("c-button c-button-secondary c-button-lg c-button-block c-button-icon c-button-icon-leading cia-form__controls__submit")[0]; - signInButton.click() - - // - // - }, 5000); - - } +// Clean up event listeners when needed +window.addEventListener("beforeunload", () => { + eventManager.clearAll(); +});