Improve shortlink behavior

This commit is contained in:
G2-Games 2024-10-27 17:33:43 -05:00
parent 769bd72542
commit ac41059f0b
3 changed files with 64 additions and 47 deletions

View file

@ -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)
}
}

View file

@ -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),

View file

@ -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.");
}