mod error;
mod test;
pub use error::*;
use crate::{EventTag, LootAction, LootServiceResponse};
use reqwest::header::{HeaderMap, HeaderValue, ACCEPT, AUTHORIZATION, CONTENT_TYPE};
use reqwest::Client;
use serde::de::DeserializeOwned;
use serde::Serialize;
pub enum MicroversusEnv {
Dev { world: String },
Prod { world: String },
}
impl MicroversusEnv {
pub fn url(&self, path: &str) -> String {
match self {
Self::Dev { world } => format!("https://{}.microversus.dev{}", world, path),
Self::Prod { world } => format!("https://{}.microversus.run{}", world, path),
}
}
}
pub struct MicroversusApi {
client: Client,
env: MicroversusEnv,
auth_token: Option<String>,
}
impl MicroversusApi {
pub fn new(world: &str, env: &str, token: Option<String>) -> Self {
let client = Client::new();
match env {
"prod" => Self {
client,
env: MicroversusEnv::Prod {
world: world.into(),
},
auth_token: token.clone(),
},
_ => Self {
client,
env: MicroversusEnv::Dev {
world: world.into(),
},
auth_token: token.clone(),
},
}
}
pub async fn get_loot(
&self,
encounter_id: &str,
tags: Option<Vec<EventTag>>,
) -> Result<LootServiceResponse, MicroversusApiError> {
post_json(
&self.client,
&self.env.url("/loot"),
self.build_headers(),
&LootAction::GetResult {
encounter_id: encounter_id.into(),
tags,
record_event: Some(true),
},
)
.await
}
fn build_headers(&self) -> HeaderMap {
let mut headers = HeaderMap::new();
headers.insert(ACCEPT, HeaderValue::from_static("application/json"));
headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
if let Some(token_str) = self.auth_token.clone() {
let value = format!("Bearer {}", token_str);
headers.insert(
AUTHORIZATION,
HeaderValue::from_str(&value).expect("Invalid token format"),
);
}
headers
}
}
async fn post_json<T: Serialize, R: DeserializeOwned>(
client: &Client,
url: &str,
headers: HeaderMap,
body: &T,
) -> Result<R, MicroversusApiError> {
tracing::debug!("url: {} => {}", url, serde_json::to_string(&body).unwrap());
let response = client
.post(url)
.headers(headers)
.json(body)
.send()
.await
.map_err(MicroversusApiError::Request)?;
response
.error_for_status()?
.json::<R>()
.await
.map_err(MicroversusApiError::Request)
}