Support building with the application key statically included in the binary.

This commit is contained in:
Paul Lietar 2016-03-14 23:41:51 +00:00
parent a5453de572
commit aa1d466e92
2 changed files with 23 additions and 11 deletions

View file

@ -54,4 +54,5 @@ json_macros = { git = "https://github.com/plietar/json_macros" }
discovery = ["dns-sd"] discovery = ["dns-sd"]
with-syntex = ["syntex", "protobuf_macros/with-syntex", "json_macros/with-syntex"] with-syntex = ["syntex", "protobuf_macros/with-syntex", "json_macros/with-syntex"]
with-tremor = ["tremor"] with-tremor = ["tremor"]
static-appkey = []
default = ["with-syntex"] default = ["with-syntex"]

View file

@ -2,12 +2,11 @@ extern crate getopts;
extern crate librespot; extern crate librespot;
extern crate rpassword; extern crate rpassword;
use getopts::Options;
use rpassword::read_password; use rpassword::read_password;
use std::clone::Clone; use std::clone::Clone;
use std::fs::File; use std::fs::File;
use std::io::{stdout, Read, Write}; use std::io::{stdout, Read, Write};
use std::path::{Path, PathBuf}; use std::path::PathBuf;
use std::thread; use std::thread;
use librespot::audio_sink::DefaultSink; use librespot::audio_sink::DefaultSink;
@ -20,23 +19,33 @@ use librespot::util::version::version_string;
static PASSWORD_ENV_NAME: &'static str = "SPOTIFY_PASSWORD"; static PASSWORD_ENV_NAME: &'static str = "SPOTIFY_PASSWORD";
fn usage(program: &str, opts: &Options) -> String { fn usage(program: &str, opts: &getopts::Options) -> String {
let brief = format!("Usage: {} [options]", program); let brief = format!("Usage: {} [options]", program);
format!("{}", opts.usage(&brief)) format!("{}", opts.usage(&brief))
} }
#[cfg(feature = "static-appkey")]
static APPKEY: Option<&'static [u8]> = Some(include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/spotify_appkey.key")));
#[cfg(not(feature = "static-appkey"))]
static APPKEY: Option<&'static [u8]> = None;
fn main() { fn main() {
let args: Vec<String> = std::env::args().collect(); let args: Vec<String> = std::env::args().collect();
let program = args[0].clone(); let program = args[0].clone();
let mut opts = Options::new(); let mut opts = getopts::Options::new();
opts.reqopt("a", "appkey", "Path to a spotify appkey", "APPKEY") opts.optopt("u", "username", "Username to sign in with", "USERNAME")
.optopt("u", "username", "Username to sign in with (optional)", "USERNAME") .optopt("p", "password", "Password", "PASSWORD")
.optopt("p", "password", "Password (optional)", "PASSWORD")
.optopt("c", "cache", "Path to a directory where files will be cached.", "CACHE") .optopt("c", "cache", "Path to a directory where files will be cached.", "CACHE")
.reqopt("n", "name", "Device name", "NAME") .reqopt("n", "name", "Device name", "NAME")
.optopt("b", "bitrate", "Bitrate (96, 160 or 320). Defaults to 160", "BITRATE"); .optopt("b", "bitrate", "Bitrate (96, 160 or 320). Defaults to 160", "BITRATE");
if APPKEY.is_none() {
opts.reqopt("a", "appkey", "Path to a spotify appkey", "APPKEY");
} else {
opts.optopt("a", "appkey", "Path to a spotify appkey", "APPKEY");
};
let matches = match opts.parse(&args[1..]) { let matches = match opts.parse(&args[1..]) {
Ok(m) => m, Ok(m) => m,
Err(f) => { Err(f) => {
@ -45,15 +54,15 @@ fn main() {
} }
}; };
let appkey = { let appkey = matches.opt_str("a").map(|appkey_path| {
let mut file = File::open(Path::new(&*matches.opt_str("a").unwrap())) let mut file = File::open(appkey_path)
.expect("Could not open app key."); .expect("Could not open app key.");
let mut data = Vec::new(); let mut data = Vec::new();
file.read_to_end(&mut data).unwrap(); file.read_to_end(&mut data).unwrap();
data data
}; }).or_else(|| APPKEY.map(ToOwned::to_owned)).unwrap();
let username = matches.opt_str("u"); let username = matches.opt_str("u");
let cache_location = matches.opt_str("c").map(PathBuf::from); let cache_location = matches.opt_str("c").map(PathBuf::from);
@ -100,6 +109,8 @@ fn main() {
.and_then(|p| File::open(p).ok()) .and_then(|p| File::open(p).ok())
.map(Credentials::from_reader) .map(Credentials::from_reader)
}).unwrap_or_else(|| { }).unwrap_or_else(|| {
println!("No username provided and no stored credentials, starting discovery ...");
let mut discovery = DiscoveryManager::new(session.clone()); let mut discovery = DiscoveryManager::new(session.clone());
discovery.run() discovery.run()
}); });