feat: add epic types and initial draft

This commit is contained in:
Guilherme Werner 2024-01-27 18:18:35 -03:00
parent d7aee90c25
commit 235fb58e99
5 changed files with 180 additions and 1 deletions

View file

@ -113,7 +113,9 @@ impl HttpClient {
/// Send a HTTP GET request and parse the JSON resonse.
#[cfg(feature = "serde")]
pub fn get_json<T: DeserializeOwned>(&mut self, path: &str) -> GDResult<T> { self.request_json("GET", path) }
pub fn get_json<T: DeserializeOwned>(&mut self, path: &str) -> GDResult<T> {
self.request_json("GET", path)
}
/// Send a HTTP Post request with JSON data and parse a JSON response.
#[cfg(feature = "serde")]
@ -121,6 +123,12 @@ impl HttpClient {
self.request_with_json_data("POST", path, data)
}
/// Send a HTTP Post request with form data and parse a JSON response.
#[cfg(feature = "serde")]
pub fn post_form<T: DeserializeOwned>(&mut self, path: &str, data: &[(&str, &str)]) -> GDResult<T> {
self.request_with_form_data("POST", path, data)
}
// NOTE: More methods can be added here as required
/// Send a HTTP request without any data and parse the JSON response.
@ -153,4 +161,22 @@ impl HttpClient {
.into_json::<T>()
.map_err(|e| ProtocolFormat.context(e))
}
/// Send a HTTP request with form data and parse the JSON response.
#[inline]
#[cfg(feature = "serde")]
fn request_with_form_data<T: DeserializeOwned>(
&mut self,
method: &str,
path: &str,
data: &[(&str, &str)],
) -> GDResult<T> {
self.address.set_path(path);
self.client
.request_url(method, &self.address)
.send_form(data)
.map_err(|e| PacketSend.context(e))?
.into_json::<T>()
.map_err(|e| ProtocolFormat.context(e))
}
}

View file

@ -0,0 +1,7 @@
/// The implementation.
pub mod protocol;
/// All types used by the implementation.
pub mod types;
pub use protocol::*;
pub use types::*;

View file

@ -0,0 +1,52 @@
use crate::http::{HTTPSettings, HttpClient};
use crate::protocols::epic::{ClientTokenResponse, Request, Response, SessionFilter};
use crate::{GDResult, TimeoutSettings};
use std::net::{IpAddr, SocketAddr};
/*
/// Query a epic server.
#[inline]
pub fn query(address: &IpAddr, port: Option<u16>) -> GDResult<Response> {
query_with_timeout(address, port, &None)
}
/// Query a epic server.
pub fn query_with_timeout(
address: &IpAddr,
port: Option<u16>,
timeout_settings: &Option<TimeoutSettings>,
) -> GDResult<Response> {
let address = &SocketAddr::new(*address, port.unwrap_or(3001));
let mut client = HttpClient::new(
address,
timeout_settings,
HTTPSettings {
protocol: crate::http::Protocol::HTTP,
hostname: None,
},
)?;
Ok(response.into())
}
*/
pub fn get_client_oauth_token(client: &mut HttpClient, deployment_id: &str) -> GDResult<ClientTokenResponse> {
let form_data = [
("grant_type", "client_credentials"),
("deployment_id", deployment_id),
];
let response = client.post_form::<ClientTokenResponse>("/auth/v1/oauth/token", &form_data)?;
Ok(response.into())
}
pub fn get_server_info(client: &mut HttpClient, deployment_id: &str) -> GDResult<Response> {
let filter = SessionFilter::new("deployment_id", "eq", deployment_id);
let request = Request::new().add_filter(filter);
let path = format!("/matchmaking/v1/{}/filter", deployment_id);
let response = client.post_json::<Response, Request>(&path, request)?;
Ok(response.into())
}

View file

@ -0,0 +1,90 @@
use serde_derive::Deserialize;
use serde_derive::Serialize;
use serde_json::Value;
use std::collections::HashMap;
use crate::protocols::types::CommonPlayer;
use crate::protocols::types::CommonResponse;
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ClientTokenResponse {
pub access_token: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Request {
pub criteria: Vec<SessionFilter>,
}
impl Request {
pub fn new() -> Self {
Self {
criteria: Vec::new(),
}
}
pub fn add_filter(mut self, filter: SessionFilter) -> Self {
self.criteria.push(filter);
self
}
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SessionFilter {
pub key: String,
pub op: String,
pub value: String,
}
impl SessionFilter {
pub fn new(key: &str, op: &str, value: &str) -> Self {
Self {
key: key.to_string(),
op: op.to_string(),
value: value.to_string(),
}
}
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Response {
pub sessions: Vec<Session>,
pub count: u32,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Session {
pub deployment: String,
pub id: String,
pub bucket: String,
pub settings: Settings,
pub total_players: u32,
pub open_public_players: u32,
pub public_players: Vec<String>,
pub started: bool,
pub last_updated: Option<String>,
pub attributes: HashMap<String, Value>,
pub owner: String,
pub owner_platform_id: Option<String>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Settings {
pub max_public_players: u32,
pub allow_invites: bool,
pub should_advertise: bool,
pub allow_read_by_id: bool,
pub allow_join_via_presence: bool,
pub allow_join_in_progress: bool,
pub allow_conference_room: bool,
pub check_sanctions: bool,
pub allow_migration: bool,
pub rejoin_after_kick: String,
pub platforms: Option<Vec<String>>,
}

View file

@ -15,4 +15,8 @@ pub mod unreal2;
/// Reference: [Server Query](https://developer.valvesoftware.com/wiki/Server_queries)
pub mod valve;
/// Reference: [EOS Web API](https://dev.epicgames.com/docs/web-api-ref)
#[cfg(feature = "serde")]
pub mod epic;
pub use types::{ExtraRequestSettings, GenericResponse, Protocol};