#![allow(dead_code)]
use std::fs;
use std::path::Path;
pub fn get_or_create_client_id(data_dir: &Path) -> String {
let id_path = data_dir.join("client_id");
if let Ok(id) = fs::read_to_string(&id_path) {
let id = id.trim().to_string();
if id.len() == 64 && id.chars().all(|c| c.is_ascii_hexdigit()) {
return id;
}
}
let id = generate_id();
let _ = fs::create_dir_all(data_dir);
let _ = fs::write(&id_path, &id);
id
}
fn generate_id() -> String {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use std::time::{SystemTime, UNIX_EPOCH};
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_nanos();
let hostname = std::env::var("HOSTNAME")
.or_else(|_| std::env::var("COMPUTERNAME"))
.unwrap_or_else(|_| "unknown".into());
let pid = std::process::id();
let mut hasher = DefaultHasher::new();
timestamp.hash(&mut hasher);
hostname.hash(&mut hasher);
pid.hash(&mut hasher);
let h1 = hasher.finish();
let mut hasher2 = DefaultHasher::new();
h1.hash(&mut hasher2);
(timestamp ^ 0xDEADBEEF).hash(&mut hasher2);
hostname.len().hash(&mut hasher2);
let h2 = hasher2.finish();
let mut hasher3 = DefaultHasher::new();
h2.hash(&mut hasher3);
(pid as u64 ^ timestamp as u64).hash(&mut hasher3);
let h3 = hasher3.finish();
let mut hasher4 = DefaultHasher::new();
h3.hash(&mut hasher4);
h1.hash(&mut hasher4);
let h4 = hasher4.finish();
format!("{h1:016x}{h2:016x}{h3:016x}{h4:016x}")
}
pub fn is_valid_client_id(id: &str) -> bool {
id.len() == 64 && id.chars().all(|c| c.is_ascii_hexdigit())
}