Implement results sync from football-data.org
This commit is contained in:
@@ -1,4 +1,29 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
import { calculatePoints } from '@/lib/scoring'
|
||||
|
||||
interface FDTeam {
|
||||
tla: string
|
||||
name: string
|
||||
}
|
||||
|
||||
interface FDScore {
|
||||
fullTime: { home: number | null; away: number | null }
|
||||
}
|
||||
|
||||
interface FDMatch {
|
||||
id: number
|
||||
status: 'TIMED' | 'SCHEDULED' | 'IN_PLAY' | 'PAUSED' | 'FINISHED' | 'POSTPONED' | 'SUSPENDED' | 'CANCELLED'
|
||||
homeTeam: FDTeam
|
||||
awayTeam: FDTeam
|
||||
score: FDScore
|
||||
}
|
||||
|
||||
function mapStatus(s: FDMatch['status']): 'SCHEDULED' | 'LIVE' | 'FINISHED' {
|
||||
if (s === 'FINISHED') return 'FINISHED'
|
||||
if (s === 'IN_PLAY' || s === 'PAUSED') return 'LIVE'
|
||||
return 'SCHEDULED'
|
||||
}
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const { searchParams } = new URL(req.url)
|
||||
@@ -8,15 +33,80 @@ export async function POST(req: Request) {
|
||||
return NextResponse.json({ error: 'No autorizado' }, { status: 401 })
|
||||
}
|
||||
|
||||
const url = process.env.RESULTS_API_URL
|
||||
if (!url) {
|
||||
return NextResponse.json({ error: 'RESULTS_API_URL no configurada' }, { status: 400 })
|
||||
const apiUrl = process.env.RESULTS_API_URL
|
||||
const apiKey = process.env.RESULTS_API_KEY
|
||||
if (!apiUrl || !apiKey) {
|
||||
return NextResponse.json({ error: 'RESULTS_API_URL o RESULTS_API_KEY no configuradas' }, { status: 400 })
|
||||
}
|
||||
|
||||
// TODO: implementar cuando se provea la URL del sitio externo
|
||||
// const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.RESULTS_API_KEY}` } })
|
||||
// const data = await res.json()
|
||||
// ... procesar y actualizar partidos
|
||||
|
||||
return NextResponse.json({ ok: true, message: 'Endpoint listo. Configurar RESULTS_API_URL para activar sync.' })
|
||||
let fdMatches: FDMatch[]
|
||||
try {
|
||||
const res = await fetch(apiUrl, {
|
||||
headers: { 'X-Auth-Token': apiKey },
|
||||
cache: 'no-store',
|
||||
})
|
||||
if (!res.ok) {
|
||||
return NextResponse.json({ error: `Error de API externa: ${res.status}` }, { status: 502 })
|
||||
}
|
||||
const data = await res.json()
|
||||
fdMatches = data.matches ?? []
|
||||
} catch {
|
||||
return NextResponse.json({ error: 'No se pudo conectar con la API externa' }, { status: 502 })
|
||||
}
|
||||
|
||||
// Precargar equipos una sola vez
|
||||
const teams = await prisma.team.findMany()
|
||||
const teamByShortName = Object.fromEntries(teams.map(t => [t.shortName, t]))
|
||||
|
||||
let updated = 0
|
||||
let skipped = 0
|
||||
|
||||
for (const fdMatch of fdMatches) {
|
||||
const newStatus = mapStatus(fdMatch.status)
|
||||
if (newStatus === 'SCHEDULED') { skipped++; continue }
|
||||
|
||||
const homeTla = fdMatch.homeTeam?.tla
|
||||
const awayTla = fdMatch.awayTeam?.tla
|
||||
if (!homeTla || !awayTla) { skipped++; continue }
|
||||
|
||||
const homeTeam = teamByShortName[homeTla]
|
||||
const awayTeam = teamByShortName[awayTla]
|
||||
if (!homeTeam || !awayTeam) { skipped++; continue }
|
||||
|
||||
const match = await prisma.match.findFirst({
|
||||
where: { homeTeamId: homeTeam.id, awayTeamId: awayTeam.id },
|
||||
})
|
||||
if (!match) { skipped++; continue }
|
||||
|
||||
// Evitar re-procesar partidos ya finalizados
|
||||
if (match.status === 'FINISHED' && newStatus === 'FINISHED') { skipped++; continue }
|
||||
|
||||
const homeScore = fdMatch.score.fullTime.home
|
||||
const awayScore = fdMatch.score.fullTime.away
|
||||
|
||||
const updatedMatch = await prisma.match.update({
|
||||
where: { id: match.id },
|
||||
data: {
|
||||
status: newStatus,
|
||||
...(homeScore !== null && { homeScore }),
|
||||
...(awayScore !== null && { awayScore }),
|
||||
},
|
||||
})
|
||||
|
||||
if (newStatus === 'FINISHED' && homeScore !== null && awayScore !== null) {
|
||||
const predictions = await prisma.prediction.findMany({ where: { matchId: match.id } })
|
||||
await Promise.all(
|
||||
predictions.map(p =>
|
||||
prisma.prediction.update({
|
||||
where: { id: p.id },
|
||||
data: { points: calculatePoints(p.result as 'HOME' | 'DRAW' | 'AWAY', homeScore, awayScore) },
|
||||
})
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
updated++
|
||||
}
|
||||
|
||||
return NextResponse.json({ ok: true, updated, skipped, total: fdMatches.length })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user