Merge branch 'search'
This commit is contained in:
commit
962ba5efc7
8 changed files with 97 additions and 22 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -4,7 +4,7 @@ version = "0.7.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ape 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ape 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"diesel 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"diesel 0.16.0 (git+https://github.com/diesel-rs/diesel?rev=034049d)",
|
||||||
"diesel_codegen 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"diesel_codegen 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -311,6 +311,15 @@ dependencies = [
|
||||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diesel"
|
||||||
|
version = "0.16.0"
|
||||||
|
source = "git+https://github.com/diesel-rs/diesel?rev=034049d#034049d38565393bf09d59dbe1e7ad38a8934295"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libsqlite3-sys 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "diesel"
|
name = "diesel"
|
||||||
version = "0.16.0"
|
version = "0.16.0"
|
||||||
|
@ -1770,6 +1779,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum derive-error-chain 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9ca9ade651388daad7c993f005d0d20c4f6fe78c1cdc93e95f161c6f5ede4a"
|
"checksum derive-error-chain 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9ca9ade651388daad7c993f005d0d20c4f6fe78c1cdc93e95f161c6f5ede4a"
|
||||||
"checksum derive_builder 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c614a69851b5fbf329a89c612c193d256c0dbb31b7a35eecff6f4b9578521c33"
|
"checksum derive_builder 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c614a69851b5fbf329a89c612c193d256c0dbb31b7a35eecff6f4b9578521c33"
|
||||||
"checksum derive_builder_core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eed37eae64daa5511467b1a55cebdf472deeaef108d22f62f25e8bbcaffd56ac"
|
"checksum derive_builder_core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eed37eae64daa5511467b1a55cebdf472deeaef108d22f62f25e8bbcaffd56ac"
|
||||||
|
"checksum diesel 0.16.0 (git+https://github.com/diesel-rs/diesel?rev=034049d)" = "<none>"
|
||||||
"checksum diesel 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "304226fa7a3982b0405f6bb95dd9c10c3e2000709f194038a60ec2c277150951"
|
"checksum diesel 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "304226fa7a3982b0405f6bb95dd9c10c3e2000709f194038a60ec2c277150951"
|
||||||
"checksum diesel_codegen 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18a42ca5c9b660add51d58bc5a50a87123380e1e458069c5504528a851ed7384"
|
"checksum diesel_codegen 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18a42ca5c9b660add51d58bc5a50a87123380e1e458069c5504528a851ed7384"
|
||||||
"checksum diesel_infer_schema 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bf1957ff5cd3b04772e43c162c2f69c2aa918080ff9b020276792d236be8be52"
|
"checksum diesel_infer_schema 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bf1957ff5cd3b04772e43c162c2f69c2aa918080ff9b020276792d236be8be52"
|
||||||
|
|
|
@ -9,7 +9,7 @@ ui = []
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ape = "0.1.2"
|
ape = "0.1.2"
|
||||||
app_dirs = "1.1.1"
|
app_dirs = "1.1.1"
|
||||||
diesel = { version = "0.16.0", features = ["sqlite"] }
|
diesel = { git = "https://github.com/diesel-rs/diesel", rev = "034049d", features = ["sqlite"] }
|
||||||
diesel_codegen = { version = "0.16.0", features = ["sqlite"] }
|
diesel_codegen = { version = "0.16.0", features = ["sqlite"] }
|
||||||
error-chain = "0.11.0"
|
error-chain = "0.11.0"
|
||||||
getopts = "0.2.15"
|
getopts = "0.2.15"
|
||||||
|
|
19
src/api.rs
19
src/api.rs
|
@ -112,6 +112,11 @@ fn get_endpoints(db: Arc<DB>, index_channel: Arc<Mutex<Sender<index::Command>>>)
|
||||||
auth_api_mount.mount("/recent/",
|
auth_api_mount.mount("/recent/",
|
||||||
move |request: &mut Request| self::recent(request, db.deref()));
|
move |request: &mut Request| self::recent(request, db.deref()));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
let db = db.clone();
|
||||||
|
auth_api_mount.mount("/search/",
|
||||||
|
move |request: &mut Request| self::search(request, db.deref()));
|
||||||
|
}
|
||||||
{
|
{
|
||||||
let db = db.clone();
|
let db = db.clone();
|
||||||
auth_api_mount.mount("/serve/",
|
auth_api_mount.mount("/serve/",
|
||||||
|
@ -429,6 +434,20 @@ fn recent(_: &mut Request, db: &DB) -> IronResult<Response> {
|
||||||
Ok(Response::with((status::Ok, result_json)))
|
Ok(Response::with((status::Ok, result_json)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn search(request: &mut Request, db: &DB) -> IronResult<Response> {
|
||||||
|
let query = request
|
||||||
|
.url
|
||||||
|
.path()
|
||||||
|
.join(&::std::path::MAIN_SEPARATOR.to_string());
|
||||||
|
let search_result = index::search(db, &query)?;
|
||||||
|
let result_json = serde_json::to_string(&search_result);
|
||||||
|
let result_json = match result_json {
|
||||||
|
Ok(j) => j,
|
||||||
|
Err(e) => return Err(IronError::new(e, status::InternalServerError)),
|
||||||
|
};
|
||||||
|
Ok(Response::with((status::Ok, result_json)))
|
||||||
|
}
|
||||||
|
|
||||||
fn serve(request: &mut Request, db: &DB) -> IronResult<Response> {
|
fn serve(request: &mut Request, db: &DB) -> IronResult<Response> {
|
||||||
let virtual_path = path_from_request(request);
|
let virtual_path = path_from_request(request);
|
||||||
let virtual_path = match virtual_path {
|
let virtual_path = match virtual_path {
|
||||||
|
|
|
@ -155,8 +155,8 @@ pub fn amend<T>(db: &T, new_config: &Config) -> Result<()>
|
||||||
if let Some(ref mount_dirs) = new_config.mount_dirs {
|
if let Some(ref mount_dirs) = new_config.mount_dirs {
|
||||||
diesel::delete(mount_points::table)
|
diesel::delete(mount_points::table)
|
||||||
.execute(connection.deref())?;
|
.execute(connection.deref())?;
|
||||||
diesel::insert(mount_dirs)
|
diesel::insert_into(mount_points::table)
|
||||||
.into(mount_points::table)
|
.values(mount_dirs)
|
||||||
.execute(connection.deref())?;
|
.execute(connection.deref())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,8 +184,8 @@ pub fn amend<T>(db: &T, new_config: &Config) -> Result<()>
|
||||||
.collect::<_>();
|
.collect::<_>();
|
||||||
for ref config_user in insert_users {
|
for ref config_user in insert_users {
|
||||||
let new_user = User::new(&config_user.name, &config_user.password, config_user.admin);
|
let new_user = User::new(&config_user.name, &config_user.password, config_user.admin);
|
||||||
diesel::insert(&new_user)
|
diesel::insert_into(users::table)
|
||||||
.into(users::table)
|
.values(&new_user)
|
||||||
.execute(connection.deref())?;
|
.execute(connection.deref())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
57
src/index.rs
57
src/index.rs
|
@ -1,6 +1,6 @@
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
use diesel;
|
use diesel;
|
||||||
use diesel::expression::sql;
|
use diesel::dsl::sql;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use diesel::sqlite::SqliteConnection;
|
use diesel::sqlite::SqliteConnection;
|
||||||
use diesel::types;
|
use diesel::types;
|
||||||
|
@ -124,8 +124,8 @@ impl<'conn> IndexBuilder<'conn> {
|
||||||
let connection = connection.deref();
|
let connection = connection.deref();
|
||||||
connection
|
connection
|
||||||
.transaction::<_, Error, _>(|| {
|
.transaction::<_, Error, _>(|| {
|
||||||
diesel::insert(&self.new_songs)
|
diesel::insert_into(songs::table)
|
||||||
.into(songs::table)
|
.values(&self.new_songs)
|
||||||
.execute(connection)?;
|
.execute(connection)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
@ -138,8 +138,8 @@ impl<'conn> IndexBuilder<'conn> {
|
||||||
let connection = connection.deref();
|
let connection = connection.deref();
|
||||||
connection
|
connection
|
||||||
.transaction::<_, Error, _>(|| {
|
.transaction::<_, Error, _>(|| {
|
||||||
diesel::insert(&self.new_directories)
|
diesel::insert_into(directories::table)
|
||||||
.into(directories::table)
|
.values(&self.new_directories)
|
||||||
.execute(connection)?;
|
.execute(connection)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
@ -382,7 +382,7 @@ pub fn update<T>(db: &T) -> Result<()>
|
||||||
clean(db)?;
|
clean(db)?;
|
||||||
populate(db)?;
|
populate(db)?;
|
||||||
info!("Library index update took {} seconds",
|
info!("Library index update took {} seconds",
|
||||||
start.elapsed().as_secs());
|
start.elapsed().as_secs());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -576,6 +576,51 @@ pub fn get_recent_albums<T>(db: &T, count: i64) -> Result<Vec<Directory>>
|
||||||
Ok(virtual_directories.collect::<Vec<_>>())
|
Ok(virtual_directories.collect::<Vec<_>>())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn search<T>(db: &T, query: &str) -> Result<Vec<CollectionFile>>
|
||||||
|
where T: ConnectionSource + VFSSource
|
||||||
|
{
|
||||||
|
let vfs = db.get_vfs()?;
|
||||||
|
let connection = db.get_connection();
|
||||||
|
let like_test = format!("%{}%", query);
|
||||||
|
let mut output = Vec::new();
|
||||||
|
|
||||||
|
// Find dirs with matching path and parent not matching
|
||||||
|
{
|
||||||
|
use self::directories::dsl::*;
|
||||||
|
let real_directories: Vec<Directory> = directories
|
||||||
|
.filter(path.like(&like_test))
|
||||||
|
.filter(parent.not_like(&like_test))
|
||||||
|
.load(connection.deref())?;
|
||||||
|
|
||||||
|
let virtual_directories = real_directories
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|s| virtualize_directory(&vfs, s));
|
||||||
|
|
||||||
|
output.extend(virtual_directories.map(|d| CollectionFile::Directory(d)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find songs with matching title/album/artist and non-matching parent
|
||||||
|
{
|
||||||
|
use self::songs::dsl::*;
|
||||||
|
let real_songs: Vec<Song> = songs
|
||||||
|
.filter(path.like(&like_test)
|
||||||
|
.or(title.like(&like_test))
|
||||||
|
.or(album.like(&like_test))
|
||||||
|
.or(artist.like(&like_test))
|
||||||
|
.or(album_artist.like(&like_test)))
|
||||||
|
.filter(parent.not_like(&like_test))
|
||||||
|
.load(connection.deref())?;
|
||||||
|
|
||||||
|
let virtual_songs = real_songs
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|s| virtualize_song(&vfs, s));
|
||||||
|
|
||||||
|
output.extend(virtual_songs.map(|s| CollectionFile::Song(s)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_populate() {
|
fn test_populate() {
|
||||||
let db = db::_get_test_db("populate.sqlite");
|
let db = db::_get_test_db("populate.sqlite");
|
||||||
|
|
|
@ -115,7 +115,10 @@ fn run() -> Result<()> {
|
||||||
options.optopt("p", "port", "set polaris to run on a custom port", "PORT");
|
options.optopt("p", "port", "set polaris to run on a custom port", "PORT");
|
||||||
options.optopt("d", "database", "set the path to index database", "FILE");
|
options.optopt("d", "database", "set the path to index database", "FILE");
|
||||||
options.optopt("w", "web", "set the path to web client files", "DIRECTORY");
|
options.optopt("w", "web", "set the path to web client files", "DIRECTORY");
|
||||||
options.optopt("l", "log", "set the log level to a value between 0 (off) and 3 (debug)", "LEVEL");
|
options.optopt("l",
|
||||||
|
"log",
|
||||||
|
"set the log level to a value between 0 (off) and 3 (debug)",
|
||||||
|
"LEVEL");
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
options.optflag("f",
|
options.optflag("f",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use core::clone::Clone;
|
use core::clone::Clone;
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
use diesel;
|
use diesel;
|
||||||
use diesel::expression::sql;
|
use diesel::dsl::sql;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use diesel::BelongingToDsl;
|
use diesel::BelongingToDsl;
|
||||||
use diesel::types::*;
|
use diesel::types::*;
|
||||||
|
@ -101,8 +101,8 @@ pub fn save_playlist<T>(playlist_name: &str,
|
||||||
owner: user.id,
|
owner: user.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
diesel::insert(&new_playlist)
|
diesel::insert_into(playlists::table)
|
||||||
.into(playlists::table)
|
.values(&new_playlist)
|
||||||
.execute(connection.deref())?;
|
.execute(connection.deref())?;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -140,8 +140,8 @@ pub fn save_playlist<T>(playlist_name: &str,
|
||||||
diesel::delete(old_songs).execute(connection.deref())?;
|
diesel::delete(old_songs).execute(connection.deref())?;
|
||||||
|
|
||||||
// Insert content
|
// Insert content
|
||||||
diesel::insert(&new_songs)
|
diesel::insert_into(playlist_songs::table)
|
||||||
.into(playlist_songs::table)
|
.values(&new_songs)
|
||||||
.execute(connection.deref())?;
|
.execute(connection.deref())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
use diesel;
|
use diesel;
|
||||||
use diesel::expression;
|
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use rand;
|
use rand;
|
||||||
use ring::{digest, pbkdf2};
|
use ring::{digest, pbkdf2};
|
||||||
|
@ -76,9 +75,8 @@ pub fn count<T>(db: &T) -> Result<i64>
|
||||||
{
|
{
|
||||||
use db::users::dsl::*;
|
use db::users::dsl::*;
|
||||||
let connection = db.get_connection();
|
let connection = db.get_connection();
|
||||||
Ok(users
|
let count = users.count().get_result(connection.deref())?;
|
||||||
.select(expression::count(name))
|
Ok(count)
|
||||||
.first(connection.deref())?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_admin<T>(db: &T, username: &str) -> Result<bool>
|
pub fn is_admin<T>(db: &T, username: &str) -> Result<bool>
|
||||||
|
|
Loading…
Add table
Reference in a new issue