diff --git a/Cargo.lock b/Cargo.lock index ddb7723..8534754 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,6 +82,9 @@ name = "arrayvec" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +dependencies = [ + "serde", +] [[package]] name = "async-convert" @@ -100,7 +103,7 @@ checksum = "9b26209963c22f8607fca31865e62793954f1fdf265135131e614584a863b799" dependencies = [ "async-convert", "backoff", - "base64 0.21.7", + "base64", "bytes", "derive_builder", "futures", @@ -150,22 +153,6 @@ dependencies = [ "syn 2.0.48", ] -[[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", - "webpki-roots 0.22.6", -] - [[package]] name = "atoi" version = "2.0.0" @@ -229,12 +216,6 @@ dependencies = [ "backtrace", ] -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.7" @@ -356,6 +337,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "bytecount" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" + [[package]] name = "byteorder" version = "1.5.0" @@ -368,6 +355,37 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +[[package]] +name = "camino" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", +] + [[package]] name = "cc" version = "1.0.83" @@ -501,6 +519,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" version = "0.8.5" @@ -551,8 +578,18 @@ version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core 0.20.3", + "darling_macro 0.20.3", ] [[package]] @@ -569,17 +606,42 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.48", +] + [[package]] name = "darling_macro" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ - "darling_core", + "darling_core 0.14.4", "quote", "syn 1.0.109", ] +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core 0.20.3", + "quote", + "syn 2.0.48", +] + [[package]] name = "dashmap" version = "5.5.3" @@ -594,6 +656,12 @@ dependencies = [ "serde", ] +[[package]] +name = "data-encoding" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" + [[package]] name = "der" version = "0.7.8" @@ -641,7 +709,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" dependencies = [ - "darling", + "darling 0.14.4", "proc-macro2", "quote", "syn 1.0.109", @@ -735,6 +803,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "error-chain" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" +dependencies = [ + "version_check", +] + [[package]] name = "etcetera" version = "0.8.0" @@ -923,6 +1000,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -950,6 +1036,12 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "globset" version = "0.4.14" @@ -1145,9 +1237,9 @@ dependencies = [ "futures-util", "http", "hyper", - "rustls 0.21.10", + "rustls", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls", ] [[package]] @@ -1275,9 +1367,9 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ "wasm-bindgen", ] @@ -1400,6 +1492,21 @@ dependencies = [ "unicase", ] +[[package]] +name = "mini-moka" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c325dfab65f261f386debee8b0969da215b3fa0037e74c8a1234db7ba986d803" +dependencies = [ + "crossbeam-channel", + "crossbeam-utils", + "dashmap", + "skeptic", + "smallvec", + "tagptr", + "triomphe", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1537,15 +1644,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" -[[package]] -name = "ordered-float" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" -dependencies = [ - "num-traits", -] - [[package]] name = "ordered-float" version = "3.9.2" @@ -1768,33 +1866,31 @@ checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" [[package]] name = "poise" -version = "0.5.7" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d104e4b5847283b2fbd6a7ec19fb6a8af328e2145623d056b66d750a30073fdf" +checksum = "1819d5a45e3590ef33754abce46432570c54a120798bdbf893112b4211fa09a6" dependencies = [ "async-trait", "derivative", - "futures-core", "futures-util", - "log", - "once_cell", "parking_lot", "poise_macros", "regex", "serenity", "tokio", + "tracing", ] [[package]] name = "poise_macros" -version = "0.5.7" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb516a8cf4e4ae4bd7ef5819d08c6ca408976461a9bea3ee3eec5138ac070c1" +checksum = "8fa2c123c961e78315cd3deac7663177f12be4460f5440dbf62a7ed37b1effea" dependencies = [ - "darling", + "darling 0.20.3", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] @@ -1871,6 +1967,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "pulldown-cmark" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" +dependencies = [ + "bitflags 1.3.2", + "memchr", + "unicase", +] + [[package]] name = "quote" version = "1.0.35" @@ -1969,7 +2076,7 @@ version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ - "base64 0.21.7", + "base64", "bytes", "encoding_rs", "futures-core", @@ -1987,7 +2094,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.10", + "rustls", "rustls-native-certs", "rustls-pemfile", "serde", @@ -1995,7 +2102,7 @@ dependencies = [ "serde_urlencoded", "system-configuration", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -2003,7 +2110,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 0.25.3", + "webpki-roots", "winreg", ] @@ -2023,21 +2130,6 @@ dependencies = [ "thiserror", ] -[[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.7" @@ -2048,7 +2140,7 @@ dependencies = [ "getrandom", "libc", "spin 0.9.8", - "untrusted 0.9.0", + "untrusted", "windows-sys 0.48.0", ] @@ -2136,18 +2228,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" @@ -2155,7 +2235,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring 0.17.7", + "ring", "rustls-webpki", "sct", ] @@ -2178,7 +2258,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.7", + "base64", ] [[package]] @@ -2187,16 +2267,10 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", + "ring", + "untrusted", ] -[[package]] -name = "rustversion" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - [[package]] name = "ryu" version = "1.0.16" @@ -2233,8 +2307,8 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -2294,15 +2368,15 @@ dependencies = [ [[package]] name = "sea-query" -version = "0.30.6" +version = "0.30.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a1feb0a26c02efedb049b22d3884e66f15a40c42b33dcbe49b46abc484c2bd" +checksum = "4166a1e072292d46dc91f31617c2a1cdaf55a8be4b5c9f4bf2ba248e3ac4999b" dependencies = [ "bigdecimal", "chrono", "derivative", "inherent", - "ordered-float 3.9.2", + "ordered-float", "rust_decimal", "serde_json", "time", @@ -2369,6 +2443,9 @@ name = "semver" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +dependencies = [ + "serde", +] [[package]] name = "serde" @@ -2379,16 +2456,6 @@ 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 2.10.1", - "serde", -] - [[package]] name = "serde_derive" version = "1.0.195" @@ -2425,47 +2492,36 @@ dependencies = [ [[package]] name = "serenity" -version = "0.11.7" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a7a89cef23483fc9d4caf2df41e6d3928e18aada84c56abd237439d929622c6" +checksum = "385647faa24a889929028973650a4f158fb1b4272b2fcf94feb9fcc3c009e813" dependencies = [ + "arrayvec", "async-trait", - "async-tungstenite", - "base64 0.21.7", - "bitflags 1.3.2", + "base64", + "bitflags 2.4.1", "bytes", - "cfg-if", "chrono", "dashmap", "flate2", "futures", - "mime", + "fxhash", "mime_guess", "parking_lot", "percent-encoding", "reqwest", - "rustversion", + "secrecy", "serde", - "serde-value", "serde_json", "time", "tokio", + "tokio-tungstenite", "tracing", "typemap_rev", + "typesize", "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.6" @@ -2519,6 +2575,21 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "skeptic" +version = "0.13.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8" +dependencies = [ + "bytecount", + "cargo_metadata", + "error-chain", + "glob", + "pulldown-cmark", + "tempfile", + "walkdir", +] + [[package]] name = "slab" version = "0.4.9" @@ -2640,7 +2711,7 @@ dependencies = [ "paste", "percent-encoding", "rust_decimal", - "rustls 0.21.10", + "rustls", "rustls-pemfile", "serde", "serde_json", @@ -2654,7 +2725,7 @@ dependencies = [ "tracing", "url", "uuid", - "webpki-roots 0.25.3", + "webpki-roots", ] [[package]] @@ -2704,7 +2775,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" dependencies = [ "atoi", - "base64 0.21.7", + "base64", "bigdecimal", "bitflags 2.4.1", "byteorder", @@ -2751,7 +2822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" dependencies = [ "atoi", - "base64 0.21.7", + "base64", "bigdecimal", "bitflags 2.4.1", "byteorder", @@ -2933,6 +3004,12 @@ dependencies = [ "libc", ] +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "tap" version = "1.0.1" @@ -3096,24 +3173,13 @@ dependencies = [ "syn 2.0.48", ] -[[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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.10", + "rustls", "tokio", ] @@ -3128,6 +3194,21 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +dependencies = [ + "futures-util", + "log", + "rustls", + "tokio", + "tokio-rustls", + "tungstenite", + "webpki-roots", +] + [[package]] name = "tokio-util" version = "0.7.10" @@ -3223,6 +3304,12 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "triomphe" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" + [[package]] name = "try-lock" version = "0.2.5" @@ -3231,30 +3318,29 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" -version = "0.17.3" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" dependencies = [ - "base64 0.13.1", "byteorder", "bytes", + "data-encoding", "http", "httparse", "log", "rand", - "rustls 0.20.9", - "sha-1", + "rustls", + "sha1", "thiserror", "url", "utf-8", - "webpki", ] [[package]] name = "typemap_rev" -version = "0.1.5" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5b74f0a24b5454580a79abb6994393b09adf0ab8070f15827cb666255de155" +checksum = "74b08b0c1257381af16a5c3605254d529d3e7e109f3c62befc5d168968192998" [[package]] name = "typenum" @@ -3262,6 +3348,35 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "typesize" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36924509726e38224322c8c90ddfbf4317324338327b7c11b7cf8672cb786da1" +dependencies = [ + "chrono", + "dashmap", + "hashbrown 0.14.3", + "mini-moka", + "parking_lot", + "secrecy", + "serde_json", + "time", + "typesize-derive", + "url", +] + +[[package]] +name = "typesize-derive" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b122284365ba8497be951b9a21491f70c9688eb6fddc582931a0703f6a00ece" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "ucd-trie" version = "0.1.6" @@ -3372,12 +3487,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" @@ -3462,9 +3571,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3472,9 +3581,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", @@ -3487,9 +3596,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" dependencies = [ "cfg-if", "js-sys", @@ -3499,9 +3608,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3509,9 +3618,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", @@ -3522,9 +3631,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "wasm-streams" @@ -3541,33 +3650,14 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" dependencies = [ "js-sys", "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.7", - "untrusted 0.9.0", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki", -] - [[package]] name = "webpki-roots" version = "0.25.3" diff --git a/Cargo.toml b/Cargo.toml index dc01b60..4387f8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ name = "cheapt" description = "OpenAI based chat bot for discord. Plain and simple. Requires OpenAI API key." repository = "https://github.com/chrisliebaer/cheapt" version = "0.1.0" +keywords = ["discord", "chat", "bot", "openai"] edition = "2021" license = "MIT" categories = ["games"] @@ -16,11 +17,11 @@ semver = "1.0" chrono = "0.4" serde = "1.0" lazy_static = "1.4" -tokio = { version = "1.34", features = ["macros", "rt", "time"] } +tokio = { version = "1.35", features = ["macros", "rt", "time"] } sea-orm = { version = "0.12", features = ["sqlx-mysql", "runtime-tokio-rustls", "macros"] } async-openai = "0.18" envconfig = "0.10" -poise = "0.5" +poise = "0.6" regex = "1.10" tera = "1" diff --git a/deny.toml b/deny.toml index 484e765..f5a78ec 100644 --- a/deny.toml +++ b/deny.toml @@ -1,11 +1,11 @@ # cargo-deny is really only ever intended to run on the "normal" tier-1 targets targets = [ - { triple = "x86_64-unknown-linux-gnu" }, - { triple = "aarch64-unknown-linux-gnu" }, - { triple = "x86_64-unknown-linux-musl" }, - { triple = "aarch64-apple-darwin" }, - { triple = "x86_64-apple-darwin" }, - { triple = "x86_64-pc-windows-msvc" }, + { triple = "x86_64-unknown-linux-gnu" }, + { triple = "aarch64-unknown-linux-gnu" }, + { triple = "x86_64-unknown-linux-musl" }, + { triple = "aarch64-apple-darwin" }, + { triple = "x86_64-apple-darwin" }, + { triple = "x86_64-pc-windows-msvc" }, ] [advisories] @@ -15,6 +15,11 @@ notice = "warn" unsound = "deny" yanked = "deny" +ignore = [ + # we are only consuming a tls endpoint + "RUSTSEC-2023-0071" +] + [bans] multiple-versions = "allow" wildcards = "deny" @@ -31,4 +36,16 @@ confidence-threshold = 0.93 allow-osi-fsf-free = "both" exceptions = [ + { allow = ["Unicode-DFS-2016"], name = "unicode-ident" }, + # ring is using multiple intermangled licenses + { allow = ["ISC", "OpenSSL"], name = "ring" }, + { allow = ["MPL-2.0"], name = "webpki-roots" } +] + + +[[licenses.clarify]] +name = "ring" +expression = "MIT AND ISC AND OpenSSL" +license-files = [ + { path = "LICENSE", hash = 0xbd0eed23 } ] diff --git a/src/completion.rs b/src/completion.rs index 541860f..c9d1f4b 100644 --- a/src/completion.rs +++ b/src/completion.rs @@ -13,11 +13,12 @@ use miette::{ }; use poise::serenity_prelude::{ ChannelId, + CreateMessage, Message, }; use tracing::{ - debug, info, + trace, }; use crate::{ @@ -36,7 +37,7 @@ struct GuildContext { impl From<&poise::serenity_prelude::PartialGuild> for GuildContext { fn from(guild: &poise::serenity_prelude::PartialGuild) -> Self { Self { - id: guild.id.0, + id: guild.id.into(), name: guild.name.clone(), members: guild.approximate_member_count, } @@ -53,7 +54,7 @@ struct ChannelContext { impl From<&poise::serenity_prelude::GuildChannel> for ChannelContext { fn from(channel: &poise::serenity_prelude::GuildChannel) -> Self { Self { - id: channel.id.0, + id: channel.id.into(), name: channel.name.clone(), topic: channel.topic.clone(), } @@ -69,7 +70,7 @@ struct UserContext { impl From<&poise::serenity_prelude::User> for UserContext { fn from(user: &poise::serenity_prelude::User) -> Self { Self { - id: user.id.0, + id: user.id.into(), name: user.name.clone(), } } @@ -119,13 +120,14 @@ async fn create_tera_context<'a>(ctx: &'a poise::serenity_prelude::Context, mess .wrap_err("failed to fetch guild")?; // if we are in guild, we will use whatever name we have in the guild + let id = ctx.cache.current_user().id; let self_member = guild - .member(ctx, ctx.cache.current_user_id()) + .member(ctx, id) .await .into_diagnostic() .wrap_err("failed to fetch ourself as guild member")? .nick - .unwrap_or_else(|| ctx.cache.current_user().name); + .unwrap_or_else(|| ctx.cache.current_user().name.to_string()); tera_context.insert("name", &self_member); let channel = message @@ -189,7 +191,7 @@ async fn generate_openai_response<'a>( let chat_history = chat_history.iter().map(|m| m.into()).collect::>(); // add all messages to invocation builder, so it can remove markup and extract users and emotes - let mut invocation_builder = InvocationBuilder::new(ctx.cache.current_user_id(), "you"); + let mut invocation_builder = InvocationBuilder::new(ctx.cache.current_user().id, "you"); for message in chat_history { invocation_builder.add_message(message); } @@ -218,7 +220,7 @@ async fn generate_openai_response<'a>( .into_diagnostic() .wrap_err("completion request failed")?; - let choice = response.choices.get(0).ok_or(miette!("Empty choice array received"))?; + let choice = response.choices.first().ok_or(miette!("Empty choice array received"))?; info!(finish_reason = ?choice.finish_reason, "OpenAI response: {:?}", choice.message.content); if choice.finish_reason == Some(FinishReason::ContentFilter) { @@ -231,14 +233,11 @@ async fn generate_openai_response<'a>( .as_ref() .ok_or(miette!("OpenAI response has no content"))?; + let content = invocation_builder.retransform_response(content); + message .channel_id - .send_message(ctx, |m| { - m.reference_message(message); - m.allowed_mentions(|am| am.empty_parse().replied_user(true)); - m.content(content); - m - }) + .send_message(ctx, CreateMessage::new().reference_message(message).content(content)) .await .into_diagnostic() .wrap_err("failed to send reply message")?; @@ -269,7 +268,7 @@ fn dump_request_messages(messages: &Vec) { lines.push(message); } - debug!("Sending following context to completion:\n{}", lines.join("\n")); + trace!("Sending following context to completion:\n{}", lines.join("\n")); } /// Sends a typing indicator to a specified channel every 5 seconds, while running a separate task to handle messages @@ -314,5 +313,5 @@ fn dump_extracted_messages(messages: &[ContextMessageVariant]) { lines.push(format!("{}({}): {}", reason, message.author.name, message.content)); } - debug!("Extracted the following messages from discord:\n{}", lines.join("\n")); + trace!("Extracted the following messages from discord:\n{}", lines.join("\n")); } diff --git a/src/context_extraction.rs b/src/context_extraction.rs index 2583ee1..4311be4 100644 --- a/src/context_extraction.rs +++ b/src/context_extraction.rs @@ -5,6 +5,7 @@ use miette::{ }; use poise::serenity_prelude::{ Context, + GetMessages, Message, }; @@ -83,7 +84,7 @@ impl InvocationContextSettings { for center in chain_messages { let window = message .channel_id - .messages(ctx, |f| f.around(center.id).limit(reply_chain_window as u64)) + .messages(ctx, GetMessages::new().around(center.id).limit(reply_chain_window as u8)) .await .into_diagnostic() .wrap_err("failed to fetch reply chain window")?; @@ -129,7 +130,7 @@ impl InvocationContextSettings { if let Some(max_channel_history) = self.max_channel_history { let history = message .channel_id - .messages(ctx, |f| f.before(message.id).limit(max_channel_history as u64)) + .messages(ctx, GetMessages::new().before(message.id).limit(max_channel_history as u8)) .await .into_diagnostic() .wrap_err("failed to fetch channel history")?; @@ -274,7 +275,7 @@ impl ContextMessageVariant { ContextMessageVariant::Reply(message) => message.id, ContextMessageVariant::ReplyWindow(message) => message.id, } - .0 + .into() } } diff --git a/src/invocation_builder.rs b/src/invocation_builder.rs index d8b330a..561fa4c 100644 --- a/src/invocation_builder.rs +++ b/src/invocation_builder.rs @@ -20,6 +20,8 @@ use regex::Regex; lazy_static! { static ref USER_MENTION_REGEX: Regex = Regex::new(r"<@!?(?P\d+)>").unwrap(); static ref EMOTE_MENTION_REGEX: Regex = Regex::new(r"<:(?P\w+):(?P\d+)>").unwrap(); + static ref USER_HANDLE_REGEX: Regex = Regex::new(r"@(?P\w+)").unwrap(); + static ref EMOTE_NAME_REGEX: Regex = Regex::new(r":(?P\w+):").unwrap(); } /// This struct contains additional user provided context for the current context. @@ -62,6 +64,7 @@ pub struct InvocationBuilder { emote_cache: HashMap, } +// TODO: implement database lookup for emoji and user ids impl InvocationBuilder { pub fn new(own_id: UserId, bot_name: &str) -> Self { let mut user_cache = HashMap::new(); @@ -86,10 +89,10 @@ impl InvocationBuilder { // extract emotes from message for capture in EMOTE_MENTION_REGEX.captures_iter(&message.content) { - if let (Some(name), Some(id)) = (capture.name("name"), capture.name("id")) { - let emoji_id = EmojiId(id.as_str().parse().unwrap_or(0)); - self.emote_cache.insert(name.as_str().to_string(), emoji_id); - } + let name = capture.name("name").unwrap().as_str().to_string(); + let id = capture.name("id").unwrap().as_str().parse().unwrap(); + + self.emote_cache.insert(name, EmojiId::new(id)); } // we can't transform the message directly, since other messages might provide additional emotes and users @@ -213,4 +216,34 @@ impl InvocationBuilder { result.to_string() } + + /// Transforms a response from the OpenAI API into a Discord message. + /// This will replace @handle with user mentions and :emote_name: with emote mentions. + pub fn retransform_response(&self, message: &str) -> String { + let result = message.to_string(); + + let result = USER_HANDLE_REGEX.replace_all(&result, |caps: ®ex::Captures| { + let handle = caps.name("handle").unwrap().as_str(); + + // try to find user id in cache, if not found, use handle with @ prefix + self + .user_cache + .get(handle) + .map(|id| format!("<@{}>", id)) + .unwrap_or(format!("@{}", handle)) + }); + + let result = EMOTE_NAME_REGEX.replace_all(&result, |caps: ®ex::Captures| { + let name = caps.name("name").unwrap().as_str(); + + // try to find emote id in cache, if not found, use :name: + self + .emote_cache + .get(name) + .map(|id| format!("<:{}:{}>", name, id)) + .unwrap_or(format!(":{}:", name)) + }); + + result.to_string() + } } diff --git a/src/main.rs b/src/main.rs index 2c12159..c9bf657 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,8 +2,6 @@ mod completion; mod context_extraction; mod invocation_builder; -use std::collections::HashMap; - use async_openai::{ config::OpenAIConfig, Client, @@ -18,16 +16,18 @@ use miette::{ }; use poise::{ serenity_prelude::{ + ClientBuilder, CreateAllowedMentions, + FullEvent, GatewayIntents, }, - Event, Framework, FrameworkError, FrameworkOptions, }; use tera::Tera; use tracing::{ + debug, error, info, info_span, @@ -105,18 +105,14 @@ async fn main() -> Result<()> { }) }, // block all mentions by default - allowed_mentions: Some(CreateAllowedMentions(HashMap::new())), + allowed_mentions: Some(CreateAllowedMentions::new().empty_roles().empty_users().replied_user(true)), manual_cooldowns: true, skip_checks_for_owners: false, event_handler: |ctx, ev, _framework, app| Box::pin(discord_listener(ctx, ev, app)), ..Default::default() }; - Framework::builder() - .token(&env_config.discord_token) - .intents( - GatewayIntents::MESSAGE_CONTENT | GatewayIntents::DIRECT_MESSAGES | GatewayIntents::GUILD_MESSAGES | GatewayIntents::GUILDS, - ) + let framework = Framework::builder() .setup(move |_ctx, _ready, _framework| { Box::pin(async move { let template_dir = format!("{}/{}", env_config.template_dir, "*.txt"); @@ -140,22 +136,33 @@ async fn main() -> Result<()> { }) .options(poise_options) .initialize_owners(false) - .run_autosharded() - .await - .into_diagnostic() - .wrap_err("failed to run discord client")?; + .build(); + + ClientBuilder::new( + &env_config.discord_token, + GatewayIntents::MESSAGE_CONTENT | GatewayIntents::DIRECT_MESSAGES | GatewayIntents::GUILD_MESSAGES | GatewayIntents::GUILDS, + ) + .framework(framework) + .await + .into_diagnostic() + .wrap_err("failed to create discord client") + .unwrap() + .start_autosharded() + .await + .into_diagnostic() + .wrap_err("failed to start discord client")?; Ok(()) } -async fn discord_listener<'a>(ctx: &'a poise::serenity_prelude::Context, ev: &'a Event<'a>, app: &'a AppState) -> Result<()> { +async fn discord_listener<'a>(ctx: &'a poise::serenity_prelude::Context, ev: &'a FullEvent, app: &'a AppState) -> Result<()> { match ev { - Event::Message { + FullEvent::Message { new_message, } => { let span = info_span!("message", author = %new_message.author.name, content = %new_message.content); - let our_id = ctx.cache.current_user_id(); + let our_id = ctx.cache.current_user().id; // ignore messages from bots or ourselves (we are a bot, but just in case) if new_message.author.bot || new_message.author.id == our_id { @@ -166,7 +173,7 @@ async fn discord_listener<'a>(ctx: &'a poise::serenity_prelude::Context, ev: &'a let concerned = { // TODO: if user opted out, we instead send a message that we won't reply - let mentioned = new_message.mentions_user_id(ctx.cache.current_user_id()); + let mentioned = new_message.mentions_user_id(our_id); let in_dm = new_message.is_private(); let replied_to_us = new_message .referenced_message @@ -182,10 +189,11 @@ async fn discord_listener<'a>(ctx: &'a poise::serenity_prelude::Context, ev: &'a handle_completion(ctx, app, new_message).instrument(span).await?; }, - Event::MessageUpdate { - new, .. + FullEvent::MessageUpdate { + new: Some(new), .. } => { // TODO: invalidate moderation cache for message + debug!("message {} updated, invalidating cache", new.id); }, _ => {}, }