Move app to apps/web-react in pnpm workspace layout

This commit is contained in:
Kalle
2026-08-16 09:20:33 +03:00
parent 7e365ccfcf
commit bbc8ea57af
2913 changed files with 227 additions and 250 deletions

View File

@@ -0,0 +1,5 @@
import { IS_E2E_TEST_RUN } from "~/utils/e2e";
/** Should the user be able to access dev controls? Seeding & user impersonation without auth. */
export const DANGEROUS_CAN_ACCESS_DEV_CONTROLS =
process.env.NODE_ENV === "development" || IS_E2E_TEST_RUN;

View File

@@ -0,0 +1,70 @@
import {
sendModDiscordWebhook,
truncateEmbedValue,
userAdminPageLink,
userPageLink,
type WebhookUser,
} from "~/modules/discord-webhook.server";
/**
* Posts a rich embed about a user getting banned to the mod channel Discord webhook.
* Fire-and-forget (see `sendModDiscordWebhook`).
*/
export function sendUserBannedWebhook(args: {
bannedUser: WebhookUser;
bannedBy: WebhookUser;
reason: string | null;
/** When the ban ends, null when the ban has no end date */
expiresAt: Date | null;
}) {
sendModDiscordWebhook({
title: "User banned",
fields: [
{
name: "Banned user",
value: userAdminPageLink(args.bannedUser),
},
{
name: "Banned by",
value: userPageLink(args.bannedBy),
},
{
name: "Expires",
value: args.expiresAt
? `<t:${Math.floor(args.expiresAt.getTime() / 1000)}:f>`
: "No end date",
},
...(args.reason
? [
{
name: "Reason",
value: truncateEmbedValue(args.reason),
},
]
: []),
],
});
}
/**
* Posts a rich embed about a user getting unbanned to the mod channel Discord webhook.
* Fire-and-forget (see `sendModDiscordWebhook`).
*/
export function sendUserUnbannedWebhook(args: {
unbannedUser: WebhookUser;
unbannedBy: WebhookUser;
}) {
sendModDiscordWebhook({
title: "User unbanned",
fields: [
{
name: "Unbanned user",
value: userAdminPageLink(args.unbannedUser),
},
{
name: "Unbanned by",
value: userPageLink(args.unbannedBy),
},
],
});
}

View File

@@ -0,0 +1,56 @@
import { addPendingPlusTiers } from "~/features/leaderboards/core/leaderboards.server";
import * as LeaderboardRepository from "~/features/leaderboards/LeaderboardRepository.server";
import * as Seasons from "~/features/mmr/core/Seasons";
import { seasonToVotingRange } from "~/features/plus-voting/core/voting-time";
import * as PlusVotingRepository from "~/features/plus-voting/PlusVotingRepository.server";
import invariant from "~/utils/invariant";
import { userIsBanned } from "../../ban/core/banned.server";
export async function plusTiersFromVotingAndLeaderboard() {
const newMembersFromVoting =
await PlusVotingRepository.findAllPlusTiersFromLatestVoting();
const newMembersFromLeaderboard = await fromLeaderboard(newMembersFromVoting);
return [
...newMembersFromLeaderboard,
// filter to ensure that user gets their highest tier
...newMembersFromVoting.filter(
(member) =>
!newMembersFromLeaderboard.some(
(leaderboardMember) => leaderboardMember.userId === member.userId,
),
),
].filter(({ userId }) => !userIsBanned(userId));
}
async function fromLeaderboard(
newMembersFromVoting: Array<{ userId: number; plusTier: number }>,
) {
const now = new Date();
const lastCompletedSeason = Seasons.previous();
invariant(lastCompletedSeason, "No previous season found");
const currSeason = Seasons.current();
if (currSeason) {
const range = seasonToVotingRange(currSeason);
// we are in the period of a season where the season's voting
// has ended but we don't yet have the latest leaderboard results
// -> last season's results are no longer valid
if (range.endDate < now) return [];
}
const leaderboard = addPendingPlusTiers(
await LeaderboardRepository.findUserSPLeaderboard(lastCompletedSeason.nth),
newMembersFromVoting,
lastCompletedSeason.nth,
);
return leaderboard.flatMap((entry) => {
if (!entry.pendingPlusTier) return [];
return {
userId: entry.id,
plusTier: entry.pendingPlusTier,
};
});
}