diff --git a/src/store/model/helpers/nvidia.ts b/src/store/model/helpers/nvidia.ts index 3937f00..268a38b 100644 --- a/src/store/model/helpers/nvidia.ts +++ b/src/store/model/helpers/nvidia.ts @@ -1,4 +1,4 @@ -import {Browser, Response} from 'puppeteer'; +import {Browser, Page, Response} from 'puppeteer'; import {NvidiaRegionInfo, regionInfos} from '../nvidia-api'; import {Config} from '../../../config'; import {Link} from '../store'; @@ -6,84 +6,75 @@ import {Logger} from '../../../logger'; import open from 'open'; import {timestampUrlParameter} from '../../timestamp-url-parameter'; -const nvidiaApiKey = '9485fa7b159e42edb08a83bde0d83dia'; - function getRegionInfo(): NvidiaRegionInfo { - const country = Array.from(regionInfos.keys()).includes(Config.store.country) ? Config.store.country : 'usa'; + let country = Config.store.country; + if (!regionInfos.has(country)) { + country = 'usa'; + } - const defaultRegionInfo: NvidiaRegionInfo = {drLocale: 'en_us', fe2060SuperId: 5379432500, fe3080Id: 5438481700, fe3090Id: null, nvidiaLocale: 'en_us'}; - return regionInfos.get(country) ?? defaultRegionInfo; + const regionInfo = regionInfos.get(country); + if (!regionInfo) { + throw new Error(`LogicException could not retrieve region info for ${country}`); + } + + return regionInfo; } -function digitalRiverStockUrl(id: number, drLocale: string): string { - return `https://api.digitalriver.com/v1/shoppers/me/products/${id}/inventory-status?` + - `&apiKey=${nvidiaApiKey}` + - `&locale=${drLocale}` + - timestampUrlParameter(); +function nvidiaStockUrl(id: number, drLocale: string, currency: string): string { + return `https://api-prod.nvidia.com/direct-sales-shop/DR/products/${drLocale}/${currency}/${id}?` + + timestampUrlParameter().slice(1); } interface NvidiaSessionTokenJSON { - access_token: string; + session_token: string; +} + +interface NvidiaAddToCardJSON { + location: string; } function nvidiaSessionUrl(nvidiaLocale: string): string { return `https://store.nvidia.com/store/nvidia/SessionToken?format=json&locale=${nvidiaLocale}` + - `&apiKey=${nvidiaApiKey}` + timestampUrlParameter(); } -function addToCartUrl(id: number, drLocale: string, token: string): string { - return 'https://api.digitalriver.com/v1/shoppers/me/carts/active/line-items?format=json&method=post' + - `&productId=${id}` + - `&token=${token}` + - '&quantity=1' + - `&locale=${drLocale}` + - timestampUrlParameter(); -} +async function addToCartAndGetLocationRedirect(page: Page, sessionToken: string, productId: number): Promise { + const url = 'https://api-prod.nvidia.com/direct-sales-shop/DR/add-to-cart'; -function checkoutUrl(drLocale: string, token: string): string { - return `https://api.digitalriver.com/v1/shoppers/me/carts/active/web-checkout?token=${token}&locale=${drLocale}`; + page.removeAllListeners('request'); + + await page.setRequestInterception(true); + + page.on('request', interceptedRequest => { + void interceptedRequest.continue({ + headers: { + ...interceptedRequest.headers(), + 'content-type': 'application/json', + nvidia_shop_id: sessionToken + }, + method: 'POST', + postData: JSON.stringify({ + products: [ + {productId, quantity: 1} + ] + }) + }); + }); + + const response = await page.goto(url, {waitUntil: 'networkidle0'}); + if (response === null) { + throw new Error('NvidiaAddToCartUnavailable'); + } + + const locationData = await response.json() as NvidiaAddToCardJSON; + + return locationData.location; } function fallbackCartUrl(nvidiaLocale: string): string { return `https://www.nvidia.com/${nvidiaLocale}/shop/geforce?${timestampUrlParameter()}`; } -export function generateSetupAction() { - return async (browser: Browser) => { - const {drLocale, nvidiaLocale} = getRegionInfo(); - - const page = await browser.newPage(); - - let response: Response | null; - try { - Logger.debug('creating cart/session token...'); - - response = await page.goto(nvidiaSessionUrl(nvidiaLocale), {waitUntil: 'networkidle0'}); - - if (response === null) { - throw new Error('NvidiaAccessTokenUnavailable'); - } - - const data = await response.json() as NvidiaSessionTokenJSON; - const accessToken = data.access_token; - const cartUrl = checkoutUrl(drLocale, accessToken); - - Logger.debug(cartUrl); - - if (Config.browser.open) { - Logger.info('ℹ opening browser for user to login'); - - await open(cartUrl); - } - } catch (error) { - Logger.error('✖ [nvidia] cannot generate cart/session token, continuing without; auto "add to cart" may not work', error); - } - - await page.close(); - }; -} - export function generateOpenCartAction(id: number, nvidiaLocale: string, drLocale: string, cardName: string) { return async (browser: Browser) => { const page = await browser.newPage(); @@ -101,16 +92,13 @@ export function generateOpenCartAction(id: number, nvidiaLocale: string, drLocal } const data = await response.json() as NvidiaSessionTokenJSON; - const accessToken = data.access_token; + const sessionToken = data.session_token; Logger.info(`🚀🚀🚀 [nvidia] ${cardName}, adding to cart 🚀🚀🚀`); - response = await page.goto(addToCartUrl(id, drLocale, accessToken), {waitUntil: 'networkidle0'}); + cartUrl = await addToCartAndGetLocationRedirect(page, sessionToken, id); Logger.info(`🚀🚀🚀 [nvidia] ${cardName}, opening checkout page 🚀🚀🚀`); - - cartUrl = checkoutUrl(drLocale, accessToken); - Logger.info(cartUrl); await open(cartUrl); @@ -129,7 +117,7 @@ export function generateOpenCartAction(id: number, nvidiaLocale: string, drLocal } export function generateLinks(): Link[] { - const {drLocale, nvidiaLocale, fe3080Id, fe3090Id, fe2060SuperId} = getRegionInfo(); + const {drLocale, nvidiaLocale, fe3080Id, fe3090Id, fe2060SuperId, currency} = getRegionInfo(); const links: Link[] = []; @@ -139,7 +127,7 @@ export function generateLinks(): Link[] { model: 'test:model', openCartAction: generateOpenCartAction(fe2060SuperId, nvidiaLocale, drLocale, 'TEST CARD debug'), series: 'test:series', - url: digitalRiverStockUrl(fe2060SuperId, drLocale) + url: nvidiaStockUrl(fe2060SuperId, drLocale, currency) }); } @@ -149,7 +137,7 @@ export function generateLinks(): Link[] { model: 'founders edition', openCartAction: generateOpenCartAction(fe3080Id, nvidiaLocale, drLocale, 'nvidia founders edition 3080'), series: '3080', - url: digitalRiverStockUrl(fe3080Id, drLocale) + url: nvidiaStockUrl(fe3080Id, drLocale, currency) }); } @@ -159,7 +147,7 @@ export function generateLinks(): Link[] { model: 'founders edition', openCartAction: generateOpenCartAction(fe3090Id, nvidiaLocale, drLocale, 'nvidia founders edition 3090'), series: '3090', - url: digitalRiverStockUrl(fe3090Id, drLocale) + url: nvidiaStockUrl(fe3090Id, drLocale, currency) }); } diff --git a/src/store/model/nvidia-api.ts b/src/store/model/nvidia-api.ts index a7e19c2..539594a 100644 --- a/src/store/model/nvidia-api.ts +++ b/src/store/model/nvidia-api.ts @@ -1,9 +1,10 @@ -import {generateLinks, generateSetupAction} from './helpers/nvidia'; import {Store} from './store'; +import {generateLinks} from './helpers/nvidia'; // Region/country set by config file, silently ignores null / missing values and defaults to usa export interface NvidiaRegionInfo { + currency: string; drLocale: string; fe3080Id: number | null; fe3090Id: number | null; @@ -12,25 +13,25 @@ export interface NvidiaRegionInfo { } export const regionInfos = new Map([ - ['austria', {drLocale: 'de_de', fe2060SuperId: null, fe3080Id: 5440853700, fe3090Id: null, nvidiaLocale: 'de_de'}], - ['belgium', {drLocale: 'fr_fr', fe2060SuperId: 5394902700, fe3080Id: 5438795700, fe3090Id: null, nvidiaLocale: 'fr_fr'}], - ['canada', {drLocale: 'en_us', fe2060SuperId: null, fe3080Id: 5438481700, fe3090Id: null, nvidiaLocale: 'en_ca'}], - ['czechia', {drLocale: 'en_gb', fe2060SuperId: null, fe3080Id: 5438793800, fe3090Id: null, nvidiaLocale: 'en_gb'}], - ['denmark', {drLocale: 'en_gb', fe2060SuperId: null, fe3080Id: 5438793300, fe3090Id: null, nvidiaLocale: 'en_gb'}], - ['finland', {drLocale: 'en_gb', fe2060SuperId: null, fe3080Id: 5438793300, fe3090Id: null, nvidiaLocale: 'en_gb'}], - ['france', {drLocale: 'fr_fr', fe2060SuperId: null, fe3080Id: 5438795200, fe3090Id: null, nvidiaLocale: 'fr_fr'}], - ['germany', {drLocale: 'de_de', fe2060SuperId: null, fe3080Id: 5438792300, fe3090Id: null, nvidiaLocale: 'de_de'}], - ['great_britain', {drLocale: 'en_gb', fe2060SuperId: null, fe3080Id: 5438792800, fe3090Id: null, nvidiaLocale: 'en_gb'}], - ['ireland', {drLocale: 'en_gb', fe2060SuperId: null, fe3080Id: 5438792800, fe3090Id: null, nvidiaLocale: 'en_gb'}], - ['italy', {drLocale: 'it_it', fe2060SuperId: null, fe3080Id: 5438796200, fe3090Id: null, nvidiaLocale: 'it_it'}], - ['luxembourg', {drLocale: 'fr_fr', fe2060SuperId: 5394902700, fe3080Id: 5438795700, fe3090Id: null, nvidiaLocale: 'fr_fr'}], - ['netherlands', {drLocale: 'nl_nl', fe2060SuperId: 5394903500, fe3080Id: 5438796700, fe3090Id: null, nvidiaLocale: 'nl_nl'}], - ['poland', {drLocale: 'pl_pl', fe2060SuperId: null, fe3080Id: 5438797700, fe3090Id: null, nvidiaLocale: 'pl_pSl'}], - ['portugal', {drLocale: 'en_gb', fe2060SuperId: null, fe3080Id: 5438794300, fe3090Id: null, nvidiaLocale: 'en_gb'}], - ['russia', {drLocale: 'ru_ru', fe2060SuperId: null, fe3080Id: null, fe3090Id: null, nvidiaLocale: 'ru_ru'}], - ['spain', {drLocale: 'es_es', fe2060SuperId: null, fe3080Id: 5438794800, fe3090Id: null, nvidiaLocale: 'es_es'}], - ['sweden', {drLocale: 'sv_SE', fe2060SuperId: null, fe3080Id: 5438798100, fe3090Id: null, nvidiaLocale: 'sv_se'}], - ['usa', {drLocale: 'en_us', fe2060SuperId: 5379432500, fe3080Id: 5438481700, fe3090Id: 5438481600, nvidiaLocale: 'en_us'}] + ['austria', {currency: 'EUR', drLocale: 'de_de', fe2060SuperId: null, fe3080Id: 5440853700, fe3090Id: null, nvidiaLocale: 'de_de'}], + ['belgium', {currency: 'EUR', drLocale: 'fr_fr', fe2060SuperId: 5394902700, fe3080Id: 5438795700, fe3090Id: null, nvidiaLocale: 'fr_fr'}], + ['canada', {currency: 'CAD', drLocale: 'en_us', fe2060SuperId: null, fe3080Id: 5438481700, fe3090Id: null, nvidiaLocale: 'en_ca'}], + ['czechia', {currency: 'CZK', drLocale: 'en_gb', fe2060SuperId: null, fe3080Id: 5438793800, fe3090Id: null, nvidiaLocale: 'en_gb'}], + ['denmark', {currency: 'EUR', drLocale: 'en_gb', fe2060SuperId: null, fe3080Id: 5438793300, fe3090Id: null, nvidiaLocale: 'en_gb'}], + ['finland', {currency: 'EUR', drLocale: 'en_gb', fe2060SuperId: null, fe3080Id: 5438793300, fe3090Id: null, nvidiaLocale: 'en_gb'}], + ['france', {currency: 'EUR', drLocale: 'fr_fr', fe2060SuperId: null, fe3080Id: 5438795200, fe3090Id: null, nvidiaLocale: 'fr_fr'}], + ['germany', {currency: 'EUR', drLocale: 'de_de', fe2060SuperId: null, fe3080Id: 5438792300, fe3090Id: null, nvidiaLocale: 'de_de'}], + ['great_britain', {currency: 'GBP', drLocale: 'en_gb', fe2060SuperId: null, fe3080Id: 5438792800, fe3090Id: null, nvidiaLocale: 'en_gb'}], + ['ireland', {currency: 'GBP', drLocale: 'en_gb', fe2060SuperId: null, fe3080Id: 5438792800, fe3090Id: null, nvidiaLocale: 'en_gb'}], + ['italy', {currency: 'EUR', drLocale: 'it_it', fe2060SuperId: null, fe3080Id: 5438796200, fe3090Id: null, nvidiaLocale: 'it_it'}], + ['luxembourg', {currency: 'EUR', drLocale: 'fr_fr', fe2060SuperId: 5394902700, fe3080Id: 5438795700, fe3090Id: null, nvidiaLocale: 'fr_fr'}], + ['netherlands', {currency: 'EUR', drLocale: 'nl_nl', fe2060SuperId: 5394903500, fe3080Id: 5438796700, fe3090Id: null, nvidiaLocale: 'nl_nl'}], + ['poland', {currency: 'PLN', drLocale: 'pl_pl', fe2060SuperId: null, fe3080Id: 5438797700, fe3090Id: null, nvidiaLocale: 'pl_pSl'}], + ['portugal', {currency: 'EUR', drLocale: 'en_gb', fe2060SuperId: null, fe3080Id: 5438794300, fe3090Id: null, nvidiaLocale: 'en_gb'}], + ['russia', {currency: 'RUB', drLocale: 'ru_ru', fe2060SuperId: null, fe3080Id: null, fe3090Id: null, nvidiaLocale: 'ru_ru'}], + ['spain', {currency: 'EUR', drLocale: 'es_es', fe2060SuperId: null, fe3080Id: 5438794800, fe3090Id: null, nvidiaLocale: 'es_es'}], + ['sweden', {currency: 'SEK', drLocale: 'sv_se', fe2060SuperId: null, fe3080Id: 5438798100, fe3090Id: null, nvidiaLocale: 'sv_se'}], + ['usa', {currency: 'USD', drLocale: 'en_us', fe2060SuperId: 5379432500, fe3080Id: 5438481700, fe3090Id: 5438481600, nvidiaLocale: 'en_us'}] ]); export const NvidiaApi: Store = { @@ -41,6 +42,5 @@ export const NvidiaApi: Store = { } }, links: generateLinks(), - name: 'nvidia-api', - setupAction: generateSetupAction() + name: 'nvidia-api' };