Simplified error boilerplate

This commit is contained in:
Antoine Gersant 2020-01-04 16:42:28 -08:00
parent 0b0bfac8fb
commit f41f45f600
17 changed files with 139 additions and 234 deletions

30
Cargo.lock generated
View file

@ -13,6 +13,11 @@ dependencies = [
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "anyhow"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "ape" name = "ape"
version = "0.2.0" version = "0.2.0"
@ -553,7 +558,6 @@ name = "error-chain"
version = "0.12.1" version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1457,12 +1461,12 @@ dependencies = [
name = "polaris" name = "polaris"
version = "0.11.0" version = "0.11.0"
dependencies = [ dependencies = [
"anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
"ape 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ape 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"diesel 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "diesel 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"flame 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "flame 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"flamer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "flamer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1486,6 +1490,7 @@ dependencies = [
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)",
"simplelog 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "simplelog 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
"thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"unix-daemonize 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unix-daemonize 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2195,6 +2200,24 @@ dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "thiserror"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"thiserror-impl 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thiserror-impl"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "thread-id" name = "thread-id"
version = "3.3.0" version = "3.3.0"
@ -2620,6 +2643,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata] [metadata]
"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" "checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
"checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c"
"checksum ape 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "890eeb3dc52632a4b762e3ea6ac37475a35577f22fce09bb6e758c2aaf38a229" "checksum ape 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "890eeb3dc52632a4b762e3ea6ac37475a35577f22fce09bb6e758c2aaf38a229"
"checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" "checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d"
"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
@ -2858,6 +2882,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" "checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
"checksum term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" "checksum term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5"
"checksum thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6f357d1814b33bc2dc221243f8424104bfe72dbe911d5b71b3816a2dff1c977e"
"checksum thiserror-impl 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2e25d25307eb8436894f727aba8f65d07adf02e5b35a13cebed48bd282bfef"
"checksum thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1" "checksum thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum tiff 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b7c2cfc4742bd8a32f2e614339dd8ce30dbcf676bb262bd63a2327bc5df57d" "checksum tiff 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b7c2cfc4742bd8a32f2e614339dd8ce30dbcf676bb262bd63a2327bc5df57d"

View file

@ -9,12 +9,12 @@ ui = []
profile-index = ["flame", "flamer"] profile-index = ["flame", "flamer"]
[dependencies] [dependencies]
anyhow = "1.0"
ape = "0.2.0" ape = "0.2.0"
app_dirs = "1.1.1" app_dirs = "1.1.1"
base64 = "0.11.0" base64 = "0.11.0"
diesel = { version = "1.4", features = ["sqlite"] } diesel = { version = "1.4", features = ["sqlite"] }
diesel_migrations = { version = "1.4", features = ["sqlite"] } diesel_migrations = { version = "1.4", features = ["sqlite"] }
error-chain = "0.12.0"
flame = { version = "0.2.2", optional = true } flame = { version = "0.2.2", optional = true }
flamer = { version = "0.4", optional = true } flamer = { version = "0.4", optional = true }
getopts = "0.2.15" getopts = "0.2.15"
@ -36,6 +36,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_derive = "1.0" serde_derive = "1.0"
serde_json = "1.0" serde_json = "1.0"
simplelog = "0.7" simplelog = "0.7"
thiserror = "1.0"
toml = "0.5" toml = "0.5"
[dependencies.rocket_contrib] [dependencies.rocket_contrib]

View file

@ -1,4 +1,4 @@
use error_chain::bail; use anyhow::*;
use rocket::http::{Cookie, Cookies, RawStr, Status}; use rocket::http::{Cookie, Cookies, RawStr, Status};
use rocket::request::{self, FromParam, FromRequest, Request}; use rocket::request::{self, FromParam, FromRequest, Request};
use rocket::response::content::Html; use rocket::response::content::Html;
@ -11,10 +11,10 @@ use std::path::PathBuf;
use std::str; use std::str;
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use thiserror::Error;
use crate::config::{self, Config, Preferences}; use crate::config::{self, Config, Preferences};
use crate::db::DB; use crate::db::DB;
use crate::errors;
use crate::index; use crate::index;
use crate::lastfm; use crate::lastfm;
use crate::playlist; use crate::playlist;
@ -58,6 +58,30 @@ pub fn get_routes() -> Vec<rocket::Route> {
] ]
} }
#[derive(Error, Debug)]
enum APIError {
#[error("Incorrect Credentials")]
IncorrectCredentials,
#[error("Unspecified")]
Unspecified,
}
impl<'r> rocket::response::Responder<'r> for APIError {
fn respond_to(self, _: &rocket::request::Request<'_>) -> rocket::response::Result<'r> {
let status = match self {
APIError::IncorrectCredentials => rocket::http::Status::Unauthorized,
_ => rocket::http::Status::InternalServerError,
};
rocket::response::Response::build().status(status).ok()
}
}
impl From<anyhow::Error> for APIError {
fn from(_: anyhow::Error) -> Self {
APIError::Unspecified
}
}
struct Auth { struct Auth {
username: String, username: String,
} }
@ -168,7 +192,7 @@ pub struct InitialSetup {
} }
#[get("/initial_setup")] #[get("/initial_setup")]
fn initial_setup(db: State<'_, Arc<DB>>) -> Result<Json<InitialSetup>, errors::Error> { fn initial_setup(db: State<'_, Arc<DB>>) -> Result<Json<InitialSetup>> {
let initial_setup = InitialSetup { let initial_setup = InitialSetup {
has_any_users: user::count::<DB>(&db)? > 0, has_any_users: user::count::<DB>(&db)? > 0,
}; };
@ -176,10 +200,7 @@ fn initial_setup(db: State<'_, Arc<DB>>) -> Result<Json<InitialSetup>, errors::E
} }
#[get("/settings")] #[get("/settings")]
fn get_settings( fn get_settings(db: State<'_, Arc<DB>>, _admin_rights: AdminRights) -> Result<Json<Config>> {
db: State<'_, Arc<DB>>,
_admin_rights: AdminRights,
) -> Result<Json<Config>, errors::Error> {
let config = config::read::<DB>(&db)?; let config = config::read::<DB>(&db)?;
Ok(Json(config)) Ok(Json(config))
} }
@ -189,13 +210,13 @@ fn put_settings(
db: State<'_, Arc<DB>>, db: State<'_, Arc<DB>>,
_admin_rights: AdminRights, _admin_rights: AdminRights,
config: Json<Config>, config: Json<Config>,
) -> Result<(), errors::Error> { ) -> Result<()> {
config::amend::<DB>(&db, &config)?; config::amend::<DB>(&db, &config)?;
Ok(()) Ok(())
} }
#[get("/preferences")] #[get("/preferences")]
fn get_preferences(db: State<'_, Arc<DB>>, auth: Auth) -> Result<Json<Preferences>, errors::Error> { fn get_preferences(db: State<'_, Arc<DB>>, auth: Auth) -> Result<Json<Preferences>> {
let preferences = config::read_preferences::<DB>(&db, &auth.username)?; let preferences = config::read_preferences::<DB>(&db, &auth.username)?;
Ok(Json(preferences)) Ok(Json(preferences))
} }
@ -205,7 +226,7 @@ fn put_preferences(
db: State<'_, Arc<DB>>, db: State<'_, Arc<DB>>,
auth: Auth, auth: Auth,
preferences: Json<Preferences>, preferences: Json<Preferences>,
) -> Result<(), errors::Error> { ) -> Result<()> {
config::write_preferences::<DB>(&db, &auth.username, &preferences)?; config::write_preferences::<DB>(&db, &auth.username, &preferences)?;
Ok(()) Ok(())
} }
@ -214,7 +235,7 @@ fn put_preferences(
fn trigger_index( fn trigger_index(
command_sender: State<'_, Arc<index::CommandSender>>, command_sender: State<'_, Arc<index::CommandSender>>,
_admin_rights: AdminRights, _admin_rights: AdminRights,
) -> Result<(), errors::Error> { ) -> Result<()> {
command_sender.trigger_reindex()?; command_sender.trigger_reindex()?;
Ok(()) Ok(())
} }
@ -235,9 +256,9 @@ fn auth(
db: State<'_, Arc<DB>>, db: State<'_, Arc<DB>>,
credentials: Json<AuthCredentials>, credentials: Json<AuthCredentials>,
mut cookies: Cookies<'_>, mut cookies: Cookies<'_>,
) -> Result<Json<AuthOutput>, errors::Error> { ) -> std::result::Result<Json<AuthOutput>, APIError> {
if !user::auth::<DB>(&db, &credentials.username, &credentials.password)? { if !user::auth::<DB>(&db, &credentials.username, &credentials.password)? {
bail!(errors::ErrorKind::IncorrectCredentials) return Err(APIError::IncorrectCredentials);
} }
cookies.add_private(get_session_cookie(&credentials.username)); cookies.add_private(get_session_cookie(&credentials.username));
@ -249,10 +270,7 @@ fn auth(
} }
#[get("/browse")] #[get("/browse")]
fn browse_root( fn browse_root(db: State<'_, Arc<DB>>, _auth: Auth) -> Result<Json<Vec<index::CollectionFile>>> {
db: State<'_, Arc<DB>>,
_auth: Auth,
) -> Result<Json<Vec<index::CollectionFile>>, errors::Error> {
let result = index::browse(db.deref().deref(), &PathBuf::new())?; let result = index::browse(db.deref().deref(), &PathBuf::new())?;
Ok(Json(result)) Ok(Json(result))
} }
@ -262,16 +280,13 @@ fn browse(
db: State<'_, Arc<DB>>, db: State<'_, Arc<DB>>,
_auth: Auth, _auth: Auth,
path: VFSPathBuf, path: VFSPathBuf,
) -> Result<Json<Vec<index::CollectionFile>>, errors::Error> { ) -> Result<Json<Vec<index::CollectionFile>>> {
let result = index::browse(db.deref().deref(), &path.into() as &PathBuf)?; let result = index::browse(db.deref().deref(), &path.into() as &PathBuf)?;
Ok(Json(result)) Ok(Json(result))
} }
#[get("/flatten")] #[get("/flatten")]
fn flatten_root( fn flatten_root(db: State<'_, Arc<DB>>, _auth: Auth) -> Result<Json<Vec<index::Song>>> {
db: State<'_, Arc<DB>>,
_auth: Auth,
) -> Result<Json<Vec<index::Song>>, errors::Error> {
let result = index::flatten(db.deref().deref(), &PathBuf::new())?; let result = index::flatten(db.deref().deref(), &PathBuf::new())?;
Ok(Json(result)) Ok(Json(result))
} }
@ -281,34 +296,25 @@ fn flatten(
db: State<'_, Arc<DB>>, db: State<'_, Arc<DB>>,
_auth: Auth, _auth: Auth,
path: VFSPathBuf, path: VFSPathBuf,
) -> Result<Json<Vec<index::Song>>, errors::Error> { ) -> Result<Json<Vec<index::Song>>> {
let result = index::flatten(db.deref().deref(), &path.into() as &PathBuf)?; let result = index::flatten(db.deref().deref(), &path.into() as &PathBuf)?;
Ok(Json(result)) Ok(Json(result))
} }
#[get("/random")] #[get("/random")]
fn random( fn random(db: State<'_, Arc<DB>>, _auth: Auth) -> Result<Json<Vec<index::Directory>>> {
db: State<'_, Arc<DB>>,
_auth: Auth,
) -> Result<Json<Vec<index::Directory>>, errors::Error> {
let result = index::get_random_albums(db.deref().deref(), 20)?; let result = index::get_random_albums(db.deref().deref(), 20)?;
Ok(Json(result)) Ok(Json(result))
} }
#[get("/recent")] #[get("/recent")]
fn recent( fn recent(db: State<'_, Arc<DB>>, _auth: Auth) -> Result<Json<Vec<index::Directory>>> {
db: State<'_, Arc<DB>>,
_auth: Auth,
) -> Result<Json<Vec<index::Directory>>, errors::Error> {
let result = index::get_recent_albums(db.deref().deref(), 20)?; let result = index::get_recent_albums(db.deref().deref(), 20)?;
Ok(Json(result)) Ok(Json(result))
} }
#[get("/search")] #[get("/search")]
fn search_root( fn search_root(db: State<'_, Arc<DB>>, _auth: Auth) -> Result<Json<Vec<index::CollectionFile>>> {
db: State<'_, Arc<DB>>,
_auth: Auth,
) -> Result<Json<Vec<index::CollectionFile>>, errors::Error> {
let result = index::search(db.deref().deref(), "")?; let result = index::search(db.deref().deref(), "")?;
Ok(Json(result)) Ok(Json(result))
} }
@ -318,7 +324,7 @@ fn search(
db: State<'_, Arc<DB>>, db: State<'_, Arc<DB>>,
_auth: Auth, _auth: Auth,
query: String, query: String,
) -> Result<Json<Vec<index::CollectionFile>>, errors::Error> { ) -> Result<Json<Vec<index::CollectionFile>>> {
let result = index::search(db.deref().deref(), &query)?; let result = index::search(db.deref().deref(), &query)?;
Ok(Json(result)) Ok(Json(result))
} }
@ -328,7 +334,7 @@ fn serve(
db: State<'_, Arc<DB>>, db: State<'_, Arc<DB>>,
_auth: Auth, _auth: Auth,
path: VFSPathBuf, path: VFSPathBuf,
) -> Result<serve::RangeResponder<File>, errors::Error> { ) -> Result<serve::RangeResponder<File>> {
let db: &DB = db.deref().deref(); let db: &DB = db.deref().deref();
let vfs = db.get_vfs()?; let vfs = db.get_vfs()?;
let real_path = vfs.virtual_to_real(&path.into() as &PathBuf)?; let real_path = vfs.virtual_to_real(&path.into() as &PathBuf)?;
@ -349,10 +355,7 @@ pub struct ListPlaylistsEntry {
} }
#[get("/playlists")] #[get("/playlists")]
fn list_playlists( fn list_playlists(db: State<'_, Arc<DB>>, auth: Auth) -> Result<Json<Vec<ListPlaylistsEntry>>> {
db: State<'_, Arc<DB>>,
auth: Auth,
) -> Result<Json<Vec<ListPlaylistsEntry>>, errors::Error> {
let playlist_names = playlist::list_playlists(&auth.username, db.deref().deref())?; let playlist_names = playlist::list_playlists(&auth.username, db.deref().deref())?;
let playlists: Vec<ListPlaylistsEntry> = playlist_names let playlists: Vec<ListPlaylistsEntry> = playlist_names
.into_iter() .into_iter()
@ -373,7 +376,7 @@ fn save_playlist(
auth: Auth, auth: Auth,
name: String, name: String,
playlist: Json<SavePlaylistInput>, playlist: Json<SavePlaylistInput>,
) -> Result<(), errors::Error> { ) -> Result<()> {
playlist::save_playlist(&name, &auth.username, &playlist.tracks, db.deref().deref())?; playlist::save_playlist(&name, &auth.username, &playlist.tracks, db.deref().deref())?;
Ok(()) Ok(())
} }
@ -383,33 +386,25 @@ fn read_playlist(
db: State<'_, Arc<DB>>, db: State<'_, Arc<DB>>,
auth: Auth, auth: Auth,
name: String, name: String,
) -> Result<Json<Vec<index::Song>>, errors::Error> { ) -> Result<Json<Vec<index::Song>>> {
let songs = playlist::read_playlist(&name, &auth.username, db.deref().deref())?; let songs = playlist::read_playlist(&name, &auth.username, db.deref().deref())?;
Ok(Json(songs)) Ok(Json(songs))
} }
#[delete("/playlist/<name>")] #[delete("/playlist/<name>")]
fn delete_playlist(db: State<'_, Arc<DB>>, auth: Auth, name: String) -> Result<(), errors::Error> { fn delete_playlist(db: State<'_, Arc<DB>>, auth: Auth, name: String) -> Result<()> {
playlist::delete_playlist(&name, &auth.username, db.deref().deref())?; playlist::delete_playlist(&name, &auth.username, db.deref().deref())?;
Ok(()) Ok(())
} }
#[put("/lastfm/now_playing/<path>")] #[put("/lastfm/now_playing/<path>")]
fn lastfm_now_playing( fn lastfm_now_playing(db: State<'_, Arc<DB>>, auth: Auth, path: VFSPathBuf) -> Result<()> {
db: State<'_, Arc<DB>>,
auth: Auth,
path: VFSPathBuf,
) -> Result<(), errors::Error> {
lastfm::now_playing(db.deref().deref(), &auth.username, &path.into() as &PathBuf)?; lastfm::now_playing(db.deref().deref(), &auth.username, &path.into() as &PathBuf)?;
Ok(()) Ok(())
} }
#[post("/lastfm/scrobble/<path>")] #[post("/lastfm/scrobble/<path>")]
fn lastfm_scrobble( fn lastfm_scrobble(db: State<'_, Arc<DB>>, auth: Auth, path: VFSPathBuf) -> Result<()> {
db: State<'_, Arc<DB>>,
auth: Auth,
path: VFSPathBuf,
) -> Result<(), errors::Error> {
lastfm::scrobble(db.deref().deref(), &auth.username, &path.into() as &PathBuf)?; lastfm::scrobble(db.deref().deref(), &auth.username, &path.into() as &PathBuf)?;
Ok(()) Ok(())
} }
@ -420,32 +415,23 @@ fn lastfm_link(
auth: Auth, auth: Auth,
token: String, token: String,
content: String, content: String,
) -> Result<Html<String>, errors::Error> { ) -> Result<Html<String>> {
lastfm::link(db.deref().deref(), &auth.username, &token)?; lastfm::link(db.deref().deref(), &auth.username, &token)?;
// Percent decode // Percent decode
let base64_content = match RawStr::from_str(&content).percent_decode() { let base64_content = RawStr::from_str(&content).percent_decode()?;
Ok(s) => s,
Err(_) => bail!(errors::ErrorKind::EncodingError),
};
// Base64 decode // Base64 decode
let popup_content = match base64::decode(base64_content.as_bytes()) { let popup_content = base64::decode(base64_content.as_bytes())?;
Ok(c) => c,
Err(_) => bail!(errors::ErrorKind::EncodingError),
};
// UTF-8 decode // UTF-8 decode
let popup_content_string = match str::from_utf8(&popup_content) { let popup_content_string = str::from_utf8(&popup_content)?;
Ok(s) => s,
Err(_) => bail!(errors::ErrorKind::EncodingError),
};
Ok(Html(popup_content_string.to_string())) Ok(Html(popup_content_string.to_string()))
} }
#[delete("/lastfm/link")] #[delete("/lastfm/link")]
fn lastfm_unlink(db: State<'_, Arc<DB>>, auth: Auth) -> Result<(), errors::Error> { fn lastfm_unlink(db: State<'_, Arc<DB>>, auth: Auth) -> Result<()> {
lastfm::unlink(db.deref().deref(), &auth.username)?; lastfm::unlink(db.deref().deref(), &auth.username)?;
Ok(()) Ok(())
} }

