674 lines
25 KiB
TypeScript
674 lines
25 KiB
TypeScript
import { NextApiRequest, NextApiResponse } from "next";
|
|
import db from "../../../Modules/database";
|
|
import { authOptions } from "#/pages/api/auth/[...nextauth]";
|
|
import { getServerSession } from "next-auth";
|
|
// This is the structure of the get response
|
|
export interface getLeagues {
|
|
money: number;
|
|
transferCount: number;
|
|
timeLeft: number;
|
|
ownership: { [Key: string]: (ownershipInfo | transferInfo)[] };
|
|
transferOpen: boolean;
|
|
}
|
|
interface ownershipInfo {
|
|
transfer: false;
|
|
owner: number;
|
|
}
|
|
interface transferInfo {
|
|
transfer: true;
|
|
seller: number;
|
|
buyer: number;
|
|
amount: number;
|
|
}
|
|
export interface GETResult {
|
|
money: number;
|
|
transferCount: number;
|
|
timeLeft: number;
|
|
ownership: { [Key: string]: (ownershipInfo | transferInfo)[] };
|
|
transferOpen: boolean;
|
|
}
|
|
export default async function handler(
|
|
req: NextApiRequest,
|
|
res: NextApiResponse,
|
|
) {
|
|
const session = await getServerSession(req, res, authOptions);
|
|
const league = parseInt(String(req.query.league));
|
|
if (!session) {
|
|
res.status(401).end("Not logged in");
|
|
} else {
|
|
const user = session.user.id;
|
|
const leagueSettings = await db
|
|
.selectFrom("leagueSettings")
|
|
.selectAll()
|
|
.where("leagueID", "=", league)
|
|
.executeTakeFirst();
|
|
// Checks if the league ia archived
|
|
if (leagueSettings?.archived !== 0) {
|
|
res.status(400).end("This league is archived");
|
|
return;
|
|
}
|
|
// Gets users money
|
|
const money =
|
|
(
|
|
await db
|
|
.selectFrom("leagueUsers")
|
|
.select("money")
|
|
.where("leagueID", "=", league)
|
|
.where("user", "=", user)
|
|
.executeTakeFirst()
|
|
)?.money || 0;
|
|
// Gets the leagues settings
|
|
if (leagueSettings.fantasyEnabled === 0) {
|
|
res.status(400).end("This league does not have fantasy enabled. ");
|
|
return;
|
|
}
|
|
// Checks if the transfer market is open
|
|
const transferOpen = await db
|
|
.selectFrom("data")
|
|
.select("value1")
|
|
.where("value1", "=", "transferOpen" + leagueSettings.league)
|
|
.where("value2", "=", "true")
|
|
.execute()
|
|
.then((e) => e.length > 0);
|
|
switch (req.method) {
|
|
// Used to return a dictionary of all transfers and ownerships
|
|
case "GET":
|
|
if (money !== undefined) {
|
|
const [transfers, squads, timeLeft] = await Promise.all([
|
|
// Gets list of all transfers
|
|
db
|
|
.selectFrom("transfers")
|
|
.selectAll()
|
|
.where("leagueID", "=", league)
|
|
.execute(),
|
|
// Gets squads
|
|
db
|
|
.selectFrom("squad")
|
|
.selectAll()
|
|
.where("leagueID", "=", league)
|
|
.execute(),
|
|
// Gets the amount of time left in the transfer period
|
|
db
|
|
.selectFrom("data")
|
|
.select("value2")
|
|
.where("value1", "=", "countdown" + leagueSettings.league)
|
|
.executeTakeFirst()
|
|
.then((e) => parseInt(String(e?.value2))),
|
|
]);
|
|
// Puts all the ownership and transfer info in a dictionary
|
|
const ownership: { [Key: string]: (ownershipInfo | transferInfo)[] } =
|
|
{};
|
|
let transferCount = 0;
|
|
squads.forEach((e) => {
|
|
if (ownership[e.playeruid] === undefined) {
|
|
ownership[e.playeruid] = [{ transfer: false, owner: e.user }];
|
|
} else {
|
|
ownership[e.playeruid].push({ transfer: false, owner: e.user });
|
|
}
|
|
});
|
|
transfers.forEach((e) => {
|
|
const data: transferInfo = {
|
|
transfer: true,
|
|
seller: e.seller,
|
|
buyer: e.buyer,
|
|
amount: e.value,
|
|
};
|
|
if (ownership[e.playeruid] === undefined) {
|
|
ownership[e.playeruid] = [data];
|
|
} else {
|
|
ownership[e.playeruid] = ownership[e.playeruid].filter(
|
|
(f) => e.seller !== (f as ownershipInfo).owner,
|
|
);
|
|
ownership[e.playeruid].push(data);
|
|
}
|
|
if (e.seller == user || e.buyer == user) {
|
|
transferCount++;
|
|
}
|
|
});
|
|
const result: GETResult = {
|
|
money,
|
|
transferCount,
|
|
timeLeft,
|
|
ownership,
|
|
transferOpen,
|
|
};
|
|
res.status(200).json(result);
|
|
} else {
|
|
res.status(404).end("League not found");
|
|
}
|
|
break;
|
|
// Used to create a new transfer
|
|
case "POST":
|
|
const playeruid = req.body.playeruid;
|
|
const amount = parseInt(req.body.amount);
|
|
// Checks if the transfer market is still open
|
|
if (!transferOpen && !leagueSettings.matchdayTransfers) {
|
|
res.status(400).end("Transfer Market is closed");
|
|
break;
|
|
}
|
|
const player = await db
|
|
.selectFrom("players")
|
|
.selectAll()
|
|
.where("uid", "=", playeruid)
|
|
.where("league", "=", leagueSettings.league)
|
|
.executeTakeFirst();
|
|
// Checks if the player exists
|
|
if (player === undefined) {
|
|
res.status(404).end("Player does not exist");
|
|
break;
|
|
}
|
|
// Says if the user still has transfers left
|
|
const emptySquad =
|
|
(await db
|
|
.selectFrom("squad")
|
|
.select(["playeruid"])
|
|
.where("leagueID", "=", league)
|
|
.where("user", "=", user)
|
|
.executeTakeFirst()) === undefined;
|
|
const transferCount = db
|
|
.selectFrom("transfers")
|
|
.select((eb) => [eb.fn.count("playeruid").as("count")])
|
|
.where("leagueID", "=", league)
|
|
.where((eb) =>
|
|
eb.or([eb("buyer", "=", user), eb("seller", "=", user)]),
|
|
)
|
|
.executeTakeFirst()
|
|
.then((e) => parseInt(String(e?.count)));
|
|
const transferLeft =
|
|
emptySquad || (await transferCount) < leagueSettings.transfers;
|
|
// Checks if this was a purchase
|
|
if (amount > 0) {
|
|
// Checks if the player is already owned by the user
|
|
if (
|
|
(await db
|
|
.selectFrom("squad")
|
|
.select(["playeruid"])
|
|
.where("leagueID", "=", league)
|
|
.where("user", "=", user)
|
|
.where("playeruid", "=", playeruid)
|
|
.executeTakeFirst()) !== undefined
|
|
) {
|
|
res.status(400).end("You already own the player");
|
|
break;
|
|
}
|
|
// Checks if the player is already being purchased
|
|
const purchaseTransfer = await db
|
|
.selectFrom("transfers")
|
|
.selectAll()
|
|
.where("buyer", "=", user)
|
|
.where("playeruid", "=", playeruid)
|
|
.where("leagueID", "=", league)
|
|
.executeTakeFirst();
|
|
if (purchaseTransfer !== undefined) {
|
|
// Makes sure the bid is greater than or equal to the current purchase amount
|
|
if (purchaseTransfer.value > amount) {
|
|
res
|
|
.status(400)
|
|
.end("You can not bid lower than your current purchase");
|
|
break;
|
|
}
|
|
await db
|
|
.updateTable("transfers")
|
|
.set({ max: amount })
|
|
.where("buyer", "=", user)
|
|
.where("playeruid", "=", playeruid)
|
|
.where("leagueID", "=", league)
|
|
.execute();
|
|
res.status(200).end(`Updated max bid to {amount} M`);
|
|
break;
|
|
}
|
|
// Checks if the user still has transfers left
|
|
if (!transferLeft) {
|
|
res.status(400).end("You have no more transfers");
|
|
break;
|
|
}
|
|
// Checks if the player can still be bought from the AI
|
|
const squadCount = await db
|
|
.selectFrom("squad")
|
|
.select((eb) => [eb.fn.count("user").as("count")])
|
|
.where("leagueID", "=", league)
|
|
.where("playeruid", "=", playeruid)
|
|
.executeTakeFirst()
|
|
.then((e) => parseInt(String(e?.count)));
|
|
const transferCountBuy = await db
|
|
.selectFrom("transfers")
|
|
.select((eb) => [eb.fn.count("buyer").as("count")])
|
|
.where("seller", "=", 0)
|
|
.where("leagueID", "=", league)
|
|
.where("playeruid", "=", playeruid)
|
|
.executeTakeFirst()
|
|
.then((e) => parseInt(String(e?.count)));
|
|
if (squadCount + transferCountBuy < leagueSettings.duplicatePlayers) {
|
|
// Checks if the user has offered enough money.
|
|
if (amount < player.sale_price) {
|
|
res
|
|
.status(400)
|
|
.end(
|
|
"You can not buy a player for less than the player's value",
|
|
);
|
|
break;
|
|
}
|
|
if (money < player.sale_price) {
|
|
res.status(400).end("You do not have enough money");
|
|
break;
|
|
}
|
|
await db
|
|
.insertInto("transfers")
|
|
.values({
|
|
leagueID: league,
|
|
seller: 0,
|
|
buyer: user,
|
|
playeruid,
|
|
value: player.sale_price,
|
|
max: amount,
|
|
})
|
|
.execute();
|
|
await db
|
|
.updateTable("leagueUsers")
|
|
.set({ money: money - player.sale_price })
|
|
.where("leagueID", "=", league)
|
|
.where("user", "=", user)
|
|
.execute();
|
|
console.log(
|
|
`Player ${playeruid} bought for ${player.sale_price} with max bid of ${amount} by user ${user} in league ${league}`,
|
|
);
|
|
res.status(200).end("Bought player");
|
|
break;
|
|
}
|
|
// Checks if the player can even be bought from anyone
|
|
const transferCountSell = await db
|
|
.selectFrom("transfers")
|
|
.select((eb) => [eb.fn.count("buyer").as("count")])
|
|
.where("leagueID", "=", league)
|
|
.where("playeruid", "=", playeruid)
|
|
.where("seller", "!=", 0)
|
|
.executeTakeFirst()
|
|
.then((e) => parseInt(String(e?.count)));
|
|
if (
|
|
squadCount - transferCountSell <
|
|
leagueSettings.duplicatePlayers
|
|
) {
|
|
// Increments all the offers by 100000 until someone drops their transfer
|
|
while (true) {
|
|
const cheapest = await db
|
|
.selectFrom("transfers")
|
|
.selectAll()
|
|
.where("leagueID", "=", league)
|
|
.where("playeruid", "=", playeruid)
|
|
.orderBy("value", "asc")
|
|
.limit(1)
|
|
.executeTakeFirst();
|
|
if (cheapest === undefined) {
|
|
res.status(500).end("Could not find transfer to outbid");
|
|
break;
|
|
}
|
|
// Checks if this is an AI
|
|
const isAI = cheapest.buyer === 0 || cheapest.buyer === -1;
|
|
// Checks if the player still wants to pay that amount
|
|
if (cheapest.value >= amount + (isAI ? 100000 : 0)) {
|
|
res.status(400).end("Not enough money offered");
|
|
break;
|
|
}
|
|
if (cheapest.value + 100000 > money + (isAI ? 100000 : 0)) {
|
|
res.status(400).end("You do not have enough money");
|
|
break;
|
|
}
|
|
// Checks if that player wants to increment the offer and if they can afford it
|
|
if (
|
|
cheapest.max > cheapest.value &&
|
|
(await db
|
|
.selectFrom("leagueUsers")
|
|
.select(["leagueID"])
|
|
.where("leagueID", "=", league)
|
|
.where("user", "=", cheapest.buyer)
|
|
.where("money", ">=", 100000)
|
|
.executeTakeFirst()) !== undefined
|
|
) {
|
|
console.log(
|
|
`User ${cheapest.buyer} increased bid to ${
|
|
cheapest.value + 100000
|
|
} for ${playeruid} due to automatic bid increase in league ${league}`,
|
|
);
|
|
// Increases the bidding amount by 100k for that bid
|
|
await Promise.all([
|
|
db
|
|
.updateTable("leagueUsers")
|
|
.set((eb) => ({
|
|
money: eb("money", "-", 100000),
|
|
}))
|
|
.where("user", "=", cheapest.buyer)
|
|
.where("leagueID", "=", league)
|
|
.execute(),
|
|
db
|
|
.updateTable("leagueUsers")
|
|
.set((eb) => ({
|
|
money: eb("money", "+", 100000),
|
|
}))
|
|
.where("user", "=", cheapest.seller)
|
|
.where("leagueID", "=", league)
|
|
.execute(),
|
|
db
|
|
.updateTable("transfers")
|
|
.set((eb) => ({
|
|
value: eb("value", "+", 100000),
|
|
}))
|
|
.where("buyer", "=", cheapest.buyer)
|
|
.where("leagueID", "=", league)
|
|
.where("playeruid", "=", playeruid)
|
|
.execute(),
|
|
]);
|
|
} else {
|
|
// Moves transfer to the new bidder
|
|
await Promise.all([
|
|
// Updates the original buyers money
|
|
db
|
|
.updateTable("leagueUsers")
|
|
.set((eb) => ({ money: eb("money", "+", cheapest.value) }))
|
|
.where("user", "=", cheapest.buyer)
|
|
.where("leagueID", "=", league)
|
|
.execute(),
|
|
// Updates the new buyers money
|
|
db
|
|
.updateTable("leagueUsers")
|
|
.set((eb) => ({
|
|
money: eb(
|
|
"money",
|
|
"-",
|
|
cheapest.value + (isAI ? 0 : 100000),
|
|
),
|
|
}))
|
|
.where("user", "=", user)
|
|
.where("leagueID", "=", league)
|
|
.execute(),
|
|
// Updates the sellers money
|
|
db
|
|
.updateTable("leagueUsers")
|
|
.set((eb) => ({
|
|
money: eb("money", "-", isAI ? 0 : 100000),
|
|
}))
|
|
.where("user", "=", cheapest.seller)
|
|
.where("leagueID", "=", league)
|
|
.execute(),
|
|
// Updates the transfers data
|
|
db
|
|
.updateTable("transfers")
|
|
.set((eb) => ({
|
|
value: eb("value", "+", isAI ? 0 : 100000),
|
|
position: "bench",
|
|
starred: 0,
|
|
buyer: user,
|
|
}))
|
|
.where("leagueID", "=", league)
|
|
.where("buyer", "=", cheapest.buyer)
|
|
.where("playeruid", "=", playeruid)
|
|
.execute(),
|
|
]);
|
|
console.log(
|
|
`User ${user} outbid ${cheapest.buyer} with ${
|
|
cheapest.value + (isAI ? 0 : 100000)
|
|
} for ${playeruid} in league ${league}`,
|
|
);
|
|
res.status(200).end("Bought player");
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
} else {
|
|
res.status(400).end("Player not for sale");
|
|
break;
|
|
}
|
|
// Checks if this is a sale
|
|
} else if (amount < 0) {
|
|
// Checks if the player is already being sold
|
|
const possibleTransfer = await db
|
|
.selectFrom("transfers")
|
|
.selectAll()
|
|
.where("leagueID", "=", league)
|
|
.where("seller", "=", user)
|
|
.where("playeruid", "=", playeruid)
|
|
.executeTakeFirst();
|
|
if (possibleTransfer !== undefined) {
|
|
if (possibleTransfer.value < amount * -1) {
|
|
// Used to check if the buyer has enough money
|
|
const enoughMoney = await db
|
|
.selectFrom("leagueUsers")
|
|
.where("leagueID", "=", league)
|
|
.where("user", "=", possibleTransfer.buyer)
|
|
.select("money")
|
|
.executeTakeFirst()
|
|
.then(
|
|
(e) =>
|
|
(e?.money || 0) >= amount * -1 - possibleTransfer.value,
|
|
);
|
|
// Checks if the user is willing to pay enough for the player
|
|
if (possibleTransfer.max >= amount * -1 && enoughMoney) {
|
|
await db
|
|
.updateTable("transfers")
|
|
.set({
|
|
value: amount * -1,
|
|
})
|
|
.where("leagueID", "=", league)
|
|
.where("buyer", "=", possibleTransfer.buyer)
|
|
.where("seller", "=", user)
|
|
.where("playeruid", "=", playeruid)
|
|
.execute();
|
|
await db
|
|
.updateTable("leagueUsers")
|
|
.set({
|
|
money: (eb) =>
|
|
eb("money", "-", amount * -1 - possibleTransfer.value),
|
|
})
|
|
.where("leagueID", "=", league)
|
|
.where("user", "=", possibleTransfer.buyer)
|
|
.execute();
|
|
await db
|
|
.updateTable("leagueUsers")
|
|
.set({
|
|
money: (eb) =>
|
|
eb("money", "+", amount * -1 - possibleTransfer.value),
|
|
})
|
|
.where("leagueID", "=", league)
|
|
.where("user", "=", user)
|
|
.execute();
|
|
} else {
|
|
if (possibleTransfer.buyer !== -1) {
|
|
// Makes sure to check if the player has enough money to cancel this
|
|
if (money < possibleTransfer.value) {
|
|
res
|
|
.status(400)
|
|
.end(
|
|
`You need to have ${
|
|
possibleTransfer.value / 1000000
|
|
}M to increase the minimum amount of the transfer`,
|
|
);
|
|
break;
|
|
}
|
|
// Makes the transaction a possible offer
|
|
await db
|
|
.updateTable("transfers")
|
|
.set({
|
|
buyer: -1,
|
|
max: amount * -1,
|
|
value: amount * -1,
|
|
})
|
|
.where("leagueID", "=", league)
|
|
.where("seller", "=", user)
|
|
.where("playeruid", "=", playeruid)
|
|
.execute();
|
|
await db
|
|
.updateTable("leagueUsers")
|
|
.set({
|
|
money: (eb) => eb("money", "-", possibleTransfer.value),
|
|
})
|
|
.where("leagueID", "=", league)
|
|
.where("user", "=", user)
|
|
.execute();
|
|
}
|
|
}
|
|
}
|
|
res.status(200).end("Updated Transfer");
|
|
break;
|
|
}
|
|
// Checks if the player is owned by the user
|
|
if (
|
|
(await db
|
|
.selectFrom("squad")
|
|
.selectAll()
|
|
.where("leagueID", "=", league)
|
|
.where("user", "=", user)
|
|
.where("playeruid", "=", playeruid)
|
|
.executeTakeFirst()) === undefined
|
|
) {
|
|
res.status(400).end("You do not own this player");
|
|
break;
|
|
}
|
|
// Checks if the user still has a transfer left
|
|
if (!transferLeft) {
|
|
res.status(400).end("You have no more transfers");
|
|
break;
|
|
}
|
|
// Sells the player
|
|
const playerValue = player.sale_price;
|
|
// Stores the amount that the user actually wants for the player
|
|
const actualAmount =
|
|
amount * -1 > player.sale_price ? amount * -1 : player.sale_price;
|
|
const success = await db
|
|
.insertInto("transfers")
|
|
.values({
|
|
leagueID: league,
|
|
seller: user,
|
|
buyer: -1,
|
|
playeruid: playeruid,
|
|
value: actualAmount,
|
|
max: actualAmount,
|
|
})
|
|
.execute()
|
|
.then(() => true)
|
|
.catch(() => false);
|
|
if (!success) {
|
|
res.status(400).end("Failed to sell player");
|
|
break;
|
|
}
|
|
// Checks if this transaction actually has a seller
|
|
if (actualAmount === playerValue) {
|
|
await db
|
|
.updateTable("leagueUsers")
|
|
.set((eb) => ({ money: eb("money", "+", actualAmount) }))
|
|
.where("leagueID", "=", league)
|
|
.where("user", "=", user)
|
|
.execute();
|
|
}
|
|
console.log(
|
|
`User ${user} is ${
|
|
actualAmount > player.sale_price ? "planning to sell" : "selling"
|
|
} ${playeruid} for ${actualAmount} in league ${league}`,
|
|
);
|
|
res
|
|
.status(200)
|
|
.end(
|
|
`${
|
|
actualAmount > player.sale_price
|
|
? "Planning to sell"
|
|
: "Selling"
|
|
} player for minimum of ${actualAmount / 1000000}M`,
|
|
);
|
|
break;
|
|
// Cancels the transaction
|
|
} else {
|
|
// Trys to find the transaction
|
|
const transfer = await db
|
|
.selectFrom("transfers")
|
|
.selectAll()
|
|
.where("leagueID", "=", league)
|
|
.where((eb) =>
|
|
eb.or([eb("seller", "=", user), eb("buyer", "=", user)]),
|
|
)
|
|
.where("playeruid", "=", playeruid)
|
|
.executeTakeFirst();
|
|
if (transfer === undefined) {
|
|
res.status(404).end("Transfer must exist to be cancelled");
|
|
break;
|
|
}
|
|
// Checks if it was a sale
|
|
if (transfer.seller == user) {
|
|
const sale = transfer;
|
|
// Checks if this offer was taken and if it was the seller has to give a refund
|
|
if (sale.buyer !== -1) {
|
|
if (money < sale.value) {
|
|
res
|
|
.status(400)
|
|
.end(
|
|
`You need to have ${
|
|
sale.value / 1000000
|
|
}M to cancel the transfer`,
|
|
);
|
|
break;
|
|
}
|
|
await db
|
|
.updateTable("leagueUsers")
|
|
.set((eb) => ({ money: eb("money", "-", sale.value) }))
|
|
.where("leagueID", "=", league)
|
|
.where("user", "=", user)
|
|
.execute();
|
|
}
|
|
// Removes the transaction and refunds all the money
|
|
await db
|
|
.updateTable("leagueUsers")
|
|
.set((eb) => ({ money: eb("money", "+", sale.value) }))
|
|
.where("leagueID", "=", league)
|
|
.where("user", "=", sale.buyer)
|
|
.execute();
|
|
await db
|
|
.deleteFrom("transfers")
|
|
.where("leagueID", "=", league)
|
|
.where("seller", "=", user)
|
|
.where("playeruid", "=", playeruid)
|
|
.execute();
|
|
res.status(200).end("Transfer cancelled");
|
|
console.log(
|
|
`User ${user} cancelled sale of ${playeruid} to ${sale.buyer} for ${sale.value} in league ${league}`,
|
|
);
|
|
break;
|
|
}
|
|
if (transfer.buyer == user) {
|
|
const purchase = transfer;
|
|
// Removes the canceller from the transaction and refunds them the value of the player
|
|
await db
|
|
.updateTable("leagueUsers")
|
|
.set((eb) => ({ money: eb("money", "+", player.sale_price) }))
|
|
.where("leagueID", "=", league)
|
|
.where("user", "=", user)
|
|
.execute();
|
|
|
|
await db
|
|
.updateTable("transfers")
|
|
.set({ max: purchase.value, buyer: 0 })
|
|
.where("leagueID", "=", league)
|
|
.where("buyer", "=", user)
|
|
.where("playeruid", "=", playeruid)
|
|
.execute();
|
|
|
|
await db
|
|
.deleteFrom("transfers")
|
|
.where("leagueID", "=", league)
|
|
.where("buyer", "=", 0)
|
|
.where("seller", "=", 0)
|
|
.where("playeruid", "=", playeruid)
|
|
.execute();
|
|
res.status(200).end("Transfer cancelled");
|
|
console.log(
|
|
`User ${user} cancelled purchase of ${playeruid} from ${purchase.buyer} for ${player.sale_price} in league ${league}`,
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
// This will run if something went wrong
|
|
console.log("A transfer failed to finish");
|
|
res.status(500).end("An unknown error happened");
|
|
break;
|
|
default:
|
|
res.status(405).end(`Method ${req.method} Not Allowed`);
|
|
break;
|
|
}
|
|
}
|
|
}
|