From e0a7ec14772639d34317554d5e8474a5cfe08255 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sat, 11 Nov 2023 15:51:56 -0500 Subject: [PATCH] Fix CRF2 API --- Cargo.toml | 2 +- src/robocraft/factory_request_builder.rs | 10 ++++-- src/robocraft2/portal.rs | 45 ++++++++++++++---------- tests/robocraft_factory.rs | 2 +- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b92780e..1531d70 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libfj" -version = "0.7.1" +version = "0.7.2" authors = ["NGnius (Graham) "] edition = "2018" description = "An unofficial collection of APIs used in FreeJam games and mods" diff --git a/src/robocraft/factory_request_builder.rs b/src/robocraft/factory_request_builder.rs index a84a0ba..9bbaec2 100644 --- a/src/robocraft/factory_request_builder.rs +++ b/src/robocraft/factory_request_builder.rs @@ -248,9 +248,13 @@ impl FactorySearchBuilder { self.reqwest_builder = self.reqwest_builder.header("Authorization", "Web ".to_owned() + &token); } let result = self.reqwest_builder.send().await; - if let Ok(response) = result { - return response.json::>().await; + //dbg!(&result); + match result { + Ok(response) => { + response.error_for_status()? + .json::>().await + } + Err(e) => Err(e), } - Err(result.err().unwrap()) } } diff --git a/src/robocraft2/portal.rs b/src/robocraft2/portal.rs index d311584..62c94cc 100644 --- a/src/robocraft2/portal.rs +++ b/src/robocraft2/portal.rs @@ -6,6 +6,9 @@ use reqwest::{Client, Error}; use serde_json::from_slice; use chrono::{DateTime, naive::NaiveDateTime, Utc}; +const GAME_VERSION: &str = "100.0"; // currently, this accepts any version >= current public release +const GAME_TARGET: &str = "Techblox"; + /// Token generator for authenticated API endpoints #[async_trait::async_trait] pub trait ITokenProvider { @@ -25,16 +28,18 @@ pub struct PortalTokenProvider { client: Client, /// target game target: String, + /// game version + version: String, } impl PortalTokenProvider { /// Login through the web browser portal pub async fn portal() -> Result { - Self::target("Techblox".to_owned()).await + Self::target(GAME_TARGET.to_owned(), GAME_VERSION.to_owned()).await } /// Login through the portal with a custom target value - pub async fn target(value: String) -> Result { + pub async fn target(value: String, version: String) -> Result { let client = Client::new(); let payload = PortalStartPayload { target: value.clone(), @@ -65,7 +70,7 @@ impl PortalTokenProvider { let check_res = check_response.json::().await?; // login with token we just got - Self::login_internal(check_res, client, value).await + Self::login_internal(check_res, client, value, version).await } pub async fn with_email(email: &str, password: &str) -> Result { @@ -79,7 +84,7 @@ impl PortalTokenProvider { .json(&payload) .send().await?; let json_res = response.json::().await?; - Self::auto_portal(client, "Techblox".to_owned(), json_res.token).await + Self::auto_portal(client, GAME_TARGET.to_owned(), json_res.token, GAME_VERSION.to_owned()).await } pub async fn with_username(username: &str, password: &str) -> Result { @@ -93,11 +98,11 @@ impl PortalTokenProvider { .json(&payload) .send().await?; let json_res = response.json::().await?; - Self::auto_portal(client, "Techblox".to_owned(), json_res.token).await + Self::auto_portal(client, GAME_TARGET.to_owned(), json_res.token, GAME_VERSION.to_owned()).await } /// Automatically validate portal - async fn auto_portal(client: Client, value: String, token: String) -> Result { + async fn auto_portal(client: Client, value: String, token: String, version: String) -> Result { let payload = PortalStartPayload { target: value.clone(), }; @@ -106,7 +111,6 @@ impl PortalTokenProvider { .json(&payload) .send().await?; let start_res = start_response.json::().await?; - let payload = PortalCheckPayload { token: start_res.token, }; @@ -124,22 +128,24 @@ impl PortalTokenProvider { let check_res = check_response.json::().await?; // login with token we just got - Self::login_internal(check_res, client, value).await + Self::login_internal(check_res, client, value, version).await } - async fn login_internal(token_data: PortalCheckResponse, client: Client, target: String) -> Result { - let progress_res = Self::login_step(&token_data, &client).await?; + async fn login_internal(token_data: PortalCheckResponse, client: Client, target: String, version: String) -> Result { + let progress_res = Self::login_step(&token_data, &client, version.clone()).await?; Ok(Self { token: progress_res, jwt: token_data, client: client, target: target, + version: version, }) } - async fn login_step(token_data: &PortalCheckResponse, client: &Client) -> Result { + async fn login_step(token_data: &PortalCheckResponse, client: &Client, version: String) -> Result { let payload = ProgressionLoginPayload { token: token_data.token.clone(), + client_version: version, }; let progress_response = client.post("https://progression.production.robocraft2.com/login/fj") .header("Content-Type", "application/json") @@ -149,8 +155,8 @@ impl PortalTokenProvider { } /// Login using the portal token data from a previous portal authentication - pub async fn login(token_data: PortalCheckResponse, target: String) -> Result { - Self::login_internal(token_data, Client::new(), target).await + pub async fn login(token_data: PortalCheckResponse, target: String, version: String) -> Result { + Self::login_internal(token_data, Client::new(), target, version).await } pub fn get_account_info(&self) -> Result { @@ -182,9 +188,10 @@ impl ITokenProvider for PortalTokenProvider { .json(&payload) .send().await?; self.jwt = refresh_response.json::().await?; - self.token = Self::login_step(&self.jwt, &self.client).await?; + self.token = Self::login_step(&self.jwt, &self.client, self.version.clone()).await?; } Ok(self.token.token.clone().unwrap()) + //Ok(self.jwt.token.clone()) } } @@ -220,7 +227,7 @@ pub(crate) struct PortalStartPayload { pub target: String, } -#[derive(Deserialize, Serialize, Clone)] +#[derive(Deserialize, Serialize, Clone, Debug)] pub(crate) struct PortalStartResponse { #[serde(rename = "Token")] pub token: String, @@ -255,11 +262,13 @@ impl PortalCheckResponse { #[derive(Deserialize, Serialize, Clone)] pub(crate) struct ProgressionLoginPayload { - #[serde(rename = "token")] + #[serde(rename = "Token")] pub token: String, + #[serde(rename = "ClientVersion")] + pub client_version: String, } -#[derive(Deserialize, Serialize, Clone)] +#[derive(Deserialize, Serialize, Clone, Debug)] pub(crate) struct ProgressionLoginResponse { #[serde(rename = "success")] pub success: bool, @@ -282,7 +291,7 @@ pub(crate) struct RefreshTokenPayload { } /// Robocraft2 account information. -#[derive(Deserialize, Serialize, Clone)] +#[derive(Deserialize, Serialize, Clone, Debug)] pub struct AccountInfo { /// User's public ID #[serde(rename = "PublicId")] diff --git a/tests/robocraft_factory.rs b/tests/robocraft_factory.rs index b3c6012..073e4fc 100644 --- a/tests/robocraft_factory.rs +++ b/tests/robocraft_factory.rs @@ -80,7 +80,7 @@ async fn robocraft_factory_custom_query() -> Result<(), ()> { #[tokio::test] async fn robocraft_factory_player_query() -> Result<(), ()> { let result = builder() - .text("Spacecam".to_string()) // there is a featured robot by this user, so this should never fail + .text("Zalera57".to_string()) // there is a featured robot by this user, so this should never fail .text_search_type(robocraft::FactoryTextSearchType::Player) .items_per_page(10) .send().await;