diff --git a/src/index.html b/src/index.html
index d8fc4ce..c80e035 100644
--- a/src/index.html
+++ b/src/index.html
@@ -130,7 +130,7 @@
## Super Mario in real life
- Imagine Ready Play One, but with minimum dystopia. **Simulo** allows you to use the _Earth_ as
+ Imagine Ready Player One, but with minimum dystopia. **Simulo** allows you to use the _Earth_ as
your
game
engine!
@@ -201,13 +201,14 @@
## _Oooooooo_
Nobody knows what this project is gonna be. The creator, Josh, won't tell anyone.
-
+
diff --git a/thesandwich-backend/.gitignore b/thesandwich-backend/.gitignore
new file mode 100644
index 0000000..b7f7b51
--- /dev/null
+++ b/thesandwich-backend/.gitignore
@@ -0,0 +1,2 @@
+.env
+target/
diff --git a/thesandwich-backend/Cargo.lock b/thesandwich-backend/Cargo.lock
index 00c04e7..ff7452c 100644
--- a/thesandwich-backend/Cargo.lock
+++ b/thesandwich-backend/Cargo.lock
@@ -17,6 +17,25 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "ansi-to-html"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12e283a4fc285735ef99577e81a125f738429516161ac33977e466d0d8d40764"
+dependencies = [
+ "regex",
+ "thiserror",
+]
+
[[package]]
name = "arrayvec"
version = "0.7.6"
@@ -34,7 +53,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.101",
]
[[package]]
@@ -178,6 +197,33 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+[[package]]
+name = "color-eyre"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e1761c0e16f8883bbbb8ce5990867f4f06bf11a0253da6495a04ce4b6ef0ec"
+dependencies = [
+ "backtrace",
+ "color-spantrace",
+ "eyre",
+ "indenter",
+ "once_cell",
+ "owo-colors",
+ "tracing-error",
+]
+
+[[package]]
+name = "color-spantrace"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ddd8d5bfda1e11a501d0a7303f3bfed9aa632ebdb859be40d0fd70478ed70d5"
+dependencies = [
+ "once_cell",
+ "owo-colors",
+ "tracing-core",
+ "tracing-error",
+]
+
[[package]]
name = "core-foundation"
version = "0.9.4"
@@ -247,7 +293,25 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.101",
+]
+
+[[package]]
+name = "dotenvy"
+version = "0.15.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
+
+[[package]]
+name = "dotenvy_macro"
+version = "0.15.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb0235d912a8c749f4e0c9f18ca253b4c28cfefc1d2518096016d6e3230b6424"
+dependencies = [
+ "dotenvy",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
]
[[package]]
@@ -265,6 +329,16 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+[[package]]
+name = "eyre"
+version = "0.6.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec"
+dependencies = [
+ "indenter",
+ "once_cell",
+]
+
[[package]]
name = "fnv"
version = "1.0.7"
@@ -324,7 +398,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.101",
]
[[package]]
@@ -657,6 +731,12 @@ dependencies = [
"icu_properties",
]
+[[package]]
+name = "indenter"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
+
[[package]]
name = "indexmap"
version = "2.9.0"
@@ -689,6 +769,12 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
[[package]]
name = "libc"
version = "0.2.172"
@@ -707,6 +793,15 @@ version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
+[[package]]
+name = "matchers"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
+dependencies = [
+ "regex-automata 0.1.10",
+]
+
[[package]]
name = "matchit"
version = "0.8.4"
@@ -734,7 +829,7 @@ dependencies = [
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
- "syn",
+ "syn 2.0.101",
]
[[package]]
@@ -779,6 +874,16 @@ dependencies = [
"windows-sys 0.59.0",
]
+[[package]]
+name = "nu-ansi-term"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
+dependencies = [
+ "overload",
+ "winapi",
+]
+
[[package]]
name = "num-conv"
version = "0.1.0"
@@ -800,6 +905,18 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+[[package]]
+name = "overload"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+
+[[package]]
+name = "owo-colors"
+version = "4.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26995317201fa17f3656c36716aed4a7c81743a9634ac4c99c0eeda495db0cec"
+
[[package]]
name = "percent-encoding"
version = "2.3.1"
@@ -859,7 +976,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.101",
"version_check",
]
@@ -902,6 +1019,50 @@ dependencies = [
"getrandom",
]
+[[package]]
+name = "regex"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata 0.4.9",
+ "regex-syntax 0.8.5",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+dependencies = [
+ "regex-syntax 0.6.29",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax 0.8.5",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+
[[package]]
name = "reqwest"
version = "0.11.27"
@@ -1089,7 +1250,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.101",
]
[[package]]
@@ -1163,6 +1324,15 @@ dependencies = [
"digest",
]
+[[package]]
+name = "sharded-slab"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
+dependencies = [
+ "lazy_static",
+]
+
[[package]]
name = "shlex"
version = "1.3.0"
@@ -1206,6 +1376,17 @@ version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
[[package]]
name = "syn"
version = "2.0.101"
@@ -1237,7 +1418,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.101",
]
[[package]]
@@ -1265,9 +1446,17 @@ dependencies = [
name = "thesandwich-backend"
version = "0.1.0"
dependencies = [
+ "ansi-to-html",
"axum",
+ "color-eyre",
+ "dotenvy_macro",
"maud",
+ "serde",
"serenity",
+ "tokio",
+ "tracing",
+ "tracing-error",
+ "tracing-subscriber",
]
[[package]]
@@ -1287,7 +1476,17 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.101",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
+dependencies = [
+ "cfg-if",
+ "once_cell",
]
[[package]]
@@ -1355,7 +1554,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.101",
]
[[package]]
@@ -1456,7 +1655,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.101",
]
[[package]]
@@ -1466,6 +1665,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
dependencies = [
"once_cell",
+ "valuable",
+]
+
+[[package]]
+name = "tracing-error"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db"
+dependencies = [
+ "tracing",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "tracing-log"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
+dependencies = [
+ "log",
+ "once_cell",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
+dependencies = [
+ "matchers",
+ "nu-ansi-term",
+ "once_cell",
+ "regex",
+ "sharded-slab",
+ "smallvec",
+ "thread_local",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
]
[[package]]
@@ -1543,6 +1782,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+[[package]]
+name = "valuable"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
+
[[package]]
name = "version_check"
version = "0.9.5"
@@ -1586,7 +1831,7 @@ dependencies = [
"log",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.101",
"wasm-bindgen-shared",
]
@@ -1621,7 +1866,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.101",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -1682,6 +1927,28 @@ dependencies = [
"rustls-pki-types",
]
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
[[package]]
name = "windows-sys"
version = "0.48.0"
@@ -1866,7 +2133,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.101",
"synstructure",
]
@@ -1887,7 +2154,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.101",
]
[[package]]
@@ -1907,7 +2174,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.101",
"synstructure",
]
@@ -1947,5 +2214,5 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.101",
]
diff --git a/thesandwich-backend/Cargo.toml b/thesandwich-backend/Cargo.toml
index 1f03b1a..e927765 100644
--- a/thesandwich-backend/Cargo.toml
+++ b/thesandwich-backend/Cargo.toml
@@ -4,6 +4,14 @@ version = "0.1.0"
edition = "2024"
[dependencies]
+ansi-to-html = { version = "0.2.2", features = ["lazy-init"] }
axum = "0.8.4"
+color-eyre = "0.6.4"
+dotenvy_macro = "0.15.7"
maud = { version = "0.27.0", features = ["axum"] }
+serde = { version = "1.0.219", features = ["derive"] }
serenity = { version = "0.12.4", default-features = false, features = ["model", "rustls_backend", "http"] }
+tokio = { version = "1.45.1", features = ["rt", "rt-multi-thread", "macros"] }
+tracing = "0.1.41"
+tracing-error = "0.2.1"
+tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
diff --git a/thesandwich-backend/src/error.rs b/thesandwich-backend/src/error.rs
new file mode 100644
index 0000000..1bd5e56
--- /dev/null
+++ b/thesandwich-backend/src/error.rs
@@ -0,0 +1,56 @@
+//! # yaaxum-error
+//! Yet Another Axum Error Handler
+//!
+//! This crate uses `eyre` to capture the error,
+//! the error is then returned to the browser or
+//! whatever it is, it's then nicely formatted to
+//! a webpage using `ansi_to_html`
+
+use std::fmt::{Debug, Display};
+
+use axum::{
+ http::StatusCode,
+ response::{Html, IntoResponse},
+};
+
+pub type Result = std::result::Result;
+
+pub struct Error(pub StatusCode, pub color_eyre::eyre::Report);
+
+impl Display for Error {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.1.handler().display(self.1.as_ref(), f)
+ }
+}
+
+impl Debug for Error {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.1.handler().debug(self.1.as_ref(), f)
+ }
+}
+
+impl IntoResponse for Error {
+ fn into_response(self) -> axum::response::Response {
+ let ansi_string = format!("{:?}", self);
+ let error = ansi_to_html::convert(&ansi_string).unwrap();
+
+ (
+ self.0,
+ Html(format!(
+ "{}
",
+ error
+ )),
+ )
+ .into_response()
+ }
+}
+
+pub trait WithStatusCode {
+ fn with_status_code(self, code: StatusCode) -> Result;
+}
+
+impl WithStatusCode for std::result::Result {
+ fn with_status_code(self, code: StatusCode) -> Result {
+ self.map_err(|e| Error(code, e))
+ }
+}
diff --git a/thesandwich-backend/src/main.rs b/thesandwich-backend/src/main.rs
index e7a11a9..7bdc886 100644
--- a/thesandwich-backend/src/main.rs
+++ b/thesandwich-backend/src/main.rs
@@ -1,3 +1,67 @@
-fn main() {
- println!("Hello, world!");
+use axum::{Router, extract::Form, http::StatusCode, routing::post};
+use color_eyre::eyre::{self, Context};
+use dotenvy_macro::dotenv;
+use error::WithStatusCode;
+use serde::Deserialize;
+use serenity::all::{ExecuteWebhook, Http, Webhook};
+use tracing::instrument;
+use tracing_error::ErrorLayer;
+use tracing_subscriber::{EnvFilter, layer::SubscriberExt, util::SubscriberInitExt};
+
+mod error;
+
+const WEBHOOK: &'static str = dotenv!("WEBHOOK");
+const LISTEN_ADDR: &'static str = dotenv!("LISTEN_ADDR");
+
+#[tokio::main]
+async fn main() -> eyre::Result<()> {
+ color_eyre::install()?;
+
+ tracing_subscriber::registry()
+ .with(ErrorLayer::default())
+ .with(
+ EnvFilter::try_from_default_env()
+ .or_else(|_| EnvFilter::try_new("info"))
+ .unwrap(),
+ )
+ .with(tracing_subscriber::fmt::layer())
+ .init();
+
+ let app = Router::new().route("/api/speculate", post(speculate));
+
+ let listener = tokio::net::TcpListener::bind(LISTEN_ADDR)
+ .await
+ .wrap_err("Failed to listen on that port")?;
+ axum::serve(listener, app)
+ .await
+ .wrap_err("Failed to run axum service")?;
+ Ok(())
+}
+
+#[derive(Deserialize, Debug)]
+struct Speculation {
+ speculation: String,
+}
+
+#[instrument]
+async fn speculate(Form(speculation): Form) -> Result {
+ let discord_http = Http::new("");
+
+ let webhook = Webhook::from_url(&discord_http, WEBHOOK)
+ .await
+ .wrap_err("Failed to initialize webhook")
+ .with_status_code(StatusCode::INTERNAL_SERVER_ERROR)?;
+
+ let builder = ExecuteWebhook::new()
+ .content(speculation.speculation)
+ .username("Anonymous speculator");
+ webhook
+ .execute(&discord_http, false, builder)
+ .await
+ .wrap_err("Could not execute webhook")
+ .with_status_code(StatusCode::INTERNAL_SERVER_ERROR)?;
+
+ Ok(maud::html! {
+ p { "Speculation launched at high speed directly into our DMs" }
+ })
}