game_manager_lib/services/integration/hltb/
client.rs1use crate::services::integration::hltb::models::{AuthInitResponse, GamesFilter, SearchOptions, SearchPayload};
2use serde_json::{json, Value};
3use std::collections::HashMap;
4use std::time::{SystemTime, UNIX_EPOCH};
5
6pub struct HltbClient {
7 client: reqwest::Client,
8 base_url: String,
9 endpoint: String,
10}
11
12impl HltbClient {
13 pub fn new() -> Self {
14 let client = reqwest::Client::builder()
16 .user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
17 .build()
18 .unwrap();
19
20 Self {
21 client,
22 base_url: "https://howlongtobeat.com".to_string(),
23 endpoint: "/api/bleed".to_string(), }
25 }
26
27 async fn get_auth_tokens(&self) -> Result<AuthInitResponse, Box<dyn std::error::Error>> {
29 let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis();
30 let init_url = format!("{}{}/init?t={}", self.base_url, self.endpoint, timestamp);
31
32 let response = self.client.get(&init_url)
33 .header("Referer", &self.base_url)
34 .send()
35 .await?;
36
37 let auth_data: AuthInitResponse = response.json().await?;
38 Ok(auth_data)
39 }
40
41 pub async fn search(&self, game_name: &str) -> Result<Value, Box<dyn std::error::Error>> {
43 let auth = self.get_auth_tokens().await?;
44
45 let search_url = format!("{}{}", self.base_url, self.endpoint);
46
47 let terms: Vec<String> = game_name.split_whitespace().map(|s| s.to_string()).collect();
49 let payload = SearchPayload {
50 search_terms: terms,
51 search_options: SearchOptions {
52 games: GamesFilter { platform: "".to_string() },
53 },
54 };
55
56 let mut json_body: HashMap<String, Value> = serde_json::to_value(payload)?
58 .as_object()
59 .unwrap()
60 .clone()
61 .into_iter()
62 .collect();
63
64 json_body.insert(auth.hp_key.clone(), json!(auth.hp_val));
66
67 let response = self.client.post(&search_url)
69 .header("Origin", &self.base_url)
70 .header("Referer", &self.base_url)
71 .header("x-auth-token", &auth.token)
72 .header("x-hp-key", &auth.hp_key)
73 .header("x-hp-val", &auth.hp_val)
74 .json(&json_body)
75 .send()
76 .await?;
77
78 let data: Value = response.json().await?;
79 Ok(data)
80 }
81}