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 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
use anyhow::{anyhow, Context, Result};
use std::{
env,
fs::File,
io::{Read, Write},
};
pub mod api_usage;
pub mod cmd_line;
pub mod user_setup;
/// Constants for the information of the program.
pub mod program_info {
/// The name of the program.
pub const PROGRAM_NAME: &str = "weather-cli";
/// The description of the program.
pub const PROGRAM_DESCRIPTION: &str = "Weather for command-line fans!";
/// The authors of the program.
pub const PROGRAM_AUTHORS: &str = "decaplanet";
}
/// Constants related to the API and settings.
mod constants {
/// The name of the json file for the API key.
pub const API_JSON_NAME: &str = "api";
/// The name of the json file for settings.
pub const SETTINGS_JSON_NAME: &str = "settings";
/// The URL template for the OpenWeatherMap API.
///
/// This template can be used to retrieve weather data by replacing the following placeholders:
///
/// - `{lat_value}`: Latitude value of the location.
/// - `{lon_value}`: Longitude value of the location.
/// - `{api_key}`: Your OpenWeatherMap API key.
/// - `{unit}`: The desired measurement unit. (ex. `metric` or `imperial`)
///
/// ## Example Usage
///
/// ```
/// pub const API_URL: &str = "https://api.openweathermap.org/data/2.5/weather?lat={lat_value}&lon={lon_value}&appid={api_key}&units={unit}";
///
/// let url = API_URL
/// .replace("{lat_value}", "37.3361663")
/// .replace("{lon_value}", "-121.890591")
/// .replace("{api_key}", "EXAMPLE_KEY")
/// .replace("{unit}", "imperial");
/// ```
pub const API_URL: &str = "https://api.openweathermap.org/data/2.5/weather?lat={lat_value}&lon={lon_value}&appid={api_key}&units={unit}";
}
/// Returns the running executable directory.
pub fn get_executable_directory() -> Result<String> {
let executable_path =
env::current_exe().context("Couldn't get the executable file directory!")?;
let executable_directory = executable_path
.parent()
.context("Couldn't get the executable directory!")?;
if let Some(dir_str) = executable_directory.to_str() {
return Ok(dir_str.to_string());
}
Err(anyhow!("Unable to get the executable directory."))
}
/// Formats the given file name with the executable directory.
pub fn get_json_file(name: &str) -> Result<File> {
let executable_dir = get_executable_directory()?;
let file = match File::open(format!("{}/weather-cli-{}.json", executable_dir, name)) {
Ok(f) => f,
Err(_) => {
let mut new_file =
File::create(format!("{}/weather-cli-{}.json", executable_dir, name))
.context("Couldn't create a json file.")?;
new_file
.write_all("{}".as_bytes())
.context("Couldn't create a json file.")?;
File::open(format!("{}/weather-cli-{}.json", executable_dir, name))
.context("Couldn't get the json file.")?
}
};
Ok(file)
}
/// Reads the given json file and returns the string.
pub fn read_json_file(json_name: &str) -> Result<String> {
let mut file = get_json_file(json_name)?;
let mut json_string = String::new();
file.read_to_string(&mut json_string)?;
Ok(json_string)
}
/// Returns the emoji for the given icon id.
pub fn get_emoji(icon_id: &str) -> String {
let return_value = match icon_id {
"01d" => "☀️",
"02d" => "⛅️",
"03d" => "☁️",
"04d" => "☁️",
"09d" => "🌧️",
"10d" => "🌦️",
"11d" => "⛈️",
"13d" => "❄️",
"50d" => "🌨️",
"01n" => "🌑",
"02n" => "🌑☁️",
"03n" => "☁️",
"04n" => "☁️☁️",
"09n" => "🌧️",
"10n" => "☔️",
"11n" => "⛈️",
"13n" => "❄️",
_ => "",
};
if !return_value.is_empty() {
format!("{} ", return_value)
} else {
return_value.to_string()
}
}
/// This module is only used for testing.
#[cfg(test)]
mod tests;