summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 2bdb798a8563f113e2a37261843a27125da673ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use serde_json::Value;
use std::{fs, path::Path};

const CONFIG_PATH: &str = "/home/adam/.config/forecast";

#[derive(Debug)]
struct WeatherInfo {
    icon: char,
    temp: i32,
}

fn main() {
    let data = request_weather(setup());
    if data.is_err() {
        println!("  ??°C  ");
        return;
    }

    let (a, b) = parse_weather(data.unwrap());
    let trend = get_trend_icon(a.temp, b.temp);

    println!(
        "  {} {}°C {} {} {}°C  ",
        a.icon, a.temp, trend, b.icon, b.temp
    );
}

fn request_weather(
    (weather_url, forecast_url): (String, String),
) -> Result<(String, String), reqwest::Error> {
    let a = reqwest::blocking::get(weather_url)?.text()?;
    let b = reqwest::blocking::get(forecast_url)?.text()?;
    Ok((a, b))
}

fn parse_weather((a, b): (String, String)) -> (WeatherInfo, WeatherInfo) {
    (
        parse_current(serde_json::from_str(&a).unwrap()).unwrap(),
        parse_forecast(serde_json::from_str(&b).unwrap()).unwrap(),
    )
}

fn parse_current(data: Value) -> Option<WeatherInfo> {
    let i = data["weather"][0]["icon"].as_str()?;
    let t = data["main"]["temp"].as_f64()?.round();
    Some(WeatherInfo {
        icon: get_weather_icon(i),
        temp: t as i32,
    })
}

fn parse_forecast(data: Value) -> Option<WeatherInfo> {
    let i = data["list"][0]["weather"][0]["icon"].as_str()?;
    let t = data["list"][0]["main"]["temp"].as_f64()?.round();
    Some(WeatherInfo {
        icon: get_weather_icon(i),
        temp: t as i32,
    })
}

fn get_weather_icon(code: &str) -> char {
    match code {
        "01d" => '',         // Clear sky - day
        "01n" => '',         // Clear sky - night
        "02d" => '',         // Few clouds (11-25%) - day
        "02n" => '',         // Few clouds (11-25%) - night
        "03d" | "03n" => '', // Scattered clouds (25-50%) - day/night
        "04d" | "04n" => '', // Broken / Overcast clouds (51-84% / 85-100%) - day/night
        "09d" => '',         // Shower rain - day
        "09n" => '',         // Shower rain - night
        "10d" => '',         // Moderate / heavy rain - day
        "10n" => '',         // Moderate / heavy rain - night
        "11d" => '',         // Thunderstorm - day
        "11n" => '',         // Thunderstorm - night
        "13d" => '',         // Snow - day
        "13n" => '',         // Snow - night
        "50d" => '',         // Fog - day
        "50n" => '',         // Fog - night
        _ => '',             // ??
    }
}

fn get_trend_icon(t1: i32, t2: i32) -> char {
    if t1 < t2 {
        ''
    } else if t1 > t2 {
        ''
    } else {
        ''
    }
}

fn setup() -> (String, String) {
    let city_id = read_file("city_id");
    let api_key = read_file("api_key");

    let current_url: String = format!(
        "https://api.openweathermap.org/data/2.5/weather?id={}&appid={}&units=metric",
        city_id, api_key
    );
    let forecast_url: String = format!(
        "https://api.openweathermap.org/data/2.5/forecast?id={}&appid={}&units=metric&cnt=1",
        city_id, api_key
    );
    (current_url, forecast_url)
}

fn read_file(file_name: &str) -> String {
    let path = Path::new(CONFIG_PATH).join(file_name);
    fs::read_to_string(path.to_string_lossy().to_string()).unwrap()
}