Skip to content

Commit 6a7a615

Browse files
committed
整理代码
1 parent a4f1884 commit 6a7a615

File tree

2 files changed

+60
-125
lines changed

2 files changed

+60
-125
lines changed

src/main.rs

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,7 @@ async fn main() {
3232
// 解析命令行参数
3333
let args = Args::parse();
3434
// 配置日志输出
35-
if let Some(args_log) = args.log {
36-
logger::set_log_file(args_log)
37-
}
38-
// 提取参数 WebUI 地址、用户名、密码
39-
// 提取参数 种子哈希
40-
let (webui_url, torrent_hash) = (args.webui_url, args.torrent_hash);
41-
35+
if let Some(log_path) = args.log { logger::set_log_file(log_path) }
4236
// 提取参数 重命名规则,提前编译正则表达式
4337
let mut rules = vec![];
4438
for rule in args.rename_rules {
@@ -48,25 +42,21 @@ async fn main() {
4842
// 如果没有等号,则认为是文件路径
4943
let content = std::fs::read_to_string(&rule)
5044
.log_unwrap("Failed to read rename rules file");
51-
for chunk in content.lines().collect::<Vec<_>>().chunks(2) {
52-
if chunk.len() >= 2 {
53-
rules.push((chunk[0].to_string(), chunk[1].to_string()));
54-
}
55-
}
45+
rules.extend(
46+
content.lines()
47+
.collect::<Vec<_>>()
48+
.chunks_exact(2)
49+
.map(|c| (c[0].to_string(), c[1].to_string()))
50+
);
5651
}
5752
}
58-
59-
let compound_replacer = CompoundReplacer::new(rules);
60-
53+
6154
let mut builder = Client::builder().cookie_store(true);
62-
if !args.vpn {
63-
builder = builder.no_proxy();
64-
}
65-
let client = builder.build().log_unwrap("Failed to create http client");
66-
let client = Box::leak(Box::new(client));
67-
let webui_url = Box::leak(Box::new(webui_url));
68-
let torrent_hash = Box::leak(Box::new(torrent_hash));
69-
let compound_replacer = Box::leak(Box::new(compound_replacer));
55+
if !args.vpn { builder = builder.no_proxy(); }
56+
let client = Box::leak(Box::new(builder.build().unwrap()));
57+
let webui_url = Box::leak(Box::new(args.webui_url));
58+
let torrent_hash = Box::leak(Box::new(args.torrent_hash));
59+
let compound_replacer = Box::leak(Box::new(CompoundReplacer::new(rules)));
7060

7161
// 如果提供了用户名和密码,则进行认证
7262
if let (Some(u), Some(p)) = (args.username, args.password) {
@@ -82,6 +72,10 @@ async fn main() {
8272
tasks.spawn(q_bit::rename_files(client, webui_url, torrent_hash, compound_replacer));
8373

8474
while let Some(res) = tasks.join_next().await {
85-
if let Err(err) = res { log!("{}", err) }
75+
match res {
76+
Ok(Ok(_)) => {},
77+
Ok(Err(e)) => log!("Task failed: {:?}", e),
78+
Err(_) => log!("Task failed"),
79+
}
8680
}
8781
}

src/q_bit.rs

Lines changed: 42 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::{log, re};
22

3-
use crate::logger::LogUnwrap;
43
use crate::re::CompoundReplacer;
54
use reqwest::Client;
65
use serde::{Deserialize, Serialize};
@@ -18,21 +17,6 @@ pub struct TorrentFile {
1817
pub index: u32,
1918
}
2019

21-
#[derive(Serialize, Debug)]
22-
pub struct RenameRequest {
23-
pub hash: String,
24-
pub name: String,
25-
}
26-
27-
#[derive(Serialize)]
28-
pub struct RenameFileRequest {
29-
pub hash: String,
30-
#[serde(rename = "oldPath")]
31-
pub old_path: String,
32-
#[serde(rename = "newPath")]
33-
pub new_path: String,
34-
}
35-
3620
pub async fn authenticate(
3721
client: &Client,
3822
webui_url: &str,
@@ -41,20 +25,16 @@ pub async fn authenticate(
4125
) -> Result<(), String> {
4226
let auth_url = format!("{}/api/v2/auth/login", webui_url);
4327
let auth_params = [("username", username), ("password", password)];
44-
let auth_response = client
28+
client
4529
.post(&auth_url)
4630
.form(&auth_params)
4731
.send()
4832
.await
49-
.log_unwrap("Failed to authenticate with qBittorrent WebUI");
33+
.and_then(|resp| resp.error_for_status())
34+
.map_err(|e| format!("Failed to authenticate: {}", e))?;
5035

51-
if auth_response.status().is_success() {
52-
log!("Authentication successful");
53-
Ok(())
54-
} else {
55-
log!("Authentication failed: {}", auth_response.status());
56-
Err(format!("Authentication failed: {}", auth_response.status()))
57-
}
36+
log!("Authentication successful");
37+
Ok(())
5838
}
5939

6040
pub async fn get_torrent_info(
@@ -68,26 +48,20 @@ pub async fn get_torrent_info(
6848
.get(&info_url)
6949
.send()
7050
.await
71-
.log_unwrap("Failed to fetch torrent info");
72-
73-
if !info_response.status().is_success() {
74-
return Err(format!(
75-
"Failed to fetch torrent info: {}",
76-
info_response.status()
77-
));
78-
}
51+
.and_then(|resp| resp.error_for_status())
52+
.map_err(|e| format!("Failed to fetch torrent info: {}", e))?;
7953

8054
let torrent_info: Vec<TorrentInfo> = info_response
8155
.json()
8256
.await
83-
.log_unwrap("Failed to parse torrent info");
57+
.map_err(|e| format!("Failed to parse torrent info: {}", e))?;
8458

8559
if torrent_info.is_empty() {
8660
return Err(format!("No torrent found with hash: {}", torrent_hash));
8761
}
8862

8963
log!("Fetched torrent info for hash: {}", torrent_hash);
90-
Ok(torrent_info[0].clone())
64+
Ok(torrent_info.into_iter().next().unwrap())
9165
}
9266

9367
pub async fn get_torrent_files(
@@ -101,15 +75,9 @@ pub async fn get_torrent_files(
10175
.get(&files_url)
10276
.send()
10377
.await
78+
.and_then(|resp| resp.error_for_status())
10479
.map_err(|e| format!("Failed to fetch torrent files: {}", e))?;
10580

106-
if !files_response.status().is_success() {
107-
return Err(format!(
108-
"Failed to fetch torrent files: {}",
109-
files_response.status()
110-
));
111-
}
112-
11381
let torrent_files: Vec<TorrentFile> = files_response
11482
.json()
11583
.await
@@ -124,33 +92,19 @@ pub async fn rename_torrent(
12492
torrent_hash: &str,
12593
compound_replacer: &CompoundReplacer,
12694
) -> Result<(), String> {
127-
let torrent = get_torrent_info(client, webui_url, torrent_hash)
128-
.await
129-
.log_unwrap("Failed to get torrent info");
130-
95+
let torrent = get_torrent_info(client, webui_url, torrent_hash).await?;
13196
let new_name = compound_replacer.replace(&torrent.name);
13297

13398
if torrent.name != new_name {
134-
let rename_url = format!("{}/api/v2/torrents/rename", webui_url);
135-
let rename_request = RenameRequest {
136-
hash: torrent.hash.clone(),
137-
name: new_name.to_string(),
138-
};
139-
let rename_response = client
140-
.post(&rename_url)
141-
.form(&rename_request)
99+
client
100+
.post(&format!("{}/api/v2/torrents/rename", webui_url))
101+
.form(&[("hash", &torrent.hash), ("name", &new_name)])
142102
.send()
143103
.await
144-
.log_unwrap("Failed to rename torrent");
104+
.and_then(|resp| resp.error_for_status())
105+
.map_err(|e| format!("Failed to rename torrent: {}", e))?;
145106

146-
if !rename_response.status().is_success() {
147-
return Err(format!(
148-
"Failed to rename torrent: {}",
149-
rename_response.status()
150-
));
151-
}
152-
153-
log!("Torrent renamed to: {}", new_name);
107+
log!("Successfully renamed torrent to: {}", new_name);
154108
}
155109

156110
Ok(())
@@ -162,51 +116,38 @@ pub async fn rename_files(
162116
torrent_hash: &str,
163117
compound_replacer: &CompoundReplacer,
164118
) -> Result<(), String> {
165-
let torrent_files: Vec<TorrentFile> = get_torrent_files(client, webui_url, torrent_hash)
166-
.await
167-
.log_unwrap("Failed to get torrent files");
168-
119+
let torrent_files: Vec<TorrentFile> = get_torrent_files(client, webui_url, torrent_hash).await?;
120+
let rename_url = format!("{webui_url}/api/v2/torrents/renameFile");
169121
let mut tasks = JoinSet::new();
170122

123+
// 并行处理每个文件重命名
171124
for file in torrent_files {
172-
let new_path = apply_rename_rules_to_file(&file.name, compound_replacer);
173-
if file.name != new_path {
174-
let rename_file_url = format!("{}/api/v2/torrents/renameFile", webui_url);
175-
let rename_file_request = RenameFileRequest {
176-
hash: torrent_hash.to_string(),
177-
old_path: file.name.clone(),
178-
new_path: new_path.clone(),
179-
};
180-
let client = client.clone();
181-
182-
// 使用 tokio::spawn 并发执行每个重命名请求
183-
tasks.spawn(async move {
184-
let result = client
185-
.post(&rename_file_url)
186-
.form(&rename_file_request)
187-
.send()
188-
.await;
189-
match result {
190-
Ok(response) if response.status().is_success() => {
191-
log!("File renamed: {} -> {}", file.name, new_path);
192-
Ok(())
193-
}
194-
Ok(response) => {
195-
log!("Failed to rename file: {} -> {}", file.name, new_path);
196-
Err(format!("Failed to rename file: {}", response.status()))
197-
}
198-
Err(e) => {
199-
log!("Failed to rename file: {} -> {}", file.name, new_path);
200-
Err(format!("Failed to rename file: {}", e))
201-
}
202-
}
203-
});
125+
let new_name = apply_rename_rules_to_file(&file.name, compound_replacer);
126+
if file.name == new_name {
127+
continue;
204128
}
129+
130+
let (client, url, hash) = (client.clone(), rename_url.clone(), torrent_hash.to_owned());
131+
132+
tasks.spawn(async move {
133+
// 发送重命名请求并处理响应
134+
let result = client
135+
.post(&url)
136+
.form(&[("hash", &hash), ("oldPath", &file.name), ("newPath", &new_name)])
137+
.send()
138+
.await
139+
.and_then(|resp| resp.error_for_status());
140+
// 返回处理结果与元数据
141+
(file.name, new_name, result)
142+
});
205143
}
144+
145+
// 统一处理所有任务结果
206146
while let Some(res) = tasks.join_next().await {
207147
match res {
208-
Ok(_) => {}
209-
Err(err) => log!("Error during renaming: {}", err),
148+
Ok((old, new, Ok(_))) => log!("Success: {} -> {}",old,new),
149+
Ok((old, new, Err(e))) => log!("Failed: {} -> {} | {}",old,new,e),
150+
Err(e) => log!("Task execution failed: {}",e),
210151
}
211152
}
212153
Ok(())

0 commit comments

Comments
 (0)