diff options
author | stale <redkugelblitzin@gmail.com> | 2022-08-21 04:53:12 -0300 |
---|---|---|
committer | stale <redkugelblitzin@gmail.com> | 2022-08-21 04:53:12 -0300 |
commit | 5e207ab59b3d5ce2ce316d8727886aa66147f758 (patch) | |
tree | 90ede1c22d238bf3c8bf6615701bb6803147588f | |
parent | e28498c4953f2da5f56a41f3123a413efa9d9a25 (diff) |
questioning tiles and irc bot mess
-rw-r--r-- | Cargo.lock | 198 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | assets/client.js | 6 | ||||
-rw-r--r-- | conf.json.sample | 5 | ||||
-rw-r--r-- | src/conn.rs | 62 | ||||
-rw-r--r-- | src/ircbot.rs | 79 | ||||
-rw-r--r-- | src/main.rs | 37 | ||||
-rw-r--r-- | src/minesweeper.rs | 42 | ||||
-rw-r--r-- | src/types.rs | 5 |
9 files changed, 284 insertions, 152 deletions
@@ -10,9 +10,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ammonia" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5ed2509ee88cc023cccee37a6fab35826830fe8b748b3869790e7720c2c4a74" +checksum = "4b477377562f3086b7778d241786e9406b883ccfaa03557c0fe0924b9349f13a" dependencies = [ "html5ever", "maplit", @@ -69,9 +69,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "byteorder" @@ -81,9 +81,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "cc" @@ -99,9 +99,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "1079fb8528d9f9c888b1e8aa651e6e079ade467323d58f75faf1d30b1808f540" dependencies = [ "libc", ] @@ -117,9 +117,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", @@ -146,9 +146,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] @@ -191,9 +191,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "ab30e97ab6aacfe635fad58f22c2bb06c8b685f7421eb1e064a729e2a5f481fa" dependencies = [ "futures-channel", "futures-core", @@ -206,9 +206,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "2bfc52cbddcfd745bf1740338492bb0bd83d76c67b445f91c5fb29fae29ecaa1" dependencies = [ "futures-core", "futures-sink", @@ -216,15 +216,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "d2acedae88d38235936c3922476b10fced7b2b68136f5e3c03c2d5be348a1115" [[package]] name = "futures-executor" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "1d11aa21b5b587a64682c0094c2bdd4df0076c5324961a40cc3abd7f37930528" dependencies = [ "futures-core", "futures-task", @@ -233,15 +233,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "93a66fc6d035a26a3ae255a6d2bca35eda63ae4c5512bef54449113f7a1228e5" [[package]] name = "futures-macro" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "0db9cce532b0eae2ccf2766ab246f114b56b9cf6d445e00c2549fbc100ca045d" dependencies = [ "proc-macro2", "quote", @@ -250,21 +250,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "ca0bae1fe9752cf7fd9b0064c674ae63f97b37bc714d745cbde0afb7ec4e6765" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "842fc63b931f4056a24d59de13fb1272134ce261816e063e634ad0c15cdc5306" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "f0828a5471e340229c11c77ca80017937ce3c58cb788a17e5f1c2d5c485a9577" dependencies = [ "futures-channel", "futures-core", @@ -280,9 +280,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", @@ -301,9 +301,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" dependencies = [ "bytes", "fnv", @@ -320,9 +320,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "headers" @@ -408,9 +408,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.19" +version = "0.14.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f" +checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" dependencies = [ "bytes", "futures-channel", @@ -462,30 +462,24 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" [[package]] name = "js-sys" -version = "0.3.58" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" +checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" dependencies = [ "wasm-bindgen", ] [[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] name = "libc" -version = "0.2.126" +version = "0.2.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" [[package]] name = "lock_api" @@ -617,9 +611,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.12.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" [[package]] name = "opaque-debug" @@ -696,18 +690,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", @@ -740,9 +734,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" dependencies = [ "unicode-ident", ] @@ -755,9 +749,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -794,9 +788,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] @@ -840,9 +834,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "safemem" @@ -874,18 +868,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.138" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.138" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" dependencies = [ "proc-macro2", "quote", @@ -894,9 +888,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" +checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" dependencies = [ "itoa", "ryu", @@ -956,9 +950,12 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "slab" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] [[package]] name = "smallvec" @@ -1010,9 +1007,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" dependencies = [ "proc-macro2", "quote", @@ -1046,18 +1043,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" dependencies = [ "proc-macro2", "quote", @@ -1081,10 +1078,11 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.19.2" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" dependencies = [ + "autocfg", "bytes", "libc", "memchr", @@ -1181,9 +1179,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" dependencies = [ "cfg-if", "log", @@ -1193,9 +1191,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" dependencies = [ "once_cell", ] @@ -1257,9 +1255,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" [[package]] name = "unicode-normalization" @@ -1349,9 +1347,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" +checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1359,13 +1357,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" +checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -1374,9 +1372,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" +checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1384,9 +1382,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" +checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" dependencies = [ "proc-macro2", "quote", @@ -1397,15 +1395,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" +checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" [[package]] name = "web-sys" -version = "0.3.58" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" +checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -1423,7 +1421,7 @@ dependencies = [ [[package]] name = "websweeper" -version = "1.5.0" +version = "1.6.0" dependencies = [ "ammonia", "flate2", @@ -1,6 +1,6 @@ [package] name = "websweeper" -version = "1.5.0" +version = "1.6.0" authors = ["stale <stale@masba.net>"] edition = "2021" diff --git a/assets/client.js b/assets/client.js index f5558a7..e1218ba 100644 --- a/assets/client.js +++ b/assets/client.js @@ -168,7 +168,7 @@ function acceptBoard(data) { let split_board = []; for (let i = 1; i < room.board.length+1; i++) { let cur = room.board[i]; - let gamechars = /^[CFO# 1-8]+$/; + let gamechars = /^[CFQO# 1-8]+$/; if ((cur != last && gamechars.test(cur)) || cur == undefined) { let txt = room.board.substr(last_idx, i-last_idx); switch(txt[0]) { @@ -181,6 +181,10 @@ function acceptBoard(data) { case 'F': txt = `<span style="color:yellow;">${txt}</span>`; break; + case 'Q': + txt = txt.replaceAll("Q", "?"); + txt = `<span style="color:purple;">${txt}</span>`; + break; case '1': txt = `<span style="color:#0100FB;">${txt}</span>`; break; case '2': txt = `<span style="color:#027F01;">${txt}</span>`; break; diff --git a/conf.json.sample b/conf.json.sample index aaf5d8d..f6ba4e0 100644 --- a/conf.json.sample +++ b/conf.json.sample @@ -16,5 +16,10 @@ "room_slots": 16, "form_size": 4096, "inbound_packet_size": 2048 + }, + + "irc": { + "server": "0.0.0.0", + "port": 6697 } } diff --git a/src/conn.rs b/src/conn.rs index 2b6ee80..c8a0a82 100644 --- a/src/conn.rs +++ b/src/conn.rs @@ -7,6 +7,7 @@ use tokio::sync::RwLock; use futures::{SinkExt, TryStreamExt, StreamExt, stream::SplitStream}; use warp::ws::{ WebSocket, Message }; use crate::livepos; +use crate::ircbot; pub async fn setup_conn(socket: WebSocket, addr: SocketAddr, rinfo: (RoomId,Arc<RwLock<Room>>), max_in: usize) { let (room_id, room) = rinfo; @@ -61,9 +62,9 @@ pub async fn setup_conn(socket: WebSocket, addr: SocketAddr, rinfo: (RoomId,Arc< pub async fn drive_conn(conn: (Conn, SplitStream<WebSocket>), rinfo: (RoomId, Arc<RwLock<Room>>), max_in: usize) { let (conn, mut incoming) = conn; let (room_id, room) = rinfo; - let (players, cmd_tx, pos_tx, room_conf) = { + let (players, cmd_tx, pos_tx, irc_tx, room_conf) = { let room = room.read().await; - (room.players.clone(), room.cmd_stream.clone(), room.pos_stream.clone(), room.conf.clone()) + (room.players.clone(), room.cmd_stream.clone(), room.pos_stream.clone(), room.irc_stream.clone(), room.conf.clone()) }; while let Ok(cmd) = incoming.try_next().await { if let Some(cmd) = cmd { @@ -144,33 +145,42 @@ pub async fn drive_conn(conn: (Conn, SplitStream<WebSocket>), rinfo: (RoomId, Ar if n.is_empty() { def } else { n } } }; - println!("{room_id} I: registered \"{name}@{}\"", conn.addr); - drop(players_lock); - let uid = { - // new scope cuz paranoid bout deadlocks - room.write().await.players.write().await.insert_conn(conn.clone(), name.clone(), clr) - }; - let players_lock = players.read().await; - let me = players_lock.get(&conn.addr).unwrap(); - conn.tx.send(Message::text(format!("regack {} {} {} {}", - room_conf.name.replace(' ', " "), name.replace(' ', " "), uid, room_conf.board_conf)) - ).expect("couldn't send register ack"); - { - let msg = Message::text(format!("players {}", - jsonenc_players(players_lock.values()) - .expect("couldn't JSONify players"))); - for p in players_lock.values() { - if let Err(e) = p.conn.tx.send(msg.clone()) { - println!("{room_id} E: couldn't dump players for {me}: {e}"); + let (nameq_tx, nameq_rx) = tokio::sync::oneshot::channel(); + irc_tx.send(ircbot::IrcCmd::NameTakenQuery(name.clone(), nameq_tx)).expect("couldn't check for name collision"); + + if nameq_rx.await.unwrap() { + println!("{room_id} I: name collision \"{name}@{}\"", conn.addr); + conn.tx.send(Message::text("namecoll")).expect("couldn't send name collision report"); + } else { + println!("{room_id} I: registered \"{name}@{}\"", conn.addr); + drop(players_lock); + let uid = { + // new scope cuz paranoid bout deadlocks + room.write().await.players.write().await.insert_conn(conn.clone(), name.clone(), clr) + }; + let players_lock = players.read().await; + let me = players_lock.get(&conn.addr).unwrap(); + conn.tx.send(Message::text(format!("regack {} {} {} {}", + room_conf.name.replace(' ', " "), name.replace(' ', " "), uid, room_conf.board_conf)) + ).expect("couldn't send register ack"); + + { + let msg = Message::text(format!("players {}", + jsonenc_players(players_lock.values()) + .expect("couldn't JSONify players"))); + for p in players_lock.values() { + if let Err(e) = p.conn.tx.send(msg.clone()) { + println!("{room_id} E: couldn't dump players for {me}: {e}"); + } } } - } - if let Err(e) = pos_tx.send(livepos::Req { id: uid, data: livepos::ReqData::StateDump }) { - println!("{room_id} E: couldn't request position dump for {me}: {e}"); - } - if let Err(e) = cmd_tx.send(MetaMove::StateDump) { - println!("{room_id} E: couldn't request game dump for {me}: {e}"); + if let Err(e) = pos_tx.send(livepos::Req { id: uid, data: livepos::ReqData::StateDump }) { + println!("{room_id} E: couldn't request position dump for {me}: {e}"); + } + if let Err(e) = cmd_tx.send(MetaMove::StateDump) { + println!("{room_id} E: couldn't request game dump for {me}: {e}"); + } } } } diff --git a/src/ircbot.rs b/src/ircbot.rs new file mode 100644 index 0000000..b61e951 --- /dev/null +++ b/src/ircbot.rs @@ -0,0 +1,79 @@ +//use irc::client::prelude::*; +use crate::types::{RoomConf, CmdTx}; +use tokio::sync::mpsc as tokio_mpsc; +use serde::Deserialize; +//use futures::prelude::*; + +#[derive(Debug)] +pub enum IrcCmd { + NameTakenQuery(String, tokio::sync::oneshot::Sender<bool>), + GameWin(String), + GameLose(String), +} + +pub type IrcCmdTx = tokio_mpsc::UnboundedSender<IrcCmd>; + +#[derive(Deserialize, Clone)] +pub struct IrcConf { + pub server: String, + pub port: u16, +} + +pub async fn manage_irc_channel(_irc_conf: IrcConf, _room_conf: RoomConf, _game_tx: CmdTx, mut irc_rx: tokio_mpsc::UnboundedReceiver<IrcCmd>) { + // turns out none of the irc libs i tried worked and i lost interest + // + // let channel_name = format!("#mines-{}", room_conf.name); + // let bot_name = format!("mines-bot-{}", room_conf.name); + // let config = Config { + // nickname: Some(bot_name.clone()), + // username: Some(bot_name.clone()), + // realname: Some(bot_name.clone()), + // server: Some(irc_conf.server), + // port: Some(irc_conf.port), + // encoding: Some("UTF-8".to_string()), + // channels: vec![channel_name.clone()], + // umodes: Some("+B-x".to_string()), + // user_info: Some("websweeper channel manager bot".to_string()), + // use_tls: Some(true), + // ping_time: Some(20), + // ping_timeout: Some(15), + // ..Default::default() + // }; + + // let mut client = Client::from_config(config).await.expect("couldn't create an irc client"); + // client.identify().expect("couldn't identify irc bot"); + + // println!("irc bot {:#?}", client); + + // if !room_conf.public { + // client.send_mode(&channel_name, &[Mode::Plus(ChannelMode::Secret, None)]).expect("couldn't set irc channel mode"); + // } + // client.send_mode(&channel_name, + // &[Mode::Plus(ChannelMode::Limit, Some(room_conf.player_cap.to_string()))] + // ).expect("couldn't set irc channel mode"); + + while let Some(req) = irc_rx.recv().await { + match req { + IrcCmd::NameTakenQuery(_nick, res_tx) => { + // let taken: bool = client.list_users(&channel_name) + // .and_then(|userlist| { + // userlist.iter().position(|u| u.get_nickname() == nick) + // }).is_some(); + // res_tx.send(taken).unwrap(); + res_tx.send(false).unwrap(); + }, + IrcCmd::GameWin(_nick) => { + // println!("irc {nick} win"); + // if let Err(e) = client.send(Command::PRIVMSG(channel_name.clone(), format!("You win! {nick} made the winning move."))) { + // println!("couldn't send irc win message: {e}"); + // } + }, + IrcCmd::GameLose(_nick) => { + // println!("irc {nick} lose"); + // if let Err(e) = client.send(Command::PRIVMSG(channel_name.clone(), format!("You win! {nick} made the winning move."))) { + // println!("couldn't send irc lose message: {e}"); + // } + }, + } + } +} diff --git a/src/main.rs b/src/main.rs index 0c81844..29a847c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,7 @@ mod types; mod livepos; mod conn; mod minesweeper; +mod ircbot; use types::*; const CONF_FILE: &str = "./conf.json"; @@ -42,6 +43,7 @@ struct Conf { pub paths: ConfPaths, pub server: ConfServer, pub limits: ConfLimits, + pub irc: ircbot::IrcConf, } fn main() -> Result<(), Box<dyn Error>> { @@ -215,7 +217,7 @@ async fn tokio_main(conf: Conf) -> Result<(), Box<dyn Error>> { // If a move is made, broadcast new board, else just send current board type MoveStreamHandles = (tokio::sync::mpsc::UnboundedSender<MetaMove>, tokio::sync::mpsc::UnboundedReceiver<MetaMove>); -async fn gameloop(moves: MoveStreamHandles, players: Arc<RwLock<PlayerMap>>, bconf: minesweeper::BoardConf) { +async fn gameloop(moves: MoveStreamHandles, irc_tx: ircbot::IrcCmdTx, players: Arc<RwLock<PlayerMap>>, bconf: minesweeper::BoardConf) { // FIXME: push new board if and only if there aren't any remaining commands in the queue use minesweeper::*; use flate2::{ Compression, write::DeflateEncoder }; @@ -245,10 +247,20 @@ async fn gameloop(moves: MoveStreamHandles, players: Arc<RwLock<PlayerMap>>, bco board_encoder.write_all(&game.board.render()).unwrap(); let compressed_board = board_encoder.finish().unwrap(); let mut reply = vec![Message::binary(compressed_board)]; - let lpname = final_player_name.as_deref().unwrap_or("unknown player").replace(' ', " "); + let lpname = final_player_name.as_deref().unwrap_or("unknown player"); match game.phase { - Phase::Win => { reply.push(Message::text(format!("win {lpname}"))); }, - Phase::Die => { reply.push(Message::text(format!("lose {lpname}"))); }, + Phase::Win => { + reply.push(Message::text(format!("win {lpname}"))); + if let Err(e) = irc_tx.send(ircbot::IrcCmd::GameWin(lpname.to_string())) { + println!("couldn't send irc win message: {e}"); + } + }, + Phase::Die => { + reply.push(Message::text(format!("lose {lpname}"))); + if let Err(e) = irc_tx.send(ircbot::IrcCmd::GameLose(lpname.to_string())) { + println!("couldn't send irc lose message: {e}"); + } + }, _ => (), } let peers = players.read().await; @@ -336,18 +348,21 @@ fn room_from_form(uid: RoomId, rinfo: &HashMap<String,String>, conf: &Conf) -> R let players = Arc::new(RwLock::new(PlayerMap::default())); - let (cmd_tx, cmd_rx) = tokio::sync::mpsc::unbounded_channel(); - let game_handle = tokio::spawn(gameloop((cmd_tx.clone(), cmd_rx), players.clone(), board_conf)); - - let (pos_tx, pos_rx) = tokio::sync::mpsc::unbounded_channel(); - let livepos_handle = tokio::spawn(livepos::livepos(players.clone(), pos_rx)); - let room_conf = RoomConf { name, player_cap: limit, public, board_conf, }; + + let (cmd_tx, cmd_rx) = tokio::sync::mpsc::unbounded_channel(); + let (irc_tx, irc_rx) = tokio::sync::mpsc::unbounded_channel(); + let (pos_tx, pos_rx) = tokio::sync::mpsc::unbounded_channel(); + + let irc_handle = tokio::spawn(ircbot::manage_irc_channel(conf.irc.clone(), room_conf.clone(), cmd_tx.clone(), irc_rx)); + let game_handle = tokio::spawn(gameloop((cmd_tx.clone(), cmd_rx), irc_tx.clone(), players.clone(), board_conf)); + let livepos_handle = tokio::spawn(livepos::livepos(players.clone(), pos_rx)); + Ok((Room { conf: room_conf, players, @@ -355,6 +370,8 @@ fn room_from_form(uid: RoomId, rinfo: &HashMap<String,String>, conf: &Conf) -> R cmd_stream: cmd_tx, livepos_driver: livepos_handle, pos_stream: pos_tx, + irc_driver: irc_handle, + irc_stream: irc_tx, }, public)) } else { Err(warp::reject::custom(BadFormData)) } } diff --git a/src/minesweeper.rs b/src/minesweeper.rs index 1e95f0d..c733d19 100644 --- a/src/minesweeper.rs +++ b/src/minesweeper.rs @@ -7,10 +7,13 @@ use serde::Serialize; const HIDDEN_BIT: u8 = 1 << 7; pub const FLAGGED_BIT: u8 = 1 << 6; -const CORRECT_BIT: u8 = 1 << 5; // grading for a rightly flagged mine +const SPECIAL_BIT: u8 = 1 << 5; // grading for a rightly flagged mine, or the question flag // all the bits that aren't flags -const TILE_NUMBITS: u8 = !(HIDDEN_BIT | FLAGGED_BIT | CORRECT_BIT); -const MINED: u8 = HIDDEN_BIT | TILE_NUMBITS; +const NUMBITS: u8 = !(HIDDEN_BIT | FLAGGED_BIT | SPECIAL_BIT); +const MINED: u8 = HIDDEN_BIT | NUMBITS; +const QUESTION: u8 = FLAGGED_BIT | SPECIAL_BIT; +const CORRECT: u8 = MINED | SPECIAL_BIT; + #[derive(PartialEq)] pub enum Phase { SafeFirstMove, @@ -182,7 +185,9 @@ impl Board { while let Some(pos) = queue.pop() { let off = pos.rel_offset_unchecked(&self); let c = &mut self.data[off]; - if *c & HIDDEN_BIT > 0 { + // don't reveal the already revealed or the flagged, but reveal the questionings + let unrevealable = (*c & FLAGGED_BIT > 0) ^ (*c & SPECIAL_BIT > 0); + if *c & HIDDEN_BIT > 0 && !unrevealable { *c = unhide(*c); self.hidden_tiles -= 1; if is_mine(*c) { return true; } @@ -198,7 +203,7 @@ impl Board { if 1 <= count && count <= 8 { let mut neighs = self.neighs(pos); let total_neighs = neighs.len(); - neighs.retain(|pos| self.data[pos.rel_offset_unchecked(&self)] & FLAGGED_BIT == 0); + neighs.retain(|pos| self.data[pos.rel_offset_unchecked(&self)] & (FLAGGED_BIT | SPECIAL_BIT) != FLAGGED_BIT); if (total_neighs - neighs.len()) == count { for pos in neighs.iter() { if self.flood_reveal(*pos) { @@ -223,14 +228,23 @@ impl Board { pub fn grade(&mut self) { for i in &mut self.data { - if *i == TILE_NUMBITS | FLAGGED_BIT | HIDDEN_BIT { - *i |= CORRECT_BIT; + if *i == MINED | FLAGGED_BIT { + *i = CORRECT; } } } pub fn flag(&mut self, pos: BoardPos) { if let Some(off) = pos.rel_offset(&self) { - self.data[off] ^= FLAGGED_BIT; + const TOPBIT_MASK: u8 = !(NUMBITS | HIDDEN_BIT); + let c = &mut self.data[off]; + if *c & HIDDEN_BIT > 0 { + let new_topbits = match *c & (TOPBIT_MASK) { + FLAGGED_BIT => QUESTION, + QUESTION => 0, + _ => FLAGGED_BIT, + } | HIDDEN_BIT; + *c = (*c & NUMBITS) | new_topbits; + } } } @@ -240,13 +254,15 @@ impl Board { for x in 0..self.width.get() { let pos: BoardPos = (x,y).try_into().unwrap(); let c = &self.data[pos.rel_offset_unchecked(&self)]; + const QUESTION_MASK: u8 = SPECIAL_BIT | FLAGGED_BIT; match *c { 0 => ret.push(b' '), _ if *c <= 8 => ret.push(b'0' + c), - _ if (*c & CORRECT_BIT) > 0 => ret.push(b'C'), + _ if (*c & QUESTION_MASK) == QUESTION_MASK => ret.push(b'Q'), + _ if (*c & SPECIAL_BIT) > 0 => ret.push(b'C'), _ if (*c & FLAGGED_BIT) > 0 => ret.push(b'F'), _ if (*c & HIDDEN_BIT) > 0 => ret.push(b'#'), - _ if *c == TILE_NUMBITS => ret.push(b'O'), + _ if *c == NUMBITS => ret.push(b'O'), _ => ret.push(b'?'), } } @@ -268,7 +284,7 @@ impl Board { let vacant_pos = { let v = self.data.iter() .enumerate() - .filter(|(_,val)| (*val & TILE_NUMBITS) != TILE_NUMBITS) + .filter(|(_,val)| (*val & NUMBITS) != NUMBITS) .map(|(p,_)| p) .next() .unwrap(); // there must be at least one @@ -315,10 +331,10 @@ impl<T: TryInto<u32>> TryFrom<(T,T)> for BoardPos { } pub fn is_mine(v: u8) -> bool { - (v & TILE_NUMBITS) == TILE_NUMBITS + (v & NUMBITS) == NUMBITS } pub fn unhide(tile: u8) -> u8 { - tile & !(HIDDEN_BIT | FLAGGED_BIT) + tile & NUMBITS } diff --git a/src/types.rs b/src/types.rs index a8a7742..b2bc93e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -4,7 +4,7 @@ use std::{ sync::{ Arc, atomic::{ AtomicUsize, Ordering }, - }, +}, fmt::Display, ops::{ Deref, DerefMut }, num::NonZeroUsize, @@ -14,6 +14,7 @@ use tokio::sync::RwLock; use serde::Serialize; use crate::minesweeper; use crate::livepos; +use crate::ircbot; #[derive(Debug, Serialize, Clone)] pub struct RoomConf { @@ -30,6 +31,8 @@ pub struct Room { pub cmd_stream: CmdTx, pub livepos_driver: tokio::task::JoinHandle<()>, pub pos_stream: tokio::sync::mpsc::UnboundedSender<livepos::Req>, + pub irc_driver: tokio::task::JoinHandle<()>, + pub irc_stream: tokio::sync::mpsc::UnboundedSender<ircbot::IrcCmd>, } #[derive(Debug)] |