1//! A wrapper library for using [Weather API](https://www.weatherapi.com/)
2//!
3//! *This is an unofficial library*
4
5//! ## Usage
6//! Put this in your Cargo.toml:
7//! ```toml
8//! [dependencies]
9//! weer_api = "0.1.0"
10//! ```
11
12//! ### Examples
13//!
14//! #### Get forecast
15//! ```no_run
16//! use weer_api::{*, chrono::{Utc, TimeZone}};
17//!
18//! # fn main() {
19//! let client = Client::new("api_key", true);
20//! let result = client.forecast()
21//! .query(Query::City("London".to_string()))
22//! .dt(Utc.ymd(2022, 08, 21).and_hms(0, 0, 0))
23//! .lang(Language::Spanish)
24//! .call();
25//!
26//! assert!(result.is_ok());
27//! # }
28//! ```
29//!
30//! #### Get future
31//! ```no_run
32//! use weer_api::{*, chrono::{Utc, TimeZone}};
33//!
34//! # fn main() {
35//! let client = Client::new("api_key", true);
36//! let result = client.future()
37//! .query(Query::Coords(48.8567, 2.3508))
38//! .dt(Utc.ymd(2022, 09, 21).and_hms(0, 0, 0))
39//! .lang(Language::Spanish)
40//! .call();
41//!
42//! assert!(result.is_ok());
43//! # }
44//! ```
45//!
46//! #### Get history
47//! ```no_run
48//! use weer_api::{*, chrono::{Utc, TimeZone}};
49//!
50//! # fn main() {
51//! let client = Client::new("api_key", true);
52//! let result = client.history()
53//! .query(Query::Ip(None))
54//! .dt(Utc.ymd(2022, 07, 21).and_hms(0, 0, 0))
55//! .hour()
56//! .call();
57//!
58//! assert!(result.is_ok())
59//! # }
60//! ```
61
62
63mod api;
64pub use api::*;
65
66mod models;
67pub use models::*;
68
69mod lang;
70pub use lang::Language;
71
72mod query;
73pub use query::Query;
74
75pub use chrono;
76
77use ureq::{Agent, AgentBuilder};
78use std::fmt::Display;
79
80
81#[derive(Debug, Clone)]
82pub struct Client {
83 pub(crate) api_key: String,
84 pub(crate) agent: Agent,
85 pub(crate) https: bool
86}
87
88impl Client {
89 /// Creates a new client
90 ///
91 /// The `https` parameter if set to true it will cause the client to make an https request instead of an http request.
92 ///
93 /// # Example:
94 /// ```no_run
95 /// use weer_api::Client;
96 ///
97 /// let client = Client::new("api_key", true);
98 /// ```
99 pub fn new(api_key: &str, https: bool) -> Self {
100 let user_agent = format!(
101 "{name} ({repo} {version})",
102 name = env!("CARGO_PKG_NAME"),
103 repo = env!("CARGO_PKG_REPOSITORY"),
104 version = env!("CARGO_PKG_VERSION"),
105 );
106
107 let agent = AgentBuilder::new()
108 .user_agent(&user_agent)
109 .https_only(https)
110 .build();
111
112 Self {
113 api_key: api_key.to_string(),
114 agent,
115 https
116 }
117 }
118
119 /// Function to get forecast
120 ///
121 /// This returns upto next 14 day weather forecast and weather alert. The data is returned as a Forecast Object.
122 ///
123 /// ## Example:
124 /// ```no_run
125 /// use weer_api::{*, chrono::{Utc, TimeZone}};
126 ///
127 /// let client = Client::new("api_key", true);
128 /// let result = client.forecast()
129 /// .query(Query::City("London".to_string()))
130 /// .dt(Utc.ymd(2022, 08, 21).and_hms(0, 0, 0))
131 /// .lang(Language::Spanish)
132 /// .call();
133 ///
134 /// assert!(result.is_ok())
135 /// ```
136 pub fn forecast<Tz: chrono::TimeZone>(&self) -> ForecastApi<Tz>
137 where
138 Tz::Offset: Display
139 {
140 ForecastApi::<Tz>::new(&self)
141 }
142
143 /// Function to get future
144 ///
145 /// This returns weather in a 3 hourly interval in future for a date between 14 days and 300 days from today in the future.
146 ///
147 /// ## Example:
148 /// ```no_run
149 /// use weer_api::{*, chrono::{Utc, TimeZone}};
150 ///
151 /// let client = Client::new("api_key", true);
152 /// let result = client.future()
153 /// .query(Query::Coords(48.8567, 2.3508))
154 /// .dt(Utc.ymd(2022, 09, 21).and_hms(0, 0, 0))
155 /// .lang(Language::Spanish)
156 /// .call();
157 ///
158 /// assert!(result.is_ok())
159 /// ```
160 pub fn future<Tz: chrono::TimeZone>(&self) -> FutureApi<Tz>
161 where
162 Tz::Offset: Display
163 {
164 FutureApi::new(&self)
165 }
166
167 /// Function to get history
168 ///
169 /// This returns historical weather for a date on or after 1st Jan, 2010. The data is returned as a Forecast Object.
170 ///
171 /// ## Example:
172 /// ```no_run
173 /// use weer_api::{*, chrono::{Utc, TimeZone}};
174 ///
175 /// let client = Client::new("api_key", true);
176 /// let result = client.history()
177 /// .query(Query::Ip(None))
178 /// .dt(Utc.ymd(2022, 07, 21).and_hms(0, 0, 0))
179 /// .hour()
180 /// .call();
181 ///
182 /// assert!(result.is_ok())
183 /// ```
184 pub fn history<Tz: chrono::TimeZone>(&self) -> HistoryApi<Tz>
185 where
186 Tz::Offset: Display
187 {
188 HistoryApi::<Tz>::new(&self)
189 }
190
191 /// Function to get realtime
192 ///
193 /// Use to get up to date current weather information. The data is returned as a Current Object.
194 ///
195 /// ## Example:
196 /// ```no_run
197 /// use weer_api::*;
198 ///
199 /// let client = Client::new("api_key", true);
200 /// let result = client.realtime()
201 /// .query(Query::Ip(None))
202 /// .lang(Language::Spanish)
203 /// .call();
204 ///
205 /// assert!(result.is_ok())
206 /// ```
207 pub fn realtime(&self) -> RealtimeApi {
208 RealtimeApi::new(&self)
209 }
210
211 /// Function to get realtime
212 ///
213 /// This returns matching cities and towns as an array of Location object
214 ///
215 /// ## Example:
216 /// ```no_run
217 /// use weer_api::*;
218 ///
219 /// let client = Client::new("api_key", true);
220 /// let result = client.search()
221 /// .query(Query::Ip(None))
222 /// .call();
223 ///
224 /// assert!(result.is_ok())
225 /// ```
226 pub fn search(&self) -> SearchApi {
227 SearchApi::new(&self)
228 }
229
230 pub fn conditions(&self) -> Result<Vec<Condition>, ureq::Error> {
231 Ok(self.agent.get("https://www.weatherapi.com/docs/weather_conditions.json").call()?.into_json()?)
232 }
233}
234
235#[cfg(test)]
236mod tests {
237 use crate::*;
238 use chrono::{Utc, TimeZone};
239
240 fn get_client() -> Client {
241 let api_key = option_env!("API_KEY").unwrap();
242 Client::new(api_key, true)
243 }
244
245 #[test]
246 fn forecast() {
247 let client = get_client();
248 let result = client.forecast()
249 .query(Query::Ip(None))
250 .dt(Utc.ymd(2022, 08, 21).and_hms(0, 0, 0))
251 .lang(Language::Spanish)
252 .call();
253
254 assert!(result.is_ok())
255 }
256
257 #[test]
258 fn future() {
259 let client = get_client();
260 let result = client.future()
261 .query(Query::Ip(None))
262 .dt(Utc.ymd(2022, 09, 21).and_hms(0, 0, 0))
263 .lang(Language::Spanish)
264 .call();
265
266 assert!(result.is_ok())
267 }
268
269 #[test]
270 fn history() {
271 let client = get_client();
272 let result = client.history()
273 .query(Query::Ip(None))
274 .dt(Utc.ymd(2022, 07, 21).and_hms(0, 0, 0))
275 .hour()
276 .call();
277
278 assert!(result.is_ok())
279 }
280
281 #[test]
282 fn realtime() {
283 let client = get_client();
284 let result = client.realtime()
285 .query(Query::Ip(None))
286 .lang(Language::Spanish)
287 .call();
288
289 assert!(result.is_ok())
290 }
291
292 #[test]
293 fn search() {
294 let client = get_client();
295 let result = client.search().query(Query::Ip(None)).call();
296
297 assert!(result.is_ok())
298 }
299
300 #[test]
301 fn lang() {
302 let l = Language::new("bg").unwrap();
303 assert_eq!(Language::Bulgarian, l)
304 }
305
306 #[test]
307 fn it_works() {
308 let result = 2 + 2;
309 assert_eq!(result, 4);
310 }
311}
312