flightradarapi 0.1.0

A modern async Rust SDK for the FlightRadar24 API
Documentation
/// Supported country filters for airport listing endpoints.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Countries {
    France,
    UnitedStates,
    UnitedKingdom,
    Germany,
    Spain,
    Italy,
    Brazil,
    Canada,
    Australia,
    Netherlands,
    Japan,
    Turkey,
    India,
    UnitedArabEmirates,
    Other(String),
}

impl Countries {
    /// Convert enum variant to API parameter value.
    pub fn as_api_value(&self) -> String {
        match self {
            Self::France => "france".to_owned(),
            Self::UnitedStates => "united-states".to_owned(),
            Self::UnitedKingdom => "united-kingdom".to_owned(),
            Self::Germany => "germany".to_owned(),
            Self::Spain => "spain".to_owned(),
            Self::Italy => "italy".to_owned(),
            Self::Brazil => "brazil".to_owned(),
            Self::Canada => "canada".to_owned(),
            Self::Australia => "australia".to_owned(),
            Self::Netherlands => "netherlands".to_owned(),
            Self::Japan => "japan".to_owned(),
            Self::Turkey => "turkey".to_owned(),
            Self::India => "india".to_owned(),
            Self::UnitedArabEmirates => "united-arab-emirates".to_owned(),
            Self::Other(value) => value.trim().to_ascii_lowercase().replace(' ', "-"),
        }
    }
}

/// Predefined geographic zones for convenient regional flight queries.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PresetZone {
    Europe,
    NorthAmerica,
    SouthAmerica,
    MiddleEastCentralAsia,
    SoutheastAsia,
    EastAsia,
    AustraliaOceania,
    Africa,
    Custom(f64, f64, f64, f64),
}

impl PresetZone {
    /// Return zone bounds in `south,west,north,east` format.
    pub fn get_bounds(&self) -> String {
        match self {
            Self::Europe => "35.6,-9.56,71.5,40.18".to_owned(),
            Self::NorthAmerica => "15.0,-170.0,72.0,-50.0".to_owned(),
            Self::SouthAmerica => "-55.5,-78.0,12.0,-35.0".to_owned(),
            Self::MiddleEastCentralAsia => "10.0,25.0,55.0,100.0".to_owned(),
            Self::SoutheastAsia => "-10.0,95.0,20.0,141.0".to_owned(),
            Self::EastAsia => "15.0,100.0,55.0,150.0".to_owned(),
            Self::AustraliaOceania => "-54.0,113.0,-10.0,180.0".to_owned(),
            Self::Africa => "-35.0,-20.0,37.0,55.0".to_owned(),
            Self::Custom(south, west, north, east) => {
                format!("{:.2},{:.2},{:.2},{:.2}", south, west, north, east)
            }
        }
    }

    /// Human-readable zone label.
    pub fn name(&self) -> &str {
        match self {
            Self::Europe => "Europe",
            Self::NorthAmerica => "North America",
            Self::SouthAmerica => "South America",
            Self::MiddleEastCentralAsia => "Middle East & Central Asia",
            Self::SoutheastAsia => "Southeast Asia",
            Self::EastAsia => "East Asia",
            Self::AustraliaOceania => "Australia & Oceania",
            Self::Africa => "Africa",
            Self::Custom(_, _, _, _) => "Custom",
        }
    }
}

/// Tracker configuration flags passed to flight listing endpoints.
#[derive(Debug, Clone)]
pub struct FlightTrackerConfig {
    /// Include FAA data.
    pub faa: bool,
    /// Include satellite data.
    pub satellite: bool,
    /// Include multilateration data.
    pub mlat: bool,
    /// Include FLARM data.
    pub flarm: bool,
    /// Include ADS-B data.
    pub adsb: bool,
    /// Include ground vehicles.
    pub gnd: bool,
    /// Include airborne traffic.
    pub air: bool,
    /// Include vehicle traffic.
    pub vehicles: bool,
    /// Include estimated positions.
    pub estimated: bool,
    /// Max age for entries in seconds.
    pub maxage: u32,
    /// Include gliders.
    pub gliders: bool,
    /// Include extra statistics fields.
    pub stats: bool,
    /// Server-side limit.
    pub limit: u32,
}

impl Default for FlightTrackerConfig {
    fn default() -> Self {
        Self {
            faa: true,
            satellite: true,
            mlat: true,
            flarm: true,
            adsb: true,
            gnd: true,
            air: true,
            vehicles: true,
            estimated: true,
            maxage: 14_400,
            gliders: true,
            stats: true,
            limit: 5_000,
        }
    }
}

impl FlightTrackerConfig {
    /// Convert tracker config to API query parameters.
    pub fn to_params(&self) -> Vec<(&'static str, String)> {
        vec![
            ("faa", bool_to_num(self.faa)),
            ("satellite", bool_to_num(self.satellite)),
            ("mlat", bool_to_num(self.mlat)),
            ("flarm", bool_to_num(self.flarm)),
            ("adsb", bool_to_num(self.adsb)),
            ("gnd", bool_to_num(self.gnd)),
            ("air", bool_to_num(self.air)),
            ("vehicles", bool_to_num(self.vehicles)),
            ("estimated", bool_to_num(self.estimated)),
            ("maxage", self.maxage.to_string()),
            ("gliders", bool_to_num(self.gliders)),
            ("stats", bool_to_num(self.stats)),
            ("limit", self.limit.to_string()),
        ]
    }
}

/// Generic pagination settings for list endpoints.
#[derive(Debug, Clone, Copy)]
pub struct Pagination {
    /// Number of entries per page.
    pub limit: usize,
    /// 1-based page index.
    pub page: usize,
}

impl Default for Pagination {
    fn default() -> Self {
        Self {
            limit: 100,
            page: 1,
        }
    }
}

/// Pagination options for airport details endpoint.
#[derive(Debug, Clone, Copy)]
pub struct AirportDetailsOptions {
    /// Number of flights to include in details payload.
    pub flight_limit: usize,
    /// 1-based page index.
    pub page: usize,
}

impl Default for AirportDetailsOptions {
    fn default() -> Self {
        Self {
            flight_limit: 100,
            page: 1,
        }
    }
}

/// History file formats supported by history export endpoint.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HistoryFileType {
    Csv,
    Kml,
}

impl HistoryFileType {
    /// Convert to API file type identifier.
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Csv => "CSV",
            Self::Kml => "KML",
        }
    }
}

fn bool_to_num(value: bool) -> String {
    if value {
        "1".to_owned()
    } else {
        "0".to_owned()
    }
}