Skip to content

Commit b0bab00

Browse files
fix getAirports and getAirlines functions for nodejs
1 parent f2afd44 commit b0bab00

File tree

9 files changed

+1213
-37
lines changed

9 files changed

+1213
-37
lines changed

nodejs/FlightRadar24/api.js

Lines changed: 181 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const Flight = require("./entities/flight");
55
const FlightTrackerConfig = require("./flightTrackerConfig");
66
const {AirportNotFoundError, LoginError} = require("./errors");
77
const {isNumeric} = require("./util");
8+
const {JSDOM} = require("jsdom");
89

910

1011
/**
@@ -22,13 +23,90 @@ class FlightRadar24API {
2223
/**
2324
* Return a list with all airlines.
2425
*
25-
* @return {object}
26+
* @return {Array<object>}
2627
*/
2728
async getAirlines() {
28-
const response = new APIRequest(Core.airlinesDataUrl, null, Core.jsonHeaders);
29+
const response = new APIRequest(Core.airlinesDataUrl, null, Core.htmlHeaders);
2930
await response.receive();
3031

31-
return (await response.getContent())["rows"];
32+
const htmlContent = await response.getContent();
33+
const airlinesData = [];
34+
35+
// Parse HTML content.
36+
const dom = new JSDOM(htmlContent);
37+
const document = dom.window.document;
38+
39+
const tbody = document.querySelector("tbody");
40+
41+
if (!tbody) {
42+
return [];
43+
}
44+
45+
// Extract data from HTML content.
46+
const trElements = tbody.querySelectorAll("tr");
47+
48+
for (const tr of trElements) {
49+
const tdNotranslate = tr.querySelector("td.notranslate");
50+
51+
if (tdNotranslate) {
52+
const aElement = tdNotranslate.querySelector("a[href^='/data/airlines']");
53+
54+
if (aElement) {
55+
const tdElements = tr.querySelectorAll("td");
56+
57+
// Extract airline name.
58+
const airlineName = aElement.textContent.trim();
59+
60+
if (airlineName.length < 2) {
61+
continue;
62+
}
63+
64+
// Extract IATA / ICAO codes.
65+
let iata = null;
66+
let icao = null;
67+
68+
if (tdElements.length >= 4) {
69+
const codesText = tdElements[3].textContent.trim();
70+
71+
if (codesText.includes(" / ")) {
72+
const parts = codesText.split(" / ");
73+
74+
if (parts.length === 2) {
75+
iata = parts[0].trim();
76+
icao = parts[1].trim();
77+
}
78+
} else if (codesText.length === 2) {
79+
iata = codesText;
80+
} else if (codesText.length === 3) {
81+
icao = codesText;
82+
}
83+
}
84+
85+
// Extract number of aircrafts.
86+
let nAircrafts = null;
87+
88+
if (tdElements.length >= 5) {
89+
const aircraftsText = tdElements[4].textContent.trim();
90+
91+
if (aircraftsText) {
92+
nAircrafts = aircraftsText.split(" ")[0].trim();
93+
nAircrafts = parseInt(nAircrafts);
94+
}
95+
}
96+
97+
const airlineData = {
98+
"Name": airlineName,
99+
"ICAO": icao,
100+
"IATA": iata,
101+
"n_aircrafts": nAircrafts
102+
};
103+
104+
airlinesData.push(airlineData);
105+
}
106+
}
107+
}
108+
109+
return airlinesData;
32110
}
33111

34112
/**
@@ -171,21 +249,112 @@ class FlightRadar24API {
171249
}
172250

173251
/**
174-
* Return a list with all airports.
252+
* Return a list with all airports for specified countries.
175253
*
254+
* @param {Array<string>} countries - Array of country names from Countries enum
176255
* @return {Array<Airport>}
177256
*/
178-
async getAirports() {
179-
const response = new APIRequest(Core.airportsDataUrl, null, Core.jsonHeaders);
180-
await response.receive();
181-
182-
const content = await response.getContent();
257+
async getAirports(countries) {
183258
const airports = [];
184259

185-
for (const airportData of content["rows"]) {
186-
const airport = new Airport(airportData);
187-
airports.push(airport);
260+
for (const countryName of countries) {
261+
const countryHref = Core.airportsDataUrl + "/" + countryName;
262+
263+
const response = new APIRequest(countryHref, null, Core.htmlHeaders);
264+
await response.receive();
265+
266+
const htmlContent = await response.getContent();
267+
268+
// Parse HTML content.
269+
const dom = new JSDOM(htmlContent);
270+
const document = dom.window.document;
271+
272+
const tbody = document.querySelector("tbody");
273+
274+
if (!tbody) {
275+
continue;
276+
}
277+
278+
// Extract country name from the URL
279+
const countryDisplayName = countryHref.split("/").pop().replace(/-/g, " ")
280+
.split(" ").map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
281+
282+
const trElements = tbody.querySelectorAll("tr");
283+
284+
for (const tr of trElements) {
285+
const aElements = tr.querySelectorAll("a[data-iata][data-lat][data-lon]");
286+
287+
if (aElements.length > 0) {
288+
const aElement = aElements[0];
289+
290+
let icao = "";
291+
let iata = aElement.getAttribute("data-iata") || "";
292+
const latitude = aElement.getAttribute("data-lat") || "";
293+
const longitude = aElement.getAttribute("data-lon") || "";
294+
295+
const airportText = aElement.textContent.trim();
296+
let namePart = airportText;
297+
298+
// Get IATA / ICAO from airport text.
299+
const smallElement = aElement.querySelector("small");
300+
301+
if (smallElement) {
302+
let codesText = smallElement.textContent.trim();
303+
codesText = codesText.replace(/^\(/, "").replace(/\)$/, "").trim();
304+
305+
// Remove IATA / ICAO from name part.
306+
namePart = namePart.replace(smallElement.textContent, "").replace(/\(\)/, "").trim();
307+
308+
// Parse codes (can be "IATA/ICAO", "IATA", or "ICAO")
309+
if (codesText.includes("/")) {
310+
const codes = codesText.split("/");
311+
const code1 = codes[0].trim();
312+
const code2 = codes[1].trim();
313+
314+
// Use length to determine IATA vs ICAO
315+
if (code1.length === 3 && code2.length === 4) {
316+
iata = code1;
317+
icao = code2;
318+
} else if (code1.length === 4 && code2.length === 3) {
319+
iata = code2;
320+
icao = code1;
321+
}
322+
} else if (codesText.length === 3) {
323+
iata = codesText;
324+
} else if (codesText.length === 4) {
325+
icao = codesText;
326+
}
327+
}
328+
329+
// Convert latitude and longitude to float
330+
let latFloat = 0.0;
331+
let lonFloat = 0.0;
332+
333+
try {
334+
latFloat = latitude ? parseFloat(latitude) : 0.0;
335+
lonFloat = longitude ? parseFloat(longitude) : 0.0;
336+
} catch (error) {
337+
latFloat = 0.0;
338+
lonFloat = 0.0;
339+
}
340+
341+
// Create Airport instance with basic_info format
342+
const airportData = {
343+
"name": namePart,
344+
"icao": icao,
345+
"iata": iata,
346+
"lat": latFloat,
347+
"lon": lonFloat,
348+
"alt": null, // Altitude not available in this format
349+
"country": countryDisplayName
350+
};
351+
352+
const airport = new Airport(airportData);
353+
airports.push(airport);
354+
}
355+
}
188356
}
357+
189358
return airports;
190359
}
191360

0 commit comments

Comments
 (0)