Skip to content

Commit 029e1a5

Browse files
committed
refactor: Reconstruct the source code structure.
1 parent 7815248 commit 029e1a5

7 files changed

Lines changed: 574 additions & 491 deletions

File tree

src/login.rs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
use crate::pmhq_client::PMHQClient;
2+
use crate::qrcode_display::{print_qrcode_terminal, save_qrcode_image};
3+
4+
use std::path::PathBuf;
5+
use std::sync::atomic::{AtomicBool, Ordering};
6+
use std::sync::Arc;
7+
use std::thread;
8+
use std::time::Duration;
9+
10+
pub fn start_login_listener(
11+
port: u16,
12+
logged_in: Arc<AtomicBool>,
13+
qrcode_path: PathBuf,
14+
show_terminal_qr: bool,
15+
) {
16+
thread::spawn(move || {
17+
let client = PMHQClient::new(port).with_timeout(Duration::from_secs(10));
18+
19+
#[cfg(target_os = "windows")]
20+
start_windows_selfinfo_title_thread(client.clone());
21+
22+
thread::sleep(Duration::from_secs(3));
23+
24+
let logged_in_refresh = logged_in.clone();
25+
let client_refresh = client.clone();
26+
thread::spawn(move || loop {
27+
if logged_in_refresh.load(Ordering::Relaxed) {
28+
break;
29+
}
30+
let _ = client_refresh.request_qrcode();
31+
for _ in 0..120 {
32+
if logged_in_refresh.load(Ordering::Relaxed) {
33+
break;
34+
}
35+
thread::sleep(Duration::from_secs(1));
36+
}
37+
});
38+
39+
client.start_sse_listener(logged_in.clone(), move |qrcode_url, png_base64| {
40+
if show_terminal_qr {
41+
print_qrcode_terminal(qrcode_url);
42+
}
43+
44+
if !png_base64.is_empty() {
45+
if let Err(e) = save_qrcode_image(png_base64, &qrcode_path) {
46+
eprintln!("保存二维码失败: {}", e);
47+
} else {
48+
println!("二维码文件: {}", qrcode_path.display());
49+
}
50+
}
51+
52+
println!(
53+
"二维码网址: https://api.2dcode.biz/v1/create-qr-code?data={}",
54+
qrcode_url
55+
);
56+
println!("请使用手机QQ扫码登录");
57+
println!();
58+
});
59+
60+
if logged_in.load(Ordering::Relaxed) {
61+
println!();
62+
println!("================");
63+
println!("登录成功!");
64+
65+
if let Ok(info) = client.get_self_info() {
66+
println!("QQ号: {}", info.uin);
67+
if !info.nickname.is_empty() {
68+
println!("昵称: {}", info.nickname);
69+
}
70+
}
71+
println!("================");
72+
println!();
73+
}
74+
});
75+
}
76+
77+
#[cfg(target_os = "windows")]
78+
fn start_windows_selfinfo_title_thread(client: PMHQClient) {
79+
use std::ffi::OsStr;
80+
use std::os::windows::ffi::OsStrExt;
81+
82+
use winapi::um::wincon::SetConsoleTitleW;
83+
84+
thread::spawn(move || loop {
85+
match client.get_self_info() {
86+
Ok(info) => {
87+
if !info.uin.is_empty() && !info.nickname.is_empty() {
88+
let title = format!("LLBot - {}({})", info.nickname, info.uin);
89+
let _ = set_windows_console_title(&title);
90+
break;
91+
}
92+
}
93+
Err(_) => {
94+
// 忽略未就绪/临时错误,继续重试
95+
}
96+
}
97+
98+
thread::sleep(Duration::from_secs(1));
99+
});
100+
101+
fn set_windows_console_title(title: &str) -> Result<(), String> {
102+
let wide: Vec<u16> = OsStr::new(title)
103+
.encode_wide()
104+
.chain(std::iter::once(0))
105+
.collect();
106+
let ok = unsafe { SetConsoleTitleW(wide.as_ptr()) };
107+
if ok == 0 {
108+
Err("SetConsoleTitleW 调用失败".to_string())
109+
} else {
110+
Ok(())
111+
}
112+
}
113+
}

0 commit comments

Comments
 (0)