Allow opening magnet links after creation

Magnet links can now be opened after creation:

    imdl torrent link --open --input METAINFO

type: added
This commit is contained in:
Casey Rodarmor 2020-03-17 06:23:33 -07:00
parent aeb9d8b317
commit d8055c6e6a
No known key found for this signature in database
GPG Key ID: 556186B153EC6FE0
4 changed files with 120 additions and 17 deletions

View File

@ -1,3 +1,11 @@
pub(crate) const ABOUT: &str = concat!(
env!("CARGO_PKG_DESCRIPTION"),
" - ",
env!("CARGO_PKG_HOMEPAGE")
);
pub(crate) const AUTHOR: &str = env!("CARGO_PKG_AUTHORS");
/// Default value for `created by` torrent metainfo field.
///
/// Example: imdl/0.0.0 (1234567890AB)
@ -12,20 +20,8 @@ pub(crate) const CREATED_BY_DEFAULT: &str = concat!(
/// Value for `encoding` torrent metainfo field.
pub(crate) const ENCODING_UTF8: &str = "UTF-8";
pub(crate) const ABOUT: &str = concat!(
env!("CARGO_PKG_DESCRIPTION"),
" - ",
env!("CARGO_PKG_HOMEPAGE")
);
pub(crate) const VERSION: &str = concat!("v", env!("CARGO_PKG_VERSION"));
pub(crate) const AUTHOR: &str = env!("CARGO_PKG_AUTHORS");
pub(crate) const HELP_MESSAGE: &str = "Print help message.";
pub(crate) const VERSION_MESSAGE: &str = "Print version number.";
/// The pogress chars are from the
/// [Block Elements unicode block](https://en.wikipedia.org/wiki/Block_Elements).
pub(crate) const PROGRESS_CHARS: &str = "█▉▊▋▌▍▎▏ ";
@ -66,3 +62,7 @@ pub(crate) const TICK_CHARS: &str = concat!(
"⢰⢱⢲⢳⢴⢵⢶⢷⣰⣱⣲⣳⣴⣵⣶⣷", // 0b1110----
"⢸⢹⢺⢻⢼⢽⢾⢿⣸⣹⣺⣻⣼⣽⣾⣿", // 0b1111----
);
pub(crate) const VERSION: &str = concat!("v", env!("CARGO_PKG_VERSION"));
pub(crate) const VERSION_MESSAGE: &str = "Print version number.";

View File

@ -1,9 +1,22 @@
use crate::common::*;
pub(crate) trait PlatformInterface {
fn open(path: &Path) -> Result<(), Error> {
fn open_file(path: &Path) -> Result<(), Error> {
Self::open_raw(path.as_os_str())
}
fn open_url(url: &Url) -> Result<(), Error> {
if cfg!(windows) {
let escaped = format!("\"{}\"", url);
Self::open_raw(escaped.as_str().as_ref())
} else {
Self::open_raw(url.as_str().as_ref())
}
}
fn open_raw(target: &OsStr) -> Result<(), Error> {
let mut command = Self::opener()?;
command.push(OsString::from(path));
command.push(OsString::from(target));
let command_string = || {
command

View File

@ -140,7 +140,7 @@ pub(crate) struct Create {
long = "open",
short = "O",
help = "Open `.torrent` file after creation. Uses `xdg-open`, `gnome-open`, or `kde-open` on \
Linux; `open` on macOS; and `cmd /C start on Windows"
Linux; `open` on macOS; and `cmd /C start` on Windows"
)]
open: bool,
#[structopt(
@ -396,7 +396,7 @@ impl Create {
if let OutputTarget::File(path) = output {
if self.open {
Platform::open(&path)?;
Platform::open_file(&path)?;
}
}

View File

@ -15,6 +15,13 @@ pub(crate) struct Link {
parse(from_os_str)
)]
input: PathBuf,
#[structopt(
long = "open",
short = "O",
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: bool,
#[structopt(
long = "peer",
short = "p",
@ -47,7 +54,13 @@ impl Link {
link.add_peer(peer);
}
outln!(env, "{}", link.to_url())?;
let url = link.to_url();
outln!(env, "{}", url)?;
if self.open {
Platform::open_url(&url)?;
}
Ok(())
}
@ -229,4 +242,81 @@ mod tests {
if path == env.resolve("foo.torrent")
);
}
#[test]
fn open() {
let mut create_env = test_env! {
args: [
"torrent",
"create",
"--input",
"foo",
],
tree: {
foo: "",
},
};
assert_matches!(create_env.run(), Ok(()));
let torrent = create_env.resolve("foo.torrent");
let mut env = test_env! {
args: [
"torrent",
"link",
"--input",
&torrent,
"--open",
],
tree: {},
};
let opened = env.resolve("opened.txt");
let link = "magnet:?xt=urn:btih:516735f4b80f2b5487eed5f226075bdcde33a54e&dn=foo";
let expected = if cfg!(target_os = "windows") {
let script = env.resolve("open.bat");
fs::write(&script, format!("echo > {}", opened.display())).unwrap();
format!("ECHO is on.\r\n")
} else {
let script = env.resolve(&Platform::opener().unwrap()[0]);
fs::write(
&script,
format!("#!/usr/bin/env sh\necho $1 > {}", opened.display()),
)
.unwrap();
Command::new("chmod")
.arg("+x")
.arg(&script)
.status()
.unwrap();
format!("{}\n", link)
};
const KEY: &str = "PATH";
let path = env::var_os(KEY).unwrap();
let mut split = env::split_paths(&path)
.into_iter()
.collect::<Vec<PathBuf>>();
split.insert(0, env.dir().to_owned());
let new = env::join_paths(split).unwrap();
env::set_var(KEY, new);
assert_matches!(env.run(), Ok(()));
let start = Instant::now();
while start.elapsed() < Duration::new(2, 0) {
if let Ok(text) = fs::read_to_string(&opened) {
assert_eq!(text, expected);
return;
}
}
panic!("Failed to read `opened.txt`.");
}
}