Partially implement BEP 53
This enables `--select-only 1,2,3` which gets appended to the magnet link as `&so=1,2,3`. It's a partial implementation because we're missing support for file ranges ie `--select-only 4-6` type: added fixes: - https://github.com/casey/intermodal/issues/245
This commit is contained in:
parent
6185d6c8a2
commit
cb8b5a6919
|
@ -2,9 +2,10 @@ Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
|
||||||
UNRELEASED - 2020-04-12
|
UNRELEASED - 2020-04-13
|
||||||
-----------------------
|
-----------------------
|
||||||
- :books: [`xxxxxxxxxxxx`](https://github.com/casey/intermodal/commits/master) Add table of packages to readme ([#372](https://github.com/casey/intermodal/pull/372)) - Fixes [#369](https://github.com/casey/intermodal/issues/369) - _Casey Rodarmor <casey@rodarmor.com>_
|
- :sparkles: [`xxxxxxxxxxxx`](https://github.com/casey/intermodal/commits/master) Partially implement BEP 53 - Fixes [#245](https://github.com/casey/intermodal/issues/245) - _strickinato <aaronstrick@gmail.com>_
|
||||||
|
- :books: [`6185d6c8a27c`](https://github.com/casey/intermodal/commit/6185d6c8a27c0d603f0434e98000c8e4a868dcc8) Add table of packages to readme ([#372](https://github.com/casey/intermodal/pull/372)) - Fixes [#369](https://github.com/casey/intermodal/issues/369) - _Casey Rodarmor <casey@rodarmor.com>_
|
||||||
- :wrench: [`ddf097c83690`](https://github.com/casey/intermodal/commit/ddf097c8369002748992165f81e9a1bdbe6eff98) Fix `publish` recipe ([#368](https://github.com/casey/intermodal/pull/368)) - _Casey Rodarmor <casey@rodarmor.com>_
|
- :wrench: [`ddf097c83690`](https://github.com/casey/intermodal/commit/ddf097c8369002748992165f81e9a1bdbe6eff98) Fix `publish` recipe ([#368](https://github.com/casey/intermodal/pull/368)) - _Casey Rodarmor <casey@rodarmor.com>_
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,12 @@ FLAGS:
|
||||||
-V, --version Print version number.
|
-V, --version Print version number.
|
||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
-i, --input <METAINFO> Generate magnet link from metainfo at `PATH`. If
|
-s, --select-only <INDICES>...
|
||||||
`PATH` is `-`, read metainfo from standard input.
|
Specify files that torrent clients select for download. Values are
|
||||||
-p, --peer <PEER>... Add `PEER` to magnet link.
|
indices into the info.files list. e.g. `--select-only 1,2,3`
|
||||||
|
-i, --input <METAINFO>
|
||||||
|
Generate magnet link from metainfo at `PATH`. If `PATH` is `-`, read
|
||||||
|
metainfo from standard input.
|
||||||
|
-p, --peer <PEER>... Add `PEER` to magnet link.
|
||||||
|
|
||||||
```
|
```
|
|
@ -245,7 +245,7 @@ _imdl() {
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
imdl__torrent__link)
|
imdl__torrent__link)
|
||||||
opts=" -O -h -V -i -p --open --help --version --input --peer "
|
opts=" -O -h -V -i -p -s --open --help --version --input --peer --select-only "
|
||||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
|
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
|
||||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||||
return 0
|
return 0
|
||||||
|
@ -268,6 +268,14 @@ _imdl() {
|
||||||
COMPREPLY=($(compgen -f "${cur}"))
|
COMPREPLY=($(compgen -f "${cur}"))
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
|
--select-only)
|
||||||
|
COMPREPLY=($(compgen -f "${cur}"))
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
-s)
|
||||||
|
COMPREPLY=($(compgen -f "${cur}"))
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -124,8 +124,10 @@ Sort in ascending order by size, break ties in descending path order:
|
||||||
cand --input 'Generate magnet link from metainfo at `PATH`. If `PATH` is `-`, read metainfo from standard input.'
|
cand --input 'Generate magnet link from metainfo at `PATH`. If `PATH` is `-`, read metainfo from standard input.'
|
||||||
cand -p 'Add `PEER` to magnet link.'
|
cand -p 'Add `PEER` to magnet link.'
|
||||||
cand --peer 'Add `PEER` to magnet link.'
|
cand --peer 'Add `PEER` to magnet link.'
|
||||||
cand -O 'Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; `open` on macOS; and `cmd /C start` on Windows'
|
cand -s 'Select files to download. Values are indices into the `info.files` list, e.g. `--select-only 1,2,3`.'
|
||||||
cand --open 'Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; `open` on macOS; and `cmd /C start` on Windows'
|
cand --select-only 'Select files to download. Values are indices into the `info.files` list, e.g. `--select-only 1,2,3`.'
|
||||||
|
cand -O 'Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; `open` on macOS; and `cmd /C start` on Windows.'
|
||||||
|
cand --open 'Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; `open` on macOS; and `cmd /C start` on Windows.'
|
||||||
cand -h 'Print help message.'
|
cand -h 'Print help message.'
|
||||||
cand --help 'Print help message.'
|
cand --help 'Print help message.'
|
||||||
cand -V 'Print version number.'
|
cand -V 'Print version number.'
|
||||||
|
|
|
@ -69,7 +69,8 @@ complete -c imdl -n "__fish_seen_subcommand_from create" -l help -d 'Print help
|
||||||
complete -c imdl -n "__fish_seen_subcommand_from create" -s V -l version -d 'Print version number.'
|
complete -c imdl -n "__fish_seen_subcommand_from create" -s V -l version -d 'Print version number.'
|
||||||
complete -c imdl -n "__fish_seen_subcommand_from link" -s i -l input -d 'Generate magnet link from metainfo at `PATH`. If `PATH` is `-`, read metainfo from standard input.'
|
complete -c imdl -n "__fish_seen_subcommand_from link" -s i -l input -d 'Generate magnet link from metainfo at `PATH`. If `PATH` is `-`, read metainfo from standard input.'
|
||||||
complete -c imdl -n "__fish_seen_subcommand_from link" -s p -l peer -d 'Add `PEER` to magnet link.'
|
complete -c imdl -n "__fish_seen_subcommand_from link" -s p -l peer -d 'Add `PEER` to magnet link.'
|
||||||
complete -c imdl -n "__fish_seen_subcommand_from link" -s O -l open -d 'Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; `open` on macOS; and `cmd /C start` on Windows'
|
complete -c imdl -n "__fish_seen_subcommand_from link" -s s -l select-only -d 'Select files to download. Values are indices into the `info.files` list, e.g. `--select-only 1,2,3`.'
|
||||||
|
complete -c imdl -n "__fish_seen_subcommand_from link" -s O -l open -d 'Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; `open` on macOS; and `cmd /C start` on Windows.'
|
||||||
complete -c imdl -n "__fish_seen_subcommand_from link" -s h -l help -d 'Print help message.'
|
complete -c imdl -n "__fish_seen_subcommand_from link" -s h -l help -d 'Print help message.'
|
||||||
complete -c imdl -n "__fish_seen_subcommand_from link" -s V -l version -d 'Print version number.'
|
complete -c imdl -n "__fish_seen_subcommand_from link" -s V -l version -d 'Print version number.'
|
||||||
complete -c imdl -n "__fish_seen_subcommand_from piece-length" -s h -l help -d 'Print help message.'
|
complete -c imdl -n "__fish_seen_subcommand_from piece-length" -s h -l help -d 'Print help message.'
|
||||||
|
|
|
@ -132,8 +132,10 @@ Sort in ascending order by size, break ties in descending path order:
|
||||||
[CompletionResult]::new('--input', 'input', [CompletionResultType]::ParameterName, 'Generate magnet link from metainfo at `PATH`. If `PATH` is `-`, read metainfo from standard input.')
|
[CompletionResult]::new('--input', 'input', [CompletionResultType]::ParameterName, 'Generate magnet link from metainfo at `PATH`. If `PATH` is `-`, read metainfo from standard input.')
|
||||||
[CompletionResult]::new('-p', 'p', [CompletionResultType]::ParameterName, 'Add `PEER` to magnet link.')
|
[CompletionResult]::new('-p', 'p', [CompletionResultType]::ParameterName, 'Add `PEER` to magnet link.')
|
||||||
[CompletionResult]::new('--peer', 'peer', [CompletionResultType]::ParameterName, 'Add `PEER` to magnet link.')
|
[CompletionResult]::new('--peer', 'peer', [CompletionResultType]::ParameterName, 'Add `PEER` to magnet link.')
|
||||||
[CompletionResult]::new('-O', 'O', [CompletionResultType]::ParameterName, 'Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; `open` on macOS; and `cmd /C start` on Windows')
|
[CompletionResult]::new('-s', 's', [CompletionResultType]::ParameterName, 'Select files to download. Values are indices into the `info.files` list, e.g. `--select-only 1,2,3`.')
|
||||||
[CompletionResult]::new('--open', 'open', [CompletionResultType]::ParameterName, 'Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; `open` on macOS; and `cmd /C start` on Windows')
|
[CompletionResult]::new('--select-only', 'select-only', [CompletionResultType]::ParameterName, 'Select files to download. Values are indices into the `info.files` list, e.g. `--select-only 1,2,3`.')
|
||||||
|
[CompletionResult]::new('-O', 'O', [CompletionResultType]::ParameterName, 'Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; `open` on macOS; and `cmd /C start` on Windows.')
|
||||||
|
[CompletionResult]::new('--open', 'open', [CompletionResultType]::ParameterName, 'Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; `open` on macOS; and `cmd /C start` on Windows.')
|
||||||
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help message.')
|
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help message.')
|
||||||
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help message.')
|
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help message.')
|
||||||
[CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version number.')
|
[CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version number.')
|
||||||
|
|
|
@ -135,8 +135,10 @@ _arguments "${_arguments_options[@]}" \
|
||||||
'--input=[Generate magnet link from metainfo at `PATH`. If `PATH` is `-`, read metainfo from standard input.]' \
|
'--input=[Generate magnet link from metainfo at `PATH`. If `PATH` is `-`, read metainfo from standard input.]' \
|
||||||
'*-p+[Add `PEER` to magnet link.]' \
|
'*-p+[Add `PEER` to magnet link.]' \
|
||||||
'*--peer=[Add `PEER` to magnet link.]' \
|
'*--peer=[Add `PEER` to magnet link.]' \
|
||||||
'-O[Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; `open` on macOS; and `cmd /C start` on Windows]' \
|
'*-s+[Select files to download. Values are indices into the `info.files` list, e.g. `--select-only 1,2,3`.]' \
|
||||||
'--open[Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; `open` on macOS; and `cmd /C start` on Windows]' \
|
'*--select-only=[Select files to download. Values are indices into the `info.files` list, e.g. `--select-only 1,2,3`.]' \
|
||||||
|
'-O[Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; `open` on macOS; and `cmd /C start` on Windows.]' \
|
||||||
|
'--open[Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; `open` on macOS; and `cmd /C start` on Windows.]' \
|
||||||
'-h[Print help message.]' \
|
'-h[Print help message.]' \
|
||||||
'--help[Print help message.]' \
|
'--help[Print help message.]' \
|
||||||
'-V[Print version number.]' \
|
'-V[Print version number.]' \
|
||||||
|
|
|
@ -19,6 +19,10 @@ and `cmd \fI\,/C\/\fP start` on Windows
|
||||||
Print version number.
|
Print version number.
|
||||||
.SH "OPTIONS:"
|
.SH "OPTIONS:"
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-s\fR, \fB\-\-select\-only\fR <INDICES>...
|
||||||
|
Specify files that torrent clients select for download. Values are indices into
|
||||||
|
the info.files list. e.g. `\-\-select\-only 1,2,3`
|
||||||
|
.TP
|
||||||
\fB\-i\fR, \fB\-\-input\fR <METAINFO>
|
\fB\-i\fR, \fB\-\-input\fR <METAINFO>
|
||||||
Generate magnet link from metainfo at `PATH`. If `PATH` is `\-`, read metainfo from
|
Generate magnet link from metainfo at `PATH`. If `PATH` is `\-`, read metainfo from
|
||||||
standard input.
|
standard input.
|
||||||
|
|
|
@ -5,6 +5,7 @@ pub(crate) struct MagnetLink {
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
peers: Vec<HostPort>,
|
peers: Vec<HostPort>,
|
||||||
trackers: Vec<Url>,
|
trackers: Vec<Url>,
|
||||||
|
indices: BTreeSet<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MagnetLink {
|
impl MagnetLink {
|
||||||
|
@ -26,6 +27,7 @@ impl MagnetLink {
|
||||||
name: None,
|
name: None,
|
||||||
peers: Vec::new(),
|
peers: Vec::new(),
|
||||||
trackers: Vec::new(),
|
trackers: Vec::new(),
|
||||||
|
indices: BTreeSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +45,10 @@ impl MagnetLink {
|
||||||
self.trackers.push(tracker);
|
self.trackers.push(tracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_index(&mut self, index: u64) {
|
||||||
|
self.indices.insert(index);
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn to_url(&self) -> Url {
|
pub(crate) fn to_url(&self) -> Url {
|
||||||
let mut url = Url::parse("magnet:").unwrap();
|
let mut url = Url::parse("magnet:").unwrap();
|
||||||
|
|
||||||
|
@ -63,6 +69,16 @@ impl MagnetLink {
|
||||||
query.push_str(&peer.to_string());
|
query.push_str(&peer.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self.indices.is_empty() {
|
||||||
|
query.push_str("&so=");
|
||||||
|
for (i, selection_index) in self.indices.iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
query.push(',');
|
||||||
|
}
|
||||||
|
query.push_str(&selection_index.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
url.set_query(Some(&query));
|
url.set_query(Some(&query));
|
||||||
|
|
||||||
url
|
url
|
||||||
|
@ -129,6 +145,19 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn with_indices() {
|
||||||
|
let mut link = MagnetLink::with_infohash(Infohash::from_bencoded_info_dict("".as_bytes()));
|
||||||
|
link.add_index(4);
|
||||||
|
link.add_index(6);
|
||||||
|
link.add_index(6);
|
||||||
|
link.add_index(2);
|
||||||
|
assert_eq!(
|
||||||
|
link.to_url().as_str(),
|
||||||
|
"magnet:?xt=urn:btih:da39a3ee5e6b4b0d3255bfef95601890afd80709&so=2,4,6"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn complex() {
|
fn complex() {
|
||||||
let mut link = MagnetLink::with_infohash(Infohash::from_bencoded_info_dict("".as_bytes()));
|
let mut link = MagnetLink::with_infohash(Infohash::from_bencoded_info_dict("".as_bytes()));
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub(crate) struct Link {
|
||||||
long = "open",
|
long = "open",
|
||||||
short = "O",
|
short = "O",
|
||||||
help = "Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; \
|
help = "Open generated magnet link. Uses `xdg-open`, `gnome-open`, or `kde-open` on Linux; \
|
||||||
`open` on macOS; and `cmd /C start` on Windows"
|
`open` on macOS; and `cmd /C start` on Windows."
|
||||||
)]
|
)]
|
||||||
open: bool,
|
open: bool,
|
||||||
#[structopt(
|
#[structopt(
|
||||||
|
@ -31,6 +31,15 @@ pub(crate) struct Link {
|
||||||
help = "Add `PEER` to magnet link."
|
help = "Add `PEER` to magnet link."
|
||||||
)]
|
)]
|
||||||
peers: Vec<HostPort>,
|
peers: Vec<HostPort>,
|
||||||
|
#[structopt(
|
||||||
|
long = "select-only",
|
||||||
|
short = "s",
|
||||||
|
value_name = "INDICES",
|
||||||
|
use_delimiter = true,
|
||||||
|
help = "Select files to download. Values are indices into the `info.files` list, e.g. \
|
||||||
|
`--select-only 1,2,3`."
|
||||||
|
)]
|
||||||
|
indices: Vec<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Link {
|
impl Link {
|
||||||
|
@ -52,6 +61,10 @@ impl Link {
|
||||||
link.add_peer(peer);
|
link.add_peer(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for index in self.indices {
|
||||||
|
link.add_index(index);
|
||||||
|
}
|
||||||
|
|
||||||
let url = link.to_url();
|
let url = link.to_url();
|
||||||
|
|
||||||
outln!(env, "{}", url)?;
|
outln!(env, "{}", url)?;
|
||||||
|
@ -194,6 +207,42 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn with_indices() {
|
||||||
|
let mut env = test_env! {
|
||||||
|
args: [
|
||||||
|
"torrent",
|
||||||
|
"link",
|
||||||
|
"--input",
|
||||||
|
"foo.torrent",
|
||||||
|
"--select-only",
|
||||||
|
"2,4",
|
||||||
|
"--select-only",
|
||||||
|
"4,6",
|
||||||
|
],
|
||||||
|
tree: {
|
||||||
|
"foo.torrent": "d\
|
||||||
|
8:announce24:https://foo.com/announce\
|
||||||
|
4:infod6:lengthi0e4:name3:foo12:piece lengthi1e6:pieces0:e\
|
||||||
|
e",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
env.assert_ok();
|
||||||
|
|
||||||
|
const INFO: &str = "d6:lengthi0e4:name3:foo12:piece lengthi1e6:pieces0:e";
|
||||||
|
|
||||||
|
let infohash = Sha1Digest::from_data(INFO.as_bytes());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
env.out(),
|
||||||
|
format!(
|
||||||
|
"magnet:?xt=urn:btih:{}&dn=foo&tr=https://foo.com/announce&so=2,4,6\n",
|
||||||
|
infohash
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn infohash_correct_with_nonstandard_info_dict() {
|
fn infohash_correct_with_nonstandard_info_dict() {
|
||||||
let mut env = test_env! {
|
let mut env = test_env! {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user