From 4d0fb59e338f5d2dd10baaa6a6681e16d0772214 Mon Sep 17 00:00:00 2001 From: Erin Nova Date: Fri, 1 Apr 2022 00:23:59 -0400 Subject: [PATCH] Read text from TOML config file --- Cargo.lock | 1 + config.toml | 40 ++++++++++ src/html.rs | 141 ++++++++++++++++++++++++++--------- templates/about/index.html | 82 ++++++++++++++++++++ templates/contact/index.html | 112 ++++++++++++++++++++++++++++ templates/index.html | 23 ++++++ 6 files changed, 363 insertions(+), 36 deletions(-) create mode 100644 config.toml create mode 100644 templates/about/index.html create mode 100644 templates/contact/index.html diff --git a/Cargo.lock b/Cargo.lock index 9c5c219..1cccdac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1406,6 +1406,7 @@ dependencies = [ "serde", "sled", "tera", + "toml", "uuid", ] diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..dbf2502 --- /dev/null +++ b/config.toml @@ -0,0 +1,40 @@ +title = "Catgirl Pharmacy" +description = "Nyaa~" + +# label - displayed in navigation bar +# title - displayed on page + +[index] +label = "Home" +href = "/" +title = "The best source for certified gay HRT & supplies" + +[about] +label = "About" +href = "/about/" +title = "About Us" + +[contact] +label = "Contact" +href = "/contact/" +title = "Contact Us" + +[products] +label = "Products" +href = "/products/" +title = "Our Products" + +[products.estrogens] +label = "Estrogens" +title = "Estrogens" +href = "/products/#estrogens" + +[products.anti_androgens] +label = "Anti-Androgens" +title = "Anti-Androgens" +href = "/products/#aa" + +[products.progestogens] +label = "Progestogens" +title = "Progestogens" +href = "/products/#progestogens" diff --git a/src/html.rs b/src/html.rs index 11c1e7a..98f52f5 100644 --- a/src/html.rs +++ b/src/html.rs @@ -1,8 +1,9 @@ use serde::{Deserialize, Serialize}; -use std::io::Write; +use std::io::{Read, Write}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Mutex; use tera::{Context, Tera}; +use toml::Value; #[derive(Serialize)] struct NavLink { @@ -11,7 +12,41 @@ struct NavLink { active: AtomicBool, } +#[derive(Serialize, Deserialize)] +struct Config { + title: String, + description: String, + index: Page, + about: Page, + contact: Page, + products: Products, +} + +#[derive(Serialize, Deserialize)] +struct Products { + label: String, + href: String, + title: String, + estrogens: Page, + anti_androgens: Page, + progestogens: Page, +} + +#[derive(Serialize, Deserialize)] +struct Page { + label: String, + href: String, + title: String, +} + pub fn render_pages() { + // Read in TOML + let mut config_file = std::fs::File::open("config.toml").unwrap(); + let mut contents = String::new(); + config_file.read_to_string(&mut contents).unwrap(); + let config: Config = toml::from_str(&contents).unwrap(); + println!("{}", config.index.href); + // Use globbing let tera = match Tera::new("templates/**/*.html") { Ok(t) => t, @@ -23,79 +58,107 @@ pub fn render_pages() { // Setup basic elements let nav_home = NavLink { - href: "/".to_string(), - text: "Home".to_string(), + href: config.index.href, + text: config.index.label.clone(), active: AtomicBool::new(true), }; let nav_about = NavLink { - href: "/about/".to_string(), - text: "About".to_string(), + href: config.about.href, + text: config.about.label.clone(), active: AtomicBool::new(false), }; let nav_products = NavLink { - href: "/products/".to_string(), - text: "Products".to_string(), + href: config.products.href, + text: config.products.label.clone(), active: AtomicBool::new(false), }; let nav_contact = NavLink { - href: "/contact/".to_string(), - text: "Contact".to_string(), + href: config.contact.href, + text: config.contact.label.clone(), active: AtomicBool::new(false), }; let nav_elements = vec![nav_home, nav_about, nav_products, nav_contact]; let estrogens = NavLink { - href: "/products/#estrogens".to_string(), - text: "Estrogens".to_string(), + href: config.products.estrogens.href, + text: config.products.estrogens.label.clone(), active: AtomicBool::new(false), }; let aa = NavLink { - href: "/products/#aa".to_string(), - text: "Anti-Androgens".to_string(), + href: config.products.anti_androgens.href, + text: config.products.anti_androgens.label.clone(), active: AtomicBool::new(false), }; let progestogens = NavLink { - href: "/products/#progestogens".to_string(), - text: "Progestogens".to_string(), + href: config.products.progestogens.href, + text: config.products.progestogens.label.clone(), active: AtomicBool::new(false), }; let product_classes = vec![estrogens, aa, progestogens]; // Render pages - + let index_render = RenderObject { + url: "index.html".to_string(), + tera: tera.clone(), + subtitle: &config.index.title, + active_page: &config.index.label, + title: &config.title, + description: &config.description, + }; render_page( // Home - "index.html".to_string(), - tera.clone(), - "The best source for certified gay HRT & supplies".to_string(), - "Home".to_string(), + index_render, &nav_elements, &product_classes, ); + + let about_render = RenderObject { + url: "about/index.html".to_string(), + tera: tera.clone(), + subtitle: &config.about.title, + active_page: &config.about.label, + title: &config.title, + description: &config.description, + }; render_page( // About - "about/index.html".to_string(), - tera.clone(), - "About Us".to_string(), - "About".to_string(), + about_render, + &nav_elements, + &product_classes, + ); + + let contact_render = RenderObject { + url: "contact/index.html".to_string(), + tera: tera.clone(), + subtitle: &config.contact.title, + active_page: &config.contact.label, + title: &config.title, + description: &config.description, + }; + render_page( + // About + contact_render, &nav_elements, &product_classes, ); } -fn render_page( +struct RenderObject<'a> { url: String, tera: Tera, - subtitle: String, - active_page: String, - nav_elements: &Vec, - product_classes: &Vec, -) { - let mut output_file = std::fs::File::create(format!("static/{}", url)).expect("create failed"); + subtitle: &'a str, + active_page: &'a str, + title: &'a str, + description: &'a str, +} + +fn render_page(data: RenderObject, nav_elements: &[NavLink], product_classes: &[NavLink]) { + let mut output_file = + std::fs::File::create(format!("static/{}", data.url)).expect("create failed"); for i in nav_elements { - if i.text == active_page { + if i.text == data.active_page { i.active.store(true, Ordering::Relaxed); } else { i.active.store(false, Ordering::Relaxed); @@ -103,14 +166,20 @@ fn render_page( } let mut context = Context::new(); - context.insert("title", "Catgirl Pharmacy"); - context.insert("description", "Meow"); - context.insert("subtitle", &subtitle); + context.insert("title", data.title); + context.insert("description", data.description); + context.insert("subtitle", &data.subtitle); for i in nav_elements { context.insert(&i.text.to_ascii_lowercase(), &i); } context.insert("product_classes", &product_classes); + if data.active_page == "Contact" { + context.insert("is_contact", &true); + } else { + context.insert("is_contact", &false); + } + output_file - .write_all(tera.render("index.html", &context).unwrap().as_bytes()) + .write_all(data.tera.render(&data.url, &context).unwrap().as_bytes()) .expect("write failed"); } diff --git a/templates/about/index.html b/templates/about/index.html new file mode 100644 index 0000000..be5747f --- /dev/null +++ b/templates/about/index.html @@ -0,0 +1,82 @@ + + + + {# head content #} + {{ title }} + + + + + + + + + + + + + + + + + + + + + +

