mirror of
https://github.com/smittix/intercept.git
synced 2026-04-25 07:10:00 -07:00
- Escape ac.icao, callsign, typeCode with escapeHtml() in aircraft card (XSS) - Add linking comments between duplicated IATA_TO_ICAO mappings - VDL2 sidebar: single-click selects aircraft, double-click opens modal - Remove stale ICAOs from acarsAircraftIcaos in cleanupOldAircraft() - Add null guard to drawPolarPlot() in weather-satellite.js - Move deferred imports (translate_message, get_flight_correlator) to module level - Check all frequency checkboxes by default on initial load - Remove extra blank lines and uncertain MC/MCO airline code entry - Add TODO comments linking duplicated renderAcarsCard implementations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
161 lines
5.2 KiB
Python
161 lines
5.2 KiB
Python
"""IATA ↔ ICAO airline code mapping for flight number translation."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
# IATA (2-letter) → ICAO (3-letter) mapping for common airlines
|
|
# NOTE: Duplicated in templates/adsb_dashboard.html (JS IATA_TO_ICAO) — keep both in sync
|
|
IATA_TO_ICAO: dict[str, str] = {
|
|
# North America — Major
|
|
"AA": "AAL", # American Airlines
|
|
"DL": "DAL", # Delta Air Lines
|
|
"UA": "UAL", # United Airlines
|
|
"WN": "SWA", # Southwest Airlines
|
|
"B6": "JBU", # JetBlue Airways
|
|
"AS": "ASA", # Alaska Airlines
|
|
"NK": "NKS", # Spirit Airlines
|
|
"F9": "FFT", # Frontier Airlines
|
|
"G4": "AAY", # Allegiant Air
|
|
"HA": "HAL", # Hawaiian Airlines
|
|
"SY": "SCX", # Sun Country Airlines
|
|
"WS": "WJA", # WestJet
|
|
"AC": "ACA", # Air Canada
|
|
"WG": "WGN", # Sunwing Airlines
|
|
"TS": "TSC", # Air Transat
|
|
"PD": "POE", # Porter Airlines
|
|
"MX": "MXA", # Breeze Airways
|
|
"QX": "QXE", # Horizon Air
|
|
"OH": "COM", # PSA Airlines (Compass)
|
|
"OO": "SKW", # SkyWest Airlines
|
|
"YX": "RPA", # Republic Airways
|
|
"9E": "FLG", # Endeavor Air (Pinnacle)
|
|
"CP": "CPZ", # Compass Airlines
|
|
"PT": "SWQ", # Piedmont Airlines
|
|
"MQ": "ENY", # Envoy Air
|
|
"YV": "ASH", # Mesa Airlines
|
|
"AX": "LOF", # Trans States / GoJet
|
|
"ZW": "AWI", # Air Wisconsin
|
|
"G7": "GJS", # GoJet Airlines
|
|
"EV": "ASQ", # ExpressJet / Atlantic Southeast
|
|
"AM": "AMX", # Aeromexico
|
|
"VB": "VIV", # VivaAerobus
|
|
"4O": "AIJ", # Interjet
|
|
"Y4": "VOI", # Volaris
|
|
# North America — Cargo
|
|
"5X": "UPS", # UPS Airlines
|
|
"FX": "FDX", # FedEx Express
|
|
# Europe — Major
|
|
"BA": "BAW", # British Airways
|
|
"LH": "DLH", # Lufthansa
|
|
"AF": "AFR", # Air France
|
|
"KL": "KLM", # KLM Royal Dutch
|
|
"IB": "IBE", # Iberia
|
|
"AZ": "ITY", # ITA Airways
|
|
"SK": "SAS", # SAS Scandinavian
|
|
"AY": "FIN", # Finnair
|
|
"OS": "AUA", # Austrian Airlines
|
|
"LX": "SWR", # Swiss International
|
|
"SN": "BEL", # Brussels Airlines
|
|
"TP": "TAP", # TAP Air Portugal
|
|
"EI": "EIN", # Aer Lingus
|
|
"U2": "EZY", # easyJet
|
|
"FR": "RYR", # Ryanair
|
|
"W6": "WZZ", # Wizz Air
|
|
"VY": "VLG", # Vueling
|
|
"PC": "PGT", # Pegasus Airlines
|
|
"TK": "THY", # Turkish Airlines
|
|
"LO": "LOT", # LOT Polish
|
|
"BT": "BTI", # airBaltic
|
|
"DY": "NAX", # Norwegian Air Shuttle
|
|
"VS": "VIR", # Virgin Atlantic
|
|
"EW": "EWG", # Eurowings
|
|
# Asia-Pacific — Major
|
|
"SQ": "SIA", # Singapore Airlines
|
|
"CX": "CPA", # Cathay Pacific
|
|
"QF": "QFA", # Qantas
|
|
"JL": "JAL", # Japan Airlines
|
|
"NH": "ANA", # All Nippon Airways
|
|
"KE": "KAL", # Korean Air
|
|
"OZ": "AAR", # Asiana Airlines
|
|
"CI": "CAL", # China Airlines
|
|
"BR": "EVA", # EVA Air
|
|
"CZ": "CSN", # China Southern
|
|
"MU": "CES", # China Eastern
|
|
"CA": "CCA", # Air China
|
|
"AI": "AIC", # Air India
|
|
"GA": "GIA", # Garuda Indonesia
|
|
"TG": "THA", # Thai Airways
|
|
"MH": "MAS", # Malaysia Airlines
|
|
"PR": "PAL", # Philippine Airlines
|
|
"VN": "HVN", # Vietnam Airlines
|
|
"NZ": "ANZ", # Air New Zealand
|
|
"3K": "JSA", # Jetstar Asia
|
|
"JQ": "JST", # Jetstar Airways
|
|
"AK": "AXM", # AirAsia
|
|
"TR": "TGW", # Scoot
|
|
"5J": "CEB", # Cebu Pacific
|
|
# Middle East / Africa
|
|
"EK": "UAE", # Emirates
|
|
"QR": "QTR", # Qatar Airways
|
|
"EY": "ETD", # Etihad Airways
|
|
"GF": "GFA", # Gulf Air
|
|
"SV": "SVA", # Saudia
|
|
"ET": "ETH", # Ethiopian Airlines
|
|
"MS": "MSR", # EgyptAir
|
|
"SA": "SAA", # South African Airways
|
|
"RJ": "RJA", # Royal Jordanian
|
|
"WY": "OMA", # Oman Air
|
|
# South America
|
|
"LA": "LAN", # LATAM Airlines
|
|
"G3": "GLO", # Gol Transportes Aéreos
|
|
"AD": "AZU", # Azul Brazilian Airlines
|
|
"AV": "AVA", # Avianca
|
|
"CM": "CMP", # Copa Airlines
|
|
"AR": "ARG", # Aerolíneas Argentinas
|
|
}
|
|
|
|
# Build reverse mapping (ICAO → IATA)
|
|
ICAO_TO_IATA: dict[str, str] = {v: k for k, v in IATA_TO_ICAO.items()}
|
|
|
|
# Regex to split flight number into airline prefix and numeric part
|
|
_FLIGHT_RE = re.compile(r'^([A-Z]{2,3})(\d+[A-Z]?)$')
|
|
|
|
|
|
def translate_flight(flight: str) -> list[str]:
|
|
"""Translate a flight number to all possible equivalent forms.
|
|
|
|
Given "UA2412" (IATA), returns ["UAL2412"] (ICAO).
|
|
Given "UAL2412" (ICAO), returns ["UA2412"] (IATA).
|
|
Returns empty list if no translation found.
|
|
"""
|
|
if not flight:
|
|
return []
|
|
|
|
upper = flight.strip().upper()
|
|
m = _FLIGHT_RE.match(upper)
|
|
if not m:
|
|
return []
|
|
|
|
prefix, number = m.group(1), m.group(2)
|
|
results = []
|
|
|
|
# Try IATA → ICAO
|
|
if prefix in IATA_TO_ICAO:
|
|
results.append(IATA_TO_ICAO[prefix] + number)
|
|
|
|
# Try ICAO → IATA
|
|
if prefix in ICAO_TO_IATA:
|
|
results.append(ICAO_TO_IATA[prefix] + number)
|
|
|
|
return results
|
|
|
|
|
|
def expand_search_terms(terms: set[str]) -> set[str]:
|
|
"""Expand a set of callsign/flight search terms with translated variants."""
|
|
expanded = set(terms)
|
|
for term in list(terms):
|
|
for translated in translate_flight(term):
|
|
expanded.add(translated)
|
|
return expanded
|