Created
August 15, 2023 09:04
-
-
Save tatocaster/59779b8af3ad089abefc53972806c750 to your computer and use it in GitHub Desktop.
get Nintendo EShop games and metacritics score
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { getGamesAmerica, GameUS, EshopError } from 'nintendo-switch-eshop'; | |
import * as fs from 'fs'; | |
import { HTMLElement, parse } from "node-html-parser"; | |
import fetch from 'node-fetch'; | |
const dest = './nintendo-games.json'; | |
const allowedLettersInTitle = /[^a-zA-Z0-9 ]+/g; | |
const PAGE_SIZE = 25 | |
interface NintendoGame { | |
title: string; | |
url : string; | |
nsuid: string; | |
esrb_rating:string; | |
date: string; | |
platform: string; | |
msrp: number; | |
genres: string; | |
meta_score: number; | |
} | |
function saveResponseToFile(response: NintendoGame[]) { | |
fs.writeFile(dest, JSON.stringify(response), (err) => { | |
if (err) { | |
console.error('Error writing JSON to file:', err); | |
} else { | |
console.log('JSON data has been written to the file successfully!'); | |
} | |
}); | |
} | |
async function readJsonFromFile(): Promise<NintendoGame[]> { | |
return new Promise((resolve, reject) => { | |
fs.readFile(dest, "utf8", (err, data) => { | |
if (err) { | |
reject(err); | |
} else { | |
try { | |
const jsonData = JSON.parse(data); | |
resolve(jsonData); | |
} catch (parseError) { | |
reject(parseError); | |
} | |
} | |
}); | |
}); | |
} | |
function getMetaScore(root: HTMLElement): number { | |
const extractMetaScore = (node: any): number => { | |
if (node.nodeType === 1 && node.rawTagName === "span") { | |
for (const attr of node.rawAttrs.split(" ")) { | |
const [key, val] = attr.split("="); | |
if (key === "itemprop" && val === "\"ratingValue\"") { | |
const metaScoreStr = node.rawText; | |
const metaScore = parseInt(metaScoreStr, 10); | |
if (isNaN(metaScore)) { | |
return 0; | |
} | |
return metaScore; | |
} | |
} | |
} | |
for (const child of node.childNodes) { | |
const score = extractMetaScore(child); | |
if (score !== 0) { | |
return score; | |
} | |
} | |
return 0; | |
}; | |
return extractMetaScore(root); | |
} | |
async function fetchAndSaveDataInChunks(batchIndex: number, batchData: NintendoGame[]): Promise<void> { | |
for (const game of batchData) { | |
const response = await fetch(`https://www.metacritic.com/game/switch/${game.title.toLowerCase().replace(/ /g, "-")}`); | |
if (!response.ok) { | |
continue; | |
} | |
const html = await response.text(); | |
const root = parse(html); | |
game.meta_score = getMetaScore(root); | |
} | |
// Save responses to a file | |
const filename = `responses_batch_${batchIndex}.json`; | |
fs.writeFileSync(filename, JSON.stringify(batchData)); | |
console.log(`Batch ${batchIndex} completed and saved to ${filename}`); | |
} | |
async function fetchMetaCriticScores() { | |
const gameData = await readJsonFromFile(); | |
console.log("JSON data size from file: ", gameData.length); | |
const totalEntries = gameData.length; | |
const totalBatches = Math.ceil(totalEntries / PAGE_SIZE); | |
for (let batchIndex = 158; batchIndex < totalBatches; batchIndex++) { | |
await fetchAndSaveDataInChunks(batchIndex, gameData.slice(batchIndex * PAGE_SIZE, (batchIndex+1) * PAGE_SIZE)); | |
} | |
console.log("All batches completed."); | |
} | |
async function main(isFetchEnabled: boolean){ | |
if(isFetchEnabled){ | |
getGamesAmerica() | |
.then((result: GameUS[]) => { | |
console.log(result.length); | |
const newData : NintendoGame[] = result.map(game => ({ | |
title: game.title.replace(allowedLettersInTitle, ""), | |
url : game.url, | |
nsuid: game.nsuid, | |
esrb_rating: game.esrbRating, | |
date: new Date(game.releaseDateDisplay).toLocaleDateString(), | |
platform: game.platform?.replace("Nintendo ", ''), | |
msrp: game.msrp, | |
genres: `[${game.genres?.map((item) => `'${item}'`).join()}]`, | |
meta_score: 0 | |
})) | |
saveResponseToFile(newData); | |
}) | |
.catch((error: EshopError) => { | |
console.error("Error occurred:", error); | |
}); | |
} else{ | |
fetchMetaCriticScores() | |
} | |
} | |
const programArguments = process.argv.slice(2) | |
const isFetchEnabled = programArguments.length > 0 && programArguments[0].toLowerCase() === "true"; | |
main(isFetchEnabled) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment