html terminal
use bot
bendn 2023-06-13
parent 33b0764 · commit 1119f97
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock929
-rw-r--r--Cargo.toml20
-rw-r--r--src/bot.rs281
-rw-r--r--src/logging.rs1
-rw-r--r--src/main.rs1
-rw-r--r--src/process.rs1
-rw-r--r--src/server.rs28
-rw-r--r--src/webhook.rs310
9 files changed, 1140 insertions, 432 deletions
diff --git a/.gitignore b/.gitignore
index ea8c4bf..df2c3c5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
/target
+*token
diff --git a/Cargo.lock b/Cargo.lock
index de1791c..ac6b57a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,6 +3,12 @@
version = 3
[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
name = "aho-corasick"
version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -21,6 +27,21 @@ dependencies = [
]
[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
name = "ansi-to-html"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -32,6 +53,12 @@ dependencies = [
]
[[package]]
+name = "anyhow"
+version = "1.0.71"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
+
+[[package]]
name = "arrayvec"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -150,6 +177,22 @@ dependencies = [
]
[[package]]
+name = "async-tungstenite"
+version = "0.17.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1b71b31561643aa8e7df3effe284fa83ab1a840e52294c5f4bd7bfd8b2becbb"
+dependencies = [
+ "futures-io",
+ "futures-util",
+ "log",
+ "pin-project-lite",
+ "tokio",
+ "tokio-rustls 0.23.4",
+ "tungstenite 0.17.3",
+ "webpki-roots",
+]
+
+[[package]]
name = "atomic-waker"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -286,6 +329,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
+name = "chrono"
+version = "0.4.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
+dependencies = [
+ "android-tzdata",
+ "iana-time-zone",
+ "num-traits",
+ "serde",
+ "winapi",
+]
+
+[[package]]
name = "concurrent-queue"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -301,16 +357,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
[[package]]
-name = "core-foundation"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
-dependencies = [
- "core-foundation-sys",
- "libc",
-]
-
-[[package]]
name = "core-foundation-sys"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -326,6 +372,15 @@ dependencies = [
]
[[package]]
+name = "crc32fast"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
name = "crossbeam-utils"
version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -356,6 +411,66 @@ dependencies = [
]
[[package]]
+name = "darling"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
+dependencies = [
+ "darling_core",
+ "darling_macro",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
+dependencies = [
+ "darling_core",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "dashmap"
+version = "5.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc"
+dependencies = [
+ "cfg-if",
+ "hashbrown",
+ "lock_api",
+ "once_cell",
+ "parking_lot_core",
+ "serde",
+]
+
+[[package]]
+name = "derivative"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
name = "derive_more"
version = "0.99.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -379,6 +494,15 @@ dependencies = [
]
[[package]]
+name = "encoding_rs"
+version = "0.8.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
name = "errno"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -386,7 +510,7 @@ checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
dependencies = [
"errno-dragonfly",
"libc",
- "windows-sys 0.48.0",
+ "windows-sys",
]
[[package]]
@@ -415,31 +539,26 @@ dependencies = [
]
[[package]]
-name = "fnv"
-version = "1.0.7"
+name = "flate2"
+version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
-
-[[package]]
-name = "foreign-types"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
dependencies = [
- "foreign-types-shared",
+ "crc32fast",
+ "miniz_oxide",
]
[[package]]
-name = "foreign-types-shared"
-version = "0.1.1"
+name = "fnv"
+version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "form_urlencoded"
-version = "1.1.0"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
+checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
dependencies = [
"percent-encoding",
]
@@ -560,9 +679,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.9"
+version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
+checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if",
"libc",
@@ -607,6 +726,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -680,23 +805,52 @@ dependencies = [
]
[[package]]
-name = "hyper-tls"
-version = "0.5.0"
+name = "hyper-rustls"
+version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
+checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7"
dependencies = [
- "bytes",
+ "http",
"hyper",
- "native-tls",
+ "rustls 0.21.1",
"tokio",
- "tokio-native-tls",
+ "tokio-rustls 0.24.1",
+]
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.57"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "windows",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
]
[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
+[[package]]
name = "idna"
-version = "0.3.0"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
+checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
dependencies = [
"unicode-bidi",
"unicode-normalization",
@@ -729,10 +883,16 @@ checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi 0.3.1",
"libc",
- "windows-sys 0.48.0",
+ "windows-sys",
]
[[package]]
+name = "ipnet"
+version = "2.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
+
+[[package]]
name = "itoa"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -764,9 +924,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.144"
+version = "0.2.146"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
[[package]]
name = "linux-raw-sys"
@@ -775,10 +935,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]]
+name = "lock_api"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
name = "log"
-version = "0.4.18"
+version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
+checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
dependencies = [
"value-bag",
]
@@ -802,6 +972,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
+name = "mime_guess"
+version = "2.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
+dependencies = [
+ "mime",
+ "unicase",
+]
+
+[[package]]
name = "minify-html"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -832,32 +1012,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
-name = "mio"
-version = "0.8.8"
+name = "miniz_oxide"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
+checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [
- "libc",
- "wasi",
- "windows-sys 0.48.0",
+ "adler",
]
[[package]]
-name = "native-tls"
-version = "0.2.11"
+name = "mio"
+version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
+checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [
- "lazy_static",
"libc",
- "log",
- "openssl",
- "openssl-probe",
- "openssl-sys",
- "schannel",
- "security-framework",
- "security-framework-sys",
- "tempfile",
+ "wasi",
+ "windows-sys",
]
[[package]]
@@ -871,73 +1042,37 @@ dependencies = [
]
[[package]]
-name = "num_cpus"
-version = "1.15.0"
+name = "num-traits"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
- "hermit-abi 0.2.6",
- "libc",
+ "autocfg",
]
[[package]]
-name = "once_cell"
-version = "1.17.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b"
-
-[[package]]
-name = "openssl"
-version = "0.10.54"
+name = "num_cpus"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69b3f656a17a6cbc115b5c7a40c616947d213ba182135b014d6051b73ab6f019"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
- "bitflags",
- "cfg-if",
- "foreign-types",
+ "hermit-abi 0.2.6",
"libc",
- "once_cell",
- "openssl-macros",
- "openssl-sys",
]
[[package]]
-name = "openssl-macros"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.18",
-]
-
-[[package]]
-name = "openssl-probe"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
-
-[[package]]
-name = "openssl-src"
-version = "111.26.0+1.1.1u"
+name = "once_cell"
+version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efc62c9f12b22b8f5208c23a7200a442b2e5999f8bdf80233852122b5a4f6f37"
-dependencies = [
- "cc",
-]
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
-name = "openssl-sys"
-version = "0.9.88"
+name = "ordered-float"
+version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2ce0f250f34a308dcfdbb351f511359857d4ed2134ba715a4eadd46e1ffd617"
+checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87"
dependencies = [
- "cc",
- "libc",
- "openssl-src",
- "pkg-config",
- "vcpkg",
+ "num-traits",
]
[[package]]
@@ -945,16 +1080,21 @@ name = "panel"
version = "0.1.0"
dependencies = [
"ansi-to-html",
+ "anyhow",
"async-std",
"axum",
"futures",
"futures-util",
"minify-html",
+ "minify-js",
"paste",
+ "poise",
+ "regex",
+ "serenity",
"strip-ansi-escapes",
+ "strum",
"tokio",
"tokio-stream",
- "webhook",
]
[[package]]
@@ -964,6 +1104,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e"
[[package]]
+name = "parking_lot"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-targets",
+]
+
+[[package]]
name = "parse-js"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -982,9 +1145,9 @@ checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
[[package]]
name = "percent-encoding"
-version = "2.2.0"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
+checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
[[package]]
name = "pin-project"
@@ -1019,10 +1182,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
-name = "pkg-config"
-version = "0.3.27"
+name = "poise"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
+checksum = "6d591af1c934c29adda172665f69b837e642d4fee85598baffb95dd98110467d"
+dependencies = [
+ "async-trait",
+ "derivative",
+ "futures-core",
+ "futures-util",
+ "log",
+ "once_cell",
+ "parking_lot",
+ "poise_macros",
+ "regex",
+ "serenity",
+ "tokio",
+]
+
+[[package]]
+name = "poise_macros"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40270099e1527efae99fdc0609d397e76310b529d4980ad38ab14d81803ca0fa"
+dependencies = [
+ "darling",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
[[package]]
name = "polling"
@@ -1037,7 +1225,7 @@ dependencies = [
"libc",
"log",
"pin-project-lite",
- "windows-sys 0.48.0",
+ "windows-sys",
]
[[package]]
@@ -1048,9 +1236,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
-version = "1.0.59"
+version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
+checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
dependencies = [
"unicode-ident",
]
@@ -1121,6 +1309,63 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
[[package]]
+name = "reqwest"
+version = "0.11.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55"
+dependencies = [
+ "base64 0.21.2",
+ "bytes",
+ "encoding_rs",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-rustls",
+ "ipnet",
+ "js-sys",
+ "log",
+ "mime",
+ "mime_guess",
+ "once_cell",
+ "percent-encoding",
+ "pin-project-lite",
+ "rustls 0.21.1",
+ "rustls-pemfile",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "tokio",
+ "tokio-rustls 0.24.1",
+ "tokio-util",
+ "tower-service",
+ "url",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "wasm-streams",
+ "web-sys",
+ "webpki-roots",
+ "winreg",
+]
+
+[[package]]
+name = "ring"
+version = "0.16.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
+dependencies = [
+ "cc",
+ "libc",
+ "once_cell",
+ "spin",
+ "untrusted",
+ "web-sys",
+ "winapi",
+]
+
+[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1137,60 +1382,87 @@ dependencies = [
[[package]]
name = "rustix"
-version = "0.37.19"
+version = "0.37.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
+checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
- "windows-sys 0.48.0",
+ "windows-sys",
]
[[package]]
-name = "rustversion"
-version = "1.0.12"
+name = "rustls"
+version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
+checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
+dependencies = [
+ "log",
+ "ring",
+ "sct",
+ "webpki",
+]
[[package]]
-name = "ryu"
-version = "1.0.13"
+name = "rustls"
+version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+checksum = "c911ba11bc8433e811ce56fde130ccf32f5127cab0e0194e9c68c5a5b671791e"
+dependencies = [
+ "log",
+ "ring",
+ "rustls-webpki",
+ "sct",
+]
[[package]]
-name = "schannel"
-version = "0.1.21"
+name = "rustls-pemfile"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3"
+checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
dependencies = [
- "windows-sys 0.42.0",
+ "base64 0.21.2",
]
[[package]]
-name = "security-framework"
-version = "2.9.1"
+name = "rustls-webpki"
+version = "0.100.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8"
+checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b"
dependencies = [
- "bitflags",
- "core-foundation",
- "core-foundation-sys",
- "libc",
- "security-framework-sys",
+ "ring",
+ "untrusted",
]
[[package]]
-name = "security-framework-sys"
-version = "2.9.0"
+name = "rustversion"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
+
+[[package]]
+name = "ryu"
+version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "sct"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
dependencies = [
- "core-foundation-sys",
- "libc",
+ "ring",
+ "untrusted",
]
[[package]]
@@ -1201,18 +1473,28 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
[[package]]
name = "serde"
-version = "1.0.163"
+version = "1.0.164"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
+checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
dependencies = [
"serde_derive",
]
[[package]]
+name = "serde-value"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
+dependencies = [
+ "ordered-float",
+ "serde",
+]
+
+[[package]]
name = "serde_derive"
-version = "1.0.163"
+version = "1.0.164"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
+checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
dependencies = [
"proc-macro2",
"quote",
@@ -1252,6 +1534,49 @@ dependencies = [
]
[[package]]
+name = "serenity"
+version = "0.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82fd5e7b5858ad96e99d440138f34f5b98e1b959ebcd3a1036203b30e78eb788"
+dependencies = [
+ "async-trait",
+ "async-tungstenite",
+ "base64 0.13.1",
+ "bitflags",
+ "bytes",
+ "cfg-if",
+ "chrono",
+ "dashmap",
+ "flate2",
+ "futures",
+ "mime",
+ "mime_guess",
+ "parking_lot",
+ "percent-encoding",
+ "reqwest",
+ "rustversion",
+ "serde",
+ "serde-value",
+ "serde_json",
+ "time",
+ "tokio",
+ "tracing",
+ "typemap_rev",
+ "url",
+]
+
+[[package]]
+name = "sha-1"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
name = "sha1"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1281,6 +1606,12 @@ dependencies = [
]
[[package]]
+name = "smallvec"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
+[[package]]
name = "socket2"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1291,6 +1622,12 @@ dependencies = [
]
[[package]]
+name = "spin"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+
+[[package]]
name = "strip-ansi-escapes"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1300,6 +1637,34 @@ dependencies = [
]
[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+[[package]]
+name = "strum"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
+dependencies = [
+ "strum_macros",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.24.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 1.0.109",
+]
+
+[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1328,19 +1693,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
-name = "tempfile"
-version = "3.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
-dependencies = [
- "cfg-if",
- "fastrand",
- "redox_syscall",
- "rustix",
- "windows-sys 0.45.0",
-]
-
-[[package]]
name = "thiserror"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1361,6 +1713,33 @@ dependencies = [
]
[[package]]
+name = "time"
+version = "0.3.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
+dependencies = [
+ "itoa",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
+
+[[package]]
+name = "time-macros"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
+dependencies = [
+ "time-core",
+]
+
+[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1386,11 +1765,12 @@ dependencies = [
"libc",
"mio",
"num_cpus",
+ "parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
- "windows-sys 0.48.0",
+ "windows-sys",
]
[[package]]
@@ -1405,12 +1785,23 @@ dependencies = [
]
[[package]]
-name = "tokio-native-tls"
-version = "0.3.1"
+name = "tokio-rustls"
+version = "0.23.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
+dependencies = [
+ "rustls 0.20.8",
+ "tokio",
+ "webpki",
+]
+
+[[package]]
+name = "tokio-rustls"
+version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
+checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
dependencies = [
- "native-tls",
+ "rustls 0.21.1",
"tokio",
]
@@ -1434,7 +1825,7 @@ dependencies = [
"futures-util",
"log",
"tokio",
- "tungstenite",
+ "tungstenite 0.18.0",
]
[[package]]
@@ -1488,10 +1879,22 @@ dependencies = [
"cfg-if",
"log",
"pin-project-lite",
+ "tracing-attributes",
"tracing-core",
]
[[package]]
+name = "tracing-attributes"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.18",
+]
+
+[[package]]
name = "tracing-core"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1508,6 +1911,27 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "tungstenite"
+version = "0.17.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0"
+dependencies = [
+ "base64 0.13.1",
+ "byteorder",
+ "bytes",
+ "http",
+ "httparse",
+ "log",
+ "rand",
+ "rustls 0.20.8",
+ "sha-1",
+ "thiserror",
+ "url",
+ "utf-8",
+ "webpki",
+]
+
+[[package]]
+name = "tungstenite"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788"
@@ -1526,12 +1950,27 @@ dependencies = [
]
[[package]]
+name = "typemap_rev"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed5b74f0a24b5454580a79abb6994393b09adf0ab8070f15827cb666255de155"
+
+[[package]]
name = "typenum"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]]
+name = "unicase"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
+dependencies = [
+ "version_check",
+]
+
+[[package]]
name = "unicode-bidi"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1553,14 +1992,21 @@ dependencies = [
]
[[package]]
+name = "untrusted"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
+
+[[package]]
name = "url"
-version = "2.3.1"
+version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
+checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
+ "serde",
]
[[package]]
@@ -1582,12 +2028,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4d330786735ea358f3bc09eea4caa098569c1c93f342d9aca0514915022fe7e"
[[package]]
-name = "vcpkg"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
-
-[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1703,6 +2143,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93"
[[package]]
+name = "wasm-streams"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bbae3363c08332cadccd13b67db371814cd214c2524020932f0804b8cf7c078"
+dependencies = [
+ "futures-util",
+ "js-sys",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+]
+
+[[package]]
name = "web-sys"
version = "0.3.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1713,15 +2166,22 @@ dependencies = [
]
[[package]]
-name = "webhook"
-version = "2.1.2"
+name = "webpki"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09d801ea0225da29d32c85b21d0cb12ed628783f5fa1fbe226e586a3ef6ca96f"
+checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
dependencies = [
- "hyper",
- "hyper-tls",
- "serde",
- "serde_json",
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "webpki-roots"
+version = "0.22.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
+dependencies = [
+ "webpki",
]
[[package]]
@@ -1747,27 +2207,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
-name = "windows-sys"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
-dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.45.0"
+name = "windows"
+version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
dependencies = [
- "windows-targets 0.42.2",
+ "windows-targets",
]
[[package]]
@@ -1776,22 +2221,7 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
- "windows-targets 0.48.0",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
-dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
+ "windows-targets",
]
[[package]]
@@ -1800,95 +2230,62 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
dependencies = [
- "windows_aarch64_gnullvm 0.48.0",
- "windows_aarch64_msvc 0.48.0",
- "windows_i686_gnu 0.48.0",
- "windows_i686_msvc 0.48.0",
- "windows_x86_64_gnu 0.48.0",
- "windows_x86_64_gnullvm 0.48.0",
- "windows_x86_64_msvc 0.48.0",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
-
-[[package]]
-name = "windows_aarch64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
-
-[[package]]
-name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
-
-[[package]]
-name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
-
-[[package]]
-name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
-
-[[package]]
-name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.42.2"
+version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
-name = "windows_x86_64_msvc"
-version = "0.48.0"
+name = "winreg"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
+dependencies = [
+ "winapi",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 4e294f5..ea8f15f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,11 +23,29 @@ tokio = { version = "1.28.2", features = [
"sync",
"rt-multi-thread",
"process",
+ "parking_lot",
] }
-webhook = "2.1.2"
tokio-stream = "0.1.14"
futures-util = "0.3.28"
strip-ansi-escapes = "0.1.1"
+serenity = { version = "0.11.5", features = [
+ "builder",
+ "client",
+ # "framework",
+ "utils",
+ "rustls_backend",
+ "gateway",
+ # "standard_framework",
+], default-features = false }
+poise = "0.5.5"
+anyhow = "1.0.71"
+strum = { version = "0.24.1", features = [
+ "strum_macros",
+ "derive",
+ "std",
+], default-features = false }
+regex = { version = "1.8.4", features = ["std"], default-features = false }
+minify-js = "0.4.3"
[profile.release]
lto = true
diff --git a/src/bot.rs b/src/bot.rs
new file mode 100644
index 0000000..e7de0f4
--- /dev/null
+++ b/src/bot.rs
@@ -0,0 +1,281 @@
+use crate::webhook::Webhook;
+use anyhow::Result;
+use futures_util::StreamExt;
+use minify_js::TopLevelMode;
+use regex::Regex;
+use serenity::http::Http;
+use serenity::prelude::*;
+use std::fs::read_to_string;
+use std::sync::{Arc, Mutex, OnceLock};
+use strum::{AsRefStr, EnumString, EnumVariantNames, VariantNames};
+use tokio::sync::broadcast;
+use tokio::sync::OnceCell as TokLock;
+pub struct Data {
+ stdin: broadcast::Sender<String>,
+}
+
+static SKIPPING: OnceLock<(Arc<Mutex<u8>>, broadcast::Sender<String>)> = OnceLock::new();
+
+pub struct Bot;
+impl Bot {
+ pub async fn new(stdout: broadcast::Receiver<String>, stdin: broadcast::Sender<String>) {
+ let tok = std::env::var("TOKEN").unwrap_or(read_to_string("token").expect("wher token"));
+ let f: poise::FrameworkBuilder<Data, anyhow::Error> = poise::Framework::builder()
+ .options(poise::FrameworkOptions {
+ commands: vec![raw(), say(), ban(), js(), maps(), start(), end(), help()],
+ prefix_options: poise::PrefixFrameworkOptions {
+ prefix: Some(">".to_string()),
+ ..Default::default()
+ },
+ ..Default::default()
+ })
+ .token(&tok)
+ .intents(GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT)
+ .setup(|ctx, _ready, framework| {
+ Box::pin(async move {
+ poise::builtins::register_globally(ctx, &framework.options().commands).await?;
+ println!("registered");
+ Ok(Data { stdin })
+ })
+ });
+
+ tokio::spawn(async move {
+ let http = Http::new("");
+ let mut wh = Webhook::new(&http, &std::env::var("WEBHOOK").expect("no webhook!")).await;
+ SKIPPING.get_or_init(|| (wh.skip.clone(), wh.skipped.clone()));
+ wh.link(stdout).await;
+ });
+ tokio::spawn(async move {
+ f.run().await.unwrap();
+ });
+ }
+}
+
+type Context<'a> = poise::Context<'a, Data, anyhow::Error>;
+
+#[poise::command(
+ prefix_command,
+ required_permissions = "USE_SLASH_COMMANDS",
+ category = "ADMINISTRATION"
+)]
+/// send a raw command to the server
+async fn raw(
+ ctx: Context<'_>,
+ #[description = "Command"]
+ #[rest]
+ cmd: String,
+) -> Result<()> {
+ ctx.data().stdin.send(cmd)?;
+ println!("sent");
+ Ok(())
+}
+
+macro_rules! return_next {
+ ($ctx:expr) => {{
+ let line = get_nextblock().await;
+ $ctx.send(|m| m.content(line)).await?;
+ Ok(())
+ }};
+}
+
+async fn get_nextblock() -> String {
+ let (skip_count, skip_send) = SKIPPING.get().unwrap();
+ {
+ *skip_count.lock().unwrap() += 1;
+ }
+ skip_send
+ .subscribe()
+ .recv()
+ .await
+ .unwrap_or("._?".to_string())
+}
+
+#[poise::command(slash_command, category = "ADMINISTRATION")]
+/// say something as the server
+async fn say(ctx: Context<'_>, #[description = "Message"] message: String) -> Result<()> {
+ let _ = ctx.defer();
+ ctx.data().stdin.send(format!("say {message}"))?;
+ return_next!(ctx)
+}
+
+#[derive(EnumString, EnumVariantNames, AsRefStr)]
+#[strum(serialize_all = "snake_case")]
+enum BanType {
+ Id,
+ Ip,
+ Name,
+}
+
+async fn autocomplete_ban<'a>(
+ _ctx: Context<'_>,
+ partial: &'a str,
+) -> impl futures::Stream<Item = String> + 'a {
+ futures::stream::iter(BanType::VARIANTS)
+ .filter(move |name| futures::future::ready(name.starts_with(partial)))
+ .map(|name| name.to_string())
+}
+
+#[poise::command(slash_command, category = "ADMINISTRATION")]
+/// ban a player
+async fn ban(
+ ctx: Context<'_>,
+ #[autocomplete = "autocomplete_ban"] ban_type: BanType,
+ #[description = "Player (id/ip/name)"] player: String,
+) -> Result<()> {
+ let _ = ctx.defer();
+ ctx.data()
+ .stdin
+ .send(format!("ban {} {player}", ban_type.as_ref()))?;
+ return_next!(ctx)
+}
+
+#[poise::command(
+ prefix_command,
+ required_permissions = "USE_SLASH_COMMANDS",
+ category = "ADMINISTRATION",
+ track_edits
+)]
+/// run arbitrary javascript
+async fn js(
+ ctx: Context<'_>,
+ #[description = "Script"]
+ #[rest]
+ script: String,
+) -> Result<()> {
+ static RE: OnceLock<Regex> = OnceLock::new();
+ let _ = ctx.channel_id().start_typing(&ctx.serenity_context().http);
+ let re = RE.get_or_init(|| Regex::new(r#"```(js|javascript)?([^`]+)```"#).unwrap());
+ let mat = re
+ .captures(&script)
+ .ok_or(anyhow::anyhow!(r#"no code found (use \`\`\`js...\`\`\`."#))?;
+ let script = mat.get(2).unwrap().as_str();
+ let mut out = vec![];
+ let script = if let Err(_) = minify_js::minify(TopLevelMode::Global, script.into(), &mut out) {
+ std::borrow::Cow::from(script.replace('\n', ";")) // xd
+ } else {
+ String::from_utf8_lossy(&out)
+ };
+ ctx.data().stdin.send(format!("js {script}"))?;
+ let line = get_nextblock().await;
+ ctx.send(|m| m.content(line)).await?;
+ Ok(())
+}
+
+fn strip_colors(from: &str) -> String {
+ let mut result = String::new();
+ result.reserve(from.len());
+ let mut level: u8 = 0;
+ for c in from.chars() {
+ if c == '[' {
+ level += 1;
+ } else if c == ']' {
+ level -= 1;
+ } else if level == 0 {
+ result.push(c);
+ }
+ }
+ result
+}
+
+static MAPS: TokLock<Vec<String>> = TokLock::const_new();
+async fn get_maps(stdin: &broadcast::Sender<String>) -> &Vec<String> {
+ MAPS.get_or_init(|| async move {
+ stdin.send(format!("listmaps")).unwrap();
+ let res = get_nextblock().await;
+ let mut vec = vec![];
+ for line in res.lines() {
+ if let Some((_, name)) = line.split_once(':') {
+ vec.push(strip_colors(name));
+ }
+ }
+ vec
+ })
+ .await
+}
+
+#[poise::command(slash_command, required_permissions = "USE_SLASH_COMMANDS")]
+/// lists the maps.
+pub async fn maps(ctx: Context<'_>) -> Result<()> {
+ let _ = ctx.defer();
+ let maps = get_maps(&ctx.data().stdin).await;
+ poise::send_reply(ctx, |m| {
+ m.embed(|e| {
+ for (k, v) in maps.iter().enumerate() {
+ e.field((k + 1).to_string(), v, true);
+ }
+ e.description("map list.")
+ })
+ })
+ .await?;
+ Ok(())
+}
+
+async fn autocomplete_map<'a>(
+ ctx: Context<'a>,
+ partial: &'a str,
+) -> impl futures::Stream<Item = String> + 'a {
+ futures::stream::iter(get_maps(&ctx.data().stdin).await)
+ .filter(move |name| futures::future::ready(name.starts_with(partial)))
+ .map(|name| name.to_string())
+}
+
+async fn mapi(map: &str, stdin: &broadcast::Sender<String>) -> usize {
+ get_maps(stdin).await.iter().position(|r| r == map).unwrap()
+}
+
+#[poise::command(slash_command, required_permissions = "USE_SLASH_COMMANDS")]
+/// start the game.
+pub async fn start(
+ ctx: Context<'_>,
+ #[description = "the map"]
+ #[autocomplete = "autocomplete_map"]
+ map: String,
+) -> Result<()> {
+ let _ = ctx.defer();
+ ctx.data()
+ .stdin
+ .send(format!("plague {}", mapi(&map, &ctx.data().stdin).await))
+ .unwrap();
+ return_next!(ctx)
+}
+
+#[poise::command(slash_command, required_permissions = "USE_SLASH_COMMANDS")]
+/// end the game.
+pub async fn end(
+ ctx: Context<'_>,
+ #[description = "the map to go to"]
+ #[autocomplete = "autocomplete_map"]
+ map: String,
+) -> Result<()> {
+ let _ = ctx.defer();
+ ctx.data()
+ .stdin
+ .send(format!("endplague {}", mapi(&map, &ctx.data().stdin).await))
+ .unwrap();
+ return_next!(ctx)
+}
+
+#[poise::command(
+ prefix_command,
+ slash_command,
+ required_permissions = "USE_SLASH_COMMANDS",
+ track_edits
+)]
+/// show help and stuff
+pub async fn help(
+ ctx: Context<'_>,
+ #[description = "Specific command to show help about"]
+ #[autocomplete = "poise::builtins::autocomplete_command"]
+ command: Option<String>,
+) -> Result<()> {
+ poise::builtins::help(
+ ctx,
+ command.as_deref(),
+ poise::builtins::HelpConfiguration {
+ extra_text_at_bottom: "Mindustry server management bot",
+ ..Default::default()
+ },
+ )
+ .await?;
+ Ok(())
+}
diff --git a/src/logging.rs b/src/logging.rs
index 1a151f4..85354eb 100644
--- a/src/logging.rs
+++ b/src/logging.rs
@@ -35,7 +35,6 @@ macro_rules! define_print {
($prefix:expr) => {
define_print!(fail, concat!($prefix, " ", "!!"), break);
define_print!(flush, concat!($prefix, " ", "<<"));
- define_print!(nooutput, concat!($prefix, " ", "!>"));
define_print!(input, concat!($prefix, " ", "<"));
define_print!(output, concat!($prefix, " ", ">"));
};
diff --git a/src/main.rs b/src/main.rs
index c738a3e..48ce3d6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,6 +4,7 @@ use std::str::FromStr;
#[macro_use]
mod logging;
+mod bot;
mod process;
mod server;
mod webhook;
diff --git a/src/process.rs b/src/process.rs
index 9a414ff..da36818 100644
--- a/src/process.rs
+++ b/src/process.rs
@@ -93,7 +93,6 @@ impl Process {
if html_output.receiver_count() > 0 {
html_output.send(ansi2html(&string)).unwrap();
}
- nooutput!();
async_std::task::sleep(Duration::from_millis(500)).await;
}
})
diff --git a/src/server.rs b/src/server.rs
index 756c984..6e0a274 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -1,7 +1,6 @@
+use crate::bot::Bot;
+use crate::process::Process;
use crate::websocket::WebSocket;
-use crate::{process::Process, webhook::Webhook};
-use axum::http::StatusCode;
-use axum::response::{Redirect, Response};
use axum::{
extract::{
ws::{Message, WebSocketUpgrade},
@@ -15,7 +14,6 @@ use axum::{
use futures::sink::SinkExt;
use minify_html::{minify, Cfg};
use paste::paste;
-use std::sync::Mutex;
use std::{
net::SocketAddr,
sync::{Arc, OnceLock},
@@ -86,7 +84,6 @@ impl Server {
.route("/plaguess.png", png!(plaguess))
.route("/favicon.ico", png!(logo32))
.route("/connect/:id", get(connect_ws))
- .route("/hook/*k", get(connect_wh))
.with_state(state.clone());
let mut server_handle = tokio::spawn(async move {
AxumServer::bind(&addr)
@@ -95,6 +92,7 @@ impl Server {
.unwrap()
});
let mut process_handle = proc.input(stdin).with_state(&state).link();
+ Bot::new(state.stdout_plain.subscribe(), state.stdin.clone()).await;
tokio::select! {
_ = (&mut server_handle) => process_handle.abort(),
_ = (&mut process_handle) => server_handle.abort(),
@@ -136,23 +134,3 @@ async fn connect_ws(
WebSocket::new(socket, state).await.wait().await;
})
}
-
-async fn connect_wh(StateW(state): StateW<Arc<State>>, Path(params): Path<String>) -> Response {
- static WEBHOOK: Mutex<Option<Webhook>> = Mutex::new(None); //one slot
- let (id, url) = {
- match params.split_once('/') {
- None => return StatusCode::BAD_REQUEST.into_response(),
- Some((a, b)) => (a, b),
- }
- };
- if !matches(id) {
- return StatusCode::FORBIDDEN.into_response();
- }
- if let Some(w) = WEBHOOK.lock().unwrap().as_ref() {
- if w.running() {
- return StatusCode::LOCKED.into_response();
- }
- }
- *WEBHOOK.lock().unwrap() = Some(Webhook::new(state.stdout_plain.subscribe(), url).await);
- Redirect::to("/panel").into_response()
-}
diff --git a/src/webhook.rs b/src/webhook.rs
index 275cdf9..6412a8f 100644
--- a/src/webhook.rs
+++ b/src/webhook.rs
@@ -1,84 +1,147 @@
-use std::{
- sync::Arc,
- time::{Duration, Instant},
-};
+use poise::serenity_prelude::Webhook as RealHook;
+use serenity::{builder::ExecuteWebhook, http::Http, json};
+use std::convert::AsRef;
+use std::sync::{Arc, Mutex};
+use std::time::{Duration, Instant};
+use tokio::sync::broadcast::{self, error::TryRecvError};
-use tokio::{
- sync::broadcast::{self, error::TryRecvError},
- task::JoinHandle,
-};
-use webhook::{client::WebhookClient, models::Message};
-
-macro_rules! send {
- ($client:ident, $block:expr) => {{
- let client = $client.clone();
- let mut m = Message::new();
- let mut bloc: Box<dyn FnMut(&mut Message) -> &mut Message> = Box::new($block);
- bloc(&mut m);
- m.allow_mentions(None, None, None, false);
- tokio::spawn(async move {
- client.send_message(&m).await.unwrap();
- });
- // handle goes out of scope, detatched
- }};
+pub struct Webhook<'a> {
+ pub skipped: broadcast::Sender<String>,
+ pub skip: Arc<Mutex<u8>>,
+ inner: RealHook,
+ http: &'a Http,
}
-pub struct Webhook(JoinHandle<()>);
-impl Webhook {
- pub async fn new(mut stdout: broadcast::Receiver<String>, url: &str) -> Self {
- let client = Arc::new(WebhookClient::new(url));
- Self(tokio::spawn(async move {
- define_print!("webhook");
- let mut last: Option<Instant> = None;
- let mut feed: Vec<String> = vec![];
- loop {
- let out = stdout.try_recv();
- let now = Instant::now();
- match out {
- Err(e) => match e {
- TryRecvError::Closed => fail!("closed"),
- TryRecvError::Lagged(_) => continue,
- TryRecvError::Empty => {
- if let Some(earlier) = last {
- let since = now.duration_since(earlier).as_secs();
- if since > 2 || feed.len() > 15 {
- last.take();
- flush::<MindustryStyle>(feed, &client).await;
- feed = vec![];
- flush!();
- }
+impl<'a> Webhook<'a> {
+ pub async fn new(http: &'a impl AsRef<Http>, url: &str) -> Webhook<'a> {
+ Self {
+ inner: RealHook::from_url(http, url).await.unwrap(),
+ http: http.as_ref(),
+ skip: Arc::new(Mutex::new(0)),
+ skipped: broadcast::channel(16).0,
+ }
+ }
+
+ async fn send<F>(&self, block: F)
+ where
+ for<'b> F: FnOnce(&'b mut ExecuteWebhook<'a>) -> &'b mut ExecuteWebhook<'a>,
+ {
+ let mut execute_webhook = ExecuteWebhook::default();
+ block(&mut execute_webhook);
+
+ let map = json::hashmap_to_json_map(execute_webhook.0);
+ if let Err(e) = self
+ .http
+ .as_ref()
+ .execute_webhook(
+ self.inner.id.0,
+ self.inner.token.as_ref().unwrap(),
+ false,
+ &map,
+ )
+ .await
+ {
+ println!("sending {map:#?} got error {e}.");
+ };
+ }
+
+ async fn send_message(&self, username: &str, content: &str) {
+ self.send(|m| m.username(username).content(content)).await;
+ }
+
+ pub async fn link(&mut self, mut stdout: broadcast::Receiver<String>) {
+ define_print!("webhook");
+ let mut last: Option<Instant> = None;
+ let mut feed: Vec<String> = vec![];
+ loop {
+ let out = stdout.try_recv();
+ let now = Instant::now();
+ match out {
+ Err(e) => match e {
+ TryRecvError::Closed => fail!("closed"),
+ TryRecvError::Lagged(_) => continue,
+ TryRecvError::Empty => {
+ if let Some(earlier) = last {
+ let since = now.duration_since(earlier).as_secs();
+ if since > 1 || feed.len() > 15 {
+ last.take();
+ self.flush::<MindustryStyle>(feed).await;
+ feed = vec![];
+ flush!();
}
- async_std::task::sleep(Duration::from_millis(20)).await;
- continue;
- }
- },
- Ok(m) => {
- for line in m.lines() {
- feed.push(line.to_string());
- input!("{line}");
}
- last = Some(now);
+ async_std::task::sleep(Duration::from_millis(20)).await;
+ continue;
+ }
+ },
+ Ok(m) => {
+ let mut lock = self.skip.lock().unwrap();
+ if *lock > 0 {
+ *lock -= 1;
+ input!("{m} < skipped");
+ self.skipped.send(m).unwrap();
+ continue;
}
+ drop(lock);
+ for line in m.lines() {
+ let line = line.to_string();
+ input!("{line}");
+ feed.push(line);
+ }
+ last = Some(now);
}
- async_std::task::sleep(Duration::from_millis(20)).await;
}
- }))
+ async_std::task::sleep(Duration::from_millis(20)).await;
+ }
}
- pub fn running(&self) -> bool {
- !self.0.is_finished()
+ pub async fn flush<Style: OutputStyle>(&self, feed: Vec<String>) {
+ let mut current: Option<String> = None;
+ let mut message: Option<String> = None;
+ let mut unnamed: Option<String> = None;
+
+ // this code is very game dependent
+ for line in feed.into_iter() {
+ let line: String = Style::fix(line);
+ if let Some((name, msg)) = Style::split(&line) {
+ if let Some(n) = current.as_ref() {
+ if n == &name {
+ message.madd_panic(&msg);
+ continue;
+ } else {
+ let message = message.take().unwrap();
+ self.send_message(n, &message).await;
+ current.take();
+ }
+ }
+ current = Some(name.to_owned());
+ message = Some(msg.to_owned());
+ // interrupt
+ if let Some(msg) = unnamed.take() {
+ self.send_message("server", &msg).await;
+ }
+ continue;
+ }
+ unnamed.madd(line);
+ }
+ // finish
+ if let Some(n) = current.as_ref() {
+ let message = message.take().unwrap();
+ self.send_message(n, &message).await;
+ }
+ if let Some(msg) = unnamed.as_ref() {
+ self.send_message("server", msg).await;
+ }
}
}
/// functions ordered by call order
pub trait OutputStyle {
/// first step
- fn fix(raw_line: String) -> String;
- /// ignore completely?
- fn ignore(line: &str) -> bool;
- /// is there no user
- fn unnamed(line: &str) -> bool;
- /// get the user and the content
+ fn fix(raw_line: String) -> String {
+ raw_line
+ }
+ /// get the user and the content (none for no user)
fn split(line: &str) -> Option<(String, String)>;
}
@@ -92,92 +155,34 @@ macro_rules! s {
}
pub struct MindustryStyle;
impl OutputStyle for MindustryStyle {
- fn fix(raw_line: String) -> String {
- raw_line.split(' ').skip(3).collect::<Vec<&str>>().join(" ")
- }
- fn ignore(line: &str) -> bool {
- line.trim().is_empty()
- || line.contains("requested trace info")
- || s!(line, Server)
- || s!(line, Connected)
- || s!(line, PLAGUE)
- || s!(line, "1 mods loaded")
- }
-
- fn unnamed(line: &str) -> bool {
- s!(line, [' ', '\t'])
- }
-
fn split(line: &str) -> Option<(String, String)> {
- if let Some(n) = line.find(':') {
- if n < 12 {
- if let Some((u, c)) = line.split_once(':') {
- return Some((
- unify(u).trim_start_matches('<').to_owned(),
- unify(c).trim_end_matches('>').to_owned(),
- ));
+ if s!(line, [' ', '\t']) || s!(line, "at") {
+ return None;
+ }
+ if line.chars().filter(|x| x == &':').count() == 1 {
+ if let Some((u, c)) = line.split_once(':') {
+ let u = unify(u).trim_start_matches('<').trim().to_owned();
+ let c = unify(c).trim_end_matches('>').trim().to_owned();
+ if !(u.is_empty() || c.is_empty()) {
+ return Some((u, c));
}
}
}
if let Some(index) = line.find("has") {
if line.contains("connected") {
let player = &line[..index];
- return Some((unify(player).trim().to_owned(), "joined".to_owned()));
+ let prefix = if line.contains("disconnected") {
+ "left"
+ } else {
+ "joined"
+ };
+ return Some((unify(player).trim().to_owned(), prefix.to_owned()));
}
}
None
}
}
-async fn flush<Style: OutputStyle>(feed: Vec<String>, client: &Arc<WebhookClient>) {
- let mut current: Option<String> = None;
- let mut message: Option<String> = None;
- let mut unnamed: Option<String> = None;
-
- // this code is very game dependent
- for line in feed.into_iter() {
- // [0-0-0-0 0-0-0-0] [i] ... -> ...
- let line: String = Style::fix(line);
- if Style::ignore(&line) {
- continue;
- }
- if Style::unnamed(&line) {
- unnamed.madd(line);
- continue;
- }
-
- if let Some((name, msg)) = Style::split(&line) {
- if !(msg.is_empty() || name.is_empty()) {
- if let Some(n) = current.as_ref() {
- if n == &name {
- message.madd_panic(&msg);
- continue;
- } else {
- let message = message.take().unwrap();
- send!(client, |m| m.content(&message).username(n));
- current.take();
- }
- }
- current = Some(name.to_owned());
- message = Some(msg.to_owned());
- // interrupt
- if let Some(msg) = unnamed.take() {
- send!(client, |m| m.username("server").content(&msg));
- }
- continue;
- }
- }
- unnamed.madd(line);
- }
- // leftovers
- if let Some(n) = current.as_ref() {
- let message = message.take().unwrap();
- send!(client, |m| m.content(&message).username(n));
- }
- if let Some(msg) = unnamed.as_ref() {
- send!(client, |m| m.username("server").content(msg));
- }
-}
/// latin > extended a > kill
fn unify(s: &str) -> String {
s.chars()
@@ -205,3 +210,32 @@ impl Madd for Option<String> {
}
}
}
+
+#[test]
+fn style() {
+ macro_rules! test_line {
+ ($line:expr) => {
+ let line = $line.to_string(); // no fixing done!
+ let got = MindustryStyle::split(&line);
+ assert!(got == None, "got {got:?}, expected None");
+ };
+ ($line:expr, $name: expr, $content: expr) => {
+ let line = $line.to_string();
+ let got = MindustryStyle::split(&line);
+ assert!(
+ got == Some(($name.into(), $content.into())),
+ "got {got:?}, expected ({}, {})",
+ $name,
+ $content
+ );
+ };
+ }
+ //unnamed
+ test_line!("undefined");
+ test_line!("Lost command socket connection: localhost/127.0.0.1:6859");
+ //named
+ test_line!("abc: hi", "abc", "hi");
+ test_line!("<a: /help>", "a", "/help");
+ test_line!("a has connected. [abc==]", "a", "joined");
+ test_line!("a has disconnected. [abc==] (closed)", "a", "left");
+}