View file

@ -1,7 +1,7 @@
use anyhow::*;
use core::ops::Deref; use core::ops::Deref;
use diesel; use diesel;
use diesel::prelude::*; use diesel::prelude::*;
use error_chain::bail;
use log::info; use log::info;
use regex::Regex; use regex::Regex;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -13,7 +13,6 @@ use toml;
use crate::db::ConnectionSource; use crate::db::ConnectionSource;
use crate::db::{ddns_config, misc_settings, mount_points, users}; use crate::db::{ddns_config, misc_settings, mount_points, users};
use crate::ddns::DDNSConfig; use crate::ddns::DDNSConfig;
use crate::errors::*;
use crate::user::*; use crate::user::*;
use crate::vfs::MountPoint; use crate::vfs::MountPoint;

View file

@ -1,14 +1,12 @@
use anyhow::*;
use core::ops::Deref; use core::ops::Deref;
use diesel::prelude::*; use diesel::prelude::*;
use diesel::sqlite::SqliteConnection; use diesel::sqlite::SqliteConnection;
use diesel_migrations; use diesel_migrations;
use error_chain::bail;
use log::info; use log::info;
use std::path::Path; use std::path::Path;
use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::{Arc, Mutex, MutexGuard};
use crate::errors::*;
mod schema; mod schema;
pub use self::schema::*; pub use self::schema::*;