{{ title }}

+ + {# Navigation #} + + +

{{ subtitle }}

+ + {# articles #} +

We're a queer, anarcho-communist, collectively-owned pharmacy.
+ We produce & distribute high-quality and cheap HRT, medical equipment, and other drugs.
+ Please go to our contact page if you have any questions, or would like to place an order.

+ +

By purchasing our products, you're helping us manufacture and distribute HRT to people. + We need to pay for raw ingredients, tools, and other supplies.
+ We are not a large pharmaceutical company, just a small group of queers who enjoy doing this.

+ +

This website is optimized for speed & privacy.
+ We will never share your information with any third-parties.
+ We only keep what details are necessary.
+ We encourage the use of encryption to secure communications.
+ This site can be used completely without javascript. + There are only some optional scripts on product pages to automatically fetch price/stock info.
+ It only makes one GET request per page, on the same domain of this site. + If you are disabling javascript, buttons will appear so that you can manually fetch the info.
+ A single private cookie is used on the contact page to store the CAPTCHA answer.

+ +

Reviews

+

Trust is important for any sort of online market, however we don't, and do not plan to, have any on-site review/comment system.
+ Not only would this require lot's of moderation to prevent abuse, but there's nothing stopping us from creating fake reviews.
+ We'd reccomend checking reviews on other sites, or getting info from a trusted person. This way the review can be trusted more.
+ We encourage you to create reviews of us though! It will help our reputation, and help spread us to help more people.

+ +

Ordering

+

You can place an order by email, XMPP, or through our website.
+ For payment, we only accept Monero (XMR) at the moment.

+ +

In your message, please specify the products & amounts you wish to purchase.
+ We will respond with the exact amount to pay, as well as the address to send payment to.

+ +

If you cannot afford it, contact us and we can work something out. We will try our best to make HRT affordable and available to everyone who needs it
+ We should also be able to make custom dosages/amounts.

+ diff --git a/templates/contact/index.html b/templates/contact/index.html new file mode 100644 index 0000000..ff7ff58 --- /dev/null +++ b/templates/contact/index.html @@ -0,0 +1,112 @@ + + + + {# head content #} + {{ title }} + + + + + + + + + + + + + + + + + + + + + +

{{ title }}

+ + {# Navigation #} + + +

{{ subtitle }}

+ + {# articles #} +

Please use our PGP key if contacting us through email, or OMEMO for XMPP.
+ We reccomend using the Gajim XMPP client. You will need to configure it to go through tor.
+

We currently only have an XMPP account on our locally ran server, so if you want to contact us there your server must be able to connect to onion services, or you can request to register on our server.
+ You can also use age to encrypt messages if you want.
+ Our age key is age13ukug0w2drc3k7x35r88rzjwuwt3dtrrqx0mvzk4uet35w5a3vysdud69t
+ Our PGP fingerprint is 28EE 9DAC B217 1959 E8A4 0321 5533 5B9E BFC6 535B
+ Our OMEMO fingerprint is
+ + 7C7D9438 DDCC620E EE3A858F 7D926374 + F65DBE83 8EF48DE1 40D6A12E 3A97D62A + +

+ + hrt@[REDACTED] + hrt@zwiybhyhqdamyjnjzmn34q6u2lnbikvlv73gfxeiks7ymzrzccy6qgyd.onion + +

Web Order

+

Use whatever name you'd prefer for us to refer to you by.
+ Your email is needed so we can send you confirmation/info of your order. (XMPP address also accepted)
+ Feel free to link to somewhere we can get your PGP key if you have one as well.
+ Required fields are followed by *.

+ + {# For Contact Page #} + {% if is_contact %} +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ {% endif %} + diff --git a/templates/index.html b/templates/index.html index 1ce4168..df88493 100644 --- a/templates/index.html +++ b/templates/index.html @@ -46,4 +46,27 @@

{{ subtitle }}

{# articles #} +

Stay Safe!

+

Check what URL you're on! The only valid URL's are here according to the dark.fail Onion Mirror Guidelines (mirror).
+ That message will be signed by our PGP key, along with a canary, which you can verify here (mirror).

+ +

Monero is the reccomended cryptocurrency for privacy. (cryptonote)
+ Only use the address we send to you directly, to ensure you're not being scammed.
+

+ +

Please use PGP for sending/recieving messages to ensure their authenticity, and to protect the contents.
+ Age can also be used for encryption, but cannot be used for signing.
+ While email is insecure, it is the easist communication platform, and most people have it, which is why we use it.
+ And with PGP, while still not the best, is still good enough for our purposes.
+ However if you would like, you can contact us over XMPP using OMEMO for more security.

+ +

Privacy Policy

+

Note: This is not a legal document!

+ +

IP's on clearnet site are stored for maximum 1 week before deletion, for anti-spam purposes.
+ Contact details, messages, etc. are stored in plaintext. You can request this info to be deleted.
+ Messages sent over email/xmpp will be subject to whatever security/privacy policies the servers used have.
+ Use encryption to prevent the site admins from reading messages.
+ Order details and addresses are stored only for as long as needed.
+ Information is not accessible to anyone other that the site admins.