new Live Scores
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
import { fetchMatchesAndTeams, fetchOdds, attachOdds } from "@/lib/feeds";
|
import { fetchMatchesAndTeams, fetchOdds, attachOdds, fetchLiveScores, applyLiveScores } from "@/lib/feeds";
|
||||||
import { computeGroupTables, computeThirdPlaceTable } from "@/lib/standings";
|
import { computeGroupTables, computeThirdPlaceTable } from "@/lib/standings";
|
||||||
import { qualifiedThirdGroups, resolveAnnexC } from "@/lib/bracket";
|
import { qualifiedThirdGroups, resolveAnnexC } from "@/lib/bracket";
|
||||||
|
|
||||||
@@ -20,6 +20,14 @@ export async function GET() {
|
|||||||
console.error("[polymarket] fetchOdds fehlgeschlagen:", err);
|
console.error("[polymarket] fetchOdds fehlgeschlagen:", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Live-Scores von worldcup26.ir (additiv, Fallback auf football-data)
|
||||||
|
try {
|
||||||
|
const liveScores = await fetchLiveScores();
|
||||||
|
matches = applyLiveScores(matches, teams, liveScores);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("[worldcup26] fetchLiveScores fehlgeschlagen:", err);
|
||||||
|
}
|
||||||
|
|
||||||
const groupTables = computeGroupTables(teams, matches);
|
const groupTables = computeGroupTables(teams, matches);
|
||||||
const groupTablesLive = computeGroupTables(teams, matches, true);
|
const groupTablesLive = computeGroupTables(teams, matches, true);
|
||||||
|
|
||||||
|
|||||||
114
lib/feeds.ts
114
lib/feeds.ts
@@ -333,4 +333,118 @@ export function attachOdds(matches: Match[], teams: Team[], odds: ParsedOdds[]):
|
|||||||
}
|
}
|
||||||
return m;
|
return m;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// worldcup26.ir: schnelle Live-Scores (additiv, Fallback auf football-data)
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
const WC26_BASE = "https://worldcup26.ir";
|
||||||
|
|
||||||
|
interface Wc26Game {
|
||||||
|
home_team_name_en?: string;
|
||||||
|
away_team_name_en?: string;
|
||||||
|
group?: string;
|
||||||
|
matchday?: string;
|
||||||
|
home_score?: string;
|
||||||
|
away_score?: string;
|
||||||
|
time_elapsed?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LiveScore {
|
||||||
|
homeName: string;
|
||||||
|
awayName: string;
|
||||||
|
group: string;
|
||||||
|
matchday: string;
|
||||||
|
homeScore: number | null;
|
||||||
|
awayScore: number | null;
|
||||||
|
status: string; // "IN_PLAY" | "FINISHED"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ruft alle Spiele von worldcup26.ir ab.
|
||||||
|
export async function fetchLiveScores(): Promise<LiveScore[]> {
|
||||||
|
const res = await fetch(`${WC26_BASE}/get/games`, {
|
||||||
|
cache: "no-store",
|
||||||
|
headers: { "User-Agent": "wm2026-board/1.0" },
|
||||||
|
signal: AbortSignal.timeout(8000),
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`worldcup26 ${res.status}`);
|
||||||
|
const data = (await res.json()) as { games: Wc26Game[] };
|
||||||
|
const games = data.games ?? [];
|
||||||
|
|
||||||
|
const scores: LiveScore[] = [];
|
||||||
|
for (const g of games) {
|
||||||
|
if (!g.home_team_name_en || !g.away_team_name_en) continue;
|
||||||
|
const hScore = parseScore(g.home_score);
|
||||||
|
const aScore = parseScore(g.away_score);
|
||||||
|
let status = "";
|
||||||
|
switch (g.time_elapsed) {
|
||||||
|
case "live": status = "IN_PLAY"; break;
|
||||||
|
case "finished": status = "FINISHED"; break;
|
||||||
|
default: continue; // notstarted → überspringen
|
||||||
|
}
|
||||||
|
// Nur anwenden, wenn mindestens ein Score vorhanden ist
|
||||||
|
if (hScore == null && aScore == null) continue;
|
||||||
|
scores.push({
|
||||||
|
homeName: g.home_team_name_en,
|
||||||
|
awayName: g.away_team_name_en,
|
||||||
|
group: g.group ?? "",
|
||||||
|
matchday: String(g.matchday ?? ""),
|
||||||
|
homeScore: hScore,
|
||||||
|
awayScore: aScore,
|
||||||
|
status,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.log("[worldcup26] spiele:", scores.length);
|
||||||
|
return scores;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseScore(s: string | undefined): number | null {
|
||||||
|
if (!s || s === "null") return null;
|
||||||
|
const n = Number(s);
|
||||||
|
return Number.isFinite(n) ? n : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wendet worldcup26-Live-Scores auf football-data-Matches an.
|
||||||
|
// Matching über normalisierte Teamnamen + group + matchday.
|
||||||
|
export function applyLiveScores(
|
||||||
|
matches: Match[], teams: Team[], liveScores: LiveScore[],
|
||||||
|
): Match[] {
|
||||||
|
// Build lookup: normName(home)::normName(away)::group::matchday → match
|
||||||
|
// Für Group-Phase ist die Paarung eindeutig (jedes Paar spielt 1x).
|
||||||
|
const byPair = new Map<string, Match>();
|
||||||
|
for (const m of matches) {
|
||||||
|
if (m.group == null) continue; // nur Gruppenphase
|
||||||
|
if (!m.homeTeamId || !m.awayTeamId) continue;
|
||||||
|
const ht = teams.find((t) => t.id === m.homeTeamId);
|
||||||
|
const at = teams.find((t) => t.id === m.awayTeamId);
|
||||||
|
if (!ht || !at) continue;
|
||||||
|
const hn = normName(ht.name);
|
||||||
|
const an = normName(at.name);
|
||||||
|
// Beide Richtungen
|
||||||
|
byPair.set(`${hn}::${an}::${m.group}`, m);
|
||||||
|
byPair.set(`${an}::${hn}::${m.group}`, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = [...matches];
|
||||||
|
let applied = 0;
|
||||||
|
for (const ls of liveScores) {
|
||||||
|
const hn = normName(ls.homeName);
|
||||||
|
const an = normName(ls.awayName);
|
||||||
|
const key = `${hn}::${an}::${ls.group}`;
|
||||||
|
const fdMatch = byPair.get(key);
|
||||||
|
if (!fdMatch) continue;
|
||||||
|
|
||||||
|
const idx = result.findIndex((m) => m.id === fdMatch.id);
|
||||||
|
if (idx < 0) continue;
|
||||||
|
|
||||||
|
result[idx] = {
|
||||||
|
...result[idx],
|
||||||
|
homeScore: ls.homeScore ?? result[idx].homeScore,
|
||||||
|
awayScore: ls.awayScore ?? result[idx].awayScore,
|
||||||
|
status: ls.status as Match["status"],
|
||||||
|
};
|
||||||
|
applied++;
|
||||||
|
}
|
||||||
|
if (applied > 0) console.log("[worldcup26] auf matches angewandt:", applied);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user