use arboard::Clipboard;
use std::{env, process, thread, time::Duration};
fn spawn_daemon(info: &str) -> Result<(), Box<dyn std::error::Error>> {
let exe_path = env::current_exe()?;
#[cfg(unix)]
{
use std::os::unix::process::CommandExt;
let mut cmd = process::Command::new(exe_path);
cmd.env("CLIPBOARD_DAEMON", "1")
.env("DYNAMIC_INFO", info) .stderr(process::Stdio::inherit())
.process_group(0);
cmd.spawn()?;
}
#[cfg(windows)]
{
use std::os::windows::process::CommandExt;
let mut cmd = process::Command::new(exe_path);
cmd.env("CLIPBOARD_DAEMON", "1")
.env("DYNAMIC_INFO", info) .stderr(process::Stdio::inherit())
.creation_flags(0x08000000);
cmd.spawn()?;
}
Ok(())
}
fn daemon_task(secret: &str, duation: u64) -> Result<(), Box<dyn std::error::Error>> {
thread::sleep(Duration::from_secs(duation));
let mut ctx = match Clipboard::new() {
Ok(ctx) => ctx,
Err(e) => {
eprintln!("[守护进程] 剪贴板初始化失败: {}", e);
return Ok(());
}
};
let current_content = ctx.get_text().unwrap_or_else(|_| String::new());
if current_content == secret {
if let Err(e) = ctx.set_text("") {
eprintln!("[守护进程] 清空剪贴板失败: {}", e);
} else {
println!("[守护进程] 剪贴板内容未更改,已清空");
}
} else {
println!("[守护进程] 剪贴板已更改,无需操作");
}
Ok(())
}
pub fn copy_to_clipboard(secret: &str, duation: u64) -> Result<(), Box<dyn std::error::Error>> {
if env::var("CLIPBOARD_DAEMON").is_ok() {
let info = env::var("DYNAMIC_INFO")
.map_err(|_| "无法获取DYNAMIC_INFO环境变量")?;
daemon_task(&info, duation)
} else {
let mut ctx = Clipboard::new()?;
ctx.set_text(secret)?;
spawn_daemon(&secret)?;
Ok(())
}
}