View file

@ -1,15 +1,14 @@
use anyhow::*;
use core::ops::Deref; use core::ops::Deref;
use diesel::prelude::*; use diesel::prelude::*;
use log::{error, info}; use log::{error, info};
use reqwest; use reqwest;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::io;
use std::thread; use std::thread;
use std::time; use std::time;
use crate::db::ddns_config; use crate::db::ddns_config;
use crate::db::{ConnectionSource, DB}; use crate::db::{ConnectionSource, DB};
use crate::errors;
#[derive(Clone, Debug, Deserialize, Insertable, PartialEq, Queryable, Serialize)] #[derive(Clone, Debug, Deserialize, Insertable, PartialEq, Queryable, Serialize)]
#[table_name = "ddns_config"] #[table_name = "ddns_config"]
@ -20,11 +19,11 @@ pub struct DDNSConfig {
} }
pub trait DDNSConfigSource { pub trait DDNSConfigSource {
fn get_ddns_config(&self) -> errors::Result<DDNSConfig>; fn get_ddns_config(&self) -> Result<DDNSConfig>;
} }
impl DDNSConfigSource for DB { impl DDNSConfigSource for DB {
fn get_ddns_config(&self) -> errors::Result<DDNSConfig> { fn get_ddns_config(&self) -> Result<DDNSConfig> {
use self::ddns_config::dsl::*; use self::ddns_config::dsl::*;
let connection = self.get_connection(); let connection = self.get_connection();
Ok(ddns_config Ok(ddns_config
@ -33,35 +32,9 @@ impl DDNSConfigSource for DB {
} }
} }
#[derive(Debug)]
enum DDNSError {
Internal(errors::Error),
Io(io::Error),
Reqwest(reqwest::Error),
Update(reqwest::StatusCode),
}
impl From<io::Error> for DDNSError {
fn from(err: io::Error) -> DDNSError {
DDNSError::Io(err)
}
}
impl From<errors::Error> for DDNSError {
fn from(err: errors::Error) -> DDNSError {
DDNSError::Internal(err)
}
}
impl From<reqwest::Error> for DDNSError {
fn from(err: reqwest::Error) -> DDNSError {
DDNSError::Reqwest(err)
}
}
const DDNS_UPDATE_URL: &str = "https://ydns.io/api/v1/update/"; const DDNS_UPDATE_URL: &str = "https://ydns.io/api/v1/update/";
fn update_my_ip<T>(config_source: &T) -> Result<(), DDNSError> fn update_my_ip<T>(config_source: &T) -> Result<()>
where where
T: DDNSConfigSource, T: DDNSConfigSource,
{ {
@ -78,7 +51,10 @@ where
.basic_auth(config.username, Some(config.password)) .basic_auth(config.username, Some(config.password))
.send()?; .send()?;
if !res.status().is_success() { if !res.status().is_success() {
return Err(DDNSError::Update(res.status())); bail!(
"DDNS update query failed with status code: {}",
res.status()
);
} }
Ok(()) Ok(())
} }

View file

@ -1,57 +0,0 @@
use ape;
use core;
use diesel;
use diesel_migrations;
use error_chain::error_chain;
use getopts;
use id3;
use image;
use lewton;
use metaflac;
use regex;
use rocket;
use rustfm_scrobble;
use serde_json;
use std;
use toml;
error_chain! {
foreign_links {
Ape(ape::Error);
Diesel(diesel::result::Error);
DieselConnection(diesel::ConnectionError);
DieselMigration(diesel_migrations::RunMigrationsError);
Encoding(core::str::Utf8Error);
Flac(metaflac::Error);
GetOpts(getopts::Fail);
Id3(id3::Error);
Image(image::ImageError);
Io(std::io::Error);
Json(serde_json::Error);
Time(std::time::SystemTimeError);
Toml(toml::de::Error);
Regex(regex::Error);
RocketConfig(rocket::config::ConfigError);
Scrobbler(rustfm_scrobble::ScrobblerError);
Vorbis(lewton::VorbisError);
}
errors {
DaemonError {}
IncorrectCredentials {}
EncodingError {}
MissingLastFMCredentials {}
}
}
impl<'r> rocket::response::Responder<'r> for Error {
fn respond_to(self, _: &rocket::request::Request<'_>) -> rocket::response::Result<'r> {
let mut build = rocket::response::Response::build();
build
.status(match self.0 {
ErrorKind::IncorrectCredentials => rocket::http::Status::Unauthorized,
_ => rocket::http::Status::InternalServerError,
})
.ok()
}
}

View file

@ -1,10 +1,10 @@
use anyhow::*;
use core::ops::Deref; use core::ops::Deref;
use diesel; use diesel;
use diesel::dsl::sql; use diesel::dsl::sql;
use diesel::prelude::*; use diesel::prelude::*;
use diesel::sql_types; use diesel::sql_types;
use diesel::sqlite::SqliteConnection; use diesel::sqlite::SqliteConnection;
use error_chain::bail;
#[cfg(feature = "profile-index")] #[cfg(feature = "profile-index")]
use flame; use flame;
use log::{error, info}; use log::{error, info};
@ -24,7 +24,6 @@ use crate::config::MiscSettings;
use crate::db; use crate::db;
use crate::db::{directories, misc_settings, songs}; use crate::db::{directories, misc_settings, songs};
use crate::db::{ConnectionSource, DB}; use crate::db::{ConnectionSource, DB};
use crate::errors;
use crate::metadata; use crate::metadata;
use crate::vfs::{VFSSource, VFS}; use crate::vfs::{VFSSource, VFS};
@ -63,7 +62,7 @@ impl CommandSender {
} }
} }
pub fn trigger_reindex(&self) -> Result<(), errors::Error> { pub fn trigger_reindex(&self) -> Result<()> {
let sender = self.sender.lock().unwrap(); let sender = self.sender.lock().unwrap();
match sender.send(Command::REINDEX) { match sender.send(Command::REINDEX) {
Ok(_) => Ok(()), Ok(_) => Ok(()),
@ -72,7 +71,7 @@ impl CommandSender {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn exit(&self) -> Result<(), errors::Error> { pub fn exit(&self) -> Result<()> {
let sender = self.sender.lock().unwrap(); let sender = self.sender.lock().unwrap();
match sender.send(Command::EXIT) { match sender.send(Command::EXIT) {
Ok(_) => Ok(()), Ok(_) => Ok(()),
@ -175,7 +174,7 @@ impl<'conn> IndexBuilder<'conn> {
fn new( fn new(
connection: &Mutex<SqliteConnection>, connection: &Mutex<SqliteConnection>,
album_art_pattern: Regex, album_art_pattern: Regex,
) -> Result<IndexBuilder<'_>, errors::Error> { ) -> Result<IndexBuilder<'_>> {
let mut new_songs = Vec::new(); let mut new_songs = Vec::new();
let mut new_directories = Vec::new(); let mut new_directories = Vec::new();
new_songs.reserve_exact(INDEX_BUILDING_INSERT_BUFFER_SIZE); new_songs.reserve_exact(INDEX_BUILDING_INSERT_BUFFER_SIZE);
@ -189,10 +188,10 @@ impl<'conn> IndexBuilder<'conn> {
} }
#[cfg_attr(feature = "profile-index", flame)] #[cfg_attr(feature = "profile-index", flame)]
fn flush_songs(&mut self) -> Result<(), errors::Error> { fn flush_songs(&mut self) -> Result<()> {
let connection = self.connection.lock().unwrap(); let connection = self.connection.lock().unwrap();
let connection = connection.deref(); let connection = connection.deref();
connection.transaction::<_, errors::Error, _>(|| { connection.transaction::<_, anyhow::Error, _>(|| {
diesel::insert_into(songs::table) diesel::insert_into(songs::table)
.values(&self.new_songs) .values(&self.new_songs)
.execute(connection)?; .execute(connection)?;
@ -203,10 +202,10 @@ impl<'conn> IndexBuilder<'conn> {
} }
#[cfg_attr(feature = "profile-index", flame)] #[cfg_attr(feature = "profile-index", flame)]
fn flush_directories(&mut self) -> Result<(), errors::Error> { fn flush_directories(&mut self) -> Result<()> {
let connection = self.connection.lock().unwrap(); let connection = self.connection.lock().unwrap();
let connection = connection.deref(); let connection = connection.deref();
connection.transaction::<_, errors::Error, _>(|| { connection.transaction::<_, anyhow::Error, _>(|| {
diesel::insert_into(directories::table) diesel::insert_into(directories::table)
.values(&self.new_directories) .values(&self.new_directories)
.execute(connection)?; .execute(connection)?;
@ -217,7 +216,7 @@ impl<'conn> IndexBuilder<'conn> {
} }
#[cfg_attr(feature = "profile-index", flame)] #[cfg_attr(feature = "profile-index", flame)]
fn push_song(&mut self, song: NewSong) -> Result<(), errors::Error> { fn push_song(&mut self, song: NewSong) -> Result<()> {
if self.new_songs.len() >= self.new_songs.capacity() { if self.new_songs.len() >= self.new_songs.capacity() {
self.flush_songs()?; self.flush_songs()?;
} }
@ -226,7 +225,7 @@ impl<'conn> IndexBuilder<'conn> {
} }
#[cfg_attr(feature = "profile-index", flame)] #[cfg_attr(feature = "profile-index", flame)]
fn push_directory(&mut self, directory: NewDirectory) -> Result<(), errors::Error> { fn push_directory(&mut self, directory: NewDirectory) -> Result<()> {
if self.new_directories.len() >= self.new_directories.capacity() { if self.new_directories.len() >= self.new_directories.capacity() {
self.flush_directories()?; self.flush_directories()?;
} }
@ -234,7 +233,7 @@ impl<'conn> IndexBuilder<'conn> {
Ok(()) Ok(())
} }
fn get_artwork(&self, dir: &Path) -> Result<Option<String>, errors::Error> { fn get_artwork(&self, dir: &Path) -> Result<Option<String>> {
for file in fs::read_dir(dir)? { for file in fs::read_dir(dir)? {
let file = file?; let file = file?;
if let Some(name_string) = file.file_name().to_str() { if let Some(name_string) = file.file_name().to_str() {
@ -247,17 +246,13 @@ impl<'conn> IndexBuilder<'conn> {
} }
#[cfg_attr(feature = "profile-index", flame)] #[cfg_attr(feature = "profile-index", flame)]
fn populate_directory( fn populate_directory(&mut self, parent: Option<&Path>, path: &Path) -> Result<()> {
&mut self,
parent: Option<&Path>,
path: &Path,
) -> Result<(), errors::Error> {
// Find artwork // Find artwork
let artwork = self.get_artwork(path).unwrap_or(None); let artwork = self.get_artwork(path).unwrap_or(None);
// Extract path and parent path // Extract path and parent path
let parent_string = parent.and_then(|p| p.to_str()).map(|s| s.to_owned()); let parent_string = parent.and_then(|p| p.to_str()).map(|s| s.to_owned());
let path_string = path.to_str().ok_or("Invalid directory path")?; let path_string = path.to_str().ok_or(anyhow!("Invalid directory path"))?;
// Find date added // Find date added
let metadata = fs::metadata(path_string)?; let metadata = fs::metadata(path_string)?;
@ -369,7 +364,7 @@ impl<'conn> IndexBuilder<'conn> {
} }
#[cfg_attr(feature = "profile-index", flame)] #[cfg_attr(feature = "profile-index", flame)]
fn clean<T>(db: &T) -> Result<(), errors::Error> fn clean<T>(db: &T) -> Result<()>
where where
T: ConnectionSource + VFSSource, T: ConnectionSource + VFSSource,
{ {
@ -429,7 +424,7 @@ where
} }
#[cfg_attr(feature = "profile-index", flame)] #[cfg_attr(feature = "profile-index", flame)]
fn populate<T>(db: &T) -> Result<(), errors::Error> fn populate<T>(db: &T) -> Result<()>
where where
T: ConnectionSource + VFSSource, T: ConnectionSource + VFSSource,
{ {
@ -453,7 +448,7 @@ where
Ok(()) Ok(())
} }
pub fn update<T>(db: &T) -> Result<(), errors::Error> pub fn update<T>(db: &T) -> Result<()>
where where
T: ConnectionSource + VFSSource, T: ConnectionSource + VFSSource,
{ {
@ -512,7 +507,7 @@ where
let sleep_duration; let sleep_duration;
{ {
let connection = db.get_connection(); let connection = db.get_connection();
let settings: Result<MiscSettings, errors::Error> = misc_settings::table let settings: Result<MiscSettings> = misc_settings::table
.get_result(connection.deref()) .get_result(connection.deref())
.map_err(|e| e.into()); .map_err(|e| e.into());
if let Err(ref e) = settings { if let Err(ref e) = settings {
@ -556,7 +551,7 @@ fn virtualize_directory(vfs: &VFS, mut directory: Directory) -> Option<Directory
Some(directory) Some(directory)
} }
pub fn browse<T, P>(db: &T, virtual_path: P) -> Result<Vec<CollectionFile>, errors::Error> pub fn browse<T, P>(db: &T, virtual_path: P) -> Result<Vec<CollectionFile>>
where where
T: ConnectionSource + VFSSource, T: ConnectionSource + VFSSource,
P: AsRef<Path>, P: AsRef<Path>,
@ -601,7 +596,7 @@ where
Ok(output) Ok(output)
} }
pub fn flatten<T, P>(db: &T, virtual_path: P) -> Result<Vec<Song>, errors::Error> pub fn flatten<T, P>(db: &T, virtual_path: P) -> Result<Vec<Song>>
where where
T: ConnectionSource + VFSSource, T: ConnectionSource + VFSSource,
P: AsRef<Path>, P: AsRef<Path>,
@ -627,7 +622,7 @@ where
Ok(virtual_songs.collect::<Vec<_>>()) Ok(virtual_songs.collect::<Vec<_>>())
} }
pub fn get_random_albums<T>(db: &T, count: i64) -> Result<Vec<Directory>, errors::Error> pub fn get_random_albums<T>(db: &T, count: i64) -> Result<Vec<Directory>>
where where
T: ConnectionSource + VFSSource, T: ConnectionSource + VFSSource,
{ {
@ -645,7 +640,7 @@ where
Ok(virtual_directories.collect::<Vec<_>>()) Ok(virtual_directories.collect::<Vec<_>>())
} }
pub fn get_recent_albums<T>(db: &T, count: i64) -> Result<Vec<Directory>, errors::Error> pub fn get_recent_albums<T>(db: &T, count: i64) -> Result<Vec<Directory>>
where where
T: ConnectionSource + VFSSource, T: ConnectionSource + VFSSource,
{ {
@ -663,7 +658,7 @@ where
Ok(virtual_directories.collect::<Vec<_>>()) Ok(virtual_directories.collect::<Vec<_>>())
} }
pub fn search<T>(db: &T, query: &str) -> Result<Vec<CollectionFile>, errors::Error> pub fn search<T>(db: &T, query: &str) -> Result<Vec<CollectionFile>>
where where
T: ConnectionSource + VFSSource, T: ConnectionSource + VFSSource,
{ {
@ -711,7 +706,7 @@ where
Ok(output) Ok(output)
} }
pub fn get_song<T>(db: &T, virtual_path: &Path) -> Result<Song, errors::Error> pub fn get_song<T>(db: &T, virtual_path: &Path) -> Result<Song>
where where
T: ConnectionSource + VFSSource, T: ConnectionSource + VFSSource,
{ {

View file

@ -1,9 +1,9 @@
use anyhow::*;
use rustfm_scrobble::{Scrobble, Scrobbler}; use rustfm_scrobble::{Scrobble, Scrobbler};
use serde::Deserialize; use serde::Deserialize;
use std::path::Path; use std::path::Path;
use crate::db::ConnectionSource; use crate::db::ConnectionSource;
use crate::errors;
use crate::index; use crate::index;
use crate::user; use crate::user;
use crate::vfs::VFSSource; use crate::vfs::VFSSource;
@ -42,7 +42,7 @@ struct AuthResponse {
pub session: AuthResponseSession, pub session: AuthResponseSession,
} }
fn scrobble_from_path<T>(db: &T, track: &Path) -> Result<Scrobble, errors::Error> fn scrobble_from_path<T>(db: &T, track: &Path) -> Result<Scrobble>
where where
T: ConnectionSource + VFSSource, T: ConnectionSource + VFSSource,
{ {
@ -54,7 +54,7 @@ where
)) ))
} }
pub fn link<T>(db: &T, username: &str, token: &str) -> Result<(), errors::Error> pub fn link<T>(db: &T, username: &str, token: &str) -> Result<()>
where where
T: ConnectionSource + VFSSource, T: ConnectionSource + VFSSource,
{ {
@ -64,14 +64,14 @@ where
user::lastfm_link(db, username, &auth_response.name, &auth_response.key) user::lastfm_link(db, username, &auth_response.name, &auth_response.key)
} }
pub fn unlink<T>(db: &T, username: &str) -> Result<(), errors::Error> pub fn unlink<T>(db: &T, username: &str) -> Result<()>
where where
T: ConnectionSource + VFSSource, T: ConnectionSource + VFSSource,
{ {
user::lastfm_unlink(db, username) user::lastfm_unlink(db, username)
} }
pub fn scrobble<T>(db: &T, username: &str, track: &Path) -> Result<(), errors::Error> pub fn scrobble<T>(db: &T, username: &str, track: &Path) -> Result<()>
where where
T: ConnectionSource + VFSSource, T: ConnectionSource + VFSSource,
{ {
@ -83,7 +83,7 @@ where
Ok(()) Ok(())
} }
pub fn now_playing<T>(db: &T, username: &str, track: &Path) -> Result<(), errors::Error> pub fn now_playing<T>(db: &T, username: &str, track: &Path) -> Result<()>
where where
T: ConnectionSource + VFSSource, T: ConnectionSource + VFSSource,
{ {

View file

@ -20,9 +20,8 @@ use std::io::prelude::*;
#[cfg(unix)] #[cfg(unix)]
use unix_daemonize::{daemonize_redirect, ChdirMode}; use unix_daemonize::{daemonize_redirect, ChdirMode};
use crate::errors::*; use anyhow::*;
use core::ops::Deref; use core::ops::Deref;
use error_chain::bail;
use getopts::Options; use getopts::Options;
use log::info; use log::info;
use simplelog::{LevelFilter, SimpleLogger, TermLogger, TerminalMode}; use simplelog::{LevelFilter, SimpleLogger, TermLogger, TerminalMode};
@ -35,7 +34,6 @@ mod api_tests;
mod config; mod config;
mod db; mod db;
mod ddns; mod ddns;
mod errors;
mod index; mod index;
mod lastfm; mod lastfm;
mod metadata; mod metadata;
@ -58,20 +56,6 @@ fn log_config() -> simplelog::Config {
.build() .build()
} }
fn main() {
if let Err(ref e) = run() {
println!("Error: {}", e);
for e in e.iter().skip(1) {
println!("caused by: {}", e);
}
if let Some(backtrace) = e.backtrace() {
println!("backtrace: {:?}", backtrace);
}
::std::process::exit(1);
}
}
#[cfg(unix)] #[cfg(unix)]
fn daemonize(options: &getopts::Matches) -> Result<()> { fn daemonize(options: &getopts::Matches) -> Result<()> {
if options.opt_present("f") { if options.opt_present("f") {
@ -128,7 +112,7 @@ fn notify_ready() {
#[cfg(not(unix))] #[cfg(not(unix))]
fn notify_ready() {} fn notify_ready() {}
fn run() -> Result<()> { fn main() -> Result<()> {
// Parse CLI options // Parse CLI options
let args: Vec<String> = std::env::args().collect(); let args: Vec<String> = std::env::args().collect();
let mut options = Options::new(); let mut options = Options::new();
@ -241,7 +225,7 @@ fn run() -> Result<()> {
.opt_str("p") .opt_str("p")
.unwrap_or_else(|| "5050".to_owned()) .unwrap_or_else(|| "5050".to_owned())
.parse() .parse()
.or(Err("invalid port number"))?; .with_context(|| "Invalid port number")?;
let server = server::get_server( let server = server::get_server(
port, port,

View file

@ -1,5 +1,5 @@
use anyhow::*;
use ape; use ape;
use error_chain::bail;
use id3; use id3;
use lewton::inside_ogg::OggStreamReader; use lewton::inside_ogg::OggStreamReader;
use metaflac; use metaflac;
@ -8,7 +8,6 @@ use regex::Regex;
use std::fs; use std::fs;
use std::path::Path; use std::path::Path;
use crate::errors::*;
use crate::utils; use crate::utils;
use crate::utils::AudioFormat; use crate::utils::AudioFormat;
@ -151,7 +150,9 @@ fn read_vorbis(path: &Path) -> Result<SongTags> {
#[cfg_attr(feature = "profile-index", flame)] #[cfg_attr(feature = "profile-index", flame)]
fn read_flac(path: &Path) -> Result<SongTags> { fn read_flac(path: &Path) -> Result<SongTags> {
let tag = metaflac::Tag::read_from_path(path)?; let tag = metaflac::Tag::read_from_path(path)?;
let vorbis = tag.vorbis_comments().ok_or("Missing Vorbis comments")?; let vorbis = tag
.vorbis_comments()
.ok_or(anyhow!("Missing Vorbis comments"))?;
let disc_number = vorbis let disc_number = vorbis
.get("DISCNUMBER") .get("DISCNUMBER")
.and_then(|d| d[0].parse::<u32>().ok()); .and_then(|d| d[0].parse::<u32>().ok());

View file

@ -1,3 +1,4 @@
use anyhow::*;
use core::clone::Clone; use core::clone::Clone;
use core::ops::Deref; use core::ops::Deref;
use diesel; use diesel;
@ -10,7 +11,6 @@ use std::path::Path;
use crate::db; use crate::db;
use crate::db::ConnectionSource; use crate::db::ConnectionSource;
use crate::db::{playlist_songs, playlists, users}; use crate::db::{playlist_songs, playlists, users};
use crate::errors::*;
use crate::index::{self, Song}; use crate::index::{self, Song};
use crate::vfs::VFSSource; use crate::vfs::VFSSource;

View file

@ -1,10 +1,10 @@
use anyhow::*;
use rocket; use rocket;
use rocket_contrib::serve::StaticFiles; use rocket_contrib::serve::StaticFiles;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use crate::db::DB; use crate::db::DB;
use crate::errors;
use crate::index::CommandSender; use crate::index::CommandSender;
pub fn get_server( pub fn get_server(
@ -17,7 +17,7 @@ pub fn get_server(
swagger_dir_path: &PathBuf, swagger_dir_path: &PathBuf,
db: Arc<DB>, db: Arc<DB>,
command_sender: Arc<CommandSender>, command_sender: Arc<CommandSender>,
) -> Result<rocket::Rocket, errors::Error> { ) -> Result<rocket::Rocket> {
let mut config = rocket::Config::build(rocket::config::Environment::Production) let mut config = rocket::Config::build(rocket::config::Environment::Production)
.port(port) .port(port)
.keep_alive(0) .keep_alive(0)

View file

@ -1,3 +1,4 @@
use anyhow::*;
use image; use image;
use image::DynamicImage; use image::DynamicImage;
use image::FilterType; use image::FilterType;
@ -11,7 +12,6 @@ use std::fs::{DirBuilder, File};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::path::*; use std::path::*;
use crate::errors::*;
use crate::utils; use crate::utils;
const THUMBNAILS_PATH: &str = "thumbnails"; const THUMBNAILS_PATH: &str = "thumbnails";

View file

@ -1,11 +1,10 @@
use anyhow::*;
use core::ops::Deref; use core::ops::Deref;
use diesel; use diesel;
use diesel::prelude::*; use diesel::prelude::*;
use error_chain::bail;
use crate::db::users; use crate::db::users;
use crate::db::ConnectionSource; use crate::db::ConnectionSource;
use crate::errors::*;
#[derive(Debug, Insertable, Queryable)] #[derive(Debug, Insertable, Queryable)]
#[table_name = "users"] #[table_name = "users"]
@ -109,7 +108,7 @@ where
.get_result(connection.deref())?; .get_result(connection.deref())?;
match token { match token {
Some(t) => Ok(t), Some(t) => Ok(t),
_ => bail!(ErrorKind::MissingLastFMCredentials), _ => Err(anyhow!("Missing LastFM credentials")),
} }
} }

View file

@ -1,10 +1,8 @@
use anyhow::*;
use app_dirs::{app_root, AppDataType, AppInfo}; use app_dirs::{app_root, AppDataType, AppInfo};
use error_chain::bail;
use std::fs; use std::fs;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use crate::errors::*;
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]
const APP_INFO: AppInfo = AppInfo { const APP_INFO: AppInfo = AppInfo {
name: "Polaris", name: "Polaris",
@ -19,7 +17,7 @@ const APP_INFO: AppInfo = AppInfo {
pub fn get_data_root() -> Result<PathBuf> { pub fn get_data_root() -> Result<PathBuf> {
if let Ok(root) = app_root(AppDataType::UserData, &APP_INFO) { if let Ok(root) = app_root(AppDataType::UserData, &APP_INFO) {
fs::create_dir_all(&root).chain_err(|| format!("opening user data: {}", root.display()))?; fs::create_dir_all(&root)?;
return Ok(root); return Ok(root);
} }
bail!("Could not retrieve data directory root"); bail!("Could not retrieve data directory root");

View file

@ -1,6 +1,6 @@
use anyhow::*;
use core::ops::Deref; use core::ops::Deref;
use diesel::prelude::*; use diesel::prelude::*;
use error_chain::bail;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::path::Path; use std::path::Path;
@ -8,7 +8,6 @@ use std::path::PathBuf;
use crate::db::mount_points; use crate::db::mount_points;
use crate::db::{ConnectionSource, DB}; use crate::db::{ConnectionSource, DB};
use crate::errors::*;
pub trait VFSSource { pub trait VFSSource {
fn get_vfs(&self) -> Result<VFS>; fn get_vfs(&self) -> Result<VFS>;