Browse Source

Implement Cardlife live lobby api functionality

tags/v0.5.1
NGnius (Graham) 3 years ago
parent
commit
31fb40158c
7 changed files with 213 additions and 3 deletions
  1. +1
    -0
      Cargo.toml
  2. +73
    -0
      src/cardlife/live.rs
  3. +85
    -0
      src/cardlife/live_json.rs
  4. +6
    -0
      src/cardlife/mod.rs
  5. +2
    -2
      src/cardlife/server_json.rs
  6. +46
    -0
      tests/cardlife_live.rs
  7. +0
    -1
      tests/clre_server.rs

+ 1
- 0
Cargo.toml View File

@@ -3,6 +3,7 @@ name = "libfj"
version = "0.1.0"
authors = ["NGnius (Graham) <ngniusness@gmail.com>"]
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



+ 73
- 0
src/cardlife/live.rs View 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
- 0
src/cardlife/live_json.rs View 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)
}
}

+ 6
- 0
src/cardlife/mod.rs View File

@@ -4,3 +4,9 @@ mod server;
mod server_json;
pub use self::server_json::{GameInfo, StatusInfo};
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};

+ 2
- 2
src/cardlife/server_json.rs View File

@@ -24,7 +24,7 @@ pub struct GameInfo {

impl std::string::ToString for GameInfo {
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 {
fn to_string(&self) -> String {
format!("{} ({})", self.name, self.id)
format!("{} ({})", &self.name, &self.id)
}
}

+ 46
- 0
tests/cardlife_live.rs View 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(())
}

tests/cardlife_server.rs → tests/clre_server.rs View File

@@ -1,7 +1,6 @@
use libfj::cardlife;

#[test]
#[allow(unused_variables)]
fn clre_server_init() -> Result<(), ()> {
assert!(cardlife::CLreServer::new("http://localhost:5030").is_ok());
Ok(())

Loading…
Cancel
Save