Files
vuelato/server/api/flight-info.get.ts
Alejandro Martinez b8906efc80
Some checks failed
ci / ci (22, ubuntu-latest) (push) Has been cancelled
Initial commit: Vuelato - buscador de vuelos
Nuxt 4 + Supabase + Flightics API. Incluye búsqueda de vuelos,
inspiraciones, watchlist, tracking de precios y mapa interactivo.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:37:06 +02:00

101 lines
3.3 KiB
TypeScript

export default defineCachedEventHandler(async (event) => {
const { flightno } = getQuery(event)
if (!flightno || typeof flightno !== 'string') {
throw createError({ statusCode: 400, message: 'flightno is required' })
}
const code = flightno.replace(/\s/g, '').toUpperCase()
const fr24Url = `https://www.flightradar24.com/data/flights/${code.toLowerCase()}`
// FR24 live feed
const data = await $fetch<any>(`https://data-live.flightradar24.com/zones/fcgi/feed.js`, {
query: { flightno: code, faa: 1, satellite: 1, mlat: 1, flarm: 1, adsb: 1, gnd: 1, air: 1, vehicles: 0, estimated: 1, gliders: 0 },
headers: {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
'Accept': 'application/json'
}
}).catch(() => null)
if (!data) return { found: false, fr24Url }
// Parse flight entries (skip metadata keys)
const flights = Object.entries(data)
.filter(([key]) => !['full_count', 'version', 'stats'].includes(key))
.map(([id, val]: [string, any]) => {
if (!Array.isArray(val) || val.length < 18) return null
return {
fr24Id: id,
icao24: val[0],
lat: val[1],
lon: val[2],
heading: val[3],
altitude: val[4],
speed: val[5],
squawk: val[6],
aircraft: val[8],
registration: val[9],
timestamp: val[10],
origin: val[11],
destination: val[12],
flightNumber: val[13],
onGround: val[14] === 1,
verticalSpeed: val[15],
callsign: val[16],
airline: val[18]
}
})
.filter((f): f is NonNullable<typeof f> => f != null && (f.lat !== 0 || f.lon !== 0 || f.aircraft != null))
if (flights.length === 0) return { found: false, fr24Url }
const flight = flights[0]
// Get detail for richer data
let detail: any = null
if (flight.fr24Id) {
detail = await $fetch<any>(`https://data-live.flightradar24.com/clickhandler/`, {
query: { version: '1.5', flight: flight.fr24Id },
headers: {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36'
}
}).catch(() => null)
}
// Determine status
let status = 'Programado'
if (detail?.status?.text) {
status = detail.status.text
} else if (flight.altitude > 0 && !flight.onGround) {
status = 'En vuelo'
} else if (flight.onGround && flight.speed > 5) {
status = 'En tierra (taxiing)'
} else if (flight.onGround) {
status = 'En tierra'
}
return {
found: true,
fr24Url,
flight: {
flightNumber: flight.flightNumber || code,
callsign: flight.callsign,
aircraft: detail?.aircraft?.model?.text || flight.aircraft || null,
aircraftCode: flight.aircraft,
registration: flight.registration,
airline: detail?.airline?.name || flight.airline || null,
origin: flight.origin,
destination: flight.destination,
lat: flight.lat,
lon: flight.lon,
altitude: flight.altitude,
speed: flight.speed,
heading: flight.heading,
onGround: flight.onGround,
verticalSpeed: flight.verticalSpeed,
status,
departureDelay: detail?.time?.historical?.delay?.departure ?? null,
arrivalDelay: detail?.time?.historical?.delay?.arrival ?? null
}
}
}, { maxAge: 60 * 5 }) // Cache 5 min