From d102e0cfa339cbc9243bfb5f0fbd383c1716ff3e Mon Sep 17 00:00:00 2001 From: Fridella <43757589+fdnt7@users.noreply.github.com> Date: Thu, 11 Apr 2024 00:46:25 +0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=86=20Update=20to=20`twilight`=20`=3D0?= =?UTF-8?q?.16.0-rc.1`=20(#14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update to `twilight` `=0.16.0-rc.1` * Fixed deprioritised partial move error * Update to use custom fork of `twilight-interactions`, rev `82b707f` & benefit from `bitflags` 2.x.x * Update to `lyra` `0.5.0` * Improved `.expect(...)` and `panic!(...)` messages & removed dead code --- lyra/Cargo.lock | 424 +++++++++++------- lyra/Cargo.toml | 26 +- lyra/lyra_proc/Cargo.toml | 2 +- lyra/src/bot/command/check.rs | 10 +- lyra/src/bot/command/declare.rs | 16 +- lyra/src/bot/command/model.rs | 7 +- lyra/src/bot/command/model/ctx.rs | 29 +- .../src/bot/command/model/ctx/command_data.rs | 32 +- lyra/src/bot/command/model/ctx/menu.rs | 16 +- lyra/src/bot/command/poll.rs | 23 +- lyra/src/bot/command/util.rs | 2 +- lyra/src/bot/component/config/access.rs | 4 +- lyra/src/bot/component/config/access/edit.rs | 12 +- lyra/src/bot/component/connection.rs | 6 +- lyra/src/bot/component/connection/join.rs | 2 +- lyra/src/bot/component/connection/leave.rs | 6 +- lyra/src/bot/component/queue/move.rs | 8 +- lyra/src/bot/component/queue/play.rs | 17 +- lyra/src/bot/component/queue/remove.rs | 2 +- lyra/src/bot/core/const.rs | 12 +- lyra/src/bot/core/model.rs | 2 +- lyra/src/bot/core/model/interaction.rs | 18 +- lyra/src/bot/error/command.rs | 2 +- lyra/src/bot/error/command/util.rs | 2 +- lyra/src/bot/error/component/connection.rs | 10 +- lyra/src/bot/error/runner.rs | 2 +- lyra/src/bot/ext/image.rs | 2 +- lyra/src/bot/ext/util.rs | 18 +- lyra/src/bot/gateway/guild.rs | 4 +- lyra/src/bot/gateway/interaction.rs | 2 +- lyra/src/bot/gateway/model.rs | 4 +- lyra/src/bot/gateway/voice.rs | 8 +- lyra/src/bot/lavalink/model.rs | 41 +- lyra/src/bot/lavalink/model/queue.rs | 9 +- lyra/src/bot/runner.rs | 88 ++-- 35 files changed, 452 insertions(+), 416 deletions(-) diff --git a/lyra/Cargo.lock b/lyra/Cargo.lock index bf9d2f9..9179e6e 100644 --- a/lyra/Cargo.lock +++ b/lyra/Cargo.lock @@ -128,15 +128,15 @@ dependencies = [ [[package]] name = "base64" -version = "0.13.1" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" -version = "0.21.7" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" [[package]] name = "base64ct" @@ -1368,6 +1368,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 1.0.0", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.14.3" @@ -1474,6 +1493,29 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.0.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.0.0", + "http-body 1.0.0", + "pin-project-lite", +] + [[package]] name = "httparse" version = "1.8.0" @@ -1496,9 +1538,9 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.24", "http 0.2.11", - "http-body", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -1511,17 +1553,23 @@ dependencies = [ ] [[package]] -name = "hyper-rustls" -version = "0.23.2" +name = "hyper" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" dependencies = [ - "http 0.2.11", - "hyper", - "rustls 0.20.9", - "rustls-native-certs", + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.4", + "http 1.0.0", + "http-body 1.0.0", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", "tokio", - "tokio-rustls 0.23.4", + "want", ] [[package]] @@ -1532,12 +1580,50 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.11", - "hyper", + "hyper 0.14.28", "rustls 0.21.10", "tokio", "tokio-rustls 0.24.1", ] +[[package]] +name = "hyper-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +dependencies = [ + "futures-util", + "http 1.0.0", + "hyper 1.2.0", + "hyper-util", + "rustls 0.22.2", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.25.0", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "hyper 1.2.0", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -1669,7 +1755,7 @@ dependencies = [ "serde_json", "serde_qs", "tokio", - "tokio-tungstenite 0.21.0", + "tokio-tungstenite", "tracing", "twilight-model", "url", @@ -1777,7 +1863,7 @@ dependencies = [ [[package]] name = "lyra" -version = "0.4.0" +version = "0.5.0" dependencies = [ "aho-corasick", "bitflags 2.5.0", @@ -2128,6 +2214,26 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -2209,9 +2315,9 @@ checksum = "744a264d26b88a6a7e37cbad97953fa233b94d585236310bcbc88474b4092d79" [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -2336,10 +2442,10 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", + "h2 0.3.24", "http 0.2.11", - "http-body", - "hyper", + "http-body 0.4.6", + "hyper 0.14.28", "hyper-rustls 0.24.2", "ipnet", "js-sys", @@ -2349,7 +2455,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustls 0.21.10", - "rustls-pemfile", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", @@ -2366,21 +2472,6 @@ dependencies = [ "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 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - [[package]] name = "ring" version = "0.17.8" @@ -2392,7 +2483,7 @@ dependencies = [ "getrandom", "libc", "spin 0.9.8", - "untrusted 0.9.0", + "untrusted", "windows-sys 0.52.0", ] @@ -2418,9 +2509,9 @@ dependencies = [ [[package]] name = "rstest" -version = "0.18.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97eeab2f3c0a199bc4be135c36c924b6590b88c377d416494288c14f2db30199" +checksum = "9d5316d2a1479eeef1ea21e7f9ddc67c191d497abc8fc3ba2467857abbb68330" dependencies = [ "futures", "futures-timer", @@ -2430,9 +2521,9 @@ dependencies = [ [[package]] name = "rstest_macros" -version = "0.18.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d428f8247852f894ee1be110b375111b586d4fa431f6c46e64ba5a0dcccbe605" +checksum = "04a9df72cc1f67020b0d63ad9bfe4a323e459ea7eb68e03bd9824db49f9a4c25" dependencies = [ "cfg-if", "glob", @@ -2473,18 +2564,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rustls" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" -dependencies = [ - "log", - "ring 0.16.20", - "sct", - "webpki", -] - [[package]] name = "rustls" version = "0.21.10" @@ -2492,7 +2571,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring 0.17.8", + "ring", "rustls-webpki 0.101.7", "sct", ] @@ -2504,7 +2583,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" dependencies = [ "log", - "ring 0.17.8", + "ring", "rustls-pki-types", "rustls-webpki 0.102.2", "subtle", @@ -2513,12 +2592,13 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.6.3" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" dependencies = [ "openssl-probe", - "rustls-pemfile", + "rustls-pemfile 2.1.2", + "rustls-pki-types", "schannel", "security-framework", ] @@ -2532,6 +2612,16 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pemfile" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64 0.22.0", + "rustls-pki-types", +] + [[package]] name = "rustls-pki-types" version = "1.3.0" @@ -2544,8 +2634,8 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -2554,9 +2644,9 @@ version = "0.102.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" dependencies = [ - "ring 0.17.8", + "ring", "rustls-pki-types", - "untrusted 0.9.0", + "untrusted", ] [[package]] @@ -2607,8 +2697,8 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -2790,6 +2880,12 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + [[package]] name = "slab" version = "0.4.9" @@ -2892,7 +2988,7 @@ dependencies = [ "paste", "percent-encoding", "rustls 0.21.10", - "rustls-pemfile", + "rustls-pemfile 1.0.4", "serde", "serde_json", "sha2", @@ -3258,17 +3354,6 @@ dependencies = [ "syn 2.0.58", ] -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls 0.20.9", - "tokio", - "webpki", -] - [[package]] name = "tokio-rustls" version = "0.24.1" @@ -3301,22 +3386,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-tungstenite" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd" -dependencies = [ - "futures-util", - "log", - "rustls 0.20.9", - "rustls-native-certs", - "tokio", - "tokio-rustls 0.23.4", - "tungstenite 0.18.0", - "webpki", -] - [[package]] name = "tokio-tungstenite" version = "0.21.0" @@ -3329,7 +3398,7 @@ dependencies = [ "rustls-pki-types", "tokio", "tokio-rustls 0.25.0", - "tungstenite 0.21.0", + "tungstenite", "webpki-roots 0.26.1", ] @@ -3347,6 +3416,52 @@ dependencies = [ "tracing", ] +[[package]] +name = "tokio-websockets" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b069bad86dda43d908b4221fe04fe49d2ed8e0a24d319a5c6a8d250e76fe15b" +dependencies = [ + "base64 0.21.7", + "bytes", + "fastrand", + "futures-core", + "futures-sink", + "http 1.0.0", + "httparse", + "ring", + "rustls-native-certs", + "rustls-pki-types", + "sha1_smol", + "simdutf8", + "tokio", + "tokio-rustls 0.25.0", + "tokio-util", + "tracing", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -3431,27 +3546,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "tungstenite" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788" -dependencies = [ - "base64 0.13.1", - "byteorder", - "bytes", - "http 0.2.11", - "httparse", - "log", - "rand", - "rustls 0.20.9", - "sha1", - "thiserror", - "url", - "utf-8", - "webpki", -] - [[package]] name = "tungstenite" version = "0.21.0" @@ -3475,17 +3569,17 @@ dependencies = [ [[package]] name = "twilight" -version = "0.15.1" +version = "0.16.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18368387c671e3705ee98819199511fc49fc9f8909cdc42b87389ea6b21bb9c9" +checksum = "f917ea79e3c1cb325a5cd060e8d3b9f6872ae124a3e1e1192c0e17b3b0a20132" [[package]] name = "twilight-cache-inmemory" -version = "0.15.4" +version = "0.16.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f5a9338cc26a6ffa77932c6386b227714e1a9b75f5cf644739d0c3605e19a95" +checksum = "a997fdd14e32ebbe80ee87887720e756efed0a7dbf97bd1170eb7c9a3956378b" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "dashmap", "serde", "twilight-model", @@ -3494,20 +3588,19 @@ dependencies = [ [[package]] name = "twilight-gateway" -version = "0.15.4" +version = "0.16.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30be5c7e2b13b4a59e0f93344c070c23404279a318a324eece1f4384ead47d86" +checksum = "3b3edd60e2b95ec0d651c475dacad8a75e4780d900f8f2ea0f4c215182d920fc" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", + "fastrand", "flate2", - "futures-util", - "rand", - "rustls 0.20.9", - "rustls-native-certs", + "futures-core", + "futures-sink", "serde", "serde_json", "tokio", - "tokio-tungstenite 0.18.0", + "tokio-websockets", "tracing", "twilight-gateway-queue", "twilight-http", @@ -3516,9 +3609,9 @@ dependencies = [ [[package]] name = "twilight-gateway-queue" -version = "0.15.4" +version = "0.16.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3073747da8e1d09bc5383eed750451c9534021c8206a20092405b9855b3cb35a" +checksum = "92d30e99f204d3803b47c679214ba9e9527cfb1dd0b0deccbe821f7e4682d9a2" dependencies = [ "tokio", "tracing", @@ -3526,15 +3619,18 @@ dependencies = [ [[package]] name = "twilight-http" -version = "0.15.4" +version = "0.16.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c78b55d912a58814dbfc4dc3cfb9496c7e83eb6ec738b1cc4c359ba0d2ff2dd8" +checksum = "a03a8133c9ae23510aa6bbe81ca7c4d5bc6fc45c52075d350fd0578b71397413" dependencies = [ "brotli", - "hyper", - "hyper-rustls 0.23.2", + "fastrand", + "http 1.0.0", + "http-body-util", + "hyper 1.2.0", + "hyper-rustls 0.26.0", + "hyper-util", "percent-encoding", - "rand", "serde", "serde_json", "tokio", @@ -3546,21 +3642,18 @@ dependencies = [ [[package]] name = "twilight-http-ratelimiting" -version = "0.15.3" +version = "0.16.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4a03343ff60a8d5b5b722ce4b0b7e266ace6cc3e9143544a840d3cc127f02b" +checksum = "87f814c51752ba6838d3b32e82638176de9679e9a2a084a65251b7879281bdc6" dependencies = [ - "futures-util", - "http 0.2.11", "tokio", "tracing", ] [[package]] name = "twilight-interactions" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f147662174686043822ade9d0abb388d8ac460edb77ba908145fd96edb285795" +version = "0.16.0-rc.1" +source = "git+https://github.com/fdnt7/twilight-interactions?rev=82b707f#82b707f016768bff8dad331394c229852df08262" dependencies = [ "twilight-interactions-derive", "twilight-model", @@ -3568,9 +3661,8 @@ dependencies = [ [[package]] name = "twilight-interactions-derive" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a297ef39ee60e672ff47624acb4f4fff5f700dcb2b509230664916f20a7d489" +version = "0.16.0-rc.1" +source = "git+https://github.com/fdnt7/twilight-interactions?rev=82b707f#82b707f016768bff8dad331394c229852df08262" dependencies = [ "proc-macro2", "quote", @@ -3579,20 +3671,20 @@ dependencies = [ [[package]] name = "twilight-mention" -version = "0.15.3" +version = "0.16.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "903136f763a70ed4716c2e6e4f5436c29d9326b748e3a2e2657010d7584f28d1" +checksum = "3dc35d15fbaf51d2a4a0ca961e746bca9a01f26f338f99d9134c15b6561b4c5b" dependencies = [ "twilight-model", ] [[package]] name = "twilight-model" -version = "0.15.4" +version = "0.16.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276bd50f4817b3b421395afac89f5d7b61fdfd0f00a28b2a7db983e4878b4a1a" +checksum = "5eaf296e6aa8784699046bb1ceb33f3c684a59c4657c2b159eb4ec1e1ce44a49" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "serde", "serde-value", "serde_repr", @@ -3601,12 +3693,12 @@ dependencies = [ [[package]] name = "twilight-standby" -version = "0.15.4" +version = "0.16.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20f10f0a07962ab9a0651ce6e4d449abf896b0dd1d883d9051cbc5c0e2b092da" +checksum = "e968572b4e0c2b0e7a05b4b31b1cbc767c7ec0df0407410045ae8c267af6e1fd" dependencies = [ "dashmap", - "futures-util", + "futures-core", "tokio", "tracing", "twilight-model", @@ -3614,9 +3706,9 @@ dependencies = [ [[package]] name = "twilight-util" -version = "0.15.4" +version = "0.16.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe3149347d8222e042a55deba80cd32f93f14770bbb845b8e4cfbd70a5062c56" +checksum = "4c8a5a519ea63090a9e009974bf25e8cb3be9284da7248011ed37377d4180295" dependencies = [ "twilight-model", "twilight-validate", @@ -3624,9 +3716,9 @@ dependencies = [ [[package]] name = "twilight-validate" -version = "0.15.3" +version = "0.16.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3595d5ad595d8d3a97096a01899b53d3a8117ab16deda27526b315a1db815da4" +checksum = "0d71bf2b683421a1674080e821eef108a35cef841ed73562f835bc5cdd478b49" dependencies = [ "twilight-model", ] @@ -3697,12 +3789,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "untrusted" version = "0.9.0" @@ -3868,16 +3954,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" -dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", -] - [[package]] name = "webpki-roots" version = "0.25.4" diff --git a/lyra/Cargo.toml b/lyra/Cargo.toml index dfad890..3b0db50 100644 --- a/lyra/Cargo.toml +++ b/lyra/Cargo.toml @@ -2,7 +2,7 @@ name = "lyra" readme = "../README.md" description = "A featureful, self-hostable Discord music bot." -version = "0.4.0" +version = "0.5.0" edition = "2021" license = "GPL-3.0" repository = "https://github.com/lyra-music/lyra" @@ -48,7 +48,7 @@ dotenvy = "0.15.7" dotenvy_macro = "0.15.7" thiserror = "1.0.58" color-eyre = "0.6.3" -rstest = "0.18.2" +rstest = "0.19.0" futures = "0.3.30" tokio = { version = "1.37.0", features = [ "sync", @@ -69,24 +69,24 @@ lazy_static = "1.4.0" chrono = "0.4.37" sqlx = { version = "0.7.4", features = ["postgres", "runtime-tokio-rustls"] } mixbox = "2.0.0" -lavalink-rs = { version = "0.11.0", features = ["twilight"] } +lavalink-rs = { version = "0.11.0", features = ["twilight16"] } aho-corasick = "1.1.3" -twilight = "0.15.1" -twilight-cache-inmemory = { version = "0.15.4", features = [ +twilight = "=0.16.0-rc.1" +twilight-cache-inmemory = { version = "=0.16.0-rc.1", features = [ "permission-calculator", ] } -twilight-gateway = "0.15.4" -twilight-http = "0.15.4" -twilight-model = "0.15.4" -twilight-standby = "0.15.4" -twilight-validate = "0.15.3" -twilight-mention = "0.15.3" -twilight-util = { version = "0.15.4", features = [ +twilight-gateway = "=0.16.0-rc.1" +twilight-http = "=0.16.0-rc.1" +twilight-model = "=0.16.0-rc.1" +twilight-standby = "=0.16.0-rc.1" +twilight-validate = "=0.16.0-rc.1" +twilight-mention = "=0.16.0-rc.1" +twilight-util = { version = "=0.16.0-rc.1", features = [ "permission-calculator", "builder", ] } -twilight-interactions = "0.15.2" +twilight-interactions = { git = "https://github.com/fdnt7/twilight-interactions", rev = "82b707f" } [dependencies.kmeans_colors] version = "0.6.0" diff --git a/lyra/lyra_proc/Cargo.toml b/lyra/lyra_proc/Cargo.toml index 276c83f..85b2949 100644 --- a/lyra/lyra_proc/Cargo.toml +++ b/lyra/lyra_proc/Cargo.toml @@ -19,6 +19,6 @@ unwrap_used = "deny" [dependencies] syn = "2.0.58" -quote = "1.0.35" +quote = "1.0.36" itertools = "0.12.1" heck = "0.5.0" diff --git a/lyra/src/bot/command/check.rs b/lyra/src/bot/command/check.rs index 901c330..6267803 100644 --- a/lyra/src/bot/command/check.rs +++ b/lyra/src/bot/command/check.rs @@ -110,9 +110,7 @@ pub async fn user_allowed_in(ctx: &Ctx) -> Result<(), check::UserA ChannelType::PublicThread | ChannelType::PrivateThread | ChannelType::AnnouncementThread => { - let parent_id = channel - .parent_id - .expect("threads must have a parent channel"); + let parent_id = channel.parent_id.expect("threads always have a parent id"); access_calculator_builder = access_calculator_builder .thread(channel.id) .text_channel(parent_id); @@ -201,7 +199,7 @@ fn someone_else_in(channel_id: Id, ctx: &Ctx) -> Op states.any(|v| { !ctx.cache() .user(v.user_id()) - .expect("user of `v.user_id()` must exist in the cache") + .expect("user should be in the cache") .bot && v.user_id() != ctx.author_id() }) @@ -336,7 +334,7 @@ async fn currently_playing(ctx: &Ctx) -> Result &'static str { let cmd_name = stringify!($raw_cmd); &SLASH_COMMANDS_MAP.get(cmd_name) - .unwrap_or_else(|| panic!("command {} must exist", cmd_name)) + .unwrap_or_else(|| panic!("command not found: {}", cmd_name)) .name } } )* impl SlashCtx { - pub async fn execute(mut self, data: CommandData) -> Result<(), CommandExecuteError> { + pub async fn execute(self, data: CommandData) -> Result<(), CommandExecuteError> { check::user_allowed_in(&self).await?; match data.name { @@ -58,7 +58,7 @@ macro_rules! declare_slash_commands { } )* _ => { - let cmd_data = self.take_partial_command_data().expect("`self.data` must exist"); + let cmd_data = self.into_partial_command_data(); return Err(CommandExecuteError::UnknownCommand(cmd_data)) } } @@ -84,14 +84,14 @@ macro_rules! declare_message_commands { fn name() -> &'static str { let cmd_name = stringify!($raw_cmd); &MESSAGE_COMMANDS_MAP.get(cmd_name) - .unwrap_or_else(|| panic!("command {} must exist", cmd_name)) + .unwrap_or_else(|| panic!("command not found: {}", cmd_name)) .name } } )* impl MessageCtx { - pub async fn execute(mut self, data: CommandData) -> Result<(), CommandExecuteError> { + pub async fn execute(self, data: CommandData) -> Result<(), CommandExecuteError> { check::user_allowed_in(&self).await?; match data.name { @@ -101,7 +101,7 @@ macro_rules! declare_message_commands { } )* _ => { - let cmd_data = self.take_partial_command_data().expect("`self.data` must exist"); + let cmd_data = self.into_partial_command_data(); return Err(CommandExecuteError::UnknownCommand(cmd_data)) } } @@ -114,7 +114,7 @@ macro_rules! declare_message_commands { macro_rules! declare_autocomplete { ($ ($raw_cmd: ident => $raw_autocomplete: ident) ,* $(,)? ) => { impl AutocompleteCtx { - pub async fn execute(mut self, data: CommandData) -> Result<(), AutocompleteExecuteError> { + pub async fn execute(self, data: CommandData) -> Result<(), AutocompleteExecuteError> { match data.name { $( ref n if n == <$raw_cmd>::name() => { @@ -122,7 +122,7 @@ macro_rules! declare_autocomplete { } )* _ => { - let cmd_data = self.take_partial_command_data().expect("`self.data` must exist"); + let cmd_data = self.into_partial_command_data(); return Err(AutocompleteExecuteError::UnknownAutocomplete(cmd_data)) } } diff --git a/lyra/src/bot/command/model.rs b/lyra/src/bot/command/model.rs index f56b596..1baa5eb 100644 --- a/lyra/src/bot/command/model.rs +++ b/lyra/src/bot/command/model.rs @@ -3,8 +3,9 @@ mod ctx; use std::sync::Arc; use twilight_model::{ - application::interaction::application_command::{ - CommandData, CommandDataOption, CommandInteractionDataResolved, + application::interaction::{ + application_command::{CommandData, CommandDataOption}, + InteractionDataResolved, }, id::{ marker::{CommandMarker, GenericMarker}, @@ -24,7 +25,7 @@ pub struct PartialCommandData { pub id: Id, pub name: Arc, pub target_id: Option>, - pub resolved: Option, + pub resolved: Option, pub options: Box<[CommandDataOption]>, } diff --git a/lyra/src/bot/command/model/ctx.rs b/lyra/src/bot/command/model/ctx.rs index 8863403..6e3ea61 100644 --- a/lyra/src/bot/command/model/ctx.rs +++ b/lyra/src/bot/command/model/ctx.rs @@ -110,7 +110,7 @@ impl Ctx { pub fn bot_member(&self) -> CachedBotMember { self.cache() .member(self.guild_id(), self.bot().user_id()) - .expect("bot's member object must exist") + .expect("bot's member should be in cache") } #[inline] @@ -122,20 +122,18 @@ impl Ctx { self.inner .channel .as_ref() - .expect("`self.inner.channel` must not be `None`") + .expect("interaction type is not ping") } pub fn author(&self) -> &User { - self.inner - .author() - .expect("`self.inner.author()` must not be `None`") + self.inner.author().expect("interaction type is not ping") } pub fn member(&self) -> &PartialMember { self.inner .member .as_ref() - .expect("`self.inner.member` must not be `None`") + .expect("interaction invoked in a guild") } #[inline] @@ -151,10 +149,6 @@ impl Ctx { &self.inner.token } - fn interaction_data(&self) -> &PartialInteractionData { - self.data.as_ref().expect("`self.data` must exist") - } - pub async fn interface(&self) -> Result { Ok(self.bot.interaction().await?.interfaces(&self.inner)) } @@ -162,7 +156,7 @@ impl Ctx { pub fn bot_permissions(&self) -> Permissions { self.inner .app_permissions - .expect("this interaction must be executed in guilds") + .expect("interaction invoked in a guild") } pub fn bot_permissions_for(&self, channel_id: Id) -> Permissions { @@ -175,7 +169,7 @@ impl Ctx { let everyone_role = self .cache() .role(guild_id.cast()) - .expect("`@everyone` role must exist"); + .expect("@everyone role should be in cache"); let member_roles = self .bot_member() .roles() @@ -191,11 +185,11 @@ impl Ctx { let channel = self .cache() .channel(channel_id) - .expect("channel must exist"); + .expect("channel should be in cache"); let channel_overwrites = channel .permission_overwrites .as_ref() - .expect("permission overrwrites must exist"); + .expect("channel is in a guild"); twilight_util::permission_calculator::PermissionCalculator::new( guild_id, @@ -256,8 +250,7 @@ impl GuildIdAware for Ctx { impl ExpectedGuildIdAware for Ctx { fn guild_id(&self) -> Id { - self.get_guild_id() - .expect("this interaction must be executed in guilds") + self.get_guild_id().expect("interaction invoked in a guild") } } @@ -266,8 +259,8 @@ impl AuthorPermissionsAware for Ctx { self.inner .member .as_ref() - .expect("this interaction must be executed in guilds") + .expect("interaction invoked in a guild") .permissions - .expect("this field should exist") + .expect("member from an interaction") } } diff --git a/lyra/src/bot/command/model/ctx/command_data.rs b/lyra/src/bot/command/model/ctx/command_data.rs index 88d6ddf..9b69e1e 100644 --- a/lyra/src/bot/command/model/ctx/command_data.rs +++ b/lyra/src/bot/command/model/ctx/command_data.rs @@ -40,18 +40,27 @@ impl Ctx { } } - pub fn command_data(&self) -> &PartialCommandData { + fn interaction_data(&self) -> &PartialInteractionData { + self.data.as_ref().expect("T: CommandDataAware") + } + + fn into_interaction_data(self) -> PartialInteractionData { + self.data.expect("T: CommandDataAware") + } + + pub fn partial_command_data(&self) -> &PartialCommandData { let PartialInteractionData::Command(data) = self.interaction_data() else { unreachable!() }; data } - pub fn take_partial_command_data(&mut self) -> Option { - self.data.take().and_then(|d| match d { - PartialInteractionData::Command(data) => Some(data), - _ => None, - }) + pub fn into_partial_command_data(self) -> PartialCommandData { + let data = self.into_interaction_data(); + let PartialInteractionData::Command(command_data) = data else { + unreachable!() + }; + command_data } pub fn command_name_full(&self) -> Box { @@ -74,14 +83,19 @@ impl Ctx { } recurse_through_names( - vec![self.command_data().name.clone()], - &self.command_data().options, + vec![self.partial_command_data().name.clone()], + &self.partial_command_data().options, ) .join(" ") .into() } pub fn command_mention_full(&self) -> Box { - format!("", self.command_name_full(), self.command_data().id).into() + format!( + "", + self.command_name_full(), + self.partial_command_data().id + ) + .into() } } diff --git a/lyra/src/bot/command/model/ctx/menu.rs b/lyra/src/bot/command/model/ctx/menu.rs index 483e3c5..c1b1e8f 100644 --- a/lyra/src/bot/command/model/ctx/menu.rs +++ b/lyra/src/bot/command/model/ctx/menu.rs @@ -27,9 +27,9 @@ impl TargetIdAware for MessageAppMarker {} impl Ctx> { pub fn target_id(&self) -> Id { - self.command_data() + self.partial_command_data() .target_id - .expect("`self.command_data().target_id` must exist") + .expect("T: TargetIdAware") } } @@ -40,13 +40,13 @@ impl UserCtx { } pub fn target_user(&self) -> &User { - self.command_data() + self.partial_command_data() .resolved .as_ref() - .expect("`self.command_data().resolved` must exist") + .expect("interaction type is application command") .users .get(&self.target_user_id()) - .expect("user must exist") + .expect("user should be resolved") } } @@ -57,12 +57,12 @@ impl MessageCtx { } pub fn target_message(&self) -> &Message { - self.command_data() + self.partial_command_data() .resolved .as_ref() - .expect("`self.command_data().resolved` must exist") + .expect("interaction type is application command") .messages .get(&self.target_message_id()) - .expect("message must exist") + .expect("message should be resolved") } } diff --git a/lyra/src/bot/command/poll.rs b/lyra/src/bot/command/poll.rs index ab790bb..2d0b7ac 100644 --- a/lyra/src/bot/command/poll.rs +++ b/lyra/src/bot/command/poll.rs @@ -11,9 +11,7 @@ use futures::StreamExt; use itertools::Itertools; use rand::{distributions::Alphanumeric, Rng}; use twilight_model::{ - application::interaction::{ - message_component::MessageComponentInteractionData, Interaction, InteractionData, - }, + application::interaction::{Interaction, InteractionData}, channel::message::{ component::{ActionRow, Button, ButtonStyle}, Component, Embed, ReactionType, @@ -198,25 +196,22 @@ struct WaitForPollActionsContext<'a> { } fn handle_interactions(inter: Interaction, upvote_button_id: &String) -> PollAction { - let user_id = inter.author_id().expect("author id must exist"); - let Some(InteractionData::MessageComponent(MessageComponentInteractionData { - custom_id: ref button_id, - .. - })) = inter.data - else { + let user_id = inter.author_id().expect("interaction from a guild"); + + let Some(InteractionData::MessageComponent(ref component)) = inter.data else { unreachable!() }; let voter_permissions = inter .member .as_ref() - .expect("member must exist") + .expect("interaction from a guild") .permissions - .expect("permissions must exist"); + .expect("member from an interaction"); match ( super::check::is_user_dj(&Voter::new(voter_permissions)), - button_id == upvote_button_id, + component.custom_id == *upvote_button_id, ) { (true, true) => PollAction::DjUpvote(inter), (true, false) => PollAction::DjDownvote(inter), @@ -325,7 +320,7 @@ fn get_users_in_voice( let users_in_voice = ctx .cache() .voice_channel_states(ctx.lavalink().connection(guild_id).channel_id) - .expect("bot must be in voice") + .expect("bot is in voice") .map(|v| ctx.cache().user(v.user_id()).ok_or(CacheError)) .filter_map_ok(|u| (!u.bot).then_some(u.id)) .collect::, _>>()?; @@ -369,7 +364,7 @@ impl EmbedUpdate<'_> { } => { client .update_message(channel_id, message_id) - .embeds(Some(&[embed]))? + .embeds(Some(&[embed])) .await? } }; diff --git a/lyra/src/bot/command/util.rs b/lyra/src/bot/command/util.rs index 1bff24e..3ee3cc6 100644 --- a/lyra/src/bot/command/util.rs +++ b/lyra/src/bot/command/util.rs @@ -164,7 +164,7 @@ pub trait GuildAvatarUrlAware { impl GuildAvatarUrlAware for PartialMember { fn id(&self) -> Id { - self.user.as_ref().expect("user must exist").id + self.user.as_ref().expect("member is not partial").id } fn avatar(&self) -> Option { self.avatar diff --git a/lyra/src/bot/component/config/access.rs b/lyra/src/bot/component/config/access.rs index c7aa23e..9e9ffdf 100644 --- a/lyra/src/bot/component/config/access.rs +++ b/lyra/src/bot/component/config/access.rs @@ -80,7 +80,7 @@ impl CalculatorBuilder { .fetch_one(&db) .await? .0 - .expect("`exists` must not be `NULL`"); + .expect("SELECT EXISTS is non-null"); let (access_mode,) = sqlx::query_as::<_, (Option,)>(&format!( "--sql @@ -118,7 +118,7 @@ impl CalculatorBuilder { .fetch_one(&db) .await? else { - panic!("`exists` must not be `NULL`") + panic!("`exists` is `NULL`") }; let access_mode = sqlx::query!( diff --git a/lyra/src/bot/component/config/access/edit.rs b/lyra/src/bot/component/config/access/edit.rs index 8f0c633..c4acadf 100644 --- a/lyra/src/bot/component/config/access/edit.rs +++ b/lyra/src/bot/component/config/access/edit.rs @@ -5,7 +5,7 @@ use twilight_interactions::command::{ CommandModel, CommandOption, CreateCommand, CreateOption, ResolvedMentionable, }; use twilight_model::{ - application::interaction::application_command::InteractionChannel, + application::interaction::InteractionChannel, channel::ChannelType, id::{ marker::{ChannelMarker, GenericMarker}, @@ -40,10 +40,7 @@ fn add_access( g: i64, ids: impl IntoIterator>, ) { - let column = cat - .iter_names_as_column() - .next() - .expect("flags must not be empty"); + let column = cat.iter_names_as_column().next().expect("cat is non-empty"); let values_clause = ids.into_iter().map(|id| format!("($1,{id})")).join(","); set.spawn(async move { @@ -72,10 +69,7 @@ fn remove_access( g: i64, ids: impl IntoIterator>, ) { - let column = cat - .iter_names_as_column() - .next() - .expect("flags must not be empty"); + let column = cat.iter_names_as_column().next().expect("cat is non-empty"); let where_clause = ids.into_iter().map(|c| format!("id = {c}")).join(" OR "); set.spawn(async move { diff --git a/lyra/src/bot/component/connection.rs b/lyra/src/bot/component/connection.rs index 307f836..6ac06fd 100644 --- a/lyra/src/bot/component/connection.rs +++ b/lyra/src/bot/component/connection.rs @@ -126,7 +126,7 @@ async fn start_inactivity_timeout( .content(&format!( "๐Ÿ’ค๐Ÿ“Ž ~~{}~~ `(Left due to inactivity)`", channel_id.mention() - ))? + )) .await?; Ok(()) @@ -186,7 +186,7 @@ pub async fn handle_voice_state_update( "{}๐Ÿ“Ž ~~{}~~ `(Bot was forcefully disconnected)`", NOTICE, old_channel_id.mention() - ))? + )) .await?; } Some(old_state) => { @@ -247,7 +247,7 @@ async fn match_state_channel_id( old_channel_id.mention(), channel_id.mention(), forcefully_moved_notice - ))? + )) .await?; if matches!(joined.kind, JoinedChannelType::Stage) { diff --git a/lyra/src/bot/component/connection/join.rs b/lyra/src/bot/component/connection/join.rs index 2ffbe2d..63f02b9 100644 --- a/lyra/src/bot/component/connection/join.rs +++ b/lyra/src/bot/component/connection/join.rs @@ -5,7 +5,7 @@ use twilight_gateway::Event; use twilight_interactions::command::{CommandModel, CreateCommand}; use twilight_mention::Mention; use twilight_model::{ - application::interaction::application_command::InteractionChannel, + application::interaction::InteractionChannel, channel::ChannelType, gateway::payload::outgoing::UpdateVoiceState, guild::Permissions, diff --git a/lyra/src/bot/component/connection/leave.rs b/lyra/src/bot/component/connection/leave.rs index df2067f..05579bf 100644 --- a/lyra/src/bot/component/connection/leave.rs +++ b/lyra/src/bot/component/connection/leave.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use twilight_gateway::error::SendError; +use twilight_gateway::error::ChannelError; use twilight_interactions::command::{CommandModel, CreateCommand}; use twilight_mention::Mention; use twilight_model::{ @@ -31,7 +31,9 @@ impl Display for LeaveResponse { } } -pub(super) fn disconnect(ctx: &(impl SenderAware + ExpectedGuildIdAware)) -> Result<(), SendError> { +pub(super) fn disconnect( + ctx: &(impl SenderAware + ExpectedGuildIdAware), +) -> Result<(), ChannelError> { ctx.sender() .command(&UpdateVoiceState::new(ctx.guild_id(), None, false, false))?; diff --git a/lyra/src/bot/component/queue/move.rs b/lyra/src/bot/component/queue/move.rs index dcf9008..29e224b 100644 --- a/lyra/src/bot/component/queue/move.rs +++ b/lyra/src/bot/component/queue/move.rs @@ -173,17 +173,17 @@ impl BotSlashCommand for Move { ); } - let position = NonZeroUsize::new(self.position as usize) - .expect("`self.position as usize` must be nonzero"); + let position = + NonZeroUsize::new(self.position as usize).expect("self.position is non-zero"); check::users_track(position, in_voice_with_user, queue, &ctx)?; let track_position = - NonZeroUsize::new(self.track as usize).expect("`self.track as usize` must be nonzero"); + NonZeroUsize::new(self.track as usize).expect("self.track is non-zero"); let queue_position = queue.position(); let track = queue .remove(track_position.get() - 1) - .expect("`self.track as usize - 1` must be in bounds"); + .expect("self.track is in bounds"); let track_title = track.track().info.corrected_title(); let message = format!("โคด๏ธ Moved `{track_title}` to position **`{position}`**"); diff --git a/lyra/src/bot/component/queue/play.rs b/lyra/src/bot/component/queue/play.rs index 1f6cec6..d5a6f54 100644 --- a/lyra/src/bot/component/queue/play.rs +++ b/lyra/src/bot/component/queue/play.rs @@ -108,7 +108,7 @@ impl Playlist { tracks: data.tracks.into(), } } - _ => panic!("`loaded.load_type` must be `LoadType::PlaylistLoaded`"), + _ => panic!("`loaded.load_type` not `LoadType::PlaylistLoaded`"), } } } @@ -222,7 +222,7 @@ impl BotAutocomplete for Autocomplete { .then(|| format!("{}search:{}", source.value(), q).into_boxed_str()) .unwrap_or(q) }) - .expect("at least one option must be focused"); + .expect("exactly one option is focused"); let guild_id = ctx.guild_id(); let load_ctx = LoadTrackContext { @@ -243,7 +243,7 @@ impl BotAutocomplete for Autocomplete { name: t.prettify(), name_localizations: None, value: CommandOptionChoiceValue::String( - t.info.uri.expect("uri must exist"), + t.info.uri.expect("track is nonlocal"), ), }) .take(COMMAND_CHOICES_LIMIT) @@ -258,7 +258,7 @@ impl BotAutocomplete for Autocomplete { name: track.prettify(), name_localizations: None, value: CommandOptionChoiceValue::String( - track.info.uri.expect("uri must exist"), + track.info.uri.expect("track is nonlocal"), ), }] } @@ -286,7 +286,7 @@ impl BotAutocomplete for Autocomplete { name: track.prettify(), name_localizations: None, value: CommandOptionChoiceValue::String( - track.info.uri.expect("uri must exist"), + track.info.uri.expect("track is nonlocal"), ), }); } @@ -321,7 +321,7 @@ async fn play( format!( "[`{}`](<{}>)", t.info.corrected_title(), - t.info.uri.as_ref().expect("uri must exist") + t.info.uri.as_ref().expect("track is nonlocal") ) }) .collect::>() @@ -365,10 +365,7 @@ async fn play( util::auto_join_or_check_in_voice_with_user_and_check_not_suppressed(ctx).await?; let total_tracks = Vec::from(results); - let first_track = total_tracks - .first() - .expect("first track must exist") - .clone(); + let first_track = total_tracks.first().expect("results is non-empty").clone(); util::auto_new_player_data(ctx).await?; diff --git a/lyra/src/bot/component/queue/remove.rs b/lyra/src/bot/component/queue/remove.rs index c5eda0f..6a082c0 100644 --- a/lyra/src/bot/component/queue/remove.rs +++ b/lyra/src/bot/component/queue/remove.rs @@ -92,7 +92,7 @@ impl BotAutocomplete for Autocomplete { AutocompleteValue::Focused(i) => Some(i), _ => None, }) - .expect("at least one option must be focused"); + .expect("exactly one option is focused"); let choices = generate_remove_choices(&focused, finished, &ctx).await; Ok(ctx.autocomplete(choices).await?) diff --git a/lyra/src/bot/core/const.rs b/lyra/src/bot/core/const.rs index 057b7c4..edb5c39 100644 --- a/lyra/src/bot/core/const.rs +++ b/lyra/src/bot/core/const.rs @@ -59,9 +59,9 @@ pub mod metadata { let rdr = include_str!("../../../../assets/lyra2-ascii.ans"); let mut wtr = Vec::new(); - let ac = AhoCorasick::new(METADATA_PATTERNS).expect("pattern must be valid"); - ac.try_stream_replace_all(rdr.as_bytes(), &mut wtr, &METADATA_REPLACEMENTS).expect("searching must not fail"); - String::from_utf8(wtr).expect("slice must be UTF-8").into() + let ac = AhoCorasick::new(METADATA_PATTERNS).expect("METADATA_PATTERNS is valid"); + ac.try_stream_replace_all(rdr.as_bytes(), &mut wtr, &METADATA_REPLACEMENTS).expect("searching is infallible"); + String::from_utf8(wtr).expect("slice is UTF-8").into() }; } } @@ -113,13 +113,13 @@ pub mod regex { lazy_static::lazy_static! { pub static ref URL: Regex = Regex::new(r"(https://www\.|http://www\.|https://|http://)?[a-zA-Z]{2,}(\.[a-zA-Z]{2,})(\.[a-zA-Z]{2,})?/[a-zA-Z0-9]{2,}|((https://www\.|http://www\.|https://|http://)?[a-zA-Z]{2,}(\.[a-zA-Z]{2,})(\.[a-zA-Z]{2,})?)|(https://www\.|http://www\.|https://|http://)?[a-zA-Z0-9]{2,}\.[a-zA-Z0-9]{2,}\.[a-zA-Z0-9]{2,}(\.[a-zA-Z0-9]{2,})?") - .expect("regex must be valid"); + .expect("regex is valid"); pub static ref TIMESTAMP: Regex = Regex::new(r"^(((?[1-9]\d*):(?[0-5]\d))|(?[0-5]?\d)):(?[0-5]\d)(\.(?\d{3}))?$") - .expect("regex must be valild"); + .expect("regex is valild"); pub static ref TIMESTAMP_2: Regex = Regex::new(r"^((?[1-9]\d*)\s?hr?)?\s*((?[1-9]|[1-5]\d)\s?m(in)?)?\s*((?[1-9]|[1-5]\d)\s?s(ec)?)?\s*((?[1-9]\d{0,2})\s?ms(ec)?)?$") - .expect("regex must be valid"); + .expect("regex is valid"); } } diff --git a/lyra/src/bot/core/model.rs b/lyra/src/bot/core/model.rs index 6d08f07..469cd62 100644 --- a/lyra/src/bot/core/model.rs +++ b/lyra/src/bot/core/model.rs @@ -173,7 +173,7 @@ impl BotState { pub fn user(&self) -> CurrentUser { self.cache .current_user() - .expect("current user object must be available") + .expect("current user should be in cache") } #[inline] diff --git a/lyra/src/bot/core/model/interaction.rs b/lyra/src/bot/core/model/interaction.rs index 1d8492c..2b44856 100644 --- a/lyra/src/bot/core/model/interaction.rs +++ b/lyra/src/bot/core/model/interaction.rs @@ -83,9 +83,9 @@ impl Interface<'_> { pub async fn update_no_components_embeds(&self, content: &str) -> MessageFollowupResult { Ok(self .update() - .components(None)? - .embeds(None)? - .content(Some(content))? + .components(None) + .embeds(None) + .content(Some(content)) .await?) } @@ -109,7 +109,7 @@ impl Interface<'_> { Ok(self .inner .create_followup(self.interaction_token()) - .content(content)? + .content(content) .await?) } @@ -118,7 +118,7 @@ impl Interface<'_> { .inner .create_followup(self.interaction_token()) .flags(MessageFlags::EPHEMERAL) - .content(content)? + .content(content) .await?) } @@ -183,7 +183,7 @@ impl Interface<'_> { ) -> UnitFollowupResult { self.inner .update_followup(self.interaction_token(), message_id) - .content(Some(content))? + .content(Some(content)) .await?; Ok(()) } @@ -230,16 +230,16 @@ impl<'a> Client<'a> { ) -> &'static twilight_model::application::command::Command { POPULATED_COMMANDS_MAP .get() - .expect("`POPULATED_COMMANDS_MAP` must be populated") + .expect("POPULATED_COMMANDS_MAP is populated") .get(T::name()) - .unwrap_or_else(|| panic!("command must exist: {}", T::name())) + .unwrap_or_else(|| panic!("command not found: {}", T::name())) } pub fn mention_command() -> Box { let cmd = Self::populated_command::(); let name = &cmd.name; - let id = cmd.id.expect("id must exist"); + let id = cmd.id.expect("id exists"); format!("").into_boxed_str() } } diff --git a/lyra/src/bot/error/command.rs b/lyra/src/bot/error/command.rs index de9abef..2f928fc 100644 --- a/lyra/src/bot/error/command.rs +++ b/lyra/src/bot/error/command.rs @@ -76,7 +76,7 @@ pub enum FlattenedError<'a> { PollVoided(&'a check::PollVoidedError), StandbyCanceled(&'a twilight_standby::future::Canceled), Confirmation(&'a util::ConfirmationError), - GatewaySend(&'a twilight_gateway::error::SendError), + GatewaySend(&'a twilight_gateway::error::ChannelError), AutoJoinSuppressed(&'a util::AutoJoinSuppressedError), AutoJoinAttemptFailed(&'a super::AutoJoinAttemptFailed), Lavalink(&'a lavalink_rs::error::LavalinkError), diff --git a/lyra/src/bot/error/command/util.rs b/lyra/src/bot/error/command/util.rs index 4c31f2b..26b9619 100644 --- a/lyra/src/bot/error/command/util.rs +++ b/lyra/src/bot/error/command/util.rs @@ -34,7 +34,7 @@ pub enum ResidualUserAllowedError { pub enum ResidualImplConnectToError { CheckUserAllowed(#[from] ResidualUserAllowedError), Cache(#[from] crate::bot::error::Cache), - GatewaySend(#[from] twilight_gateway::error::SendError), + GatewaySend(#[from] twilight_gateway::error::ChannelError), TwilightHttp(#[from] twilight_http::Error), Lavalink(#[from] lavalink_rs::error::LavalinkError), } diff --git a/lyra/src/bot/error/component/connection.rs b/lyra/src/bot/error/component/connection.rs index 493445c..3fe8ff7 100644 --- a/lyra/src/bot/error/component/connection.rs +++ b/lyra/src/bot/error/component/connection.rs @@ -23,7 +23,7 @@ pub mod join { Forbidden(#[from] crate::bot::error::ConnectionForbidden), CheckUserAllowed(#[from] check::UserAllowedError), Cache(#[from] crate::bot::error::Cache), - GatewaySend(#[from] twilight_gateway::error::SendError), + GatewaySend(#[from] twilight_gateway::error::ChannelError), TwilightHttp(#[from] twilight_http::Error), Lavalink(#[from] lavalink_rs::error::LavalinkError), } @@ -122,7 +122,7 @@ pub mod join { pub enum ResidualImplConnectToError { CheckUserAllowed(#[from] ResidualUserAllowedError), Cache(#[from] crate::bot::error::Cache), - GatewaySend(#[from] twilight_gateway::error::SendError), + GatewaySend(#[from] twilight_gateway::error::ChannelError), TwilightHttp(#[from] twilight_http::Error), Lavalink(#[from] lavalink_rs::error::LavalinkError), } @@ -265,7 +265,7 @@ pub mod leave { InVoiceWithoutUser(#[from] crate::bot::error::InVoiceWithoutUser), CheckUserOnlyIn(#[from] crate::bot::error::command::check::UserOnlyInError), PreDisconnectCleanup(#[from] PreDisconnectCleanupError), - GatewaySend(#[from] twilight_gateway::error::SendError), + GatewaySend(#[from] twilight_gateway::error::ChannelError), } impl Error { @@ -299,7 +299,7 @@ pub mod leave { InVoiceWithoutUser(#[from] crate::bot::error::InVoiceWithoutUser), CheckUserOnlyIn(#[from] crate::bot::error::command::check::UserOnlyInError), PreDisconnectCleanupError(#[from] PreDisconnectCleanupError), - GatewaySend(#[from] twilight_gateway::error::SendError), + GatewaySend(#[from] twilight_gateway::error::ChannelError), } } @@ -309,7 +309,7 @@ use thiserror::Error; #[error("starting inactivity timeout failed: {:?}", .0)] pub enum StartInactivityTimeoutError { EventSend(#[from] tokio::sync::broadcast::error::SendError), - GatewaySend(#[from] twilight_gateway::error::SendError), + GatewaySend(#[from] twilight_gateway::error::ChannelError), MessageValidation(#[from] twilight_validate::message::MessageValidationError), Http(#[from] twilight_http::Error), PreDisconnectCleanup(#[from] leave::PreDisconnectCleanupError), diff --git a/lyra/src/bot/error/runner.rs b/lyra/src/bot/error/runner.rs index 4c68c06..5763b1d 100644 --- a/lyra/src/bot/error/runner.rs +++ b/lyra/src/bot/error/runner.rs @@ -3,7 +3,7 @@ use thiserror::Error; #[derive(Error, Debug)] #[error("starting bot failed: {:?}", .0)] pub enum StartError { - StartRecommended(#[from] twilight_gateway::stream::StartRecommendedError), + StartRecommended(#[from] twilight_gateway::error::StartRecommendedError), Sqlx(#[from] sqlx::Error), DeserializeBody(#[from] twilight_http::response::DeserializeBodyError), Http(#[from] twilight_http::Error), diff --git a/lyra/src/bot/ext/image.rs b/lyra/src/bot/ext/image.rs index d52bda8..7c5a941 100644 --- a/lyra/src/bot/ext/image.rs +++ b/lyra/src/bot/ext/image.rs @@ -40,7 +40,7 @@ impl DominantPalette for DynamicImage { ) }) .max_by(|k1, k2| k1.score.total_cmp(&k2.score)) - .expect("`RUNS` must be greater or equal to 1"); + .expect("RUNS is non-zero"); let mut res = Lab::sort_indexed_colors(&result.centroids, &result.indices); res.sort_unstable_by(|a, b| (b.percentage).total_cmp(&a.percentage)); diff --git a/lyra/src/bot/ext/util.rs b/lyra/src/bot/ext/util.rs index 48678f6..fcf3e2c 100644 --- a/lyra/src/bot/ext/util.rs +++ b/lyra/src/bot/ext/util.rs @@ -8,7 +8,6 @@ use bitflags::Flags; use chrono::Duration; use heck::ToTitleCase; use itertools::Itertools; -use twilight_model::guild::Permissions; use unicode_segmentation::UnicodeSegmentation; use crate::bot::{ @@ -159,19 +158,6 @@ impl PrettyTruncator for str { } } -pub trait BitFlagsPrettify: Debug { - fn prettify_code(&self) -> String { - format!("{self:?}") - .split(" | ") - .map(|s| format!("`{}`", s.to_title_case())) - .collect::>() - .pretty_join_with_and() - } -} - -impl BitFlagsPrettify for Permissions {} - -// FIXME: Use this impl instead once twilight updated bitflags to 2.x.x pub trait FlagsPrettify: Flags { fn prettify(&self) -> String { self.iter_names() @@ -309,8 +295,8 @@ impl Iterator for MultiInterleave { } } -/* FIXME: make this generic over `T: std::ops::Add + std::ops::AddAssign + std::iter::Step + Copy` - once `std::iter::Step` is stablised: https://github.com/rust-lang/rust/issues/42168 +/* FIXME: make this generic over `T: std::ops::Add + std::ops::AddAssign + std::iter::Step + Copy` once `std::iter::Step` is stablised: + https://github.com/rust-lang/rust/issues/42168 */ pub fn chunked_range( start: usize, diff --git a/lyra/src/bot/gateway/guild.rs b/lyra/src/bot/gateway/guild.rs index feb9331..3b72eca 100644 --- a/lyra/src/bot/gateway/guild.rs +++ b/lyra/src/bot/gateway/guild.rs @@ -15,7 +15,9 @@ pub(super) struct CreateContext<'a> { impl CreateContext<'_> { async fn increment_guild_count(&self) -> Result<(), sqlx::Error> { - // FIXME: wait until twilight stop deserializing missing `Guild::unavailable` to false + /* FIXME: wait until twilight stop deserializing missing `Guild::unavailable` to false: + https://github.com/twilight-rs/twilight/pull/2330 + */ if !self.inner.unavailable { return Ok(()); } diff --git a/lyra/src/bot/gateway/interaction.rs b/lyra/src/bot/gateway/interaction.rs index 7450f8a..d24e9f8 100644 --- a/lyra/src/bot/gateway/interaction.rs +++ b/lyra/src/bot/gateway/interaction.rs @@ -92,7 +92,7 @@ impl Context { .channel .as_ref() .map(|c| c.id) - .expect("channel must exist"); + .expect("interaction type is not ping"); let result = match data.kind { CommandType::ChatInput => { diff --git a/lyra/src/bot/gateway/model.rs b/lyra/src/bot/gateway/model.rs index d4fb95e..56ed0e7 100644 --- a/lyra/src/bot/gateway/model.rs +++ b/lyra/src/bot/gateway/model.rs @@ -32,9 +32,7 @@ impl LastCachedStates { Event::VoiceStateUpdate(event) => cache .voice_state( event.user_id, - event - .guild_id - .expect("`VoiceStateUpdate::guild_id` must exist"), + event.guild_id.expect("event received in a guild"), ) .as_deref() .cloned(), diff --git a/lyra/src/bot/gateway/voice.rs b/lyra/src/bot/gateway/voice.rs index 604de00..f4aaad6 100644 --- a/lyra/src/bot/gateway/voice.rs +++ b/lyra/src/bot/gateway/voice.rs @@ -47,9 +47,7 @@ impl Context { } pub fn guild_id(&self) -> Id { - self.inner - .guild_id - .expect("`VoiceStateUpdate::guild_id` must exist") + self.inner.guild_id.expect("event received in a guild") } } @@ -91,9 +89,7 @@ impl SenderAware for Context { impl ExpectedGuildIdAware for Context { fn guild_id(&self) -> Id { - self.inner - .guild_id - .expect("`VoiceStateUpdate::guild_id` must exist") + self.inner.guild_id.expect("event received in a guild") } } diff --git a/lyra/src/bot/lavalink/model.rs b/lyra/src/bot/lavalink/model.rs index d645965..26b2a29 100644 --- a/lyra/src/bot/lavalink/model.rs +++ b/lyra/src/bot/lavalink/model.rs @@ -90,7 +90,7 @@ pub trait DelegateMethods { } twilight_gateway::Event::VoiceStateUpdate(e) => { self._handle_voice_state_update( - e.guild_id.expect("guild_id must exist"), + e.guild_id.expect("event received in a guild"), e.channel_id, e.user_id, e.session_id.clone(), @@ -105,25 +105,6 @@ pub trait DelegateMethods { guild_id: impl Into + Send, timeout: std::time::Duration, ) -> LavalinkResult; - async fn get_lavalink_connection_info( - &self, - guild_id: impl Into + Send, - ) -> Option { - self._get_connection_info( - guild_id, - *r#const::connection::GET_LAVALINK_CONNECTION_INFO_TIMEOUT, - ) - .await - .ok() - } - async fn lavalink_connection_info( - &self, - guild_id: impl Into + Send, - ) -> ConnectionInfo { - self.get_lavalink_connection_info(guild_id) - .await - .expect("timeout should not have been reached") - } async fn _create_player_context_with_data( &self, @@ -136,7 +117,12 @@ pub trait DelegateMethods { guild_id: impl Into + Send + Copy, ) -> LavalinkResult<()> { let now = tokio::time::Instant::now(); - let info = self.lavalink_connection_info(guild_id).await; + let info = self + ._get_connection_info( + guild_id, + *r#const::connection::GET_LAVALINK_CONNECTION_INFO_TIMEOUT, + ) + .await?; tracing::trace!("getting lavalink connection info took {:?}", now.elapsed()); let data = Arc::new(RwLock::new(PlayerData::new())); @@ -152,16 +138,14 @@ pub trait DelegateMethods { guild_id: impl Into + Send, ) -> Option>> { self._get_player_context(guild_id) - .map(|c| c.data().expect("data type must be valid")) + .map(|c| c.data().expect("data type is valid")) } fn player(&self, guild_id: impl Into + Send) -> PlayerContext { self._get_player_context(guild_id) - .expect("player context must exist") + .expect("player context exists") } fn player_data(&self, guild_id: impl Into + Send) -> Arc> { - self.player(guild_id) - .data() - .expect("data type must be valid") + self.player(guild_id).data().expect("data type is valid") } } @@ -193,13 +177,12 @@ impl Lavalink { } pub fn connection(&self, guild_id: Id) -> ConnectionRef { - self.get_connection(guild_id) - .expect("connection must exist") + self.get_connection(guild_id).expect("connection exists") } pub fn connection_mut(&self, guild_id: Id) -> ConnectionRefMut { self.get_connection_mut(guild_id) - .expect("connection must exist") + .expect("connection exists") } pub fn notify_connection_change(&self, guild_id: Id) { diff --git a/lyra/src/bot/lavalink/model/queue.rs b/lyra/src/bot/lavalink/model/queue.rs index 2d2434e..12007a0 100644 --- a/lyra/src/bot/lavalink/model/queue.rs +++ b/lyra/src/bot/lavalink/model/queue.rs @@ -117,13 +117,8 @@ impl Queue { } pub fn position(&self) -> NonZeroUsize { - NonZeroUsize::new( - self.index - + self - .current() - .map_or_else(|| usize::from(self.index == 0), |_| 1), - ) - .expect("`self.index + 1` must be nonzero") + let d = usize::from(self.current().is_some() || self.index == 0); + NonZeroUsize::new(self.index + d).expect("self.index + d is non-zero") } pub const fn index(&self) -> &usize { diff --git a/lyra/src/bot/runner.rs b/lyra/src/bot/runner.rs index 3470ed3..543cab6 100644 --- a/lyra/src/bot/runner.rs +++ b/lyra/src/bot/runner.rs @@ -1,4 +1,10 @@ -use std::{str::FromStr, sync::Arc}; +use std::{ + str::FromStr, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, +}; use dotenvy_macro::dotenv; use lavalink_rs::{client::LavalinkClient, model::client::NodeDistributionStrategy}; @@ -7,12 +13,12 @@ use sqlx::{ postgres::{PgConnectOptions, PgPoolOptions}, ConnectOptions, }; -use tokio::{sync::watch, task::JoinSet}; +use tokio::task::JoinHandle; use twilight_gateway::{ - stream::{self, StartRecommendedError}, - CloseFrame, Config as ShardConfig, Event, + error::{ReceiveMessageErrorType, StartRecommendedError}, + CloseFrame, Config as ShardConfig, ConfigBuilder, Event, EventTypeFlags, Intents, + MessageSender, Shard, StreamExt as _, }; -use twilight_gateway::{ConfigBuilder, Intents, Shard}; use twilight_http::{client::ClientBuilder, Client}; use twilight_model::{ channel::message::AllowedMentions, @@ -44,6 +50,8 @@ const CONFIG: Config = Config { }; const INTENTS: Intents = Intents::GUILDS.union(Intents::GUILD_VOICE_STATES); +static SHUTDOWN: AtomicBool = AtomicBool::new(false); + fn build_http_client() -> Client { ClientBuilder::default() .default_allowed_mentions(AllowedMentions::default()) @@ -64,7 +72,7 @@ fn build_shard_config() -> ShardConfig { None, Status::Online, ) - .expect("activities must not be empty"), + .expect("activities is non-empty"), ) .build() } @@ -85,35 +93,28 @@ pub(super) async fn start() -> Result<(), StartError> { let lavalink = build_lavalink_client(user_id).await; let shards = build_and_split_shards(&http).await?; + let shards_len = shards.len(); + let mut senders = Vec::with_capacity(shards_len); + let mut tasks = Vec::with_capacity(shards_len); let bot = Arc::new(BotState::new(db, http, lavalink)); bot.interaction().await?.register_global_commands().await?; - let (tx, rx) = watch::channel(false); - let mut set = JoinSet::new(); - for mut shard in shards { - let mut rx = rx.clone(); - let bot = bot.clone(); - - set.spawn(async move { - tokio::select! { - () = handle_gateway_events(&mut shard, bot.clone()) => {}, - _ = rx.changed() => { - _ = shard.close(CloseFrame::NORMAL).await; - } - } - }); + for shard in shards { + senders.push(shard.sender()); + tasks.push(tokio::spawn(handle_gateway_events(shard, bot.clone()))); } - print_banner(); - Ok(wait_until_shutdown(tx, set).await?) + println!("{}", *BANNER); + Ok(wait_until_shutdown(senders, tasks).await?) } async fn build_and_split_shards( client: &Client, -) -> Result, StartRecommendedError> { +) -> Result, StartRecommendedError> { let shard_config = build_shard_config(); let shards = - stream::create_recommended(client, shard_config, |_, builder| builder.build()).await?; + twilight_gateway::create_recommended(client, shard_config, |_, builder| builder.build()) + .await?; Ok(shards) } @@ -133,22 +134,26 @@ async fn build_lavalink_client(user_id: Id) -> Lavalink { } #[tracing::instrument(skip_all, name = "gateway")] -async fn handle_gateway_events(shard: &mut Shard, bot: Arc) { - loop { - let event = match shard.next_event().await { +async fn handle_gateway_events(mut shard: Shard, bot: Arc) { + while let Some(item) = shard.next_event(EventTypeFlags::all()).await { + let event = match item { + Ok(Event::GatewayClose(_)) if SHUTDOWN.load(Ordering::Relaxed) => break, Ok(event) => event, + Err(source) + if SHUTDOWN.load(Ordering::Relaxed) + && matches!(source.kind(), ReceiveMessageErrorType::WebSocket) => + { + break + } Err(source) => { tracing::warn!(?source, "error receiving event"); - if source.is_fatal() { - break; - } - continue; } }; - process_gateway_events(shard, event, bot.clone()); + tracing::trace!(?event, shard = ?shard.id(), "received event"); + process_gateway_events(&shard, event, bot.clone()); } } @@ -169,10 +174,6 @@ fn process_gateway_events(shard: &Shard, event: Event, bot: Arc) { )); } -fn print_banner() { - println!("{}", *BANNER); -} - #[tracing::instrument] async fn wait_for_signal() -> Result<(), WaitForSignalError> { #[cfg(target_family = "unix")] @@ -200,14 +201,19 @@ async fn wait_for_signal() -> Result<(), WaitForSignalError> { #[tracing::instrument(skip_all, name = "shutdown")] async fn wait_until_shutdown( - tx: watch::Sender, - mut set: JoinSet<()>, + senders: Vec, + tasks: Vec>, ) -> Result<(), WaitUntilShutdownError> { wait_for_signal().await?; tracing::info!("gracefully shutting down..."); - tx.send(true)?; - while set.join_next().await.is_some() {} - tracing::info!("shut down gracefully"); + SHUTDOWN.store(true, Ordering::Relaxed); + for sender in senders { + _ = sender.close(CloseFrame::NORMAL); + } + for jh in tasks { + _ = jh.await; + } + tracing::info!("shut down gracefully"); Ok(()) }