feat: event-driven rustdesk sync
This commit is contained in:
parent
e410a4874c
commit
e0bb6bb80f
4 changed files with 263 additions and 96 deletions
|
|
@ -1,7 +1,7 @@
|
|||
#![cfg(target_os = "windows")]
|
||||
|
||||
use crate::RustdeskProvisioningResult;
|
||||
use chrono::Local;
|
||||
use chrono::{Local, Utc};
|
||||
use once_cell::sync::Lazy;
|
||||
use parking_lot::Mutex;
|
||||
use reqwest::blocking::Client;
|
||||
|
|
@ -53,9 +53,13 @@ struct ReleaseResponse {
|
|||
assets: Vec<ReleaseAsset>,
|
||||
}
|
||||
|
||||
pub fn provision(machine_id: &str) -> Result<RustdeskProvisioningResult, RustdeskError> {
|
||||
pub fn ensure_rustdesk(
|
||||
config_string: Option<&str>,
|
||||
password_override: Option<&str>,
|
||||
machine_id: Option<&str>,
|
||||
) -> Result<RustdeskProvisioningResult, RustdeskError> {
|
||||
let _guard = PROVISION_MUTEX.lock();
|
||||
log_event("Iniciando provisionamento do RustDesk");
|
||||
log_event("Iniciando preparo do RustDesk");
|
||||
|
||||
let exe_path = detect_executable_path();
|
||||
let (installed_version, freshly_installed) = ensure_installed(&exe_path)?;
|
||||
|
|
@ -65,26 +69,57 @@ pub fn provision(machine_id: &str) -> Result<RustdeskProvisioningResult, Rustdes
|
|||
"RustDesk já instalado, usando binário existente"
|
||||
});
|
||||
|
||||
let config_path = write_config_files()?;
|
||||
log_event(&format!(
|
||||
"Arquivo de configuração atualizado em {}",
|
||||
config_path.display()
|
||||
));
|
||||
|
||||
if let Err(error) = apply_config(&exe_path, &config_path) {
|
||||
log_event(&format!("Falha ao aplicar configuração via CLI: {error}"));
|
||||
if let Some(value) = config_string.and_then(|raw| {
|
||||
let trimmed = raw.trim();
|
||||
if trimmed.is_empty() { None } else { Some(trimmed) }
|
||||
}) {
|
||||
if let Err(error) = run_with_args(&exe_path, &["--config", value]) {
|
||||
log_event(&format!("Falha ao aplicar configuração inline: {error}"));
|
||||
} else {
|
||||
log_event("Configuração aplicada via --config");
|
||||
}
|
||||
} else {
|
||||
log_event("Configuração aplicada via CLI");
|
||||
let config_path = write_config_files()?;
|
||||
log_event(&format!(
|
||||
"Arquivo de configuração atualizado em {}",
|
||||
config_path.display()
|
||||
));
|
||||
|
||||
if let Err(error) = apply_config(&exe_path, &config_path) {
|
||||
log_event(&format!("Falha ao aplicar configuração via CLI: {error}"));
|
||||
} else {
|
||||
log_event("Configuração aplicada via CLI");
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(error) = set_password(&exe_path) {
|
||||
let password = password_override
|
||||
.map(|value| value.trim().to_string())
|
||||
.filter(|value| !value.is_empty())
|
||||
.unwrap_or_else(|| DEFAULT_PASSWORD.to_string());
|
||||
|
||||
if let Err(error) = set_password(&exe_path, &password) {
|
||||
log_event(&format!("Falha ao definir senha padrão: {error}"));
|
||||
} else {
|
||||
log_event("Senha padrão definida com sucesso");
|
||||
}
|
||||
|
||||
let custom_id = set_custom_id(&exe_path, machine_id)?;
|
||||
log_event(&format!("ID determinístico definido: {custom_id}"));
|
||||
let custom_id = if let Some(value) = machine_id.and_then(|raw| {
|
||||
let trimmed = raw.trim();
|
||||
if trimmed.is_empty() { None } else { Some(trimmed) }
|
||||
}) {
|
||||
match set_custom_id(&exe_path, value) {
|
||||
Ok(custom) => {
|
||||
log_event(&format!("ID determinístico definido: {custom}"));
|
||||
Some(custom)
|
||||
}
|
||||
Err(error) => {
|
||||
log_event(&format!("Falha ao definir ID determinístico: {error}"));
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Err(error) = ensure_service_running() {
|
||||
log_event(&format!("Falha ao reiniciar serviço do RustDesk: {error}"));
|
||||
|
|
@ -92,21 +127,26 @@ pub fn provision(machine_id: &str) -> Result<RustdeskProvisioningResult, Rustdes
|
|||
log_event("Serviço RustDesk reiniciado/run ativo");
|
||||
}
|
||||
|
||||
let reported_id = query_id(&exe_path)
|
||||
.ok()
|
||||
.filter(|value| !value.is_empty())
|
||||
.or_else(|| {
|
||||
let fallback = read_remote_id_from_profiles();
|
||||
if let Some(value) = &fallback {
|
||||
log_event(&format!("ID obtido via arquivos de perfil: {value}"));
|
||||
let reported_id = match query_id_with_retries(&exe_path, 5) {
|
||||
Ok(value) => value,
|
||||
Err(error) => {
|
||||
log_event(&format!("Falha ao obter ID após múltiplas tentativas: {error}"));
|
||||
match read_remote_id_from_profiles().or_else(|| custom_id.clone()) {
|
||||
Some(value) => {
|
||||
log_event(&format!("ID obtido via arquivos de perfil: {value}"));
|
||||
value
|
||||
}
|
||||
None => return Err(error),
|
||||
}
|
||||
fallback
|
||||
})
|
||||
.unwrap_or_else(|| custom_id.clone());
|
||||
if reported_id != custom_id {
|
||||
log_event(&format!(
|
||||
"ID retornado difere do determinístico ({custom_id}) -> aplicando {reported_id}"
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(expected) = custom_id.as_ref() {
|
||||
if expected != &reported_id {
|
||||
log_event(&format!(
|
||||
"ID retornado difere do determinístico ({expected}) -> aplicando {reported_id}"
|
||||
));
|
||||
}
|
||||
}
|
||||
ensure_remote_id_files(&reported_id);
|
||||
|
||||
|
|
@ -114,9 +154,10 @@ pub fn provision(machine_id: &str) -> Result<RustdeskProvisioningResult, Rustdes
|
|||
|
||||
let result = RustdeskProvisioningResult {
|
||||
id: reported_id.clone(),
|
||||
password: DEFAULT_PASSWORD.to_string(),
|
||||
password: password.clone(),
|
||||
installed_version: version.clone(),
|
||||
updated: freshly_installed,
|
||||
last_provisioned_at: Utc::now().timestamp_millis(),
|
||||
};
|
||||
|
||||
log_event(&format!("Provisionamento concluído. ID final: {reported_id}. Versão: {:?}", version));
|
||||
|
|
@ -266,8 +307,8 @@ fn apply_config(exe_path: &Path, config_path: &Path) -> Result<(), RustdeskError
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn set_password(exe_path: &Path) -> Result<(), RustdeskError> {
|
||||
run_with_args(exe_path, &["--password", DEFAULT_PASSWORD])
|
||||
fn set_password(exe_path: &Path, secret: &str) -> Result<(), RustdeskError> {
|
||||
run_with_args(exe_path, &["--password", secret])
|
||||
}
|
||||
|
||||
fn set_custom_id(exe_path: &Path, machine_id: &str) -> Result<String, RustdeskError> {
|
||||
|
|
@ -309,6 +350,25 @@ fn run_sc(args: &[&str]) -> Result<(), RustdeskError> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn query_id_with_retries(exe_path: &Path, attempts: usize) -> Result<String, RustdeskError> {
|
||||
let mut last_error: Option<RustdeskError> = None;
|
||||
for attempt in 0..attempts {
|
||||
match query_id(exe_path) {
|
||||
Ok(value) if !value.trim().is_empty() => return Ok(value),
|
||||
Ok(_) => {
|
||||
last_error = Some(RustdeskError::MissingId);
|
||||
}
|
||||
Err(error) => {
|
||||
last_error = Some(error);
|
||||
}
|
||||
}
|
||||
if attempt + 1 < attempts {
|
||||
thread::sleep(Duration::from_millis(800));
|
||||
}
|
||||
}
|
||||
Err(last_error.unwrap_or(RustdeskError::MissingId))
|
||||
}
|
||||
|
||||
fn query_id(exe_path: &Path) -> Result<String, RustdeskError> {
|
||||
let output = Command::new(exe_path)
|
||||
.arg("--get-id")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue