Stop referencing the {color,species,zone}_translations tables

We're in the process of migrating away from translating these records,
because Neopets hasn't supported non-English languages in many years,
and it'll simplify our code and database lookups.

In Main DTI, we already wrote code to copy these fields onto the main
records and keep them in sync for now; now, once DTI 2020 isn't
referencing them anymore, it should be safe for the main app to drop
the tables altogether.

Note that some Prettier changes got mixed in here and that's fine!

I also wasn't suuuper careful testing these, most of them seem to be
trivially testable by just loading the homepage or doing a few basic
wardrobe actions, and the others are in Discord support log actions
that aren't enabled in development mode, so I'm just like… ehh I'll do
a couple support actions after deploy and see that they don't crash!
This commit is contained in:
Emi Matchu 2024-02-03 08:05:15 -08:00
parent 4e1739cd16
commit dc954d7c3c
13 changed files with 188 additions and 477 deletions

View file

@ -23,7 +23,7 @@ if (
) { ) {
throw new Error( throw new Error(
`must provide DTI_AWS_ACCESS_KEY_ID and DTI_AWS_SECRET_ACCESS_KEY ` + `must provide DTI_AWS_ACCESS_KEY_ID and DTI_AWS_SECRET_ACCESS_KEY ` +
`environment variables` `environment variables`,
); );
} }
@ -87,7 +87,7 @@ async function handle(req, res) {
const { layerId } = req.query; const { layerId } = req.query;
const [layerRows] = await db.execute( const [layerRows] = await db.execute(
`SELECT * FROM swf_assets WHERE id = ?`, `SELECT * FROM swf_assets WHERE id = ?`,
[layerId] [layerId],
); );
const layer = normalizeRow(layerRows[0]); const layer = normalizeRow(layerRows[0]);
if (!layer) { if (!layer) {
@ -105,7 +105,7 @@ async function handle(req, res) {
const [result] = await db.execute( const [result] = await db.execute(
`UPDATE swf_assets SET image_manual = 1, converted_at = ? `UPDATE swf_assets SET image_manual = 1, converted_at = ?
WHERE type = ? AND remote_id = ? LIMIT 1`, WHERE type = ? AND remote_id = ? LIMIT 1`,
[now, assetType, remoteId] [now, assetType, remoteId],
); );
if (result.affectedRows !== 1) { if (result.affectedRows !== 1) {
res res
@ -115,30 +115,22 @@ async function handle(req, res) {
if (process.env["SUPPORT_TOOLS_DISCORD_WEBHOOK_URL"]) { if (process.env["SUPPORT_TOOLS_DISCORD_WEBHOOK_URL"]) {
try { try {
const { const { itemLoader, itemTranslationLoader, zoneLoader } =
itemLoader, buildLoaders(db);
itemTranslationLoader,
zoneTranslationLoader,
} = buildLoaders(db);
// Copied from setLayerBodyId mutation // Copied from setLayerBodyId mutation
const itemId = await db const itemId = await db
.execute( .execute(
`SELECT parent_id FROM parents_swf_assets `SELECT parent_id FROM parents_swf_assets
WHERE swf_asset_id = ? AND parent_type = "Item" LIMIT 1;`, WHERE swf_asset_id = ? AND parent_type = "Item" LIMIT 1;`,
[layerId] [layerId],
) )
.then(([rows]) => normalizeRow(rows[0]).parentId); .then(([rows]) => normalizeRow(rows[0]).parentId);
const [ const [item, itemTranslation, zone, bodyName] = await Promise.all([
item,
itemTranslation,
zoneTranslation,
bodyName,
] = await Promise.all([
itemLoader.load(itemId), itemLoader.load(itemId),
itemTranslationLoader.load(itemId), itemTranslationLoader.load(itemId),
zoneTranslationLoader.load(layer.zoneId), zoneLoader.load(layer.zoneId),
loadBodyName(layer.bodyId, db), loadBodyName(layer.bodyId, db),
]); ]);
@ -153,7 +145,7 @@ async function handle(req, res) {
}, },
fields: [ fields: [
{ {
name: `Layer ${layerId} (${zoneTranslation.label})`, name: `Layer ${layerId} (${zone.label})`,
value: `🎨 Uploaded new PNG for ${bodyName}`, value: `🎨 Uploaded new PNG for ${bodyName}`,
}, },
], ],
@ -173,7 +165,7 @@ async function handle(req, res) {
async function handleWithBeeline(req, res) { async function handleWithBeeline(req, res) {
beeline.withTrace( beeline.withTrace(
{ name: "api/uploadLayerImage", operation_name: "api/uploadLayerImage" }, { name: "api/uploadLayerImage", operation_name: "api/uploadLayerImage" },
() => handle(req, res) () => handle(req, res),
); );
} }

View file

@ -1,5 +1,4 @@
yarn run --silent mysqldump openneo_impress species species_translations colors \ yarn run --silent mysqldump openneo_impress species colors zones \
color_translations zones zone_translations \
> $(dirname $0)/../public-data-constants.sql \ > $(dirname $0)/../public-data-constants.sql \
&& yarn run --silent mysqldump openneo_impress alt_styles items item_translations \ && yarn run --silent mysqldump openneo_impress alt_styles items item_translations \
parents_swf_assets pet_states pet_types swf_assets \ parents_swf_assets pet_states pet_types swf_assets \

View file

@ -1,7 +1,6 @@
yarn run --silent mysqldump --no-data openneo_impress closet_hangers closet_lists \ yarn run --silent mysqldump --no-data openneo_impress closet_hangers closet_lists \
colors color_translations items item_translations modeling_logs \ colors items item_translations modeling_logs parents_swf_assets pet_types \
parents_swf_assets pet_types pet_states species species_translations \ pet_states species swf_assets users zones \
swf_assets users zones zone_translations \
| \ | \
sed 's/ AUTO_INCREMENT=[0-9]*//g' \ sed 's/ AUTO_INCREMENT=[0-9]*//g' \
> $(dirname $0)/../schema-for-impress.sql \ > $(dirname $0)/../schema-for-impress.sql \

File diff suppressed because one or more lines are too long

View file

@ -57,4 +57,4 @@ CREATE TABLE `users` (
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2024-02-01 2:00:53 -- Dump completed on 2024-02-03 7:55:56

View file

@ -79,26 +79,6 @@ CREATE TABLE `colors` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1; ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `color_translations`
--
DROP TABLE IF EXISTS `color_translations`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `color_translations` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`color_id` int(11) DEFAULT NULL,
`locale` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_color_translations_on_color_id` (`color_id`),
KEY `index_color_translations_on_locale` (`locale`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Table structure for table `items` -- Table structure for table `items`
-- --
@ -249,26 +229,6 @@ CREATE TABLE `species` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1; ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `species_translations`
--
DROP TABLE IF EXISTS `species_translations`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `species_translations` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`species_id` int(11) DEFAULT NULL,
`locale` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_species_translations_on_species_id` (`species_id`),
KEY `index_species_translations_on_locale` (`locale`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Table structure for table `swf_assets` -- Table structure for table `swf_assets`
-- --
@ -342,27 +302,6 @@ CREATE TABLE `zones` (
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1; ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `zone_translations`
--
DROP TABLE IF EXISTS `zone_translations`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `zone_translations` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`zone_id` int(11) DEFAULT NULL,
`locale` varchar(255) DEFAULT NULL,
`label` varchar(255) DEFAULT NULL,
`plain_label` varchar(255) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_zone_translations_on_zone_id` (`zone_id`),
KEY `index_zone_translations_on_locale` (`locale`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
@ -373,4 +312,4 @@ CREATE TABLE `zone_translations` (
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2024-02-01 2:00:51 -- Dump completed on 2024-02-03 7:55:53

View file

@ -4,7 +4,6 @@ USE openneo_impress;
GRANT SELECT ON alt_styles TO impress2020; GRANT SELECT ON alt_styles TO impress2020;
GRANT SELECT ON campaigns TO impress2020; GRANT SELECT ON campaigns TO impress2020;
GRANT SELECT ON colors TO impress2020; GRANT SELECT ON colors TO impress2020;
GRANT SELECT ON color_translations TO impress2020;
GRANT SELECT ON donation_features TO impress2020; GRANT SELECT ON donation_features TO impress2020;
GRANT SELECT ON donations TO impress2020; GRANT SELECT ON donations TO impress2020;
GRANT SELECT ON items TO impress2020; GRANT SELECT ON items TO impress2020;
@ -14,10 +13,8 @@ GRANT SELECT ON parents_swf_assets TO impress2020;
GRANT SELECT ON pet_types TO impress2020; GRANT SELECT ON pet_types TO impress2020;
GRANT SELECT ON pet_states TO impress2020; GRANT SELECT ON pet_states TO impress2020;
GRANT SELECT ON species TO impress2020; GRANT SELECT ON species TO impress2020;
GRANT SELECT ON species_translations TO impress2020;
GRANT SELECT ON swf_assets TO impress2020; GRANT SELECT ON swf_assets TO impress2020;
GRANT SELECT ON zones TO impress2020; GRANT SELECT ON zones TO impress2020;
GRANT SELECT ON zone_translations TO impress2020;
-- Public data tables: write. Used in modeling and support tools. -- Public data tables: write. Used in modeling and support tools.
GRANT INSERT, UPDATE ON items TO impress2020; GRANT INSERT, UPDATE ON items TO impress2020;

View file

@ -88,25 +88,6 @@ const buildColorLoader = (db) => {
return colorLoader; return colorLoader;
}; };
const buildColorTranslationLoader = (db) =>
new DataLoader(async (colorIds) => {
const qs = colorIds.map((_) => "?").join(",");
const [rows] = await db.execute(
`SELECT * FROM color_translations
WHERE color_id IN (${qs}) AND locale = "en"`,
colorIds,
);
const entities = rows.map(normalizeRow);
const entitiesByColorId = new Map(entities.map((e) => [e.colorId, e]));
return colorIds.map(
(colorId) =>
entitiesByColorId.get(String(colorId)) ||
new Error(`could not find translation for color ${colorId}`),
);
});
const buildSpeciesLoader = (db) => { const buildSpeciesLoader = (db) => {
const speciesLoader = new DataLoader(async (speciesIds) => { const speciesLoader = new DataLoader(async (speciesIds) => {
const qs = speciesIds.map((_) => "?").join(","); const qs = speciesIds.map((_) => "?").join(",");
@ -139,25 +120,6 @@ const buildSpeciesLoader = (db) => {
return speciesLoader; return speciesLoader;
}; };
const buildSpeciesTranslationLoader = (db) =>
new DataLoader(async (speciesIds) => {
const qs = speciesIds.map((_) => "?").join(",");
const [rows] = await db.execute(
`SELECT * FROM species_translations
WHERE species_id IN (${qs}) AND locale = "en"`,
speciesIds,
);
const entities = rows.map(normalizeRow);
const entitiesBySpeciesId = new Map(entities.map((e) => [e.speciesId, e]));
return speciesIds.map(
(speciesId) =>
entitiesBySpeciesId.get(String(speciesId)) ||
new Error(`could not find translation for species ${speciesId}`),
);
});
const buildTradeMatchesLoader = (db) => const buildTradeMatchesLoader = (db) =>
new DataLoader( new DataLoader(
async (userPairs) => { async (userPairs) => {
@ -1487,24 +1449,6 @@ const buildZoneLoader = (db) => {
return zoneLoader; return zoneLoader;
}; };
const buildZoneTranslationLoader = (db) =>
new DataLoader(async (zoneIds) => {
const qs = zoneIds.map((_) => "?").join(",");
const [rows] = await db.execute(
`SELECT * FROM zone_translations WHERE zone_id IN (${qs}) AND locale = "en"`,
zoneIds,
);
const entities = rows.map(normalizeRow);
const entitiesByZoneId = new Map(entities.map((e) => [e.zoneId, e]));
return zoneIds.map(
(zoneId) =>
entitiesByZoneId.get(String(zoneId)) ||
new Error(`could not find translation for zone ${zoneId}`),
);
});
function buildLoaders(db) { function buildLoaders(db) {
const loaders = {}; const loaders = {};
loaders.loadAllPetTypes = loadAllPetTypes(db); loaders.loadAllPetTypes = loadAllPetTypes(db);
@ -1514,7 +1458,6 @@ function buildLoaders(db) {
loaders.closetHangersForDefaultListLoader = loaders.closetHangersForDefaultListLoader =
buildClosetHangersForDefaultListLoader(db); buildClosetHangersForDefaultListLoader(db);
loaders.colorLoader = buildColorLoader(db); loaders.colorLoader = buildColorLoader(db);
loaders.colorTranslationLoader = buildColorTranslationLoader(db);
loaders.itemLoader = buildItemLoader(db); loaders.itemLoader = buildItemLoader(db);
loaders.itemTranslationLoader = buildItemTranslationLoader(db); loaders.itemTranslationLoader = buildItemTranslationLoader(db);
loaders.itemByNameLoader = buildItemByNameLoader(db, loaders); loaders.itemByNameLoader = buildItemByNameLoader(db, loaders);
@ -1563,7 +1506,6 @@ function buildLoaders(db) {
loaders.petStateByPetTypeAndAssetsLoader = loaders.petStateByPetTypeAndAssetsLoader =
buildPetStateByPetTypeAndAssetsLoader(db, loaders); buildPetStateByPetTypeAndAssetsLoader(db, loaders);
loaders.speciesLoader = buildSpeciesLoader(db); loaders.speciesLoader = buildSpeciesLoader(db);
loaders.speciesTranslationLoader = buildSpeciesTranslationLoader(db);
loaders.tradeMatchesLoader = buildTradeMatchesLoader(db); loaders.tradeMatchesLoader = buildTradeMatchesLoader(db);
loaders.userLoader = buildUserLoader(db); loaders.userLoader = buildUserLoader(db);
loaders.userByNameLoader = buildUserByNameLoader(db); loaders.userByNameLoader = buildUserByNameLoader(db);
@ -1575,7 +1517,6 @@ function buildLoaders(db) {
loaders.userOutfitsLoader = buildUserOutfitsLoader(db, loaders); loaders.userOutfitsLoader = buildUserOutfitsLoader(db, loaders);
loaders.userLastTradeActivityLoader = buildUserLastTradeActivityLoader(db); loaders.userLastTradeActivityLoader = buildUserLastTradeActivityLoader(db);
loaders.zoneLoader = buildZoneLoader(db); loaders.zoneLoader = buildZoneLoader(db);
loaders.zoneTranslationLoader = buildZoneTranslationLoader(db);
return loaders; return loaders;
} }

View file

@ -104,22 +104,20 @@ const resolvers = {
setManualSpecialColor: async ( setManualSpecialColor: async (
_, _,
{ itemId, colorId, supportSecret }, { itemId, colorId, supportSecret },
{ itemLoader, itemTranslationLoader, colorTranslationLoader, db } { itemLoader, itemTranslationLoader, colorLoader, db },
) => { ) => {
assertSupportSecretOrThrow(supportSecret); assertSupportSecretOrThrow(supportSecret);
const oldItem = await itemLoader.load(itemId); const oldItem = await itemLoader.load(itemId);
const [ const [result] = await db.execute(
result,
] = await db.execute(
`UPDATE items SET manual_special_color_id = ? WHERE id = ? LIMIT 1`, `UPDATE items SET manual_special_color_id = ? WHERE id = ? LIMIT 1`,
[colorId, itemId] [colorId, itemId],
); );
if (result.affectedRows !== 1) { if (result.affectedRows !== 1) {
throw new Error( throw new Error(
`Expected to affect 1 item, but affected ${result.affectedRows}` `Expected to affect 1 item, but affected ${result.affectedRows}`,
); );
} }
@ -127,25 +125,19 @@ const resolvers = {
if (process.env["SUPPORT_TOOLS_DISCORD_WEBHOOK_URL"]) { if (process.env["SUPPORT_TOOLS_DISCORD_WEBHOOK_URL"]) {
try { try {
const [ const [itemTranslation, oldColor, newColor] = await Promise.all([
itemTranslation,
oldColorTranslation,
newColorTranslation,
] = await Promise.all([
itemTranslationLoader.load(itemId), itemTranslationLoader.load(itemId),
oldItem.manualSpecialColorId oldItem.manualSpecialColorId
? colorTranslationLoader.load(oldItem.manualSpecialColorId) ? colorLoader.load(oldItem.manualSpecialColorId)
: Promise.resolve(null),
colorId
? colorTranslationLoader.load(colorId)
: Promise.resolve(null), : Promise.resolve(null),
colorId ? colorLoader.load(colorId) : Promise.resolve(null),
]); ]);
const oldColorName = oldColorTranslation const oldColorName = oldColor
? capitalize(oldColorTranslation.name) ? capitalize(oldColor.name)
: "Auto-detect"; : "Auto-detect";
const newColorName = newColorTranslation const newColorName = newColor
? capitalize(newColorTranslation.name) ? capitalize(newColor.name)
: "Auto-detect"; : "Auto-detect";
await logToDiscord({ await logToDiscord({
embeds: [ embeds: [
@ -180,22 +172,20 @@ const resolvers = {
setItemExplicitlyBodySpecific: async ( setItemExplicitlyBodySpecific: async (
_, _,
{ itemId, explicitlyBodySpecific, supportSecret }, { itemId, explicitlyBodySpecific, supportSecret },
{ itemLoader, itemTranslationLoader, db } { itemLoader, itemTranslationLoader, db },
) => { ) => {
assertSupportSecretOrThrow(supportSecret); assertSupportSecretOrThrow(supportSecret);
const oldItem = await itemLoader.load(itemId); const oldItem = await itemLoader.load(itemId);
const [ const [result] = await db.execute(
result,
] = await db.execute(
`UPDATE items SET explicitly_body_specific = ? WHERE id = ? LIMIT 1`, `UPDATE items SET explicitly_body_specific = ? WHERE id = ? LIMIT 1`,
[explicitlyBodySpecific ? 1 : 0, itemId] [explicitlyBodySpecific ? 1 : 0, itemId],
); );
if (result.affectedRows !== 1) { if (result.affectedRows !== 1) {
throw new Error( throw new Error(
`Expected to affect 1 item, but affected ${result.affectedRows}` `Expected to affect 1 item, but affected ${result.affectedRows}`,
); );
} }
@ -243,22 +233,20 @@ const resolvers = {
setItemIsManuallyNc: async ( setItemIsManuallyNc: async (
_, _,
{ itemId, isManuallyNc, supportSecret }, { itemId, isManuallyNc, supportSecret },
{ itemLoader, itemTranslationLoader, db } { itemLoader, itemTranslationLoader, db },
) => { ) => {
assertSupportSecretOrThrow(supportSecret); assertSupportSecretOrThrow(supportSecret);
const oldItem = await itemLoader.load(itemId); const oldItem = await itemLoader.load(itemId);
const [ const [result] = await db.execute(
result,
] = await db.execute(
`UPDATE items SET is_manually_nc = ? WHERE id = ? LIMIT 1`, `UPDATE items SET is_manually_nc = ? WHERE id = ? LIMIT 1`,
[isManuallyNc ? 1 : 0, itemId] [isManuallyNc ? 1 : 0, itemId],
); );
if (result.affectedRows !== 1) { if (result.affectedRows !== 1) {
throw new Error( throw new Error(
`Expected to affect 1 item, but affected ${result.affectedRows}` `Expected to affect 1 item, but affected ${result.affectedRows}`,
); );
} }
@ -306,20 +294,14 @@ const resolvers = {
setLayerBodyId: async ( setLayerBodyId: async (
_, _,
{ layerId, bodyId, supportSecret }, { layerId, bodyId, supportSecret },
{ { itemLoader, itemTranslationLoader, swfAssetLoader, zoneLoader, db },
itemLoader,
itemTranslationLoader,
swfAssetLoader,
zoneTranslationLoader,
db,
}
) => { ) => {
assertSupportSecretOrThrow(supportSecret); assertSupportSecretOrThrow(supportSecret);
const oldSwfAsset = await swfAssetLoader.load(layerId); const oldSwfAsset = await swfAssetLoader.load(layerId);
if (!oldSwfAsset) { if (!oldSwfAsset) {
console.warn( console.warn(
`Skipping setLayerBodyId for unknown layer ID: ${layerId}` `Skipping setLayerBodyId for unknown layer ID: ${layerId}`,
); );
return null; return null;
} }
@ -328,21 +310,19 @@ const resolvers = {
if (oldSwfAsset.bodyId === bodyId) { if (oldSwfAsset.bodyId === bodyId) {
console.info( console.info(
`Skipping setLayerBodyId for ${layerId}: no change. ` + `Skipping setLayerBodyId for ${layerId}: no change. ` +
`(bodyId=${oldSwfAsset.bodyId})` `(bodyId=${oldSwfAsset.bodyId})`,
); );
return { id: layerId }; return { id: layerId };
} }
const [ const [result] = await db.execute(
result,
] = await db.execute(
`UPDATE swf_assets SET body_id = ? WHERE id = ? LIMIT 1`, `UPDATE swf_assets SET body_id = ? WHERE id = ? LIMIT 1`,
[bodyId, layerId] [bodyId, layerId],
); );
if (result.affectedRows !== 1) { if (result.affectedRows !== 1) {
throw new Error( throw new Error(
`Expected to affect 1 layer, but affected ${result.affectedRows}` `Expected to affect 1 layer, but affected ${result.affectedRows}`,
); );
} }
@ -354,20 +334,15 @@ const resolvers = {
.execute( .execute(
`SELECT parent_id FROM parents_swf_assets `SELECT parent_id FROM parents_swf_assets
WHERE swf_asset_id = ? AND parent_type = "Item" LIMIT 1;`, WHERE swf_asset_id = ? AND parent_type = "Item" LIMIT 1;`,
[layerId] [layerId],
) )
.then(([rows]) => normalizeRow(rows[0]).parentId); .then(([rows]) => normalizeRow(rows[0]).parentId);
const [ const [item, itemTranslation, zone, oldBodyName, newBodyName] =
item, await Promise.all([
itemTranslation,
zoneTranslation,
oldBodyName,
newBodyName,
] = await Promise.all([
itemLoader.load(itemId), itemLoader.load(itemId),
itemTranslationLoader.load(itemId), itemTranslationLoader.load(itemId),
zoneTranslationLoader.load(oldSwfAsset.zoneId), zoneLoader.load(oldSwfAsset.zoneId),
loadBodyName(oldSwfAsset.bodyId, db), loadBodyName(oldSwfAsset.bodyId, db),
loadBodyName(bodyId, db), loadBodyName(bodyId, db),
]); ]);
@ -384,7 +359,7 @@ const resolvers = {
fields: [ fields: [
{ {
name: name:
`Layer ${layerId} (${zoneTranslation.label}): ` + `Layer ${layerId} (${zone.label}): ` +
`Pet compatibility`, `Pet compatibility`,
value: `${oldBodyName} → **${newBodyName}**`, value: `${oldBodyName} → **${newBodyName}**`,
}, },
@ -411,20 +386,20 @@ const resolvers = {
itemLoader, itemLoader,
itemTranslationLoader, itemTranslationLoader,
swfAssetLoader, swfAssetLoader,
zoneTranslationLoader, zoneLoader,
petStateLoader, petStateLoader,
petTypeLoader, petTypeLoader,
colorTranslationLoader, colorLoader,
speciesTranslationLoader, speciesLoader,
db, db,
} },
) => { ) => {
assertSupportSecretOrThrow(supportSecret); assertSupportSecretOrThrow(supportSecret);
const oldSwfAsset = await swfAssetLoader.load(layerId); const oldSwfAsset = await swfAssetLoader.load(layerId);
if (!oldSwfAsset) { if (!oldSwfAsset) {
console.warn( console.warn(
`Skipping setLayerKnownGlitches for unknown layer ID: ${layerId}` `Skipping setLayerKnownGlitches for unknown layer ID: ${layerId}`,
); );
return null; return null;
} }
@ -435,21 +410,19 @@ const resolvers = {
if (oldSwfAsset.knownGlitches === newKnownGlitchesString) { if (oldSwfAsset.knownGlitches === newKnownGlitchesString) {
console.info( console.info(
`Skipping setLayerKnownGlitches for ${layerId}: no change. ` + `Skipping setLayerKnownGlitches for ${layerId}: no change. ` +
`(knownGlitches=${oldSwfAsset.knownGlitches})` `(knownGlitches=${oldSwfAsset.knownGlitches})`,
); );
return { id: layerId }; return { id: layerId };
} }
const [ const [result] = await db.execute(
result,
] = await db.execute(
`UPDATE swf_assets SET known_glitches = ? WHERE id = ? LIMIT 1`, `UPDATE swf_assets SET known_glitches = ? WHERE id = ? LIMIT 1`,
[newKnownGlitchesString, layerId] [newKnownGlitchesString, layerId],
); );
if (result.affectedRows !== 1) { if (result.affectedRows !== 1) {
throw new Error( throw new Error(
`Expected to affect 1 layer, but affected ${result.affectedRows}` `Expected to affect 1 layer, but affected ${result.affectedRows}`,
); );
} }
@ -461,15 +434,15 @@ const resolvers = {
.execute( .execute(
`SELECT parent_type, parent_id FROM parents_swf_assets `SELECT parent_type, parent_id FROM parents_swf_assets
WHERE swf_asset_id = ? LIMIT 1;`, WHERE swf_asset_id = ? LIMIT 1;`,
[layerId] [layerId],
) )
.then(([rows]) => normalizeRow(rows[0])); .then(([rows]) => normalizeRow(rows[0]));
if (parentType === "Item") { if (parentType === "Item") {
const [item, itemTranslation, zoneTranslation] = await Promise.all([ const [item, itemTranslation, zone] = await Promise.all([
itemLoader.load(parentId), itemLoader.load(parentId),
itemTranslationLoader.load(parentId), itemTranslationLoader.load(parentId),
zoneTranslationLoader.load(oldSwfAsset.zoneId), zoneLoader.load(oldSwfAsset.zoneId),
]); ]);
await logToDiscord({ await logToDiscord({
@ -484,8 +457,7 @@ const resolvers = {
fields: [ fields: [
{ {
name: name:
`Layer ${layerId} (${zoneTranslation.label}): ` + `Layer ${layerId} (${zone.label}): ` + `Known glitches`,
`Known glitches`,
value: `${oldSwfAsset.knownGlitches || "<none>"} → **${ value: `${oldSwfAsset.knownGlitches || "<none>"} → **${
newKnownGlitchesString || "<none>" newKnownGlitchesString || "<none>"
}**`, }**`,
@ -499,18 +471,14 @@ const resolvers = {
} else if (parentType === "PetState") { } else if (parentType === "PetState") {
const petState = await petStateLoader.load(parentId); const petState = await petStateLoader.load(parentId);
const petType = await petTypeLoader.load(petState.petTypeId); const petType = await petTypeLoader.load(petState.petTypeId);
const [ const [color, species, zone] = await Promise.all([
colorTranslation, colorLoader.load(petType.colorId),
speciesTranslation, speciesLoader.load(petType.speciesId),
zoneTranslation, zoneLoader.load(oldSwfAsset.zoneId),
] = await Promise.all([
colorTranslationLoader.load(petType.colorId),
speciesTranslationLoader.load(petType.speciesId),
zoneTranslationLoader.load(oldSwfAsset.zoneId),
]); ]);
const colorName = capitalize(colorTranslation.name); const colorName = capitalize(color.name);
const speciesName = capitalize(speciesTranslation.name); const speciesName = capitalize(species.name);
const pose = getPoseFromPetState(petState); const pose = getPoseFromPetState(petState);
await logToDiscord({ await logToDiscord({
@ -526,7 +494,7 @@ const resolvers = {
}, },
fields: [ fields: [
{ {
name: `Appearance ${petState.id}, Layer ${layerId} (${zoneTranslation.label}): Known glitches`, name: `Appearance ${petState.id}, Layer ${layerId} (${zone.label}): Known glitches`,
value: `${oldSwfAsset.knownGlitches || "<none>"} → **${ value: `${oldSwfAsset.knownGlitches || "<none>"} → **${
newKnownGlitchesString || "<none>" newKnownGlitchesString || "<none>"
}**`, }**`,
@ -539,7 +507,7 @@ const resolvers = {
}); });
} else { } else {
console.error( console.error(
`Error building Discord support log: unexpected parent type ${parentType}` `Error building Discord support log: unexpected parent type ${parentType}`,
); );
} }
} catch (e) { } catch (e) {
@ -555,14 +523,14 @@ const resolvers = {
bulkAddLayersToItem: async ( bulkAddLayersToItem: async (
_, _,
{ itemId, entries, supportSecret }, { itemId, entries, supportSecret },
{ itemLoader, itemTranslationLoader, db } { itemLoader, itemTranslationLoader, db },
) => { ) => {
assertSupportSecretOrThrow(supportSecret); assertSupportSecretOrThrow(supportSecret);
const item = await itemLoader.load(itemId); const item = await itemLoader.load(itemId);
if (!item) { if (!item) {
console.warn( console.warn(
`Skipping removeLayerFromItem for unknown item ID: ${itemId}` `Skipping removeLayerFromItem for unknown item ID: ${itemId}`,
); );
return null; return null;
} }
@ -585,7 +553,7 @@ const resolvers = {
swf_asset_id = ? swf_asset_id = ?
) )
`, `,
[itemId, layerId, itemId, layerId] [itemId, layerId, itemId, layerId],
), ),
]); ]);
}; };
@ -629,13 +597,7 @@ const resolvers = {
removeLayerFromItem: async ( removeLayerFromItem: async (
_, _,
{ layerId, itemId, supportSecret }, { layerId, itemId, supportSecret },
{ { itemLoader, itemTranslationLoader, swfAssetLoader, zoneLoader, db },
itemLoader,
itemTranslationLoader,
swfAssetLoader,
zoneTranslationLoader,
db,
}
) => { ) => {
assertSupportSecretOrThrow(supportSecret); assertSupportSecretOrThrow(supportSecret);
@ -645,12 +607,12 @@ const resolvers = {
`DELETE FROM parents_swf_assets ` + `DELETE FROM parents_swf_assets ` +
`WHERE swf_asset_id = ? AND parent_type = "Item" AND parent_id = ? ` + `WHERE swf_asset_id = ? AND parent_type = "Item" AND parent_id = ? ` +
`LIMIT 1`, `LIMIT 1`,
[layerId, itemId] [layerId, itemId],
); );
if (result.affectedRows !== 1) { if (result.affectedRows !== 1) {
throw new Error( throw new Error(
`Expected to affect 1 layer, but affected ${result.affectedRows}` `Expected to affect 1 layer, but affected ${result.affectedRows}`,
); );
} }
@ -658,15 +620,10 @@ const resolvers = {
if (process.env["SUPPORT_TOOLS_DISCORD_WEBHOOK_URL"]) { if (process.env["SUPPORT_TOOLS_DISCORD_WEBHOOK_URL"]) {
try { try {
const [ const [item, itemTranslation, zone, bodyName] = await Promise.all([
item,
itemTranslation,
zoneTranslation,
bodyName,
] = await Promise.all([
itemLoader.load(itemId), itemLoader.load(itemId),
itemTranslationLoader.load(itemId), itemTranslationLoader.load(itemId),
zoneTranslationLoader.load(oldSwfAsset.zoneId), zoneLoader.load(oldSwfAsset.zoneId),
loadBodyName(oldSwfAsset.bodyId, db), loadBodyName(oldSwfAsset.bodyId, db),
]); ]);
@ -681,7 +638,7 @@ const resolvers = {
}, },
fields: [ fields: [
{ {
name: `Layer ${layerId} (${zoneTranslation.label})`, name: `Layer ${layerId} (${zone.label})`,
value: `❌ Removed from ${bodyName}`, value: `❌ Removed from ${bodyName}`,
}, },
], ],
@ -703,34 +660,24 @@ const resolvers = {
setPetAppearancePose: async ( setPetAppearancePose: async (
_, _,
{ appearanceId, pose, supportSecret }, { appearanceId, pose, supportSecret },
{ { colorLoader, speciesLoader, petStateLoader, petTypeLoader, db },
colorTranslationLoader,
speciesTranslationLoader,
petStateLoader,
petTypeLoader,
db,
}
) => { ) => {
assertSupportSecretOrThrow(supportSecret); assertSupportSecretOrThrow(supportSecret);
const oldPetState = await petStateLoader.load(appearanceId); const oldPetState = await petStateLoader.load(appearanceId);
const { const { moodId, female, unconverted, labeled } =
moodId, getPetStateFieldsFromPose(pose);
female,
unconverted,
labeled,
} = getPetStateFieldsFromPose(pose);
const [result] = await db.execute( const [result] = await db.execute(
`UPDATE pet_states SET mood_id = ?, female = ?, unconverted = ?, `UPDATE pet_states SET mood_id = ?, female = ?, unconverted = ?,
labeled = ? WHERE id = ? LIMIT 1`, labeled = ? WHERE id = ? LIMIT 1`,
[moodId, female, unconverted, labeled, appearanceId] [moodId, female, unconverted, labeled, appearanceId],
); );
if (result.affectedRows !== 1) { if (result.affectedRows !== 1) {
throw new Error( throw new Error(
`Expected to affect 1 layer, but affected ${result.affectedRows}` `Expected to affect 1 layer, but affected ${result.affectedRows}`,
); );
} }
@ -740,14 +687,14 @@ const resolvers = {
if (process.env["SUPPORT_TOOLS_DISCORD_WEBHOOK_URL"]) { if (process.env["SUPPORT_TOOLS_DISCORD_WEBHOOK_URL"]) {
try { try {
const petType = await petTypeLoader.load(oldPetState.petTypeId); const petType = await petTypeLoader.load(oldPetState.petTypeId);
const [colorTranslation, speciesTranslation] = await Promise.all([ const [color, species] = await Promise.all([
colorTranslationLoader.load(petType.colorId), colorLoader.load(petType.colorId),
speciesTranslationLoader.load(petType.speciesId), speciesLoader.load(petType.speciesId),
]); ]);
const oldPose = getPoseFromPetState(oldPetState); const oldPose = getPoseFromPetState(oldPetState);
const colorName = capitalize(colorTranslation.name); const colorName = capitalize(color.name);
const speciesName = capitalize(speciesTranslation.name); const speciesName = capitalize(species.name);
await logToDiscord({ await logToDiscord({
embeds: [ embeds: [
@ -784,28 +731,20 @@ const resolvers = {
setPetAppearanceIsGlitched: async ( setPetAppearanceIsGlitched: async (
_, _,
{ appearanceId, isGlitched, supportSecret }, { appearanceId, isGlitched, supportSecret },
{ { colorLoader, speciesLoader, petStateLoader, petTypeLoader, db },
colorTranslationLoader,
speciesTranslationLoader,
petStateLoader,
petTypeLoader,
db,
}
) => { ) => {
assertSupportSecretOrThrow(supportSecret); assertSupportSecretOrThrow(supportSecret);
const oldPetState = await petStateLoader.load(appearanceId); const oldPetState = await petStateLoader.load(appearanceId);
const [ const [result] = await db.execute(
result,
] = await db.execute(
`UPDATE pet_states SET glitched = ? WHERE id = ? LIMIT 1`, `UPDATE pet_states SET glitched = ? WHERE id = ? LIMIT 1`,
[isGlitched, appearanceId] [isGlitched, appearanceId],
); );
if (result.affectedRows !== 1) { if (result.affectedRows !== 1) {
throw new Error( throw new Error(
`Expected to affect 1 layer, but affected ${result.affectedRows}` `Expected to affect 1 layer, but affected ${result.affectedRows}`,
); );
} }
@ -815,13 +754,13 @@ const resolvers = {
if (process.env["SUPPORT_TOOLS_DISCORD_WEBHOOK_URL"]) { if (process.env["SUPPORT_TOOLS_DISCORD_WEBHOOK_URL"]) {
try { try {
const petType = await petTypeLoader.load(oldPetState.petTypeId); const petType = await petTypeLoader.load(oldPetState.petTypeId);
const [colorTranslation, speciesTranslation] = await Promise.all([ const [color, species] = await Promise.all([
colorTranslationLoader.load(petType.colorId), colorLoader.load(petType.colorId),
speciesTranslationLoader.load(petType.speciesId), speciesLoader.load(petType.speciesId),
]); ]);
const colorName = capitalize(colorTranslation.name); const colorName = capitalize(color.name);
const speciesName = capitalize(speciesTranslation.name); const speciesName = capitalize(species.name);
const pose = getPoseFromPetState(oldPetState); const pose = getPoseFromPetState(oldPetState);
const oldGlitchinessState = const oldGlitchinessState =
@ -863,7 +802,7 @@ const resolvers = {
setUsername: async ( setUsername: async (
_, _,
{ userId, newUsername, supportSecret }, { userId, newUsername, supportSecret },
{ userLoader, db } { userLoader, db },
) => { ) => {
assertSupportSecretOrThrow(supportSecret); assertSupportSecretOrThrow(supportSecret);
@ -881,18 +820,18 @@ const resolvers = {
UPDATE users SET name = ? WHERE id = ? LIMIT 1; UPDATE users SET name = ? WHERE id = ? LIMIT 1;
UPDATE openneo_id.users SET name = ? WHERE id = ? LIMIT 1; UPDATE openneo_id.users SET name = ? WHERE id = ? LIMIT 1;
`, `,
[newUsername, userId, newUsername, oldUser.remoteId] [newUsername, userId, newUsername, oldUser.remoteId],
); );
if (result1.affectedRows !== 1) { if (result1.affectedRows !== 1) {
throw new Error( throw new Error(
`[UPDATE 1] Expected to affect 1 user, but affected ${result1.affectedRows}` `[UPDATE 1] Expected to affect 1 user, but affected ${result1.affectedRows}`,
); );
} }
if (result2.affectedRows !== 1) { if (result2.affectedRows !== 1) {
throw new Error( throw new Error(
`[UPDATE 2] Expected to affect 1 user, but affected ${result2.affectedRows}` `[UPDATE 2] Expected to affect 1 user, but affected ${result2.affectedRows}`,
); );
} }
@ -907,7 +846,7 @@ const resolvers = {
try { try {
await getAuth0().users.update( await getAuth0().users.update(
{ id: `auth0|impress-${userId}` }, { id: `auth0|impress-${userId}` },
{ username: newUsername } { username: newUsername },
); );
} catch (error) { } catch (error) {
if (error.statusCode === 404) { if (error.statusCode === 404) {
@ -938,8 +877,7 @@ const resolvers = {
const auth0WarningFields = auth0Warning const auth0WarningFields = auth0Warning
? [ ? [
{ {
name: name: "⚠ Auth0 warning, update skipped (maybe they weren't imported?)",
"⚠ Auth0 warning, update skipped (maybe they weren't imported?)",
value: auth0Warning.message, value: auth0Warning.message,
}, },
] ]

View file

@ -136,14 +136,14 @@ const typeDefs = gql`
const resolvers = { const resolvers = {
Color: { Color: {
name: async ({ id }, _, { colorTranslationLoader }) => { name: async ({ id }, _, { colorLoader }) => {
// TODO: Add colorId=0 to the database? Pets on Neopets.com can have it. // TODO: Add colorId=0 to the database? Pets on Neopets.com can have it.
if (id === "0") { if (id === "0") {
return "Unknown"; return "Unknown";
} }
const colorTranslation = await colorTranslationLoader.load(id); const color = await colorLoader.load(id);
return capitalize(colorTranslation.name); return capitalize(color.name);
}, },
isStandard: async ({ id }, _, { colorLoader }) => { isStandard: async ({ id }, _, { colorLoader }) => {
// TODO: Add colorId=0 to the database? Pets on Neopets.com can have it. // TODO: Add colorId=0 to the database? Pets on Neopets.com can have it.
@ -157,7 +157,7 @@ const resolvers = {
appliedToAllCompatibleSpecies: async ( appliedToAllCompatibleSpecies: async (
{ id }, { id },
_, _,
{ petTypesForColorLoader } { petTypesForColorLoader },
) => { ) => {
const petTypes = await petTypesForColorLoader.load(id); const petTypes = await petTypesForColorLoader.load(id);
const speciesColorPairs = petTypes.map((petType) => ({ id: petType.id })); const speciesColorPairs = petTypes.map((petType) => ({ id: petType.id }));
@ -166,15 +166,15 @@ const resolvers = {
}, },
Species: { Species: {
name: async ({ id }, _, { speciesTranslationLoader }) => { name: async ({ id }, _, { speciesLoader }) => {
const speciesTranslation = await speciesTranslationLoader.load(id); const species = await speciesLoader.load(id);
return capitalize(speciesTranslation.name); return capitalize(species.name);
}, },
canonicalAppearance: async ( canonicalAppearance: async (
{ id, species }, { id, species },
{ preferredColorId }, { preferredColorId },
{ petTypeBySpeciesAndColorLoader, canonicalPetStateForBodyLoader } { petTypeBySpeciesAndColorLoader, canonicalPetStateForBodyLoader },
) => { ) => {
const petType = await petTypeBySpeciesAndColorLoader.load({ const petType = await petTypeBySpeciesAndColorLoader.load({
speciesId: id, speciesId: id,
@ -221,7 +221,7 @@ const resolvers = {
withColor: async ( withColor: async (
{ id }, { id },
{ colorId }, { colorId },
{ petTypeBySpeciesAndColorLoader } { petTypeBySpeciesAndColorLoader },
) => { ) => {
const petType = await petTypeBySpeciesAndColorLoader.load({ const petType = await petTypeBySpeciesAndColorLoader.load({
speciesId: id, speciesId: id,
@ -244,7 +244,7 @@ const resolvers = {
} }
throw new Error( throw new Error(
"HACK: We populate this when you look up a canonicalAppearance, but " + "HACK: We populate this when you look up a canonicalAppearance, but " +
"don't have a direct query for it yet, oops!" "don't have a direct query for it yet, oops!",
); );
}, },
representsAllBodies: ({ id }) => { representsAllBodies: ({ id }) => {
@ -253,7 +253,7 @@ const resolvers = {
canonicalAppearance: async ( canonicalAppearance: async (
{ id, species }, { id, species },
{ preferredColorId }, { preferredColorId },
{ canonicalPetStateForBodyLoader } { canonicalPetStateForBodyLoader },
) => { ) => {
const petState = await canonicalPetStateForBodyLoader.load({ const petState = await canonicalPetStateForBodyLoader.load({
bodyId: id, bodyId: id,
@ -331,7 +331,7 @@ const resolvers = {
canonicalAppearance: async ( canonicalAppearance: async (
{ id }, { id },
_, _,
{ petTypeLoader, canonicalPetStateForBodyLoader } { petTypeLoader, canonicalPetStateForBodyLoader },
) => { ) => {
const petType = await petTypeLoader.load(id); const petType = await petTypeLoader.load(id);
@ -386,7 +386,7 @@ const resolvers = {
petAppearance: async ( petAppearance: async (
_, _,
{ speciesId, colorId, pose }, { speciesId, colorId, pose },
{ petTypeBySpeciesAndColorLoader, petStatesForPetTypeLoader } { petTypeBySpeciesAndColorLoader, petStatesForPetTypeLoader },
) => { ) => {
const petType = await petTypeBySpeciesAndColorLoader.load({ const petType = await petTypeBySpeciesAndColorLoader.load({
speciesId, speciesId,
@ -409,7 +409,7 @@ const resolvers = {
petAppearances: async ( petAppearances: async (
_, _,
{ speciesId, colorId }, { speciesId, colorId },
{ petTypeBySpeciesAndColorLoader, petStatesForPetTypeLoader } { petTypeBySpeciesAndColorLoader, petStatesForPetTypeLoader },
) => { ) => {
const petType = await petTypeBySpeciesAndColorLoader.load({ const petType = await petTypeBySpeciesAndColorLoader.load({
speciesId, speciesId,
@ -421,7 +421,7 @@ const resolvers = {
speciesColorPairsThatNeedSupportLabeling: async ( speciesColorPairsThatNeedSupportLabeling: async (
_, _,
__, __,
{ db, petTypeLoader } { db, petTypeLoader },
) => { ) => {
const [rows] = await db.query( const [rows] = await db.query(
` `
@ -443,7 +443,7 @@ const resolvers = {
AND (unconverted = 0 OR unconverted IS NULL) AND (unconverted = 0 OR unconverted IS NULL)
AND glitched = 0 AND glitched = 0
) >= 1; ) >= 1;
` `,
); );
const petTypes = rows.map(normalizeRow); const petTypes = rows.map(normalizeRow);
@ -458,61 +458,61 @@ const resolvers = {
// NOTE: This matches the colors on ItemPage, so that they always match! // NOTE: This matches the colors on ItemPage, so that they always match!
const colors = { BLUE: "8", RED: "61", GREEN: "34", YELLOW: "84" }; const colors = { BLUE: "8", RED: "61", GREEN: "34", YELLOW: "84" };
const FALLBACK_COLOR_IDS = { const FALLBACK_COLOR_IDS = {
"1": colors.GREEN, // Acara 1: colors.GREEN, // Acara
"2": colors.BLUE, // Aisha 2: colors.BLUE, // Aisha
"3": colors.YELLOW, // Blumaroo 3: colors.YELLOW, // Blumaroo
"4": colors.YELLOW, // Bori 4: colors.YELLOW, // Bori
"5": colors.YELLOW, // Bruce 5: colors.YELLOW, // Bruce
"6": colors.YELLOW, // Buzz 6: colors.YELLOW, // Buzz
"7": colors.RED, // Chia 7: colors.RED, // Chia
"8": colors.YELLOW, // Chomby 8: colors.YELLOW, // Chomby
"9": colors.GREEN, // Cybunny 9: colors.GREEN, // Cybunny
"10": colors.YELLOW, // Draik 10: colors.YELLOW, // Draik
"11": colors.RED, // Elephante 11: colors.RED, // Elephante
"12": colors.RED, // Eyrie 12: colors.RED, // Eyrie
"13": colors.GREEN, // Flotsam 13: colors.GREEN, // Flotsam
"14": colors.YELLOW, // Gelert 14: colors.YELLOW, // Gelert
"15": colors.BLUE, // Gnorbu 15: colors.BLUE, // Gnorbu
"16": colors.BLUE, // Grarrl 16: colors.BLUE, // Grarrl
"17": colors.GREEN, // Grundo 17: colors.GREEN, // Grundo
"18": colors.RED, // Hissi 18: colors.RED, // Hissi
"19": colors.GREEN, // Ixi 19: colors.GREEN, // Ixi
"20": colors.YELLOW, // Jetsam 20: colors.YELLOW, // Jetsam
"21": colors.GREEN, // Jubjub 21: colors.GREEN, // Jubjub
"22": colors.YELLOW, // Kacheek 22: colors.YELLOW, // Kacheek
"23": colors.BLUE, // Kau 23: colors.BLUE, // Kau
"24": colors.GREEN, // Kiko 24: colors.GREEN, // Kiko
"25": colors.GREEN, // Koi 25: colors.GREEN, // Koi
"26": colors.RED, // Korbat 26: colors.RED, // Korbat
"27": colors.BLUE, // Kougra 27: colors.BLUE, // Kougra
"28": colors.BLUE, // Krawk 28: colors.BLUE, // Krawk
"29": colors.YELLOW, // Kyrii 29: colors.YELLOW, // Kyrii
"30": colors.YELLOW, // Lenny 30: colors.YELLOW, // Lenny
"31": colors.YELLOW, // Lupe 31: colors.YELLOW, // Lupe
"32": colors.BLUE, // Lutari 32: colors.BLUE, // Lutari
"33": colors.YELLOW, // Meerca 33: colors.YELLOW, // Meerca
"34": colors.GREEN, // Moehog 34: colors.GREEN, // Moehog
"35": colors.BLUE, // Mynci 35: colors.BLUE, // Mynci
"36": colors.BLUE, // Nimmo 36: colors.BLUE, // Nimmo
"37": colors.YELLOW, // Ogrin 37: colors.YELLOW, // Ogrin
"38": colors.RED, // Peophin 38: colors.RED, // Peophin
"39": colors.GREEN, // Poogle 39: colors.GREEN, // Poogle
"40": colors.RED, // Pteri 40: colors.RED, // Pteri
"41": colors.YELLOW, // Quiggle 41: colors.YELLOW, // Quiggle
"42": colors.BLUE, // Ruki 42: colors.BLUE, // Ruki
"43": colors.RED, // Scorchio 43: colors.RED, // Scorchio
"44": colors.YELLOW, // Shoyru 44: colors.YELLOW, // Shoyru
"45": colors.RED, // Skeith 45: colors.RED, // Skeith
"46": colors.YELLOW, // Techo 46: colors.YELLOW, // Techo
"47": colors.BLUE, // Tonu 47: colors.BLUE, // Tonu
"48": colors.YELLOW, // Tuskaninny 48: colors.YELLOW, // Tuskaninny
"49": colors.GREEN, // Uni 49: colors.GREEN, // Uni
"50": colors.RED, // Usul 50: colors.RED, // Usul
"55": colors.YELLOW, // Vandagyre 55: colors.YELLOW, // Vandagyre
"51": colors.YELLOW, // Wocky 51: colors.YELLOW, // Wocky
"52": colors.RED, // Xweetok 52: colors.RED, // Xweetok
"53": colors.RED, // Yurble 53: colors.RED, // Yurble
"54": colors.BLUE, // Zafara 54: colors.BLUE, // Zafara
}; };
module.exports = { typeDefs, resolvers }; module.exports = { typeDefs, resolvers };

View file

@ -23,9 +23,9 @@ const resolvers = {
const zone = await zoneLoader.load(id); const zone = await zoneLoader.load(id);
return zone.depth; return zone.depth;
}, },
label: async ({ id }, _, { zoneTranslationLoader }) => { label: async ({ id }, _, { zoneLoader }) => {
const zoneTranslation = await zoneTranslationLoader.load(id); const zone = await zoneLoader.load(id);
return zoneTranslation.label; return zone.label;
}, },
isCommonlyUsedByItems: async ({ id }, _, { zoneLoader }) => { isCommonlyUsedByItems: async ({ id }, _, { zoneLoader }) => {
// Zone metadata marks item zones with types 2, 3, and 4. But also, in // Zone metadata marks item zones with types 2, 3, and 4. But also, in

View file

@ -29,7 +29,7 @@ function getPoseFromPetState(petState) {
`could not identify pose: ` + `could not identify pose: ` +
`moodId=${moodId}, ` + `moodId=${moodId}, ` +
`female=${female}, ` + `female=${female}, ` +
`unconverted=${unconverted}` `unconverted=${unconverted}`,
); );
} }
} }
@ -87,16 +87,13 @@ async function loadBodyName(bodyId, db) {
} }
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT pt.body_id, st.name AS species_name, `SELECT pt.body_id, s.name AS species_name,
ct.name AS color_name, c.standard FROM pet_types pt c.name AS color_name, c.standard FROM pet_types pt
INNER JOIN species_translations st INNER JOIN species s ON pt.species_id = s.id
ON pt.species_id = st.species_id AND st.locale = "en"
INNER JOIN color_translations ct
ON pt.color_id = ct.color_id AND ct.locale = "en"
INNER JOIN colors c ON c.id = pt.color_id INNER JOIN colors c ON c.id = pt.color_id
WHERE pt.body_id = ? WHERE pt.body_id = ?
ORDER BY c.standard DESC, ct.name, st.name LIMIT 1;`, ORDER BY c.standard DESC, color_name, species_name LIMIT 1;`,
[bodyId] [bodyId],
); );
const row = normalizeRow(rows[0]); const row = normalizeRow(rows[0]);
const speciesName = capitalize(row.speciesName); const speciesName = capitalize(row.speciesName);
@ -119,7 +116,7 @@ async function logToDiscord(body) {
if (!res.ok) { if (!res.ok) {
const resText = await res.text(); const resText = await res.text();
throw new Error( throw new Error(
`Discord returned ${res.status} ${res.statusText}: ${resText}` `Discord returned ${res.status} ${res.statusText}: ${resText}`,
); );
} }
} finally { } finally {