use async_trait::async_trait;
use reqwest::{Response, RequestBuilder, StatusCode};
use crate::{cursor::Cursor, json};
#[async_trait]
pub trait ResponseUtils where Self: Sized {
fn only_success(self) -> Result<Self, StatusCode>;
async fn json_parser<T: json::Parsable, E: From<T::Error> + From<reqwest::Error>>(self) -> Result<T, E>;
async fn json_parser_vec<T: json::Parsable, E: From<T::Error> + From<reqwest::Error>>(self) -> Result<Vec<T>, E>;
}
#[async_trait]
impl ResponseUtils for Response {
fn only_success(self) -> Result<Self, StatusCode> {
if self.status().is_success() {
Ok(self)
} else {
Err(self.status())
}
}
async fn json_parser<T: json::Parsable, E: From<T::Error> + From<reqwest::Error>>(self) -> Result<T, E> {
Ok(T::parse(&self.json::<json::Parser>().await?)?)
}
async fn json_parser_vec<T: json::Parsable, E: From<T::Error> + From<reqwest::Error>>(self) -> Result<Vec<T>, E> {
Ok(T::parse_vec(&self.json::<Vec<json::Parser>>().await?)?)
}
}
#[async_trait]
pub trait RequestBuilderUtils where Self: Sized {
async fn send_success(self) -> Result<Response, super::Error>;
async fn project_send_success(self, id: u64) -> Result<Response, super::Error>;
fn cursor(self, cursor: impl Into<Cursor>) -> Self;
fn cursor_limited(self, cursor: impl Into<Cursor>, limit: usize) -> Self;
fn project_referer(self, id: u64) -> Self;
}
#[async_trait]
impl RequestBuilderUtils for RequestBuilder {
async fn send_success(self) -> Result<Response, super::Error> {
let idk = self.send().await;
Ok(idk?.only_success()?)
}
async fn project_send_success(self, id: u64) -> Result<Response, super::Error> {
self.project_referer(id).send_success().await
}
fn project_referer(self, id: u64) -> Self {
self.header("referer", format!("https://scratch.mit.edu/projects/{id}"))
}
fn cursor(self, cursor: impl Into<Cursor>) -> Self {
let cursor: Cursor = cursor.into();
self.query(&[
("limit", cursor.get_limit().map(|v| v.min(40))),
("offset", Some(cursor.start))
])
}
fn cursor_limited(self, cursor: impl Into<Cursor>, limit: usize) -> Self {
let cursor: Cursor = cursor.into();
self.query(&[
("limit", cursor.get_limit().map(|v| v.min(limit))),
("offset", Some(cursor.start))
])
}
}