1use facebook_access_token::{
2 AccessTokenExpiresIn, AppAccessToken, LongLivedUserAccessToken, PageAccessToken,
3 PageSessionInfoAccessToken, ShortLivedUserAccessToken, UserAccessToken,
4 UserSessionInfoAccessToken,
5};
6use facebook_graph_api_object_error::Error;
7use http_api_client::{Client, ClientRespondEndpointError};
8use http_api_client_endpoint::http::StatusCode;
9
10use crate::{
11 endpoints::{AccessTokenEndpoint, DebugTokenEndpoint, EndpointError, EndpointRet},
12 objects::{DebugTokenResult, ResponseBodyErrJson},
13};
14
15pub async fn get_long_lived_user_access_token<C: Client + Send + Sync>(
20 client: &C,
21 app_id: u64,
22 app_secret: impl AsRef<str>,
23 short_lived_user_access_token: impl Into<ShortLivedUserAccessToken>,
24) -> Result<
25 Result<
26 (LongLivedUserAccessToken, Option<AccessTokenExpiresIn>),
27 (StatusCode, ResponseBodyErrJson),
28 >,
29 ClientRespondEndpointError<C::RespondError, EndpointError, EndpointError>,
30> {
31 let ep = AccessTokenEndpoint::new(
32 "fb_exchange_token",
33 app_id,
34 Some(app_secret.as_ref().into()),
35 Some(short_lived_user_access_token.into().into_inner().into()),
36 None,
37 );
38
39 let ret = client.respond_endpoint(&ep).await?;
40
41 match ret {
42 EndpointRet::Ok(ok_json) => Ok(Ok((
43 ok_json.access_token.into(),
44 ok_json.expires_in.map(Into::into),
45 ))),
46 EndpointRet::Other((status_code, Ok(err_json))) => Ok(Err((status_code, err_json))),
47 EndpointRet::Other((status_code, Err(body))) => Ok(Err((
48 status_code,
49 ResponseBodyErrJson {
50 error: Error::new_with_status_code_and_body(
51 status_code.as_u16(),
52 String::from_utf8_lossy(&body).as_ref(),
53 ),
54 },
55 ))),
56 }
57}
58
59pub async fn gen_app_access_token<C: Client + Send + Sync>(
63 client: &C,
64 app_id: u64,
65 app_secret: impl AsRef<str>,
66) -> Result<
67 Result<AppAccessToken, (StatusCode, ResponseBodyErrJson)>,
68 ClientRespondEndpointError<C::RespondError, EndpointError, EndpointError>,
69> {
70 let ep = AccessTokenEndpoint::new(
71 "client_credentials",
72 app_id,
73 Some(app_secret.as_ref().into()),
74 None,
75 None,
76 );
77
78 let ret = client.respond_endpoint(&ep).await?;
79
80 match ret {
81 EndpointRet::Ok(ok_json) => Ok(Ok(ok_json.access_token.into())),
82 EndpointRet::Other((status_code, Ok(err_json))) => Ok(Err((status_code, err_json))),
83 EndpointRet::Other((status_code, Err(body))) => Ok(Err((
84 status_code,
85 ResponseBodyErrJson {
86 error: Error::new_with_status_code_and_body(
87 status_code.as_u16(),
88 String::from_utf8_lossy(&body).as_ref(),
89 ),
90 },
91 ))),
92 }
93}
94
95async fn gen_x_session_info_access_token_inner<C: Client + Send + Sync>(
99 client: &C,
100 app_id: u64,
101 x_session_info_access_token: &str,
102) -> Result<
103 Result<(String, Option<AccessTokenExpiresIn>), (StatusCode, ResponseBodyErrJson)>,
104 ClientRespondEndpointError<C::RespondError, EndpointError, EndpointError>,
105> {
106 let ep = AccessTokenEndpoint::new(
107 "fb_attenuate_token",
108 app_id,
109 None,
110 Some(x_session_info_access_token.into()),
111 None,
112 );
113
114 let ret = client.respond_endpoint(&ep).await?;
115
116 match ret {
117 EndpointRet::Ok(ok_json) => Ok(Ok((
118 ok_json.access_token.to_owned(),
119 ok_json.expires_in.map(Into::into),
120 ))),
121 EndpointRet::Other((status_code, Ok(err_json))) => Ok(Err((status_code, err_json))),
122 EndpointRet::Other((status_code, Err(body))) => Ok(Err((
123 status_code,
124 ResponseBodyErrJson {
125 error: Error::new_with_status_code_and_body(
126 status_code.as_u16(),
127 String::from_utf8_lossy(&body).as_ref(),
128 ),
129 },
130 ))),
131 }
132}
133
134pub async fn gen_user_session_info_access_token<C: Client + Send + Sync>(
136 client: &C,
137 app_id: u64,
138 long_lived_user_access_token: impl Into<LongLivedUserAccessToken>,
139) -> Result<
140 Result<
141 (UserSessionInfoAccessToken, Option<AccessTokenExpiresIn>),
142 (StatusCode, ResponseBodyErrJson),
143 >,
144 ClientRespondEndpointError<C::RespondError, EndpointError, EndpointError>,
145> {
146 match gen_x_session_info_access_token_inner(
147 client,
148 app_id,
149 long_lived_user_access_token.into().inner(),
150 )
151 .await
152 {
153 Ok(Ok((value, expires_in))) => Ok(Ok((value.into(), expires_in))),
154 Ok(Err(x)) => Ok(Err(x)),
155 Err(err) => Err(err),
156 }
157}
158
159pub async fn gen_page_session_info_access_token<C: Client + Send + Sync>(
161 client: &C,
162 app_id: u64,
163 page_access_token: impl Into<PageAccessToken>,
164) -> Result<
165 Result<
166 (PageSessionInfoAccessToken, Option<AccessTokenExpiresIn>),
167 (StatusCode, ResponseBodyErrJson),
168 >,
169 ClientRespondEndpointError<C::RespondError, EndpointError, EndpointError>,
170> {
171 match gen_x_session_info_access_token_inner(client, app_id, page_access_token.into().inner())
172 .await
173 {
174 Ok(Ok((value, expires_in))) => Ok(Ok((value.into(), expires_in))),
175 Ok(Err(x)) => Ok(Err(x)),
176 Err(err) => Err(err),
177 }
178}
179
180async fn debug_x_access_token_inner<C: Client + Send + Sync>(
184 client: &C,
185 input_token: &str,
186 access_token: &str,
187) -> Result<
188 Result<DebugTokenResult, (StatusCode, ResponseBodyErrJson)>,
189 ClientRespondEndpointError<C::RespondError, EndpointError, EndpointError>,
190> {
191 let ep = DebugTokenEndpoint::new(input_token, access_token, None);
192
193 let ret = client.respond_endpoint(&ep).await?;
194
195 match ret {
196 EndpointRet::Ok(ok_json) => Ok(Ok(ok_json.data)),
197 EndpointRet::Other((status_code, Ok(err_json))) => Ok(Err((status_code, err_json))),
198 EndpointRet::Other((status_code, Err(body))) => Ok(Err((
199 status_code,
200 ResponseBodyErrJson {
201 error: Error::new_with_status_code_and_body(
202 status_code.as_u16(),
203 String::from_utf8_lossy(&body).as_ref(),
204 ),
205 },
206 ))),
207 }
208}
209
210pub async fn debug_user_access_token<C: Client + Send + Sync>(
212 client: &C,
213 short_lived_or_long_lived_user_access_token: impl Into<UserAccessToken>,
214) -> Result<
215 Result<DebugTokenResult, (StatusCode, ResponseBodyErrJson)>,
216 ClientRespondEndpointError<C::RespondError, EndpointError, EndpointError>,
217> {
218 let token = short_lived_or_long_lived_user_access_token.into();
219 debug_x_access_token_inner(client, token.inner(), token.inner()).await
220}
221
222pub async fn debug_user_access_token_via_app_access_token<C: Client + Send + Sync>(
236 client: &C,
237 short_lived_or_long_lived_user_access_token: impl Into<UserAccessToken>,
238 app_access_token: impl Into<AppAccessToken>,
239) -> Result<
240 Result<DebugTokenResult, (StatusCode, ResponseBodyErrJson)>,
241 ClientRespondEndpointError<C::RespondError, EndpointError, EndpointError>,
242> {
243 let input_token = short_lived_or_long_lived_user_access_token.into();
244 let access_token = app_access_token.into();
245 debug_x_access_token_inner(client, input_token.inner(), access_token.inner()).await
246}
247
248pub async fn debug_app_access_token<C: Client + Send + Sync>(
250 client: &C,
251 app_access_token: impl Into<AppAccessToken>,
252) -> Result<
253 Result<DebugTokenResult, (StatusCode, ResponseBodyErrJson)>,
254 ClientRespondEndpointError<C::RespondError, EndpointError, EndpointError>,
255> {
256 let token = app_access_token.into();
257 debug_x_access_token_inner(client, token.inner(), token.inner()).await
258}
259
260pub async fn debug_page_access_token<C: Client + Send + Sync>(
262 client: &C,
263 page_access_token: impl Into<PageAccessToken>,
264) -> Result<
265 Result<DebugTokenResult, (StatusCode, ResponseBodyErrJson)>,
266 ClientRespondEndpointError<C::RespondError, EndpointError, EndpointError>,
267> {
268 let token = page_access_token.into();
269 debug_x_access_token_inner(client, token.inner(), token.inner()).await
270}
271
272pub async fn debug_user_session_info_access_token_via_app_access_token<C: Client + Send + Sync>(
274 client: &C,
275 user_session_info_access_token: impl Into<UserSessionInfoAccessToken>,
276 app_access_token: impl Into<AppAccessToken>,
277) -> Result<
278 Result<DebugTokenResult, (StatusCode, ResponseBodyErrJson)>,
279 ClientRespondEndpointError<C::RespondError, EndpointError, EndpointError>,
280> {
281 let input_token = user_session_info_access_token.into();
282 let access_token = app_access_token.into();
283 debug_x_access_token_inner(client, input_token.inner(), access_token.inner()).await
284}
285
286pub async fn debug_user_session_info_access_token_via_long_lived_user_access_token<
288 C: Client + Send + Sync,
289>(
290 client: &C,
291 user_session_info_access_token: impl Into<UserSessionInfoAccessToken>,
292 long_lived_user_access_token: impl Into<LongLivedUserAccessToken>,
293) -> Result<
294 Result<DebugTokenResult, (StatusCode, ResponseBodyErrJson)>,
295 ClientRespondEndpointError<C::RespondError, EndpointError, EndpointError>,
296> {
297 let input_token = user_session_info_access_token.into();
298 let access_token = long_lived_user_access_token.into();
299 debug_x_access_token_inner(client, input_token.inner(), access_token.inner()).await
300}
301
302pub async fn debug_page_session_info_access_token_via_app_access_token<C: Client + Send + Sync>(
304 client: &C,
305 page_session_info_access_token: impl Into<PageSessionInfoAccessToken>,
306 app_access_token: impl Into<AppAccessToken>,
307) -> Result<
308 Result<DebugTokenResult, (StatusCode, ResponseBodyErrJson)>,
309 ClientRespondEndpointError<C::RespondError, EndpointError, EndpointError>,
310> {
311 let input_token = page_session_info_access_token.into();
312 let access_token = app_access_token.into();
313 debug_x_access_token_inner(client, input_token.inner(), access_token.inner()).await
314}
315
316pub async fn debug_page_session_info_access_token_via_page_access_token<C: Client + Send + Sync>(
318 client: &C,
319 page_session_info_access_token: impl Into<PageSessionInfoAccessToken>,
320 page_access_token: impl Into<PageAccessToken>,
321) -> Result<
322 Result<DebugTokenResult, (StatusCode, ResponseBodyErrJson)>,
323 ClientRespondEndpointError<C::RespondError, EndpointError, EndpointError>,
324> {
325 let input_token = page_session_info_access_token.into();
326 let access_token = page_access_token.into();
327 debug_x_access_token_inner(client, input_token.inner(), access_token.inner()).await
328}