Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
parent
e6404f781c
commit
7117b65cf5
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "rlidentitygui",
|
"name": "RLIdentity",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@ -13,5 +13,6 @@ commands.allow = [
|
|||||||
"inject_dll",
|
"inject_dll",
|
||||||
"validate_key",
|
"validate_key",
|
||||||
"check_status",
|
"check_status",
|
||||||
"get_hwid"
|
"get_hwid",
|
||||||
|
"download_assets"
|
||||||
]
|
]
|
||||||
|
|||||||
@ -37,6 +37,13 @@ pub struct KeyValidationResponse {
|
|||||||
pub user: Option<UserInfo>,
|
pub user: Option<UserInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct SaveConfigPayload {
|
||||||
|
#[serde(rename = "spoofedName")]
|
||||||
|
name: String,
|
||||||
|
platform: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct AssetManifest {
|
struct AssetManifest {
|
||||||
injector_hash: String,
|
injector_hash: String,
|
||||||
@ -64,7 +71,7 @@ async fn get_last_epic_id(base_path: &Path) -> String {
|
|||||||
|
|
||||||
// --- commands ---
|
// --- commands ---
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command(rename_all = "snake_case")]
|
||||||
fn get_hwid() -> String {
|
fn get_hwid() -> String {
|
||||||
let output = Command::new("reg")
|
let output = Command::new("reg")
|
||||||
.args(["query", r"HKLM\SOFTWARE\Microsoft\Cryptography", "/v", "MachineGuid"])
|
.args(["query", r"HKLM\SOFTWARE\Microsoft\Cryptography", "/v", "MachineGuid"])
|
||||||
@ -78,11 +85,10 @@ fn get_hwid() -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// strictly avoid returning "unknown" to prevent key sharing bypasses
|
|
||||||
"00000000-0000-0000-0000-000000000000".to_string()
|
"00000000-0000-0000-0000-000000000000".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command(rename_all = "snake_case")]
|
||||||
async fn validate_key(
|
async fn validate_key(
|
||||||
key: String,
|
key: String,
|
||||||
hwid: String,
|
hwid: String,
|
||||||
@ -101,19 +107,20 @@ async fn validate_key(
|
|||||||
.map_err(|e| format!("api schema mismatch: {}", e))
|
.map_err(|e| format!("api schema mismatch: {}", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command(rename_all = "snake_case")]
|
||||||
async fn inject_dll(state: State<'_, AppState>) -> Result<String, String> {
|
async fn inject_dll(state: State<'_, AppState>) -> Result<String, String> {
|
||||||
let injector_path = state.app_data.join("injector.exe");
|
let injector_path = state.app_data.join("injector.exe");
|
||||||
let dll_path = state.app_data.join("RLIdentity.dll");
|
let dll_path = state.app_data.join("RLIdentity.dll");
|
||||||
|
|
||||||
{
|
let is_running = {
|
||||||
let mut sys = state.sys.lock().unwrap();
|
let mut sys = state.sys.lock().unwrap();
|
||||||
// fix: use refresh_processes_specifics and add the remove_dead_processes bool
|
sys.refresh_processes_specifics(ProcessRefreshKind::new());
|
||||||
sys.refresh_processes_specifics(ProcessRefreshKind::new());
|
let x = sys.processes_by_exact_name("RocketLeague.exe").next().is_some(); x
|
||||||
if sys.processes_by_exact_name("RocketLeague.exe").next().is_none() {
|
};
|
||||||
|
|
||||||
|
if !is_running {
|
||||||
return Err("rocket league is not running".into());
|
return Err("rocket league is not running".into());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if !injector_path.exists() || !dll_path.exists() {
|
if !injector_path.exists() || !dll_path.exists() {
|
||||||
return Err("files missing, please update".into());
|
return Err("files missing, please update".into());
|
||||||
@ -132,11 +139,10 @@ sys.refresh_processes_specifics(ProcessRefreshKind::new());
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command(rename_all = "snake_case")]
|
||||||
async fn download_assets(state: State<'_, AppState>) -> Result<(), String> {
|
async fn download_assets(state: State<'_, AppState>) -> Result<(), String> {
|
||||||
fs::create_dir_all(&state.app_data).await.map_err(|e| e.to_string())?;
|
fs::create_dir_all(&state.app_data).await.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
// dynamically fetch latest hashes to avoid brittle hardcoding
|
|
||||||
let manifest: AssetManifest = state.client.get("https://api.rlidentity.me/manifest")
|
let manifest: AssetManifest = state.client.get("https://api.rlidentity.me/manifest")
|
||||||
.send().await.map_err(|e| e.to_string())?
|
.send().await.map_err(|e| e.to_string())?
|
||||||
.json().await.map_err(|e| e.to_string())?;
|
.json().await.map_err(|e| e.to_string())?;
|
||||||
@ -164,29 +170,36 @@ async fn download_assets(state: State<'_, AppState>) -> Result<(), String> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command(rename_all = "snake_case")]
|
||||||
async fn check_status(state: State<'_, AppState>) -> Result<Status, String> {
|
async fn check_status(state: State<'_, AppState>) -> Result<Status, String> {
|
||||||
|
let is_running = {
|
||||||
let mut sys = state.sys.lock().unwrap();
|
let mut sys = state.sys.lock().unwrap();
|
||||||
// fix: use refresh_processes_specifics and add the remove_dead_processes bool
|
sys.refresh_processes_specifics(ProcessRefreshKind::new());
|
||||||
sys.refresh_processes_specifics(ProcessRefreshKind::new());
|
let x = sys.processes_by_exact_name("RocketLeague.exe").next().is_some(); x
|
||||||
let is_running = sys.processes_by_exact_name("RocketLeague.exe").next().is_some();
|
};
|
||||||
|
|
||||||
Ok(Status { is_running, is_injected: false })
|
Ok(Status { is_running, is_injected: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command(rename_all = "snake_case")]
|
||||||
async fn save_config(config_data: String, state: State<'_, AppState>) -> Result<(), String> {
|
async fn save_config(name: String, platform: String, state: State<'_, AppState>) -> Result<(), String> {
|
||||||
let config_path = state.app_data.join("config.json");
|
let config_path = state.app_data.join("config.json");
|
||||||
let temp_path = state.app_data.join("config.json.tmp");
|
let payload = SaveConfigPayload { name, platform };
|
||||||
|
|
||||||
// atomic write: write to tmp then rename to prevent corruption on crash
|
if !state.app_data.exists() {
|
||||||
fs::write(&temp_path, config_data).await.map_err(|e| e.to_string())?;
|
fs::create_dir_all(&state.app_data).await.map_err(|e| e.to_string())?;
|
||||||
fs::rename(temp_path, config_path).await.map_err(|e| e.to_string())
|
}
|
||||||
|
|
||||||
|
let json = serde_json::to_string(&payload).map_err(|e| e.to_string())?;
|
||||||
|
fs::write(config_path, json).await.map_err(|e| e.to_string())
|
||||||
}
|
}
|
||||||
#[tauri::command]
|
|
||||||
|
#[tauri::command(rename_all = "snake_case")]
|
||||||
fn get_app_version(app: tauri::AppHandle) -> String {
|
fn get_app_version(app: tauri::AppHandle) -> String {
|
||||||
app.package_info().version.to_string()
|
app.package_info().version.to_string()
|
||||||
}
|
}
|
||||||
#[tauri::command]
|
|
||||||
|
#[tauri::command(rename_all = "snake_case")]
|
||||||
fn minimize_to_tray(window: WebviewWindow) {
|
fn minimize_to_tray(window: WebviewWindow) {
|
||||||
let _ = window.hide();
|
let _ = window.hide();
|
||||||
}
|
}
|
||||||
@ -222,23 +235,26 @@ pub fn run() {
|
|||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
apply_acrylic(&window, Some((18, 18, 18, 125))).ok();
|
apply_acrylic(&window, Some((18, 18, 18, 125))).ok();
|
||||||
|
|
||||||
let handle = app.handle().clone();
|
let monitor_handle = app.handle().clone();
|
||||||
let tray_menu = tauri::menu::Menu::with_items(app, &[
|
tauri::async_runtime::spawn(async move {
|
||||||
&tauri::menu::MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?,
|
let mut last_seen_running = false;
|
||||||
])?;
|
loop {
|
||||||
|
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
|
||||||
|
|
||||||
let _ = tauri::tray::TrayIconBuilder::new()
|
let state = monitor_handle.state::<AppState>();
|
||||||
.icon(app.default_window_icon().unwrap().clone())
|
let is_running = {
|
||||||
.menu(&tray_menu)
|
let mut sys = state.sys.lock().unwrap();
|
||||||
.on_menu_event(move |_app, event| {
|
sys.refresh_processes_specifics(ProcessRefreshKind::new());
|
||||||
if event.id().as_ref() == "quit" { handle.exit(0); }
|
let x = sys.processes_by_exact_name("RocketLeague.exe").next().is_some(); x
|
||||||
})
|
};
|
||||||
.on_tray_icon_event(|tray, event| {
|
|
||||||
if let tauri::tray::TrayIconEvent::Click { button: tauri::tray::MouseButton::Left, .. } = event {
|
if is_running && !last_seen_running {
|
||||||
let _ = tray.app_handle().get_webview_window("main").unwrap().show();
|
println!("auto-detect: rocket league started. injecting...");
|
||||||
|
let _ = inject_dll(state).await;
|
||||||
}
|
}
|
||||||
})
|
last_seen_running = is_running;
|
||||||
.build(app)?;
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|||||||
15
src/App.tsx
15
src/App.tsx
@ -138,9 +138,20 @@ export default function App() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (initialApiKey) authorize(initialApiKey);
|
if (initialApiKey) authorize(initialApiKey);
|
||||||
syncAssetsAndCheckUpdates();
|
syncAssetsAndCheckUpdates();
|
||||||
tryInvoke("get_app_version").then(v => setVersion(v as string));
|
loadAppVersion();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
async function loadAppVersion() {
|
||||||
|
if (!isTauriRuntime()) return;
|
||||||
|
try {
|
||||||
|
const app = await import("@tauri-apps/api/app");
|
||||||
|
setVersion(await app.getVersion());
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to get app version:", e);
|
||||||
|
setVersion("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function syncAssetsAndCheckUpdates() {
|
async function syncAssetsAndCheckUpdates() {
|
||||||
if (!isTauriRuntime()) return;
|
if (!isTauriRuntime()) return;
|
||||||
try {
|
try {
|
||||||
@ -244,7 +255,7 @@ export default function App() {
|
|||||||
async function inject() {
|
async function inject() {
|
||||||
setStatus("injecting...");
|
setStatus("injecting...");
|
||||||
try {
|
try {
|
||||||
const res = await tryInvoke<string>("inject_dll", { discordId: userData?.discord_id });
|
const res = await tryInvoke<string>("inject_dll");
|
||||||
setLastLog(res || "Successfully Injected!");
|
setLastLog(res || "Successfully Injected!");
|
||||||
setStatus("Successfully Injected!");
|
setStatus("Successfully Injected!");
|
||||||
window.setTimeout(() => setStatus("ready"), 1400);
|
window.setTimeout(() => setStatus("ready"), 1400);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user