Last active
January 11, 2021 21:40
-
-
Save brucebentley/f14297796a89e679c0bf9112ac2fed70 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Buy A PS5 | |
// @version 1.0.0 | |
// @description A userscript that collapses markdown headers | |
// @author Bruce Bentley <brucebentley@me.com> (https://brucebentley.io) | |
// @copyright 2021, Bruce Bentley (https://github.com/brucebentley) | |
// @license MIT; https://opensource.org/licenses/MIT | |
// @namespace https://github.com/brucebentley | |
// @description | |
// @match https://www.target.com/* | |
// @match https://www.bestbuy.com/* | |
// @match https://www.gamestop.com/* | |
// @match https://www.walmart.com/* | |
// @match https://www.amazon.com/* | |
// @grant GM_setValue | |
// @grant GM_getValue | |
// ==/UserScript== | |
/** | |
* HOW THIS SCRIPT WORKS: | |
* Hello! I hope you're having a marvellous October. | |
* When you're on a product detail page (target.com/p/...), this script replicates | |
* the server request the page would normally perform. No hacky fake-button-clicking! | |
* The script polls for stock availability repeatedly, and the instant it finds it, | |
* it attempts to add to cart and instant-checkout. | |
* | |
* WHAT YOU SHOULD DO: | |
* 1. Purchase anything from target.com so your credit card details and CCV are | |
* saved to your account. | |
* 3. Log in. | |
* 4. You'll first need access keys. These are the keys your Target web app uses to | |
* authenticate with the server. Go to a random in-stock pre-order product, say, | |
* https://www.target.com/p/spider-man-miles-morales-playstation-4/-/A-81491473 | |
* 5. Right click -> Inspect Element -> Network -> XHR | |
* 6. On the webpage, refresh. Click "Pre-order". | |
* 7. In Inspect Element, in the Filter text box, type "pdp_fulfilment". | |
* Click the item in the list. In the right column, scroll to "Query string | |
* parameters", and copy "key". Paste this below under PUBLIC_ACCESS_KEY. | |
* 8. Back in the Filter box, type "cart_items" | |
* 9. Again, click the cart_items list item, scroll the right column and copy "key". | |
* Paste it in PRIVATE_ACCESS_KEY. | |
* 10. Okay hard part is done! Be sure to clear your cart. | |
* 4. Go to the PDP (target.com/p/...) of the product you want to pre-order. | |
* 5. Enable the script. Refresh. | |
* 6. Right-click -> Inspect Element to see progress in the Console. | |
* Messages from the script are prefixed "TAMPERMONKEY:". Check "Preserve log" under the gear icon. | |
* | |
* NOTES: | |
* - This script will immediately purchase the product you're looking at the *instant* | |
* it's available! Don't casually browse Target.com with this script enabled! | |
* - Your tab needs to be visible and screensaver disabled or Chrome will slow down the script. | |
* - This script doesn't need the PS5 saved in your "Saved for later". | |
* - You don't need to refresh the page while the script runs. You'll never see the enabled | |
* "Pre-order now" red button. Success will send you straight to your cart. | |
* - You only need one tab open. Multiple tabs open might cause multiple purchases! | |
* - The script will attempt to stop once one purchase happens. You should then turn it off. | |
* - If adding to the cart has failed (because someone beat you to it), the server will | |
* respond "access denied". It'll also say that if you're banned. So don't make this script | |
* too aggressive. | |
*/ | |
const PUBLIC_ACCESS_KEY = 'abc123123_PASTE_KEY_HERE'; | |
const PRIVATE_ACCESS_KEY = 'abc123123_PASTE_KEY_HERE'; | |
const CHECK_FOR_STOCK_SECONDS = 1; | |
const REPEATEDLY_ADD_TO_CART_SECONDS = 5; | |
const RELOAD_PAGE_MINUTES = 10; | |
const PRODUCT_ID = window.location.pathname.match(/A-(\d*)/)[1]; | |
const isPDP = window.location.pathname.startsWith('/p/'); | |
let timeoutValid = true; | |
let stockAvail = false; | |
const consoleBg1 = [ 'background: orange', 'color: white', 'display: block', 'padding: 30px 0'].join(';'); | |
const consoleBg2 = [ 'background: #00c4ff', 'color: white', 'display: block', 'padding: 30px 0'].join(';'); | |
const consoleBg3 = [ 'background: green', 'color: white', 'display: block', 'padding: 30px 0'].join(';'); | |
const beep = () => {(new Audio( | |
"data:audio/wav;base64,//uQRAAAAWMSLwUIYAAsYkXgoQwAEaYLWfkWgAI0wWs/ItAAAGDgYtAgAyN+QWaAAihwMWm4G8QQRDiMcCBcH3Cc+CDv/7xA4Tvh9Rz/y8QADBwMWgQAZG/ILNAARQ4GLTcDeIIIhxGOBAuD7hOfBB3/94gcJ3w+o5/5eIAIAAAVwWgQAVQ2ORaIQwEMAJiDg95G4nQL7mQVWI6GwRcfsZAcsKkJvxgxEjzFUgfHoSQ9Qq7KNwqHwuB13MA4a1q/DmBrHgPcmjiGoh//EwC5nGPEmS4RcfkVKOhJf+WOgoxJclFz3kgn//dBA+ya1GhurNn8zb//9NNutNuhz31f////9vt///z+IdAEAAAK4LQIAKobHItEIYCGAExBwe8jcToF9zIKrEdDYIuP2MgOWFSE34wYiR5iqQPj0JIeoVdlG4VD4XA67mAcNa1fhzA1jwHuTRxDUQ//iYBczjHiTJcIuPyKlHQkv/LHQUYkuSi57yQT//uggfZNajQ3Vmz+ Zt//+mm3Wm3Q576v////+32///5/EOgAAADVghQAAAAA//uQZAUAB1WI0PZugAAAAAoQwAAAEk3nRd2qAAAAACiDgAAAAAAABCqEEQRLCgwpBGMlJkIz8jKhGvj4k6jzRnqasNKIeoh5gI7BJaC1A1AoNBjJgbyApVS4IDlZgDU5WUAxEKDNmmALHzZp0Fkz1FMTmGFl1FMEyodIavcCAUHDWrKAIA4aa2oCgILEBupZgHvAhEBcZ6joQBxS76AgccrFlczBvKLC0QI2cBoCFvfTDAo7eoOQInqDPBtvrDEZBNYN5xwNwxQRfw8ZQ5wQVLvO8OYU+mHvFLlDh05Mdg7BT6YrRPpCBznMB2r//xKJjyyOh+cImr2/4doscwD6neZjuZR4AgAABYAAAABy1xcdQtxYBYYZdifkUDgzzXaXn98Z0oi9ILU5mBjFANmRwlVJ3/6jYDAmxaiDG3/6xjQQCCKkRb/6kg/wW+kSJ5//rLobkLSiKmqP/0ikJuDaSaSf/6JiLYLEYnW/+kXg1WRVJL/9EmQ1YZIsv/6Qzwy5qk7/+tEU0nkls3/zIUMPKNX/6yZLf+kFgAfgGyLFAUwY//uQZAUABcd5UiNPVXAAAApAAAAAE0VZQKw9ISAAACgAAAAAVQIygIElVrFkBS+Jhi+EAuu+lKAkYUEIsmEAEoMeDmCETMvfSHTGkF5RWH7kz/ESHWPAq/kcCRhqBtMdokPdM7vil7RG98A2sc7zO6ZvTdM7pmOUAZTnJW+NXxqmd41dqJ6mLTXxrPpnV8avaIf5SvL7pndPvPpndJR9Kuu8fePvuiuhorgWjp7Mf/PRjxcFCPDkW31srioCExivv9lcwKEaHsf/7ow2Fl1T/9RkXgEhYElAoCLFtMArxwivDJJ+bR1HTKJdlEoTELCIqgEwVGSQ+hIm0NbK8WXcTEI0UPoa2NbG4y2K00JEWbZavJXkYaqo9CRHS55FcZTjKEk3NKoCYUnSQ 0rWxrZbFKbKIhOKPZe1cJKzZSaQrIyULHDZmV5K4xySsDRKWOruanGtjLJXFEmwaIbDLX0hIPBUQPVFVkQkDoUNfSoDgQGKPekoxeGzA4DUvnn4bxzcZrtJyipKfPNy5w+9lnXwgqsiyHNeSVpemw4bWb9psYeq//uQZBoABQt4yMVxYAIAAAkQoAAAHvYpL5m6AAgAACXDAAAAD59jblTirQe9upFsmZbpMudy7Lz1X1DYsxOOSWpfPqNX2WqktK0DMvuGwlbNj44TleLPQ+Gsfb+GOWOKJoIrWb3cIMeeON6lz2umTqMXV8Mj30yWPpjoSa9ujK8SyeJP5y5mOW1D6hvLepeveEAEDo0mgCRClOEgANv3B9a6fikgUSu/DmAMATrGx7nng5p5iimPNZsfQLYB2sDLIkzRKZOHGAaUyDcpFBSLG9MCQALgAIgQs2YunOszLSAyQYPVC2YdGGeHD2dTdJk1pAHGAWDjnkcLKFymS3RQZTInzySoBwMG0QueC3gMsCEYxUqlrcxK6k1LQQcsmyYeQPdC2YfuGPASCBkcVMQQqpVJshui1tkXQJQV0OXGAZMXSOEEBRirXbVRQW7ugq7IM7rPWSZyDlM3IuNEkxzCOJ0ny2ThNkyRai1b6ev//3dzNGzNb//4uAvHT5sURcZCFcuKLhOFs8mLAAEAt4UWAAIABAAAAAB4qbHo0tIjVkUU//uQZAwABfSFz3ZqQAAAAAngwAAAE1HjMp2qAAAAACZDgAAAD5UkTE1UgZEUExqYynN1qZvqIOREEFmBcJQkwdxiFtw0qEOkGYfRDifBui9MQg4QAHAqWtAWHoCxu1Yf4VfWLPIM2mHDFsbQEVGwyqQoQcwnfHeIkNt9YnkiaS1oizycqJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7 FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb//////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=" | |
)).play()} | |
setTimeout(() => { | |
if (document.querySelector("[data-test='accountUserName']").textContent == 'Sign in') { | |
alert("TAMPERMONKEY: You're not logged in. Log in first.") | |
} | |
},3000); | |
const superInstantCheckout = async () => { | |
const preCheckoutRes = await fetch("https://carts.target.com/web_checkouts/v1/pre_checkout?field_groups=ADDRESSES%2CCART%2CCART_ITEMS%2CDELIVERY_WINDOWS%2CPAYMENT_INSTRUCTIONS%2CPICKUP_INSTRUCTIONS%2CPROMOTION_CODES%2CSUMMARY&key=" + PRIVATE_ACCESS_KEY, { | |
"headers": { | |
"accept": "application/json", | |
"accept-language": "en-US,en;q=0.9", | |
"content-type": "application/json", | |
"sec-fetch-dest": "empty", | |
"sec-fetch-mode": "cors", | |
"sec-fetch-site": "same-site", | |
"x-application-name": "web" | |
}, | |
"referrer": "https://www.target.com/co-review?precheckout=true", | |
"body": "{\"cart_type\":\"REGULAR\"}", | |
"method": "POST", | |
"mode": "cors", | |
"credentials": "include" | |
}); | |
console.info('%c TAMPERMONKEY: At pre-checkout stage. Result:', consoleBg3, await preCheckoutRes.json()); | |
const res = await fetch("https://carts.target.com/web_checkouts/v1/checkout?field_groups=ADDRESSES%2CCART%2CCART_ITEMS%2CDELIVERY_WINDOWS%2CPAYMENT_INSTRUCTIONS%2CPICKUP_INSTRUCTIONS%2CPROMOTION_CODES%2CSUMMARY&key=" + PRIVATE_ACCESS_KEY, { | |
"headers": { | |
"accept": "application/json", | |
"accept-language": "en-US,en;q=0.9", | |
"content-type": "application/json", | |
"sec-fetch-dest": "empty", | |
"sec-fetch-mode": "cors", | |
"sec-fetch-site": "same-site", | |
"x-application-name": "web" | |
}, | |
"referrer": "https://www.target.com/co-review", | |
"body": "{\"cart_type\":\"REGULAR\",\"channel_id\":10}", | |
"method": "POST", | |
"mode": "cors", | |
"credentials": "include" | |
}); | |
console.info('%c TAMPERMONKEY: Purchase attempted!!! Result:', consoleBg3, await res.json()) | |
} | |
// if it's a product detail page | |
if (isPDP) { | |
// CHECK FOR STOCK | |
setInterval(async function() { | |
if (GM_getValue('brucebentleyPS5Purchased')) return console.log('TAMPERMONKEY: Purchased a PS5 in another tab. Stopped.') | |
const res = await fetch("https://redsky.target.com/redsky_aggregations/v1/web/pdp_fulfillment_v1?key=" + PUBLIC_ACCESS_KEY + "&tcin="+ PRODUCT_ID +"&store_id=1108&zip=11787&state=NY&latitude=40.870&longitude=-73.210&scheduled_delivery_store_id=1108&pricing_store_id=1108&fulfillment_test_mode=grocery_opu_team_member_test&is_bot=false", { | |
"headers": { | |
"accept": "application/json", | |
"accept-language": "en-US,en;q=0.9", | |
"sec-fetch-dest": "empty", | |
"sec-fetch-mode": "cors", | |
"sec-fetch-site": "same-site" | |
}, | |
"referrer": "https://www.target.com/p/playstation-5-console/-/A-81114595", | |
"body": null, | |
"method": "GET", | |
"mode": "cors", | |
"credentials": "omit" | |
}); | |
const resJson = await res.json() | |
let availStatus; | |
if (resJson.data && resJson.data.product && resJson.data.product.fulfillment) { | |
availStatus = resJson.data.product.fulfillment.shipping_options.availability_status | |
} | |
if (availStatus == 'PRE_ORDER_UNSELLABLE') { | |
console.log('TAMPERMONKEY: No stock available.') | |
stockAvail = false; | |
timeoutValid = true; | |
} else { | |
beep(); beep(); beep(); | |
stockAvail = true | |
return console.info('%c TAMPERMONKEY: ' + availStatus, consoleBg2, ' \n', new Date(), '\n', resJson); | |
} | |
}, CHECK_FOR_STOCK_SECONDS*1000); | |
// ADD TO CART | |
setInterval(async function() { | |
if (!timeoutValid || !stockAvail) return; | |
// I don't advise having multiple competing tabs, but this will attempt to prevent dupe purchases | |
if (GM_getValue('brucebentleyPS5Purchased')) return console.log('TAMPERMONKEY: Purchased a PS5 in another tab. Stopped.') | |
// run this timeout instantly, once. It'll re-enable in the block below | |
timeoutValid = false; | |
const res = await fetch("https://carts.target.com/web_checkouts/v1/cart_items?field_groups=CART%2CCART_ITEMS%2CSUMMARY&key=" + PRIVATE_ACCESS_KEY, { | |
"headers": { | |
"accept": "application/json", | |
"accept-language": "en-US,en;q=0.9", | |
"content-type": "application/json", | |
"sec-fetch-dest": "empty", | |
"sec-fetch-mode": "cors", | |
"sec-fetch-site": "same-site", | |
"x-application-name": "web" | |
}, | |
"referrer": "https://www.target.com/p/playstation-5-console/-/A-81114595", | |
"body": "{\"cart_type\":\"REGULAR\",\"channel_id\":\"10\",\"shopping_context\":\"DIGITAL\",\"cart_item\":{\"tcin\":\"" + PRODUCT_ID + "\",\"quantity\":1,\"item_channel_id\":\"10\"},\"fulfillment\":{\"fulfillment_test_mode\":\"grocery_opu_team_member_test\"}}", | |
"method": "POST", | |
"mode": "cors", | |
"credentials": "include" | |
}); | |
const resJson = await res.json() | |
if (res.ok || resJson.cart_id) { | |
console.info('%c TAMPERMONKEY: Successfully added to cart! Attempting to purchase...', consoleBg3, resJson); | |
timeoutValid = false; | |
GM_setValue('brucebentleyPS5Purchased', true); | |
superInstantCheckout() | |
} else { | |
const err = resJson['Error']['Detail']; | |
return console.error('%c TAMPERMONKEY: add to cart failed. ', consoleBg1, '\n', new Date(), '\n', err, res, resJson); | |
} | |
}, 1); | |
// reset the add to cart timeout | |
// in case adding failed the first time. | |
// don't make this too aggressive! | |
setInterval(() => { | |
timeoutValid = true; | |
}, REPEATEDLY_ADD_TO_CART_SECONDS*1000); | |
// reload the page every so often to refresh the session cookies/not get bot-banned | |
setInterval(() => { | |
window.location.reload() | |
}, RELOAD_PAGE_MINUTES*60*1000); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment