summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock198
-rw-r--r--Cargo.toml2
-rw-r--r--assets/client.js6
-rw-r--r--conf.json.sample5
-rw-r--r--src/conn.rs62
-rw-r--r--src/ircbot.rs79
-rw-r--r--src/main.rs37
-rw-r--r--src/minesweeper.rs42
-rw-r--r--src/types.rs5
9 files changed, 284 insertions, 152 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3361e48..faee7e4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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",
diff --git a/Cargo.toml b/Cargo.toml
index f103746..5b24047 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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(' ', "&nbsp;"), name.replace(' ', "&nbsp;"), 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(' ', "&nbsp;"), name.replace(' ', "&nbsp;"), 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(' ', "&nbsp");
+ 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)]