SHOW:
|
|
- or go back to the newest paste.
| 1 | const rp = require("request-promise")
| |
| 2 | ||
| 3 | const getPookyUrl = (region) => {
| |
| 4 | let usPooky = "https://pooky.dev:1337/gen?token=h20-44a81-s28dn-8ad9s" | |
| 5 | let euPooky = "https://pooky.dev:1337/gen?token=h20-44a81-s28dn-8ad9s®ion=eu" | |
| 6 | return region === 'SupremeUS' ? usPooky : euPooky | |
| 7 | } | |
| 8 | ||
| 9 | const iPhone6 = {
| |
| 10 | 'name': 'iPhone 6', | |
| 11 | 'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | |
| 12 | 'viewport': {
| |
| 13 | 'width': 375, | |
| 14 | 'height': 667, | |
| 15 | 'deviceScaleFactor': 2, | |
| 16 | 'isMobile': true, | |
| 17 | 'hasTouch': true, | |
| 18 | 'isLandscape': false | |
| 19 | } | |
| 20 | }; | |
| 21 | ||
| 22 | function sleep(ms) {
| |
| 23 | return new Promise(resolve => {
| |
| 24 | setTimeout(resolve, ms) | |
| 25 | }) | |
| 26 | } | |
| 27 | ||
| 28 | ||
| 29 | const encodeVariants = (variants) => {
| |
| 30 | let varObj = {}
| |
| 31 | variants.forEach(v => varObj[v] = 1) | |
| 32 | return encodeURIComponent(JSON.stringify(varObj).replace(/'/g, '"')) | |
| 33 | } | |
| 34 | ||
| 35 | const getCheckoutData = (region, variants) => {
| |
| 36 | const usCheckoutData = {
| |
| 37 | 'store_credit_id': '', | |
| 38 | 'from_mobile': '1', | |
| 39 | 'cookie-sub': encodeVariants(variants), | |
| 40 | 'same_as_billing_address': '1', | |
| 41 | 'scerkhaj': 'CKCRSUJHXH', | |
| 42 | 'order[bn]': "Daniel Young", | |
| 43 | 'order[billing_name]': "", | |
| 44 | 'order[email]': "[email protected]", | |
| 45 | 'order[tel]': "2155123271", | |
| 46 | 'order[billing_address]': "3561 Meadowlark Drive", | |
| 47 | 'order[billing_address_2]': "", | |
| 48 | 'order[billing_zip]': "19006", | |
| 49 | 'order[billing_city]': "Huntingdon Valley", | |
| 50 | 'order[billing_state]': "Pennsylvania", | |
| 51 | 'order[billing_country]': "United States", | |
| 52 | 'riearmxa': "4478874829206427", | |
| 53 | 'credit_card[month]': "02", | |
| 54 | 'credit_card[year]': "2020", | |
| 55 | 'rand': '', | |
| 56 | 'credit_card[meknk]': "717", | |
| 57 | 'order[terms]': 0, | |
| 58 | 'order[terms]': 1, | |
| 59 | 'g-recaptcha-response': "03AOLTBLRb_A0LF2utI5YYdYjkrIM2FZgxO4dLjQpwsGVSMuGAwdkK03VN-2Sq5r1G3BG6xFQeoxU-6ZWcwfsJaE-qrU4fFtlU2oyMb37_NtgPPUbsGE4rJxDRv3hKNZez1BTIQehk2taTXhFe9vtk0-9ro41486uTgk_9SxRSDMbpuU8ckeju1tXWzfNVetDOLEH66U7mROk3NpZYYUj8-A6wu7J9HAC1PGiVDlfDVAH8RmQQXEyYRQWSMfbsdeTN9OlypInmcRWHN59iXi9SieCdzH6Q1W35tOurTPzvU8LKHfjEUwN9b2wsMnato0zQlgui0sGTkCGPeXbQNTYcCiiZKwbjWuhckUGd_3OMfKPRpnctCrPAdxQ55aogYjjtHQCmj7-E4Y10dZIdZFQoEypqXWqwCC343w" | |
| 60 | } | |
| 61 | ||
| 62 | return region === 'SupremeUS' ? usCheckoutData : euCheckoutData | |
| 63 | } | |
| 64 | ||
| 65 | class SupremeClient {
| |
| 66 | ||
| 67 | constructor(task) {
| |
| 68 | this.task = task | |
| 69 | ||
| 70 | ||
| 71 | //keep track | |
| 72 | this.pookyString; | |
| 73 | ||
| 74 | //TODO: implement stop | |
| 75 | this.stopped = false; | |
| 76 | this.canStart = true; | |
| 77 | ||
| 78 | this.rp = rp.defaults({ jar: true, json: true });
| |
| 79 | ||
| 80 | } | |
| 81 | ||
| 82 | ||
| 83 | async start() {
| |
| 84 | console.log("Starting task")
| |
| 85 | this.stopped = false; | |
| 86 | this.canStart = false; | |
| 87 | ||
| 88 | } | |
| 89 | ||
| 90 | ||
| 91 | async stop() {
| |
| 92 | console.log(`Stopping task`) | |
| 93 | ||
| 94 | this.canStart = true; | |
| 95 | this.stopped = true; | |
| 96 | } | |
| 97 | ||
| 98 | async getItem() {
| |
| 99 | if (!this.stopped) {
| |
| 100 | const category = this.task.category; | |
| 101 | const keywords = this.task.keywords; | |
| 102 | ||
| 103 | console.log("keywords:", keywords)
| |
| 104 | ||
| 105 | const time = (new Date()).getTime(); | |
| 106 | let options = {
| |
| 107 | url: `https://www.supremenewyork.com/shop.json?_=${time}`,
| |
| 108 | method: 'get', | |
| 109 | headers: {
| |
| 110 | 'User-Agent': iPhone6.userAgent | |
| 111 | } | |
| 112 | }; | |
| 113 | ||
| 114 | console.log(options) | |
| 115 | ||
| 116 | try {
| |
| 117 | let response = await this.rp(options) | |
| 118 | ||
| 119 | const parsedProducts = response['products_and_categories'] | |
| 120 | ||
| 121 | var parsedNewProducts = [] | |
| 122 | ||
| 123 | //TODO: modify depending on values in html. | |
| 124 | if (category === 'All') {
| |
| 125 | for (let category of Object.values(parsedProducts)) {
| |
| 126 | for (let product of category) {
| |
| 127 | parsedNewProducts.push(product) | |
| 128 | } | |
| 129 | } | |
| 130 | } else {
| |
| 131 | if (category === 'New') | |
| 132 | parsedNewProducts = parsedProducts['new']; | |
| 133 | else | |
| 134 | parsedNewProducts = parsedProducts[category]; | |
| 135 | } | |
| 136 | ||
| 137 | const positiveKeywords = keywords.split(',').filter(keyword => keyword.includes('+')).map(keyword => keyword.replace('+', '').trim());
| |
| 138 | const negativeKeywords = keywords.split(',').filter(keyword => keyword.includes('-')).map(keyword => keyword.replace('-', '').trim());
| |
| 139 | console.log(positiveKeywords, negativeKeywords) | |
| 140 | for (let product of parsedNewProducts) {
| |
| 141 | let productTitle = product.name.replace(/[\u{0080}-\u{FFFF}]/gu, "")
| |
| 142 | let productId = product.id | |
| 143 | var posNum = 0 | |
| 144 | var negNum = 0 | |
| 145 | for (let posKw of positiveKeywords) {
| |
| 146 | if (productTitle.toLowerCase().includes(posKw.toLowerCase().trim())) {
| |
| 147 | posNum++ | |
| 148 | } | |
| 149 | } | |
| 150 | for (let negKw of negativeKeywords) {
| |
| 151 | if (productTitle.toLowerCase().includes(negKw.toLowerCase().trim())) {
| |
| 152 | negNum++ | |
| 153 | } | |
| 154 | } | |
| 155 | if (posNum === positiveKeywords.length && negNum === 0) {
| |
| 156 | // productTitle , productId | |
| 157 | //TODO: add error handling if no product is found | |
| 158 | console.log("found product", productTitle, productId)
| |
| 159 | return await this.getSizes(productId) | |
| 160 | } | |
| 161 | } | |
| 162 | } catch (err) {
| |
| 163 | console.log(`Error getting item: ${err.message}`)
| |
| 164 | await this.getItem() | |
| 165 | } | |
| 166 | } | |
| 167 | ||
| 168 | } | |
| 169 | ||
| 170 | async getSizes(productId) {
| |
| 171 | if (!this.stopped) {
| |
| 172 | console.log("Finding Size")
| |
| 173 | let productColorPref = this.task.color; | |
| 174 | let productSizePref = this.task.size; | |
| 175 | let options = {
| |
| 176 | url: `https://www.supremenewyork.com/shop/${productId}.json`,
| |
| 177 | method: 'get', | |
| 178 | headers: {
| |
| 179 | 'User-Agent': iPhone6.userAgent | |
| 180 | } | |
| 181 | }; | |
| 182 | ||
| 183 | try {
| |
| 184 | let response = await this.rp(options) | |
| 185 | const styles = response["styles"] | |
| 186 | ||
| 187 | ||
| 188 | ||
| 189 | console.log(styles) | |
| 190 | ||
| 191 | let colorId; | |
| 192 | let sizeId; | |
| 193 | ||
| 194 | for (let style of styles) {
| |
| 195 | if (style["name"].toLowerCase() === productColorPref.toLowerCase()) {
| |
| 196 | colorId = style["id"] | |
| 197 | for (let size of style["sizes"]) {
| |
| 198 | if (productSizePref === "None") {
| |
| 199 | sizeId = size['id'] | |
| 200 | } else if (size["name"].toLowerCase() === productSizePref.toLowerCase()) {
| |
| 201 | sizeId = size["id"]; | |
| 202 | ||
| 203 | break; | |
| 204 | } | |
| 205 | } | |
| 206 | ||
| 207 | break; | |
| 208 | } | |
| 209 | } | |
| 210 | ||
| 211 | //TODO: change to status message, maybe add retry? | |
| 212 | if (!colorId || !sizeId) {
| |
| 213 | console.log(colorId, sizeId) | |
| 214 | return undefined; | |
| 215 | } else {
| |
| 216 | console.log("got colorid and sizeid", colorId, sizeId)
| |
| 217 | return await this.atc(colorId, sizeId, productId) | |
| 218 | } | |
| 219 | ||
| 220 | } catch (err) {
| |
| 221 | this.sendStatus("Error Getting Sizes")
| |
| 222 | await getSizes(productId) | |
| 223 | console.log(`Error getting sizes: ${err}`)
| |
| 224 | } | |
| 225 | ||
| 226 | } | |
| 227 | ||
| 228 | } | |
| 229 | ||
| 230 | async atc(colorId, sizeId, productId, formStyle, formSize) {
| |
| 231 | if (!this.stopped) {
| |
| 232 | console.log("Adding To Cart")
| |
| 233 | ||
| 234 | let parsedPooky, msBefore | |
| 235 | if (this.task.pooky === "on") {
| |
| 236 | msBefore = Date.now() | |
| 237 | parsedPooky = await this.getPooky(false) | |
| 238 | ||
| 239 | if (!parsedPooky) {
| |
| 240 | console.log("Could not get pooky cookies... stopping.")
| |
| 241 | return this.stopped = true; | |
| 242 | } | |
| 243 | } | |
| 244 | ||
| 245 | ||
| 246 | //TODO: check region, proxy support | |
| 247 | let options = {
| |
| 248 | url: `https://www.supremenewyork.com/shop/${productId}/add.json`,
| |
| 249 | method: 'POST', | |
| 250 | headers: {
| |
| 251 | 'Host': 'www.supremenewyork.com', | |
| 252 | 'Accept': 'application/json', | |
| 253 | "Content-Type": "application/x-www-form-urlencoded", | |
| 254 | 'X-Requested-With': 'XMLHttpRequest', | |
| 255 | 'Pragma': 'no-cache', | |
| 256 | 'Cache-Control': 'no-cache', | |
| 257 | 'Accept-Language': 'en-us', | |
| 258 | 'Origin': 'https://www.supremenewyork.com', | |
| 259 | 'User-Agent': "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1", | |
| 260 | 'Referer': 'https://www.supremenewyork.com/mobile', | |
| 261 | 'Connection': 'keep-alive', | |
| 262 | }, | |
| 263 | form: {
| |
| 264 | "qty": "1" | |
| 265 | }, | |
| 266 | proxy: this.task.proxy | |
| 267 | }; | |
| 268 | ||
| 269 | if (this.task.site === "SupremeUS") {
| |
| 270 | options["form"]["s"] = sizeId | |
| 271 | options["form"]["st"] = colorId | |
| 272 | } else {
| |
| 273 | options["form"]["size"] = sizeId | |
| 274 | options["form"]["style"] = colorId | |
| 275 | } | |
| 276 | ||
| 277 | if (this.task.pooky === "on") {
| |
| 278 | options["headers"]["cookie"] = `lastid=${msBefore}; ${parsedPooky}`
| |
| 279 | } | |
| 280 | console.log(options["form"]) | |
| 281 | try {
| |
| 282 | let response = await this.rp(options) | |
| 283 | ||
| 284 | console.log("atc response:", response)
| |
| 285 | ||
| 286 | //TODO: check | |
| 287 | if (response[0].in_stock === true) {
| |
| 288 | console.log("Added to cart")
| |
| 289 | return await this.checkout(sizeId) | |
| 290 | } else {
| |
| 291 | console.log("Error")
| |
| 292 | sleep(1000) | |
| 293 | return this.atc(colorId, sizeId, productId) | |
| 294 | } | |
| 295 | ||
| 296 | } catch (err) {
| |
| 297 | console.log(`Error adding to cart: ${err.message}`)
| |
| 298 | } | |
| 299 | } | |
| 300 | } | |
| 301 | ||
| 302 | async checkout(variant) {
| |
| 303 | if (!this.stopped) {
| |
| 304 | let parsedPooky, msBefore | |
| 305 | if (this.task.pooky === "on") {
| |
| 306 | msBefore = Date.now() | |
| 307 | parsedPooky = await this.getPooky(true) | |
| 308 | ||
| 309 | if (!parsedPooky) {
| |
| 310 | console.log("Could not get pooky cookies... stopping.")
| |
| 311 | return this.stopped = true; | |
| 312 | } | |
| 313 | } | |
| 314 | ||
| 315 | //TODO: use promise.all or something to get captcha and pooky at same time.. | |
| 316 | ||
| 317 | ||
| 318 | let options = {
| |
| 319 | url: `https://www.supremenewyork.com/checkout.json`, | |
| 320 | method: 'post', | |
| 321 | headers: {
| |
| 322 | 'Accept': 'application/json', | |
| 323 | 'accept-encoding': 'gzip, deflate, br', | |
| 324 | 'Accept-Language': 'en-US,en;q=0.9', | |
| 325 | 'Origin': 'https://www.supremenewyork.com', | |
| 326 | 'Referer': 'https://www.supremenewyork.com/mobile/', | |
| 327 | "Content-Type": "application/x-www-form-urlencoded", | |
| 328 | 'User-Agent': "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1", | |
| 329 | 'X-Requested-With': 'XMLHttpRequest', | |
| 330 | 'sec-fetch-mode': 'cors', | |
| 331 | 'sec-fetch-site': 'same-origin' | |
| 332 | }, | |
| 333 | formData: getCheckoutData(this.task.site, [variant]), | |
| 334 | // proxy: this.task.proxy, | |
| 335 | resolveWithFullResponse: true | |
| 336 | }; | |
| 337 | ||
| 338 | if (this.task.pooky === "on") {
| |
| 339 | options["headers"]["cookie"] = `lastid=${msBefore}; ${parsedPooky}`
| |
| 340 | } | |
| 341 | ||
| 342 | ||
| 343 | try {
| |
| 344 | ||
| 345 | console.log("Checking Out")
| |
| 346 | await sleep(3) | |
| 347 | let response = await this.rp(options) | |
| 348 | ||
| 349 | console.log(response.body) | |
| 350 | ||
| 351 | if (response.status === 'failed') {
| |
| 352 | console.log('Failed to checkout')
| |
| 353 | } else if (response.status === 'outOfStock') {
| |
| 354 | console.log("Item OOS")
| |
| 355 | } else if (response.status === 'queued') {
| |
| 356 | console.log('Queued...')
| |
| 357 | console.log(response.slug) | |
| 358 | } | |
| 359 | ||
| 360 | ||
| 361 | } catch (err) {
| |
| 362 | console.log(`Error checking out: ${err.message}`)
| |
| 363 | return this.stopped = true; | |
| 364 | } | |
| 365 | } | |
| 366 | } | |
| 367 | ||
| 368 | /*async checkSlug(slug) {
| |
| 369 | try {
| |
| 370 | const res = await this.rp(`https://www.supremenewyork.com/checkout/${slug}/status.json`)
| |
| 371 | if (res.data.status === 'queued') {
| |
| 372 | console.log('In queue.. Checking again in 1s')
| |
| 373 | await sleep(1000) | |
| 374 | return this.checkStatus(slug) | |
| 375 | } else if (res.data.status === 'failed') {
| |
| 376 | console.log(res.data) | |
| 377 | console.log('Failed to checkout')
| |
| 378 | ||
| 379 | } else if (res.data.status === "success") {
| |
| 380 | console.log("Checkout Success")
| |
| 381 | } | |
| 382 | } catch (err) {
| |
| 383 | console.log("Error checking slug", err.message)
| |
| 384 | } | |
| 385 | }*/ | |
| 386 | ||
| 387 | async getPooky(isCheckout) {
| |
| 388 | let pookyUrl = (isCheckout) ? `${getPookyUrl(this.task.site)}&pookyuuid=${this.pookyString}` : getPookyUrl(this.task.site);
| |
| 389 | ||
| 390 | let options = {
| |
| 391 | url: pookyUrl, | |
| 392 | method: 'get' | |
| 393 | }; | |
| 394 | ||
| 395 | console.log(options) | |
| 396 | ||
| 397 | try {
| |
| 398 | let response = await this.rp(options) | |
| 399 | console.log("pooky response", response)
| |
| 400 | if (response["status"] === "successful") {
| |
| 401 | if (!isCheckout) | |
| 402 | this.pookyString = response["cookie"][0].split("=")[1]
| |
| 403 | ||
| 404 | let pookyString = ""; | |
| 405 | for (let cookie of response["cookie"]) {
| |
| 406 | pookyString += `${cookie}; `
| |
| 407 | } | |
| 408 | console.log("RETURNING POOKY STRING", pookyString)
| |
| 409 | return pookyString; | |
| 410 | } else {
| |
| 411 | return undefined; | |
| 412 | } | |
| 413 | ||
| 414 | } catch (err) {
| |
| 415 | console.log("Error getting pooky ", err.message)
| |
| 416 | } | |
| 417 | } | |
| 418 | ||
| 419 | } | |
| 420 | ||
| 421 | ||
| 422 | var array = {"category": "Accessories", "keywords": "+hanes,+socks", "color": "Red", "size": "N/A", "pooky": "on", "site": "SupremeUS", "timer": ""}
| |
| 423 | var Supreme = new SupremeClient(array) | |
| 424 | Supreme.getItem() |