Skip to content

Commit 9f37186

Browse files
author
slundi
committed
feat: per client yank magnet behaviour
Ref: Beastwik18#40
1 parent efea4e0 commit 9f37186

File tree

8 files changed

+141
-47
lines changed

8 files changed

+141
-47
lines changed

src/app.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use crate::{
2828
},
2929
sync::{EventSync, ReloadType, SearchQuery},
3030
theme::{self, Theme},
31-
util::conv::key_to_string,
31+
util::{conv::key_to_string, strings::minimal_magnet_link},
3232
widget::{
3333
batch::BatchWidget,
3434
category::CategoryPopup,
@@ -655,7 +655,7 @@ impl App {
655655
't' => item.torrent_link,
656656
'm' => {
657657
if ctx.config.yank_full_magnet {
658-
match item.minimal_magnet_link() {
658+
match minimal_magnet_link(&item.magnet_link) {
659659
Ok(magnet) => magnet,
660660
Err(e) => return ctx.notify_error(e),
661661
}

src/client.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,4 +221,74 @@ impl Client {
221221
Self::Transmission => TransmissionClient::load_config(cfg),
222222
};
223223
}
224+
225+
pub fn get_link(
226+
use_magnet: bool,
227+
yank_full_magnet: Option<bool>,
228+
torrent: String,
229+
magnet: String,
230+
) -> String {
231+
if use_magnet {
232+
if let Some(full) = yank_full_magnet {
233+
if full {
234+
magnet
235+
} else {
236+
match crate::util::strings::minimal_magnet_link(&magnet) {
237+
Ok(minimal) => minimal,
238+
Err(_) => magnet,
239+
}
240+
}
241+
} else {
242+
magnet
243+
}
244+
} else {
245+
torrent
246+
}
247+
}
248+
}
249+
250+
#[cfg(test)]
251+
mod tests {
252+
use crate::util::strings::minimal_magnet_link;
253+
254+
use super::*;
255+
256+
#[test]
257+
fn test_get_link() {
258+
let torrent_link = String::from("torrent");
259+
let magnet_link = String::from("magnet:?xt=urn:btih:691526c892951e9b41b7946524513f945e5c7c45&dn=Example.File.Name&tr=http://example.com/tracker/announce");
260+
261+
// use magnet_link
262+
assert_eq!(
263+
Client::get_link(true, None, torrent_link.clone(), magnet_link.clone()),
264+
magnet_link
265+
);
266+
assert_eq!(
267+
Client::get_link(true, Some(true), torrent_link.clone(), magnet_link.clone()),
268+
magnet_link
269+
);
270+
assert_eq!(
271+
Client::get_link(true, Some(false), torrent_link.clone(), magnet_link.clone()),
272+
minimal_magnet_link(&magnet_link).unwrap()
273+
);
274+
275+
// do not use magnet link
276+
assert_eq!(
277+
Client::get_link(false, None, torrent_link.clone(), magnet_link.clone()),
278+
torrent_link
279+
);
280+
assert_eq!(
281+
Client::get_link(false, Some(true), torrent_link.clone(), magnet_link.clone()),
282+
torrent_link
283+
);
284+
assert_eq!(
285+
Client::get_link(
286+
false,
287+
Some(false),
288+
torrent_link.clone(),
289+
magnet_link.clone()
290+
),
291+
torrent_link
292+
);
293+
}
224294
}

src/client/cmd.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use serde::{Deserialize, Serialize};
22

3-
use crate::{source::Item, util::cmd::CommandBuilder};
3+
use crate::{
4+
source::Item,
5+
util::{cmd::CommandBuilder, strings::minimal_magnet_link},
6+
};
47

58
use super::{
69
multidownload, BatchDownloadResult, ClientConfig, DownloadClient, SingleDownloadResult,
@@ -11,6 +14,7 @@ use super::{
1114
pub struct CmdConfig {
1215
cmd: String,
1316
shell_cmd: String,
17+
yank_full_magnet: Option<bool>,
1418
}
1519

1620
pub struct CmdClient;
@@ -24,6 +28,7 @@ impl Default for CmdConfig {
2428
cmd: "curl \"{torrent}\" > ~/{file}".to_owned(),
2529

2630
shell_cmd: CommandBuilder::default_shell(),
31+
yank_full_magnet: None,
2732
}
2833
}
2934
}
@@ -36,8 +41,14 @@ impl DownloadClient for CmdClient {
3641
return SingleDownloadResult::error("Failed to get cmd config");
3742
}
3843
};
44+
45+
let magnet = if cmd.yank_full_magnet.unwrap_or(true) {
46+
&item.magnet_link
47+
} else {
48+
&minimal_magnet_link(&item.magnet_link).unwrap_or_else(|_| item.magnet_link.clone())
49+
};
3950
let res = CommandBuilder::new(cmd.cmd)
40-
.sub("{magnet}", &item.magnet_link)
51+
.sub("{magnet}", magnet)
4152
.sub("{torrent}", &item.torrent_link)
4253
.sub("{title}", &item.title)
4354
.sub("{file}", &item.file_name)

src/client/default_app.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use super::{
1010
#[serde(default)]
1111
pub struct DefaultAppConfig {
1212
use_magnet: bool,
13+
pub yank_full_magnet: Option<bool>,
1314
}
1415

1516
pub struct DefaultAppClient;
@@ -22,10 +23,12 @@ impl DownloadClient for DefaultAppClient {
2223
return SingleDownloadResult::error("Failed to get default app config");
2324
}
2425
};
25-
let link = match conf.use_magnet {
26-
true => item.magnet_link.to_owned(),
27-
false => item.torrent_link.to_owned(),
28-
};
26+
let link = super::Client::get_link(
27+
conf.use_magnet,
28+
conf.yank_full_magnet,
29+
item.torrent_link.clone(),
30+
item.magnet_link.clone(),
31+
);
2932
match open::that_detached(link).map_err(|e| e.to_string()) {
3033
Ok(()) => {
3134
SingleDownloadResult::success("Successfully opened link in default app", item.id)

src/client/rqbit.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub struct RqbitConfig {
1818
pub use_magnet: Option<bool>,
1919
pub overwrite: Option<bool>,
2020
pub output_folder: Option<String>,
21+
pub yank_full_magnet: Option<bool>,
2122
}
2223

2324
pub struct RqbitClient;
@@ -35,6 +36,7 @@ impl Default for RqbitConfig {
3536
use_magnet: None,
3637
overwrite: None,
3738
output_folder: None,
39+
yank_full_magnet: None,
3840
}
3941
}
4042
}
@@ -76,10 +78,12 @@ impl DownloadClient for RqbitClient {
7678
return SingleDownloadResult::error("Failed to get rqbit config");
7779
}
7880
};
79-
let link = match conf.use_magnet.unwrap_or(true) {
80-
true => item.magnet_link.to_owned(),
81-
false => item.torrent_link.to_owned(),
82-
};
81+
let link = super::Client::get_link(
82+
conf.use_magnet.unwrap_or(true),
83+
conf.yank_full_magnet,
84+
item.torrent_link.clone(),
85+
item.magnet_link.clone(),
86+
);
8387
let res = match add_torrent(&conf, link, &client).await {
8488
Ok(r) => r,
8589
Err(e) => {

src/client/transmission.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub struct TransmissionConfig {
2525
pub peer_limit: Option<i64>,
2626
pub download_dir: Option<String>,
2727
pub bandwidth_priority: Option<Priority>,
28+
pub yank_full_magnet: Option<bool>,
2829
}
2930

3031
pub struct TransmissionClient;
@@ -42,6 +43,7 @@ impl Default for TransmissionConfig {
4243
peer_limit: None,
4344
download_dir: None,
4445
bandwidth_priority: None,
46+
yank_full_magnet: None,
4547
}
4648
}
4749
}
@@ -113,10 +115,12 @@ impl DownloadClient for TransmissionClient {
113115
}
114116
}
115117

