diff --git a/src/main.rs b/src/main.rs index 9bd7b68..38c98cf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,10 @@ -use std::{env, fs::{self, File}, thread}; +use std::{collections::HashMap, env, fs::{self, File}, sync::{Arc, Mutex}, thread}; use chrono::Utc; use kv::{Config, Store, Json, Bucket, Value}; use paste::Paste; use rand::{Rng, distributions::Alphanumeric}; -use rouille::{Response, router, try_or_400, post_input, Request, Server}; +use rouille::{post_input, router, try_or_400, websocket, Request, Response, Server}; use signal_hook::{iterator::Signals, consts::{SIGINT, SIGTERM}}; mod paste; @@ -30,6 +30,7 @@ fn generate_key(key: Option, store: &Bucket) -> St } } +// Get query parameters fn get_query(req: &Request, name: &str) -> Option { let params: Vec<&str> = req.raw_query_string().split('&').collect(); let param = params.iter().find(|p|p.starts_with(&format!("{}=", name))); @@ -58,6 +59,8 @@ fn main() { let links = store.bucket::(Some("links")) .expect("Failed to open links bucket"); + // Temp pastes + let temp_pastes = Arc::new(Mutex::new(HashMap::new())); // Create server let server = Server::new(format!("0.0.0.0:{}", port), move |req| { @@ -68,6 +71,10 @@ fn main() { } } + if req.url().starts_with("/ws") { + handle_websocket(temp_pastes.clone(), &req); + } + router!(req, (GET) (/) => { match File::open(format!("{}/index.html", &source_dir)) { @@ -115,7 +122,7 @@ fn main() { }, (POST) (/{id: String}) => { let id = if id.is_empty() { None } else { Some(id) }; - register_paste(&pastes, req, id, prefix.clone()) + register_paste(&pastes, req, id, prefix.clone(), None) }, _ => Response::empty_404() ) @@ -143,8 +150,7 @@ fn main() { } // Register paste handler -fn register_paste(pastes: &Bucket>, req: &Request, id: Option, prefix: Option) -> Response { - +fn register_paste(pastes: &Bucket>, req: &Request, id: Option, prefix: Option, allow_edit: Option) -> Response { // Try read body from form data, and if not present from request body let body = match post_input!(req, { content: String @@ -165,6 +171,7 @@ fn register_paste(pastes: &Bucket>, req: &Request, id: Optio content: body, expires: None, language, + allow_edit, created: Utc::now() }); @@ -209,4 +216,32 @@ fn register_link(links: &Bucket, req: &Request, id: Option>>, req: &Request) -> Response { + let key = get_query(&req, "key").unwrap(); + + let mut current_text = String::new(); + match pastes.lock().expect("Failed to access pastes DB").get(&key) { + Some(paste) => { + current_text = paste.clone() + }, + None => { + // OK, ignore + } + } + + let (response, websocket) = try_or_400!(websocket::start(req, Some("pastabble"))); + if let Ok(mut ws) = websocket.recv() { + thread::spawn(move || { + if !current_text.is_empty() { + _ = ws.send_text(¤t_text); + } + + + }); + return response.with_additional_header("Access-Control-Allow-Origin", "*"); + } else { + return Response::empty_400() + } } \ No newline at end of file diff --git a/src/paste.rs b/src/paste.rs index f4965fd..fe06369 100644 --- a/src/paste.rs +++ b/src/paste.rs @@ -9,5 +9,7 @@ pub struct Paste { #[serde(with = "ts_seconds_option")] pub expires: Option>, - pub created: DateTime + pub created: DateTime, + + pub allow_edit: Option } \ No newline at end of file