Add basic networking code
This commit is contained in:
parent
b40041ae04
commit
fe695541e4
|
@ -24,3 +24,5 @@ bincode = "1.3.3"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_derive = "1.0.132"
|
serde_derive = "1.0.132"
|
||||||
rss = "2.0.0"
|
rss = "2.0.0"
|
||||||
|
rocket = { version = "0.5.0-rc.1", features = ["json", "secrets"] }
|
||||||
|
captcha = "0.0.8"
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
// Generate & verify CAPTCHA's
|
||||||
|
extern crate captcha;
|
||||||
|
|
||||||
|
use std::fs::File;
|
||||||
|
|
||||||
|
use captcha::filters::{Grid, Noise, Wave};
|
||||||
|
use captcha::Captcha;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use crate::structures::{CaptchaAnswer};
|
||||||
|
use rocket::{form::Form, http::Cookie, http::CookieJar};
|
||||||
|
|
||||||
|
// Create a new captcha image
|
||||||
|
fn create_captcha() -> Captcha {
|
||||||
|
let mut captcha = Captcha::new(); // create empty captcha
|
||||||
|
|
||||||
|
captcha
|
||||||
|
.add_chars(7)
|
||||||
|
.apply_filter(Noise::new(0.2))
|
||||||
|
.apply_filter(Grid::new(41, 67))
|
||||||
|
.add_text_area()
|
||||||
|
.apply_filter(Wave::new(1.6373, 5.1363))
|
||||||
|
.view(220, 120); // create image
|
||||||
|
|
||||||
|
let captcha_text = captcha.chars_as_string();
|
||||||
|
|
||||||
|
captcha
|
||||||
|
.save(Path::new(
|
||||||
|
&("/tmp/captcha".to_owned() + &captcha_text + ".png"),
|
||||||
|
))
|
||||||
|
.expect("save failed"); // save captcha
|
||||||
|
|
||||||
|
return captcha;
|
||||||
|
}
|
||||||
|
|
||||||
|
// API to get a new captcha
|
||||||
|
#[get("/captcha")]
|
||||||
|
pub fn return_captcha(cookies: &CookieJar<'_>) -> File {
|
||||||
|
let captcha = create_captcha(); // Create a new captcha
|
||||||
|
let captcha_text = captcha.chars_as_string(); // Store the captcha answer text
|
||||||
|
|
||||||
|
let file = File::open(&("/tmp/captcha".to_owned() + &captcha_text + ".png")); // Open the captcha image file
|
||||||
|
|
||||||
|
info!("created new captcha {}", captcha_text); // Print the captcha text
|
||||||
|
cookies.add_private(Cookie::new( // Set the token as a private cookie
|
||||||
|
"token", // Add a cookie to store the captcha answer
|
||||||
|
captcha_text
|
||||||
|
));
|
||||||
|
|
||||||
|
return file.unwrap(); // Return the captcha image
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the provided captcha answer is correct
|
||||||
|
#[post("/captcha", data = "<answer>")]
|
||||||
|
pub fn check_captcha(answer: Form<CaptchaAnswer>, cookies: &CookieJar<'_>) -> String {
|
||||||
|
let user_token = cookies.get_private("token").unwrap();
|
||||||
|
if user_token.value() == answer.text {
|
||||||
|
return "correct".to_string();
|
||||||
|
} else {
|
||||||
|
return "incorrect".to_string();
|
||||||
|
}
|
||||||
|
}
|
41
src/main.rs
41
src/main.rs
|
@ -4,6 +4,17 @@ use uuid::Uuid;
|
||||||
mod structures;
|
mod structures;
|
||||||
mod io;
|
mod io;
|
||||||
mod tests;
|
mod tests;
|
||||||
|
mod networking;
|
||||||
|
mod captcha;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate rocket;
|
||||||
|
use rocket::fairing::{Fairing, Info, Kind};
|
||||||
|
use rocket::{http::Header, Request, Response};
|
||||||
|
use rocket::fs::FileServer;
|
||||||
|
|
||||||
|
use crate::networking::*;
|
||||||
|
use crate::captcha::*;
|
||||||
|
|
||||||
fn construct_main_page() {
|
fn construct_main_page() {
|
||||||
// Create the footer
|
// Create the footer
|
||||||
|
@ -67,16 +78,24 @@ fn rebuild() {
|
||||||
io::write_feed("en");
|
io::write_feed("en");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
#[launch]
|
||||||
/*
|
fn rocket() -> _ {
|
||||||
let full_recipe = Recipe::new(
|
|
||||||
"Full Recipe".to_string(),
|
|
||||||
(3, Minutes),
|
|
||||||
(4, Hours),
|
|
||||||
7,
|
|
||||||
vec![(3, Cups, "flour".to_string()), (4, Tablespoons, "sugar".to_string()), (1, Cups, "water".to_string())],
|
|
||||||
vec!["Mix flour and sugar in a bowl".to_string(), "Slowly add water".to_string(), "Bake in the oven for 4 hours".to_string()],
|
|
||||||
"Erin Nova".to_string(),
|
|
||||||
Some(vec![Tag('#', "meow".to_string()), Tag('#', "gay".to_string())]));*/
|
|
||||||
rebuild();
|
rebuild();
|
||||||
|
|
||||||
|
// Launch rocket
|
||||||
|
let _config = sled::Config::default()
|
||||||
|
.use_compression(true)
|
||||||
|
.compression_factor(15);
|
||||||
|
|
||||||
|
rocket::build()
|
||||||
|
.mount(
|
||||||
|
"/api",
|
||||||
|
routes![
|
||||||
|
test,
|
||||||
|
return_captcha,
|
||||||
|
check_captcha,
|
||||||
|
new_recipe
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.mount("/", FileServer::from("static/en/"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
use rocket::form::Form;
|
||||||
|
use crate::structures::RecipeForm;
|
||||||
|
|
||||||
|
#[get("/test")]
|
||||||
|
pub fn test() -> String {
|
||||||
|
return "Hello! :3".to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/new-recipe", data = "<recipe>")]
|
||||||
|
pub fn new_recipe(recipe: Form<RecipeForm>) -> String {
|
||||||
|
return recipe.name.clone();
|
||||||
|
}
|
|
@ -3,11 +3,12 @@ use chrono::prelude::*;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use build_html::{self, Html, HtmlContainer, ContainerType, Container, HtmlPage};
|
use build_html::{self, Html, HtmlContainer, ContainerType, Container, HtmlPage};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use rocket::form::Form;
|
||||||
|
|
||||||
use crate::io::write_html;
|
use crate::io::write_html;
|
||||||
|
|
||||||
// Content strings to add to html
|
// Content strings to add to html
|
||||||
pub const TITLE: &str = r#"Catgirl Cooking"#;
|
pub const TITLE: &str = r#"🥘 Catgirl Cooking"#;
|
||||||
pub const HEADER: &str = r#"🥘 Catgirl Cooking"#;
|
pub const HEADER: &str = r#"🥘 Catgirl Cooking"#;
|
||||||
pub const DESCRIPTION: &str = r#"The cutest cooking site on the net :3"#;
|
pub const DESCRIPTION: &str = r#"The cutest cooking site on the net :3"#;
|
||||||
pub const DETAILS: &str = r#"Absolutely no ads, tracking, or nazis, ever."#;
|
pub const DETAILS: &str = r#"Absolutely no ads, tracking, or nazis, ever."#;
|
||||||
|
@ -104,6 +105,18 @@ impl Tag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(FromForm)]
|
||||||
|
pub struct RecipeForm {
|
||||||
|
pub name: String,
|
||||||
|
pub author: String,
|
||||||
|
pub tags: String,
|
||||||
|
pub prep_time: String,
|
||||||
|
pub cooking_time: String,
|
||||||
|
pub servings: String,
|
||||||
|
pub ingredients: String,
|
||||||
|
pub directions: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Recipe {
|
pub struct Recipe {
|
||||||
pub id: Uuid, // Unique recipe ID
|
pub id: Uuid, // Unique recipe ID
|
||||||
|
@ -274,3 +287,9 @@ pub fn construct_shortcode(full_name: String) -> String {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Struct for the users answer to a captcha
|
||||||
|
#[derive(Clone, Debug, FromForm)]
|
||||||
|
pub struct CaptchaAnswer {
|
||||||
|
pub text: String,
|
||||||
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<h1>Submit a New Recipe</h1>
|
<h1>Submit a New Recipe</h1>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<form action="/api/new-recipe" method="post">
|
<form action="http://127.0.0.1:8000/api/new-recipe" method="post">
|
||||||
<ul class="form">
|
<ul class="form">
|
||||||
<li>
|
<li>
|
||||||
<label for="name">Recipe Name:</label>
|
<label for="name">Recipe Name:</label>
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label for="cooking_time">Cooking Time:</label>
|
<label for="cooking_time">Cooking Time:</label>
|
||||||
<input type="text" id="cooking_time" placeholder="2 hours">
|
<input type="text" id="cooking_time" name="cooking_time" placeholder="2 hours">
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label for="servings">Servings:</label>
|
<label for="servings">Servings:</label>
|
||||||
|
|
Loading…
Reference in New Issue