diff --git a/Cargo.lock b/Cargo.lock index b6a4366..8e31f94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -266,6 +266,19 @@ dependencies = [ "syn", ] +[[package]] +name = "async-tungstenite" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5c45a0dd44b7e6533ac4e7acc38ead1a3b39885f5bbb738140d30ea528abc7c" +dependencies = [ + "futures-io", + "futures-util", + "log", + "pin-project", + "tungstenite", +] + [[package]] name = "atomic-waker" version = "1.0.0" @@ -446,6 +459,12 @@ version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +[[package]] +name = "bytes" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" + [[package]] name = "cache-padded" version = "1.1.1" @@ -478,6 +497,8 @@ name = "charcuterie" version = "0.1.0" dependencies = [ "async-std", + "async-tungstenite", + "futures", "glob", "handlebars", "log", @@ -728,6 +749,27 @@ dependencies = [ "web-sys", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.5" @@ -735,6 +777,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -743,6 +786,17 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" +[[package]] +name = "futures-executor" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.5" @@ -776,6 +830,12 @@ dependencies = [ "syn", ] +[[package]] +name = "futures-sink" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc" + [[package]] name = "futures-task" version = "0.3.5" @@ -801,9 +861,13 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" dependencies = [ + "futures-channel", "futures-core", + "futures-io", "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project", "pin-utils", "proc-macro-hack", @@ -925,6 +989,17 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549" +[[package]] +name = "http" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-types" version = "2.4.0" @@ -976,6 +1051,15 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6854dd77ddc4f9ba1a448f487e27843583d407648150426a30c2ea3a2c39490a" +[[package]] +name = "input_buffer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19a8a95243d5a0398cae618ec29477c6e3cb631152be5c19481f80bc71559754" +dependencies = [ + "bytes", +] + [[package]] name = "itoa" version = "0.4.6" @@ -1257,7 +1341,7 @@ checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" dependencies = [ "maplit", "pest", - "sha-1", + "sha-1 0.8.2", ] [[package]] @@ -1595,6 +1679,19 @@ dependencies = [ "opaque-debug 0.2.3", ] +[[package]] +name = "sha-1" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170a36ea86c864a3f16dd2687712dd6646f7019f301e57537c7f4dc9f5916770" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpuid-bool", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + [[package]] name = "sha1" version = "0.6.0" @@ -1850,6 +1947,25 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" +[[package]] +name = "tungstenite" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0308d80d86700c5878b9ef6321f020f29b1bb9d5ff3cab25e75e23f3a492a23" +dependencies = [ + "base64", + "byteorder", + "bytes", + "http", + "httparse", + "input_buffer", + "log", + "rand", + "sha-1 0.9.1", + "url", + "utf-8", +] + [[package]] name = "typenum" version = "1.12.0" @@ -1908,6 +2024,12 @@ dependencies = [ "serde", ] +[[package]] +name = "utf-8" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" + [[package]] name = "vec-arena" version = "0.5.2" diff --git a/Cargo.toml b/Cargo.toml index f1896d1..2e694cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,8 @@ edition = "2018" [dependencies] async-std = { version = "~1.6.1", features = ["attributes"] } +async-tungstenite = "~0.8.0" +futures = "~0.3.5" glob = "~0.3.0" handlebars = { version = "~3.4.0", features = ["dir_source"] } log = "~0.4.11" diff --git a/assets/board.png b/assets/board.png new file mode 100644 index 0000000..2dc073f Binary files /dev/null and b/assets/board.png differ diff --git a/sounds/boo.wav b/sounds/boo.wav deleted file mode 100644 index ce4c3da..0000000 Binary files a/sounds/boo.wav and /dev/null differ diff --git a/src/main.rs b/src/main.rs index cf7cf9f..751f0d8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,33 +2,53 @@ extern crate serde_json; use async_std::task; +use async_std::net::{TcpListener, TcpStream}; +use futures::prelude::*; use glob::glob; use handlebars::Handlebars; use log::*; use rodio::Source; +use serde::Deserialize; use tide::{Body, Request, StatusCode}; use std::fs::File; use std::io::BufReader; +#[derive(Debug, Deserialize)] +struct Query { + admin: String, +} async fn index(req: Request<()>) -> Result { let mut hb = Handlebars::new(); - hb.register_templates_directory(".hbs", "views") - .expect("Failed to register templates"); + + if let Err(failure) = hb.register_templates_directory(".hbs", "views") { + error!("Failed to render: {:?}", failure); + return Err(tide::Error::from_str(StatusCode::InternalServerError, "Could not render templates")) + } + + let mut admin = false; + if let Ok(query) = req.query::() { + info!("admin: {:?}", query); + admin = query.admin == "rtyler"; + } let mut sounds = vec![]; for sound in glob("sounds/*.wav").expect("Failed to glob sounds") { if let Ok(sound) = sound { if let Some(name) = sound.as_path().file_stem() { - sounds.push(name.to_os_string().into_string().unwrap()); + // factory whistle is a special admin only sound ^_^ + if name != "factorywhistle" { + sounds.push(name.to_os_string().into_string().unwrap()); + } } } } info!("sounds: {:?}", sounds); - let view = hb.render("index", &json!({"sounds": sounds})) + let view = hb.render("index", + &json!({"sounds": sounds, "admin" : admin})) .expect("Failed to render"); let mut body = Body::from_string(view); body.set_mime("text/html"); @@ -48,6 +68,24 @@ async fn play(req: Request<()>) -> tide::Result { } } +async fn handle_websocket(stream: TcpStream) { + let addr = stream + .peer_addr() + .expect("connected streams should have a peer address"); + info!("Peer address: {}", addr); + + let ws_stream = async_tungstenite::accept_async(stream) + .await + .expect("Error during the websocket handshake occurred"); + + info!("New WebSocket connection: {}", addr); + + let (write, read) = ws_stream.split(); + read.forward(write) + .await + .expect("Failed to forward message") +} + #[async_std::main] async fn main() -> Result<(), tide::Error> { pretty_env_logger::init(); @@ -55,6 +93,19 @@ async fn main() -> Result<(), tide::Error> { let mut app = tide::new(); app.at("/play/:sound").post(play); app.at("/").get(index); + app.at("/assets").serve_dir("assets/"); + + task::spawn(async move { + let addr = "0.0.0.0:9078"; + // Create the event loop and TCP listener we'll accept connections on. + let try_socket = TcpListener::bind(&addr).await; + let listener = try_socket.expect("Failed to bind"); + info!("Listening on: {}", addr); + + while let Ok((stream, _)) = listener.accept().await { + task::spawn(handle_websocket(stream)); + } + }); Ok(app.listen("0.0.0.0:9077").await?) } diff --git a/views/index.hbs b/views/index.hbs index 2c1392f..1787ebf 100644 --- a/views/index.hbs +++ b/views/index.hbs @@ -1,16 +1,142 @@ Charcuterie + + - A sound board for Meet, get it? +
+
+ +
+ A sound board for Meet, get it? +
- {{#each sounds}} -
- -
- {{/each}} +
+
+
+
+ + +
+
+
+ + + + {{#if admin}} +
+ +
+ {{else}} + {{/if}} +