import { eq } from "drizzle-orm"; import * as schema from "~/database/schema"; import type { database } from "~/database/context"; import { findDiscordIdsByUserIds } from "~/models/account"; import { sendPickAnnouncementNotification } from "~/services/discord"; type DraftSlot = { teamId: string; draftOrder: number }; // Inline snake-draft pick calculation — mirrors calculatePickInfo in draft-utils.ts // without creating a circular import (draft-utils imports this module). function pickInRoundFor(pickNumber: number, teamCount: number): number { const round = Math.ceil(pickNumber / teamCount); const rawPickInRound = ((pickNumber - 1) % teamCount) + 1; const isOddRound = round % 2 === 1; const teamIndex = isOddRound ? rawPickInRound - 1 : teamCount - rawPickInRound; return teamIndex + 1; } export async function notifyPickMadeOnDiscord(params: { seasonId: string; leagueId: string; pickedTeamName: string; participantName: string; sportName: string; pickNumber: number; round: number; pickInRound: number; isDraftComplete: boolean; totalTeams: number; draftSlots: DraftSlot[]; db: ReturnType; }): Promise { const { seasonId, leagueId, pickedTeamName, participantName, sportName, pickNumber, round, pickInRound, isDraftComplete, totalTeams, draftSlots, db, } = params; const league = await db.query.leagues.findFirst({ where: eq(schema.leagues.id, leagueId), }); if (!league?.discordWebhookUrl || !league.discordPicksAnnouncementEnabled) return; const appUrl = process.env.APP_URL ?? "https://brackt.com"; const draftUrl = `${appUrl}/leagues/${leagueId}/draft/${seasonId}`; let nextTeamName: string | undefined; let nextOwnerDiscordId: string | undefined; if (!isDraftComplete) { // Read currentPickNumber fresh from DB so we see the post-autodraft-chain state, // matching the same guarantee sendOnTheClockEmail provides. const freshSeason = await db.query.seasons.findFirst({ where: eq(schema.seasons.id, seasonId), }); if (freshSeason) { const nextPickInRound = pickInRoundFor(freshSeason.currentPickNumber ?? 1, totalTeams); const nextSlot = draftSlots.find((s) => s.draftOrder === nextPickInRound); if (nextSlot) { const nextTeam = await db.query.teams.findFirst({ where: eq(schema.teams.id, nextSlot.teamId), }); if (nextTeam) { nextTeamName = nextTeam.name; if (nextTeam.ownerId) { const owner = await db.query.users.findFirst({ where: eq(schema.users.id, nextTeam.ownerId), }); if (owner?.discordPingEnabled) { const discordIds = await findDiscordIdsByUserIds([owner.id]); nextOwnerDiscordId = discordIds.get(owner.id); } } } } } } await sendPickAnnouncementNotification({ webhookUrl: league.discordWebhookUrl, draftUrl, pickNumber, round, pickInRound, pickedTeamName, participantName, sportName, nextTeamName, nextOwnerDiscordId, isDraftComplete, }); }