diff --git a/src/lib.rs b/src/lib.rs index 44a205d..92dd606 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,8 @@ -use std::convert::TryInto; +use std::{collections::HashMap, convert::TryInto, thread, time}; +use hmacsha1::hmac_sha1; +use reqwest::{Url, cookie::CookieStore, header::{COOKIE, USER_AGENT}}; use serde::{Serialize, Deserialize}; +use log::*; pub mod steamapi; @@ -25,6 +28,7 @@ pub struct SteamGuardAccount { pub server_time: u64, pub uri: String, pub fully_enrolled: bool, + pub device_id: String, #[serde(rename = "Session")] pub session: Option, } @@ -66,6 +70,7 @@ impl SteamGuardAccount { server_time: 0, uri: String::from(""), fully_enrolled: false, + device_id: String::from(""), session: Option::None, } } @@ -95,6 +100,61 @@ impl SteamGuardAccount { return String::from_utf8(code_array.iter().map(|c| *c).collect()).unwrap() } + + fn get_confirmation_query_params(&self, tag: &str) -> HashMap<&str, String> { + let session = self.session.clone().unwrap(); + let time = steamapi::get_server_time(); + let mut params = HashMap::new(); + params.insert("p", self.device_id.clone()); + params.insert("a", session.steam_id.to_string()); + params.insert("k", self.generate_confirmation_hash_for_time(time, tag)); + params.insert("t", time.to_string()); + params.insert("m", String::from("android")); + params.insert("tag", String::from(tag)); + return params; + } + + fn generate_confirmation_hash_for_time(&self, time: i64, tag: &str) -> String { + let decode: &[u8] = &base64::decode(&self.identity_secret).unwrap(); + let time_bytes = build_time_bytes(time); + let tag_bytes = tag.as_bytes(); + let array = [&time_bytes, tag_bytes].concat(); + let hash = hmac_sha1(decode, &array); + let encoded = base64::encode(hash); + return encoded; + } + + pub fn get_trade_confirmations(&self) { + // uri: "https://steamcommunity.com/mobileconf/conf" + // confirmation details: + let url = "https://steamcommunity.com".parse::().unwrap(); + let cookies = reqwest::cookie::Jar::default(); + let session_id = self.session.clone().unwrap().session_id; + let cookie_val = format!("sessionid={}", session_id); + cookies.add_cookie_str(cookie_val.as_str(), &url); + let client = reqwest::blocking::ClientBuilder::new() + .build() + .unwrap(); + + loop { + match client + .get("https://steamcommunity.com/mobileconf/conf".parse::().unwrap()) + .header("X-Requested-With", "com.valvesoftware.android.steam.community") + .header(USER_AGENT, "Mozilla/5.0 (Linux; U; Android 4.1.1; en-us; Google Nexus 4 - 4.1.1 - API 16 - 768x1280 Build/JRO03S) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30") + .header(COOKIE, cookies.cookies(&url).unwrap()) + .query(&self.get_confirmation_query_params("conf")) + .send() { + Ok(resp) => { + info!("{:?}", resp); + break; + } + Err(e) => { + error!("error: {:?}", e); + thread::sleep(time::Duration::from_secs(3)); + } + } + } + } } #[cfg(test)] diff --git a/src/main.rs b/src/main.rs index 4db61a6..2f29419 100644 --- a/src/main.rs +++ b/src/main.rs @@ -141,6 +141,9 @@ fn main() { return; } } + + info!("Checking for trade confirmations"); + account.get_trade_confirmations(); } } else { let server_time = steamapi::get_server_time(); diff --git a/src/steamapi.rs b/src/steamapi.rs index aa88282..77da21d 100644 --- a/src/steamapi.rs +++ b/src/steamapi.rs @@ -104,7 +104,7 @@ impl UserLogin { self.cookies.add_cookie_str("mobileClient=android", &url); self.cookies.add_cookie_str("Steam_Language=english", &url); - let _ = self.client + let resp = self.client .get("https://steamcommunity.com/login?oauth_client_id=DE45CD61&oauth_scope=read_profile%20write_profile%20read_client%20write_client".parse::().unwrap()) .header("X-Requested-With", "com.valvesoftware.android.steam.community") .header(USER_AGENT, "Mozilla/5.0 (Linux; U; Android 4.1.1; en-us; Google Nexus 4 - 4.1.1 - API 16 - 768x1280 Build/JRO03S) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30") @@ -113,6 +113,7 @@ impl UserLogin { // .header(COOKIE, "Steam_Language=english") .header(COOKIE, self.cookies.cookies(&url).unwrap()) .send(); + trace!("{:?}", resp); trace!("cookies: {:?}", self.cookies); }