Browse Source

Fix CRF2 API

master
NGnius (Graham) 5 months ago
parent
commit
e0a7ec1477
4 changed files with 36 additions and 23 deletions
  1. +1
    -1
      Cargo.toml
  2. +7
    -3
      src/robocraft/factory_request_builder.rs
  3. +27
    -18
      src/robocraft2/portal.rs
  4. +1
    -1
      tests/robocraft_factory.rs

+ 1
- 1
Cargo.toml View File

@@ -1,6 +1,6 @@
[package]
name = "libfj"
version = "0.7.1"
version = "0.7.2"
authors = ["NGnius (Graham) <ngniusness@gmail.com>"]
edition = "2018"
description = "An unofficial collection of APIs used in FreeJam games and mods"


+ 7
- 3
src/robocraft/factory_request_builder.rs View File

@@ -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::<FactoryInfo<RoboShopItemsInfo>>().await;
//dbg!(&result);
match result {
Ok(response) => {
response.error_for_status()?
.json::<FactoryInfo<RoboShopItemsInfo>>().await
}
Err(e) => Err(e),
}
Err(result.err().unwrap())
}
}

+ 27
- 18
src/robocraft2/portal.rs View File

@@ -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, Error> {
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<Self, Error> {
pub async fn target(value: String, version: String) -> Result<Self, Error> {
let client = Client::new();
let payload = PortalStartPayload {
target: value.clone(),
@@ -65,7 +70,7 @@ impl PortalTokenProvider {
let check_res = check_response.json::<PortalCheckResponse>().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<Self, Error> {
@@ -79,7 +84,7 @@ impl PortalTokenProvider {
.json(&payload)
.send().await?;
let json_res = response.json::<AuthenticationResponseInfo>().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<Self, Error> {
@@ -93,11 +98,11 @@ impl PortalTokenProvider {
.json(&payload)
.send().await?;
let json_res = response.json::<AuthenticationResponseInfo>().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<Self, Error> {
async fn auto_portal(client: Client, value: String, token: String, version: String) -> Result<Self, Error> {
let payload = PortalStartPayload {
target: value.clone(),
};
@@ -106,7 +111,6 @@ impl PortalTokenProvider {
.json(&payload)
.send().await?;
let start_res = start_response.json::<PortalStartResponse>().await?;

let payload = PortalCheckPayload {
token: start_res.token,
};
@@ -124,22 +128,24 @@ impl PortalTokenProvider {
let check_res = check_response.json::<PortalCheckResponse>().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<Self, Error> {
let progress_res = Self::login_step(&token_data, &client).await?;
async fn login_internal(token_data: PortalCheckResponse, client: Client, target: String, version: String) -> Result<Self, Error> {
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<ProgressionLoginResponse, Error> {
async fn login_step(token_data: &PortalCheckResponse, client: &Client, version: String) -> Result<ProgressionLoginResponse, Error> {
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, Error> {
Self::login_internal(token_data, Client::new(), target).await
pub async fn login(token_data: PortalCheckResponse, target: String, version: String) -> Result<Self, Error> {
Self::login_internal(token_data, Client::new(), target, version).await
}

pub fn get_account_info(&self) -> Result<AccountInfo, Error> {
@@ -182,9 +188,10 @@ impl ITokenProvider for PortalTokenProvider {
.json(&payload)
.send().await?;
self.jwt = refresh_response.json::<PortalCheckResponse>().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")]


+ 1
- 1
tests/robocraft_factory.rs View File

@@ -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;


Loading…
Cancel
Save