OneLauncher-Cracked/packages/oneclient_auth/src/offline.rs
2026-07-28 12:11:02 +02:00

54 lines
1.5 KiB
Rust

use chrono::{Duration, Utc};
use md5::{Digest, Md5};
use uuid::Uuid;
use super::error::AuthError;
use super::data::{AccountKind, MinecraftAccount};
use crate::error::AuthResult;
pub fn offline_uuid(username: &str) -> Uuid {
let mut hasher = Md5::new();
hasher.update(format!("OfflinePlayer:{username}").as_bytes());
let digest = hasher.finalize();
let mut bytes = [0u8; 16];
bytes.copy_from_slice(&digest);
bytes[6] = (bytes[6] & 0x0f) | 0x30;
bytes[8] = (bytes[8] & 0x3f) | 0x80;
Uuid::from_bytes(bytes)
}
pub fn validate_offline_username(username: &str) -> AuthResult<()> {
let len = username.chars().count();
if !(3..=16).contains(&len) {
return Err(AuthError::InvalidOfflineUsername {
reason: "username must be 3-16 characters".into(),
}
);
}
if !username
.chars()
.all(|c| c.is_ascii_alphanumeric() || c == '_')
{
return Err(AuthError::InvalidOfflineUsername {
reason: "username may only contain letters, digits, and underscores".into(),
}
);
}
Ok(())
}
#[tracing::instrument(level = "debug", fields(username = %username))]
pub fn offline_account(username: String) -> MinecraftAccount {
tracing::info!("creating offline account");
MinecraftAccount {
id: offline_uuid(&username),
username,
access_token: String::new(),
refresh_token: String::new(),
expires: Utc::now() + Duration::days(3650),
kind: AccountKind::Offline,
}
}