openweather-api 0.1.0

OpenWeather API
Documentation
use serde::{Deserialize, Serialize};

use crate::{CurrentWeather, Units, WeatherForecast};

#[derive(Debug, Deserialize, Serialize)]
pub struct OneCallResponse {
    pub lat: f64,
    pub lon: f64,
    pub timezone: String,
    pub timezone_offset: i32,
    pub current: CurrentWeather,
    pub hourly: Option<Vec<WeatherForecast>>,
}

pub async fn onecall(
    api_key: &str,
    latitude: f64,
    longitude: f64,
    exclude: &[&str],
    units: Option<Units>,
) -> anyhow::Result<OneCallResponse> {
    let units = match units {
        Some(Units::Standard) => "standard",
        Some(Units::Metric) => "metric",
        Some(Units::Imperial) => "imperial",
        None => "standard",
    };

    let url = format!("https://api.openweathermap.org/data/3.0/onecall?lat={}&lon={}&exclude={}&units={}&appid={}", latitude, longitude, exclude.join(","), units, api_key);
    let response = reqwest::get(&url).await?;
    let body = response.text().await?;

    let one_call_response: OneCallResponse = serde_json::from_str(&body)?;

    Ok(one_call_response)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_create_get_delete() -> anyhow::Result<()> {
        dotenvy::from_filename(".env.test").ok();

        let api_key = std::env::var("OPENWEATHER_API_KEY").unwrap();

        let one_call_response = onecall(
            &api_key,
            37.8267,
            -122.4233,
            &["minutely", "hourly", "daily"],
            Some(Units::Metric),
        )
        .await?;

        assert_eq!(one_call_response.lat, 37.8267);
        assert_eq!(one_call_response.lon, -122.4233);

        println!("{:#?}", one_call_response);
        Ok(())
    }
}