fix: report adsb unavailable state as degraded
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
// ADS-B Exchange — Unfiltered Flight Tracking (including Military)
|
||||
// Unlike FlightRadar24/FlightAware, ADS-B Exchange does NOT filter military aircraft.
|
||||
// Public feed access varies; RapidAPI tier available for programmatic use.
|
||||
// This module attempts the public endpoints and falls back to a documented stub.
|
||||
// This module reports explicit disabled/degraded state instead of making
|
||||
// unavailable aircraft data look live.
|
||||
|
||||
import { safeFetch } from '../utils/fetch.mjs';
|
||||
|
||||
@@ -140,6 +141,7 @@ async function fetchViaRapidApi(apiKey) {
|
||||
// Get all military aircraft
|
||||
const data = await safeFetch(`${ENDPOINTS.rapidApi}/mil`, {
|
||||
timeout: 20000,
|
||||
source: 'adsb-rapidapi',
|
||||
headers: {
|
||||
'X-RapidAPI-Key': apiKey,
|
||||
'X-RapidAPI-Host': 'adsbexchange-com1.p.rapidapi.com',
|
||||
@@ -151,21 +153,26 @@ async function fetchViaRapidApi(apiKey) {
|
||||
|
||||
// Attempt to fetch from public feed
|
||||
async function fetchPublicFeed() {
|
||||
const data = await safeFetch(ENDPOINTS.publicFeed, { timeout: 15000 });
|
||||
const data = await safeFetch(ENDPOINTS.publicFeed, { timeout: 15000, source: 'adsb-public' });
|
||||
return data;
|
||||
}
|
||||
|
||||
// Get military aircraft from available sources
|
||||
export async function getMilitaryAircraft(apiKey) {
|
||||
async function getMilitaryAircraftResult(apiKey) {
|
||||
const failures = [];
|
||||
|
||||
// Try RapidAPI first if key available
|
||||
if (apiKey) {
|
||||
const data = await fetchViaRapidApi(apiKey);
|
||||
if (data && !data.error) {
|
||||
const aircraft = data.ac || data.aircraft || [];
|
||||
if (Array.isArray(aircraft)) {
|
||||
return aircraft.map(classifyAircraft).filter(a => a.isMilitary);
|
||||
return {
|
||||
provider: 'rapidapi',
|
||||
aircraft: aircraft.map(classifyAircraft).filter(a => a.isMilitary),
|
||||
};
|
||||
}
|
||||
}
|
||||
failures.push({ provider: 'rapidapi', error: data?.error || 'RapidAPI returned an unsupported payload' });
|
||||
}
|
||||
|
||||
// Try public feed
|
||||
@@ -173,11 +180,21 @@ export async function getMilitaryAircraft(apiKey) {
|
||||
if (pubData && !pubData.error) {
|
||||
const aircraft = pubData.ac || pubData.aircraft || pubData.states || [];
|
||||
if (Array.isArray(aircraft)) {
|
||||
return aircraft.map(classifyAircraft).filter(a => a.isMilitary);
|
||||
return {
|
||||
provider: 'public-feed',
|
||||
aircraft: aircraft.map(classifyAircraft).filter(a => a.isMilitary),
|
||||
};
|
||||
}
|
||||
}
|
||||
failures.push({ provider: 'public-feed', error: pubData?.error || 'Public feed returned an unsupported payload' });
|
||||
|
||||
return null; // all sources failed
|
||||
return { provider: null, aircraft: null, failures };
|
||||
}
|
||||
|
||||
// Get military aircraft from available sources
|
||||
export async function getMilitaryAircraft(apiKey) {
|
||||
const result = await getMilitaryAircraftResult(apiKey);
|
||||
return result.aircraft;
|
||||
}
|
||||
|
||||
// Get all aircraft in a geographic bounding box via RapidAPI
|
||||
@@ -208,7 +225,8 @@ export async function getAircraftInArea(lat, lon, radiusNm = 250, apiKey) {
|
||||
// Briefing — attempt to get military flight data, document what's available
|
||||
export async function briefing() {
|
||||
const apiKey = process.env.ADSB_API_KEY || process.env.RAPIDAPI_KEY || null;
|
||||
const militaryAircraft = await getMilitaryAircraft(apiKey);
|
||||
const result = await getMilitaryAircraftResult(apiKey);
|
||||
const militaryAircraft = result.aircraft;
|
||||
|
||||
// If we got data, analyze it
|
||||
if (militaryAircraft && militaryAircraft.length > 0) {
|
||||
@@ -255,6 +273,7 @@ export async function briefing() {
|
||||
source: 'ADS-B Exchange',
|
||||
timestamp: new Date().toISOString(),
|
||||
status: 'live',
|
||||
provider: result.provider,
|
||||
totalMilitary: militaryAircraft.length,
|
||||
byCountry,
|
||||
categories: {
|
||||
@@ -269,10 +288,18 @@ export async function briefing() {
|
||||
}
|
||||
|
||||
// No data available — return stub with integration documentation
|
||||
const status = apiKey ? 'degraded' : 'disabled';
|
||||
const error = apiKey
|
||||
? 'ADS-B providers returned no usable aircraft data'
|
||||
: 'ADSB_API_KEY or RAPIDAPI_KEY is not configured';
|
||||
|
||||
return {
|
||||
source: 'ADS-B Exchange',
|
||||
timestamp: new Date().toISOString(),
|
||||
status: apiKey ? 'error' : 'no_key',
|
||||
status,
|
||||
provider: result.provider,
|
||||
error,
|
||||
failures: result.failures,
|
||||
militaryAircraft: [],
|
||||
message: apiKey
|
||||
? 'ADS-B Exchange API returned no data. The endpoint may be temporarily unavailable.'
|
||||
|
||||
Reference in New Issue
Block a user