Initial commit
This commit is contained in:
93
src/main.rs
Normal file
93
src/main.rs
Normal file
@@ -0,0 +1,93 @@
|
||||
use std::{env, fs};
|
||||
|
||||
use chrono::Utc;
|
||||
use kv::{Config, Store, Json};
|
||||
use paste::Paste;
|
||||
use rand::{Rng, distributions::Alphanumeric};
|
||||
use rouille::{Response, router, try_or_400, post_input};
|
||||
|
||||
mod paste;
|
||||
|
||||
// Generate random key function
|
||||
fn new_key() -> String {
|
||||
rand::thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
.take(5)
|
||||
.map(char::from)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Get settings
|
||||
let port: u16 = env::var("PORT").unwrap_or(String::from("8080")).parse().expect("Failed to parse PORT variable");
|
||||
let data_dir: String = env::var("DATA_DIR").unwrap_or(String::from("./data"));
|
||||
|
||||
let config = Config::new(data_dir);
|
||||
let store = Store::new(config).expect("Failed to initialize database store");
|
||||
let about = fs::read_to_string("./about.html").expect("about.html not found!!");
|
||||
|
||||
// Get pastes bucket (default)
|
||||
let pastes = store.bucket::<String, Json<Paste>>(Some("pastes"))
|
||||
.expect("Failed to open default bucket");
|
||||
|
||||
// Start server
|
||||
println!("Started PASTABBLE server on port {}", port);
|
||||
rouille::start_server(format!("0.0.0.0:{}", port), move |req| {
|
||||
router!(req,
|
||||
(GET) (/) => {
|
||||
Response::html(&about)
|
||||
},
|
||||
(GET) (/{id: String}) => {
|
||||
// Get note from database, if exists
|
||||
match pastes.get(&id).expect("Failed to access DB") {
|
||||
Some(paste) => {
|
||||
Response::text(paste.0.content)
|
||||
},
|
||||
None => {
|
||||
Response::text(format!("Note with ID '{}' not found", &id))
|
||||
.with_status_code(404)
|
||||
}
|
||||
}
|
||||
},
|
||||
(POST) (/{id: String}) => {
|
||||
// Use provided key or generate new one
|
||||
let key = if !id.is_empty() && !pastes.contains(&id).unwrap() {
|
||||
id
|
||||
} else {
|
||||
loop {
|
||||
let new_key = new_key();
|
||||
if !pastes.contains(&new_key).expect("Could not access store") {
|
||||
break new_key;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Try read body from form data, and if not present from request body
|
||||
let body = match post_input!(&req, {
|
||||
content: String
|
||||
}) {
|
||||
Ok(f) => {
|
||||
f.content
|
||||
},
|
||||
Err(_) => {
|
||||
try_or_400!(rouille::input::plain_text_body(&req))
|
||||
}
|
||||
};
|
||||
|
||||
// Create and save new note
|
||||
let paste = Json(Paste {
|
||||
content: body,
|
||||
expires: None,
|
||||
language: None,
|
||||
created: Utc::now()
|
||||
});
|
||||
|
||||
pastes.set(&key, &paste).expect("Failed to save note");
|
||||
|
||||
// Return key
|
||||
Response::text(key)
|
||||
},
|
||||
_ => Response::empty_404()
|
||||
)
|
||||
});
|
||||
}
|
||||
13
src/paste.rs
Normal file
13
src/paste.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use chrono::serde::ts_seconds_option;
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
pub struct Paste {
|
||||
pub content: String,
|
||||
pub language: Option<String>,
|
||||
|
||||
#[serde(with = "ts_seconds_option")]
|
||||
pub expires: Option<DateTime<Utc>>,
|
||||
pub created: DateTime<Utc>
|
||||
}
|
||||
Reference in New Issue
Block a user