Skip to content

Commit 9437d9b

Browse files
slundislundi
andauthored
feat: yank magnet without metadata and trackers (#40)
Co-authored-by: slundi <slundi@ikmail.com>
1 parent c496c50 commit 9437d9b

File tree

11 files changed

+173
-24
lines changed

11 files changed

+173
-24
lines changed

Cargo.lock

Lines changed: 17 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ base64 = { version = "0.22.1", default-features = false, features = ["alloc"] }
4646
lexopt = "0.3.0"
4747
ratatui-image = { version = "1.0.5", optional = true , default-features = false }
4848
image = { version = "0.25.1", optional = true, features = ["png"], default-features = false }
49+
url = "2.5.4"
4950

5051
[lib]
5152
name = "nyaa"

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ request_proxy = "localhost:8118" # request proxy for sending requests through (u
148148
timeout = 30 # request timeout for sources and clients (measured in seconds)
149149
scroll_padding = 6 # scroll padding for results table
150150
save_config_on_change = true # save config when changing sources/themes
151+
yank_full_magnet = true # if false, only keep the torrent hash in the magnet link
151152

152153

153154
[source.nyaa]

src/app.rs

Lines changed: 11 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,
@@ -653,7 +653,16 @@ impl App {
653653
Some(item) => {
654654
let link = match c {
655655
't' => item.torrent_link,
656-
'm' => item.magnet_link,
656+
'm' => {
657+
if ctx.config.yank_full_magnet {
658+
match minimal_magnet_link(&item.magnet_link) {
659+
Ok(magnet) => magnet,
660+
Err(e) => return ctx.notify_error(e),
661+
}
662+
} else {
663+
item.magnet_link
664+
}
665+
}
657666
'p' => item.post_link,
658667
'i' => match item.extra.get("imdb").cloned() {
659668
Some(imdb) => imdb,

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.clone()
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/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ pub struct Config {
5959
pub cursor_padding: usize,
6060
pub save_config_on_change: bool,
6161
pub hot_reload_config: bool,
62+
/// Tell if we yank all available magnet info or just the minimal magnet info when it is `false`:
63+
/// `magnet:?xt=urn:btih:691526c892951e9b41b7946524513f945e5c7c45&dn=Example.File.Name&tr=http://example.com/tracker/announce` become `magnet:?xt=urn:btih:691526c892951e9b41b7946524513f945e5c7c45` when `false`
64+
pub yank_full_magnet: bool,
6265

6366
#[serde(rename = "notifications")]
6467
pub notifications: Option<NotificationConfig>,
@@ -85,6 +88,7 @@ impl Default for Config {
8588
cursor_padding: 4,
8689
save_config_on_change: true,
8790
hot_reload_config: true,
91+
yank_full_magnet: true,
8892

8993
notifications: None,
9094
clipboard: None,

0 commit comments

Comments
 (0)