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 | |
63 | mod api; |
64 | pub use api::*; |
65 | |
66 | mod models; |
67 | pub use models::*; |
68 | |
69 | mod lang; |
70 | pub use lang::Language; |
71 | |
72 | mod query; |
73 | pub use query::Query; |
74 | |
75 | pub use chrono; |
76 | |
77 | use ureq::{Agent, AgentBuilder}; |
78 | use std::fmt::Display; |
79 | |
80 | |
81 | #[derive (Debug, Clone)] |
82 | pub struct Client { |
83 | pub(crate) api_key: String, |
84 | pub(crate) agent: Agent, |
85 | pub(crate) https: bool |
86 | } |
87 | |
88 | impl 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)] |
236 | mod 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 | |