twapi_reqwest/
v1.rs

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        // search
253        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        // home_timeline
272        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        // statuses/update
291        /*
292        let url = "https://api.twitter.com/1.1/statuses/update.json";
293        let form_options = vec![
294            ("status", "!\"'#$%&\\()+,/:;<=>?@[\\]^`{|}~;-._* 全部"),
295            ("in_reply_to_status_id", "1178811297455935488"),
296        ];
297        let res: Value = v1::post(
298            url,
299            &vec![],
300            &form_options,
301            &consumer_key,
302            &consumer_secret,
303            &access_key,
304            &access_secret,
305        )
306        .await
307        .unwrap()
308        .json()
309        .await
310        .unwrap();
311        println!("{:?}", res);
312         */
313        /*
314            // direct_messages new
315            let url = "https://api.twitter.com/1.1/direct_messages/events/new.json";
316            let data = r#"{
317                        "event": {
318                            "type": "message_create",
319                            "message_create": {
320                                "target": {
321                                    "recipient_id": "19522946"
322                                },
323                                "message_data": {
324                                    "text": "予定表〜①ハンカクだ!"
325                                }
326                            }
327                        }
328                    }"#;
329            let data: Value = serde_json::from_str(data).unwrap();
330            let res: Value = v1::json(
331                url,
332                &vec![],
333                &data,
334                &consumer_key,
335                &consumer_secret,
336                &access_key,
337                &access_secret,
338            )
339            .await
340            .unwrap()
341            .json()
342            .await
343            .unwrap();
344            println!("{:?}", res);
345
346            // media/upload
347            let metadata = std::fs::metadata("test.jpg").unwrap();
348            let file_size = metadata.len();
349            let f = std::fs::File::open("test.jpg").unwrap();
350            let mut cursor = Cursor::new(vec![0; file_size as usize]);
351            let mut reader = BufReader::new(f);
352            reader.read(cursor.get_mut()).unwrap();
353
354            let part = reqwest::multipart::Part::bytes(cursor.into_inner());
355            let data = reqwest::multipart::Form::new().part("media", part);
356            let url = "https://upload.twitter.com/1.1/media/upload.json";
357            let res: Value = v1::multipart(
358                url,
359                &vec![],
360                data,
361                &consumer_key,
362                &consumer_secret,
363                &access_key,
364                &access_secret,
365            )
366            .await
367            .unwrap()
368            .json()
369            .await
370            .unwrap();
371            println!("{:?}", res);
372        */
373    }
374}