feat(contact-me): added webhook integration into contact me

This commit is contained in:
darkicewolf50 2025-05-12 17:22:18 -06:00
parent 4f5eff6cdb
commit 3fa74f8fd0
4 changed files with 423 additions and 74 deletions

311
Cargo.lock generated
View File

@ -402,7 +402,7 @@ dependencies = [
"cocoa-foundation 0.1.2",
"core-foundation 0.9.4",
"core-graphics 0.23.2",
"foreign-types",
"foreign-types 0.5.0",
"libc",
"objc",
]
@ -418,7 +418,7 @@ dependencies = [
"cocoa-foundation 0.2.0",
"core-foundation 0.10.0",
"core-graphics 0.24.0",
"foreign-types",
"foreign-types 0.5.0",
"libc",
"objc",
]
@ -571,7 +571,7 @@ dependencies = [
"bitflags 1.3.2",
"core-foundation 0.9.4",
"core-graphics-types 0.1.3",
"foreign-types",
"foreign-types 0.5.0",
"libc",
]
@ -584,7 +584,7 @@ dependencies = [
"bitflags 2.9.0",
"core-foundation 0.10.0",
"core-graphics-types 0.2.0",
"foreign-types",
"foreign-types 0.5.0",
"libc",
]
@ -1310,6 +1310,15 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "encoding_rs"
version = "0.8.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
dependencies = [
"cfg-if",
]
[[package]]
name = "endi"
version = "1.1.0"
@ -1446,6 +1455,15 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared 0.1.1",
]
[[package]]
name = "foreign-types"
version = "0.5.0"
@ -1453,7 +1471,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
dependencies = [
"foreign-types-macros",
"foreign-types-shared",
"foreign-types-shared 0.3.1",
]
[[package]]
@ -1467,6 +1485,12 @@ dependencies = [
"syn 2.0.100",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "foreign-types-shared"
version = "0.3.1"
@ -1955,6 +1979,25 @@ dependencies = [
"syn 2.0.100",
]
[[package]]
name = "h2"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5"
dependencies = [
"atomic-waker",
"bytes",
"fnv",
"futures-core",
"futures-sink",
"http",
"indexmap 2.9.0",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "half"
version = "2.6.0"
@ -2079,6 +2122,7 @@ dependencies = [
"bytes",
"futures-channel",
"futures-util",
"h2",
"http",
"http-body",
"httparse",
@ -2089,6 +2133,39 @@ dependencies = [
"want",
]
[[package]]
name = "hyper-rustls"
version = "0.27.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2"
dependencies = [
"futures-util",
"http",
"hyper",
"hyper-util",
"rustls",
"rustls-pki-types",
"tokio",
"tokio-rustls",
"tower-service",
]
[[package]]
name = "hyper-tls"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
dependencies = [
"bytes",
"http-body-util",
"hyper",
"hyper-util",
"native-tls",
"tokio",
"tokio-native-tls",
"tower-service",
]
[[package]]
name = "hyper-util"
version = "0.1.11"
@ -2671,6 +2748,23 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "native-tls"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e"
dependencies = [
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]]
name = "ndk"
version = "0.9.0"
@ -2962,6 +3056,50 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "openssl"
version = "0.10.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da"
dependencies = [
"bitflags 2.9.0",
"cfg-if",
"foreign-types 0.3.2",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
]
[[package]]
name = "openssl-probe"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
[[package]]
name = "openssl-sys"
version = "0.9.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "option-ext"
version = "0.2.0"
@ -3043,6 +3181,8 @@ name = "personal_site"
version = "1.0.0"
dependencies = [
"dioxus",
"reqwest",
"serde_json",
]
[[package]]
@ -3490,26 +3630,34 @@ checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb"
dependencies = [
"base64",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-rustls",
"hyper-tls",
"hyper-util",
"ipnet",
"js-sys",
"log",
"mime",
"mime_guess",
"native-tls",
"once_cell",
"percent-encoding",
"pin-project-lite",
"rustls-pemfile",
"serde",
"serde_json",
"serde_urlencoded",
"sync_wrapper",
"system-configuration",
"tokio",
"tokio-native-tls",
"tokio-util",
"tower",
"tower-service",
@ -3544,6 +3692,20 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "ring"
version = "0.17.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
dependencies = [
"cc",
"cfg-if",
"getrandom 0.2.15",
"libc",
"untrusted",
"windows-sys 0.52.0",
]
[[package]]
name = "rustc-demangle"
version = "0.1.24"
@ -3591,6 +3753,48 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "rustls"
version = "0.23.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321"
dependencies = [
"once_cell",
"rustls-pki-types",
"rustls-webpki",
"subtle",
"zeroize",
]
[[package]]
name = "rustls-pemfile"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "rustls-pki-types"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
dependencies = [
"zeroize",
]
[[package]]
name = "rustls-webpki"
version = "0.103.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7149975849f1abb3832b246010ef62ccc80d3a76169517ada7188252b9cfb437"
dependencies = [
"ring",
"rustls-pki-types",
"untrusted",
]
[[package]]
name = "rustversion"
version = "1.0.20"
@ -3612,12 +3816,44 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "schannel"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "security-framework"
version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [
"bitflags 2.9.0",
"core-foundation 0.9.4",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "selectors"
version = "0.22.0"
@ -4003,6 +4239,12 @@ dependencies = [
"quote",
]
[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "1.0.109"
@ -4045,6 +4287,27 @@ dependencies = [
"syn 2.0.100",
]
[[package]]
name = "system-configuration"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
dependencies = [
"bitflags 2.9.0",
"core-foundation 0.9.4",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "system-deps"
version = "6.2.2"
@ -4234,6 +4497,26 @@ dependencies = [
"syn 2.0.100",
]
[[package]]
name = "tokio-native-tls"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
dependencies = [
"native-tls",
"tokio",
]
[[package]]
name = "tokio-rustls"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
dependencies = [
"rustls",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.14"
@ -4458,6 +4741,12 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "url"
version = "2.5.4"
@ -4500,6 +4789,12 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version-compare"
version = "0.2.0"
@ -5413,6 +5708,12 @@ dependencies = [
"synstructure",
]
[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
[[package]]
name = "zerovec"
version = "0.10.4"

View File

@ -5,9 +5,10 @@ authors = ["darkicewolf50 <brock.tomlinson@ucalgary.ca>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dioxus = { version = "0.6.0", features = ["router"] }
reqwest = { version = "0.12.15", features = ["json"] }
serde_json = "1"
[features]
default = ["web"]

View File

@ -15,21 +15,14 @@
border-radius: var(--card-border-radius);
flex-direction: column;
justify-content: center;
margin: 2svh 0.5svw;
padding: 2svh 1svw;
max-width: 600px;
}
#ContactMe p {
margin: 2svh 2svw;
padding: 0svh 2svw;
}
#contact-me {
display: flex;
justify-content: center;
flex-direction: column;
background-color: transparent;
border-radius: 0px;
margin: 2svh 0.5svw;
padding: 0svh 1svw;
margin: 2svh 0svw;
padding: 0svh 0svw;
}
#contact-me input {
@ -66,16 +59,6 @@
border-color: transparent;
}
#ContactMe form {
display: flex;
justify-content: center;
flex-direction: column;
background-color: transparent;
border-radius: 0px;
margin: 2svh 0.5svw;
padding: 0svh 1svw;
}
#ContactMe input {
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);

View File

@ -1,6 +1,8 @@
use std::collections::HashMap;
use reqwest::Client;
use serde_json;
use dioxus::{logger::tracing, prelude::*};
// use dioxus::logger::tracing;
use dioxus::prelude::*;
use crate::views::Contact;
@ -8,18 +10,15 @@ const CONTACTME_CSS: Asset = asset!("/assets/styling/contactme.css");
#[component]
pub fn ContactMe() -> Element {
let mut pre_form: Signal<HashMap<&'static str, String>> = use_signal(|| {
HashMap::from([
("Name", "".to_string()),
("Email", "".to_string()),
("Message", "".to_string()),
])
});
let mut contact_me_name = use_signal(|| String::new());
let mut contact_me_email = use_signal(|| String::new());
let mut contact_me_message = use_signal(|| String::new());
let mut error_box_message: Signal<String> = use_signal(|| "".to_string());
let mut _error_box_message = use_signal(|| String::new());
rsx! {
document::Link { rel: "stylesheet", href: CONTACTME_CSS }
title { "Brock Tomlinson - Contact" }
div { id: "ContactMe",
div {
h2 { "Get in Touch" }
@ -29,46 +28,111 @@ pub fn ContactMe() -> Element {
}
}
div {
div { id: "contact-me",
// div { id: "contact-me",
label { "Name" }
input {
oninput: move |event| {
pre_form.write().insert("Name", event.value());
contact_me_name.set(event.value());
},
}
label { "Email" }
input {
r#type: "email",
oninput: move |event| {
pre_form.write().insert("Email", event.value());
contact_me_email.set(event.value());
},
}
label { "Message" }
textarea {
oninput: move |event| {
pre_form.write().insert("Message", event.value());
contact_me_message.set(event.value());
},
}
p { "{error_box_message}" }
p { "{_error_box_message}" }
button {
r#type: "submit",
onclick: move |_| tracing::info!("Clicked!\n{:?}", pre_form),
onclick: move |_| async move {
send_message(
contact_me_name(),
contact_me_email(),
contact_me_message(),
_error_box_message,
)
.await
},
"Submit"
}
}
// }
}
}
Contact {}
}
}
// onsubmit:move |event| { log::info!("Submitted! {event:?}"),
// FormEvent {
// value: "NameEmailMessageSubmit",
// values: {
// "name": FormValue(["asdasd"]),
// "message": FormValue(["asdads"]),
// "email": FormValue(["adasdad@asdasd.asdads"])
// },
// valid: false
// }
async fn send_message(name: String, email: String, message: String, mut recived: Signal<String>) {
if name == "".to_string() && email == "".to_string() && message == "".to_string() {
recived.set("Please fill fill out the form first".to_string());
return ();
} else if name == "".to_string() {
recived.set("Please fill in your name so I know who I am contacting".to_string());
return ();
} else if email == "".to_string() {
recived.set("Please fill in your email so I can get into contact".to_string());
return ();
} else if message == "".to_string() {
recived.set("Please write a message so I know why you wanted to be in contact".to_string());
return ();
}
if is_valid_email_basic(&email) == false {
recived.set("Please write a vaild email".to_string());
return ();
}
let json_to_send = serde_json::json!({
"content": format!("***New Message***\n*Name*: {name}\n*Email*: [{email}](mailto:{email})\n*Message*: {message}")
});
let client = Client::new();
let res = client
.post("https://discord.com/api/webhooks/1371617469281861772/uARm18pvzzs4DVNLSYNYCyl7CQk_7eglqGmBabQASow2L7NHgGRHzQhkSAKaOIZmLnn1")
.json(&json_to_send)
.send()
.await;
match res {
Ok(_) => {
recived.set("Sent Sucessfully".to_string());
}
Err(_) => {
recived.set("An Error Occured".to_string());
}
}
}
fn is_valid_email_basic(email: &str) -> bool {
// Find the position of '@'
if let Some(at_pos) = email.find('@') {
// Ensure there's only one '@'
if email.rfind('@') != Some(at_pos) {
return false;
}
// Split into local and domain parts
let local = &email[..at_pos];
let domain = &email[at_pos + 1..];
// Check both parts are non-empty
if local.is_empty() || domain.is_empty() {
return false;
}
// Check domain contains at least one '.' and it's not at the start or end
if let Some(dot_pos) = domain.find('.') {
// '.' must not be at the beginning or end of the domain
if dot_pos == 0 || dot_pos == domain.len() - 1 {
return false;
}
return true;
}
}
false
}