1use reqwest::{multipart::Form, Error, Response};
2use serde_json::Value;
3use std::time::Duration;
4use twapi_oauth::oauth1_authorization_header;
5
6pub struct Client {
7 consumer_key: String,
8 consumer_secret: String,
9 access_key: String,
10 access_secret: String,
11 timeout_sec: Option<Duration>,
12}
13
14impl Client {
15 pub fn new(
16 consumer_key: &str,
17 consumer_secret: &str,
18 access_key: &str,
19 access_secret: &str,
20 timeout_sec: Option<Duration>,
21 ) -> Self {
22 Self {
23 consumer_key: consumer_key.to_owned(),
24 consumer_secret: consumer_secret.to_owned(),
25 access_key: access_key.to_owned(),
26 access_secret: access_secret.to_owned(),
27 timeout_sec,
28 }
29 }
30
31 pub fn new_by_env() -> Result<Self, std::env::VarError> {
32 Ok(Self {
33 consumer_key: std::env::var("CONSUMER_KEY")?,
34 consumer_secret: std::env::var("CONSUMER_SECRET")?,
35 access_key: std::env::var("ACCESS_KEY")?,
36 access_secret: std::env::var("ACCESS_SECRET")?,
37 timeout_sec: None,
38 })
39 }
40
41 fn calc_oauth(&self, method: &str, url: &str, query_options: &Vec<(&str, &str)>) -> String {
42 oauth1_authorization_header(
43 &self.consumer_key,
44 &self.consumer_secret,
45 &self.access_key,
46 &self.access_secret,
47 method,
48 url,
49 &query_options,
50 )
51 }
52
53 pub async fn get(
54 &self,
55 url: &str,
56 query_options: &Vec<(&str, &str)>,
57 ) -> Result<Response, Error> {
58 let authorization = self.calc_oauth("GET", url, &query_options);
59 crate::raw::get(url, query_options, &authorization, self.timeout_sec).await
60 }
61
62 pub async fn post(
63 &self,
64 url: &str,
65 query_options: &Vec<(&str, &str)>,
66 form_options: &Vec<(&str, &str)>,
67 ) -> Result<Response, Error> {
68 let mut merged_options = query_options.clone();
69 for option in form_options {
70 merged_options.push(*option);
71 }
72 let authorization = self.calc_oauth("POST", url, &merged_options);
73 crate::raw::post(
74 url,
75 query_options,
76 form_options,
77 &authorization,
78 self.timeout_sec,
79 )
80 .await
81 }
82
83 pub async fn json(
84 &self,
85 url: &str,
86 query_options: &Vec<(&str, &str)>,
87 data: &Value,
88 ) -> Result<Response, Error> {
89 let authorization = self.calc_oauth("POST", url, &query_options);
90 crate::raw::json(url, query_options, data, &authorization, self.timeout_sec).await
91 }
92
93 pub async fn put(
94 &self,
95 url: &str,
96 query_options: &Vec<(&str, &str)>,
97 ) -> Result<Response, Error> {
98 let authorization = self.calc_oauth("PUT", url, &query_options);
99 crate::raw::put(url, query_options, &authorization, self.timeout_sec).await
100 }
101
102 pub async fn delete(
103 &self,
104 url: &str,
105 query_options: &Vec<(&str, &str)>,
106 ) -> Result<Response, Error> {
107 let authorization = self.calc_oauth("DELETE", url, &query_options);
108 crate::raw::delete(url, query_options, &authorization, self.timeout_sec).await
109 }
110
111 pub async fn multipart(
112 &self,
113 url: &str,
114 query_options: &Vec<(&str, &str)>,
115 data: Form,
116 ) -> Result<Response, Error> {
117 let authorization = self.calc_oauth("POST", url, &query_options);
118 crate::raw::multipart(url, query_options, data, &authorization, self.timeout_sec).await
119 }
120}
121
122pub async fn get(
123 url: &str,
124 query_options: &Vec<(&str, &str)>,
125 consumer_key: &str,
126 consumer_secret: &str,
127 access_key: &str,
128 access_secret: &str,
129 timeout_sec: Option<Duration>,
130) -> Result<Response, Error> {
131 let client = Client::new(
132 consumer_key,
133 consumer_secret,
134 access_key,
135 access_secret,
136 timeout_sec,
137 );
138 client.get(url, query_options).await
139}
140
141pub async fn post(
142 url: &str,
143 query_options: &Vec<(&str, &str)>,
144 form_options: &Vec<(&str, &str)>,
145 consumer_key: &str,
146 consumer_secret: &str,
147 access_key: &str,
148 access_secret: &str,
149 timeout_sec: Option<Duration>,
150) -> Result<Response, Error> {
151 let client = Client::new(
152 consumer_key,
153 consumer_secret,
154 access_key,
155 access_secret,
156 timeout_sec,
157 );
158 client.post(url, query_options, form_options).await
159}
160
161pub async fn json(
162 url: &str,
163 query_options: &Vec<(&str, &str)>,
164 data: &Value,
165 consumer_key: &str,
166 consumer_secret: &str,
167 access_key: &str,
168 access_secret: &str,
169 timeout_sec: Option<Duration>,
170) -> Result<Response, Error> {
171 let client = Client::new(
172 consumer_key,
173 consumer_secret,
174 access_key,
175 access_secret,
176 timeout_sec,
177 );
178 client.json(url, query_options, data).await
179}
180
181pub async fn put(
182 url: &str,
183 query_options: &Vec<(&str, &str)>,
184 consumer_key: &str,
185 consumer_secret: &str,
186 access_key: &str,
187 access_secret: &str,
188 timeout_sec: Option<Duration>,
189) -> Result<Response, Error> {
190 let client = Client::new(
191 consumer_key,
192 consumer_secret,
193 access_key,
194 access_secret,
195 timeout_sec,
196 );
197 client.put(url, query_options).await
198}
199
200pub async fn delete(
201 url: &str,
202 query_options: &Vec<(&str, &str)>,
203 consumer_key: &str,
204 consumer_secret: &str,
205 access_key: &str,
206 access_secret: &str,
207 timeout_sec: Option<Duration>,
208) -> Result<Response, Error> {
209 let client = Client::new(
210 consumer_key,
211 consumer_secret,
212 access_key,
213 access_secret,
214 timeout_sec,
215 );
216 client.delete(url, query_options).await
217}
218
219pub async fn multipart(
220 url: &str,
221 query_options: &Vec<(&str, &str)>,
222 data: Form,
223 consumer_key: &str,
224 consumer_secret: &str,
225 access_key: &str,
226 access_secret: &str,
227 timeout_sec: Option<Duration>,
228) -> Result<Response, Error> {
229 let client = Client::new(
230 consumer_key,
231 consumer_secret,
232 access_key,
233 access_secret,
234 timeout_sec,
235 );
236 client.multipart(url, query_options, data).await
237}
238
239#[cfg(test)]
240mod tests {
241 use crate::*;
242 use serde_json::Value;
243 use std::env;
244
245 #[tokio::test]
246 async fn test_api() {
247 let consumer_key = env::var("CONSUMER_KEY").unwrap();
248 let consumer_secret = env::var("CONSUMER_SECRET").unwrap();
249 let access_key = env::var("ACCESS_KEY").unwrap();
250 let access_secret = env::var("ACCESS_SECRET").unwrap();
251
252 let url = "https://api.twitter.com/1.1/search/tweets.json";
254 let query_options = vec![("q", "*abc"), ("count", "2")];
255 let res: Value = v1::get(
256 url,
257 &query_options,
258 &consumer_key,
259 &consumer_secret,
260 &access_key,
261 &access_secret,
262 None,
263 )
264 .await
265 .unwrap()
266 .json()
267 .await
268 .unwrap();
269 println!("{:?}", res);
270
271 let url = "https://api.twitter.com/1.1/statuses/home_timeline.json";
273 let query_options = vec![("count", "2")];
274 let res: Value = v1::get(
275 url,
276 &query_options,
277 &consumer_key,
278 &consumer_secret,
279 &access_key,
280 &access_secret,
281 None,
282 )
283 .await
284 .unwrap()
285 .json()
286 .await
287 .unwrap();
288 println!("{:?}", res);
289
290 }
374}