mirror of
https://github.com/Dangoware/confetti-box.git
synced 2025-04-19 15:22:57 -05:00
Improve shortlink behavior
This commit is contained in:
parent
769bd72542
commit
ac41059f0b
3 changed files with 64 additions and 47 deletions
|
@ -1,5 +1,5 @@
|
|||
use std::{
|
||||
collections::{hash_map::Values, HashMap, HashSet}, 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};
|
||||
|
@ -308,3 +308,38 @@ impl TryFrom<&str> for Mmid {
|
|||
Ok(Self(value.to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&Path> for Mmid {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: &Path) -> Result<Self, Self::Error> {
|
||||
value.as_os_str().try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&OsStr> for Mmid {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: &OsStr) -> Result<Self, Self::Error> {
|
||||
let string = match value.to_str() {
|
||||
Some(p) => p,
|
||||
None => return Err(()),
|
||||
};
|
||||
|
||||
if string.len() != 8 {
|
||||
return Err(())
|
||||
}
|
||||
|
||||
if string.chars().any(|c| !c.is_ascii_alphanumeric()) {
|
||||
return Err(())
|
||||
}
|
||||
|
||||
Ok(Self(string.to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Mmid {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::sync::{Arc, RwLock};
|
||||
use std::{path::PathBuf, sync::{Arc, RwLock}};
|
||||
|
||||
use rocket::{
|
||||
fs::NamedFile, get, http::ContentType, serde::{self, json::Json}, tokio::fs::File, State
|
||||
get, http::ContentType, response::Redirect, serde::{self, json::Json}, tokio::fs::File, uri, State
|
||||
};
|
||||
use serde::Serialize;
|
||||
|
||||
|
@ -36,56 +36,36 @@ pub struct ServerInfo {
|
|||
|
||||
/// Look up the [`Mmid`] of a file to find it.
|
||||
#[get("/f/<mmid>")]
|
||||
pub async fn lookup(
|
||||
pub async fn lookup_mmid(
|
||||
db: &State<Arc<RwLock<Database>>>,
|
||||
settings: &State<Settings>,
|
||||
mmid: &str
|
||||
) -> Option<(ContentType, NamedFile)> {
|
||||
let mmid: Mmid = match mmid.try_into() {
|
||||
Ok(v) => v,
|
||||
Err(_) => return None,
|
||||
};
|
||||
mmid: &str,
|
||||
) -> Option<Redirect> {
|
||||
let mmid: Mmid = mmid.try_into().ok()?;
|
||||
let entry = db.read().unwrap().get(&mmid).cloned()?;
|
||||
|
||||
let entry = if let Some(e) = db.read().unwrap().get(&mmid).cloned() {
|
||||
e
|
||||
} else {
|
||||
return None
|
||||
};
|
||||
|
||||
let file = NamedFile::open(settings.file_dir.join(entry.hash().to_string())).await.ok()?;
|
||||
|
||||
Some((
|
||||
ContentType::from_extension(entry.extension()).unwrap_or(ContentType::Binary),
|
||||
file
|
||||
))
|
||||
Some(
|
||||
Redirect::to(uri!(lookup_mmid_name(mmid.to_string(), entry.name())))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
#[get("/f/<mmid>/<filename>")]
|
||||
pub async fn lookup_filename(
|
||||
/// Look up the [`Mmid`] of a file to find it.
|
||||
#[get("/f/<mmid>/<name>")]
|
||||
pub async fn lookup_mmid_name(
|
||||
db: &State<Arc<RwLock<Database>>>,
|
||||
settings: &State<Settings>,
|
||||
mmid: &str,
|
||||
filename: &str,
|
||||
) -> Option<(ContentType, NamedFile)> {
|
||||
let mmid: Mmid = match mmid.try_into() {
|
||||
Ok(v) => v,
|
||||
Err(_) => return None,
|
||||
};
|
||||
name: &str,
|
||||
) -> Option<(ContentType, File)> {
|
||||
let mmid: Mmid = mmid.try_into().ok()?;
|
||||
|
||||
let entry = if let Some(e) = db.read().unwrap().get(&mmid).cloned() {
|
||||
e
|
||||
} else {
|
||||
return None
|
||||
};
|
||||
let entry = db.read().unwrap().get(&mmid).cloned()?;
|
||||
|
||||
dbg!(entry.name());
|
||||
dbg!(filename);
|
||||
if entry.name() != filename {
|
||||
// If the name does not match, then this is invalid
|
||||
if name != entry.name() {
|
||||
return None
|
||||
}
|
||||
|
||||
let file = NamedFile::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((
|
||||
ContentType::from_extension(entry.extension()).unwrap_or(ContentType::Binary),
|
||||
|
|
14
src/main.rs
14
src/main.rs
|
@ -11,7 +11,7 @@ use std::{
|
|||
|
||||
use chrono::{DateTime, TimeDelta, Utc};
|
||||
use database::{clean_loop, Database, Mmid, MochiFile};
|
||||
use endpoints::{lookup, lookup_filename, server_info};
|
||||
use endpoints::{lookup_mmid, lookup_mmid_name, server_info};
|
||||
use log::info;
|
||||
use maud::{html, Markup, PreEscaped, DOCTYPE};
|
||||
use rocket::{
|
||||
|
@ -102,7 +102,7 @@ fn home(settings: &State<Settings>) -> Markup {
|
|||
footer {
|
||||
p {a href="https://github.com/G2-Games/confetti-box" {"Source"}}
|
||||
p {a href="https://g2games.dev/" {"My Website"}}
|
||||
p {a href="#" {"Links"}}
|
||||
p {a href="api" {"API Info"}}
|
||||
p {a href="#" {"Go"}}
|
||||
p {a href="#" {"Here"}}
|
||||
}
|
||||
|
@ -264,8 +264,8 @@ async fn main() {
|
|||
stylesheet,
|
||||
server_info,
|
||||
favicon,
|
||||
lookup,
|
||||
lookup_filename,
|
||||
lookup_mmid,
|
||||
lookup_mmid_name,
|
||||
],
|
||||
)
|
||||
.mount(
|
||||
|
@ -284,12 +284,14 @@ async fn main() {
|
|||
// Ensure the server gracefully shuts down
|
||||
rocket.expect("Server failed to shutdown gracefully");
|
||||
|
||||
info!("Stopping database cleaning thread");
|
||||
info!("Stopping database cleaning thread...");
|
||||
shutdown
|
||||
.send(())
|
||||
.await
|
||||
.expect("Failed to stop cleaner thread");
|
||||
.expect("Failed to stop cleaner thread.");
|
||||
info!("Stopping database cleaning thread completed successfully.");
|
||||
|
||||
info!("Saving database on shutdown...");
|
||||
local_db.write().unwrap().save();
|
||||
info!("Saving database completed successfully.");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue