Add upload option to send DB to LMS

This commit is contained in:
Craig Drummond 2022-02-20 11:50:52 +00:00
parent eec7a24f25
commit 09a4f91fc9
4 changed files with 371 additions and 23 deletions

246
Cargo.lock generated
View File

@ -128,6 +128,7 @@ dependencies = [
"regex",
"rusqlite",
"substring",
"ureq",
]
[[package]]
@ -203,6 +204,12 @@ dependencies = [
"byte-tools",
]
[[package]]
name = "bumpalo"
version = "3.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
[[package]]
name = "byte-tools"
version = "0.3.1"
@ -258,6 +265,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "chunked_transfer"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e"
[[package]]
name = "clang-sys"
version = "0.29.3"
@ -474,6 +487,16 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "form_urlencoded"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
dependencies = [
"matches",
"percent-encoding",
]
[[package]]
name = "generic-array"
version = "0.12.4"
@ -563,6 +586,17 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "idna"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
dependencies = [
"matches",
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "indexmap"
version = "1.8.0"
@ -603,6 +637,15 @@ dependencies = [
"libc",
]
[[package]]
name = "js-sys"
version = "0.3.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
@ -670,6 +713,12 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
[[package]]
name = "matches"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "matrixmultiply"
version = "0.3.2"
@ -869,6 +918,12 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "percent-encoding"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pest"
version = "2.1.3"
@ -1059,6 +1114,21 @@ version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "ring"
version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
"cc",
"libc",
"once_cell",
"spin",
"untrusted",
"web-sys",
"winapi",
]
[[package]]
name = "ripemd160"
version = "0.9.1"
@ -1117,12 +1187,34 @@ dependencies = [
"transpose",
]
[[package]]
name = "rustls"
version = "0.20.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921"
dependencies = [
"log",
"ring",
"sct",
"webpki",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "sct"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "sha-1"
version = "0.8.2"
@ -1147,6 +1239,12 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "strength_reduce"
version = "0.2.3"
@ -1241,6 +1339,21 @@ dependencies = [
"winapi",
]
[[package]]
name = "tinyvec"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "transpose"
version = "0.2.1"
@ -1263,6 +1376,21 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]]
name = "unicode-bidi"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"
[[package]]
name = "unicode-normalization"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
version = "1.9.0"
@ -1275,6 +1403,41 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "ureq"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9399fa2f927a3d327187cbd201480cee55bee6ac5d3c77dd27f0c6814cff16d5"
dependencies = [
"base64",
"chunked_transfer",
"flate2",
"log",
"once_cell",
"rustls",
"url",
"webpki",
"webpki-roots",
]
[[package]]
name = "url"
version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
dependencies = [
"form_urlencoded",
"idna",
"matches",
"percent-encoding",
]
[[package]]
name = "vcpkg"
version = "0.2.15"
@ -1299,6 +1462,89 @@ version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wasm-bindgen"
version = "0.2.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2"
[[package]]
name = "web-sys"
version = "0.3.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "webpki"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "webpki-roots"
version = "0.22.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449"
dependencies = [
"webpki",
]
[[package]]
name = "winapi"
version = "0.3.9"

View File

@ -21,4 +21,5 @@ lofty = { git = "https://github.com/Serial-ATA/lofty-rs", rev = "4c0b7c2" }
dirs = "1"
chrono = "0.4.19"
regex = "1"
substring = "1.4.5"
substring = "1.4.5"
ureq = "2.4.0"

View File

