Implement Cardlife live lobby api functionality
This commit is contained in:
parent
b02215b223
commit
31fb40158c
7 changed files with 213 additions and 3 deletions
|
@ -3,6 +3,7 @@ name = "libfj"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["NGnius (Graham) <ngniusness@gmail.com>"]
|
authors = ["NGnius (Graham) <ngniusness@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
description = "An unofficial collection of APIs used in FreeJam games and mods"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|
73
src/cardlife/live.rs
Normal file
73
src/cardlife/live.rs
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
use reqwest::{Client, Error};
|
||||||
|
use url::{Url};
|
||||||
|
|
||||||
|
use crate::cardlife::{AuthenticationInfo, AuthenticationPayload, LobbyInfo, LobbyPayload};
|
||||||
|
|
||||||
|
const AUTHENTICATION_DOMAIN: &str = "https://live-auth.cardlifegame.com/";
|
||||||
|
const LOBBY_DOMAIN: &str = "https://live-lobby.cardlifegame.com/";
|
||||||
|
|
||||||
|
pub struct LiveAPI {
|
||||||
|
client: Client,
|
||||||
|
auth: Option<AuthenticationInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveAPI {
|
||||||
|
pub fn new() -> LiveAPI {
|
||||||
|
LiveAPI {
|
||||||
|
client: Client::new(),
|
||||||
|
auth: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn login_email(email: &str, password: &str) -> Result<LiveAPI, Error> {
|
||||||
|
let mut instance = LiveAPI::new();
|
||||||
|
let result = instance.authenticate_email(email, password).await;
|
||||||
|
if let Ok(response) = result {
|
||||||
|
instance.auth = Some(response);
|
||||||
|
return Ok(instance);
|
||||||
|
} else {
|
||||||
|
return Err(result.err().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn authenticate_email(&mut self, email: &str, password: &str) -> Result<AuthenticationInfo, Error> {
|
||||||
|
let url = Url::parse(AUTHENTICATION_DOMAIN)
|
||||||
|
.unwrap()
|
||||||
|
.join("/api/auth/authenticate")
|
||||||
|
.unwrap();
|
||||||
|
let payload = AuthenticationPayload {
|
||||||
|
email_address: email.to_string(),
|
||||||
|
password: password.to_string()
|
||||||
|
};
|
||||||
|
let result = self.client.post(url)
|
||||||
|
.json(&payload)
|
||||||
|
.send().await;
|
||||||
|
if let Ok(response) = result {
|
||||||
|
let res = response.json::<AuthenticationInfo>().await;
|
||||||
|
if let Ok(auth) = &res {
|
||||||
|
self.auth = Some(auth.clone());
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
Err(result.err().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn lobbies(&self) -> Result<LobbyInfo, Error> {
|
||||||
|
let url = Url::parse(LOBBY_DOMAIN)
|
||||||
|
.unwrap()
|
||||||
|
.join("/api/client/games")
|
||||||
|
.unwrap();
|
||||||
|
let public_id;
|
||||||
|
if let Some(auth) = &self.auth {
|
||||||
|
public_id = auth.public_id.clone();
|
||||||
|
} else {
|
||||||
|
public_id = "".to_string();
|
||||||
|
}
|
||||||
|
let payload = LobbyPayload{public_id};
|
||||||
|
let result = self.client.post(url).json(&payload).send().await;
|
||||||
|
if let Ok(response) = result {
|
||||||
|
return response.json::<LobbyInfo>().await;
|
||||||
|
}
|
||||||
|
Err(result.err().unwrap())
|
||||||
|
}
|
||||||
|
}
|
85
src/cardlife/live_json.rs
Normal file
85
src/cardlife/live_json.rs
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
|
pub(crate) struct AuthenticationPayload {
|
||||||
|
#[serde(rename = "EmailAddress")]
|
||||||
|
pub email_address: String,
|
||||||
|
#[serde(rename = "Password")]
|
||||||
|
pub password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
|
pub struct AuthenticationInfo {
|
||||||
|
#[serde(rename = "PublicId")]
|
||||||
|
pub public_id: String,
|
||||||
|
#[serde(rename = "EmailAddress")]
|
||||||
|
pub email_address: String,
|
||||||
|
#[serde(rename = "DisplayName")]
|
||||||
|
pub display_name: String,
|
||||||
|
#[serde(rename = "Purchases")]
|
||||||
|
purchases: Vec<String>, // ???
|
||||||
|
#[serde(rename = "Flags")]
|
||||||
|
flags: Vec<String>, // ???
|
||||||
|
#[serde(rename = "Confirmed")]
|
||||||
|
pub confirmed: bool,
|
||||||
|
#[serde(rename = "Token")]
|
||||||
|
pub token: String,
|
||||||
|
#[serde(rename = "SteamId")]
|
||||||
|
steam_id: Option<String>, // ???
|
||||||
|
#[serde(rename = "ID")]
|
||||||
|
pub id: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::string::ToString for AuthenticationInfo {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
format!("{} ({})", &self.display_name, &self.public_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
|
pub(crate) struct LobbyPayload {
|
||||||
|
#[serde(rename = "PublicId")]
|
||||||
|
pub public_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
|
pub struct LobbyInfo {
|
||||||
|
#[serde(rename = "Games")]
|
||||||
|
pub games: Vec<LiveGameInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
|
pub struct LiveGameInfo {
|
||||||
|
#[serde(rename = "Id")]
|
||||||
|
pub id: usize,
|
||||||
|
#[serde(rename = "WorldName")]
|
||||||
|
pub world_name: String,
|
||||||
|
#[serde(rename = "MaxPlayers")]
|
||||||
|
pub max_players: usize,
|
||||||
|
#[serde(rename = "CurrentPlayers")]
|
||||||
|
pub current_players: usize,
|
||||||
|
#[serde(rename = "GameVersion")]
|
||||||
|
pub game_version: String,
|
||||||
|
#[serde(rename = "Ping")]
|
||||||
|
pub ping: usize,
|
||||||
|
#[serde(rename = "HasPlayed")]
|
||||||
|
pub has_played: bool,
|
||||||
|
#[serde(rename = "HasPassword")]
|
||||||
|
pub has_password: bool,
|
||||||
|
#[serde(rename = "IsPvp")]
|
||||||
|
pub is_pvp: bool,
|
||||||
|
#[serde(rename = "IsAntiCheatEnabled")]
|
||||||
|
pub is_anticheat_enabled: bool,
|
||||||
|
#[serde(rename = "IsOfficial")]
|
||||||
|
pub is_official: bool,
|
||||||
|
#[serde(rename = "ModInfo")]
|
||||||
|
pub mod_info: String,
|
||||||
|
#[serde(rename = "Region")]
|
||||||
|
pub region: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::string::ToString for LiveGameInfo {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
format!("{} ({}):{}/{}", self.world_name, self.id, self.current_players, self.max_players)
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,3 +4,9 @@ mod server;
|
||||||
mod server_json;
|
mod server_json;
|
||||||
pub use self::server_json::{GameInfo, StatusInfo};
|
pub use self::server_json::{GameInfo, StatusInfo};
|
||||||
pub use self::server::{CLreServer};
|
pub use self::server::{CLreServer};
|
||||||
|
|
||||||
|
mod live;
|
||||||
|
mod live_json;
|
||||||
|
pub use self::live::{LiveAPI};
|
||||||
|
pub use self::live_json::{AuthenticationInfo, LobbyInfo, LiveGameInfo};
|
||||||
|
pub(crate) use self::live_json::{AuthenticationPayload, LobbyPayload};
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub struct GameInfo {
|
||||||
|
|
||||||
impl std::string::ToString for GameInfo {
|
impl std::string::ToString for GameInfo {
|
||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
format!("{} ({})", self.world_name, self.game_guid)
|
format!("{} ({})", &self.world_name, &self.game_guid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +58,6 @@ pub struct PlayerStatusInfo {
|
||||||
|
|
||||||
impl std::string::ToString for PlayerStatusInfo {
|
impl std::string::ToString for PlayerStatusInfo {
|
||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
format!("{} ({})", self.name, self.id)
|
format!("{} ({})", &self.name, &self.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
46
tests/cardlife_live.rs
Normal file
46
tests/cardlife_live.rs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
use libfj::cardlife;
|
||||||
|
|
||||||
|
const EMAIL: &str = "";
|
||||||
|
const PASSWORD: &str = "";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn live_api_init() -> Result<(), ()> {
|
||||||
|
cardlife::LiveAPI::new();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn live_api_init_auth() -> Result<(), ()> {
|
||||||
|
let live = cardlife::LiveAPI::login_email(EMAIL, PASSWORD).await;
|
||||||
|
assert!(live.is_err()); // invalid credentials
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn live_api_authenticate() -> Result<(), ()> {
|
||||||
|
let mut live = cardlife::LiveAPI::new();
|
||||||
|
let result = live.authenticate_email(EMAIL, PASSWORD).await;
|
||||||
|
assert!(result.is_err()); // invalid credentials
|
||||||
|
/*let auth_info = result.unwrap();
|
||||||
|
assert_ne!(auth_info.token, "");
|
||||||
|
assert_ne!(auth_info.display_name, "");
|
||||||
|
assert_eq!(auth_info.email_address, EMAIL);
|
||||||
|
assert_ne!(auth_info.public_id, "");
|
||||||
|
println!("AuthenticationInfo.to_string() -> `{}`", auth_info.to_string());*/
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn live_api_lobbies() -> Result<(), ()> {
|
||||||
|
//let live = cardlife::LiveAPI::login_email(EMAIL, PASSWORD).await.unwrap();
|
||||||
|
let live = cardlife::LiveAPI::new();
|
||||||
|
let result = live.lobbies().await;
|
||||||
|
assert!(result.is_err());
|
||||||
|
/*
|
||||||
|
let lobby_info = result.unwrap();
|
||||||
|
assert_ne!(lobby_info.games.len(), 0);
|
||||||
|
for game in &lobby_info.games {
|
||||||
|
println!("LiveGameInfo.to_string() -> `{}`", game.to_string());
|
||||||
|
}*/
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
use libfj::cardlife;
|
use libfj::cardlife;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn clre_server_init() -> Result<(), ()> {
|
fn clre_server_init() -> Result<(), ()> {
|
||||||
assert!(cardlife::CLreServer::new("http://localhost:5030").is_ok());
|
assert!(cardlife::CLreServer::new("http://localhost:5030").is_ok());
|
||||||
Ok(())
|
Ok(())
|
Loading…
Add table
Reference in a new issue