116-
let link = match conf.use_magnet {
117-
None | Some(true) => item.magnet_link.to_owned(),
118-
Some(false) => item.torrent_link.to_owned(),
119-
};
118+
let link = super::Client::get_link(
119+
conf.use_magnet.unwrap_or(true),
120+
conf.yank_full_magnet,
121+
item.torrent_link.clone(),
122+
item.magnet_link.clone(),
123+
);
120124
if let Err(e) = add_torrent(conf, link, client).await {
121125
return SingleDownloadResult::error(e);
122126
}

src/source.rs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use serde::{Deserialize, Serialize};
66
use strum::{Display, VariantArray};
77
use sukebei_nyaa::SukebeiTheme;
88
use torrent_galaxy::TgxTheme;
9-
use url::Url;
109

1110
use crate::{
1211
app::{Context, LoadType, Widgets},
@@ -174,23 +173,6 @@ pub struct Item {
174173
pub extra: HashMap<String, String>,
175174
}
176175

177-
impl Item {
178-
pub fn minimal_magnet_link(self) -> Result<String, String> {
179-
let url = Url::parse(&self.magnet_link).map_err(|e| e.to_string())?;
180-
181-
// Extract the query parameters into a HashMap.
182-
let query_pairs = url.query_pairs();
183-
let params: HashMap<_, _> = query_pairs.into_owned().collect();
184-
185-
let xt = params
186-
.get("xt")
187-
.ok_or("Missing `xt` in magnet URL".to_string())?;
188-
let mut magnet = "magnet:?xt=".to_string();
189-
magnet.push_str(xt);
190-
Ok(magnet)
191-
}
192-
}
193-
194176
#[derive(Serialize, Deserialize, Display, Clone, Copy, VariantArray, PartialEq, Eq)]
195177
pub enum Sources {
196178
#[strum(serialize = "Nyaa")]
@@ -397,15 +379,3 @@ impl Sources {
397379
}
398380
}
399381
}
400-
401-
#[cfg(test)]
402-
mod tests {
403-
#[test]
404-
fn test_minimal_magnet_link() {
405-
let item = crate::source::Item {magnet_link: "magnet:?xt=urn:btih:691526c892951e9b41b7946524513f945e5c7c45&dn=Example.File.Name&tr=http://example.com/tracker/announce".to_owned(), ..Default::default()};
406-
assert_eq!(
407-
&item.minimal_magnet_link().unwrap(),
408-
"magnet:?xt=urn:btih:691526c892951e9b41b7946524513f945e5c7c45"
409-
);
410-
}
411-
}

