View difference between Paste ID: UWm6sz4E and sjX6EdSe
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&region=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()