mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-03-21 18:04:39 -05:00
129 lines
3.7 KiB
TypeScript
129 lines
3.7 KiB
TypeScript
import type { ActionFunction } from "react-router";
|
|
import { redirect } from "react-router";
|
|
import * as AdminRepository from "~/features/admin/AdminRepository.server";
|
|
import { requireUser } from "~/features/auth/core/user.server";
|
|
import { refreshBannedCache } from "~/features/ban/core/banned.server";
|
|
import * as Seasons from "~/features/mmr/core/Seasons";
|
|
import * as SQGroupRepository from "~/features/sendouq/SQGroupRepository.server";
|
|
import { giveTrust } from "~/features/tournament/queries/giveTrust.server";
|
|
import * as UserRepository from "~/features/user-page/UserRepository.server";
|
|
import invariant from "~/utils/invariant";
|
|
import { errorToastIfFalsy, parseRequestPayload } from "~/utils/remix.server";
|
|
import { assertUnreachable } from "~/utils/types";
|
|
import {
|
|
SENDOUQ_LOOKING_PAGE,
|
|
SENDOUQ_PREPARING_PAGE,
|
|
SUSPENDED_PAGE,
|
|
} from "~/utils/urls";
|
|
import { refreshSendouQInstance, SendouQ } from "../core/SendouQ.server";
|
|
import { JOIN_CODE_SEARCH_PARAM_KEY } from "../q-constants";
|
|
import { frontPageSchema } from "../q-schemas.server";
|
|
import { userCanJoinQueueAt } from "../q-utils";
|
|
|
|
export const action: ActionFunction = async ({ request }) => {
|
|
const user = requireUser();
|
|
const data = await parseRequestPayload({
|
|
request,
|
|
schema: frontPageSchema,
|
|
});
|
|
|
|
switch (data._action) {
|
|
case "JOIN_QUEUE": {
|
|
await validateCanJoinQ(user);
|
|
|
|
await SQGroupRepository.createGroup({
|
|
status: data.direct === "true" ? "ACTIVE" : "PREPARING",
|
|
userId: user.id,
|
|
});
|
|
|
|
await refreshSendouQInstance();
|
|
|
|
return redirect(
|
|
data.direct === "true" ? SENDOUQ_LOOKING_PAGE : SENDOUQ_PREPARING_PAGE,
|
|
);
|
|
}
|
|
case "JOIN_TEAM_WITH_TRUST":
|
|
case "JOIN_TEAM": {
|
|
await validateCanJoinQ(user);
|
|
|
|
const code = new URL(request.url).searchParams.get(
|
|
JOIN_CODE_SEARCH_PARAM_KEY,
|
|
);
|
|
|
|
const groupInvitedTo =
|
|
code && user ? SendouQ.findGroupByInviteCode(code) : undefined;
|
|
errorToastIfFalsy(
|
|
groupInvitedTo,
|
|
"Invite code doesn't match any active team",
|
|
);
|
|
|
|
await SQGroupRepository.addMember(groupInvitedTo.id, {
|
|
userId: user.id,
|
|
role: "MANAGER",
|
|
});
|
|
|
|
if (data._action === "JOIN_TEAM_WITH_TRUST") {
|
|
const owner = groupInvitedTo.members.find((m) => m.role === "OWNER");
|
|
invariant(owner, "Owner not found");
|
|
|
|
giveTrust({
|
|
trustGiverUserId: user.id,
|
|
trustReceiverUserId: owner.id,
|
|
});
|
|
}
|
|
|
|
await refreshSendouQInstance();
|
|
|
|
return redirect(
|
|
groupInvitedTo.status === "PREPARING"
|
|
? SENDOUQ_PREPARING_PAGE
|
|
: SENDOUQ_LOOKING_PAGE,
|
|
);
|
|
}
|
|
case "ADD_FRIEND_CODE": {
|
|
errorToastIfFalsy(
|
|
!(await UserRepository.currentFriendCodeByUserId(user.id)),
|
|
"Friend code already set",
|
|
);
|
|
|
|
const isTakenFriendCode = (
|
|
await UserRepository.allCurrentFriendCodes()
|
|
).has(data.friendCode);
|
|
|
|
await UserRepository.insertFriendCode({
|
|
userId: user.id,
|
|
friendCode: data.friendCode,
|
|
submitterUserId: user.id,
|
|
});
|
|
|
|
if (isTakenFriendCode) {
|
|
await AdminRepository.banUser({
|
|
userId: user.id,
|
|
banned: 1,
|
|
bannedReason:
|
|
"[automatic ban] This friend code is already in use by some other account. Please contact staff on our Discord helpdesk for resolution including merging accounts.",
|
|
bannedByUserId: null,
|
|
});
|
|
|
|
await refreshBannedCache();
|
|
|
|
throw redirect(SUSPENDED_PAGE);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
default: {
|
|
assertUnreachable(data);
|
|
}
|
|
}
|
|
};
|
|
|
|
async function validateCanJoinQ(user: { id: number; discordId: string }) {
|
|
const friendCode = await UserRepository.currentFriendCodeByUserId(user.id);
|
|
errorToastIfFalsy(friendCode, "No friend code");
|
|
const canJoinQueue = userCanJoinQueueAt(user, friendCode) === "NOW";
|
|
|
|
errorToastIfFalsy(Seasons.current(), "Season is not active");
|
|
errorToastIfFalsy(canJoinQueue, "Can't join queue right now");
|
|
}
|