1
0
Fork 0
forked from OpenNeo/impress
impress/src/server/neopets-assets.js
Matchu 4cd5cf5800 Fix handling of assets with https://images.neopets.com/temp SWF URLs
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!
2023-11-11 13:28:47 -08:00

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 };