Add basic networking code

This commit is contained in:
~erin 2022-01-23 21:07:35 -05:00
parent b40041ae04
commit fe695541e4
No known key found for this signature in database
GPG Key ID: DA70E064A8C70F44
6 changed files with 128 additions and 14 deletions

View File

@ -24,3 +24,5 @@ bincode = "1.3.3"
serde = { version = "1.0", features = ["derive"] }
serde_derive = "1.0.132"
rss = "2.0.0"
rocket = { version = "0.5.0-rc.1", features = ["json", "secrets"] }
captcha = "0.0.8"

62
src/captcha.rs Normal file
View File

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

View File

@ -4,6 +4,17 @@ use uuid::Uuid;
mod structures;
mod io;
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() {
// Create the footer
@ -67,16 +78,24 @@ fn rebuild() {
io::write_feed("en");
}
fn main() {
/*
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())]));*/
#[launch]
fn rocket() -> _ {
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/"))
}

12
src/networking.rs Normal file
View File

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

View File

@ -3,11 +3,12 @@ use chrono::prelude::*;
use serde_derive::{Deserialize, Serialize};
use build_html::{self, Html, HtmlContainer, ContainerType, Container, HtmlPage};
use std::fmt;
use rocket::form::Form;
use crate::io::write_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 DESCRIPTION: &str = r#"The cutest cooking site on the net :3"#;
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)]
pub struct Recipe {
pub id: Uuid, // Unique recipe ID
@ -274,3 +287,9 @@ pub fn construct_shortcode(full_name: String) -> String {
})
.collect();
}
// Struct for the users answer to a captcha
#[derive(Clone, Debug, FromForm)]
pub struct CaptchaAnswer {
pub text: String,
}

View File

@ -12,7 +12,7 @@
<h1>Submit a New Recipe</h1>
<hr>
<form action="/api/new-recipe" method="post">
<form action="http://127.0.0.1:8000/api/new-recipe" method="post">
<ul class="form">
<li>
<label for="name">Recipe Name:</label>
@ -32,7 +32,7 @@
</li>
<li>
<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>
<label for="servings">Servings:</label>