@ -15,6 +15,7 @@ use std::process;
mod analyse;
mod db;
mod tags;
mod upload;
const VERSION: &'static str = env!("CARGO_PKG_VERSION");
@ -26,6 +27,7 @@ fn main() {
let mut keep_old:bool = false;
let mut dry_run:bool = false;
let mut tags_only:bool = false;
let mut upload = "".to_string();
match dirs::home_dir() {
Some(path) => { music_path = String::from(path.join("Music").to_string_lossy()); }
@ -48,6 +50,7 @@ fn main() {
arg_parse.refer(&mut dry_run).add_option(&["-r", "--dry-run"], StoreTrue, "Dry run, only show what needs to be done");
arg_parse.refer(&mut tags_only).add_option(&["-t", "--tags-only"], StoreTrue, "Re-read tags");
arg_parse.refer(&mut ignore_file).add_option(&["-i", "--ignore"], Store, "Update ignore status in DB");
arg_parse.refer(&mut upload).add_option(&["-u", "--upload"], Store, "Upload database to LMS (specify hostname or IP address)");
arg_parse.parse_args_or_exit();
}
@ -70,30 +73,39 @@ fn main() {
process::exit(-1);
}
let mpath = PathBuf::from(&music_path);
if !mpath.exists() {
log::error!("Music path ({}) does not exist", music_path);
process::exit(-1);
}
if !mpath.is_dir() {
log::error!("Music path ({}) is not a directory", music_path);
process::exit(-1);
}
if tags_only {
analyse::read_tags(&db_path, &mpath);
} else if !ignore_file.is_empty() {
let ignore_path = PathBuf::from(&ignore_file);
if !ignore_path.exists() {
log::error!("Ignore file ({}) does not exist", ignore_file);
if !upload.is_empty() {
if path.exists() {
upload::upload_db(&db_path, &upload);
} else {
log::error!("DB ({}) does not exist", db_path);
process::exit(-1);
}
if !ignore_path.is_file() {
log::error!("Ignore file ({}) is not a file", ignore_file);
process::exit(-1);
}
analyse::update_ignore(&db_path, &ignore_path);
} else {
analyse::analyse_files(&db_path, &mpath, dry_run, keep_old);
let mpath = PathBuf::from(&music_path);
if !mpath.exists() {
log::error!("Music path ({}) does not exist", music_path);
process::exit(-1);
}
if !mpath.is_dir() {
log::error!("Music path ({}) is not a directory", music_path);
process::exit(-1);
}
if tags_only {
analyse::read_tags(&db_path, &mpath);
} else if !ignore_file.is_empty() {
let ignore_path = PathBuf::from(&ignore_file);
if !ignore_path.exists() {
log::error!("Ignore file ({}) does not exist", ignore_file);
process::exit(-1);
}
if !ignore_path.is_file() {
log::error!("Ignore file ({}) is not a file", ignore_file);
process::exit(-1);
}
analyse::update_ignore(&db_path, &ignore_path);
} else {
analyse::analyse_files(&db_path, &mpath, dry_run, keep_old);
}
}
}

89
src/upload.rs Normal file
View File

@ -0,0 +1,89 @@
/**
* Analyse music with Bliss
*
* Copyright (c) 2022 Craig Drummond <craig.p.drummond@gmail.com>
* GPLv3 license.
*
**/
use std::fs::File;
use std::io::BufReader;
use std::process;
use substring::Substring;
use ureq;
fn fail(msg:&str) {
log::error!("{}", msg);
process::exit(-1);
}
pub fn upload_db(db_path:&String, lms:&String) {
// First tell LMS to restart the mixer in upload mode
let start_req = "{\"id\":1, \"method\":\"slim.request\",\"params\":[\"\",[\"blissmixer\",\"start-upload\"]]}";
let mut port:u16 = 0;
log::info!("Requesting LMS plugin to allow uploads");
match ureq::post(&format!("http://{}:9000/jsonrpc.js", lms)).send_string(&start_req) {
Ok(resp) => {
match resp.into_string() {
Ok(text) => {
match text.find("\"port\":") {
Some(s) => {
let txt = text.to_string().substring(s+7, text.len()).to_string();
match txt.find("}") {
Some(e) => {
let p = txt.substring(0, e);
let test = p.parse::<u16>();
match test {
Ok(val) => {
port = val;
},
Err(_) => { fail("Could not parse resp (cast)"); }
}
},
None => { fail("Could not parse resp (closing)"); }
}
},
None => { fail("Could not parse resp (no port)"); }
}
},
Err(_) => { fail("No text?")}
}
},
Err(e) => {
fail(&format!("Failed to ask LMS plugin to allow upload. {}", e));
}
}
if port<=0 {
fail("Invalid port");
}
// Now we have port number, do the actual upload...
log::info!("Uploading {}", db_path);
match File::open(db_path) {
Ok(file) => {
match file.metadata() {
Ok(meta) => {
let buffered_reader = BufReader::new(file);
match ureq::put(&format!("http://{}:{}/upload", lms, port)).set("Content-Length", &meta.len().to_string()).send(buffered_reader) {
Ok(_) => {
log::info!("Database uploaded")
},
Err(e) => {
fail(&format!("Failed to upload database. {}", e));
}
}
},
Err(e) => {
fail(&format!("Failed to open database. {}", e));
}
}
},
Err(e) => {
fail(&format!("Failed to open database. {}", e));
}
}
}