use super::*;
use std::convert::TryInto;
#[non_exhaustive]
pub struct CustomResponse<'d, R, D>
where
R: Request,
D: 'd, {
pub pagination: Option<Cursor>,
pub request: Option<R>,
pub total: Option<i64>,
pub other: serde_json::Map<String, serde_json::Value>,
pub raw_data: Box<serde_json::value::RawValue>,
pd: std::marker::PhantomData<&'d D>,
}
impl<'d, R, D> CustomResponse<'d, R, D>
where
R: Request,
D: 'd + serde::Deserialize<'d>,
{
pub fn data(&'d self) -> Result<D, serde_json::Error> {
serde_json::from_str(self.raw_data.get())
}
}
impl<C: crate::HttpClient> HelixClient<'_, C> {
pub async fn req_get_custom<'d, R, D, T>(
&self,
request: R,
token: &T,
) -> Result<CustomResponse<'d, R, D>, ClientRequestError<<C as crate::HttpClient>::Error>>
where
R: Request + RequestGet,
D: serde::de::Deserialize<'d> + 'd,
T: TwitchToken + ?Sized,
C: Send,
{
let req = request.create_request(token.token().secret(), token.client_id().as_str())?;
let uri = req.uri().clone();
let response = self
.client
.req(req)
.await
.map_err(ClientRequestError::RequestError)?;
{
let request = Some(request);
let uri = &uri;
let text = std::str::from_utf8(response.body()).map_err(|e| {
HelixRequestGetError::Utf8Error(response.body().clone(), e, uri.clone())
})?;
if let Ok(HelixRequestError {
error,
status,
message,
}) = parse_json::<HelixRequestError>(text, false)
{
return Err(HelixRequestGetError::Error {
error,
status: status.try_into().unwrap_or(http::StatusCode::BAD_REQUEST),
message,
uri: uri.clone(),
}
.into());
}
let response: CustomInnerResponse<'_> = crate::parse_json(text, true).map_err(|e| {
HelixRequestGetError::DeserializeError(
text.to_owned(),
e,
uri.clone(),
response.status(),
)
})?;
Ok(CustomResponse {
pagination: response.pagination.cursor,
request,
total: response.total,
other: response.other,
raw_data: response.data.to_owned(),
pd: std::marker::PhantomData,
})
}
}
pub async fn req_post_custom<'d, R, B, D, T>(
&self,
request: R,
body: B,
token: &T,
) -> Result<CustomResponse<'d, R, D>, ClientRequestError<<C as crate::HttpClient>::Error>>
where
R: Request + RequestPost + RequestPost<Body = B>,
B: HelixRequestBody,
D: serde::de::Deserialize<'d> + 'd,
T: TwitchToken + ?Sized,
C: Send,
{
let req =
request.create_request(body, token.token().secret(), token.client_id().as_str())?;
let uri = req.uri().clone();
let response = self
.client
.req(req)
.await
.map_err(ClientRequestError::RequestError)?;
{
let request = Some(request);
let uri = &uri;
let text = std::str::from_utf8(response.body()).map_err(|e| {
HelixRequestPostError::Utf8Error(response.body().clone(), e, uri.clone())
})?;
if let Ok(HelixRequestError {
error,
status,
message,
}) = parse_json::<HelixRequestError>(text, false)
{
return Err(HelixRequestPostError::Error {
error,
status: status.try_into().unwrap_or(http::StatusCode::BAD_REQUEST),
message,
uri: uri.clone(),
body: response.body().clone(),
}
.into());
}
let response: CustomInnerResponse<'_> = crate::parse_json(text, true).map_err(|e| {
HelixRequestPostError::DeserializeError(
text.to_owned(),
e,
uri.clone(),
response.status(),
)
})?;
Ok(CustomResponse {
pagination: response.pagination.cursor,
request,
total: response.total,
other: response.other,
raw_data: response.data.to_owned(),
pd: std::marker::PhantomData,
})
}
}
pub async fn req_patch_custom<'d, R, B, D, T, F>(
&self,
request: R,
body: B,
token: &T,
function: F,
) -> Result<CustomResponse<'d, R, D>, ClientRequestError<<C as crate::HttpClient>::Error>>
where
R: Request + RequestPatch + RequestPatch<Body = B>,
B: HelixRequestBody,
D: serde::de::Deserialize<'d> + 'd,
T: TwitchToken + ?Sized,
C: Send,
F: Fn(&R, &http::Uri, &str, http::StatusCode) -> Result<(), HelixRequestPatchError>,
{
let req =
request.create_request(body, token.token().secret(), token.client_id().as_str())?;
let uri = req.uri().clone();
let response = self
.client
.req(req)
.await
.map_err(ClientRequestError::RequestError)?;
{
let uri = &uri;
let text = std::str::from_utf8(response.body()).map_err(|e| {
HelixRequestPatchError::Utf8Error(response.body().clone(), e, uri.clone())
})?;
if let Ok(HelixRequestError {
error,
status,
message,
}) = parse_json::<HelixRequestError>(text, false)
{
return Err(HelixRequestPatchError::Error {
error,
status: status.try_into().unwrap_or(http::StatusCode::BAD_REQUEST),
message,
uri: uri.clone(),
body: response.body().clone(),
}
.into());
}
function(&request, uri, text, response.status())?;
let response: CustomInnerResponse<'_> = crate::parse_json(text, true).map_err(|e| {
HelixRequestPatchError::DeserializeError(
text.to_owned(),
e,
uri.clone(),
response.status(),
)
})?;
Ok(CustomResponse {
pagination: response.pagination.cursor,
request: Some(request),
total: response.total,
other: response.other,
raw_data: response.data.to_owned(),
pd: std::marker::PhantomData,
})
}
}
pub async fn req_delete_custom<'d, R, D, T, F>(
&self,
request: R,
token: &T,
function: F,
) -> Result<CustomResponse<'d, R, D>, ClientRequestError<<C as crate::HttpClient>::Error>>
where
R: Request + RequestDelete,
D: serde::de::Deserialize<'d> + 'd,
T: TwitchToken + ?Sized,
C: Send,
F: Fn(&R, &http::Uri, &str, http::StatusCode) -> Result<(), HelixRequestDeleteError>,
{
let req = request.create_request(token.token().secret(), token.client_id().as_str())?;
let uri = req.uri().clone();
let response = self
.client
.req(req)
.await
.map_err(ClientRequestError::RequestError)?;
{
let uri = &uri;
let text = std::str::from_utf8(response.body()).map_err(|e| {
HelixRequestDeleteError::Utf8Error(response.body().clone(), e, uri.clone())
})?;
if let Ok(HelixRequestError {
error,
status,
message,
}) = parse_json::<HelixRequestError>(text, false)
{
return Err(HelixRequestDeleteError::Error {
error,
status: status.try_into().unwrap_or(http::StatusCode::BAD_REQUEST),
message,
uri: uri.clone(),
body: response.body().clone(),
}
.into());
}
function(&request, uri, text, response.status())?;
let response: CustomInnerResponse<'_> = crate::parse_json(text, true).map_err(|e| {
HelixRequestPatchError::DeserializeError(
text.to_owned(),
e,
uri.clone(),
response.status(),
)
})?;
Ok(CustomResponse {
pagination: response.pagination.cursor,
request: Some(request),
total: response.total,
other: response.other,
raw_data: response.data.to_owned(),
pd: std::marker::PhantomData,
})
}
}
pub async fn req_put_custom<'d, R, B, D, T, F>(
&self,
request: R,
body: B,
token: &T,
function: F,
) -> Result<CustomResponse<'d, R, D>, ClientRequestError<<C as crate::HttpClient>::Error>>
where
R: Request + RequestPut + RequestPut<Body = B>,
B: HelixRequestBody,
D: serde::de::Deserialize<'d> + 'd,
T: TwitchToken + ?Sized,
C: Send,
F: Fn(&R, &http::Uri, &str, http::StatusCode) -> Result<(), HelixRequestDeleteError>,
{
let req =
request.create_request(body, token.token().secret(), token.client_id().as_str())?;
let uri = req.uri().clone();
let response = self
.client
.req(req)
.await
.map_err(ClientRequestError::RequestError)?;
{
let uri = &uri;
let text = std::str::from_utf8(response.body()).map_err(|e| {
HelixRequestPutError::Utf8Error(response.body().clone(), e, uri.clone())
})?;
if let Ok(HelixRequestError {
error,
status,
message,
}) = parse_json::<HelixRequestError>(text, false)
{
return Err(HelixRequestPutError::Error {
error,
status: status.try_into().unwrap_or(http::StatusCode::BAD_REQUEST),
message,
uri: uri.clone(),
body: response.body().clone(),
}
.into());
}
function(&request, uri, text, response.status())?;
let response: CustomInnerResponse<'_> = crate::parse_json(text, true).map_err(|e| {
HelixRequestPatchError::DeserializeError(
text.to_owned(),
e,
uri.clone(),
response.status(),
)
})?;
Ok(CustomResponse {
pagination: response.pagination.cursor,
request: Some(request),
total: response.total,
other: response.other,
raw_data: response.data.to_owned(),
pd: std::marker::PhantomData,
})
}
}
}