|
- use std::sync::Mutex;
-
- use reqwest::{Client, Error as ReqwestError, Response};
- use url::{Url};
-
- use crate::robocraft2::{ITokenProvider, ErrorPayload};
- use crate::robocraft2::{SearchPayload, SearchResponse, CreateRobotPayload, CreateRobotResponse, FactoryInfoResponse, PublishRobotPayload, PublishRobotResponse, MyRobotsResponse, GetRobotResponse};
-
- /// Community Factory Robot 2 root URL
- pub const FACTORY_DOMAIN: &str = "https://factory.production.robocraft2.com";
-
- #[derive(Debug)]
- pub enum FactoryError {
- Protocol(ReqwestError),
- Response(ErrorPayload),
- ResponseCode(ReqwestError, u16)
- }
-
- impl std::fmt::Display for FactoryError {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
- match self {
- Self::Protocol(p) => if let Some(status) = p.status() {
- write!(f, "HTTP Error {}: {}", status, p)
- } else {
- write!(f, "HTTP Error: {}", p)
- }
- Self::Response(r) => write!(f, "Factory Error #{}: {}", r.error, r.error_message),
- Self::ResponseCode(p, s) => write!(f, "HTTP Error {}: {}", s, p)
- }
- }
- }
-
- impl std::error::Error for FactoryError {}
-
- async fn handle_json_response<D: for<'a> serde::Deserialize<'a>>(response: Response) -> Result<D, FactoryError> {
- let status_code: u16 = response.status().into();
- if status_code > 199 && status_code < 300 {
- Ok(response.json::<D>().await.map_err(FactoryError::Protocol)?)
- } else {
- match response.json::<ErrorPayload>().await {
- Ok(err) => Err(FactoryError::Response(err)),
- Err(e) => Err(FactoryError::ResponseCode(e, status_code))
- }
- }
- }
-
- /// CRF API implementation
- pub struct FactoryAPI {
- client: Client,
- token: Mutex<Box<dyn ITokenProvider + Send>>,
- }
-
- impl FactoryAPI {
- /*/// Create a new instance, using `DefaultTokenProvider`.
- pub fn new() -> FactoryAPI {
- FactoryAPI {
- client: Client::new(),
- token: Box::new(DefaultTokenProvider{}),
- }
- }*/
-
- /// Create a new instance using the provided token provider.
- pub fn with_auth(token_provider: Box<dyn ITokenProvider + Send>) -> FactoryAPI {
- FactoryAPI {
- client: Client::new(),
- token: Mutex::new(token_provider),
- }
- }
-
- /// Retrieve CRF robots on the main page.
- pub async fn list(&self) -> Result<SearchResponse, FactoryError> {
- self.search(SearchPayload::default()).await
- }
-
- /// Search for robots on the CRF which meet the provided parameters
- pub async fn search(&self, params: SearchPayload) -> Result<SearchResponse, FactoryError> {
- let mut url = Url::parse(FACTORY_DOMAIN)
- .unwrap()
- .join("/v1/foundry/search")
- .unwrap();
- if let Some(text) = ¶ms.text {
- url.query_pairs_mut().append_pair("text", text);
- }
- if let Some(base_minimum_cpu) = params.base_minimum_cpu {
- url.query_pairs_mut().append_pair("baseCpuMinimum", &base_minimum_cpu.to_string());
- }
- if let Some(base_maximum_cpu) = ¶ms.base_maximum_cpu {
- url.query_pairs_mut().append_pair("baseCpuMaximum", &base_maximum_cpu.to_string());
- }
- if let Some(x) = ¶ms.weapon_minimum_cpu {
- url.query_pairs_mut().append_pair("weaponCpuMinimum", &x.to_string());
- }
- if let Some(x) = ¶ms.weapon_maximum_cpu {
- url.query_pairs_mut().append_pair("weaponCpuMaximum", &x.to_string());
- }
- if let Some(x) = ¶ms.cosmetic_minimum_cpu {
- url.query_pairs_mut().append_pair("cosmeticCpuMinimum", &x.to_string());
- }
- if let Some(x) = ¶ms.cosmetic_maximum_cpu {
- url.query_pairs_mut().append_pair("cosmeticCpuMaximum", &x.to_string());
- }
- if let Some(x) = ¶ms.cluster_minimum {
- url.query_pairs_mut().append_pair("clusterMinimum", &x.to_string());
- }
- if let Some(x) = ¶ms.cluster_maximum {
- url.query_pairs_mut().append_pair("clusterMaximum", &x.to_string());
- }
- if let Some(x) = ¶ms.date_minimum {
- url.query_pairs_mut().append_pair("dateMinimum", x);
- }
- if let Some(x) = ¶ms.date_maximum {
- url.query_pairs_mut().append_pair("dateMaximum", x);
- }
- if let Some(x) = ¶ms.creator_id {
- url.query_pairs_mut().append_pair("creatorId", x);
- }
- if let Some(x) = ¶ms.page {
- url.query_pairs_mut().append_pair("page", &x.to_string());
- }
- if let Some(x) = ¶ms.count {
- url.query_pairs_mut().append_pair("count", &x.to_string());
- }
- url.query_pairs_mut().append_pair("sortBy", ¶ms.sort_by);
- url.query_pairs_mut().append_pair("orderBy", ¶ms.order_by);
- let token = self.token.lock().unwrap().token().await.map_err(FactoryError::Protocol)?;
- let result = self.client.get(url)
- .header("Authorization", "Bearer ".to_owned() + &token)
- .send().await
- .map_err(FactoryError::Protocol)?;
- handle_json_response::<SearchResponse>(result).await
- }
-
- pub async fn create_robot(&self, robot: CreateRobotPayload) -> Result<CreateRobotResponse, FactoryError> {
- let url = Url::parse(FACTORY_DOMAIN)
- .unwrap()
- .join("/v1/foundry/garage")
- .unwrap();
- let token = self.token.lock().unwrap().token().await.map_err(FactoryError::Protocol)?;
- let result = self.client.post(url)
- .header("Authorization", "Bearer ".to_owned() + &token)
- .header("Content-Type", "application/json")
- .json(&robot)
- .send().await
- .map_err(FactoryError::Protocol)?;
- handle_json_response::<CreateRobotResponse>(result).await
- }
-
- pub async fn publish_robot(&self, robot: PublishRobotPayload, id: String) -> Result<PublishRobotResponse, FactoryError> {
- let url = Url::parse(FACTORY_DOMAIN)
- .unwrap()
- .join(&format!("/v1/foundry/vehicles/{}/publish", id))
- .unwrap();
- let token = self.token.lock().unwrap().token().await.map_err(FactoryError::Protocol)?;
- let result = self.client.post(url)
- .header("Authorization", "Bearer ".to_owned() + &token)
- .header("Content-Type", "application/json")
- .json(&robot)
- .send().await
- .map_err(FactoryError::Protocol)?;
- handle_json_response(result).await
- }
-
- pub async fn unpublish_bot(&self, id: String) -> Result<(), FactoryError> {
- let url = Url::parse(FACTORY_DOMAIN)
- .unwrap()
- .join(&format!("/v1/foundry/vehicles/{}/unpublish", id))
- .unwrap();
- let token = self.token.lock().unwrap().token().await.map_err(FactoryError::Protocol)?;
- let result = self.client.post(url)
- .header("Authorization", "Bearer ".to_owned() + &token)
- .send().await
- .map_err(FactoryError::Protocol)?;
- let status_code = result.status().as_u16();
- if status_code > 199 && status_code < 300 {
- Ok(())
- } else {
- match result.json::<ErrorPayload>().await {
- Ok(err) => Err(FactoryError::Response(err)),
- Err(e) => Err(FactoryError::ResponseCode(e, status_code))
- }
- }
- }
-
- pub async fn delete_robot(&self, id: String) -> Result<(), FactoryError> {
- let url = Url::parse(FACTORY_DOMAIN)
- .unwrap()
- .join(&format!("/v1/foundry/vehicles/{}", id))
- .unwrap();
- let token = self.token.lock().unwrap().token().await.map_err(FactoryError::Protocol)?;
- let result = self.client.delete(url)
- .header("Authorization", "Bearer ".to_owned() + &token)
- .header("Content-Type", "application/json")
- .send().await
- .map_err(FactoryError::Protocol)?;
- let status_code = result.status().as_u16();
- if status_code > 199 && status_code < 300 {
- Ok(())
- } else {
- match result.json::<ErrorPayload>().await {
- Ok(err) => Err(FactoryError::Response(err)),
- Err(e) => Err(FactoryError::ResponseCode(e, status_code))
- }
- }
- }
-
- pub async fn factory_info(&self) -> Result<FactoryInfoResponse, FactoryError> {
- let url = Url::parse(FACTORY_DOMAIN)
- .unwrap()
- .join("/v1/foundry/info")
- .unwrap();
- let token = self.token.lock().unwrap().token().await.map_err(FactoryError::Protocol)?;
- let result = self.client.get(url)
- .header("Authorization", "Bearer ".to_owned() + &token)
- .send().await
- .map_err(FactoryError::Protocol)?;
- handle_json_response::<FactoryInfoResponse>(result).await
- }
-
- pub async fn my_robots(&self) -> Result<MyRobotsResponse, FactoryError> {
- let url = Url::parse(FACTORY_DOMAIN)
- .unwrap()
- .join("/v1/foundry/garage")
- .unwrap();
- let token = self.token.lock().unwrap().token().await.map_err(FactoryError::Protocol)?;
- let result = self.client.get(url)
- .header("Authorization", "Bearer ".to_owned() + &token)
- .send().await
- .map_err(FactoryError::Protocol)?;
- handle_json_response::<MyRobotsResponse>(result).await
- }
-
- pub async fn my_published_robots(&self) -> Result<MyRobotsResponse, FactoryError> {
- let url = Url::parse(FACTORY_DOMAIN)
- .unwrap()
- .join("/v1/foundry/published")
- .unwrap();
- let token = self.token.lock().unwrap().token().await.map_err(FactoryError::Protocol)?;
- let result = self.client.get(url)
- .header("Authorization", "Bearer ".to_owned() + &token)
- .send().await
- .map_err(FactoryError::Protocol)?;
- handle_json_response::<MyRobotsResponse>(result).await
- }
-
- pub async fn get(&self, id: String) -> Result<GetRobotResponse, FactoryError> {
- let url = Url::parse(FACTORY_DOMAIN)
- .unwrap()
- .join(&format!("/v1/foundry/vehicles/{}", id))
- .unwrap();
- let token = self.token.lock().unwrap().token().await.map_err(FactoryError::Protocol)?;
- let result = self.client.get(url)
- .header("Authorization", "Bearer ".to_owned() + &token)
- .send().await
- .map_err(FactoryError::Protocol)?;
- handle_json_response::<GetRobotResponse>(result).await
- }
- }
|