import puppeteer from 'puppeteer'; import {Config} from '../config'; import {Logger} from '../logger'; import open from 'open'; import {Store} from './model'; import {sendNotification} from '../notification'; import {includesLabels} from './out-of-stock'; /** * Returns true if the brand should be checked for stock * * @param brand The brand of the GPU */ function filterBrand(brand: string) { if (Config.showOnlyBrands.length === 0) { return true; } return Config.showOnlyBrands.includes(brand); } /** * Responsible for looking up information about a each product within * a `Store`. It's important that we ignore `no-await-in-loop` here * because we don't want to get rate limited within the same store. * * @param store Vendor of graphics cards. */ export async function lookup(store: Store) { /* eslint-disable no-await-in-loop */ for (const link of store.links) { if (!filterBrand(link.brand)) { continue; } const browser = await puppeteer.launch(); const page = await browser.newPage(); page.setDefaultNavigationTimeout(Config.page.navigationTimeout); await page.setUserAgent(Config.page.userAgent); await page.setViewport({ height: Config.page.height, width: Config.page.width }); const graphicsCard = `${link.brand} ${link.model}`; try { await page.goto(link.url, {waitUntil: 'networkidle0'}); } catch { Logger.error(`✖ [${store.name}] ${graphicsCard} skipping; timed out`); await browser.close(); continue; } const bodyHandle = await page.$('body'); const textContent = await page.evaluate(body => body.textContent, bodyHandle); Logger.debug(textContent); if (includesLabels(textContent, link.oosLabels)) { Logger.info(`✖ [${store.name}] still out of stock: ${graphicsCard}`); } else if (link.captchaLabels && includesLabels(textContent, link.captchaLabels)) { Logger.warn(`✖ [${store.name}] CAPTCHA from: ${graphicsCard}`); } else { Logger.info(`🚀🚀🚀 [${store.name}] ${graphicsCard} IN STOCK 🚀🚀🚀`); Logger.info(link.url); if (Config.page.capture === 'true') { Logger.debug('ℹ saving screenshot'); await page.screenshot({path: `success-${Date.now()}.png`}); } const givenUrl = store.cartUrl ? store.cartUrl : link.url; if (Config.openBrowser === 'true') { await open(givenUrl); } sendNotification(givenUrl); } await browser.close(); } /* eslint-enable no-await-in-loop */ }