diff --git a/src/database.rs b/src/database.rs index 968903f..c3f90dd 100644 --- a/src/database.rs +++ b/src/database.rs @@ -69,19 +69,19 @@ impl Database { /// Insert a [`MochiFile`] into the database. /// /// If the database already contained this value, then `false` is returned. - pub fn insert(&mut self, entry: MochiFile) -> bool { + pub fn insert(&mut self, mmid: &Mmid, entry: MochiFile) -> bool { if let Some(s) = self.hashes.get_mut(&entry.hash) { // If the database already contains the hash, make sure the file is unique - if !s.insert(entry.mmid.clone()) { + if !s.insert(mmid.clone()) { return false; } } else { // If the database does not contain the hash, create a new set for it self.hashes - .insert(entry.hash, HashSet::from([entry.mmid.clone()])); + .insert(entry.hash, HashSet::from([mmid.clone()])); } - self.entries.insert(entry.mmid.clone(), entry.clone()); + self.entries.insert(mmid.clone(), entry.clone()); true } @@ -266,7 +266,9 @@ pub async fn clean_loop( /// A unique identifier for an entry in the database, 8 characters long, /// consists of ASCII alphanumeric characters (`a-z`, `A-Z`, and `0-9`). -#[derive(Debug, PartialEq, Eq, Clone, Decode, Encode, Hash, Deserialize, Serialize)] +#[derive(Debug, PartialEq, Eq, Clone, Hash)] +#[derive(Decode, Encode)] +#[derive(Deserialize, Serialize)] pub struct Mmid(String); impl Mmid { diff --git a/src/endpoints.rs b/src/endpoints.rs index 8133422..cf2fdab 100644 --- a/src/endpoints.rs +++ b/src/endpoints.rs @@ -54,10 +54,9 @@ pub async fn lookup_mmid(db: &State>>, mmid: &str) -> Optio )))) } -/// Look up the [`Mmid`] of a file to find it. +/// Look up the [`Mmid`] of a file to find it, along with the name of the file #[get("/f//")] -pub async fn lookup_mmid_name( - db: &State>>, +pub async fn lookup_mmid_name(db: &State>>, settings: &State, mmid: &str, name: &str, diff --git a/src/main.rs b/src/main.rs index ef1af86..eedc050 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ mod endpoints; mod settings; mod strings; mod utils; +mod pages; use std::{ fs, @@ -13,37 +14,16 @@ use chrono::{DateTime, TimeDelta, Utc}; use database::{clean_loop, Database, Mmid, MochiFile}; use endpoints::{lookup_mmid, lookup_mmid_name, server_info}; use log::info; -use maud::{html, Markup, PreEscaped, DOCTYPE}; +use maud::{html, Markup, PreEscaped}; +use pages::{api_info, footer, head}; use rocket::{ - data::{Limits, ToByteUnit}, - form::Form, - fs::{FileServer, Options, TempFile}, - get, - http::ContentType, - post, - response::content::{RawCss, RawJavaScript}, - routes, - serde::{json::Json, Serialize}, - tokio, Config, FromForm, State, + data::{Limits, ToByteUnit}, form::Form, fs::{FileServer, Options, TempFile}, get, http::ContentType, post, response::content::{RawCss, RawJavaScript}, routes, serde::{json::Json, Serialize}, tokio, Config, FromForm, State }; use settings::Settings; use strings::{parse_time_string, to_pretty_time}; use utils::hash_file; use uuid::Uuid; -fn head(page_title: &str) -> Markup { - html! { - (DOCTYPE) - meta charset="UTF-8"; - meta name="viewport" content="width=device-width, initial-scale=1"; - title { (page_title) } - // Javascript stuff for client side handling - script src="./request.js" { } - link rel="icon" type="image/svg+xml" href="favicon.svg"; - link rel="stylesheet" href="./main.css"; - } -} - /// Stylesheet #[get("/main.css")] fn stylesheet() -> RawCss<&'static str> { @@ -65,6 +45,7 @@ fn favicon() -> (ContentType, &'static str) { fn home(settings: &State) -> Markup { html! { (head("Confetti-Box")) + script src="./request.js" { } center { h1 { "Confetti-Box 🎉" } @@ -86,10 +67,10 @@ fn home(settings: &State) -> Markup { } form #uploadForm { // It's stupid how these can't be styled so they're just hidden here... - input #fileInput type="file" name="fileUpload" multiple - onchange="formSubmit(this.parentNode)" data-max-filesize=(settings.max_filesize) style="display:none;"; input #fileDuration type="text" name="duration" minlength="2" maxlength="7" value=(settings.duration.default.num_seconds().to_string() + "s") style="display:none;"; + input #fileInput type="file" name="fileUpload" multiple + onchange="formSubmit(this.parentNode)" data-max-filesize=(settings.max_filesize) style="display:none;"; } hr; @@ -99,13 +80,7 @@ fn home(settings: &State) -> Markup { } hr; - footer { - p {a href="https://github.com/G2-Games/confetti-box" {"Source"}} - p {a href="https://g2games.dev/" {"My Website"}} - p {a href="api" {"API Info"}} - p {a href="#" {"Go"}} - p {a href="#" {"Here"}} - } + (footer()) } } } @@ -171,7 +146,7 @@ async fn handle_upload( // Move it to the new proper place std::fs::rename(temp_filename, settings.file_dir.join(file_hash.to_string()))?; - db.write().unwrap().insert(constructed_file.clone()); + db.write().unwrap().insert(&file_mmid, constructed_file.clone()); db.write().unwrap().save(); Ok(Json(ClientResponse { @@ -253,6 +228,7 @@ async fn main() { config.server.root_path.clone() + "/", routes![ home, + api_info, handle_upload, form_handler_js, stylesheet, diff --git a/src/pages.rs b/src/pages.rs new file mode 100644 index 0000000..87c6d5a --- /dev/null +++ b/src/pages.rs @@ -0,0 +1,52 @@ +use maud::{html, Markup, DOCTYPE}; +use rocket::get; + +pub fn head(page_title: &str) -> Markup { + html! { + (DOCTYPE) + meta charset="UTF-8"; + meta name="viewport" content="width=device-width, initial-scale=1"; + title { (page_title) } + link rel="icon" type="image/svg+xml" href="favicon.svg"; + link rel="stylesheet" href="./main.css"; + } +} + +pub fn footer() -> Markup { + html! { + footer { + p {a href="/" {"Home"}} + p {a href="https://github.com/G2-Games/confetti-box" {"Source"}} + p {a href="https://g2games.dev/" {"My Website"}} + p {a href="api_info" {"API Info"}} + p {a href="https://ko-fi.com/g2_games" {"Donate"}} + } + } +} + +#[get("/api_info")] +pub fn api_info() -> Markup { + html! { + (head("Confetti-Box | API")) + + center { + h1 { "API Information" } + hr; + + div style="text-align: left;" { + p { + """ + The API for this service can be used by POST ing a form + with an expiration time and file to upload to the upload + endpoint: + """ + } + pre { "/upload POST duration=\"6h\" fileUpload=(file data)" } + + } + + hr; + (footer()) + } + } +} diff --git a/web/main.css b/web/main.css index d362099..3e41a99 100644 --- a/web/main.css +++ b/web/main.css @@ -1,5 +1,3 @@ -@import url('https://g2games.dev/assets/fonts/fonts.css'); - body { font-family: sans-serif; } @@ -74,6 +72,13 @@ button.main_file_upload { border: 2px dashed grey; } +pre { + color: white; + background-color: black; + font-size: 11pt; + padding: 10px; +} + #durationBox { margin-top: 0; display: flex; diff --git a/web/request.js b/web/request.js index 5619fd5..32a47e9 100644 --- a/web/request.js +++ b/web/request.js @@ -72,8 +72,8 @@ async function fileSend(files, duration, maxSize) { // Create and send FormData try { const formData = new FormData(); - formData.append("fileUpload", file); formData.append("duration", duration); + formData.append("fileUpload", file); request.send(formData); } catch (e) { makeErrored(progressBar, progressText, linkRow, ERROR_TEXT);