diff --git a/Cargo.lock b/Cargo.lock index 7a2aa5d..eea9acc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,6 +19,15 @@ dependencies = [ "version_check", ] +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -40,6 +49,23 @@ version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" +[[package]] +name = "arc-swap" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" + +[[package]] +name = "async-rustls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93b21a03b7c21702a0110f9f8d228763a533570deb376119042dabf33c37a01a" +dependencies = [ + "futures-io", + "rustls", + "webpki", +] + [[package]] name = "async-trait" version = "0.1.64" @@ -66,6 +92,18 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "awaitdrop" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771051cdc7eec2dc1b23fbf870bb7fbb89136fe374227c875e377f1eed99a429" +dependencies = [ + "futures", + "generational-arena", + "parking_lot 0.12.1", + "slotmap", +] + [[package]] name = "axum" version = "0.6.9" @@ -206,6 +244,12 @@ version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -264,7 +308,7 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -273,7 +317,7 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-utils", ] @@ -283,7 +327,7 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-utils", ] @@ -293,7 +337,7 @@ version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -312,7 +356,7 @@ version = "4.0.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d4ba9852b42210c7538b75484f9daa0655e9a3ac04f693747bb0f02cf3cfe16" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "digest", "fiat-crypto", "packed_simd_2", @@ -327,7 +371,7 @@ version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "hashbrown", "lock_api", "once_cell", @@ -419,7 +463,7 @@ version = "0.8.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -604,6 +648,15 @@ dependencies = [ "slab", ] +[[package]] +name = "generational-arena" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d3b771574f62d0548cee0ad9057857e9fc25d7a3335f140c84f6acd0bf601" +dependencies = [ + "cfg-if 0.1.10", +] + [[package]] name = "generic-array" version = "0.14.6" @@ -620,7 +673,7 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi", ] @@ -637,6 +690,7 @@ dependencies = [ "ed25519-dalek", "hex", "hyper", + "ngrok", "opentelemetry", "opentelemetry-jaeger", "rand", @@ -750,6 +804,17 @@ dependencies = [ "digest", ] +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + [[package]] name = "http" version = "0.2.9" @@ -867,7 +932,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -956,7 +1021,7 @@ version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -969,6 +1034,12 @@ dependencies = [ "prost-types", ] +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + [[package]] name = "matchers" version = "0.1.0" @@ -1032,6 +1103,25 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "muxado" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e92b89ac3127251efde6f5a9586e5aae99468d06fcf9f133b377f58d5ed66446" +dependencies = [ + "async-trait", + "awaitdrop", + "bitflags", + "bytes", + "futures", + "pin-project", + "rand", + "thiserror", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "native-tls" version = "0.2.11" @@ -1050,6 +1140,37 @@ dependencies = [ "tempfile", ] +[[package]] +name = "ngrok" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "463eb318839cc5bae65e95b93bb9201eb442418bf2383e8359fc88f4196db826" +dependencies = [ + "arc-swap", + "async-rustls", + "async-trait", + "awaitdrop", + "axum", + "base64 0.13.1", + "bytes", + "futures", + "hostname", + "hyper", + "muxado", + "once_cell", + "parking_lot 0.12.1", + "regex", + "rustls-pemfile", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-retry", + "tokio-util", + "tracing", + "windows-sys 0.45.0", +] + [[package]] name = "nom" version = "7.1.3" @@ -1102,7 +1223,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd2523381e46256e40930512c7fd25562b9eae4812cb52078f155e87217c9d1e" dependencies = [ "bitflags", - "cfg-if", + "cfg-if 1.0.0", "foreign-types", "libc", "once_cell", @@ -1243,7 +1364,7 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1914cd452d8fccd6f9db48147b29fd4ae05bea9dc5d9ad578509f72415de282" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libm", ] @@ -1274,7 +1395,7 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "instant", "libc", "redox_syscall", @@ -1288,7 +1409,7 @@ version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", @@ -1469,10 +1590,12 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.1" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ + "aho-corasick", + "memchr", "regex-syntax", ] @@ -1487,9 +1610,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.28" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "reqwest" @@ -1729,7 +1852,7 @@ version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest", ] @@ -1740,7 +1863,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest", ] @@ -1778,6 +1901,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slotmap" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" +dependencies = [ + "version_check", +] + [[package]] name = "smallvec" version = "1.10.0" @@ -1962,7 +2094,7 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "fastrand", "redox_syscall", "rustix", @@ -1995,7 +2127,7 @@ version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", ] @@ -2104,6 +2236,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-retry" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" +dependencies = [ + "pin-project", + "rand", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.23.4" @@ -2134,6 +2277,7 @@ checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ "bytes", "futures-core", + "futures-io", "futures-sink", "pin-project-lite", "tokio", @@ -2199,7 +2343,7 @@ version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "log", "pin-project-lite", "tracing-attributes", @@ -2522,7 +2666,7 @@ version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] @@ -2547,7 +2691,7 @@ version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", diff --git a/Cargo.toml b/Cargo.toml index e11c51c..cfaaeed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,10 @@ license = "AGPL-3.0-or-later" [profile.dev.package.sqlx-macros] opt-level = 3 +[features] +default = ["ngrok"] +ngrok = ["dep:ngrok"] + [dependencies] anyhow = "1.0.70" axum = "0.6.9" @@ -44,3 +48,4 @@ url = "2.3.1" ureq = { version = "2.6.2", features = ["json"] } uuid = "1.3.0" rand = "0.8.5" +ngrok = { version = "0.11.3", features = ["axum"], optional = true } diff --git a/src/lib.rs b/src/lib.rs index 33d6378..6b904d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,13 +10,15 @@ use twilight_model::id::{marker::ApplicationMarker, Id}; pub mod database; pub mod discord; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Config { pub discord_client_id: Id, discord_client_secret: String, discord_pub_key: VerifyingKey, pub database_url: String, - pub listen_port: u16, + pub listen_port: Option, + pub ngrok_use: bool, + pub ngrok_domain: Option, } impl Config { @@ -34,7 +36,21 @@ impl Config { discord_client_secret: std::env::var("DISCORD_CLIENT_SECRET")?, discord_pub_key: VerifyingKey::from_bytes(&pub_key)?, database_url: std::env::var("DATABASE_URL")?, - listen_port: std::env::var("LISTEN_PORT")?.parse()?, + listen_port: { + if let Ok(port) = std::env::var("LISTEN_PORT") { + Some(port.parse()?) + } else { + None + } + }, + ngrok_use: { + if let Ok(ngrok_use) = std::env::var("NGROK_USE") { + ngrok_use.parse()? + } else { + false + } + }, + ngrok_domain: std::env::var("NGROK_DOMAIN").ok(), }) } diff --git a/src/main.rs b/src/main.rs index f407eb1..8d26f87 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,10 @@ use std::{net::SocketAddr, process}; +use anyhow::bail; use axum::{routing::post, Router}; +#[cfg(feature = "ngrok")] +use ngrok::{tunnel::UrlTunnel, prelude::TunnelBuilder}; use sqlx::postgres::PgPoolOptions; use tokio::signal; @@ -40,8 +43,6 @@ async fn main() -> anyhow::Result<()> { ) .init(); - let port = config.listen_port; - let pg_pool = PgPoolOptions::new() .max_connections(5) .connect(&config.database_url) @@ -50,21 +51,51 @@ async fn main() -> anyhow::Result<()> { sqlx::migrate!().run(&pg_pool).await?; register_commands(config.discord_client_id.to_owned(), config.authorization()).await?; - let state = AppState { config, pg_pool }; + let state = AppState { + config: config.clone(), + pg_pool, + }; let app = Router::new() .route("/api/discord/interactions/", post(post_interaction)) .with_state(state) .layer(TraceLayer::new_for_http()); - - let addr = SocketAddr::from(([127, 0, 0, 1], port)); - tracing::debug!("listening on {}", addr); tokio::spawn(loki_task); - axum::Server::bind(&addr) - .serve(app.into_make_service()) - .with_graceful_shutdown(shutdown_signal()) - .await?; + if config.ngrok_use { + #[cfg(feature = "ngrok")] + { + let mut tunnel_builder = ngrok::Session::builder() + .authtoken_from_env() + .connect() + .await? + .http_endpoint(); + if let Some(domain) = config.ngrok_domain { + tunnel_builder = tunnel_builder.domain(domain); + } + + let tunnel = tunnel_builder.listen().await?; + tracing::debug!("Ngrok tunnel at {:?}", tunnel.url()); + axum::Server::builder(tunnel) + .serve(app.into_make_service()) + .with_graceful_shutdown(shutdown_signal()) + .await?; + } + #[cfg(not(feature = "ngrok"))] + { + bail!("Ngrok requested, but feature ngrok wasn't enabled.") + } + } else if let Some(port) = config.listen_port { + let addr = SocketAddr::from(([127, 0, 0, 1], port)); + tracing::debug!("listening on {}", addr); + + axum::Server::bind(&addr) + .serve(app.into_make_service()) + .with_graceful_shutdown(shutdown_signal()) + .await?; + } else { + bail!("Failed to construct a builder"); + }; tracing::info!("server down");