From 1c8eba4698fc1eea3480796eaa92e2adb1016418 Mon Sep 17 00:00:00 2001 From: Matchu Date: Mon, 31 Aug 2020 00:48:54 -0700 Subject: [PATCH] Support tools can set appearance glitched state! this is also very good! :3 --- .../WardrobePage/support/PosePickerSupport.js | 86 ++++++++++++++++-- src/server/index.js | 91 +++++++++++++++++++ 2 files changed, 170 insertions(+), 7 deletions(-) diff --git a/src/app/WardrobePage/support/PosePickerSupport.js b/src/app/WardrobePage/support/PosePickerSupport.js index 3af7acb..ae6c7d6 100644 --- a/src/app/WardrobePage/support/PosePickerSupport.js +++ b/src/app/WardrobePage/support/PosePickerSupport.js @@ -213,7 +213,7 @@ function PosePickerSupportNavigator({ function PosePickerSupportPoseFields({ petAppearance, speciesId, colorId }) { const { supportSecret } = useSupport(); - const [mutate, { loading, error, data }] = useMutation( + const [mutatePose, poseMutation] = useMutation( gql` mutation PosePickerSupportSetPetAppearancePose( $appearanceId: ID! @@ -248,6 +248,41 @@ function PosePickerSupportPoseFields({ petAppearance, speciesId, colorId }) { } ); + const [mutateIsGlitched, isGlitchedMutation] = useMutation( + gql` + mutation PosePickerSupportSetPetAppearanceIsGlitched( + $appearanceId: ID! + $isGlitched: Boolean! + $supportSecret: String! + ) { + setPetAppearanceIsGlitched( + appearanceId: $appearanceId + isGlitched: $isGlitched + supportSecret: $supportSecret + ) { + id + isGlitched + } + } + `, + { + refetchQueries: [ + { + query: gql` + query PosePickerSupportRefetchCanonicalAppearances( + $speciesId: ID! + $colorId: ID! + ) { + ...CanonicalPetAppearances + } + ${canonicalPetAppearancesFragment} + `, + variables: { speciesId, colorId }, + }, + ], + } + ); + return ( @@ -255,10 +290,16 @@ function PosePickerSupportPoseFields({ petAppearance, speciesId, colorId }) { size="sm" value={petAppearance.pose} flex="0 1 200px" - icon={loading ? : data ? : undefined} + icon={ + poseMutation.loading ? ( + + ) : poseMutation.data ? ( + + ) : undefined + } onChange={(e) => { const pose = e.target.value; - mutate({ + mutatePose({ variables: { appearanceId: petAppearance.id, pose, @@ -276,7 +317,7 @@ function PosePickerSupportPoseFields({ petAppearance, speciesId, colorId }) { /* Discard errors here; we'll show them in the UI! */ }); }} - isInvalid={error != null} + isInvalid={poseMutation.error != null} > {Object.entries(POSE_NAMES).map(([pose, name]) => ( - {error && {error.message}} + {poseMutation.error && ( + {poseMutation.error.message} + )} + {isGlitchedMutation.error && ( + {isGlitchedMutation.error.message} + )} ); } diff --git a/src/server/index.js b/src/server/index.js index a238598..101e501 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -267,6 +267,12 @@ const typeDefs = gql` pose: Pose! supportSecret: String! ): PetAppearance! + + setPetAppearanceIsGlitched( + appearanceId: ID! + isGlitched: Boolean! + supportSecret: String! + ): PetAppearance! } `; @@ -1027,6 +1033,91 @@ const resolvers = { return { id: appearanceId }; }, + + setPetAppearanceIsGlitched: async ( + _, + { appearanceId, isGlitched, supportSecret }, + { + colorTranslationLoader, + speciesTranslationLoader, + petStateLoader, + petTypeLoader, + db, + } + ) => { + if (supportSecret !== process.env["SUPPORT_SECRET"]) { + throw new Error(`Support secret is incorrect. Try setting up again?`); + } + + const oldPetState = await petStateLoader.load(appearanceId); + + const [ + result, + ] = await db.execute( + `UPDATE pet_states SET glitched = ? WHERE id = ? LIMIT 1`, + [isGlitched, appearanceId] + ); + + if (result.affectedRows !== 1) { + throw new Error( + `Expected to affect 1 layer, but affected ${result.affectedRows}` + ); + } + + // we changed it, so clear it from cache + petStateLoader.clear(appearanceId); + + if (process.env["SUPPORT_TOOLS_DISCORD_WEBHOOK_URL"]) { + try { + const petType = await petTypeLoader.load(oldPetState.petTypeId); + const [colorTranslation, speciesTranslation] = await Promise.all([ + colorTranslationLoader.load(petType.colorId), + speciesTranslationLoader.load(petType.speciesId), + ]); + + const colorName = capitalize(colorTranslation.name); + const speciesName = capitalize(speciesTranslation.name); + + const pose = getPoseFromPetState(oldPetState); + const oldGlitchinessState = + String(oldPetState.glitched) === "1" ? "Glitched" : "Valid"; + const newGlitchinessState = isGlitched ? "Glitched" : "Valid"; + + await logToDiscord({ + embeds: [ + { + title: `🛠 ${colorName} ${speciesName}`, + thumbnail: { + url: `http://pets.neopets.com/cp/${ + petType.basicImageHash || petType.imageHash + }/1/6.png`, + height: 150, + width: 150, + }, + fields: [ + { + name: `Appearance ${appearanceId}`, + value: `${oldGlitchinessState} → **${newGlitchinessState}**`, + }, + { + name: "As a reminder…", + value: "…the thumbnail might not match!", + }, + ], + timestamp: new Date().toISOString(), + url: `https://impress-2020.openneo.net/outfits/new?species=${petType.speciesId}&color=${petType.colorId}&pose=${pose}&state=${appearanceId}`, + }, + ], + }); + } catch (e) { + console.error("Error sending Discord support log", e); + } + } else { + console.warn("No Discord support webhook provided, skipping"); + } + + return { id: appearanceId }; + }, }, };