sendou.ink/pages/api/builds/index.ts
Kalle (Sendou) 3a589c053f crash fixes
2021-01-30 13:36:39 +02:00

165 lines
4.2 KiB
TypeScript

import { Ability } from "@prisma/client";
import { getMySession } from "lib/api";
import { GANBA_DISCORD_ID } from "lib/constants";
import { getWeaponNormalized } from "lib/lists/weapons";
import { buildSchema } from "lib/validators/build";
import { NextApiRequest, NextApiResponse } from "next";
import prisma from "prisma/client";
const modes = ["TW", "SZ", "TC", "RM", "CB"];
const buildHandler = async (req: NextApiRequest, res: NextApiResponse) => {
const user = await getMySession(req);
switch (req.method) {
case "POST":
await postHandler();
break;
case "PUT":
await updateHandler();
break;
case "DELETE":
await deleteHandler();
break;
default:
return res.status(405).end();
}
async function postHandler() {
if (!user) return res.status(401).end();
const parsed = buildSchema.safeParse(req.body);
if (!parsed.success) {
return res.status(400).end();
}
const postsJpBuilds = user.discordId === GANBA_DISCORD_ID;
if (
!postsJpBuilds &&
(await prisma.build.count({ where: { id: user.id } })) >= 100
) {
return res
.status(400)
.json({ message: "You have too many builds posted already" });
}
await prisma.build.create({
data: {
...parsed.data,
modes: parsed.data.modes.sort(
(a, b) => modes.indexOf(a) - modes.indexOf(b)
),
abilityPoints: getAbilityPoints(
parsed.data.headAbilities,
parsed.data.clothingAbilities,
parsed.data.shoesAbilities
),
jpn: postsJpBuilds,
top500: await hasTop500WithTheWeapon(user.id, parsed.data.weapon),
userId: user.id,
},
});
res.status(200).end();
}
async function updateHandler() {
if (!user) return res.status(401).end();
const parsed = buildSchema.safeParse(req.body);
if (!parsed.success) {
return res.status(400).end();
}
const id = parsed.data.id;
const existingBuild = await prisma.build.findUnique({
where: { id },
});
if (!existingBuild) {
return res.status(400).end();
}
if (existingBuild.userId !== user.id) {
return res.status(403).end();
}
delete parsed.data.id;
await prisma.build.update({
where: { id },
data: {
...parsed.data,
modes: parsed.data.modes.sort(
(a, b) => modes.indexOf(a) - modes.indexOf(b)
),
top500:
parsed.data.weapon === existingBuild.weapon
? existingBuild.top500
: await hasTop500WithTheWeapon(user.id, parsed.data.weapon),
abilityPoints: getAbilityPoints(
parsed.data.headAbilities,
parsed.data.clothingAbilities,
parsed.data.shoesAbilities
),
},
});
res.status(200).end();
}
async function deleteHandler() {
if (!user) return res.status(401).end();
const id = parseInt(req.body.id);
if (Number.isNaN(id)) return res.status(400).end();
const buildToDelete = await prisma.build.findUnique({ where: { id } });
if (!buildToDelete) return res.status(400).end();
if (buildToDelete.userId !== user.id) return res.status(401).end();
await prisma.build.delete({ where: { id } });
res.status(200).end();
}
};
function getAbilityPoints(
headAbilities: Ability[],
clothingAbilities: Ability[],
shoesAbilities: Ability[]
) {
const result: Partial<Record<Ability, number>> = {};
const getPointsFromAbilityArray = (ability: Ability, index: number) => {
const existingAmount = result[ability] ?? 0;
const apsToAdd = index === 0 ? 10 : 3;
result[ability] = existingAmount + apsToAdd;
};
headAbilities.forEach(getPointsFromAbilityArray);
clothingAbilities.forEach(getPointsFromAbilityArray);
shoesAbilities.forEach(getPointsFromAbilityArray);
return result;
}
async function hasTop500WithTheWeapon(userId: number, weapon: string) {
const playerData = await prisma.player.findFirst({
where: { userId: userId },
include: { placements: true },
});
if (!playerData) return false;
return playerData.placements.some(
(placement) => placement.weapon === getWeaponNormalized(weapon)
);
}
export default buildHandler;