use std::io::{Cursor, Read};
use reqwest::header::Authorization;
use reqwest::multipart::{Form, Part};
use reqwest::{Client as ReqwestClient, RequestBuilder, StatusCode, Url};
use serde::de::DeserializeOwned;
use serde_json;
use ::model::{
ApiResponse,
Image,
ImageTagsResponse,
ImageTypesResponse,
ImageUploadResponse
};
use ::{Error, ImageParams, Result, UploadParams, constants};
pub trait WeebApiRequester {
fn get_images(&self) -> Result<ApiResponse>;
fn get_image_info<S>(&self, auth: S, id: &str) -> Result<Image>
where S: Into<String>;
fn get_image_random<S>(&self, auth: S, params: ImageParams) ->
Result<Image> where S: Into<String>;
fn get_image_tags<S>(&self, auth: S, hidden: bool) -> Result<Vec<String>>
where S: Into<String>;
fn get_image_types<S>(&self, auth: S, hidden: bool) -> Result<Vec<String>>
where S: Into<String>;
fn upload_image<S>(&self, auth: S, params: UploadParams) ->
Result<ImageUploadResponse> where S: Into<String>;
}
impl WeebApiRequester for ReqwestClient {
fn get_images(&self) -> Result<ApiResponse> {
handle_request(&mut self.get(constants::GET_IMAGES))
}
fn get_image_info<S>(&self, auth: S, id: &str) -> Result<Image>
where S: Into<String> {
let url = Url::parse(&format!("{}{}", constants::GET_IMAGE_INFO, id))?;
handle_request(self.get(url).header(Authorization(auth.into())))
}
fn get_image_random<S>(&self, auth: S, params: ImageParams)
-> Result<Image> where S: Into<String> {
let built = params.into_data();
if built.is_empty() {
return Err(Error::NoParamsSpecified);
}
let url = Url::parse_with_params(constants::GET_IMAGE_RANDOM, built)?;
handle_request(self.get(url).header(Authorization(auth.into())))
}
fn get_image_tags<S>(&self, auth: S, hidden: bool) -> Result<Vec<String>>
where S: Into<String> {
let param = [("hidden", &hidden.to_string())];
let url = Url::parse_with_params(constants::GET_IMAGE_TAGS, ¶m)?;
let mut request = self.get(url);
request.header(Authorization(auth.into()));
handle_request::<ImageTagsResponse>(&mut request).map(|x| x.tags)
}
fn get_image_types<S>(&self, auth: S, hidden: bool) -> Result<Vec<String>>
where S: Into<String> {
let param = [("hidden", &hidden.to_string())];
let url = Url::parse_with_params(constants::GET_IMAGE_TYPES, ¶m)?;
let mut request = self.get(url);
request.header(Authorization(auth.into()));
handle_request::<ImageTypesResponse>(&mut request).map(|x| x.types)
}
fn upload_image<S>(&self, auth: S, params: UploadParams) ->
Result<ImageUploadResponse> where S: Into<String> {
let (built, file) = params.into_data();
if built.is_empty() {
return Err(Error::NoUploadSpecified);
}
let url = Url::parse_with_params(constants::POST_IMAGE, built)?;
let part = Part::reader(Cursor::new(file));
let form = Form::new().part("file", part);
let mut request = self.post(url);
request.multipart(form);
request.header(Authorization(auth.into()));
handle_request(&mut request)
}
}
fn handle_request<T: DeserializeOwned>(request: &mut RequestBuilder) -> Result<T> {
let response = request.send()?;
match response.status() {
StatusCode::Ok => {},
StatusCode::BadRequest => {
return Err(Error::ReqwestBad(Box::new(response)));
},
StatusCode::Unauthorized => {
return Err(Error::ReqwestUnauthorized(Box::new(response)));
},
_ => return Err(Error::ReqwestInvalid(Box::new(response))),
}
from_reader(response)
}
#[inline]
fn from_reader<T: DeserializeOwned, U: Read>(reader: U) -> Result<T> {
serde_json::from_reader(reader).map_err(From::from)
}