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()
}
|