mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-03-21 18:04:39 -05:00
Expiring chat codes
This commit is contained in:
parent
b9486c4f03
commit
1edb2809b5
|
|
@ -1,5 +1,52 @@
|
|||
import { sub } from "date-fns";
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { datePlaceholder, resolveDatePlaceholders } from "./chat-utils";
|
||||
import {
|
||||
chatAccessible,
|
||||
datePlaceholder,
|
||||
resolveDatePlaceholders,
|
||||
} from "./chat-utils";
|
||||
|
||||
describe("chatCodeVisible", () => {
|
||||
test("visible when within expiration window", () => {
|
||||
const result = chatAccessible({
|
||||
isStaff: false,
|
||||
expiresAfterDays: 1,
|
||||
comparedTo: new Date(),
|
||||
});
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
test("not visible when past expiration window", () => {
|
||||
const result = chatAccessible({
|
||||
isStaff: false,
|
||||
expiresAfterDays: 1,
|
||||
comparedTo: sub(new Date(), { days: 3 }),
|
||||
});
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
test("staff gets 7 extra days", () => {
|
||||
const result = chatAccessible({
|
||||
isStaff: true,
|
||||
expiresAfterDays: 1,
|
||||
comparedTo: sub(new Date(), { days: 5 }),
|
||||
});
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
test("staff extra days are not infinite", () => {
|
||||
const result = chatAccessible({
|
||||
isStaff: true,
|
||||
expiresAfterDays: 1,
|
||||
comparedTo: sub(new Date(), { days: 10 }),
|
||||
});
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("datePlaceholder", () => {
|
||||
test("returns correctly formatted placeholder string", () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,20 @@
|
|||
import { differenceInDays } from "date-fns";
|
||||
import type { ChatMessage } from "./chat-types";
|
||||
|
||||
const STAFF_EXTRA_DAYS = 7;
|
||||
|
||||
export function chatAccessible(args: {
|
||||
isStaff: boolean;
|
||||
expiresAfterDays: number;
|
||||
comparedTo: Date;
|
||||
}): boolean {
|
||||
const extraDays = args.isStaff ? STAFF_EXTRA_DAYS : 0;
|
||||
return (
|
||||
differenceInDays(new Date(), args.comparedTo) <=
|
||||
args.expiresAfterDays + extraDays
|
||||
);
|
||||
}
|
||||
|
||||
const DATE_PLACEHOLDER_PATTERN = /\{\{date:(\d+)\}\}/g;
|
||||
|
||||
export function datePlaceholder(date: Date): string {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import * as React from "react";
|
||||
import type { ChatContextValue } from "./chat-provider-types";
|
||||
|
||||
// xxx: think how chats should expire in relation to chatCode getting returned from loaders etc.
|
||||
|
||||
export const ChatContext = React.createContext<ChatContextValue | null>(null);
|
||||
|
||||
export function useChatContext(): ChatContextValue | null {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import type { LoaderFunctionArgs } from "react-router";
|
||||
import { chatAccessible } from "~/features/chat/chat-utils";
|
||||
import { tournamentDataCached } from "~/features/tournament-bracket/core/Tournament.server";
|
||||
import * as UserRepository from "~/features/user-page/UserRepository.server";
|
||||
import { databaseTimestampToDate } from "~/utils/dates";
|
||||
import { notFoundIfFalsy } from "../../../utils/remix.server";
|
||||
import {
|
||||
type AuthenticatedUser,
|
||||
|
|
@ -29,7 +31,12 @@ export const loader = async ({ params }: LoaderFunctionArgs) => {
|
|||
return {
|
||||
post,
|
||||
chatCode:
|
||||
user.roles.includes("STAFF") || participantIds.includes(user.id)
|
||||
(user.roles.includes("STAFF") || participantIds.includes(user.id)) &&
|
||||
chatAccessible({
|
||||
isStaff: user.roles.includes("STAFF"),
|
||||
expiresAfterDays: 1,
|
||||
comparedTo: databaseTimestampToDate(Scrim.getStartTime(post)),
|
||||
})
|
||||
? post.chatCode
|
||||
: undefined,
|
||||
anyUserPrefersNoScreen:
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import type { LoaderFunctionArgs } from "react-router";
|
||||
import { getUser } from "~/features/auth/core/user.server";
|
||||
import { chatAccessible } from "~/features/chat/chat-utils";
|
||||
import { SendouQ } from "~/features/sendouq/core/SendouQ.server";
|
||||
import * as PrivateUserNoteRepository from "~/features/sendouq/PrivateUserNoteRepository.server";
|
||||
import { reportedWeaponsToArrayOfArrays } from "~/features/sendouq-match/core/reported-weapons.server";
|
||||
import * as ReportedWeaponRepository from "~/features/sendouq-match/ReportedWeaponRepository.server";
|
||||
import * as SQMatchRepository from "~/features/sendouq-match/SQMatchRepository.server";
|
||||
import { databaseTimestampToDate } from "~/utils/dates";
|
||||
import { notFoundIfFalsy, parseParams } from "~/utils/remix.server";
|
||||
import { qMatchPageParamsSchema } from "../q-match-schemas";
|
||||
|
||||
|
|
@ -44,7 +46,13 @@ export const loader = async ({ params }: LoaderFunctionArgs) => {
|
|||
: null,
|
||||
rawReportedWeapons,
|
||||
chatCode:
|
||||
user?.roles.includes("STAFF") || (user && matchUsers.includes(user.id))
|
||||
(user?.roles.includes("STAFF") ||
|
||||
(user && matchUsers.includes(user.id))) &&
|
||||
chatAccessible({
|
||||
isStaff: user?.roles.includes("STAFF") ?? false,
|
||||
expiresAfterDays: 1,
|
||||
comparedTo: databaseTimestampToDate(matchUnmapped.createdAt),
|
||||
})
|
||||
? match.chatCode
|
||||
: null,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import cachified from "@epic-web/cachified";
|
|||
import type { LoaderFunctionArgs } from "react-router";
|
||||
import { getUser } from "~/features/auth/core/user.server";
|
||||
import * as ChatSystemMessage from "~/features/chat/ChatSystemMessage.server";
|
||||
import { chatAccessible } from "~/features/chat/chat-utils";
|
||||
import * as TournamentRepository from "~/features/tournament/TournamentRepository.server";
|
||||
import * as TournamentTeamRepository from "~/features/tournament/TournamentTeamRepository.server";
|
||||
import * as UserRepository from "~/features/user-page/UserRepository.server";
|
||||
|
|
@ -125,6 +126,18 @@ export const loader = async ({ params }: LoaderFunctionArgs) => {
|
|||
tournament.isOrganizerOrStreamer(user) ||
|
||||
match.players.some((p) => p.id === user?.id);
|
||||
|
||||
const isStaff = user?.roles.includes("STAFF") ?? false;
|
||||
const chatCodeExpired = tournament.ctx.isFinalized
|
||||
? true
|
||||
: !chatAccessible({
|
||||
isStaff,
|
||||
expiresAfterDays: 90,
|
||||
comparedTo: tournament.ctx.startTime,
|
||||
});
|
||||
|
||||
const visibleChatCode =
|
||||
shouldSeeChat && !chatCodeExpired ? match.chatCode : undefined;
|
||||
|
||||
return {
|
||||
match: shouldSeeChat ? match : { ...match, chatCode: undefined },
|
||||
results,
|
||||
|
|
@ -132,6 +145,6 @@ export const loader = async ({ params }: LoaderFunctionArgs) => {
|
|||
matchIsOver,
|
||||
endedEarly,
|
||||
noScreen,
|
||||
chatCode: shouldSeeChat ? match.chatCode : undefined,
|
||||
chatCode: visibleChatCode,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user