Compare commits

10 Commits

17 changed files with 239 additions and 1 deletions

2
.env.sample Normal file
View File

@ -0,0 +1,2 @@
ACCUWHEATHER_API_ID=########
PATH_TO_CITIES="/share/cities.json"

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
**/.env
**/target/
**/*.lock
cities.json

11
Dockerfile Normal file
View File

@ -0,0 +1,11 @@
FROM rust AS build
WORKDIR /code
COPY ./code .
RUN cargo install --path .
FROM debian:buster-slim
COPY --from=build /usr/local/cargo/bin/clima /usr/local/bin/clima
RUN apt-get update && apt-get install -y libssl-dev && rm -rf /var/lib/apt/lists/*
ENV ACCUWHEATHER_API_ID "1"
ENV PATH_TO_CITIES "/share/cities.json"
CMD [ "sh", "-c", "/usr/local/bin/clima $ACCUWHEATHER_API_ID $PATH_TO_CITIES" ]

View File

@ -1,5 +1,17 @@
# Call
```
app ACCUWHEATHER_API_ID PATH_TO_CITIES.txt
docker compose up
```
# Compile / Build
```
docker compose build
```
# Rebuild
```
docker compose down --rmi all; docker compose build
```

58
code/src/lib.rs Normal file
View File

@ -0,0 +1,58 @@
use std::fs::File;
pub mod model;
use crate::model::{Country, Weather};
// Get all the city and countrie data outside of the program
pub fn get_list(path:String) -> Vec<Country> {
let file = File::open(path).expect("El archivo debería permitir la lectura.");
let json: Vec<Country> = serde_json::from_reader(file).expect("Pensá un poquito... capaz que no colocaste la ruta correctamente o peñarol peñarol.");
return json;
}
// This is the call to the api.
pub async fn call_api(code:&String, api_key:&String) -> Result<Weather, reqwest::Error> {
let url = format!(
"http://dataservice.accuweather.com/forecasts/v1/daily/1day/{}?apikey={}&language=es-ES&metric=true",
code,
api_key);
let data = reqwest::get(url)
.await?
.json::<Weather>()
.await?;
Ok(data)
}
pub fn convert_icon(icon: i32) -> String {
let final_icon = match icon {
1..=5 => ":soleado:",
6 => ":casi_todo_soleado:",
7..=8 => ":nube:",
35..=38 => ":nube:",
11 => ":nube:",
22 => ":nube:",
12 => ":nube_de_lluvia:",
13..=14 => ":sol_tras_nubes_lluvia:",
19 => ":nube_de_nieve:",
15 => ":nube_de_truenos_y_lluvia:",
20..=21 => ":sol_con_nubes:",
23 => ":sol_con_nubes:",
24 => ":cubito_de_hielo:",
18 => ":nube_de_lluvia:",
25 => ":nube_de_lluvia:",
39..=40 => ":nube_de_lluvia:",
16..=17 => ":nube_de_truenos_y_lluvia:",
41..=42 => ":nube_de_truenos_y_lluvia:",
26 => ":nube_de_nieve:",
29 => ":nube_de_nieve:",
30 => ":cara_con_calor:",
31 => ":cara_con_frio:",
32 => ":guión:",
33..=34 => ":luna_llena_con_cara:",
_=>""
};
return final_icon.to_string();
}

36
code/src/main.rs Normal file
View File

@ -0,0 +1,36 @@
use std::env;
use std::string::String;
use clima::{get_list, call_api, convert_icon};
use clima::model::Country;
#[tokio::main]
async fn main() {
let args: Vec<String> = env::args().collect();
let key = &args[1];
let path = &args[2];
let countries: Vec<Country> = get_list(path.to_string());
for country in countries {
println!("{} {}", country.name, country.flag);
for city in country.cities {
println!("{}", city.name);
if let Ok(w) = call_api(&city.code, &key).await {
println!("{}", w.headline.text);
println!("Máxima: {} | Mínima:{}",w.daily_forecasts[0].temperature.maximum.value, w.daily_forecasts[0].temperature.minimum.value);
println!("Día {} ({}) | Noche {} ({})",
convert_icon(w.daily_forecasts[0].day.icon),
w.daily_forecasts[0].day.icon_phrase,
convert_icon(w.daily_forecasts[0].night.icon),
w.daily_forecasts[0].night.icon_phrase,
);
println!("Más información: {}", w.daily_forecasts[0].link);
println!("***************************");
} else {
println!("Tan cerca... pero tan lejos. Algo en las estructuras está mal. Quizá nunca debiste ponerte a estudiar RUST. Cagón!");
}
}
}
}

7
code/src/model/city.rs Normal file
View File

@ -0,0 +1,7 @@
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct City {
pub name : String,
pub code: String
}

10
code/src/model/country.rs Normal file
View File

@ -0,0 +1,10 @@
use serde::{Serialize, Deserialize};
use std::string::String;
use super::City;
#[derive(Debug, Serialize, Deserialize)]
pub struct Country {
pub name : String,
pub flag: String,
pub cities: Vec<City>
}

View File

@ -0,0 +1,17 @@
use serde::{Serialize, Deserialize};
use std::string::String;
use super::{Day, Temperature};
#[derive(Debug, Serialize, Deserialize)]
pub struct DailyForecasts {
#[serde(rename = "Date")]
pub date: String,
#[serde(rename = "Day")]
pub day: Day,
#[serde(rename = "Night")]
pub night: Day,
#[serde(rename = "Temperature")]
pub temperature : Temperature,
#[serde(rename = "Link")]
pub link: String
}

10
code/src/model/day.rs Normal file
View File

@ -0,0 +1,10 @@
use serde::{Serialize, Deserialize};
use std::string::String;
#[derive(Debug, Serialize, Deserialize)]
pub struct Day {
#[serde(rename = "Icon")]
pub icon: i32,
#[serde(rename = "IconPhrase")]
pub icon_phrase : String
}

View File

@ -0,0 +1,8 @@
use serde::{Serialize, Deserialize};
use std::string::String;
#[derive(Debug, Serialize, Deserialize)]
pub struct Headline {
#[serde(rename = "Text")]
pub text: String
}

21
code/src/model/mod.rs Normal file
View File

@ -0,0 +1,21 @@
mod city;
pub use city::City;
mod country;
pub use country::Country;
mod temperature_value;
pub use temperature_value::TemperatureValue;
mod temperature;
pub use temperature::Temperature;
mod day;
pub use day::Day;
mod daily_forecasts;
pub use daily_forecasts::DailyForecasts;
mod headline;
pub use headline::Headline;
mod weather;
pub use weather::Weather;

View File

@ -0,0 +1,10 @@
use serde::{Serialize, Deserialize};
use super::TemperatureValue;
#[derive(Debug, Serialize, Deserialize)]
pub struct Temperature {
#[serde(rename = "Minimum")]
pub minimum: TemperatureValue,
#[serde(rename = "Maximum")]
pub maximum: TemperatureValue
}

View File

@ -0,0 +1,12 @@
use serde::{Serialize, Deserialize};
use std::string::String;
#[derive(Debug, Serialize, Deserialize)]
pub struct TemperatureValue {
#[serde(rename = "Value")]
pub value: f32,
#[serde(rename = "Unit")]
pub unit: String,
#[serde(rename = "UnitType")]
pub unit_type: u32,
}

10
code/src/model/weather.rs Normal file
View File

@ -0,0 +1,10 @@
use serde::{Serialize, Deserialize};
use super::{Headline, DailyForecasts};
#[derive(Debug, Serialize, Deserialize)]
pub struct Weather {
#[serde(rename = "Headline")]
pub headline: Headline,
#[serde(rename = "DailyForecasts")]
pub daily_forecasts: Vec<DailyForecasts>,
}

10
docker-compose.yml Normal file
View File

@ -0,0 +1,10 @@
version: '3'
services:
app:
image: rust
build: .
env_file:
- .env
volumes:
- ./cities.json:/share/cities.json