diff --git a/app/routes/api/draft.force-manual-pick.ts b/app/routes/api/draft.force-manual-pick.ts index 3ac2fd1..5752f51 100644 --- a/app/routes/api/draft.force-manual-pick.ts +++ b/app/routes/api/draft.force-manual-pick.ts @@ -8,6 +8,7 @@ import { getDraftPicksWithSports, getTeamDraftPicksWithSports } from "~/models/d import { getParticipantsForSeasonWithSports } from "~/models/season-participant"; import { getSeasonSportsSimple } from "~/models/season-sport"; import { calculatePickInfo, checkAndTriggerNextAutodraft } from "~/models/draft-utils"; +import { getTeamForPick } from "~/lib/draft-order"; import { enqueuePickNotification } from "~/services/discord"; import { notifyPickMadeOnDiscord } from "~/services/draft-discord.server"; import { logCommissionerAction } from "~/models/audit-log"; @@ -240,7 +241,7 @@ export async function action(args: ActionFunctionArgs) { // Emit socket event try { const io = getSocketIO(); - const team = draftSlots.find((slot) => slot.team.id === teamId)?.team; + const team = expectedDraftSlot.team; io.to(`draft-${seasonId}`).emit("pick-made", { pick: { @@ -264,16 +265,13 @@ export async function action(args: ActionFunctionArgs) { logger.error("Socket.IO error:", error); } - const pickedTeam = draftSlots.find((slot) => slot.team.id === teamId)?.team; - // Announce pick on Discord - const { pickInRound: nextPickInRound } = calculatePickInfo(nextPickNumber, totalTeams); - const nextSlot = !isDraftComplete ? draftSlots.find((s) => s.draftOrder === nextPickInRound) : undefined; + const nextSlot = !isDraftComplete ? getTeamForPick(nextPickNumber, draftSlots) : undefined; enqueuePickNotification(season.leagueId, () => notifyPickMadeOnDiscord({ seasonId, leagueId: season.leagueId, - pickedTeamName: pickedTeam?.name ?? teamId, + pickedTeamName: expectedDraftSlot.team.name, participantName: participant.name, sportName: participant.sportsSeason.sport.name, pickNumber, @@ -295,7 +293,7 @@ export async function action(args: ActionFunctionArgs) { details: { pickNumber, teamId, - teamName: pickedTeam?.name ?? teamId, + teamName: expectedDraftSlot.team.name, participantId, participantName: participant.name, }, diff --git a/app/routes/api/draft.make-pick.ts b/app/routes/api/draft.make-pick.ts index 1ecb368..032a43e 100644 --- a/app/routes/api/draft.make-pick.ts +++ b/app/routes/api/draft.make-pick.ts @@ -1,4 +1,5 @@ import { auth } from "~/lib/auth.server"; +import { getTeamForPick } from "~/lib/draft-order"; import { database } from "~/database/context"; import * as schema from "~/database/schema"; import { eq, and, sql } from "drizzle-orm"; @@ -306,8 +307,7 @@ export async function action(args: ActionFunctionArgs) { // Announce before triggering the chain so Discord messages arrive in pick-number // order. If the chain ran first, chained picks would announce before this one. - const { pickInRound: nextPickInRound } = calculatePickInfo(nextPickNumber, totalTeams); - const nextSlot = !isDraftComplete ? draftSlots.find((s) => s.draftOrder === nextPickInRound) : undefined; + const nextSlot = !isDraftComplete ? getTeamForPick(nextPickNumber, draftSlots) : undefined; enqueuePickNotification(season.leagueId, () => notifyPickMadeOnDiscord({ seasonId, diff --git a/app/services/discord.ts b/app/services/discord.ts index ef8e1a0..016c064 100644 --- a/app/services/discord.ts +++ b/app/services/discord.ts @@ -20,7 +20,11 @@ const leagueChains = new Map>(); export function enqueuePickNotification(leagueId: string, fn: () => Promise): void { const prev = leagueChains.get(leagueId) ?? Promise.resolve(); - leagueChains.set(leagueId, prev.then(() => fn().catch(() => {}))); + const next = prev.then(() => fn().catch(() => {})); + leagueChains.set(leagueId, next); + // Clean up the map entry once the chain settles, but only if no newer pick + // was enqueued after this one (reference equality guards against that race). + next.then(() => { if (leagueChains.get(leagueId) === next) leagueChains.delete(leagueId); }); } export async function sendDiscordWebhook(