Skip to content

Commit

Permalink
Allow opening magnet links after creation
Browse files Browse the repository at this point in the history
Magnet links can now be opened after creation:

    imdl torrent link --open --input METAINFO

type: added
  • Loading branch information
casey committed Apr 8, 2020
1 parent aeb9d8b commit d8055c6
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 17 deletions.
24 changes: 12 additions & 12 deletions src/consts.rs
@@ -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)
Expand All @@ -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 = "█▉▊▋▌▍▎▏ ";
Expand Down Expand Up @@ -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.";
17 changes: 15 additions & 2 deletions src/platform_interface.rs
@@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/subcommand/torrent/create.rs
Expand Up @@ -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(
Expand Down Expand Up @@ -396,7 +396,7 @@ impl Create {

if let OutputTarget::File(path) = output {
if self.open {
Platform::open(&path)?;
Platform::open_file(&path)?;
}
}

Expand Down
92 changes: 91 additions & 1 deletion src/subcommand/torrent/link.rs
Expand Up @@ -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",
Expand Down Expand Up @@ -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(())
}
Expand Down Expand Up @@ -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`.");
}
}

0 comments on commit d8055c6

Please sign in to comment.