#![warn(missing_docs)]
use crate::settings::Settings;
use anyhow::{Context, Result};
use reqwest;
use serde::Deserialize;
use serde_json;
#[derive(Debug, Deserialize, serde::Serialize)]
pub struct SunMoonTimes {
pub sunrise: String,
pub sunset: String,
pub solar_noon: String,
pub day_length: String,
pub civil_twilight_begin: String,
pub civil_twilight_end: String,
pub nautical_twilight_begin: String,
pub nautical_twilight_end: String,
pub astronomical_twilight_begin: String,
pub astronomical_twilight_end: String,
}
#[derive(Debug, Deserialize, serde::Serialize)]
pub struct SunMoonTimesResponse {
pub results: SunMoonTimes,
pub status: String,
pub tzid: String,
}
fn get_sun_moon_times() -> Result<String> {
let settings = Settings::new()
.context("Failed to load settings")?;
let url = reqwest::Url::parse_with_params(
"https://api.sunrise-sunset.org/json",
[
("lat", settings.observatory.latitude.to_string()),
("lng", settings.observatory.longitude.to_string()),
],
)
.context("Failed to parse sunrise-sunset URL")?;
let response = reqwest::blocking::get(url)
.context("Failed to fetch sun/moon times")?
.text()
.context("Failed to read sun/moon times response")?;
Ok(response)
}
pub fn parse_sun_moon_json(response: &str) -> Result<SunMoonTimesResponse> {
serde_json::from_str(response).context("Failed to parse sun/moon times JSON")
}
pub fn prepare_data() -> Result<SunMoonTimesResponse> {
parse_sun_moon_json(&get_sun_moon_times()?)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_parse_sun_moon_from_fixture() {
let json = include_str!("../response_examples/sunrise_sunset.json");
let response = parse_sun_moon_json(json).unwrap();
assert_eq!(response.status, "OK");
assert!(response.results.solar_noon.contains(':'));
}
#[cfg(feature = "network-tests")]
#[test]
fn test_get_sun_moon_times_live() {
let result = get_sun_moon_times();
assert!(result.is_ok());
assert!(result.unwrap().contains("solar_noon"));
}
#[cfg(feature = "network-tests")]
#[test]
fn test_prepare_data_live() {
let data = prepare_data();
assert!(data.is_ok());
let response = data.unwrap();
assert_eq!(response.status, "OK");
}
}