forked from OpenNeo/impress
Weird! Well! This caused two issues. One is that we used to filter down to only assets whose urls end in `.swf`, because I never added support for the sound ones :p The other is that we were using the SWF URL to infer the potential manifest URLs, which we can't do when the SWF URL is a weird placeholder! Thankfully, just yesterday (wow!) we happened to have Classic DTI keep track of `manifest_url` during the modeling process, and we backfilled everything. So the most recent `temp` assets have their manifest! But slightly older ones (not that old tho!!) didn't, so I manually inferred the manifest URL from the asset's `remote_id` field instead (which worked cuz there was no hash component to the manifest URL, unlike some manifests). The item "Flowing Black Cloak" (86668) on the Zafara is the one we were looking at and testing with!
63 lines
1.9 KiB
JavaScript
63 lines
1.9 KiB
JavaScript
import fetch from "node-fetch";
|
|
|
|
async function loadAssetManifest(manifestUrl, swfUrl) {
|
|
const possibleManifestUrls =
|
|
manifestUrl != null
|
|
? [manifestUrl]
|
|
: convertSwfUrlToPossibleManifestUrls(swfUrl);
|
|
|
|
const responses = await Promise.all(
|
|
possibleManifestUrls.map((url) => fetch(url)),
|
|
);
|
|
|
|
// Print errors for any responses with unexpected statuses. We'll do this
|
|
// even if other requests succeeded, or failed with an expected 404.
|
|
for (const res of responses) {
|
|
if (!res.ok && res.status !== 404) {
|
|
console.error(
|
|
`for asset manifest, images.neopets.com returned: ` +
|
|
`${res.status} ${res.statusText}. (${res.url})`,
|
|
);
|
|
}
|
|
}
|
|
|
|
const successfulResponse = responses.find((res) => res.ok);
|
|
if (!successfulResponse) {
|
|
return null;
|
|
}
|
|
|
|
const json = await successfulResponse.json();
|
|
return {
|
|
assets: json["cpmanifest"]["assets"].map((asset) => ({
|
|
format: asset["format"],
|
|
assetData: asset["asset_data"].map((assetDatum) => ({
|
|
path: assetDatum["url"],
|
|
})),
|
|
})),
|
|
};
|
|
}
|
|
|
|
const SWF_URL_PATTERN =
|
|
/^https?:\/\/images\.neopets\.com\/cp\/(bio|items)\/swf\/(.+?)_([a-z0-9]+)\.swf$/;
|
|
|
|
function convertSwfUrlToPossibleManifestUrls(swfUrl) {
|
|
const match = new URL(swfUrl, "https://images.neopets.com")
|
|
.toString()
|
|
.match(SWF_URL_PATTERN);
|
|
if (!match) {
|
|
throw new Error(`unexpected SWF URL format: ${JSON.stringify(swfUrl)}`);
|
|
}
|
|
|
|
const type = match[1];
|
|
const folders = match[2];
|
|
const hash = match[3];
|
|
|
|
// TODO: There are a few potential manifest URLs in play! Long-term, we
|
|
// should get this from modeling data. But these are some good guesses!
|
|
return [
|
|
`https://images.neopets.com/cp/${type}/data/${folders}/manifest.json`,
|
|
`https://images.neopets.com/cp/${type}/data/${folders}_${hash}/manifest.json`,
|
|
];
|
|
}
|
|
|
|
module.exports = { loadAssetManifest };
|