Use 2018-style macro imports
This commit is contained in:
parent
57ded63cb8
commit
6d963c059f
17 changed files with 79 additions and 48 deletions
|
@ -28,7 +28,7 @@ ring = "0.13.5"
|
||||||
reqwest = "0.9.2"
|
reqwest = "0.9.2"
|
||||||
rocket = "0.4.2"
|
rocket = "0.4.2"
|
||||||
rust-crypto = "0.2.36"
|
rust-crypto = "0.2.36"
|
||||||
serde = "1.0"
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
simplelog = "0.6"
|
simplelog = "0.6"
|
||||||
|
|
25
src/api.rs
25
src/api.rs
|
@ -1,8 +1,10 @@
|
||||||
|
use error_chain::bail;
|
||||||
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;
|
||||||
use rocket::{Outcome, State};
|
use rocket::{delete, get, post, put, routes, Outcome, State};
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -266,7 +268,10 @@ fn browse(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/flatten")]
|
#[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>>, 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))
|
||||||
}
|
}
|
||||||
|
@ -282,13 +287,19 @@ fn flatten(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/random")]
|
#[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>>, 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(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>>, 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))
|
||||||
}
|
}
|
||||||
|
@ -394,7 +405,11 @@ fn lastfm_now_playing(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/lastfm/scrobble/<path>")]
|
#[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<(), 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(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
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 regex::Regex;
|
use regex::Regex;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path;
|
use std::path;
|
||||||
|
|
|
@ -2,6 +2,8 @@ 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 std::fs;
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::{Arc, Mutex, MutexGuard};
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
|
use log::{error, info};
|
||||||
use reqwest;
|
use reqwest;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time;
|
use std::time;
|
||||||
|
|
|
@ -2,6 +2,7 @@ use ape;
|
||||||
use core;
|
use core;
|
||||||
use diesel;
|
use diesel;
|
||||||
use diesel_migrations;
|
use diesel_migrations;
|
||||||
|
use error_chain::error_chain;
|
||||||
use getopts;
|
use getopts;
|
||||||
use id3;
|
use id3;
|
||||||
use image;
|
use image;
|
||||||
|
|
|
@ -4,7 +4,10 @@ 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;
|
||||||
|
use log::{error, info};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use rustfm_scrobble::{Scrobble, Scrobbler};
|
use rustfm_scrobble::{Scrobble, Scrobbler};
|
||||||
|
use serde::Deserialize;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use crate::db::ConnectionSource;
|
use crate::db::ConnectionSource;
|
||||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -6,14 +6,6 @@
|
||||||
extern crate diesel;
|
extern crate diesel;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate diesel_migrations;
|
extern crate diesel_migrations;
|
||||||
#[macro_use]
|
|
||||||
extern crate error_chain;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate rocket;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate serde_derive;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate log;
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
@ -24,7 +16,9 @@ use unix_daemonize::{daemonize_redirect, ChdirMode};
|
||||||
|
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
|
use error_chain::bail;
|
||||||
use getopts::Options;
|
use getopts::Options;
|
||||||
|
use log::info;
|
||||||
use simplelog::{Level, LevelFilter, SimpleLogger, TermLogger, TerminalMode};
|
use simplelog::{Level, LevelFilter, SimpleLogger, TermLogger, TerminalMode};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
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;
|
||||||
|
|
36
src/serve.rs
36
src/serve.rs
|
@ -1,8 +1,9 @@
|
||||||
|
use log::warn;
|
||||||
use rocket;
|
use rocket;
|
||||||
use rocket::http::hyper::header::*;
|
use rocket::http::hyper::header::*;
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
use rocket::Response;
|
|
||||||
use rocket::response::{self, Responder};
|
use rocket::response::{self, Responder};
|
||||||
|
use rocket::Response;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
@ -44,7 +45,11 @@ impl<'r, R: Responder<'r>> RangeResponder<R> {
|
||||||
RangeResponder { original }
|
RangeResponder { original }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ignore_range(self, request: &rocket::request::Request<'_>, file_length: Option<u64>) -> response::Result<'r> {
|
fn ignore_range(
|
||||||
|
self,
|
||||||
|
request: &rocket::request::Request<'_>,
|
||||||
|
file_length: Option<u64>,
|
||||||
|
) -> response::Result<'r> {
|
||||||
let mut response = self.original.respond_to(request)?;
|
let mut response = self.original.respond_to(request)?;
|
||||||
if let Some(content_length) = file_length {
|
if let Some(content_length) = file_length {
|
||||||
response.set_header(ContentLength(content_length));
|
response.set_header(ContentLength(content_length));
|
||||||
|
@ -55,8 +60,8 @@ impl<'r, R: Responder<'r>> RangeResponder<R> {
|
||||||
|
|
||||||
fn reject_range(self, file_length: Option<u64>) -> response::Result<'r> {
|
fn reject_range(self, file_length: Option<u64>) -> response::Result<'r> {
|
||||||
let mut response = Response::build()
|
let mut response = Response::build()
|
||||||
.status(Status::RangeNotSatisfiable)
|
.status(Status::RangeNotSatisfiable)
|
||||||
.finalize();
|
.finalize();
|
||||||
if file_length.is_some() {
|
if file_length.is_some() {
|
||||||
let content_range = ContentRange(ContentRangeSpec::Bytes {
|
let content_range = ContentRange(ContentRangeSpec::Bytes {
|
||||||
range: None,
|
range: None,
|
||||||
|
@ -100,7 +105,6 @@ fn truncate_range(range: &PartialFileRange, file_length: &Option<u64>) -> Option
|
||||||
|
|
||||||
impl<'r> Responder<'r> for RangeResponder<File> {
|
impl<'r> Responder<'r> for RangeResponder<File> {
|
||||||
fn respond_to(mut self, request: &rocket::request::Request<'_>) -> response::Result<'r> {
|
fn respond_to(mut self, request: &rocket::request::Request<'_>) -> response::Result<'r> {
|
||||||
|
|
||||||
let metadata: Option<_> = self.original.metadata().ok();
|
let metadata: Option<_> = self.original.metadata().ok();
|
||||||
let file_length: Option<u64> = metadata.map(|m| m.len());
|
let file_length: Option<u64> = metadata.map(|m| m.len());
|
||||||
|
|
||||||
|
@ -113,9 +117,12 @@ impl<'r> Responder<'r> for RangeResponder<File> {
|
||||||
let vec_range = match Range::from_str(range_header) {
|
let vec_range = match Range::from_str(range_header) {
|
||||||
Ok(Range::Bytes(v)) => v,
|
Ok(Range::Bytes(v)) => v,
|
||||||
_ => {
|
_ => {
|
||||||
warn!("Ignoring range header that could not be parse {:?}, file length is {:?}", range_header, file_length);
|
warn!(
|
||||||
|
"Ignoring range header that could not be parse {:?}, file length is {:?}",
|
||||||
|
range_header, file_length
|
||||||
|
);
|
||||||
return self.ignore_range(request, file_length);
|
return self.ignore_range(request, file_length);
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let partial_file_range = match vec_range.into_iter().next() {
|
let partial_file_range = match vec_range.into_iter().next() {
|
||||||
|
@ -138,15 +145,18 @@ impl<'r> Responder<'r> for RangeResponder<File> {
|
||||||
}
|
}
|
||||||
let partial_original = self.original.take(content_len);
|
let partial_original = self.original.take(content_len);
|
||||||
let response = Response::build()
|
let response = Response::build()
|
||||||
.status(Status::PartialContent)
|
.status(Status::PartialContent)
|
||||||
.header(ContentLength(content_len))
|
.header(ContentLength(content_len))
|
||||||
.header(content_range)
|
.header(content_range)
|
||||||
.streamed_body(partial_original)
|
.streamed_body(partial_original)
|
||||||
.finalize();
|
.finalize();
|
||||||
|
|
||||||
Ok(response)
|
Ok(response)
|
||||||
} else {
|
} else {
|
||||||
warn!("Rejecting unsatisfiable range header {:?}, file length is {:?}", &partial_file_range, &file_length);
|
warn!(
|
||||||
|
"Rejecting unsatisfiable range header {:?}, file length is {:?}",
|
||||||
|
&partial_file_range, &file_length
|
||||||
|
);
|
||||||
self.reject_range(file_length)
|
self.reject_range(file_length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
use rocket::http::uri::Origin;
|
use rocket::http::uri::Origin;
|
||||||
use rocket::response::NamedFile;
|
use rocket::response::NamedFile;
|
||||||
use rocket::response::Redirect;
|
use rocket::response::Redirect;
|
||||||
use rocket::State;
|
use rocket::{get, routes, State};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::server::StaticDirs;
|
use crate::server::StaticDirs;
|
||||||
|
|
||||||
pub fn get_routes() -> Vec<rocket::Route> {
|
pub fn get_routes() -> Vec<rocket::Route> {
|
||||||
routes![
|
routes![index, files,]
|
||||||
index,
|
|
||||||
files,
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/", rank = 9)]
|
#[get("/", rank = 9)]
|
||||||
|
@ -28,25 +25,28 @@ fn index(origin: &Origin<'_>) -> Redirect {
|
||||||
#[get("/<file..>", rank = 9)]
|
#[get("/<file..>", rank = 9)]
|
||||||
fn files(static_dirs: State<'_, Arc<StaticDirs>>, file: PathBuf) -> Option<NamedFile> {
|
fn files(static_dirs: State<'_, Arc<StaticDirs>>, file: PathBuf) -> Option<NamedFile> {
|
||||||
let path = static_dirs.swagger_dir_path.clone().join(file.clone());
|
let path = static_dirs.swagger_dir_path.clone().join(file.clone());
|
||||||
NamedFile::open(path).ok()
|
NamedFile::open(path).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_index_redirect() {
|
fn test_index_redirect() {
|
||||||
use rocket::http::Status;
|
|
||||||
use crate::test::get_test_environment;
|
use crate::test::get_test_environment;
|
||||||
|
use rocket::http::Status;
|
||||||
|
|
||||||
let env = get_test_environment("swagger_index_redirect.sqlite");
|
let env = get_test_environment("swagger_index_redirect.sqlite");
|
||||||
let client = &env.client;
|
let client = &env.client;
|
||||||
let response = client.get("/swagger").dispatch();
|
let response = client.get("/swagger").dispatch();
|
||||||
assert_eq!(response.status(), Status::PermanentRedirect);
|
assert_eq!(response.status(), Status::PermanentRedirect);
|
||||||
assert_eq!(response.headers().get_one("Location"), Some("/swagger/index.html"));
|
assert_eq!(
|
||||||
|
response.headers().get_one("Location"),
|
||||||
|
Some("/swagger/index.html")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_index() {
|
fn test_index() {
|
||||||
use rocket::http::Status;
|
|
||||||
use crate::test::get_test_environment;
|
use crate::test::get_test_environment;
|
||||||
|
use rocket::http::Status;
|
||||||
|
|
||||||
let env = get_test_environment("swagger_index.sqlite");
|
let env = get_test_environment("swagger_index.sqlite");
|
||||||
let client = &env.client;
|
let client = &env.client;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use log::info;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time;
|
use std::time;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
use diesel;
|
use diesel;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
|
use error_chain::bail;
|
||||||
use rand;
|
use rand;
|
||||||
use ring::{digest, pbkdf2};
|
use ring::{digest, pbkdf2};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
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};
|
||||||
|
|
||||||
|
@ -54,10 +55,7 @@ pub fn get_audio_format(path: &Path) -> Option<AudioFormat> {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_audio_format() {
|
fn test_get_audio_format() {
|
||||||
assert_eq!(
|
assert_eq!(get_audio_format(Path::new("animals/🐷/my🐖file.jpg")), None);
|
||||||
get_audio_format(Path::new("animals/🐷/my🐖file.jpg")),
|
|
||||||
None
|
|
||||||
);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_audio_format(Path::new("animals/🐷/my🐖file.flac")),
|
get_audio_format(Path::new("animals/🐷/my🐖file.flac")),
|
||||||
Some(AudioFormat::FLAC)
|
Some(AudioFormat::FLAC)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
|
use error_chain::bail;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
13
src/web.rs
13
src/web.rs
|
@ -1,5 +1,5 @@
|
||||||
use rocket::response::NamedFile;
|
use rocket::response::NamedFile;
|
||||||
use rocket::State;
|
use rocket::{get, routes, State};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -7,29 +7,26 @@ use std::sync::Arc;
|
||||||
use crate::server::StaticDirs;
|
use crate::server::StaticDirs;
|
||||||
|
|
||||||
pub fn get_routes() -> Vec<rocket::Route> {
|
pub fn get_routes() -> Vec<rocket::Route> {
|
||||||
routes![
|
routes![index, files,]
|
||||||
index,
|
|
||||||
files,
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/", rank = 10)]
|
#[get("/", rank = 10)]
|
||||||
fn index(static_dirs: State<'_, Arc<StaticDirs>>) -> io::Result<NamedFile> {
|
fn index(static_dirs: State<'_, Arc<StaticDirs>>) -> io::Result<NamedFile> {
|
||||||
let mut path = static_dirs.web_dir_path.clone();
|
let mut path = static_dirs.web_dir_path.clone();
|
||||||
path.push("index.html");
|
path.push("index.html");
|
||||||
NamedFile::open(path)
|
NamedFile::open(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/<file..>", rank = 10)]
|
#[get("/<file..>", rank = 10)]
|
||||||
fn files(static_dirs: State<'_, Arc<StaticDirs>>, file: PathBuf) -> Option<NamedFile> {
|
fn files(static_dirs: State<'_, Arc<StaticDirs>>, file: PathBuf) -> Option<NamedFile> {
|
||||||
let path = static_dirs.web_dir_path.clone().join(file.clone());
|
let path = static_dirs.web_dir_path.clone().join(file.clone());
|
||||||
NamedFile::open(path).ok()
|
NamedFile::open(path).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_index() {
|
fn test_index() {
|
||||||
use rocket::http::Status;
|
|
||||||
use crate::test::get_test_environment;
|
use crate::test::get_test_environment;
|
||||||
|
use rocket::http::Status;
|
||||||
|
|
||||||
let env = get_test_environment("web_index.sqlite");
|
let env = get_test_environment("web_index.sqlite");
|
||||||
let client = &env.client;
|
let client = &env.client;
|
||||||
|
|
Loading…
Add table
Reference in a new issue