Skip to content

Commit 45b34d4

Browse files
committed
proxy support added, auth not completely working yet
1 parent 9972c06 commit 45b34d4

File tree

5 files changed

+190
-152
lines changed

5 files changed

+190
-152
lines changed

src-tauri/src/account.rs

Lines changed: 97 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use urlencoding::{decode, encode};
1212
use crate::{
1313
app_handle,
1414
log::{alert, log},
15+
set_ratelimit, set_thread_status,
1516
};
1617

1718
#[derive(PartialEq, Clone, Debug)]
@@ -20,7 +21,7 @@ enum AccType {
2021
UNCLAIMED,
2122
}
2223

23-
#[derive(Debug)]
24+
#[derive(Clone, Debug)]
2425
pub struct Account {
2526
token: String,
2627
refresh_token: String,
@@ -90,7 +91,7 @@ impl Account {
9091
} else {
9192
ClientBuilder::new().default_headers(map).build().ok()?
9293
};
93-
if self.get_type() == AccType::UNCLAIMED {
94+
if self.acc_type == AccType::UNCLAIMED {
9495
let data = format!(
9596
r#"{{
9697
"profileName" : "{}"
@@ -222,12 +223,60 @@ impl Account {
222223
None
223224
}
224225

225-
pub fn get_token(&self) -> String {
226-
self.token.clone()
227-
}
226+
pub fn check(&self, name: String, proxy: Option<Proxy>) -> Result<bool, String> {
227+
let client = match if let Some(proxy) = proxy {
228+
ClientBuilder::new().proxy(proxy).build()
229+
} else {
230+
ClientBuilder::new().build()
231+
} {
232+
Ok(c) => c,
233+
Err(_) => return Err("Failed to build client for checking!".to_string()),
234+
};
235+
236+
let Ok(res) = client
237+
.get(format!(
238+
"https://api.minecraftservices.com/minecraft/profile/name/{}/available",
239+
name
240+
))
241+
.header("Authorization", format!("Bearer {}", self.token))
242+
.send()
243+
else {
244+
return Err("Failed to send request for checking".to_string());
245+
};
246+
247+
let status = res.status().as_u16();
248+
if status == 401 {
249+
return Err("A check request returned unathorized!".to_string());
250+
} else if status == 429 {
251+
set_ratelimit(true);
252+
return Err("Hit a ratelimit, sleeping for 300 seconds to clear it.".to_string());
253+
} else if status != 200 {
254+
return Err(format!(
255+
"Checking request returned status code {} with body: {}",
256+
status,
257+
res.text()
258+
.unwrap_or_else(|_| "Failed to get body.".to_string())
259+
));
260+
}
261+
262+
let Ok(body) = res.text() else {
263+
return Err("Failed to get body from check request.".to_string());
264+
};
228265

229-
fn get_type(&self) -> AccType {
230-
self.acc_type.clone()
266+
if body.contains("AVAILABLE") {
267+
return Ok(true);
268+
} else if body.contains("DUPLICATE") {
269+
return Ok(false);
270+
} else if body.contains("NOT_ALLOWED") {
271+
alert("The name is blocked by mojang!");
272+
set_thread_status(false);
273+
return Err("The name is blocked by mojang!".to_string());
274+
} else {
275+
return Err(format!(
276+
"Check request response body is malformed: {}",
277+
body
278+
));
279+
}
231280
}
232281

233282
fn check_type(token: String, proxy: Option<Proxy>) -> Option<AccType> {
@@ -277,7 +326,7 @@ impl Account {
277326
}
278327

279328
fn reauth(&mut self, proxy: Option<Proxy>) -> Result<(), String> {
280-
let Ok(client) = (if let Some(proxy) = proxy {
329+
let Ok(client) = (if let Some(proxy) = proxy.clone() {
281330
ClientBuilder::new().cookie_store(true).proxy(proxy).build()
282331
} else {
283332
ClientBuilder::new().cookie_store(true).build()
@@ -301,11 +350,35 @@ impl Account {
301350
};
302351

303352
let Some(access_token) = body.get("access_token").and_then(|v| v.as_str()) else {
304-
return Err("No access_token in response!".to_string());
353+
log(
354+
"ERROR",
355+
Color::from((255, 0, 0)),
356+
"Failed to reauth with refresh_token, trying full auth!",
357+
);
358+
match Self::auth(&self.user, &self.passwd, proxy) {
359+
Ok((bearer, refresh_token)) => {
360+
self.token = bearer;
361+
self.refresh_token = refresh_token;
362+
return Ok(());
363+
}
364+
Err(e) => return Err(e),
365+
}
305366
};
306367

307368
let Some(refresh_token) = body.get("refresh_token").and_then(|v| v.as_str()) else {
308-
return Err("No refresh_token in response!".to_string());
369+
log(
370+
"ERROR",
371+
Color::from((255, 0, 0)),
372+
"Failed to reauth with refresh_token, trying full auth!",
373+
);
374+
match Self::auth(&self.user, &self.passwd, proxy) {
375+
Ok((bearer, refresh_token)) => {
376+
self.token = bearer;
377+
self.refresh_token = refresh_token;
378+
return Ok(());
379+
}
380+
Err(e) => return Err(e),
381+
}
309382
};
310383

311384
let body = json!({
@@ -455,8 +528,8 @@ impl Account {
455528
let Ok(res) = client.get("https://login.live.com/oauth20_authorize.srf?client_id=000000004C12AE6F&redirect_uri=https://login.live.com/oauth20_desktop.srf&scope=service::user.auth.xboxlive.com::MBI_SSL&display=touch&response_type=token&locale=en").send() else {
456529
return Err("Failed to send initial request for auth!".to_string()) };
457530

458-
let val_regex = Regex::new("value=\"(.+?)\"").unwrap();
459-
let url_post_regex = Regex::new("urlPost:'(.+?)'").unwrap();
531+
let val_regex = Regex::new(r#"value=\\\"(.*?)\\\""#).unwrap();
532+
let url_post_regex = Regex::new(r#"urlPost":"(.+?)""#).unwrap();
460533

461534
let Ok(res) = res.text() else {
462535
return Err("Failed to extract text from initial request for auth!".to_string());
@@ -554,12 +627,12 @@ impl Account {
554627

555628
let body = json!({
556629
"Properties": {
557-
"Authmethod": "RPS",
558-
"Sitename": "user.auth.xboxlive.com",
559-
"Rpsticket": access_token,
630+
"AuthMethod": "RPS",
631+
"SiteName": "user.auth.xboxlive.com",
632+
"RpsTicket": access_token,
560633
},
561-
"Relyingparty": "http://auth.xboxlive.com",
562-
"Tokentype": "JWT",
634+
"RelyingParty": "http://auth.xboxlive.com",
635+
"TokenType": "JWT",
563636
});
564637

565638
let mut headers = HeaderMap::new();
@@ -662,8 +735,8 @@ impl Account {
662735
};
663736

664737
let body = json!({
665-
"identityToken" : format!("XBL3.0 x={};{}", uhs, token),
666-
"ensureLegacyEnabled" : true
738+
"identityToken" : dbg!(format!("XBL3.0 x={};{}", uhs, token)),
739+
"ensureLegacyEnabled": true
667740
});
668741

669742
let Ok(res) = client
@@ -674,9 +747,12 @@ impl Account {
674747
return Err("Failed to send request for bearer!".to_string());
675748
};
676749

677-
let Ok(data) = res.json::<Value>() else {
750+
println!("{}", res.text().unwrap());
751+
752+
/* let Ok(data) = res.json::<Value>() else {
678753
return Err("Failed to parse response for bearer!".to_string());
679-
};
754+
}; */
755+
let data = Value::Null;
680756

681757
let Some(bearer) = data.get("access_token").and_then(|v| v.as_str()) else {
682758
return Err("Failed to extract bearer!".to_string());

src-tauri/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use tauri::{AppHandle, Manager};
77

88
static APP_HANDLE: OnceLock<AppHandle> = OnceLock::new();
99
static THREAD_STATUS: OnceLock<Mutex<bool>> = OnceLock::new();
10+
static RATELIMIT: OnceLock<Mutex<bool>> = OnceLock::new();
1011

1112
fn app_handle<'a>() -> &'a AppHandle {
1213
APP_HANDLE.get().unwrap()
@@ -23,6 +24,17 @@ fn set_thread_status(param: bool) {
2324
let mut data = mutex.lock().unwrap();
2425
*data = param;
2526
}
27+
fn get_ratelimit() -> bool {
28+
let mutex = RATELIMIT.get_or_init(|| Mutex::new(false));
29+
let data = mutex.lock().unwrap();
30+
*data
31+
}
32+
33+
fn set_ratelimit(param: bool) {
34+
let mutex = RATELIMIT.get_or_init(|| Mutex::new(false));
35+
let mut data = mutex.lock().unwrap();
36+
*data = param;
37+
}
2638

2739
#[cfg_attr(mobile, tauri::mobile_entry_point)]
2840
pub fn run() {

0 commit comments

Comments
 (0)