70 lines
2.5 KiB
TypeScript
70 lines
2.5 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { fetchMatchesAndTeams, fetchOdds, attachOdds, attachKOOdds, fetchFifaScores, applyFifaScores, assignKONumbersBySlots } from "@/lib/feeds";
|
|
import { computeGroupTables, computeThirdPlaceTable } from "@/lib/standings";
|
|
import { qualifiedThirdGroups, resolveAnnexC } from "@/lib/bracket";
|
|
import { securelyQualifiedThirdTeams } from "@/lib/third-place-security";
|
|
|
|
// Diese Route wird vom Frontend gepollt. Sie ist der einzige Ort, der die
|
|
// Upstream-Feeds berührt — gecacht, damit Rate Limits eingehalten werden.
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export async function GET() {
|
|
try {
|
|
const { matches: rawMatches, teams } = await fetchMatchesAndTeams();
|
|
|
|
// Odds sind optional: fällt der Polymarket-Call aus, liefern wir trotzdem.
|
|
let matches = rawMatches;
|
|
let odds: Awaited<ReturnType<typeof fetchOdds>> | null = null;
|
|
try {
|
|
odds = await fetchOdds();
|
|
matches = attachOdds(rawMatches, teams, odds);
|
|
} catch (err) {
|
|
console.error("[polymarket] fetchOdds fehlgeschlagen:", err);
|
|
}
|
|
|
|
// FIFA-Live-Scores (additiv, Fallback auf football-data)
|
|
assignKONumbersBySlots(matches, teams);
|
|
|
|
if (odds) {
|
|
matches = attachKOOdds(matches, teams, odds);
|
|
}
|
|
|
|
try {
|
|
const fifaData = await fetchFifaScores();
|
|
matches = applyFifaScores(matches, teams, fifaData);
|
|
} catch (err) {
|
|
console.warn("[fifa] Scores fehlgeschlagen:", err instanceof Error ? err.message : err);
|
|
}
|
|
|
|
const groupTables = computeGroupTables(teams, matches);
|
|
const groupTablesLive = computeGroupTables(teams, matches, true);
|
|
|
|
const normalizedMatches = matches.map((m) => ({ ...m, prob: m.prob ?? null }));
|
|
|
|
const thirdTable = computeThirdPlaceTable(groupTablesLive);
|
|
const qGroups = qualifiedThirdGroups(thirdTable);
|
|
const annex = qGroups.length === 8 ? resolveAnnexC(qGroups) : null;
|
|
|
|
// Sichere Drittplatzierte (Team-IDs, deren Top-8-Platz mathematisch feststeht)
|
|
const secureThirdTeams = securelyQualifiedThirdTeams(matches, teams);
|
|
|
|
return NextResponse.json({
|
|
updatedAt: new Date().toISOString(),
|
|
teams,
|
|
matches: normalizedMatches,
|
|
groupTables,
|
|
groupTablesLive,
|
|
thirdTable,
|
|
secureThirdTeams: [...secureThirdTeams],
|
|
annexAssignment: annex,
|
|
annexResolved: annex != null,
|
|
});
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : "unbekannter Fehler";
|
|
return NextResponse.json(
|
|
{ error: "Feed nicht erreichbar", detail: message },
|
|
{ status: 502 },
|
|
);
|
|
}
|
|
}
|