Make command line argument parsing more robust.

This commit is contained in:
Simon Persson 2015-07-19 20:36:14 +00:00
parent 17fdca40dd
commit ef1c86df18
4 changed files with 90 additions and 12 deletions

42
Cargo.lock generated
View file

@ -3,6 +3,7 @@ name = "librespot"
version = "0.1.0"
dependencies = [
"byteorder 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"librespot-protocol 0.1.0",
"mod_path 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -12,6 +13,7 @@ dependencies = [
"protobuf_macros 0.1.0 (git+https://github.com/plietar/rust-protobuf-macros.git)",
"rand 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"readall 0.1.0 (git+https://github.com/plietar/rust-readall.git)",
"rpassword 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-crypto 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-gmp 0.2.0 (git+https://github.com/plietar/rust-gmp.git)",
"shannon 0.1.0 (git+https://github.com/plietar/rust-shannon.git)",
@ -41,6 +43,14 @@ name = "gcc"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "getopts"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel32-sys"
version = "0.1.2"
@ -68,6 +78,14 @@ dependencies = [
"protobuf 1.0.1 (git+https://github.com/plietar/rust-protobuf.git)",
]
[[package]]
name = "log"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mod_path"
version = "0.1.5"
@ -139,6 +157,17 @@ name = "readall"
version = "0.1.0"
source = "git+https://github.com/plietar/rust-readall.git#d2bcc1de325705230e79ba444cde2f39b469f891"
[[package]]
name = "rpassword"
version = "0.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"termios 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rust-crypto"
version = "0.2.31"
@ -193,6 +222,14 @@ dependencies = [
"winapi 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termios"
version = "0.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.30"
@ -254,6 +291,11 @@ dependencies = [
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-build"
version = "0.1.0"

View file

@ -24,6 +24,8 @@ lazy_static = "0.1.*"
rust-crypto = "*"
time = "*"
tempfile = "*"
rpassword = "*"
getopts = "0.2.4"
[dependencies.protobuf]
git = "https://github.com/plietar/rust-protobuf.git"

View file

@ -25,12 +25,11 @@ cargo build
A sample program implementing a headless Spotify Connect receiver is provided.
Once you've built *librespot*, run it using :
```shell
target/debug/main APPKEY USERNAME PASSWORD CACHEDIR DEVICENAME
target/debug/main -a APPKEY -u USERNAME -c CACHEDIR -d DEVICENAME
```
where `APPKEY` is the path to a Spotify application key file, `USERNAME` and
`PASSWORD` are your Spotify credentials, `CACHEDIR` is the path to directory
where data will be cached, and `DEVICENAME` is the name that will appear in the
Spotify Connect menu.
where `APPKEY` is the path to a Spotify application key file, `USERNAME` is your
Spotify username, `CACHEDIR` is the path to directory where data will be cached,
and `DEVICENAME` is the name that will appear in the Spotify Connect menu.
## Disclaimer
Using this code to connect to Spotify's API is probably forbidden by them, and

View file

@ -1,27 +1,62 @@
#![feature(scoped)]
#![feature(result_expect)]
#![allow(deprecated)]
extern crate getopts;
extern crate librespot;
extern crate rpassword;
use std::clone::Clone;
use std::fs::File;
use std::io::Read;
use std::io::{stdout, Read, Write};
use std::path::Path;
use std::thread;
use std::path::PathBuf;
use getopts::Options;
use rpassword::read_password;
use librespot::session::{Config, Session};
use librespot::util::version::version_string;
use librespot::player::Player;
use librespot::spirc::SpircManager;
fn usage(program: &str, opts: &Options) -> String {
let brief = format!("Usage: {} [options]", program);
format!("{}", opts.usage(&brief))
}
fn main() {
let mut args = std::env::args().skip(1);
let mut appkey_file = File::open(Path::new(&args.next().unwrap())).unwrap();
let username = args.next().unwrap();
let password = args.next().unwrap();
let cache_location = args.next().unwrap();
let name = args.next().unwrap();
let args: Vec<String> = std::env::args().collect();
let program = args[0].clone();
let mut opts = Options::new();
opts.reqopt("a", "appkey", "Path to a spotify appkey", "APPKEY");
opts.reqopt("u", "username", "Username to sign in with", "USERNAME");
opts.optopt("p", "password", "Password (optional)", "PASSWORD");
opts.reqopt("c", "cache", "Path to a directory where files will be cached.", "CACHE");
opts.reqopt("n", "name", "Device name", "NAME");
let matches = match opts.parse(&args[1..]) {
Ok(m) => { m },
Err(f) => {
print!("Error: {}\n{}", f.to_string(), usage(&*program, &opts));
return;
}
};
let mut appkey_file = File::open(
Path::new(&*matches.opt_str("a").unwrap())
).expect("Could not open app key.");
let username = matches.opt_str("u").unwrap();
let cache_location = matches.opt_str("c").unwrap();
let name = matches.opt_str("n").unwrap();
let password = matches.opt_str("p").unwrap_or_else(|| {
print!("Password: ");
stdout().flush().unwrap();
read_password().unwrap()
});
let mut appkey = Vec::new();
appkey_file.read_to_end(&mut appkey).unwrap();