mirror of
https://github.com/Dangoware/confetti-box.git
synced 2025-04-19 23:32:58 -05:00
Cleaned up clippy suggestions, ran cargo fmt
This commit is contained in:
parent
ac41059f0b
commit
d0761d9e69
3 changed files with 51 additions and 64 deletions
|
@ -1,11 +1,14 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::{hash_map::Values, HashMap, HashSet}, ffi::OsStr, fs::{self, File}, path::{Path, PathBuf}, sync::{Arc, RwLock}
|
collections::{hash_map::Values, HashMap, HashSet},
|
||||||
|
ffi::OsStr,
|
||||||
|
fs::{self, File},
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
use bincode::{config::Configuration, decode_from_std_read, encode_into_std_write, Decode, Encode};
|
use bincode::{config::Configuration, decode_from_std_read, encode_into_std_write, Decode, Encode};
|
||||||
use blake3::Hash;
|
use blake3::Hash;
|
||||||
use chrono::{DateTime, TimeDelta, Utc};
|
use chrono::{DateTime, TimeDelta, Utc};
|
||||||
use file_format::FileFormat;
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use rand::distributions::{Alphanumeric, DistString};
|
use rand::distributions::{Alphanumeric, DistString};
|
||||||
use rocket::{
|
use rocket::{
|
||||||
|
@ -13,8 +16,6 @@ use rocket::{
|
||||||
tokio::{select, sync::mpsc::Receiver, time},
|
tokio::{select, sync::mpsc::Receiver, time},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::settings::Settings;
|
|
||||||
|
|
||||||
const BINCODE_CFG: Configuration = bincode::config::standard();
|
const BINCODE_CFG: Configuration = bincode::config::standard();
|
||||||
|
|
||||||
#[derive(Debug, Clone, Decode, Encode)]
|
#[derive(Debug, Clone, Decode, Encode)]
|
||||||
|
@ -76,7 +77,8 @@ impl Database {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If the database does not contain the hash, create a new set for it
|
// If the database does not contain the hash, create a new set for it
|
||||||
self.hashes.insert(entry.hash, HashSet::from([entry.mmid.clone()]));
|
self.hashes
|
||||||
|
.insert(entry.hash, HashSet::from([entry.mmid.clone()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.entries.insert(entry.mmid.clone(), entry.clone());
|
self.entries.insert(entry.mmid.clone(), entry.clone());
|
||||||
|
@ -88,11 +90,11 @@ impl Database {
|
||||||
///
|
///
|
||||||
/// If the database did not contain this value, then `false` is returned.
|
/// If the database did not contain this value, then `false` is returned.
|
||||||
pub fn remove_mmid(&mut self, mmid: &Mmid) -> bool {
|
pub fn remove_mmid(&mut self, mmid: &Mmid) -> bool {
|
||||||
let hash = if let Some(h) = self.entries.get(mmid).and_then(|e| Some(e.hash)) {
|
let hash = if let Some(h) = self.entries.get(mmid).map(|e| e.hash) {
|
||||||
self.entries.remove(mmid);
|
self.entries.remove(mmid);
|
||||||
h
|
h
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(s) = self.hashes.get_mut(&hash) {
|
if let Some(s) = self.hashes.get_mut(&hash) {
|
||||||
|
@ -109,22 +111,18 @@ impl Database {
|
||||||
if let Some(s) = self.hashes.get(hash) {
|
if let Some(s) = self.hashes.get(hash) {
|
||||||
if s.is_empty() {
|
if s.is_empty() {
|
||||||
self.hashes.remove(hash);
|
self.hashes.remove(hash);
|
||||||
return Some(true)
|
Some(true)
|
||||||
} else {
|
} else {
|
||||||
return Some(false)
|
Some(false)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if a hash contained in the database contains no more [`Mmid`]s.
|
/// Checks if a hash contained in the database contains no more [`Mmid`]s.
|
||||||
pub fn is_hash_empty(&self, hash: &Hash) -> Option<bool> {
|
pub fn is_hash_empty(&self, hash: &Hash) -> Option<bool> {
|
||||||
if let Some(s) = self.hashes.get(hash) {
|
self.hashes.get(hash).map(|s| s.is_empty())
|
||||||
Some(s.is_empty())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an entry by its [`Mmid`]. Returns [`None`] if the value does not exist.
|
/// Get an entry by its [`Mmid`]. Returns [`None`] if the value does not exist.
|
||||||
|
@ -213,10 +211,7 @@ impl MochiFile {
|
||||||
|
|
||||||
/// Clean the database. Removes files which are past their expiry
|
/// Clean the database. Removes files which are past their expiry
|
||||||
/// [`chrono::DateTime`]. Also removes files which no longer exist on the disk.
|
/// [`chrono::DateTime`]. Also removes files which no longer exist on the disk.
|
||||||
fn clean_database(
|
fn clean_database(db: &Arc<RwLock<Database>>, file_path: &Path) {
|
||||||
db: &Arc<RwLock<Database>>,
|
|
||||||
file_path: &PathBuf,
|
|
||||||
) {
|
|
||||||
let mut database = db.write().unwrap();
|
let mut database = db.write().unwrap();
|
||||||
|
|
||||||
// Add expired entries to the removal list
|
// Add expired entries to the removal list
|
||||||
|
@ -224,7 +219,7 @@ fn clean_database(
|
||||||
.entries()
|
.entries()
|
||||||
.filter_map(|e| {
|
.filter_map(|e| {
|
||||||
if e.is_expired() {
|
if e.is_expired() {
|
||||||
Some((e.mmid().clone(), e.hash().clone()))
|
Some((e.mmid().clone(), *e.hash()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -234,7 +229,6 @@ fn clean_database(
|
||||||
let mut removed_files = 0;
|
let mut removed_files = 0;
|
||||||
let mut removed_entries = 0;
|
let mut removed_entries = 0;
|
||||||
for e in &files_to_remove {
|
for e in &files_to_remove {
|
||||||
|
|
||||||
if database.remove_mmid(&e.0) {
|
if database.remove_mmid(&e.0) {
|
||||||
removed_entries += 1;
|
removed_entries += 1;
|
||||||
}
|
}
|
||||||
|
@ -272,8 +266,7 @@ pub async fn clean_loop(
|
||||||
|
|
||||||
/// A unique identifier for an entry in the database, 8 characters long,
|
/// A unique identifier for an entry in the database, 8 characters long,
|
||||||
/// consists of ASCII alphanumeric characters (`a-z`, `A-Z`, and `0-9`).
|
/// consists of ASCII alphanumeric characters (`a-z`, `A-Z`, and `0-9`).
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Decode, Encode, Hash)]
|
#[derive(Debug, PartialEq, Eq, Clone, Decode, Encode, Hash, Deserialize, Serialize)]
|
||||||
#[derive(Deserialize, Serialize)]
|
|
||||||
pub struct Mmid(String);
|
pub struct Mmid(String);
|
||||||
|
|
||||||
impl Mmid {
|
impl Mmid {
|
||||||
|
@ -283,14 +276,6 @@ impl Mmid {
|
||||||
|
|
||||||
Self(string)
|
Self(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_str(&self) -> &str {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_string(&self) -> String {
|
|
||||||
self.0.to_owned()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<&str> for Mmid {
|
impl TryFrom<&str> for Mmid {
|
||||||
|
@ -298,11 +283,11 @@ impl TryFrom<&str> for Mmid {
|
||||||
|
|
||||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||||
if value.len() != 8 {
|
if value.len() != 8 {
|
||||||
return Err(())
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if value.chars().any(|c| !c.is_ascii_alphanumeric()) {
|
if value.chars().any(|c| !c.is_ascii_alphanumeric()) {
|
||||||
return Err(())
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self(value.to_owned()))
|
Ok(Self(value.to_owned()))
|
||||||
|
@ -327,11 +312,11 @@ impl TryFrom<&OsStr> for Mmid {
|
||||||
};
|
};
|
||||||
|
|
||||||
if string.len() != 8 {
|
if string.len() != 8 {
|
||||||
return Err(())
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if string.chars().any(|c| !c.is_ascii_alphanumeric()) {
|
if string.chars().any(|c| !c.is_ascii_alphanumeric()) {
|
||||||
return Err(())
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self(string.to_owned()))
|
Ok(Self(string.to_owned()))
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
use std::{path::PathBuf, sync::{Arc, RwLock}};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use rocket::{
|
use rocket::{
|
||||||
get, http::ContentType, response::Redirect, serde::{self, json::Json}, tokio::fs::File, uri, State
|
get,
|
||||||
|
http::ContentType,
|
||||||
|
response::Redirect,
|
||||||
|
serde::{self, json::Json},
|
||||||
|
tokio::fs::File,
|
||||||
|
uri, State,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{database::{Database, Mmid}, settings::Settings};
|
use crate::{
|
||||||
|
database::{Database, Mmid},
|
||||||
|
settings::Settings,
|
||||||
|
};
|
||||||
|
|
||||||
/// An endpoint to obtain information about the server's capabilities
|
/// An endpoint to obtain information about the server's capabilities
|
||||||
#[get("/info")]
|
#[get("/info")]
|
||||||
|
@ -36,16 +44,14 @@ pub struct ServerInfo {
|
||||||
|
|
||||||
/// Look up the [`Mmid`] of a file to find it.
|
/// Look up the [`Mmid`] of a file to find it.
|
||||||
#[get("/f/<mmid>")]
|
#[get("/f/<mmid>")]
|
||||||
pub async fn lookup_mmid(
|
pub async fn lookup_mmid(db: &State<Arc<RwLock<Database>>>, mmid: &str) -> Option<Redirect> {
|
||||||
db: &State<Arc<RwLock<Database>>>,
|
|
||||||
mmid: &str,
|
|
||||||
) -> Option<Redirect> {
|
|
||||||
let mmid: Mmid = mmid.try_into().ok()?;
|
let mmid: Mmid = mmid.try_into().ok()?;
|
||||||
let entry = db.read().unwrap().get(&mmid).cloned()?;
|
let entry = db.read().unwrap().get(&mmid).cloned()?;
|
||||||
|
|
||||||
Some(
|
Some(Redirect::to(uri!(lookup_mmid_name(
|
||||||
Redirect::to(uri!(lookup_mmid_name(mmid.to_string(), entry.name())))
|
mmid.to_string(),
|
||||||
)
|
entry.name()
|
||||||
|
))))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Look up the [`Mmid`] of a file to find it.
|
/// Look up the [`Mmid`] of a file to find it.
|
||||||
|
@ -62,13 +68,15 @@ pub async fn lookup_mmid_name(
|
||||||
|
|
||||||
// If the name does not match, then this is invalid
|
// If the name does not match, then this is invalid
|
||||||
if name != entry.name() {
|
if name != entry.name() {
|
||||||
return None
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let file = File::open(settings.file_dir.join(entry.hash().to_string())).await.ok()?;
|
let file = File::open(settings.file_dir.join(entry.hash().to_string()))
|
||||||
|
.await
|
||||||
|
.ok()?;
|
||||||
|
|
||||||
Some((
|
Some((
|
||||||
ContentType::from_extension(entry.extension()).unwrap_or(ContentType::Binary),
|
ContentType::from_extension(entry.extension()).unwrap_or(ContentType::Binary),
|
||||||
file
|
file,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
26
src/main.rs
26
src/main.rs
|
@ -160,24 +160,18 @@ async fn handle_upload(
|
||||||
// Process filetype
|
// Process filetype
|
||||||
let file_type = file_format::FileFormat::from_file(&temp_filename)?;
|
let file_type = file_format::FileFormat::from_file(&temp_filename)?;
|
||||||
|
|
||||||
let constructed_file =
|
let constructed_file = MochiFile::new_with_expiry(
|
||||||
MochiFile::new_with_expiry(
|
file_mmid.clone(),
|
||||||
file_mmid.clone(),
|
raw_name,
|
||||||
raw_name,
|
file_type.extension(),
|
||||||
file_type.extension(),
|
file_hash,
|
||||||
file_hash,
|
expire_time,
|
||||||
expire_time
|
);
|
||||||
);
|
|
||||||
|
|
||||||
// Move it to the new proper place
|
// Move it to the new proper place
|
||||||
std::fs::rename(
|
std::fs::rename(temp_filename, settings.file_dir.join(file_hash.to_string()))?;
|
||||||
temp_filename,
|
|
||||||
settings.file_dir.join(file_hash.to_string())
|
|
||||||
)?;
|
|
||||||
|
|
||||||
db.write()
|
db.write().unwrap().insert(constructed_file.clone());
|
||||||
.unwrap()
|
|
||||||
.insert(constructed_file.clone());
|
|
||||||
db.write().unwrap().save();
|
db.write().unwrap().save();
|
||||||
|
|
||||||
Ok(Json(ClientResponse {
|
Ok(Json(ClientResponse {
|
||||||
|
@ -251,7 +245,7 @@ async fn main() {
|
||||||
tokio::spawn({
|
tokio::spawn({
|
||||||
let cleaner_db = database.clone();
|
let cleaner_db = database.clone();
|
||||||
let file_path = config.file_dir.clone();
|
let file_path = config.file_dir.clone();
|
||||||
async move { clean_loop(cleaner_db, file_path, rx, TimeDelta::minutes(2)).await }
|
async move { clean_loop(cleaner_db, file_path, rx, TimeDelta::minutes(2)).await }
|
||||||
});
|
});
|
||||||
|
|
||||||
let rocket = rocket::build()
|
let rocket = rocket::build()
|
||||||
|
|
Loading…
Reference in a new issue