From c74c3b626eb2ad2cfac0b246eaa9b38b951c761f Mon Sep 17 00:00:00 2001 From: Matt Isenhower Date: Sun, 11 Jan 2026 19:09:20 -0800 Subject: [PATCH] Add query hash utility --- utility/getQueryHashes.mjs | 55 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 utility/getQueryHashes.mjs diff --git a/utility/getQueryHashes.mjs b/utility/getQueryHashes.mjs new file mode 100644 index 0000000..93043d1 --- /dev/null +++ b/utility/getQueryHashes.mjs @@ -0,0 +1,55 @@ +// Adapted for JS from: https://github.com/imink-app/SplatNet3/blob/master/Sources/SplatNet3Helper/SN3Helper.swift + +// This utility fetches GraphQL query hashes from the SplatNet 3 web view +// Usage: +// node utility/getQueryHashes.mjs + +import _ from 'lodash'; + +const { fromPairs, isPlainObject, mapValues, sortBy, toPairs } = _; + +const baseUrl = 'https://api.lp1.av5ja.srv.nintendo.net'; +const versionRegex = /=.(?[0-9a-f]{40}).*revision_info_not_set.*=.(?\d+\.\d+\.\d+)-/; +const hashRegex = /params:\{id:"(?[0-9a-f]{32}|[0-9a-f]{64})",metadata:\{\},name:"(?[a-zA-Z0-9_]+)",/g; + +function sortObjectKeys(obj) { + if (Array.isArray(obj)) return obj.map(sortObjectKeys); + if (!isPlainObject(obj)) return obj; + return fromPairs(sortBy(toPairs(mapValues(obj, sortObjectKeys)), 0)); +} + +(async () => { + // Fetch main HTML and find the script path + let html = await (await fetch(baseUrl)).text(); + let scriptMatch = html.match(/]+src="([^"]*static[^"]*)"/); + if (!scriptMatch) { + console.error('Could not find main.js script in HTML'); + return; + } + + // Fetch the JavaScript file + let jsUrl = scriptMatch[1].startsWith('http') ? scriptMatch[1] : baseUrl + scriptMatch[1]; + let js = await (await fetch(jsUrl)).text(); + + // Parse version + let versionMatch = versionRegex.exec(js); + if (!versionMatch?.groups) { + console.error('Could not parse version from JavaScript'); + return; + } + let version = `${versionMatch.groups.version}-${versionMatch.groups.revision.substring(0, 8)}`; + + // Parse GraphQL hashes + let hashMap = {}; + let match; + while ((match = hashRegex.exec(js)) !== null) { + hashMap[match.groups.name] = match.groups.id; + } + + let data = sortObjectKeys({ + graphql: { hash_map: hashMap }, + version, + }); + + console.log(JSON.stringify(data, undefined, 2)); +})();