src/util/strings.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
use std::{collections::VecDeque, ops::RangeBounds};
1+
use std::{
2+
collections::{HashMap, VecDeque},
3+
ops::RangeBounds,
4+
};
25

36
use unicode_width::UnicodeWidthChar as _;
7+
use url::Url;
48

59
pub fn pos_of_nth_char(s: &str, idx: usize) -> usize {
610
s.chars()
@@ -150,3 +154,31 @@ pub fn forward_word(input: &str, start: usize) -> usize {
150154
.map(|n| n + nonws)
151155
.unwrap_or(input.chars().count())
152156
}
157+
158+
pub fn minimal_magnet_link(magnet_link: &String) -> Result<String, String> {
159+
let url = Url::parse(magnet_link).map_err(|e| e.to_string())?;
160+
161+
// Extract the query parameters into a HashMap.
162+
let query_pairs = url.query_pairs();
163+
let params: HashMap<_, _> = query_pairs.into_owned().collect();
164+
165+
let xt = params
166+
.get("xt")
167+
.ok_or("Missing `xt` in magnet URL".to_string())?;
168+
let mut magnet = "magnet:?xt=".to_string();
169+
magnet.push_str(xt);
170+
Ok(magnet)
171+
}
172+
173+
#[cfg(test)]
174+
mod tests {
175+
use super::*;
176+
177+
#[test]
178+
fn test_minimal_magnet_link() {
179+
assert_eq!(
180+
minimal_magnet_link(&String::from("magnet:?xt=urn:btih:691526c892951e9b41b7946524513f945e5c7c45&dn=Example.File.Name&tr=http://example.com/tracker/announce")).unwrap(),
181+
"magnet:?xt=urn:btih:691526c892951e9b41b7946524513f945e5c7c45"
182+
);
183+
}
184+
}

0 commit comments

Comments
 (0)