line_bot_messaging_api/
lib.rs1pub mod api;
2mod entity;
3mod error;
4pub(crate) mod util;
5
6pub use entity::*;
7pub use error::*;
8use reqwest::{Body, Method, RequestBuilder, Url};
9use serde_json::{json, Value};
10
11pub struct LineClient {
12 pub(crate) context: LineContext,
13}
14
15impl LineClient {
16 pub fn new(token: &str) -> Self {
17 Self {
18 context: LineContext {
19 token: Some(token.to_string()),
20 },
21 }
22 }
23}
24
25struct LineContext {
26 token: Option<String>,
27}
28
29pub type LineApiResponse<T> = Result<T, LineError>;
30
31impl LineClient {
32 async fn http_response_reqwest<R>(
33 response: Result<reqwest::Response, reqwest::Error>,
34 ) -> LineApiResponse<R>
35 where
36 R: for<'de> serde::Deserialize<'de>,
37 {
38 let response = match response {
39 Ok(v) => v,
40 Err(e) => return Err(LineSystemError::new(e.to_string()).into()),
41 };
42
43 let status = response.status();
44
45 let body = match response.bytes().await {
46 Ok(v) => v.to_vec(),
47 Err(e) => {
48 return Err(LineHttpError::new(status.as_u16(), e.to_string()).into());
49 }
50 };
51
52 let http_response_body = match String::from_utf8(body) {
53 Ok(v) => v,
54 Err(e) => return Err(LineSystemError::new(e.to_string()).into()),
55 };
56
57 let value = match serde_json::from_str::<Value>(http_response_body.as_str()) {
58 Ok(v) => v,
59 Err(e) => return Err(LineSystemError::new(e.to_string()).into()),
60 };
61
62 Self::http_response_text(status.as_u16(), http_response_body, value).await
63 }
64 async fn http_response_text<R>(
65 status: u16,
66 http_response_body: String,
67 value: Value,
68 ) -> LineApiResponse<R>
69 where
70 R: for<'de> serde::Deserialize<'de>,
71 {
72 if 400 <= status {
73 if let Ok(res) = serde_json::from_value(value.clone()) {
74 return Err(LineApiError {
75 status: status,
76 error: res,
77 warnings: None,
78 http_response_body: Some(http_response_body),
79 }
80 .into());
81 }
82 }
83
84 match serde_json::from_value(value.clone()) {
85 Ok(v) => Ok(v),
86 Err(e) => {
87 if let Ok(res) = serde_json::from_value(value.clone()) {
88 return Err(LineApiError {
89 status: status,
90 error: res,
91 warnings: None,
92 http_response_body: Some(http_response_body),
93 }
94 .into());
95 }
96 Err(LineSystemError::new(e.to_string()).into())
97 }
98 }
99 }
100 pub(crate) async fn http_get<P, R>(&self, url: &str, value: &P) -> LineApiResponse<R>
101 where
102 P: serde::Serialize,
103 R: for<'de> serde::Deserialize<'de>,
104 {
105 let build = builder2(
106 Url::parse(url).unwrap(),
107 Method::GET,
108 self.context.token.clone().unwrap_or_default().as_str(),
109 );
110 let request = build.body(Body::from(json!(value).to_string()));
111 LineClient::http_response_reqwest(request.send().await).await
112 }
113 pub(crate) async fn http_get_stream<P>(&self, url: &str, value: &P) -> LineApiResponse<Vec<u8>>
114 where
115 P: serde::Serialize,
116 {
117 let build = builder2(
118 Url::parse(url).unwrap(),
119 Method::GET,
120 self.context.token.clone().unwrap_or_default().as_str(),
121 );
122 let request = build.body(Body::from(json!(value).to_string()));
123
124 let a = request.send().await.unwrap();
125 let stream = a.bytes().await.unwrap();
126 Ok(stream.to_vec())
127 }
128 pub(crate) async fn http_post<P, R>(&self, url: &str, value: &P) -> LineApiResponse<R>
129 where
130 P: serde::Serialize,
131 R: for<'de> serde::Deserialize<'de>,
132 {
133 let build = builder2(
134 Url::parse(url).unwrap(),
135 Method::POST,
136 self.context.token.clone().unwrap_or_default().as_str(),
137 );
138
139 let request = build.json(&json!(value));
140 LineClient::http_response_reqwest(request.send().await).await
141 }
142 pub(crate) async fn http_put<P, R>(&self, url: &str, value: &P) -> LineApiResponse<R>
143 where
144 P: serde::Serialize,
145 R: for<'de> serde::Deserialize<'de>,
146 {
147 let build = builder2(
148 Url::parse(url).unwrap(),
149 Method::PUT,
150 self.context.token.clone().unwrap_or_default().as_str(),
151 );
152
153 let request = build.json(&json!(value));
154 LineClient::http_response_reqwest(request.send().await).await
155 }
156 pub(crate) async fn http_delete<P, R>(&self, url: &str, value: &P) -> LineApiResponse<R>
157 where
158 P: serde::Serialize,
159 R: for<'de> serde::Deserialize<'de>,
160 {
161 let build = builder2(
162 Url::parse(url).unwrap(),
163 Method::DELETE,
164 self.context.token.clone().unwrap_or_default().as_str(),
165 );
166
167 let request = build.json(&json!(value));
168 LineClient::http_response_reqwest(request.send().await).await
169 }
170 pub(crate) async fn http_post_data<R>(&self, url: &str, content: Vec<u8>) -> LineApiResponse<R>
171 where
172 R: for<'de> serde::Deserialize<'de>,
173 {
174 let req = reqwest::Client::new()
175 .post(url)
176 .header(
177 "Authorization",
178 format!("Bearer {}", self.context.token.clone().unwrap().to_string()),
179 )
180 .header("Content-Type", "image/jpeg")
181 .body(content)
182 .send()
183 .await;
184
185 Self::http_response_reqwest(req).await
186 }
187}
188
189fn builder2(url: Url, method: reqwest::Method, token: &str) -> RequestBuilder {
190 reqwest::Client::new()
191 .request(method, url)
192 .header("Authorization", format!("Bearer {}", token))
193}
194
195