Support tools can set appearance glitched state!
this is also very good! :3
This commit is contained in:
parent
2929c3373e
commit
1c8eba4698
2 changed files with 170 additions and 7 deletions
|
@ -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 (
|
||||
<Box>
|
||||
<Box display="flex" flexDirection="row" alignItems="center">
|
||||
|
@ -255,10 +290,16 @@ function PosePickerSupportPoseFields({ petAppearance, speciesId, colorId }) {
|
|||
size="sm"
|
||||
value={petAppearance.pose}
|
||||
flex="0 1 200px"
|
||||
icon={loading ? <Spinner /> : data ? <CheckCircleIcon /> : undefined}
|
||||
icon={
|
||||
poseMutation.loading ? (
|
||||
<Spinner />
|
||||
) : poseMutation.data ? (
|
||||
<CheckCircleIcon />
|
||||
) : 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]) => (
|
||||
<option key={pose} value={pose}>
|
||||
|
@ -289,14 +330,45 @@ function PosePickerSupportPoseFields({ petAppearance, speciesId, colorId }) {
|
|||
marginLeft="2"
|
||||
flex="0 1 150px"
|
||||
value={petAppearance.isGlitched}
|
||||
cursor="not-allowed"
|
||||
isReadOnly
|
||||
icon={
|
||||
isGlitchedMutation.loading ? (
|
||||
<Spinner />
|
||||
) : isGlitchedMutation.data ? (
|
||||
<CheckCircleIcon />
|
||||
) : undefined
|
||||
}
|
||||
onChange={(e) => {
|
||||
const isGlitched = e.target.value === "true";
|
||||
mutateIsGlitched({
|
||||
variables: {
|
||||
appearanceId: petAppearance.id,
|
||||
isGlitched,
|
||||
supportSecret,
|
||||
},
|
||||
optimisticResponse: {
|
||||
__typename: "Mutation",
|
||||
setPetAppearanceIsGlitched: {
|
||||
__typename: "PetAppearance",
|
||||
id: petAppearance.id,
|
||||
isGlitched,
|
||||
},
|
||||
},
|
||||
}).catch((e) => {
|
||||
/* Discard errors here; we'll show them in the UI! */
|
||||
});
|
||||
}}
|
||||
isInvalid={isGlitchedMutation.error != null}
|
||||
>
|
||||
<option value="false">Valid</option>
|
||||
<option value="true">Glitched</option>
|
||||
</Select>
|
||||
</Box>
|
||||
{error && <Box color="red.400">{error.message}</Box>}
|
||||
{poseMutation.error && (
|
||||
<Box color="red.400">{poseMutation.error.message}</Box>
|
||||
)}
|
||||
{isGlitchedMutation.error && (
|
||||
<Box color="red.400">{isGlitchedMutation.error.message}</Box>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 };
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue