diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..ad2cf87 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,12 @@ +{ + "printWidth": 100, + "tabWidth": 4, + "useTabs": false, + "semi": true, + "singleQuote": true, + "quoteProps": "as-needed", + "trailingComma": "es5", + "bracketSpacing": true, + "arrowParens": "avoid", + "endOfLine": "auto" +} diff --git a/.vscode/launch.json b/.vscode/launch.json index c51bab9..5e43b44 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,7 +7,7 @@ { "type": "node", "request": "launch", - "name": "Launch Program", + "name": "Start", "program": "${workspaceFolder}\\app.js" } ] diff --git a/app.js b/app.js index 2d46b8d..785df57 100644 --- a/app.js +++ b/app.js @@ -1,18 +1,19 @@ -const _express = require("express"); +const _express = require('express'); const _app = _express(); -const _bodyParser = require("body-parser"); -const _httpClient = require("./services/http-client"); -const _steamScraper = require("./services/steam-scraper"); -const _logger = require("./services/logger"); +const _bodyParser = require('body-parser'); +const _httpClient = require('./services/http-client'); +const _steamScraper = require('./services/steam-scraper'); +const _oculusScraper = require('./services/oculus-scraper'); +const _logger = require('./services/logger'); const PORT = process.env.PORT || 8080; function main() { - _app.use(_express.static("public")); + _app.use(_express.static('public')); _app.use(_bodyParser.urlencoded({ extended: false })); _app.use(_bodyParser.json()); - _app.post("/api/app-scrape", async (req, res) => { + _app.post('/api/steam/app-scrape', async (req, res) => { let appUrl = req.body.url; let appPageHtml; @@ -20,7 +21,7 @@ function main() { appPageHtml = await _httpClient.get(appUrl); } catch (error) { _logger.error(error); - res.status(500).json({ message: "Error retrieving page HTML." }); + res.status(500).json({ message: 'Error retrieving page HTML.' }); return; } @@ -30,49 +31,47 @@ function main() { res.status(200).json(appPageData); return; } catch (error) { - if (error.type == "NO_GAME_ELEMENTS") { + if (error.type == 'NO_GAME_ELEMENTS') { res.status(400).json({ message: error.message }); return; } _logger.error(error); - res.status(500).json({ message: "Error scraping page data." }); + res.status(500).json({ message: 'Error scraping page data.' }); return; } }); - _app.post("/api/search-scrape", async (req, res) => { + _app.post('/api/steam/search-scrape', async (req, res) => { let searchUrl = req.body.url; let searchPageHtml; try { searchPageHtml = await _httpClient.get(searchUrl); } catch (error) { _logger.error(error); - res.status(500).json({ message: "Error retrieving page HTML." }); + res.status(500).json({ message: 'Error retrieving page HTML.' }); return; } try { - let searchPageData = _steamScraper.getSearchPageData( - searchPageHtml - ); + let searchPageData = _steamScraper.getSearchPageData(searchPageHtml); res.status(200).json(searchPageData); return; } catch (error) { _logger.error(error); - res.status(500).json({ message: "Error scraping page data." }); + res.status(500).json({ message: 'Error scraping page data.' }); return; } }); - _app.post("/api/search-app-scrape", async (req, res) => { + _app.post('/api/steam/search-app-scrape', async (req, res) => { let appUrl = req.body.url; let appPageHtml; try { appPageHtml = await _httpClient.get(appUrl); } catch (error) { _logger.error(error); - res.status(500).json({ message: "Error retrieving page HTML." }); + res.status(500).json({ message: 'Error retrieving page HTML.' }); return; } @@ -81,13 +80,37 @@ function main() { res.status(200).json(appPageData); return; } catch (error) { - if (error.type == "NO_GAME_ELEMENTS") { + if (error.type == 'NO_GAME_ELEMENTS') { res.status(400).json({ message: error.message }); return; } _logger.error(error); - res.status(500).json({ message: "Error scraping page data." }); + res.status(500).json({ message: 'Error scraping page data.' }); + return; + } + }); + + _app.post('/api/oculus/experience-scrape', async (req, res) => { + let experienceUrl = req.body.url; + + let experiencePageHtml; + try { + experiencePageHtml = await _httpClient.get(experienceUrl); + } catch (error) { + _logger.error(error); + res.status(500).json({ message: 'Error retrieving page HTML.' }); + return; + } + + try { + let experiencePageData = _oculusScraper.getExperiencePageData(experiencePageHtml); + experiencePageData.link = experienceUrl; + res.status(200).json(experiencePageData); + return; + } catch (error) { + _logger.error(error); + res.status(500).json({ message: 'Error scraping page data.' }); return; } }); diff --git a/public/scripts/index.js b/public/scripts/index.js index 3f0e212..172d41a 100644 --- a/public/scripts/index.js +++ b/public/scripts/index.js @@ -3,67 +3,61 @@ const STEAM_SEARCH_URL_REGEX = /^https:\/\/store.steampowered.com\/search\/\S*/; const PRICE_NUMBER_REGEX = /\$(\d+\.\d{2})/; const PERCENT_NUMBER_REGEX = /(\d+)%/; -const NEW_LINE = " "; +const NEW_LINE = ' '; const MAX_PAGES = 100; const MAX_RETRIES = 10; -const BUNDLE_PREFIX = "**Bundle** - "; +const BUNDLE_PREFIX = '**Bundle** - '; const HEADSET_ALIASES = { - "Valve Index": { - shortName: "Index", - abbreviation: "I" + 'Valve Index': { + shortName: 'Index', + abbreviation: 'I', }, - "HTC Vive": { - shortName: "Vive", - abbreviation: "V" + 'HTC Vive': { + shortName: 'Vive', + abbreviation: 'V', }, - "Oculus Rift": { - shortName: "Rift", - abbreviation: "R" + 'Oculus Rift': { + shortName: 'Rift', + abbreviation: 'R', }, - "Oculus Rift DK2": { - shortName: "Rift DK2", - abbreviation: "DK2" + 'Oculus Rift DK2': { + shortName: 'Rift DK2', + abbreviation: 'DK2', + }, + 'Windows Mixed Reality': { + shortName: 'WMR', + abbreviation: 'W', }, - "Windows Mixed Reality": { - shortName: "WMR", - abbreviation: "W" - } }; // Steam App Titler -let steamAppBtn = document.getElementById("steam-app-btn"); -let steamAppUrlInput = document.getElementById("steam-app-url-input"); -let steamAppInfoSpan = document.getElementById("steam-app-info-span"); -let steamAppResultsDiv = document.getElementById("steam-app-results"); -let steamAppResultLink = document.getElementById("steam-app-result-link"); -let steamAppRowTextArea = document.getElementById("steam-app-row-textarea"); +let steamAppBtn = document.getElementById('steam-app-btn'); +let steamAppUrlInput = document.getElementById('steam-app-url-input'); +let steamAppInfoSpan = document.getElementById('steam-app-info-span'); +let steamAppResultsDiv = document.getElementById('steam-app-results'); +let steamAppResultLink = document.getElementById('steam-app-result-link'); +let steamAppRowTextArea = document.getElementById('steam-app-row-textarea'); // Steam Search Tabler -let steamSearchBtn = document.getElementById("steam-search-btn"); -let steamSearchUrlInput = document.getElementById("steam-search-url-input"); -let steamSearchAllPagesInput = document.getElementById( - "steam-search-all-pages-input" -); -let steamSearchInfoSpan = document.getElementById("steam-search-info-span"); -let steamSearchResultsDiv = document.getElementById("steam-search-results"); -let steamSearchResultTextArea = document.getElementById( - "steam-search-result-textarea" -); -let steamSearchDownloadLink = document.getElementById( - "steam-search-download-link" -); +let steamSearchBtn = document.getElementById('steam-search-btn'); +let steamSearchUrlInput = document.getElementById('steam-search-url-input'); +let steamSearchAllPagesInput = document.getElementById('steam-search-all-pages-input'); +let steamSearchInfoSpan = document.getElementById('steam-search-info-span'); +let steamSearchResultsDiv = document.getElementById('steam-search-results'); +let steamSearchResultTextArea = document.getElementById('steam-search-result-textarea'); +let steamSearchDownloadLink = document.getElementById('steam-search-download-link'); // Register events -steamAppUrlInput.addEventListener("keyup", event => { +steamAppUrlInput.addEventListener('keyup', event => { if (event.keyCode === 13) { event.preventDefault(); steamAppBtn.click(); } }); -steamSearchUrlInput.addEventListener("keyup", event => { +steamSearchUrlInput.addEventListener('keyup', event => { if (event.keyCode === 13) { event.preventDefault(); steamSearchBtn.click(); @@ -73,26 +67,23 @@ steamSearchUrlInput.addEventListener("keyup", event => { async function retrieveSteamAppTitle() { steamAppBtn.disabled = true; hideElement(steamAppResultsDiv); - setUnhideElement(steamAppInfoSpan, "Retrieving..."); + setUnhideElement(steamAppInfoSpan, 'Retrieving...'); let steamAppUrl = steamAppUrlInput.value.trim(); if (!steamAppUrl || !STEAM_APP_URL_REGEX.test(steamAppUrl)) { steamAppBtn.disabled = false; - setUnhideElement( - steamAppInfoSpan, - "No results. Please input a valid Steam App URL." - ); + setUnhideElement(steamAppInfoSpan, 'No results. Please input a valid Steam App URL.'); return; } let content = { - url: steamAppUrl + url: steamAppUrl, }; try { - let appData = await post("./api/app-scrape", content); + let appData = await post('./api/steam/app-scrape', content); - let text = ""; + let text = ''; if (appData.headsets.length > 0) { let platforms = getPlatformText(appData.headsets); text += `[${platforms}] `; @@ -115,7 +106,7 @@ async function retrieveSteamAppTitle() { } catch (error) { console.error(error); hideElement(steamAppResultsDiv); - setUnhideElement(steamAppInfoSpan, "No results."); + setUnhideElement(steamAppInfoSpan, 'No results.'); } steamAppBtn.disabled = false; @@ -124,15 +115,12 @@ async function retrieveSteamAppTitle() { async function retrieveSteamSearchTable() { steamSearchBtn.disabled = true; hideElement(steamSearchResultsDiv); - setUnhideElement(steamSearchInfoSpan, "Retrieving..."); + setUnhideElement(steamSearchInfoSpan, 'Retrieving...'); let steamSearchUrl = steamSearchUrlInput.value.trim(); if (!steamSearchUrl || !STEAM_SEARCH_URL_REGEX.test(steamSearchUrl)) { steamSearchBtn.disabled = false; - setUnhideElement( - steamSearchInfoSpan, - "No results. Please input a valid Steam Search URL." - ); + setUnhideElement(steamSearchInfoSpan, 'No results. Please input a valid Steam Search URL.'); return; } @@ -142,28 +130,22 @@ async function retrieveSteamSearchTable() { let searchData = []; if (searchAllPages) { for (let i = 1; i <= MAX_PAGES; i++) { - setUnhideElement( - steamSearchInfoSpan, - `Retrieving page ${i}...` - ); - let searchPageData = await retrieveSearchPageData( - steamSearchUrl, - i - ); + setUnhideElement(steamSearchInfoSpan, `Retrieving page ${i}...`); + let searchPageData = await retrieveSearchPageData(steamSearchUrl, i); if (searchPageData.length < 1) { break; } searchData.push(...searchPageData); } } else { - setUnhideElement(steamSearchInfoSpan, "Retrieving page..."); + setUnhideElement(steamSearchInfoSpan, 'Retrieving page...'); let searchPageData = await retrieveSearchPageData(steamSearchUrl); searchData.push(...searchPageData); } if (!searchData || searchData.length < 1) { steamSearchBtn.disabled = false; - setUnhideElement(steamSearchInfoSpan, "No results."); + setUnhideElement(steamSearchInfoSpan, 'No results.'); return; } @@ -173,22 +155,22 @@ async function retrieveSteamSearchTable() { steamSearchInfoSpan, `Retrieving result ${itemNumber} of ${searchData.length}...` ); - if (app.type == "APP") { + if (app.type == 'APP') { let content = { - url: app.link + url: app.link, }; - let appData = await post("./api/search-app-scrape", content); + let appData = await post('./api/steam/search-app-scrape', content); app.headsets = appData.headsets || []; - app.countdown = appData.countdown || { text: "", time: 0 }; - app.vrSupport = appData.vrSupport || ""; + app.countdown = appData.countdown || { text: '', time: 0 }; + app.vrSupport = appData.vrSupport || ''; } else { app.headsets = []; app.countdown = { - text: "", - time: 0 + text: '', + time: 0, }; - app.vrSupport = ""; + app.vrSupport = ''; } } @@ -199,10 +181,10 @@ async function retrieveSteamSearchTable() { let text = createMarkdownTable(formattedSearchData); steamSearchResultTextArea.innerHTML = text; - let csvString = "\ufeff" + json2csv.parse(formattedSearchData); + let csvString = '\ufeff' + json2csv.parse(formattedSearchData); let csvData = new Blob([csvString], { - encoding: "UTF-8", - type: "text/csv;charset=UTF-8" + encoding: 'UTF-8', + type: 'text/csv;charset=UTF-8', }); let csvUrl = URL.createObjectURL(csvData); @@ -213,7 +195,7 @@ async function retrieveSteamSearchTable() { } catch (error) { console.error(error); hideElement(steamSearchResultsDiv); - setUnhideElement(steamSearchInfoSpan, "No results."); + setUnhideElement(steamSearchInfoSpan, 'No results.'); } steamSearchBtn.disabled = false; @@ -228,50 +210,45 @@ function getFormattedTime() { let h = today.getHours(); let mi = today.getMinutes(); let s = today.getSeconds(); - return y + "-" + m + "-" + d + "-" + h + "-" + mi + "-" + s; + return y + '-' + m + '-' + d + '-' + h + '-' + mi + '-' + s; } function formatAppData(app) { let formattedData = { - type: "", - vrSupport: "", - platform: "", - platformAbbreviated: "", - title: "", - titleLink: "", - link: "", - price: "", - originalPrice: "", - percentOff: "", - countdownText: "", + type: '', + vrSupport: '', + platform: '', + platformAbbreviated: '', + title: '', + titleLink: '', + link: '', + price: '', + originalPrice: '', + percentOff: '', + countdownText: '', countdownTime: 0, - reviews: "", - reviewsCount: "" + reviews: '', + reviewsCount: '', }; formattedData.type = app.type; formattedData.vrSupport = app.vrSupport; - formattedData.platform = app.headsets.join(", "); + formattedData.platform = app.headsets.join(', '); formattedData.platformAbbreviated = app.headsets .map(platform => getHeadsetAbbreviation(platform)) - .join("/"); + .join('/'); formattedData.title = app.title; - let titlePrefix = app.type == "BUNDLE" ? BUNDLE_PREFIX : ""; - formattedData.titleLink = `${titlePrefix}[${escapePipes(app.title)}](${ - app.link - })`; + let titlePrefix = app.type == 'BUNDLE' ? BUNDLE_PREFIX : ''; + formattedData.titleLink = `${titlePrefix}[${escapePipes(app.title)}](${app.link})`; formattedData.link = app.link; formattedData.price = extractNumberFromPrice(app.price) || app.price; - formattedData.originalPrice = - extractNumberFromPrice(app.originalPrice) || app.price; - formattedData.percentOff = - extractNumberFromPercent(app.percentOff) || app.percentOff; + formattedData.originalPrice = extractNumberFromPrice(app.originalPrice) || app.price; + formattedData.percentOff = extractNumberFromPercent(app.percentOff) || app.percentOff; formattedData.countdownText = app.countdown.text; formattedData.countdownTime = app.countdown.time; - formattedData.reviews = - extractNumberFromPercent(app.reviewsPercent) || app.reviewsPercent; + formattedData.reviews = extractNumberFromPercent(app.reviewsPercent) || app.reviewsPercent; formattedData.reviewsCount = app.reviewsCount; return formattedData; @@ -279,18 +256,17 @@ function formatAppData(app) { async function retrieveSearchPageData(steamSearchUrl, pageNumber) { let content = { - url: `${steamSearchUrl}` + url: `${steamSearchUrl}`, }; if (pageNumber) { content.url += `&page=${pageNumber}`; } - return await post("./api/search-scrape", content); + return await post('./api/steam/search-scrape', content); } function createMarkdownTable(formattedSearchData) { - let header = - "| Platform | Title | Price (USD) | Discount (%) | Rating (%) | Review Count |"; - let divider = "| :- | :- | -: | -: | -: | -: |"; + let header = '| Platform | Title | Price (USD) | Discount (%) | Rating (%) | Review Count |'; + let divider = '| :- | :- | -: | -: | -: | -: |'; let result = header + NEW_LINE + divider + NEW_LINE; for (let app of formattedSearchData) { @@ -308,12 +284,12 @@ async function post(url, content) { let response; for (let i = 0; i < MAX_RETRIES; i++) { response = await fetch(url, { - method: "POST", + method: 'POST', headers: { - Accept: "application/json", - "Content-Type": "application/json" + Accept: 'application/json', + 'Content-Type': 'application/json', }, - body: JSON.stringify(content) + body: JSON.stringify(content), }); if (!shouldRetry(response.status)) { break; @@ -324,14 +300,11 @@ async function post(url, content) { } function shouldRetry(statusCode) { - return !( - (statusCode >= 200 && statusCode <= 299) || - (statusCode >= 400 && statusCode <= 499) - ); + return !((statusCode >= 200 && statusCode <= 299) || (statusCode >= 400 && statusCode <= 499)); } function escapePipes(input) { - return input.replace(/\|/g, "‖"); + return input.replace(/\|/g, '‖'); } function extractNumberFromPrice(input) { @@ -350,14 +323,12 @@ function extractNumberFromPercent(input) { function getPlatformText(platforms) { if (platforms.length == 1) { - return getHeadsetshortName(platforms[0]); + return getHeadsetShortName(platforms[0]); } - return platforms - .map(platform => getHeadsetAbbreviation(platform)) - .join("/"); + return platforms.map(platform => getHeadsetAbbreviation(platform)).join('/'); } -function getHeadsetshortName(headsetName) { +function getHeadsetShortName(headsetName) { let headsetAlias = HEADSET_ALIASES[headsetName]; if (headsetAlias) { return headsetAlias.shortName; @@ -376,14 +347,14 @@ function getHeadsetAbbreviation(headsetName) { } function hideElement(element) { - element.classList.add("hidden"); + element.classList.add('hidden'); } function unhideElement(element) { - element.classList.remove("hidden"); + element.classList.remove('hidden'); } function setUnhideElement(element, innerHtml) { element.innerHTML = innerHtml; - element.classList.remove("hidden"); + element.classList.remove('hidden'); } diff --git a/services/http-client.js b/services/http-client.js index 7e9dca3..8cf317a 100644 --- a/services/http-client.js +++ b/services/http-client.js @@ -1,9 +1,9 @@ -const _rp = require("request-promise"); +const _rp = require('request-promise'); async function get(url) { return await _rp({ url }); } module.exports = { - get + get, }; diff --git a/services/logger.js b/services/logger.js index 0a5767b..2eb787a 100644 --- a/services/logger.js +++ b/services/logger.js @@ -1,18 +1,18 @@ function info(message) { console.log({ timestamp: Date.now(), - message + message, }); } function error(error) { console.log({ timestamp: Date.now(), - error: error.stack + error: error.stack, }); } module.exports = { info, - error + error, }; diff --git a/services/oculus-scraper.js b/services/oculus-scraper.js new file mode 100644 index 0000000..09e8724 --- /dev/null +++ b/services/oculus-scraper.js @@ -0,0 +1,21 @@ +const _cheerio = require('cheerio'); + +function getExperiencePageData(experiencePageHtml) { + let $ = _cheerio.load(experiencePageHtml, { xmlMode: false }); + + let data = $('script[type="application/ld+json"]').html(); + let experienceData = JSON.parse(data); + + return { + title: experienceData.title, + price: '', + originalPrice: '', + percentOff: '', + headsets: ['Quest', 'Rift', 'Go', 'Gear VR'], + link: '', + }; +} + +module.exports = { + getExperiencePageData, +}; diff --git a/services/steam-scraper.js b/services/steam-scraper.js index 751a429..f75633f 100644 --- a/services/steam-scraper.js +++ b/services/steam-scraper.js @@ -1,15 +1,12 @@ -const _cheerio = require("cheerio"); -const _regexUtils = require("../utils/regex-utils"); -const _stringUtils = require("../utils/string-utils"); -const { CustomException } = require("../models/exceptions"); +const _cheerio = require('cheerio'); +const _regexUtils = require('../utils/regex-utils'); +const _stringUtils = require('../utils/string-utils'); +const { CustomException } = require('../models/exceptions'); function getAppPageData(appPageHtml) { let firstGame = getMainGameElement(appPageHtml); if (!firstGame) { - throw new CustomException( - "NO_GAME_ELEMENTS", - "Could not find any game elements." - ); + throw new CustomException('NO_GAME_ELEMENTS', 'Could not find any game elements.'); } let title = getTitle(appPageHtml); @@ -32,9 +29,7 @@ function getAppPageData(appPageHtml) { function getSearchPageData(searchPageHtml) { let $ = _cheerio.load(searchPageHtml); - let searchResults = Array.from( - $("#search_resultsRows > a.search_result_row") - ); + let searchResults = Array.from($('#search_resultsRows > a.search_result_row')); let searchPageData = []; @@ -49,10 +44,7 @@ function getSearchPageData(searchPageHtml) { function getSearchAppPageData(appPageHtml) { let firstGame = getMainGameElement(appPageHtml); if (!firstGame) { - throw new CustomException( - "NO_GAME_ELEMENTS", - "Could not find any game elements." - ); + throw new CustomException('NO_GAME_ELEMENTS', 'Could not find any game elements.'); } let countdown = getCountdownFromGameElement(firstGame); @@ -70,9 +62,7 @@ function getMainGameElement(appPageHtml) { let $ = _cheerio.load(appPageHtml); let gameElements = Array.from( - $( - "#game_area_purchase .game_area_purchase_game:not(.demo_above_purchase)" - ) + $('#game_area_purchase .game_area_purchase_game:not(.demo_above_purchase)') ); if (gameElements.length < 1) { return; @@ -84,11 +74,9 @@ function getMainGameElement(appPageHtml) { function getTitle(appPageHtml) { let $ = _cheerio.load(appPageHtml); - let title = ""; + let title = ''; - let gameDetailsElement = $( - '.game_details .details_block:contains("Title:")' - ).first(); + let gameDetailsElement = $('.game_details .details_block:contains("Title:")').first(); if (gameDetailsElement) { let gameDetailsContent = gameDetailsElement.html().trim(); @@ -101,17 +89,13 @@ function getTitle(appPageHtml) { function getHeadsets(appPageHtml) { let $ = _cheerio.load(appPageHtml); - let headsetTitleElement = $( - '.details_block.vrsupport > div:contains("Headsets")' - ).parent(); - let headsetElements = Array.from( - headsetTitleElement.nextUntil(".details_block") - ); + let headsetTitleElement = $('.details_block.vrsupport > div:contains("Headsets")').parent(); + let headsetElements = Array.from(headsetTitleElement.nextUntil('.details_block')); let headsets = []; for (let headsetElement of headsetElements) { - let headsetName = $(".name", headsetElement).text().trim(); + let headsetName = $('.name', headsetElement).text().trim(); if (headsetName) { headsets.push(headsetName); } @@ -124,15 +108,13 @@ function getReviews(appPageHtml) { let $ = _cheerio.load(appPageHtml); let reviewData = { - reviewsPercent: "", - reviewsCount: "", + reviewsPercent: '', + reviewsCount: '', }; - let reviewsTooltip = $( - "div.user_reviews_summary_bar span.game_review_summary" - ) + let reviewsTooltip = $('div.user_reviews_summary_bar span.game_review_summary') .first() - .data("tooltip-html"); + .data('tooltip-html'); if (reviewsTooltip) { reviewsTooltip = reviewsTooltip.trim(); @@ -146,17 +128,17 @@ function getGameDataFromSearchResult(searchResult) { let $ = _cheerio.load(searchResult); let gameData = { - link: "", - title: "", - type: "UNKNOWN", - price: "", - originalPrice: "", - percentOff: "", - reviewsPercent: "", - reviewsCount: "", + link: '', + title: '', + type: 'UNKNOWN', + price: '', + originalPrice: '', + percentOff: '', + reviewsPercent: '', + reviewsCount: '', }; - let title = $("div.search_name > span.title").text().trim(); + let title = $('div.search_name > span.title').text().trim(); if (title) { gameData.title = title; } @@ -166,46 +148,35 @@ function getGameDataFromSearchResult(searchResult) { gameData.link = link; } - if (gameData.link.includes("/app/")) { - gameData.type = "APP"; - } else if (gameData.link.includes("/bundle/")) { - gameData.type = "BUNDLE"; + if (gameData.link.includes('/app/')) { + gameData.type = 'APP'; + } else if (gameData.link.includes('/bundle/')) { + gameData.type = 'BUNDLE'; } - let price = $("div.search_price") - .clone() - .children() - .remove() - .end() - .text() - .trim(); + let price = $('div.search_price').clone().children().remove().end().text().trim(); if (price) { gameData.price = price; } - let originalPrice = $("div.search_price > span > strike").text().trim(); + let originalPrice = $('div.search_price > span > strike').text().trim(); if (originalPrice) { gameData.originalPrice = originalPrice; } - let percentOff = _regexUtils.extractPercent( - $("div.search_discount > span").text().trim() - ); + let percentOff = _regexUtils.extractPercent($('div.search_discount > span').text().trim()); if (percentOff) { gameData.percentOff = percentOff; } - if (gameData.type == "APP") { - let reviewsTooltip = $( - "div.search_reviewscore > span.search_review_summary" - ).data("tooltip-html"); + if (gameData.type == 'APP') { + let reviewsTooltip = $('div.search_reviewscore > span.search_review_summary').data( + 'tooltip-html' + ); if (reviewsTooltip) { reviewsTooltip = reviewsTooltip.trim(); - let reviewData = extractReviewDataFromTooltip( - reviewsTooltip, - gameData - ); + let reviewData = extractReviewDataFromTooltip(reviewsTooltip, gameData); gameData.reviewsPercent = reviewData.reviewsPercent; gameData.reviewsCount = reviewData.reviewsCount; } @@ -216,8 +187,8 @@ function getGameDataFromSearchResult(searchResult) { function extractReviewDataFromTooltip(reviewsTooltip) { let reviewData = { - reviewsPercent: "", - reviewsCount: "", + reviewsPercent: '', + reviewsCount: '', }; let reviewsPercent = _regexUtils.extractPercent(reviewsTooltip); @@ -236,26 +207,24 @@ function getGameDataFromGameElement(gameElement) { let $ = _cheerio.load(gameElement); let gameData = { - price: "", - originalPrice: "", - percentOff: "", + price: '', + originalPrice: '', + percentOff: '', }; - let originalPrice = $(".discount_original_price").text().trim(); + let originalPrice = $('.discount_original_price').text().trim(); if (originalPrice) { gameData.originalPrice = originalPrice; } - let percentOff = _regexUtils.extractPercent( - $(".discount_pct").text().trim() - ); + let percentOff = _regexUtils.extractPercent($('.discount_pct').text().trim()); if (percentOff) { gameData.percentOff = percentOff; } let price = gameData.originalPrice - ? $(".discount_final_price").text().trim() - : $(".game_purchase_price").text().trim(); + ? $('.discount_final_price').text().trim() + : $('.game_purchase_price').text().trim(); if (price) { gameData.price = price; } @@ -267,23 +236,20 @@ function getCountdownFromGameElement(gameElement) { let $ = _cheerio.load(gameElement); let countdownData = { - text: "", + text: '', time: 0, }; try { - let text = $(".game_purchase_discount_countdown").text().trim(); + let text = $('.game_purchase_discount_countdown').text().trim(); if (text) { countdownData.text = text; } } catch {} try { - let countdownScript = $(".game_area_purchase_game > script")[0] - .children[0].data; - let countdownTimeText = _regexUtils.extractDiscountCountdown( - countdownScript - ); + let countdownScript = $('.game_area_purchase_game > script')[0].children[0].data; + let countdownTimeText = _regexUtils.extractDiscountCountdown(countdownScript); let time = parseInt(countdownTimeText); if (time) { countdownData.time = time; @@ -296,12 +262,12 @@ function getCountdownFromGameElement(gameElement) { function getVrSupportFromGameElement(gameElement) { let $ = _cheerio.load(gameElement); - let vrSupport = "NONE"; + let vrSupport = 'NONE'; - if ($(".vr_required").length > 0) { - vrSupport = "REQUIRED"; - } else if ($(".vr_supported").length > 0) { - vrSupport = "SUPPORTED"; + if ($('.vr_required').length > 0) { + vrSupport = 'REQUIRED'; + } else if ($('.vr_supported').length > 0) { + vrSupport = 'SUPPORTED'; } return vrSupport;