Add /api/tournament/:id/streams route (#3067)

This commit is contained in:
Josiah Glosson
2026-05-14 08:33:36 -05:00
committed by GitHub
parent 099449cbc6
commit 3b7d941d59
3 changed files with 94 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
import { sql } from "kysely";
import { jsonArrayFrom } from "kysely/helpers/sqlite";
import type { LoaderFunctionArgs } from "react-router";
import { z } from "zod";
import { db } from "~/db/sql";
import { notFoundIfFalsy, parseParams } from "~/utils/remix.server";
import { id } from "~/utils/zod";
import type { GetTournamentStreamsResponse } from "../schema";
const paramsSchema = z.object({
id,
});
export const loader = async ({ params }: LoaderFunctionArgs) => {
const { id } = parseParams({
params,
schema: paramsSchema,
});
const tournament = notFoundIfFalsy(
await db
.selectFrom("Tournament")
.select([
jsonArrayFrom(
db
.selectFrom("LiveStream")
.leftJoin(
"TournamentTeamMember",
"TournamentTeamMember.userId",
"LiveStream.userId",
)
.leftJoin(
"TournamentTeam",
"TournamentTeam.id",
"TournamentTeamMember.tournamentTeamId",
)
.select([
"LiveStream.userId",
"LiveStream.twitch",
"LiveStream.viewerCount",
])
.where("TournamentTeam.tournamentId", "=", id),
).as("playerStreams"),
jsonArrayFrom(
db
.selectFrom("LiveStream")
.select(["LiveStream.twitch", "LiveStream.viewerCount"])
.where(
sql<boolean>`"LiveStream"."twitch" IN (SELECT value FROM json_each("Tournament"."castTwitchAccounts"))`,
),
).as("castStreams"),
])
.where("Tournament.id", "=", id)
.executeTakeFirst(),
);
const playerStreams: GetTournamentStreamsResponse =
tournament?.playerStreams.map((stream) => ({
type: "PLAYER",
userId: stream.userId!,
platform: "TWITCH",
channelId: stream.twitch!,
viewerCount: stream.viewerCount!,
})) ?? [];
const castStreams: GetTournamentStreamsResponse =
tournament?.castStreams.map((stream) => ({
type: "CAST",
platform: "TWITCH",
channelId: stream.twitch!,
viewerCount: stream.viewerCount!,
})) ?? [];
const result: GetTournamentStreamsResponse = [
...playerStreams,
...castStreams,
].sort((a, b) => b.viewerCount - a.viewerCount);
return Response.json(result);
};

View File

@@ -292,6 +292,16 @@ type TournamentCastChannel = {
channelId: string;
};
/** GET /api/tournament/{tournamentId}/streams */
export type GetTournamentStreamsResponse = Array<
{
platform: "TWITCH";
channelId: string;
viewerCount: number;
} & ({ type: "PLAYER"; userId: number } | { type: "CAST" })
>;
/** GET /api/tournament-match/{matchId} */
export interface GetTournamentMatchResponse {

View File

@@ -339,6 +339,10 @@ export default [
"/tournament/:id/starting-brackets",
"features/api-public/routes/tournament.$id.starting-brackets.ts",
),
route(
"/tournament/:id/streams",
"features/api-public/routes/tournament.$id.streams.ts",
),
route(
"/tournament/:id/teams/:teamId/add-member",
"features/api-public/routes/tournament.$id.teams.$teamId.add-member.ts",