Skip to content

Instantly share code, notes, and snippets.

@whokilleddb
Last active December 26, 2021 11:35
Show Gist options
  • Save whokilleddb/52266c99378196edb5d97b272f05fbfe to your computer and use it in GitHub Desktop.
Save whokilleddb/52266c99378196edb5d97b272f05fbfe to your computer and use it in GitHub Desktop.
Rust Program To Give You Weather Stats Using openweathermap.org
[package]
name = "forecast"
version = "0.1.0"
authors = ["whokilleddb <whokilleddb@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
structopt = "0.3.15"
exitfailure = "0.5.1"
reqwest = { version = "0.10.6", features = ["json"] }
serde = "1.0.114"
serde_json = "1.0.56"
serde_derive = "1.0.114"
tokio = { version = "0.2.21", features = ["full"]}
tabled = "0.3.0"
$ cargo build --release
$ API_KEY=YOUR-API-KEY ./target/release/forecast London UK
+--------------+---------+
| City | London |
+--------------+---------+
| Country Code | UK |
+--------------+---------+
| Latitude | 51.5085 |
+--------------+---------+
| Longitude | -0.1257 |
+--------------+---------+
| Clouds | mist |
+--------------+---------+
| Temperature | 8.10°C |
+--------------+---------+
| Humidity | 97 |
+--------------+---------+
| Pressure | 1001 |
+--------------+---------+
use structopt::StructOpt;
use exitfailure::{ExitFailure};
use serde_derive::{Deserialize, Serialize};
use std::env;
use std::process;
use reqwest::Url;
use tabled::{Tabled, Table};
use tabled::Disable;
#[derive(StructOpt)]
struct Cli {
city: String,
country_code: String,
}
#[derive(Serialize, Deserialize, Debug)]
struct Coord{
lon: f64,
lat: f64,
}
#[derive(Serialize, Deserialize, Debug)]
struct Weather{
details: Details
}
#[derive(Serialize, Deserialize, Debug)]
struct Details{
id: i32,
main: String,
description: String,
icon: String,
}
#[derive(Serialize, Deserialize, Debug)]
struct Temps{
temp: f64,
feels_like: f64,
temp_min: f64,
temp_max: f64,
pressure: i32,
humidity: i32,
}
#[derive(Serialize, Deserialize, Debug)]
struct Wind{
speed: f64,
deg: i32,
}
#[derive(Serialize, Deserialize, Debug)]
struct Clouds{
all: i32,
}
#[derive(Serialize, Deserialize, Debug)]
struct Sys{
r#type: f64,
id: i32,
country: String,
sunrise: i32,
sunset: i32,
}
#[derive(Serialize, Deserialize, Debug)]
struct Forecast{
coord: Coord,
weather: Weather,
base: String,
main: Temps,
visibility: i32,
wind: Wind,
clouds: Clouds,
dt: i32,
sys: Sys,
timezone: i32,
id: i32,
name: String,
cod: i32,
}
fn exit_on_error(msg: &str) -> !{ // Note the `-> !` here
eprintln!("Error: {}", msg);
process::exit(-1);
}
impl Forecast {
async fn get(city: &String, country_code: &String, api_key: &String) -> Result<Self, ExitFailure>{
let url: String = format!("http://api.openweathermap.org/data/2.5/weather?q={},{}&appid={}",city, country_code, api_key);
let url = Url::parse(&*url)?;
let resp = reqwest::get(url)
.await?
.json::<Forecast>()
.await?;
Ok(resp)
}
}
#[derive(Tabled)]
struct Cell{
param: &'static str,
val: String,
}
#[tokio::main]
async fn main() -> Result<(), ExitFailure> {
let args = Cli::from_args();
let api_key = match env::var("API_KEY") {
Ok(api_key) => api_key,
Err(_e) => exit_on_error("API_KEY not set"),
};
let response = Forecast::get(&args.city,&args.country_code,&api_key).await?;
let cells = vec![
Cell{
param: "City",
val: args.city.clone(),
},
Cell{
param: "Country Code",
val: args.country_code.clone(),
},
Cell{
param: "Latitude",
val: response.coord.lat.to_string(),
},
Cell{
param: "Longitude",
val: response.coord.lon.to_string(),
},
Cell{
param: "Clouds",
val: response.weather.details.description.to_string(),
},
Cell{
param: "Temperature",
val: format!("{:.1$}°C",(response.main.temp - 273.00),2),
},
Cell{
param: "Humidity",
val: response.main.humidity.to_string(),
},
Cell{
param: "Pressure",
val: response.main.pressure.to_string(),
}
];
let table = Table::new(cells).with(Disable::Row(..1)).to_string();
println!("{}",table);
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment