fix(catalog): resolve classname candidates using public_name
This commit is contained in:
1 parent
8c47c3c158
commit
ca6aa97eb2
5 files changed
+187
-93
No files matched your search
@@ -193,13 +193,15 @@ describe.skipIf(!runLive)("catalog audit live (read-only)", () => {
|
|||||||
if (types.NO_ASSET_KINDS.has(kind)) continue;
|
if (types.NO_ASSET_KINDS.has(kind)) continue;
|
||||||
if (
|
if (
|
||||||
!types
|
!types
|
||||||
.assetNameCandidates(r.item_name)
|
.assetNameCandidates(r.item_name, r.public_name)
|
||||||
.nitro.some((n) => nitroSet.has(n))
|
.nitro.some((n) => nitroSet.has(n))
|
||||||
) {
|
) {
|
||||||
missingNitro++;
|
missingNitro++;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
!types.assetNameCandidates(r.item_name).icon.some((n) => iconSet.has(n))
|
!types
|
||||||
|
.assetNameCandidates(r.item_name, r.public_name)
|
||||||
|
.icon.some((n) => iconSet.has(n))
|
||||||
) {
|
) {
|
||||||
missingIcon++;
|
missingIcon++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -320,9 +320,10 @@ export async function runCatalogAudit(
|
|||||||
itemId: item.id,
|
itemId: item.id,
|
||||||
message: `"${item.item_name}" (ID ${item.id}) has no catalog_items entry — not purchasable`,
|
message: `"${item.item_name}" (ID ${item.id}) has no catalog_items entry — not purchasable`,
|
||||||
});
|
});
|
||||||
const hasNitro = assetNameCandidates(item.item_name).nitro.some((n) =>
|
const hasNitro = assetNameCandidates(
|
||||||
nitroSet.has(n),
|
item.item_name,
|
||||||
);
|
item.public_name,
|
||||||
|
).nitro.some((n) => nitroSet.has(n));
|
||||||
// Pets ship their assets through the pet pipeline, not as furni
|
// Pets ship their assets through the pet pipeline, not as furni
|
||||||
// .nitro bundles, so they can get a catalog entry regardless.
|
// .nitro bundles, so they can get a catalog entry regardless.
|
||||||
if (kind === "pet" || hasNitro) {
|
if (kind === "pet" || hasNitro) {
|
||||||
@@ -398,9 +399,10 @@ export async function runCatalogAudit(
|
|||||||
// Badges, pets, effects, bots and sticky notes never ship a furni
|
// Badges, pets, effects, bots and sticky notes never ship a furni
|
||||||
// .nitro bundle — skip the asset check for them.
|
// .nitro bundle — skip the asset check for them.
|
||||||
if (NO_ASSET_KINDS.has(kindOf(item.item_name))) continue;
|
if (NO_ASSET_KINDS.has(kindOf(item.item_name))) continue;
|
||||||
const hasNitro = assetNameCandidates(item.item_name).nitro.some((n) =>
|
const hasNitro = assetNameCandidates(
|
||||||
nitroSet.has(n),
|
item.item_name,
|
||||||
);
|
item.public_name,
|
||||||
|
).nitro.some((n) => nitroSet.has(n));
|
||||||
if (!hasNitro) {
|
if (!hasNitro) {
|
||||||
missingNitroClassnames.push(item.item_name);
|
missingNitroClassnames.push(item.item_name);
|
||||||
issues.push({
|
issues.push({
|
||||||
@@ -429,9 +431,10 @@ export async function runCatalogAudit(
|
|||||||
// Badges use album1584 .gif icons; pets, effects, bots and sticky notes
|
// Badges use album1584 .gif icons; pets, effects, bots and sticky notes
|
||||||
// never ship a furni icon file — skip the asset check for them.
|
// never ship a furni icon file — skip the asset check for them.
|
||||||
if (NO_ASSET_KINDS.has(kindOf(item.item_name))) continue;
|
if (NO_ASSET_KINDS.has(kindOf(item.item_name))) continue;
|
||||||
const hasIcon = assetNameCandidates(item.item_name).icon.some((n) =>
|
const hasIcon = assetNameCandidates(
|
||||||
iconSet.has(n),
|
item.item_name,
|
||||||
);
|
item.public_name,
|
||||||
|
).icon.some((n) => iconSet.has(n));
|
||||||
if (!hasIcon) {
|
if (!hasIcon) {
|
||||||
missingIconClassnames.push(item.item_name);
|
missingIconClassnames.push(item.item_name);
|
||||||
issues.push({
|
issues.push({
|
||||||
@@ -493,9 +496,11 @@ export async function runCatalogAudit(
|
|||||||
// left over cannot be restored from any source → legacy/broken.
|
// left over cannot be restored from any source → legacy/broken.
|
||||||
const stillMissing: string[] = [];
|
const stillMissing: string[] = [];
|
||||||
for (const classname of missingIconClassnames) {
|
for (const classname of missingIconClassnames) {
|
||||||
const hasIcon = assetNameCandidates(classname).icon.some((n) =>
|
const item = itemByName.get(classname);
|
||||||
iconSet.has(n),
|
const hasIcon = assetNameCandidates(
|
||||||
);
|
classname,
|
||||||
|
item?.public_name,
|
||||||
|
).icon.some((n) => iconSet.has(n));
|
||||||
if (!hasIcon) {
|
if (!hasIcon) {
|
||||||
stillMissing.push(classname);
|
stillMissing.push(classname);
|
||||||
}
|
}
|
||||||
@@ -566,9 +571,11 @@ export async function runCatalogAudit(
|
|||||||
// left over cannot be restored from any source → legacy/broken.
|
// left over cannot be restored from any source → legacy/broken.
|
||||||
const stillMissing: string[] = [];
|
const stillMissing: string[] = [];
|
||||||
for (const classname of missingNitroClassnames) {
|
for (const classname of missingNitroClassnames) {
|
||||||
const hasNitro = assetNameCandidates(classname).nitro.some((n) =>
|
const item = itemByName.get(classname);
|
||||||
nitroSet.has(n),
|
const hasNitro = assetNameCandidates(
|
||||||
);
|
classname,
|
||||||
|
item?.public_name,
|
||||||
|
).nitro.some((n) => nitroSet.has(n));
|
||||||
if (!hasNitro) {
|
if (!hasNitro) {
|
||||||
stillMissing.push(classname);
|
stillMissing.push(classname);
|
||||||
}
|
}
|
||||||
@@ -714,9 +721,10 @@ export async function runCatalogAudit(
|
|||||||
}
|
}
|
||||||
if (NO_CATALOG_KINDS.has(kind)) continue;
|
if (NO_CATALOG_KINDS.has(kind)) continue;
|
||||||
if (postCatalogIds.has(item.id)) continue;
|
if (postCatalogIds.has(item.id)) continue;
|
||||||
const hasNitro = assetNameCandidates(item.item_name).nitro.some((n) =>
|
const hasNitro = assetNameCandidates(
|
||||||
nitroSet.has(n),
|
item.item_name,
|
||||||
);
|
item.public_name,
|
||||||
|
).nitro.some((n) => nitroSet.has(n));
|
||||||
if (kind === "pet" || hasNitro) {
|
if (kind === "pet" || hasNitro) {
|
||||||
missingCatalogEntries.push({
|
missingCatalogEntries.push({
|
||||||
classname: item.item_name,
|
classname: item.item_name,
|
||||||
|
|||||||
@@ -77,8 +77,15 @@ export const NO_CATALOG_KINDS: ReadonlySet<CatalogItemKind> = new Set([
|
|||||||
* files. Returns `.nitro` and icon candidates (most specific first):
|
* files. Returns `.nitro` and icon candidates (most specific first):
|
||||||
* the exact classname, the star-variant base, the star→underscore name and the
|
* the exact classname, the star-variant base, the star→underscore name and the
|
||||||
* dot→underscore name (`post.it` → `post_it.nitro`).
|
* dot→underscore name (`post.it` → `post_it.nitro`).
|
||||||
|
*
|
||||||
|
* When `publicName` is provided it is treated as an alternative classname (many
|
||||||
|
* hotels store the real classname in `items_base.public_name` while `item_name`
|
||||||
|
* holds a display name). Candidates from both names are merged and deduplicated.
|
||||||
*/
|
*/
|
||||||
export function assetNameCandidates(classname: string): {
|
export function assetNameCandidates(
|
||||||
|
classname: string,
|
||||||
|
publicName?: string,
|
||||||
|
): {
|
||||||
nitro: string[];
|
nitro: string[];
|
||||||
icon: string[];
|
icon: string[];
|
||||||
} {
|
} {
|
||||||
@@ -97,12 +104,24 @@ export function assetNameCandidates(classname: string): {
|
|||||||
const starUnderscore = classname.replace(/\*/g, "_");
|
const starUnderscore = classname.replace(/\*/g, "_");
|
||||||
const dotUnderscore = classname.replace(/\./g, "_");
|
const dotUnderscore = classname.replace(/\./g, "_");
|
||||||
|
|
||||||
|
const bases = [classname, starBase, dotUnderscore, starUnderscore];
|
||||||
|
|
||||||
|
// Also try public_name when it looks like a real classname (no spaces,
|
||||||
|
// not empty, not "0" which some hotels use as a "no value" marker).
|
||||||
|
if (
|
||||||
|
publicName &&
|
||||||
|
publicName !== classname &&
|
||||||
|
!publicName.includes(" ") &&
|
||||||
|
publicName !== "0"
|
||||||
|
) {
|
||||||
|
const pnBase = publicName.split("*")[0];
|
||||||
|
const pnStar = publicName.replace(/\*/g, "_");
|
||||||
|
const pnDot = publicName.replace(/\./g, "_");
|
||||||
|
bases.push(publicName, pnBase, pnDot, pnStar);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
nitro: unique([classname, starBase, dotUnderscore, starUnderscore]).map(
|
nitro: unique(bases).map((n) => `${n}.nitro`),
|
||||||
(n) => `${n}.nitro`,
|
icon: unique(bases).map((n) => `${n}_icon.png`),
|
||||||
),
|
|
||||||
icon: unique([classname, starUnderscore, dotUnderscore, starBase]).map(
|
|
||||||
(n) => `${n}_icon.png`,
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user