Simplified error boilerplate
This commit is contained in:
parent
0b0bfac8fb
commit
f41f45f600
17 changed files with 139 additions and 234 deletions
30
Cargo.lock
generated
30
Cargo.lock
generated
|
@ -13,6 +13,11 @@ dependencies = [
|
|||
"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]]
|
||||
name = "ape"
|
||||
version = "0.2.0"
|
||||
|
@ -553,7 +558,6 @@ name = "error-chain"
|
|||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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)",
|
||||
]
|
||||
|
||||
|
@ -1457,12 +1461,12 @@ dependencies = [
|
|||
name = "polaris"
|
||||
version = "0.11.0"
|
||||
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)",
|
||||
"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)",
|
||||
"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)",
|
||||
"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)",
|
||||
"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)",
|
||||
|
@ -1486,6 +1490,7 @@ dependencies = [
|
|||
"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)",
|
||||
"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)",
|
||||
"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)",
|
||||
|
@ -2195,6 +2200,24 @@ dependencies = [
|
|||
"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]]
|
||||
name = "thread-id"
|
||||
version = "3.3.0"
|
||||
|
@ -2620,6 +2643,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
[metadata]
|
||||
"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 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 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"
|
||||
|
@ -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 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 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_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"
|
||||
|
|
|
@ -9,12 +9,12 @@ ui = []
|
|||
profile-index = ["flame", "flamer"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
ape = "0.2.0"
|
||||
app_dirs = "1.1.1"
|
||||
base64 = "0.11.0"
|
||||
diesel = { version = "1.4", features = ["sqlite"] }
|
||||
diesel_migrations = { version = "1.4", features = ["sqlite"] }
|
||||
error-chain = "0.12.0"
|
||||
flame = { version = "0.2.2", optional = true }
|
||||
flamer = { version = "0.4", optional = true }
|
||||
getopts = "0.2.15"
|
||||
|
@ -36,6 +36,7 @@ serde = { version = "1.0", features = ["derive"] }
|
|||
serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
||||
simplelog = "0.7"
|
||||
thiserror = "1.0"
|
||||
toml = "0.5"
|
||||
|
||||
[dependencies.rocket_contrib]
|
||||
|
|
122
src/api.rs
122
src/api.rs
|
@ -1,4 +1,4 @@
|
|||
use error_chain::bail;
|
||||
use anyhow::*;
|
||||
use rocket::http::{Cookie, Cookies, RawStr, Status};
|
||||
use rocket::request::{self, FromParam, FromRequest, Request};
|
||||
use rocket::response::content::Html;
|
||||
|
@ -11,10 +11,10 @@ use std::path::PathBuf;
|
|||
use std::str;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::config::{self, Config, Preferences};
|
||||
use crate::db::DB;
|
||||
use crate::errors;
|
||||
use crate::index;
|
||||
use crate::lastfm;
|
||||
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 {
|
||||
username: String,
|
||||
}
|
||||
|
@ -168,7 +192,7 @@ pub struct InitialSetup {
|
|||
}
|
||||
|
||||
#[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 {
|
||||
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")]
|
||||
fn get_settings(
|
||||
db: State<'_, Arc<DB>>,
|
||||
_admin_rights: AdminRights,
|
||||
) -> Result<Json<Config>, errors::Error> {
|
||||
fn get_settings(db: State<'_, Arc<DB>>, _admin_rights: AdminRights) -> Result<Json<Config>> {
|
||||
let config = config::read::<DB>(&db)?;
|
||||
Ok(Json(config))
|
||||
}
|
||||
|
@ -189,13 +210,13 @@ fn put_settings(
|
|||
db: State<'_, Arc<DB>>,
|
||||
_admin_rights: AdminRights,
|
||||
config: Json<Config>,
|
||||
) -> Result<(), errors::Error> {
|
||||
) -> Result<()> {
|
||||
config::amend::<DB>(&db, &config)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[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)?;
|
||||
Ok(Json(preferences))
|
||||
}
|
||||
|
@ -205,7 +226,7 @@ fn put_preferences(
|
|||
db: State<'_, Arc<DB>>,
|
||||
auth: Auth,
|
||||
preferences: Json<Preferences>,
|
||||
) -> Result<(), errors::Error> {
|
||||
) -> Result<()> {
|
||||
config::write_preferences::<DB>(&db, &auth.username, &preferences)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -214,7 +235,7 @@ fn put_preferences(
|
|||
fn trigger_index(
|
||||
command_sender: State<'_, Arc<index::CommandSender>>,
|
||||
_admin_rights: AdminRights,
|
||||
) -> Result<(), errors::Error> {
|
||||
) -> Result<()> {
|
||||
command_sender.trigger_reindex()?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -235,9 +256,9 @@ fn auth(
|
|||
db: State<'_, Arc<DB>>,
|
||||
credentials: Json<AuthCredentials>,
|
||||
mut cookies: Cookies<'_>,
|
||||
) -> Result<Json<AuthOutput>, errors::Error> {
|
||||
) -> std::result::Result<Json<AuthOutput>, APIError> {
|
||||
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));
|
||||
|
@ -249,10 +270,7 @@ fn auth(
|
|||
}
|
||||
|
||||
#[get("/browse")]
|
||||
fn browse_root(
|
||||
db: State<'_, Arc<DB>>,
|
||||
_auth: Auth,
|
||||
) -> Result<Json<Vec<index::CollectionFile>>, errors::Error> {
|
||||
fn browse_root(db: State<'_, Arc<DB>>, _auth: Auth) -> Result<Json<Vec<index::CollectionFile>>> {
|
||||
let result = index::browse(db.deref().deref(), &PathBuf::new())?;
|
||||
Ok(Json(result))
|
||||
}
|
||||
|
@ -262,16 +280,13 @@ fn browse(
|
|||
db: State<'_, Arc<DB>>,
|
||||
_auth: Auth,
|
||||
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)?;
|
||||
Ok(Json(result))
|
||||
}
|
||||
|
||||
#[get("/flatten")]
|
||||
fn flatten_root(
|
||||
db: State<'_, Arc<DB>>,
|
||||
_auth: Auth,
|
||||
) -> Result<Json<Vec<index::Song>>, errors::Error> {
|
||||
fn flatten_root(db: State<'_, Arc<DB>>, _auth: Auth) -> Result<Json<Vec<index::Song>>> {
|
||||
let result = index::flatten(db.deref().deref(), &PathBuf::new())?;
|
||||
Ok(Json(result))
|
||||
}
|
||||
|
@ -281,34 +296,25 @@ fn flatten(
|
|||
db: State<'_, Arc<DB>>,
|
||||
_auth: Auth,
|
||||
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)?;
|
||||
Ok(Json(result))
|
||||
}
|
||||
|
||||
#[get("/random")]
|
||||
fn random(
|
||||
db: State<'_, Arc<DB>>,
|
||||
_auth: Auth,
|
||||
) -> Result<Json<Vec<index::Directory>>, errors::Error> {
|
||||
fn random(db: State<'_, Arc<DB>>, _auth: Auth) -> Result<Json<Vec<index::Directory>>> {
|
||||
let result = index::get_random_albums(db.deref().deref(), 20)?;
|
||||
Ok(Json(result))
|
||||
}
|
||||
|
||||
#[get("/recent")]
|
||||
fn recent(
|
||||
db: State<'_, Arc<DB>>,
|
||||
_auth: Auth,
|
||||
) -> Result<Json<Vec<index::Directory>>, errors::Error> {
|
||||
fn recent(db: State<'_, Arc<DB>>, _auth: Auth) -> Result<Json<Vec<index::Directory>>> {
|
||||
let result = index::get_recent_albums(db.deref().deref(), 20)?;
|
||||
Ok(Json(result))
|
||||
}
|
||||
|
||||
#[get("/search")]
|
||||
fn search_root(
|
||||
db: State<'_, Arc<DB>>,
|
||||
_auth: Auth,
|
||||
) -> Result<Json<Vec<index::CollectionFile>>, errors::Error> {
|
||||
fn search_root(db: State<'_, Arc<DB>>, _auth: Auth) -> Result<Json<Vec<index::CollectionFile>>> {
|
||||
let result = index::search(db.deref().deref(), "")?;
|
||||
Ok(Json(result))
|
||||
}
|
||||
|
@ -318,7 +324,7 @@ fn search(
|
|||
db: State<'_, Arc<DB>>,
|
||||
_auth: Auth,
|
||||
query: String,
|
||||
) -> Result<Json<Vec<index::CollectionFile>>, errors::Error> {
|
||||
) -> Result<Json<Vec<index::CollectionFile>>> {
|
||||
let result = index::search(db.deref().deref(), &query)?;
|
||||
Ok(Json(result))
|
||||
}
|
||||
|
@ -328,7 +334,7 @@ fn serve(
|
|||
db: State<'_, Arc<DB>>,
|
||||
_auth: Auth,
|
||||
path: VFSPathBuf,
|
||||
) -> Result<serve::RangeResponder<File>, errors::Error> {
|
||||
) -> Result<serve::RangeResponder<File>> {
|
||||
let db: &DB = db.deref().deref();
|
||||
let vfs = db.get_vfs()?;
|
||||
let real_path = vfs.virtual_to_real(&path.into() as &PathBuf)?;
|
||||
|
@ -349,10 +355,7 @@ pub struct ListPlaylistsEntry {
|
|||
}
|
||||
|
||||
#[get("/playlists")]
|
||||
fn list_playlists(
|
||||
db: State<'_, Arc<DB>>,
|
||||
auth: Auth,
|
||||
) -> Result<Json<Vec<ListPlaylistsEntry>>, errors::Error> {
|
||||
fn list_playlists(db: State<'_, Arc<DB>>, auth: Auth) -> Result<Json<Vec<ListPlaylistsEntry>>> {
|
||||
let playlist_names = playlist::list_playlists(&auth.username, db.deref().deref())?;
|
||||
let playlists: Vec<ListPlaylistsEntry> = playlist_names
|
||||
.into_iter()
|
||||
|
@ -373,7 +376,7 @@ fn save_playlist(
|
|||
auth: Auth,
|
||||
name: String,
|
||||
playlist: Json<SavePlaylistInput>,
|
||||
) -> Result<(), errors::Error> {
|
||||
) -> Result<()> {
|
||||
playlist::save_playlist(&name, &auth.username, &playlist.tracks, db.deref().deref())?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -383,33 +386,25 @@ fn read_playlist(
|
|||
db: State<'_, Arc<DB>>,
|
||||
auth: Auth,
|
||||
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())?;
|
||||
Ok(Json(songs))
|
||||
}
|
||||
|
||||
#[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())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[put("/lastfm/now_playing/<path>")]
|
||||
fn lastfm_now_playing(
|
||||
db: State<'_, Arc<DB>>,
|
||||
auth: Auth,
|
||||
path: VFSPathBuf,
|
||||
) -> Result<(), errors::Error> {
|
||||
fn lastfm_now_playing(db: State<'_, Arc<DB>>, auth: Auth, path: VFSPathBuf) -> Result<()> {
|
||||
lastfm::now_playing(db.deref().deref(), &auth.username, &path.into() as &PathBuf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[post("/lastfm/scrobble/<path>")]
|
||||
fn lastfm_scrobble(
|
||||
db: State<'_, Arc<DB>>,
|
||||
auth: Auth,
|
||||
path: VFSPathBuf,
|
||||
) -> Result<(), errors::Error> {
|
||||
fn lastfm_scrobble(db: State<'_, Arc<DB>>, auth: Auth, path: VFSPathBuf) -> Result<()> {
|
||||
lastfm::scrobble(db.deref().deref(), &auth.username, &path.into() as &PathBuf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -420,32 +415,23 @@ fn lastfm_link(
|
|||
auth: Auth,
|
||||
token: String,
|
||||
content: String,
|
||||
) -> Result<Html<String>, errors::Error> {
|
||||
) -> Result<Html<String>> {
|
||||
lastfm::link(db.deref().deref(), &auth.username, &token)?;
|
||||
|
||||
// Percent decode
|
||||
let base64_content = match RawStr::from_str(&content).percent_decode() {
|
||||
Ok(s) => s,
|
||||
Err(_) => bail!(errors::ErrorKind::EncodingError),
|
||||
};
|
||||
let base64_content = RawStr::from_str(&content).percent_decode()?;
|
||||
|
||||
// Base64 decode
|
||||
let popup_content = match base64::decode(base64_content.as_bytes()) {
|
||||
Ok(c) => c,
|
||||
Err(_) => bail!(errors::ErrorKind::EncodingError),
|
||||
};
|
||||
let popup_content = base64::decode(base64_content.as_bytes())?;
|
||||
|
||||
// UTF-8 decode
|
||||
let popup_content_string = match str::from_utf8(&popup_content) {
|
||||
Ok(s) => s,
|
||||
Err(_) => bail!(errors::ErrorKind::EncodingError),
|
||||
};
|
||||
let popup_content_string = str::from_utf8(&popup_content)?;
|
||||
|
||||
Ok(Html(popup_content_string.to_string()))
|
||||
}
|
||||
|
||||
#[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)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use anyhow::*;
|
||||
use core::ops::Deref;
|
||||
use diesel;
|
||||
use diesel::prelude::*;
|
||||
use error_chain::bail;
|
||||
use log::info;
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -13,7 +13,6 @@ use toml;
|
|||
use crate::db::ConnectionSource;
|
||||
use crate::db::{ddns_config, misc_settings, mount_points, users};
|
||||
use crate::ddns::DDNSConfig;
|
||||
use crate::errors::*;
|
||||
use crate::user::*;
|
||||
use crate::vfs::MountPoint;
|
||||
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
use anyhow::*;
|
||||
use core::ops::Deref;
|
||||
use diesel::prelude::*;
|
||||
use diesel::sqlite::SqliteConnection;
|
||||
use diesel_migrations;
|
||||
use error_chain::bail;
|
||||
use log::info;
|
||||
use std::path::Path;
|
||||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
|
||||
use crate::errors::*;
|
||||
|
||||
mod schema;
|
||||
|
||||
pub use self::schema::*;
|
||||
|
|
40
src/ddns.rs
40
src/ddns.rs
|
@ -1,15 +1,14 @@
|
|||
use anyhow::*;
|
||||
use core::ops::Deref;
|
||||
use diesel::prelude::*;
|
||||
use log::{error, info};
|
||||
use reqwest;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
use std::thread;
|
||||
use std::time;
|
||||
|
||||
use crate::db::ddns_config;
|
||||
use crate::db::{ConnectionSource, DB};
|
||||
use crate::errors;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Insertable, PartialEq, Queryable, Serialize)]
|
||||
#[table_name = "ddns_config"]
|
||||
|
@ -20,11 +19,11 @@ pub struct DDNSConfig {
|
|||
}
|
||||
|
||||
pub trait DDNSConfigSource {
|
||||
fn get_ddns_config(&self) -> errors::Result<DDNSConfig>;
|
||||
fn get_ddns_config(&self) -> Result<DDNSConfig>;
|
||||
}
|
||||
|
||||
impl DDNSConfigSource for DB {
|
||||
fn get_ddns_config(&self) -> errors::Result<DDNSConfig> {
|
||||
fn get_ddns_config(&self) -> Result<DDNSConfig> {
|
||||
use self::ddns_config::dsl::*;
|
||||
let connection = self.get_connection();
|
||||
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/";
|
||||
|
||||
fn update_my_ip<T>(config_source: &T) -> Result<(), DDNSError>
|
||||
fn update_my_ip<T>(config_source: &T) -> Result<()>
|
||||
where
|
||||
T: DDNSConfigSource,
|
||||
{
|
||||
|
@ -78,7 +51,10 @@ where
|
|||
.basic_auth(config.username, Some(config.password))
|
||||
.send()?;
|
||||
if !res.status().is_success() {
|
||||
return Err(DDNSError::Update(res.status()));
|
||||
bail!(
|
||||
"DDNS update query failed with status code: {}",
|
||||
res.status()
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
51
src/index.rs
51
src/index.rs
|
@ -1,10 +1,10 @@
|
|||
use anyhow::*;
|
||||
use core::ops::Deref;
|
||||
use diesel;
|
||||
use diesel::dsl::sql;
|
||||
use diesel::prelude::*;
|
||||
use diesel::sql_types;
|
||||
use diesel::sqlite::SqliteConnection;
|
||||
use error_chain::bail;
|
||||
#[cfg(feature = "profile-index")]
|
||||
use flame;
|
||||
use log::{error, info};
|
||||
|
@ -24,7 +24,6 @@ use crate::config::MiscSettings;
|
|||
use crate::db;
|
||||
use crate::db::{directories, misc_settings, songs};
|
||||
use crate::db::{ConnectionSource, DB};
|
||||
use crate::errors;
|
||||
use crate::metadata;
|
||||
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();
|
||||
match sender.send(Command::REINDEX) {
|
||||
Ok(_) => Ok(()),
|
||||
|
@ -72,7 +71,7 @@ impl CommandSender {
|
|||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn exit(&self) -> Result<(), errors::Error> {
|
||||
pub fn exit(&self) -> Result<()> {
|
||||
let sender = self.sender.lock().unwrap();
|
||||
match sender.send(Command::EXIT) {
|
||||
Ok(_) => Ok(()),
|
||||
|
@ -175,7 +174,7 @@ impl<'conn> IndexBuilder<'conn> {
|
|||
fn new(
|
||||
connection: &Mutex<SqliteConnection>,
|
||||
album_art_pattern: Regex,
|
||||
) -> Result<IndexBuilder<'_>, errors::Error> {
|
||||
) -> Result<IndexBuilder<'_>> {
|
||||
let mut new_songs = Vec::new();
|
||||
let mut new_directories = Vec::new();
|
||||
new_songs.reserve_exact(INDEX_BUILDING_INSERT_BUFFER_SIZE);
|
||||
|
@ -189,10 +188,10 @@ impl<'conn> IndexBuilder<'conn> {
|
|||
}
|
||||
|
||||
#[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 = connection.deref();
|
||||
connection.transaction::<_, errors::Error, _>(|| {
|
||||
connection.transaction::<_, anyhow::Error, _>(|| {
|
||||
diesel::insert_into(songs::table)
|
||||
.values(&self.new_songs)
|
||||
.execute(connection)?;
|
||||
|
@ -203,10 +202,10 @@ impl<'conn> IndexBuilder<'conn> {
|
|||
}
|
||||
|
||||
#[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 = connection.deref();
|
||||
connection.transaction::<_, errors::Error, _>(|| {
|
||||
connection.transaction::<_, anyhow::Error, _>(|| {
|
||||
diesel::insert_into(directories::table)
|
||||
.values(&self.new_directories)
|
||||
.execute(connection)?;
|
||||
|
@ -217,7 +216,7 @@ impl<'conn> IndexBuilder<'conn> {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
self.flush_songs()?;
|
||||
}
|
||||
|
@ -226,7 +225,7 @@ impl<'conn> IndexBuilder<'conn> {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
self.flush_directories()?;
|
||||
}
|
||||
|
@ -234,7 +233,7 @@ impl<'conn> IndexBuilder<'conn> {
|
|||
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)? {
|
||||
let file = file?;
|
||||
if let Some(name_string) = file.file_name().to_str() {
|
||||
|
@ -247,17 +246,13 @@ impl<'conn> IndexBuilder<'conn> {
|
|||
}
|
||||
|
||||
#[cfg_attr(feature = "profile-index", flame)]
|
||||
fn populate_directory(
|
||||
&mut self,
|
||||
parent: Option<&Path>,
|
||||
path: &Path,
|
||||
) -> Result<(), errors::Error> {
|
||||
fn populate_directory(&mut self, parent: Option<&Path>, path: &Path) -> Result<()> {
|
||||
// Find artwork
|
||||
let artwork = self.get_artwork(path).unwrap_or(None);
|
||||
|
||||
// Extract path and parent path
|
||||
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
|
||||
let metadata = fs::metadata(path_string)?;
|
||||
|
@ -369,7 +364,7 @@ impl<'conn> IndexBuilder<'conn> {
|
|||
}
|
||||
|
||||
#[cfg_attr(feature = "profile-index", flame)]
|
||||
fn clean<T>(db: &T) -> Result<(), errors::Error>
|
||||
fn clean<T>(db: &T) -> Result<()>
|
||||
where
|
||||
T: ConnectionSource + VFSSource,
|
||||
{
|
||||
|
@ -429,7 +424,7 @@ where
|
|||
}
|
||||
|
||||
#[cfg_attr(feature = "profile-index", flame)]
|
||||
fn populate<T>(db: &T) -> Result<(), errors::Error>
|
||||
fn populate<T>(db: &T) -> Result<()>
|
||||
where
|
||||
T: ConnectionSource + VFSSource,
|
||||
{
|
||||
|
@ -453,7 +448,7 @@ where
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update<T>(db: &T) -> Result<(), errors::Error>
|
||||
pub fn update<T>(db: &T) -> Result<()>
|
||||
where
|
||||
T: ConnectionSource + VFSSource,
|
||||
{
|
||||
|
@ -512,7 +507,7 @@ where
|
|||
let sleep_duration;
|
||||
{
|
||||
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())
|
||||
.map_err(|e| e.into());
|
||||
if let Err(ref e) = settings {
|
||||
|
@ -556,7 +551,7 @@ fn virtualize_directory(vfs: &VFS, mut directory: Directory) -> Option<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
|
||||
T: ConnectionSource + VFSSource,
|
||||
P: AsRef<Path>,
|
||||
|
@ -601,7 +596,7 @@ where
|
|||
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
|
||||
T: ConnectionSource + VFSSource,
|
||||
P: AsRef<Path>,
|
||||
|
@ -627,7 +622,7 @@ where
|
|||
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
|
||||
T: ConnectionSource + VFSSource,
|
||||
{
|
||||
|
@ -645,7 +640,7 @@ where
|
|||
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
|
||||
T: ConnectionSource + VFSSource,
|
||||
{
|
||||
|
@ -663,7 +658,7 @@ where
|
|||
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
|
||||
T: ConnectionSource + VFSSource,
|
||||
{
|
||||
|
@ -711,7 +706,7 @@ where
|
|||
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
|
||||
T: ConnectionSource + VFSSource,
|
||||
{
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use anyhow::*;
|
||||
use rustfm_scrobble::{Scrobble, Scrobbler};
|
||||
use serde::Deserialize;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::db::ConnectionSource;
|
||||
use crate::errors;
|
||||
use crate::index;
|
||||
use crate::user;
|
||||
use crate::vfs::VFSSource;
|
||||
|
@ -42,7 +42,7 @@ struct AuthResponse {
|
|||
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
|
||||
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
|
||||
T: ConnectionSource + VFSSource,
|
||||
{
|
||||
|
@ -64,14 +64,14 @@ where
|
|||
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
|
||||
T: ConnectionSource + VFSSource,
|
||||
{
|
||||
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
|
||||
T: ConnectionSource + VFSSource,
|
||||
{
|
||||
|
@ -83,7 +83,7 @@ where
|
|||
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
|
||||
T: ConnectionSource + VFSSource,
|
||||
{
|
||||
|
|
22
src/main.rs
22
src/main.rs
|
@ -20,9 +20,8 @@ use std::io::prelude::*;
|
|||
#[cfg(unix)]
|
||||
use unix_daemonize::{daemonize_redirect, ChdirMode};
|
||||
|
||||
use crate::errors::*;
|
||||
use anyhow::*;
|
||||
use core::ops::Deref;
|
||||
use error_chain::bail;
|
||||
use getopts::Options;
|
||||
use log::info;
|
||||
use simplelog::{LevelFilter, SimpleLogger, TermLogger, TerminalMode};
|
||||
|
@ -35,7 +34,6 @@ mod api_tests;
|
|||
mod config;
|
||||
mod db;
|
||||
mod ddns;
|
||||
mod errors;
|
||||
mod index;
|
||||
mod lastfm;
|
||||
mod metadata;
|
||||
|
@ -58,20 +56,6 @@ fn log_config() -> simplelog::Config {
|
|||
.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)]
|
||||
fn daemonize(options: &getopts::Matches) -> Result<()> {
|
||||
if options.opt_present("f") {
|
||||
|
@ -128,7 +112,7 @@ fn notify_ready() {
|
|||
#[cfg(not(unix))]
|
||||
fn notify_ready() {}
|
||||
|
||||
fn run() -> Result<()> {
|
||||
fn main() -> Result<()> {
|
||||
// Parse CLI options
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
let mut options = Options::new();
|
||||
|
@ -241,7 +225,7 @@ fn run() -> Result<()> {
|
|||
.opt_str("p")
|
||||
.unwrap_or_else(|| "5050".to_owned())
|
||||
.parse()
|
||||
.or(Err("invalid port number"))?;
|
||||
.with_context(|| "Invalid port number")?;
|
||||
|
||||
let server = server::get_server(
|
||||
port,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::*;
|
||||
use ape;
|
||||
use error_chain::bail;
|
||||
use id3;
|
||||
use lewton::inside_ogg::OggStreamReader;
|
||||
use metaflac;
|
||||
|
@ -8,7 +8,6 @@ use regex::Regex;
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::errors::*;
|
||||
use crate::utils;
|
||||
use crate::utils::AudioFormat;
|
||||
|
||||
|
@ -151,7 +150,9 @@ fn read_vorbis(path: &Path) -> Result<SongTags> {
|
|||
#[cfg_attr(feature = "profile-index", flame)]
|
||||
fn read_flac(path: &Path) -> Result<SongTags> {
|
||||
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
|
||||
.get("DISCNUMBER")
|
||||
.and_then(|d| d[0].parse::<u32>().ok());
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use anyhow::*;
|
||||
use core::clone::Clone;
|
||||
use core::ops::Deref;
|
||||
use diesel;
|
||||
|
@ -10,7 +11,6 @@ use std::path::Path;
|
|||
use crate::db;
|
||||
use crate::db::ConnectionSource;
|
||||
use crate::db::{playlist_songs, playlists, users};
|
||||
use crate::errors::*;
|
||||
use crate::index::{self, Song};
|
||||
use crate::vfs::VFSSource;
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use anyhow::*;
|
||||
use rocket;
|
||||
use rocket_contrib::serve::StaticFiles;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::db::DB;
|
||||
use crate::errors;
|
||||
use crate::index::CommandSender;
|
||||
|
||||
pub fn get_server(
|
||||
|
@ -17,7 +17,7 @@ pub fn get_server(
|
|||
swagger_dir_path: &PathBuf,
|
||||
db: Arc<DB>,
|
||||
command_sender: Arc<CommandSender>,
|
||||
) -> Result<rocket::Rocket, errors::Error> {
|
||||
) -> Result<rocket::Rocket> {
|
||||
let mut config = rocket::Config::build(rocket::config::Environment::Production)
|
||||
.port(port)
|
||||
.keep_alive(0)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use anyhow::*;
|
||||
use image;
|
||||
use image::DynamicImage;
|
||||
use image::FilterType;
|
||||
|
@ -11,7 +12,6 @@ use std::fs::{DirBuilder, File};
|
|||
use std::hash::{Hash, Hasher};
|
||||
use std::path::*;
|
||||
|
||||
use crate::errors::*;
|
||||
use crate::utils;
|
||||
|
||||
const THUMBNAILS_PATH: &str = "thumbnails";
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use anyhow::*;
|
||||
use core::ops::Deref;
|
||||
use diesel;
|
||||
use diesel::prelude::*;
|
||||
use error_chain::bail;
|
||||
|
||||
use crate::db::users;
|
||||
use crate::db::ConnectionSource;
|
||||
use crate::errors::*;
|
||||
|
||||
#[derive(Debug, Insertable, Queryable)]
|
||||
#[table_name = "users"]
|
||||
|
@ -109,7 +108,7 @@ where
|
|||
.get_result(connection.deref())?;
|
||||
match token {
|
||||
Some(t) => Ok(t),
|
||||
_ => bail!(ErrorKind::MissingLastFMCredentials),
|
||||
_ => Err(anyhow!("Missing LastFM credentials")),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
use anyhow::*;
|
||||
use app_dirs::{app_root, AppDataType, AppInfo};
|
||||
use error_chain::bail;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::errors::*;
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
const APP_INFO: AppInfo = AppInfo {
|
||||
name: "Polaris",
|
||||
|
@ -19,7 +17,7 @@ const APP_INFO: AppInfo = AppInfo {
|
|||
|
||||
pub fn get_data_root() -> Result<PathBuf> {
|
||||
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);
|
||||
}
|
||||
bail!("Could not retrieve data directory root");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use anyhow::*;
|
||||
use core::ops::Deref;
|
||||
use diesel::prelude::*;
|
||||
use error_chain::bail;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
|
@ -8,7 +8,6 @@ use std::path::PathBuf;
|
|||
|
||||
use crate::db::mount_points;
|
||||
use crate::db::{ConnectionSource, DB};
|
||||
use crate::errors::*;
|
||||
|
||||
pub trait VFSSource {
|
||||
fn get_vfs(&self) -> Result<VFS>;
|
||||
|
|
Loading…
Add table
Reference in a new issue