From bb54c0d2c031639563b9cc9cfb043ae6f289a1c5 Mon Sep 17 00:00:00 2001 From: jellywx Date: Tue, 25 Jan 2022 22:59:05 +0000 Subject: [PATCH 1/9] lots of things and stuff --- Cargo.lock | 973 +++++++++++++++++---------- Cargo.toml | 7 +- regex_command_attr/Cargo.toml | 15 - regex_command_attr/src/attributes.rs | 408 ----------- regex_command_attr/src/consts.rs | 6 - regex_command_attr/src/lib.rs | 173 ----- regex_command_attr/src/structures.rs | 359 ---------- regex_command_attr/src/util.rs | 239 ------- src/cmds/info.rs | 213 +----- src/cmds/manage.rs | 253 ++----- src/cmds/mod.rs | 6 +- src/cmds/play.rs | 481 +++---------- src/cmds/search.rs | 9 +- src/event_handlers.rs | 241 +++---- src/framework.rs | 735 -------------------- src/guild_data.rs | 30 +- src/main.rs | 276 +++----- src/sound.rs | 51 +- 18 files changed, 988 insertions(+), 3487 deletions(-) delete mode 100644 regex_command_attr/Cargo.toml delete mode 100644 regex_command_attr/src/attributes.rs delete mode 100644 regex_command_attr/src/consts.rs delete mode 100644 regex_command_attr/src/lib.rs delete mode 100644 regex_command_attr/src/structures.rs delete mode 100644 regex_command_attr/src/util.rs delete mode 100644 src/framework.rs diff --git a/Cargo.lock b/Cargo.lock index f9baebc..d8c1cd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,9 +20,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ "getrandom", "once_cell", @@ -38,6 +38,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "arrayvec" version = "0.4.12" @@ -49,31 +58,15 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" dependencies = [ "proc-macro2", "quote", "syn", ] -[[package]] -name = "async-tungstenite" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b30ef0ea5c20caaa54baea49514a206308989c68be7ecd86c7f956e4da6378" -dependencies = [ - "futures-io", - "futures-util", - "log", - "pin-project-lite", - "tokio", - "tokio-rustls", - "tungstenite", - "webpki-roots", -] - [[package]] name = "async-tungstenite" version = "0.14.0" @@ -85,9 +78,25 @@ dependencies = [ "log", "pin-project-lite", "tokio", - "tokio-rustls", - "tungstenite", - "webpki-roots", + "tokio-rustls 0.22.0", + "tungstenite 0.13.0", + "webpki-roots 0.21.1", +] + +[[package]] +name = "async-tungstenite" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5682ea0913e5c20780fe5785abacb85a411e7437bf52a1bedb93ddb3972cb8dd" +dependencies = [ + "futures-io", + "futures-util", + "log", + "pin-project-lite", + "tokio", + "tokio-rustls 0.23.2", + "tungstenite 0.16.0", + "webpki-roots 0.22.2", ] [[package]] @@ -147,13 +156,19 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "base64ct" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6b4d9b1225d28d360ec6a231d65af1fd99a2a095154c8040689617290569c5c" + [[package]] name = "bigdecimal" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1e50562e37200edf7c6c43e54a08e64a5553bfb59d9c297d5572512aa517256" dependencies = [ - "num-bigint 0.3.3", + "num-bigint", "num-integer", "num-traits 0.2.14", ] @@ -175,9 +190,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.7.0" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "byteorder" @@ -193,15 +208,9 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "cc" -version = "1.0.70" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" [[package]] name = "cfg-if" @@ -219,7 +228,6 @@ dependencies = [ "num-integer", "num-traits 0.2.14", "serde", - "time", "winapi", ] @@ -233,20 +241,16 @@ dependencies = [ ] [[package]] -name = "command_attr" -version = "0.3.7" -source = "git+https://github.com/serenity-rs/serenity?branch=next#723749c43182838925dd89ac90b93dd2a837261d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +name = "const-oid" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" [[package]] name = "core-foundation" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" +checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" dependencies = [ "core-foundation-sys", "libc", @@ -254,9 +258,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cpufeatures" @@ -269,54 +273,132 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "a2209c310e29876f7f0b2721e7e26b84aff178aa3da5d091f9bfbf47669e60e3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-queue" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9" +checksum = "b979d76c9fcb84dffc80a73f7290da0f83e4c95773494674cb44b76d13a7a110" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "lazy_static", ] +[[package]] +name = "crypto-bigint" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83bd3bb4314701c568e340cd8cf78c975aa0ca79e03d3f6d1677d5b0c9c0c03" +dependencies = [ + "generic-array", + "rand_core", + "subtle", +] + +[[package]] +name = "darling" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "dashmap" version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "num_cpus", +] + +[[package]] +name = "dashmap" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b799062aaf67eb976af3bdca031ee6f846d2f0a5710ddbb0d2efee33f3cc4760" +dependencies = [ + "cfg-if", + "num_cpus", + "parking_lot", "serde", ] +[[package]] +name = "der" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" +dependencies = [ + "const-oid", + "crypto-bigint", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "digest" version = "0.9.0" @@ -350,11 +432,11 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "encoding_rs" -version = "0.8.28" +version = "0.8.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" +checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -379,13 +461,22 @@ dependencies = [ "termcolor", ] +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + [[package]] name = "flate2" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crc32fast", "libc", "miniz_oxide", @@ -393,9 +484,9 @@ dependencies = [ [[package]] name = "flume" -version = "0.10.9" +version = "0.10.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24c3fd473b3a903a62609e413ed7538f99e10b665ecb502b5e481a95283f8ab4" +checksum = "5d04dafd11240188e146b6f6476a898004cace3be31d4ec5e08e216bf4947ac0" dependencies = [ "futures-core", "futures-sink", @@ -437,9 +528,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" +checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" dependencies = [ "futures-channel", "futures-core", @@ -452,9 +543,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" +checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" dependencies = [ "futures-core", "futures-sink", @@ -462,15 +553,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" +checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" [[package]] name = "futures-executor" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c" +checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" dependencies = [ "futures-core", "futures-task", @@ -490,18 +581,16 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" +checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" [[package]] name = "futures-macro" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" +checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" dependencies = [ - "autocfg 1.0.1", - "proc-macro-hack", "proc-macro2", "quote", "syn", @@ -509,23 +598,22 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" +checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" [[package]] name = "futures-task" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" +checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" [[package]] name = "futures-util" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" +checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" dependencies = [ - "autocfg 1.0.1", "futures-channel", "futures-core", "futures-io", @@ -535,16 +623,14 @@ dependencies = [ "memchr", "pin-project-lite", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] [[package]] name = "generator" -version = "0.6.25" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061d3be1afec479d56fa3bd182bf966c7999ec175fcfdb87ac14d417241366c6" +checksum = "c1d9279ca822891c1a4dae06d185612cf8fc6acfe5dff37781b41297811b12ee" dependencies = [ "cc", "libc", @@ -555,9 +641,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" dependencies = [ "typenum", "version_check", @@ -565,11 +651,11 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "libc", "wasi", @@ -578,9 +664,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.4" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f3675cfef6a30c8031cf9e6493ebdc3bb3272a3fea3923c4210d1830e6a472" +checksum = "0c9de88456263e249e241fcd211d3954e2c9b0ef7ccfc235a444eb367cae3689" dependencies = [ "bytes", "fnv", @@ -639,20 +725,20 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "http" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" dependencies = [ "bytes", "fnv", - "itoa", + "itoa 1.0.1", ] [[package]] name = "http-body" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" dependencies = [ "bytes", "http", @@ -667,9 +753,9 @@ checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" [[package]] name = "httpdate" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "humantime" @@ -679,9 +765,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.13" +version = "0.14.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d1cfb9e4f68655fa04c01f59edb405b6074a0f7118ea881e5026e4a1cd8593" +checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" dependencies = [ "bytes", "futures-channel", @@ -692,7 +778,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", + "itoa 0.4.8", "pin-project-lite", "socket2", "tokio", @@ -703,17 +789,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.22.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" +checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" dependencies = [ - "futures-util", + "http", "hyper", - "log", - "rustls", + "rustls 0.20.2", "tokio", - "tokio-rustls", - "webpki", + "tokio-rustls 0.23.2", ] [[package]] @@ -729,6 +813,12 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.2.3" @@ -742,9 +832,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ "autocfg 1.0.1", "hashbrown", @@ -761,11 +851,11 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -776,9 +866,9 @@ checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" [[package]] name = "itertools" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" dependencies = [ "either", ] @@ -790,10 +880,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] -name = "js-sys" -version = "0.3.55" +name = "itoa" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "js-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" dependencies = [ "wasm-bindgen", ] @@ -809,9 +905,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.102" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" +checksum = "b0005d08a8f7b65fb8073cb697aa0b12b631ed251ce73d862ce50eeb52ce3b50" [[package]] name = "libm" @@ -834,20 +930,31 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] name = "loom" -version = "0.3.6" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0e8460f2f2121162705187214720353c517b97bdfb3494c0b1e33d83ebe4bed" +checksum = "edc5c7d328e32cc4954e8e01193d7f0ef5ab257b5090b70a964e099a36034309" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", "generator", "scoped-tls", "serde", "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", ] [[package]] @@ -880,9 +987,9 @@ dependencies = [ [[package]] name = "minimal-lexical" -version = "0.1.3" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c835948974f68e0bd58636fc6c5b1fbff7b297e3046f11b3b3c18bbac012c6d" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" @@ -896,9 +1003,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" dependencies = [ "libc", "log", @@ -951,9 +1058,9 @@ checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" [[package]] name = "nom" -version = "7.0.0" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffd9d26838a953b4af82cbeb9f1592c6798916983959be223a7124e992742c1" +checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" dependencies = [ "memchr", "minimal-lexical", @@ -980,17 +1087,6 @@ dependencies = [ "num-traits 0.2.14", ] -[[package]] -name = "num-bigint" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74e768dff5fb39a41b3bcd30bb25cf989706c90d028d1ad71971987aa309d535" -dependencies = [ - "autocfg 1.0.1", - "num-integer", - "num-traits 0.2.14", -] - [[package]] name = "num-bigint-dig" version = "0.7.0" @@ -1051,9 +1147,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", @@ -1061,9 +1157,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" [[package]] name = "opaque-debug" @@ -1073,12 +1169,12 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.36" +version = "0.10.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a" +checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" dependencies = [ "bitflags", - "cfg-if 1.0.0", + "cfg-if", "foreign-types", "libc", "once_cell", @@ -1087,15 +1183,15 @@ dependencies = [ [[package]] name = "openssl-probe" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.66" +version = "0.9.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1996d2d305e561b70d1ee0c53f1542833f4e1ac6ce9a6708b6ff2738ca67dc82" +checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" dependencies = [ "autocfg 1.0.1", "cc", @@ -1121,7 +1217,7 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "instant", "libc", "redox_syscall", @@ -1130,14 +1226,12 @@ dependencies = [ ] [[package]] -name = "pem" -version = "0.8.3" +name = "pem-rfc7468" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb" +checksum = "84e93a3b1cc0510b03020f33f21e62acdde3dcaef432edc95bea377fbd4c2cd4" dependencies = [ - "base64", - "once_cell", - "regex", + "base64ct", ] [[package]] @@ -1148,18 +1242,18 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pin-project" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" dependencies = [ "proc-macro2", "quote", @@ -1168,9 +1262,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" [[package]] name = "pin-utils" @@ -1179,10 +1273,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "pkg-config" -version = "0.3.19" +name = "pkcs1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" +checksum = "116bee8279d783c0cf370efa1a94632f2108e5ef0bb32df31f051647810a4e2c" +dependencies = [ + "der", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "pkcs8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447" +dependencies = [ + "der", + "pem-rfc7468", + "pkcs1", + "spki", + "zeroize", +] + +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" [[package]] name = "pnet_base" @@ -1211,6 +1329,32 @@ dependencies = [ "pnet_base", ] +[[package]] +name = "poise" +version = "0.1.0" +source = "git+https://github.com/kangalioo/poise?branch=master#9ebc7b541b2deca8efde1c8bcbdf3d415d8e3a9a" +dependencies = [ + "async-trait", + "futures-core", + "futures-util", + "once_cell", + "poise_macros", + "regex", + "serenity", + "tokio", +] + +[[package]] +name = "poise_macros" +version = "0.1.0" +source = "git+https://github.com/kangalioo/poise?branch=master#9ebc7b541b2deca8efde1c8bcbdf3d415d8e3a9a" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "poly1305" version = "0.7.2" @@ -1224,36 +1368,24 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" - -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" -version = "1.0.29" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.9" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" dependencies = [ "proc-macro2", ] @@ -1318,21 +1450,21 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + [[package]] name = "regex-syntax" version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" -[[package]] -name = "regex_command_attr" -version = "0.3.6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "remove_dir_all" version = "0.5.3" @@ -1344,15 +1476,16 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.4" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246e9f61b9bb77df069a947682be06e31ac43ea37862e244a69f177694ea6d22" +checksum = "87f242f1488a539a79bac6dbe7c8609ae43b7914b7736210f239a37cccb32525" dependencies = [ "base64", "bytes", "encoding_rs", "futures-core", "futures-util", + "h2", "http", "http-body", "hyper", @@ -1367,18 +1500,20 @@ dependencies = [ "native-tls", "percent-encoding", "pin-project-lite", - "rustls", + "rustls 0.20.2", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-native-tls", - "tokio-rustls", + "tokio-rustls 0.23.2", + "tokio-util", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", + "webpki-roots 0.22.2", "winreg", ] @@ -1399,9 +1534,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0aeddcca1082112a6eeb43bf25fd7820b066aaf6eaef776e19d0a1febe38fe" +checksum = "e05c2603e2823634ab331437001b411b9ed11660fbc4066f3908c84a9439260d" dependencies = [ "byteorder", "digest", @@ -1410,9 +1545,9 @@ dependencies = [ "num-integer", "num-iter", "num-traits 0.2.14", - "pem", + "pkcs1", + "pkcs8", "rand", - "simple_asn1", "subtle", "zeroize", ] @@ -1426,21 +1561,42 @@ dependencies = [ "base64", "log", "ring", - "sct", - "webpki", + "sct 0.6.1", + "webpki 0.21.4", +] + +[[package]] +name = "rustls" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" +dependencies = [ + "log", + "ring", + "sct 0.7.0", + "webpki 0.22.0", +] + +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64", ] [[package]] name = "rustversion" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "salsa20" @@ -1485,10 +1641,20 @@ dependencies = [ ] [[package]] -name = "security-framework" -version = "2.4.2" +name = "sct" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "security-framework" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d09d3c15d814eda1d6a836f2f2b56a6abc1446c8a34351cb3180d3db92ffe4ce" dependencies = [ "bitflags", "core-foundation", @@ -1499,9 +1665,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" +checksum = "e90dd10c41c6bfc633da6e0c659bd25d31e0791e5974ac42970267d59eba87f7" dependencies = [ "core-foundation-sys", "libc", @@ -1509,18 +1675,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.130" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ "proc-macro2", "quote", @@ -1529,11 +1695,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.68" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" +checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085" dependencies = [ - "itoa", + "itoa 1.0.1", "ryu", "serde", ] @@ -1551,29 +1717,28 @@ dependencies = [ [[package]] name = "serde_urlencoded" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa", + "itoa 1.0.1", "ryu", "serde", ] [[package]] name = "serenity" -version = "0.10.9" -source = "git+https://github.com/serenity-rs/serenity?branch=next#723749c43182838925dd89ac90b93dd2a837261d" +version = "0.10.10" +source = "git+https://github.com/serenity-rs/serenity?branch=next#ad78ab6543c8671f005246c89ce2651bf4809375" dependencies = [ "async-trait", - "async-tungstenite 0.13.1", + "async-tungstenite 0.16.1", "base64", "bitflags", "bytes", "chrono", - "command_attr", - "dashmap", + "dashmap 5.0.0", "flate2", "futures", "mime", @@ -1583,18 +1748,16 @@ dependencies = [ "reqwest", "serde", "serde_json", - "static_assertions", "tokio", "tracing", "typemap_rev", "url", - "uwl", ] [[package]] name = "serenity-voice-model" -version = "0.1.0" -source = "git+https://github.com/serenity-rs/serenity?branch=next#723749c43182838925dd89ac90b93dd2a837261d" +version = "0.1.1" +source = "git+https://github.com/serenity-rs/serenity?branch=next#ad78ab6543c8671f005246c89ce2651bf4809375" dependencies = [ "bitflags", "enum_primitive", @@ -1610,7 +1773,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ "block-buffer", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest", "opaque-debug", @@ -1618,17 +1781,26 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest", "opaque-debug", ] +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -1638,35 +1810,23 @@ dependencies = [ "libc", ] -[[package]] -name = "simple_asn1" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb4ea60fb301dc81dfc113df680571045d375ab7345d171c5dc7d7e13107a80" -dependencies = [ - "chrono", - "num-bigint 0.4.2", - "num-traits 0.2.14", - "thiserror", -] - [[package]] name = "slab" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] name = "smallvec" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "socket2" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +checksum = "0f82496b90c36d70af5fcd482edaa2e0bd16fade569de1330405fecbbdac736b" dependencies = [ "libc", "winapi", @@ -1674,14 +1834,15 @@ dependencies = [ [[package]] name = "songbird" -version = "0.2.0" -source = "git+https://github.com/serenity-rs/songbird?branch=next#a953430810cc3f08d609ad6f76f7708f457703fc" +version = "0.2.1" +source = "git+https://github.com/serenity-rs/songbird?branch=next#d3f0974412d217e7047c9681ba85d0217d79e741" dependencies = [ "async-trait", "async-tungstenite 0.14.0", "audiopus", "byteorder", - "dashmap", + "dashmap 4.0.2", + "derivative", "discortp", "flume", "futures", @@ -1706,18 +1867,17 @@ dependencies = [ [[package]] name = "soundfx-rs" -version = "1.4.3" +version = "1.5.0" dependencies = [ - "dashmap", + "dashmap 4.0.2", "dotenv", "env_logger", "lazy_static", "log", + "poise", "regex", - "regex_command_attr", "reqwest", "serde_json", - "serenity", "songbird", "sqlx", "tokio", @@ -1748,6 +1908,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "spki" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32" +dependencies = [ + "der", +] + [[package]] name = "sqlformat" version = "0.1.8" @@ -1761,9 +1930,9 @@ dependencies = [ [[package]] name = "sqlx" -version = "0.5.7" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4b94ab0f8c21ee4899b93b06451ef5d965f1a355982ee73684338228498440" +checksum = "692749de69603d81e016212199d73a2e14ee20e2def7d7914919e8db5d4d48b9" dependencies = [ "sqlx-core", "sqlx-macros", @@ -1771,13 +1940,12 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.5.7" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec28b91a01e1fe286d6ba66f68289a2286df023fc97444e1fd86c2fd6d5dc026" +checksum = "518be6f6fff5ca76f985d434f9c37f3662af279642acf730388f271dff7b9016" dependencies = [ "ahash", "atoi", - "base64", "bigdecimal", "bitflags", "byteorder", @@ -1794,17 +1962,18 @@ dependencies = [ "generic-array", "hashlink", "hex", - "itoa", + "indexmap", + "itoa 1.0.1", "libc", "log", "memchr", - "num-bigint 0.3.3", + "num-bigint", "once_cell", "parking_lot", "percent-encoding", "rand", "rsa", - "rustls", + "rustls 0.19.1", "sha-1", "sha2", "smallvec", @@ -1814,20 +1983,18 @@ dependencies = [ "thiserror", "tokio-stream", "url", - "webpki", - "webpki-roots", - "whoami", + "webpki 0.21.4", + "webpki-roots 0.21.1", ] [[package]] name = "sqlx-macros" -version = "0.5.7" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc33c35d54774eed73d54568d47a6ac099aed8af5e1556a017c131be88217d5" +checksum = "38e45140529cf1f90a5e1c2e561500ca345821a1c513652c8f486bbf07407cc8" dependencies = [ "dotenv", "either", - "futures", "heck", "once_cell", "proc-macro2", @@ -1840,26 +2007,20 @@ dependencies = [ [[package]] name = "sqlx-rt" -version = "0.5.7" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14302b678d9c76b28f2e60115211e25e0aabc938269991745a169753dc00e35c" +checksum = "8061cbaa91ee75041514f67a09398c65a64efed72c90151ecd47593bad53da99" dependencies = [ "once_cell", "tokio", - "tokio-rustls", + "tokio-rustls 0.22.0", ] -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "streamcatcher" -version = "0.1.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9501b1be04455a53f782940f7ca17050482de0a6e322c1ff606afc0ebbc62674" +checksum = "71664755c349abb0758fda6218fb2d2391ca2a73f9302c03b145491db4fcea29" dependencies = [ "crossbeam-utils", "futures-util", @@ -1876,6 +2037,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "subtle" version = "2.4.1" @@ -1897,9 +2064,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.76" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f107db402c2c2055242dbf4d2af0e69197202e9faacbef9571bbe47f5a1b84" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" dependencies = [ "proc-macro2", "quote", @@ -1908,9 +2075,9 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", @@ -1920,13 +2087,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "fastrand", "libc", - "rand", "redox_syscall", "remove_dir_all", "winapi", @@ -1943,18 +2110,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.29" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.29" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ "proc-macro2", "quote", @@ -1962,20 +2129,19 @@ dependencies = [ ] [[package]] -name = "time" -version = "0.1.43" +name = "thread_local" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ - "libc", - "winapi", + "once_cell", ] [[package]] name = "tinyvec" -version = "1.4.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5241dd6f21443a3606b432718b166d3cedc962fd4b8bea54a8bc7f514ebda986" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" dependencies = [ "tinyvec_macros", ] @@ -1988,11 +2154,10 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.11.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4efe6fc2395938c8155973d7be49fe8d03a843726e285e100a8a383cc0154ce" +checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" dependencies = [ - "autocfg 1.0.1", "bytes", "libc", "memchr", @@ -2007,9 +2172,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.3.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", @@ -2032,16 +2197,27 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" dependencies = [ - "rustls", + "rustls 0.19.1", "tokio", - "webpki", + "webpki 0.21.4", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" +dependencies = [ + "rustls 0.20.2", + "tokio", + "webpki 0.22.0", ] [[package]] name = "tokio-stream" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f" +checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" dependencies = [ "futures-core", "pin-project-lite", @@ -2050,9 +2226,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d3725d3efa29485e87311c5b699de63cde14b00ed4d256b8318aa30ca452cd" +checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" dependencies = [ "bytes", "futures-core", @@ -2070,11 +2246,11 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.27" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ba9ab62b7d6497a8638dfda5e5c4fb3b2d5a7fca4118f2b96151c8ef1a437e" +checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "log", "pin-project-lite", "tracing-attributes", @@ -2083,9 +2259,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.16" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98863d0dd09fa59a1b79c6750ad80dbda6b75f4e71c437a6a1a8cb91a8bcbd77" +checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" dependencies = [ "proc-macro2", "quote", @@ -2094,9 +2270,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46125608c26121c81b0c6d693eab5a420e416da7e43c426d2e8f7df8da8a3acf" +checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" dependencies = [ "lazy_static", ] @@ -2111,6 +2287,35 @@ dependencies = [ "tracing", ] +[[package]] +name = "tracing-log" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5312f325fe3588e277415f5a6cca1f4ccad0f248c4cd5a4bd33032d7286abc22" +dependencies = [ + "ansi_term", + "lazy_static", + "matchers", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + [[package]] name = "try-lock" version = "0.2.3" @@ -2131,13 +2336,34 @@ dependencies = [ "input_buffer", "log", "rand", - "rustls", + "rustls 0.19.1", "sha-1", "thiserror", "url", "utf-8", - "webpki", - "webpki-roots", + "webpki 0.21.4", + "webpki-roots 0.21.1", +] + +[[package]] +name = "tungstenite" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ad3713a14ae247f22a728a0456a545df14acf3867f905adff84be99e23b3ad1" +dependencies = [ + "base64", + "byteorder", + "bytes", + "http", + "httparse", + "log", + "rand", + "rustls 0.20.2", + "sha-1", + "thiserror", + "url", + "utf-8", + "webpki 0.22.0", ] [[package]] @@ -2148,9 +2374,9 @@ checksum = "ed5b74f0a24b5454580a79abb6994393b09adf0ab8070f15827cb666255de155" [[package]] name = "typenum" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "unicase" @@ -2163,9 +2389,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085" +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" [[package]] name = "unicode-normalization" @@ -2238,12 +2464,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "uwl" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4bf03e0ca70d626ecc4ba6b0763b934b6f2976e8c744088bb3c1d646fbb1ad0" - [[package]] name = "vcpkg" version = "0.2.15" @@ -2252,9 +2472,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "want" @@ -2274,21 +2494,19 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" dependencies = [ - "cfg-if 1.0.0", - "serde", - "serde_json", + "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" dependencies = [ "bumpalo", "lazy_static", @@ -2301,11 +2519,11 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" +checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -2313,9 +2531,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2323,9 +2541,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" dependencies = [ "proc-macro2", "quote", @@ -2336,15 +2554,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" [[package]] name = "web-sys" -version = "0.3.55" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" dependencies = [ "js-sys", "wasm-bindgen", @@ -2360,23 +2578,32 @@ dependencies = [ "untrusted", ] +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "webpki-roots" version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" dependencies = [ - "webpki", + "webpki 0.21.4", ] [[package]] -name = "whoami" -version = "1.1.3" +name = "webpki-roots" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7741161a40200a867c96dfa5574544efa4178cf4c8f770b62dd1cc0362d7ae1" +checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" dependencies = [ - "wasm-bindgen", - "web-sys", + "webpki 0.22.0", ] [[package]] @@ -2444,9 +2671,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.1.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2c1e130bebaeab2f23886bf9acbaca14b092408c452543c857f66399cd6dab1" +checksum = "81e8f13fef10b63c06356d65d416b070798ddabcadc10d3ece0c5be9b3c7eddb" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index ed3dd3b..015bd0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "soundfx-rs" -version = "1.4.3" +version = "1.5.0" authors = ["jellywx "] edition = "2018" [dependencies] songbird = { git = "https://github.com/serenity-rs/songbird", branch = "next" } -serenity = { git = "https://github.com/serenity-rs/serenity", branch = "next", features = ["voice", "collector", "unstable_discord_api"] } +poise = { git = "https://github.com/kangalioo/poise", branch = "master", features = ["collector"] } sqlx = { version = "0.5", default-features = false, features = ["runtime-tokio-rustls", "macros", "mysql", "bigdecimal"] } dotenv = "0.15" tokio = { version = "1", features = ["fs", "process", "io-util"] } @@ -17,6 +17,3 @@ regex = "1.4" log = "0.4" serde_json = "1.0" dashmap = "4.0" - -[dependencies.regex_command_attr] -path = "./regex_command_attr" diff --git a/regex_command_attr/Cargo.toml b/regex_command_attr/Cargo.toml deleted file mode 100644 index 24e5fa5..0000000 --- a/regex_command_attr/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "regex_command_attr" -version = "0.3.6" -authors = ["acdenisSK ", "jellywx "] -edition = "2018" -description = "Procedural macros for command creation for the Serenity library." -license = "ISC" - -[lib] -proc-macro = true - -[dependencies] -quote = "^1.0" -syn = { version = "^1.0", features = ["full", "derive", "extra-traits"] } -proc-macro2 = "1.0" diff --git a/regex_command_attr/src/attributes.rs b/regex_command_attr/src/attributes.rs deleted file mode 100644 index f9522b3..0000000 --- a/regex_command_attr/src/attributes.rs +++ /dev/null @@ -1,408 +0,0 @@ -use std::fmt::{self, Write}; - -use proc_macro2::Span; -use syn::parse::{Error, Result}; -use syn::spanned::Spanned; -use syn::{Attribute, Ident, Lit, LitStr, Meta, NestedMeta, Path}; - -use crate::structures::{ApplicationCommandOptionType, Arg, CommandKind, PermissionLevel}; -use crate::util::{AsOption, LitExt}; - -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum ValueKind { - // #[] - Name, - - // #[ = ] - Equals, - - // #[([, , , ...])] - List, - - // #[([ = , = , ...])] - EqualsList, - - // #[()] - SingleList, -} - -impl fmt::Display for ValueKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ValueKind::Name => f.pad("`#[]`"), - ValueKind::Equals => f.pad("`#[ = ]`"), - ValueKind::List => f.pad("`#[([, , , ...])]`"), - ValueKind::EqualsList => { - f.pad("`#[([ = , = , ...])]`") - } - ValueKind::SingleList => f.pad("`#[()]`"), - } - } -} - -fn to_ident(p: Path) -> Result { - if p.segments.is_empty() { - return Err(Error::new( - p.span(), - "cannot convert an empty path to an identifier", - )); - } - - if p.segments.len() > 1 { - return Err(Error::new( - p.span(), - "the path must not have more than one segment", - )); - } - - if !p.segments[0].arguments.is_empty() { - return Err(Error::new( - p.span(), - "the singular path segment must not have any arguments", - )); - } - - Ok(p.segments[0].ident.clone()) -} - -#[derive(Debug)] -pub struct Values { - pub name: Ident, - pub literals: Vec<(Option, Lit)>, - pub kind: ValueKind, - pub span: Span, -} - -impl Values { - #[inline] - pub fn new( - name: Ident, - kind: ValueKind, - literals: Vec<(Option, Lit)>, - span: Span, - ) -> Self { - Values { - name, - literals, - kind, - span, - } - } -} - -pub fn parse_values(attr: &Attribute) -> Result { - fn is_list_or_named_list(meta: &NestedMeta) -> ValueKind { - match meta { - // catch if the nested value is a literal value - NestedMeta::Lit(_) => ValueKind::List, - // catch if the nested value is a meta value - NestedMeta::Meta(m) => match m { - // path => some quoted value - Meta::Path(_) => ValueKind::List, - Meta::List(_) | Meta::NameValue(_) => ValueKind::EqualsList, - }, - } - } - - let meta = attr.parse_meta()?; - - match meta { - Meta::Path(path) => { - let name = to_ident(path)?; - - Ok(Values::new(name, ValueKind::Name, Vec::new(), attr.span())) - } - Meta::List(meta) => { - let name = to_ident(meta.path)?; - let nested = meta.nested; - - if nested.is_empty() { - return Err(Error::new(attr.span(), "list cannot be empty")); - } - - if is_list_or_named_list(nested.first().unwrap()) == ValueKind::List { - let mut lits = Vec::with_capacity(nested.len()); - - for meta in nested { - match meta { - // catch if the nested value is a literal value - NestedMeta::Lit(l) => lits.push((None, l)), - // catch if the nested value is a meta value - NestedMeta::Meta(m) => match m { - // path => some quoted value - Meta::Path(path) => { - let i = to_ident(path)?; - lits.push((None, Lit::Str(LitStr::new(&i.to_string(), i.span())))) - } - Meta::List(_) | Meta::NameValue(_) => { - return Err(Error::new(attr.span(), "cannot nest a list; only accept literals and identifiers at this level")) - } - }, - } - } - - let kind = if lits.len() == 1 { - ValueKind::SingleList - } else { - ValueKind::List - }; - - Ok(Values::new(name, kind, lits, attr.span())) - } else { - let mut lits = Vec::with_capacity(nested.len()); - - for meta in nested { - match meta { - // catch if the nested value is a literal value - NestedMeta::Lit(_) => { - return Err(Error::new(attr.span(), "key-value pairs expected")) - } - // catch if the nested value is a meta value - NestedMeta::Meta(m) => match m { - Meta::NameValue(n) => { - let name = to_ident(n.path)?.to_string(); - let value = n.lit; - - lits.push((Some(name), value)); - } - Meta::List(_) | Meta::Path(_) => { - return Err(Error::new(attr.span(), "key-value pairs expected")) - } - }, - } - } - - Ok(Values::new(name, ValueKind::EqualsList, lits, attr.span())) - } - } - Meta::NameValue(meta) => { - let name = to_ident(meta.path)?; - let lit = meta.lit; - - Ok(Values::new( - name, - ValueKind::Equals, - vec![(None, lit)], - attr.span(), - )) - } - } -} - -#[derive(Debug, Clone)] -struct DisplaySlice<'a, T>(&'a [T]); - -impl<'a, T: fmt::Display> fmt::Display for DisplaySlice<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut iter = self.0.iter().enumerate(); - - match iter.next() { - None => f.write_str("nothing")?, - Some((idx, elem)) => { - write!(f, "{}: {}", idx, elem)?; - - for (idx, elem) in iter { - f.write_char('\n')?; - write!(f, "{}: {}", idx, elem)?; - } - } - } - - Ok(()) - } -} - -#[inline] -fn is_form_acceptable(expect: &[ValueKind], kind: ValueKind) -> bool { - if expect.contains(&ValueKind::List) && kind == ValueKind::SingleList { - true - } else { - expect.contains(&kind) - } -} - -#[inline] -fn validate(values: &Values, forms: &[ValueKind]) -> Result<()> { - if !is_form_acceptable(forms, values.kind) { - return Err(Error::new( - values.span, - // Using the `_args` version here to avoid an allocation. - format_args!( - "the attribute must be in of these forms:\n{}", - DisplaySlice(forms) - ), - )); - } - - Ok(()) -} - -#[inline] -pub fn parse(values: Values) -> Result { - T::parse(values) -} - -pub trait AttributeOption: Sized { - fn parse(values: Values) -> Result; -} - -impl AttributeOption for Vec { - fn parse(values: Values) -> Result { - validate(&values, &[ValueKind::List])?; - - Ok(values - .literals - .into_iter() - .map(|(_, l)| l.to_str()) - .collect()) - } -} - -impl AttributeOption for String { - #[inline] - fn parse(values: Values) -> Result { - validate(&values, &[ValueKind::Equals, ValueKind::SingleList])?; - - Ok(values.literals[0].1.to_str()) - } -} - -impl AttributeOption for bool { - #[inline] - fn parse(values: Values) -> Result { - validate(&values, &[ValueKind::Name, ValueKind::SingleList])?; - - Ok(values.literals.get(0).map_or(true, |(_, l)| l.to_bool())) - } -} - -impl AttributeOption for Ident { - #[inline] - fn parse(values: Values) -> Result { - validate(&values, &[ValueKind::SingleList])?; - - Ok(values.literals[0].1.to_ident()) - } -} - -impl AttributeOption for Vec { - #[inline] - fn parse(values: Values) -> Result { - validate(&values, &[ValueKind::List])?; - - Ok(values - .literals - .into_iter() - .map(|(_, l)| l.to_ident()) - .collect()) - } -} - -impl AttributeOption for Option { - fn parse(values: Values) -> Result { - validate( - &values, - &[ValueKind::Name, ValueKind::Equals, ValueKind::SingleList], - )?; - - Ok(values.literals.get(0).map(|(_, l)| l.to_str())) - } -} - -impl AttributeOption for PermissionLevel { - fn parse(values: Values) -> Result { - validate(&values, &[ValueKind::SingleList])?; - - Ok(values - .literals - .get(0) - .map(|(_, l)| PermissionLevel::from_str(&*l.to_str()).unwrap()) - .unwrap()) - } -} - -impl AttributeOption for CommandKind { - fn parse(values: Values) -> Result { - validate(&values, &[ValueKind::SingleList])?; - - Ok(values - .literals - .get(0) - .map(|(_, l)| CommandKind::from_str(&*l.to_str()).unwrap()) - .unwrap()) - } -} - -impl AttributeOption for Arg { - fn parse(values: Values) -> Result { - validate(&values, &[ValueKind::EqualsList])?; - - let mut arg: Arg = Default::default(); - - for (key, value) in &values.literals { - match key { - Some(s) => match s.as_str() { - "name" => { - arg.name = value.to_str(); - } - "description" => { - arg.description = value.to_str(); - } - "required" => { - arg.required = value.to_bool(); - } - "kind" => arg.kind = ApplicationCommandOptionType::from_str(value.to_str()), - _ => { - return Err(Error::new(key.span(), "unexpected attribute")); - } - }, - _ => { - return Err(Error::new(key.span(), "unnamed attribute")); - } - } - } - - Ok(arg) - } -} - -impl AttributeOption for AsOption { - #[inline] - fn parse(values: Values) -> Result { - Ok(AsOption(Some(T::parse(values)?))) - } -} - -macro_rules! attr_option_num { - ($($n:ty),*) => { - $( - impl AttributeOption for $n { - fn parse(values: Values) -> Result { - validate(&values, &[ValueKind::SingleList])?; - - Ok(match &values.literals[0].1 { - Lit::Int(l) => l.base10_parse::<$n>()?, - l => { - let s = l.to_str(); - // Use `as_str` to guide the compiler to use `&str`'s parse method. - // We don't want to use our `parse` method here (`impl AttributeOption for String`). - match s.as_str().parse::<$n>() { - Ok(n) => n, - Err(_) => return Err(Error::new(l.span(), "invalid integer")), - } - } - }) - } - } - - impl AttributeOption for Option<$n> { - #[inline] - fn parse(values: Values) -> Result { - <$n as AttributeOption>::parse(values).map(Some) - } - } - )* - } -} - -attr_option_num!(u16, u32, usize); diff --git a/regex_command_attr/src/consts.rs b/regex_command_attr/src/consts.rs deleted file mode 100644 index 9235297..0000000 --- a/regex_command_attr/src/consts.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod suffixes { - pub const COMMAND: &str = "COMMAND"; - pub const ARG: &str = "ARG"; -} - -pub use self::suffixes::*; diff --git a/regex_command_attr/src/lib.rs b/regex_command_attr/src/lib.rs deleted file mode 100644 index 2ae6b0f..0000000 --- a/regex_command_attr/src/lib.rs +++ /dev/null @@ -1,173 +0,0 @@ -#![deny(rust_2018_idioms)] -#![deny(broken_intra_doc_links)] - -use proc_macro::TokenStream; -use proc_macro2::Ident; -use quote::quote; -use syn::{parse::Error, parse_macro_input, parse_quote, spanned::Spanned, Lit}; - -pub(crate) mod attributes; -pub(crate) mod consts; -pub(crate) mod structures; - -#[macro_use] -pub(crate) mod util; - -use attributes::*; -use consts::*; -use structures::*; -use util::*; - -macro_rules! match_options { - ($v:expr, $values:ident, $options:ident, $span:expr => [$($name:ident);*]) => { - match $v { - $( - stringify!($name) => $options.$name = propagate_err!($crate::attributes::parse($values)), - )* - _ => { - return Error::new($span, format_args!("invalid attribute: {:?}", $v)) - .to_compile_error() - .into(); - }, - } - }; -} - -#[proc_macro_attribute] -pub fn command(attr: TokenStream, input: TokenStream) -> TokenStream { - let mut fun = parse_macro_input!(input as CommandFun); - - let _name = if !attr.is_empty() { - parse_macro_input!(attr as Lit).to_str() - } else { - fun.name.to_string() - }; - - let mut options = Options::new(); - - for attribute in &fun.attributes { - let span = attribute.span(); - let values = propagate_err!(parse_values(attribute)); - - let name = values.name.to_string(); - let name = &name[..]; - - match name { - "arg" => options - .cmd_args - .push(propagate_err!(attributes::parse(values))), - "example" => { - options - .examples - .push(propagate_err!(attributes::parse(values))); - } - "description" => { - let line: String = propagate_err!(attributes::parse(values)); - util::append_line(&mut options.description, line); - } - _ => { - match_options!(name, values, options, span => [ - aliases; - group; - required_permissions; - kind - ]); - } - } - } - - let Options { - aliases, - description, - group, - examples, - required_permissions, - kind, - mut cmd_args, - } = options; - - propagate_err!(create_declaration_validations(&mut fun)); - - let res = parse_quote!(serenity::framework::standard::CommandResult); - create_return_type_validation(&mut fun, res); - - let visibility = fun.visibility; - let name = fun.name.clone(); - let body = fun.body; - let ret = fun.ret; - - let n = name.with_suffix(COMMAND); - - let cooked = fun.cooked.clone(); - - let command_path = quote!(crate::framework::Command); - let arg_path = quote!(crate::framework::Arg); - - populate_fut_lifetimes_on_refs(&mut fun.args); - let args = fun.args; - - let arg_idents = cmd_args - .iter() - .map(|arg| { - n.with_suffix(arg.name.replace(" ", "_").replace("-", "_").as_str()) - .with_suffix(ARG) - }) - .collect::>(); - - let mut tokens = cmd_args - .iter_mut() - .map(|arg| { - let Arg { - name, - description, - kind, - required, - } = arg; - - let an = n.with_suffix(name.as_str()).with_suffix(ARG); - - quote! { - #(#cooked)* - #[allow(missing_docs)] - pub static #an: #arg_path = #arg_path { - name: #name, - description: #description, - kind: #kind, - required: #required, - }; - } - }) - .fold(quote! {}, |mut a, b| { - a.extend(b); - a - }); - - tokens.extend(quote! { - #(#cooked)* - #[allow(missing_docs)] - pub static #n: #command_path = #command_path { - fun: #name, - names: &[#_name, #(#aliases),*], - desc: #description, - group: #group, - examples: &[#(#examples),*], - required_permissions: #required_permissions, - kind: #kind, - args: &[#(&#arg_idents),*], - }; - - #(#cooked)* - #[allow(missing_docs)] - #visibility fn #name<'fut> (#(#args),*) -> ::serenity::futures::future::BoxFuture<'fut, #ret> { - use ::serenity::futures::future::FutureExt; - - async move { - let _output: #ret = { #(#body)* }; - #[allow(unreachable_code)] - _output - }.boxed() - } - }); - - tokens.into() -} diff --git a/regex_command_attr/src/structures.rs b/regex_command_attr/src/structures.rs deleted file mode 100644 index 0cab491..0000000 --- a/regex_command_attr/src/structures.rs +++ /dev/null @@ -1,359 +0,0 @@ -use proc_macro2::TokenStream as TokenStream2; -use quote::{quote, ToTokens}; -use syn::{ - braced, - parse::{Error, Parse, ParseStream, Result}, - spanned::Spanned, - Attribute, Block, FnArg, Ident, Pat, ReturnType, Stmt, Token, Type, Visibility, -}; - -use crate::util::{self, Argument, Parenthesised}; - -fn parse_argument(arg: FnArg) -> Result { - match arg { - FnArg::Typed(typed) => { - let pat = typed.pat; - let kind = typed.ty; - - match *pat { - Pat::Ident(id) => { - let name = id.ident; - let mutable = id.mutability; - - Ok(Argument { - mutable, - name, - kind: *kind, - }) - } - Pat::Wild(wild) => { - let token = wild.underscore_token; - - let name = Ident::new("_", token.spans[0]); - - Ok(Argument { - mutable: None, - name, - kind: *kind, - }) - } - _ => Err(Error::new( - pat.span(), - format_args!("unsupported pattern: {:?}", pat), - )), - } - } - FnArg::Receiver(_) => Err(Error::new( - arg.span(), - format_args!("`self` arguments are prohibited: {:?}", arg), - )), - } -} - -/// Test if the attribute is cooked. -fn is_cooked(attr: &Attribute) -> bool { - const COOKED_ATTRIBUTE_NAMES: &[&str] = &[ - "cfg", "cfg_attr", "derive", "inline", "allow", "warn", "deny", "forbid", - ]; - - COOKED_ATTRIBUTE_NAMES.iter().any(|n| attr.path.is_ident(n)) -} - -/// Removes cooked attributes from a vector of attributes. Uncooked attributes are left in the vector. -/// -/// # Return -/// -/// Returns a vector of cooked attributes that have been removed from the input vector. -fn remove_cooked(attrs: &mut Vec) -> Vec { - let mut cooked = Vec::new(); - - // FIXME: Replace with `Vec::drain_filter` once it is stable. - let mut i = 0; - while i < attrs.len() { - if !is_cooked(&attrs[i]) { - i += 1; - continue; - } - - cooked.push(attrs.remove(i)); - } - - cooked -} - -#[derive(Debug)] -pub struct CommandFun { - /// `#[...]`-style attributes. - pub attributes: Vec, - /// Populated cooked attributes. These are attributes outside of the realm of this crate's procedural macros - /// and will appear in generated output. - pub cooked: Vec, - pub visibility: Visibility, - pub name: Ident, - pub args: Vec, - pub ret: Type, - pub body: Vec, -} - -impl Parse for CommandFun { - fn parse(input: ParseStream<'_>) -> Result { - let mut attributes = input.call(Attribute::parse_outer)?; - - // Rename documentation comment attributes (`#[doc = "..."]`) to `#[description = "..."]`. - util::rename_attributes(&mut attributes, "doc", "description"); - - let cooked = remove_cooked(&mut attributes); - - let visibility = input.parse::()?; - - input.parse::()?; - - input.parse::()?; - let name = input.parse()?; - - // (...) - let Parenthesised(args) = input.parse::>()?; - - let ret = match input.parse::()? { - ReturnType::Type(_, t) => (*t).clone(), - ReturnType::Default => { - return Err(input - .error("expected a result type of either `CommandResult` or `CheckResult`")) - } - }; - - // { ... } - let bcont; - braced!(bcont in input); - let body = bcont.call(Block::parse_within)?; - - let args = args - .into_iter() - .map(parse_argument) - .collect::>>()?; - - Ok(Self { - attributes, - cooked, - visibility, - name, - args, - ret, - body, - }) - } -} - -impl ToTokens for CommandFun { - fn to_tokens(&self, stream: &mut TokenStream2) { - let Self { - attributes: _, - cooked, - visibility, - name, - args, - ret, - body, - } = self; - - stream.extend(quote! { - #(#cooked)* - #visibility async fn #name (#(#args),*) -> #ret { - #(#body)* - } - }); - } -} - -#[derive(Debug)] -pub enum PermissionLevel { - Unrestricted, - Managed, - Restricted, -} - -impl Default for PermissionLevel { - fn default() -> Self { - Self::Unrestricted - } -} - -impl PermissionLevel { - pub fn from_str(s: &str) -> Option { - Some(match s.to_uppercase().as_str() { - "UNRESTRICTED" => Self::Unrestricted, - "MANAGED" => Self::Managed, - "RESTRICTED" => Self::Restricted, - _ => return None, - }) - } -} - -impl ToTokens for PermissionLevel { - fn to_tokens(&self, stream: &mut TokenStream2) { - let path = quote!(crate::framework::PermissionLevel); - let variant; - - match self { - Self::Unrestricted => { - variant = quote!(Unrestricted); - } - - Self::Managed => { - variant = quote!(Managed); - } - - Self::Restricted => { - variant = quote!(Restricted); - } - } - - stream.extend(quote! { - #path::#variant - }); - } -} - -#[derive(Debug)] -pub enum CommandKind { - Slash, - Both, - Text, -} - -impl Default for CommandKind { - fn default() -> Self { - Self::Both - } -} - -impl CommandKind { - pub fn from_str(s: &str) -> Option { - Some(match s.to_uppercase().as_str() { - "SLASH" => Self::Slash, - "BOTH" => Self::Both, - "TEXT" => Self::Text, - _ => return None, - }) - } -} - -impl ToTokens for CommandKind { - fn to_tokens(&self, stream: &mut TokenStream2) { - let path = quote!(crate::framework::CommandKind); - let variant; - - match self { - Self::Slash => { - variant = quote!(Slash); - } - - Self::Both => { - variant = quote!(Both); - } - - Self::Text => { - variant = quote!(Text); - } - } - - stream.extend(quote! { - #path::#variant - }); - } -} - -#[derive(Debug)] -pub(crate) enum ApplicationCommandOptionType { - SubCommand, - SubCommandGroup, - String, - Integer, - Boolean, - User, - Channel, - Role, - Mentionable, - Unknown, -} - -impl ApplicationCommandOptionType { - pub fn from_str(s: String) -> Self { - match s.as_str() { - "SubCommand" => Self::SubCommand, - "SubCommandGroup" => Self::SubCommandGroup, - "String" => Self::String, - "Integer" => Self::Integer, - "Boolean" => Self::Boolean, - "User" => Self::User, - "Channel" => Self::Channel, - "Role" => Self::Role, - "Mentionable" => Self::Mentionable, - _ => Self::Unknown, - } - } -} - -impl ToTokens for ApplicationCommandOptionType { - fn to_tokens(&self, stream: &mut TokenStream2) { - let path = quote!( - serenity::model::interactions::application_command::ApplicationCommandOptionType - ); - let variant = match self { - ApplicationCommandOptionType::SubCommand => quote!(SubCommand), - ApplicationCommandOptionType::SubCommandGroup => quote!(SubCommandGroup), - ApplicationCommandOptionType::String => quote!(String), - ApplicationCommandOptionType::Integer => quote!(Integer), - ApplicationCommandOptionType::Boolean => quote!(Boolean), - ApplicationCommandOptionType::User => quote!(User), - ApplicationCommandOptionType::Channel => quote!(Channel), - ApplicationCommandOptionType::Role => quote!(Role), - ApplicationCommandOptionType::Mentionable => quote!(Mentionable), - ApplicationCommandOptionType::Unknown => quote!(Unknown), - }; - - stream.extend(quote! { - #path::#variant - }); - } -} - -#[derive(Debug)] -pub(crate) struct Arg { - pub name: String, - pub description: String, - pub kind: ApplicationCommandOptionType, - pub required: bool, -} - -impl Default for Arg { - fn default() -> Self { - Self { - name: String::new(), - description: String::new(), - kind: ApplicationCommandOptionType::String, - required: false, - } - } -} - -#[derive(Debug, Default)] -pub(crate) struct Options { - pub aliases: Vec, - pub description: String, - pub group: String, - pub examples: Vec, - pub required_permissions: PermissionLevel, - pub kind: CommandKind, - pub cmd_args: Vec, -} - -impl Options { - #[inline] - pub fn new() -> Self { - Self { - group: "Other".to_string(), - ..Default::default() - } - } -} diff --git a/regex_command_attr/src/util.rs b/regex_command_attr/src/util.rs deleted file mode 100644 index 12197d8..0000000 --- a/regex_command_attr/src/util.rs +++ /dev/null @@ -1,239 +0,0 @@ -use proc_macro::TokenStream; -use proc_macro2::Span; -use proc_macro2::TokenStream as TokenStream2; -use quote::{format_ident, quote, ToTokens}; -use syn::{ - braced, bracketed, parenthesized, - parse::{Error, Parse, ParseStream, Result as SynResult}, - parse_quote, - punctuated::Punctuated, - spanned::Spanned, - token::{Comma, Mut}, - Attribute, Ident, Lifetime, Lit, Path, PathSegment, Type, -}; - -use crate::structures::CommandFun; - -pub trait LitExt { - fn to_str(&self) -> String; - fn to_bool(&self) -> bool; - fn to_ident(&self) -> Ident; -} - -impl LitExt for Lit { - fn to_str(&self) -> String { - match self { - Lit::Str(s) => s.value(), - Lit::ByteStr(s) => unsafe { String::from_utf8_unchecked(s.value()) }, - Lit::Char(c) => c.value().to_string(), - Lit::Byte(b) => (b.value() as char).to_string(), - _ => panic!("values must be a (byte)string or a char"), - } - } - - fn to_bool(&self) -> bool { - if let Lit::Bool(b) = self { - b.value - } else { - self.to_str() - .parse() - .unwrap_or_else(|_| panic!("expected bool from {:?}", self)) - } - } - - #[inline] - fn to_ident(&self) -> Ident { - Ident::new(&self.to_str(), self.span()) - } -} - -pub trait IdentExt2: Sized { - fn to_uppercase(&self) -> Self; - fn with_suffix(&self, suf: &str) -> Ident; -} - -impl IdentExt2 for Ident { - #[inline] - fn to_uppercase(&self) -> Self { - format_ident!("{}", self.to_string().to_uppercase()) - } - - #[inline] - fn with_suffix(&self, suffix: &str) -> Ident { - format_ident!("{}_{}", self.to_string().to_uppercase(), suffix) - } -} - -#[inline] -pub fn into_stream(e: Error) -> TokenStream { - e.to_compile_error().into() -} - -macro_rules! propagate_err { - ($res:expr) => {{ - match $res { - Ok(v) => v, - Err(e) => return $crate::util::into_stream(e), - } - }}; -} - -#[derive(Debug)] -pub struct Bracketed(pub Punctuated); - -impl Parse for Bracketed { - fn parse(input: ParseStream<'_>) -> SynResult { - let content; - bracketed!(content in input); - - Ok(Bracketed(content.parse_terminated(T::parse)?)) - } -} - -#[derive(Debug)] -pub struct Braced(pub Punctuated); - -impl Parse for Braced { - fn parse(input: ParseStream<'_>) -> SynResult { - let content; - braced!(content in input); - - Ok(Braced(content.parse_terminated(T::parse)?)) - } -} - -#[derive(Debug)] -pub struct Parenthesised(pub Punctuated); - -impl Parse for Parenthesised { - fn parse(input: ParseStream<'_>) -> SynResult { - let content; - parenthesized!(content in input); - - Ok(Parenthesised(content.parse_terminated(T::parse)?)) - } -} - -#[derive(Debug)] -pub struct AsOption(pub Option); - -impl ToTokens for AsOption { - fn to_tokens(&self, stream: &mut TokenStream2) { - match &self.0 { - Some(o) => stream.extend(quote!(Some(#o))), - None => stream.extend(quote!(None)), - } - } -} - -impl Default for AsOption { - #[inline] - fn default() -> Self { - AsOption(None) - } -} - -#[derive(Debug)] -pub struct Argument { - pub mutable: Option, - pub name: Ident, - pub kind: Type, -} - -impl ToTokens for Argument { - fn to_tokens(&self, stream: &mut TokenStream2) { - let Argument { - mutable, - name, - kind, - } = self; - - stream.extend(quote! { - #mutable #name: #kind - }); - } -} - -#[inline] -pub fn generate_type_validation(have: Type, expect: Type) -> syn::Stmt { - parse_quote! { - serenity::static_assertions::assert_type_eq_all!(#have, #expect); - } -} - -pub fn create_declaration_validations(fun: &mut CommandFun) -> SynResult<()> { - if fun.args.len() > 3 { - return Err(Error::new( - fun.args.last().unwrap().span(), - format_args!("function's arity exceeds more than 3 arguments"), - )); - } - - let context: Type = parse_quote!(&serenity::client::Context); - let message: Type = parse_quote!(&(dyn crate::framework::CommandInvoke + Sync + Send)); - let args: Type = parse_quote!(crate::framework::Args); - - let mut index = 0; - - let mut spoof_or_check = |kind: Type, name: &str| { - match fun.args.get(index) { - Some(x) => fun - .body - .insert(0, generate_type_validation(x.kind.clone(), kind)), - None => fun.args.push(Argument { - mutable: None, - name: Ident::new(name, Span::call_site()), - kind, - }), - } - - index += 1; - }; - - spoof_or_check(context, "_ctx"); - spoof_or_check(message, "_msg"); - spoof_or_check(args, "_args"); - - Ok(()) -} - -#[inline] -pub fn create_return_type_validation(r#fn: &mut CommandFun, expect: Type) { - let stmt = generate_type_validation(r#fn.ret.clone(), expect); - r#fn.body.insert(0, stmt); -} - -#[inline] -pub fn populate_fut_lifetimes_on_refs(args: &mut Vec) { - for arg in args { - if let Type::Reference(reference) = &mut arg.kind { - reference.lifetime = Some(Lifetime::new("'fut", Span::call_site())); - } - } -} - -/// Renames all attributes that have a specific `name` to the `target`. -pub fn rename_attributes(attributes: &mut Vec, name: &str, target: &str) { - for attr in attributes { - if attr.path.is_ident(name) { - attr.path = Path::from(PathSegment::from(Ident::new(target, Span::call_site()))); - } - } -} - -pub fn append_line(desc: &mut String, mut line: String) { - if line.starts_with(' ') { - line.remove(0); - } - - match line.rfind("\\$") { - Some(i) => { - desc.push_str(line[..i].trim_end()); - desc.push(' '); - } - None => { - desc.push_str(&line); - desc.push('\n'); - } - } -} diff --git a/src/cmds/info.rs b/src/cmds/info.rs index 1931699..72bc8a5 100644 --- a/src/cmds/info.rs +++ b/src/cmds/info.rs @@ -1,201 +1,11 @@ -use std::{collections::HashMap, sync::Arc}; +use crate::{Context, Error, THEME_COLOR}; -use regex_command_attr::command; -use serenity::{client::Context, framework::standard::CommandResult}; +/// Get additional information about the bot +#[poise::command(slash_command, category = "Information")] +pub async fn info(ctx: Context<'_>) -> Result<(), Error> { + let current_user = ctx.discord().cache.current_user(); -use crate::{ - framework::{Args, CommandInvoke, CommandKind, CreateGenericResponse, RegexFramework}, - THEME_COLOR, -}; - -#[command] -#[group("Information")] -#[description("Get information on the commands of the bot")] -#[arg( - name = "command", - description = "Get help for a specific command", - kind = "String", - required = false -)] -#[example("`/help` - see all commands")] -#[example("`/help play` - get help about the `play` command")] -pub async fn help( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - args: Args, -) -> CommandResult { - fn get_groups(framework: Arc) -> HashMap<&'static str, Vec<&'static str>> { - let mut groups = HashMap::new(); - - for command in &framework.commands_ { - let entry = groups.entry(command.group).or_insert(vec![]); - - entry.push(command.names[0]); - } - - groups - } - - let framework = ctx - .data - .read() - .await - .get::() - .cloned() - .unwrap(); - - if let Some(command_name) = args.named("command") { - if let Some(command) = framework.commands.get(command_name) { - let examples = if command.examples.is_empty() { - "".to_string() - } else { - format!( - "**Examples** -{}", - command - .examples - .iter() - .map(|e| format!(" • {}", e)) - .collect::>() - .join("\n") - ) - }; - - let args = if command.args.is_empty() { - "**Arguments** - • *This command has no arguments*" - .to_string() - } else { - format!( - "**Arguments** -{}", - command - .args - .iter() - .map(|a| format!( - " • `{}` {} - {}", - a.name, - if a.required { "" } else { "[optional]" }, - a.description - )) - .collect::>() - .join("\n") - ) - }; - - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().embed(|e| { - e.title(format!("{} Help", command_name)) - .color(THEME_COLOR) - .description(format!( - "**Available In** -`Slash Commands` {} -` Text Commands` {} - -**Aliases** -{} - -**Overview** - • {} -{} - -{}", - if command.kind != CommandKind::Text { - "✅" - } else { - "❎" - }, - if command.kind != CommandKind::Slash { - "✅" - } else { - "❎" - }, - command - .names - .iter() - .map(|n| format!("`{}`", n)) - .collect::>() - .join(" "), - command.desc, - args, - examples - )) - }), - ) - .await?; - } else { - let groups = get_groups(framework); - let groups_iter = groups.iter().map(|(name, commands)| { - ( - name, - commands - .iter() - .map(|c| format!("`{}`", c)) - .collect::>() - .join(" "), - true, - ) - }); - - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().embed(|e| { - e.title("Invalid Command") - .color(THEME_COLOR) - .description("Type `/help command` to view more about a command below:") - .fields(groups_iter) - }), - ) - .await?; - } - } else { - let groups = get_groups(framework); - let groups_iter = groups.iter().map(|(name, commands)| { - ( - name, - commands - .iter() - .map(|c| format!("`{}`", c)) - .collect::>() - .join(" "), - true, - ) - }); - - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().embed(|e| { - e.title("Help") - .color(THEME_COLOR) - .description("**Welcome to SoundFX!** -To get started, upload a sound with `/upload`, or use `/search` and `/play` to look at some of the public sounds - -Type `/help command` to view help about a command below:") - .fields(groups_iter) - }), - ) - .await?; - } - - Ok(()) -} - -#[command] -#[group("Information")] -#[aliases("invite")] -#[description("Get additional information on the bot")] -async fn info( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - _args: Args, -) -> CommandResult { - let current_user = ctx.cache.current_user(); - - invoke.respond(ctx.http.clone(), CreateGenericResponse::new() + ctx.send(|m| m .embed(|e| e .title("Info") .color(THEME_COLOR) @@ -211,15 +21,10 @@ Invite me: https://discord.com/api/oauth2/authorize?client_id={1}&permissions=31 Developer: <@203532103185465344> Find me on https://discord.jellywx.com/ and on https://github.com/JellyWX :) -**Sound Credits** -\"The rain falls against the parasol\" https://freesound.org/people/straget/ -\"Heavy Rain\" https://freesound.org/people/lebaston100/ -\"Rain on Windows, Interior, A\" https://freesound.org/people/InspectorJ/ -\"Seaside Waves, Close, A\" https://freesound.org/people/InspectorJ/ -\"Small River 1 - Fast - Close\" https://freesound.org/people/Pfannkuchn/ - **An online dashboard is available!** Visit https://soundfx.jellywx.com/dashboard -There is a maximum sound limit per user. This can be removed by subscribing at **https://patreon.com/jellywx**", current_user.name, current_user.id.as_u64())))).await?; +There is a maximum sound limit per user. This can be removed by subscribing at **https://patreon.com/jellywx**", + current_user.name, + current_user.id.as_u64())))).await?; Ok(()) } diff --git a/src/cmds/manage.rs b/src/cmds/manage.rs index 6406629..938619b 100644 --- a/src/cmds/manage.rs +++ b/src/cmds/manage.rs @@ -1,32 +1,15 @@ use std::time::Duration; -use regex_command_attr::command; -use serenity::{ - client::Context, - framework::standard::CommandResult, - model::id::{GuildId, RoleId}, -}; +use poise::serenity::model::id::{GuildId, RoleId}; -use crate::{ - framework::{Args, CommandInvoke, CreateGenericResponse}, - sound::Sound, - MySQL, MAX_SOUNDS, PATREON_GUILD, PATREON_ROLE, -}; +use crate::{sound::Sound, Context, Error, MAX_SOUNDS, PATREON_GUILD, PATREON_ROLE}; -#[command("upload")] -#[group("Manage")] -#[description("Upload a new sound to the bot")] -#[arg( - name = "name", - description = "Name to upload sound to", - kind = "String", - required = true -)] +/// Upload a new sound to the bot +#[poise::command(slash_command, rename = "upload", category = "Manage")] pub async fn upload_new_sound( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - args: Args, -) -> CommandResult { + ctx: Context<'_>, + #[description = "Name to upload sound to"] name: String, +) -> Result<(), Error> { fn is_numeric(s: &String) -> bool { for char in s.chars() { if char.is_digit(10) { @@ -38,36 +21,27 @@ pub async fn upload_new_sound( true } - let new_name = args - .named("name") - .map(|n| n.to_string()) - .unwrap_or(String::new()); - - if !new_name.is_empty() && new_name.len() <= 20 { - if !is_numeric(&new_name) { - let pool = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("Could not get SQLPool from data"); + if !name.is_empty() && name.len() <= 20 { + if !is_numeric(&name) { + let pool = ctx.data().database.clone(); // need to check the name is not currently in use by the user let count_name = - Sound::count_named_user_sounds(invoke.author_id().0, &new_name, pool.clone()) - .await?; + Sound::count_named_user_sounds(ctx.author().id, &name, pool.clone()).await?; if count_name > 0 { - invoke.respond(ctx.http.clone(), CreateGenericResponse::new().content("You are already using that name. Please choose a unique name for your upload.")).await?; + ctx.say( + "You are already using that name. Please choose a unique name for your upload.", + ) + .await?; } else { // need to check how many sounds user currently has - let count = Sound::count_user_sounds(invoke.author_id().0, pool.clone()).await?; + let count = Sound::count_user_sounds(ctx.author().id, pool.clone()).await?; let mut permit_upload = true; // need to check if user is patreon or nah if count >= *MAX_SOUNDS { let patreon_guild_member = GuildId(*PATREON_GUILD) - .member(ctx, invoke.author_id()) + .member(ctx.discord(), ctx.author().id) .await; if let Ok(member) = patreon_guild_member { @@ -78,19 +52,13 @@ pub async fn upload_new_sound( } if permit_upload { - let attachment = if let Some(attachment) = invoke - .msg() - .map(|m| m.attachments.get(0).map(|a| a.url.clone())) - .flatten() - { - Some(attachment) - } else { - invoke.respond(ctx.http.clone(), CreateGenericResponse::new().content("Please now upload an audio file under 1MB in size (larger files will be automatically trimmed):")).await?; + let attachment = { + ctx.say("Please now upload an audio file under 1MB in size (larger files will be automatically trimmed):").await?; - let reply = invoke + let reply = ctx .channel_id() - .await_reply(&ctx) - .author_id(invoke.author_id()) + .await_reply(&ctx.discord()) + .author_id(ctx.author().id) .timeout(Duration::from_secs(120)) .await; @@ -99,20 +67,14 @@ pub async fn upload_new_sound( if let Some(attachment) = reply_msg.attachments.get(0) { Some(attachment.url.clone()) } else { - invoke.followup(ctx.http.clone(), CreateGenericResponse::new().content("Please upload 1 attachment following your upload command. Aborted")).await?; + ctx.say("Please upload 1 attachment following your upload command. Aborted").await?; None } } None => { - invoke - .followup( - ctx.http.clone(), - CreateGenericResponse::new() - .content("Upload timed out. Please redo the command"), - ) - .await?; + ctx.say("Upload timed out. Please redo the command").await?; None } @@ -121,91 +83,52 @@ pub async fn upload_new_sound( if let Some(url) = attachment { match Sound::create_anon( - &new_name, + &name, url.as_str(), - invoke.guild_id().unwrap().0, - invoke.author_id().0, + ctx.guild_id().unwrap(), + ctx.author().id, pool, ) .await { Ok(_) => { - invoke - .followup( - ctx.http.clone(), - CreateGenericResponse::new() - .content("Sound has been uploaded"), - ) - .await?; + ctx.say("Sound has been uploaded").await?; } Err(e) => { println!("Error occurred during upload: {:?}", e); - invoke - .followup( - ctx.http.clone(), - CreateGenericResponse::new() - .content("Sound failed to upload."), - ) - .await?; + ctx.say("Sound failed to upload.").await?; } } } } else { - invoke.respond( - ctx.http.clone(), - CreateGenericResponse::new().content(format!( + ctx.say(format!( "You have reached the maximum number of sounds ({}). Either delete some with `/delete` or join our Patreon for unlimited uploads at **https://patreon.com/jellywx**", *MAX_SOUNDS, - ))).await?; + )).await?; } } } else { - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new() - .content("Please ensure the sound name contains a non-numerical character"), - ) + ctx.say("Please ensure the sound name contains a non-numerical character") .await?; } } else { - invoke.respond(ctx.http.clone(), CreateGenericResponse::new().content("Usage: `/upload `. Please ensure the name provided is less than 20 characters in length")).await?; + ctx.say("Usage: `/upload `. Please ensure the name provided is less than 20 characters in length").await?; } Ok(()) } -#[command("delete")] -#[group("Manage")] -#[description("Delete a sound you have uploaded")] -#[arg( - name = "query", - description = "Delete sound with the specified name or ID", - kind = "String", - required = true -)] -#[example("`/delete beep` - delete the sound with the name \"beep\"")] +/// Delete a sound you have uploaded +#[poise::command(slash_command, rename = "delete", category = "Manage")] pub async fn delete_sound( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - args: Args, -) -> CommandResult { - let pool = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("Could not get SQLPool from data"); + ctx: Context<'_>, + #[description = "Name or ID of sound to delete"] name: String, +) -> Result<(), Error> { + let pool = ctx.data().database.clone(); - let uid = invoke.author_id().0; - let gid = invoke.guild_id().unwrap().0; - - let name = args - .named("query") - .map(|s| s.to_owned()) - .unwrap_or(String::new()); + let uid = ctx.author().id.0; + let gid = ctx.guild_id().unwrap().0; let sound_vec = Sound::search_for_sound(&name, gid, uid, pool.clone(), true).await?; let sound_result = sound_vec.first(); @@ -213,18 +136,12 @@ pub async fn delete_sound( match sound_result { Some(sound) => { if sound.uploader_id != Some(uid) && sound.server_id != gid { - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content( - "You can only delete sounds from this guild or that you have uploaded.", - ), - ) + ctx.say("You can only delete sounds from this guild or that you have uploaded.") .await?; } else { let has_perms = { - if let Ok(member) = invoke.member(&ctx).await { - if let Ok(perms) = member.permissions(&ctx) { + if let Ok(member) = ctx.guild_id().unwrap().member(&ctx.discord(), uid).await { + if let Ok(perms) = member.permissions(&ctx.discord()) { perms.manage_guild() } else { false @@ -237,94 +154,49 @@ pub async fn delete_sound( if sound.uploader_id == Some(uid) || has_perms { sound.delete(pool).await?; - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content("Sound has been deleted"), - ) - .await?; + ctx.say("Sound has been deleted").await?; } else { - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content( - "Only server admins can delete sounds uploaded by other users.", - ), - ) + ctx.say("Only server admins can delete sounds uploaded by other users.") .await?; } } } None => { - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content("Sound could not be found by that name."), - ) - .await?; + ctx.say("Sound could not be found by that name.").await?; } } Ok(()) } -#[command("public")] -#[group("Manage")] -#[description("Change a sound between public and private")] -#[arg( - name = "query", - kind = "String", - description = "Sound name or ID to change the privacy setting of", - required = true -)] -#[example("`/public 12` - change sound with ID 12 to private")] -#[example("`/public 12` - change sound with ID 12 back to public")] +/// Change a sound between public and private +#[poise::command(slash_command, rename = "public", category = "Manage")] pub async fn change_public( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - args: Args, -) -> CommandResult { - let pool = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("Could not get SQLPool from data"); + ctx: Context<'_>, + #[description = "Name or ID of sound to change privacy setting of"] name: String, +) -> Result<(), Error> { + let pool = ctx.data().database.clone(); - let uid = invoke.author_id().as_u64().to_owned(); + let uid = ctx.author().id.0; + let gid = ctx.guild_id().unwrap().0; - let name = args.named("query").unwrap(); - let gid = *invoke.guild_id().unwrap().as_u64(); - - let mut sound_vec = Sound::search_for_sound(name, gid, uid, pool.clone(), true).await?; + let mut sound_vec = Sound::search_for_sound(&name, gid, uid, pool.clone(), true).await?; let sound_result = sound_vec.first_mut(); match sound_result { Some(sound) => { if sound.uploader_id != Some(uid) { - invoke.respond(ctx.http.clone(), CreateGenericResponse::new().content("You can only change the visibility of sounds you have uploaded. Use `?list me` to view your sounds")).await?; + ctx.say("You can only change the visibility of sounds you have uploaded. Use `/list` to view your sounds").await?; } else { if sound.public { sound.public = false; - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new() - .content("Sound has been set to private 🔒"), - ) - .await?; + ctx.say("Sound has been set to private 🔒").await?; } else { sound.public = true; - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content("Sound has been set to public 🔓"), - ) - .await?; + ctx.say("Sound has been set to public 🔓").await?; } sound.commit(pool).await? @@ -332,12 +204,7 @@ pub async fn change_public( } None => { - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content("Sound could not be found by that name."), - ) - .await?; + ctx.say("Sound could not be found by that name.").await?; } } diff --git a/src/cmds/mod.rs b/src/cmds/mod.rs index 1a8aa9c..ae5369c 100644 --- a/src/cmds/mod.rs +++ b/src/cmds/mod.rs @@ -1,6 +1,6 @@ pub mod info; pub mod manage; pub mod play; -pub mod search; -pub mod settings; -pub mod stop; +// pub mod search; +// pub mod settings; +// pub mod stop; diff --git a/src/cmds/play.rs b/src/cmds/play.rs index 397c518..0195784 100644 --- a/src/cmds/play.rs +++ b/src/cmds/play.rs @@ -1,389 +1,106 @@ -use std::{convert::TryFrom, time::Duration}; - -use regex_command_attr::command; -use serenity::{ - builder::CreateActionRow, - client::Context, - framework::standard::CommandResult, - model::interactions::{message_component::ButtonStyle, InteractionResponseType}, -}; -use songbird::{ - create_player, ffmpeg, - input::{cached::Memory, Input}, - Event, +use poise::serenity::{ + builder::CreateActionRow, model::interactions::message_component::ButtonStyle, }; -use crate::{ - event_handlers::RestartTrack, - framework::{Args, CommandInvoke, CreateGenericResponse}, - guild_data::CtxGuildData, - join_channel, play_from_query, - sound::Sound, - AudioIndex, MySQL, -}; +use crate::{play_from_query, sound::Sound, Context, Error}; -#[command] -#[aliases("p")] -#[required_permissions(Managed)] -#[group("Play")] -#[description("Play a sound in your current voice channel")] -#[arg( - name = "query", - description = "Play sound with the specified name or ID", - kind = "String", - required = true -)] -#[example("`/play ubercharge` - play sound with name \"ubercharge\" ")] -#[example("`/play 13002` - play sound with ID 13002")] +/// Play a sound in your current voice channel +#[poise::command(slash_command)] pub async fn play( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - args: Args, -) -> CommandResult { - let guild = invoke.guild(ctx.cache.clone()).unwrap(); + ctx: Context<'_>, + #[description = "Name or ID of sound to play"] name: String, +) -> Result<(), Error> { + let guild = ctx.guild().unwrap(); - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new() - .content(play_from_query(ctx, guild, invoke.author_id(), args, false).await), - ) + ctx.say(play_from_query(&ctx, guild, ctx.author().id, &name, false).await) .await?; Ok(()) } -#[command("loop")] -#[required_permissions(Managed)] -#[group("Play")] -#[description("Play a sound on loop in your current voice channel")] -#[arg( - name = "query", - description = "Play sound with the specified name or ID", - kind = "String", - required = true -)] -#[example("`/loop rain` - loop sound with name \"rain\" ")] -#[example("`/loop 13002` - play sound with ID 13002")] +/// Loop a sound in your current voice channel +#[poise::command(slash_command)] pub async fn loop_play( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - args: Args, -) -> CommandResult { - let guild = invoke.guild(ctx.cache.clone()).unwrap(); + ctx: Context<'_>, + #[description = "Name or ID of sound to loop"] name: String, +) -> Result<(), Error> { + let guild = ctx.guild().unwrap(); - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new() - .content(play_from_query(ctx, guild, invoke.author_id(), args, true).await), - ) + ctx.say(play_from_query(&ctx, guild, ctx.author().id, &name, true).await) .await?; Ok(()) } -#[command("ambience")] -#[required_permissions(Managed)] -#[group("Play")] -#[description("Play ambient sound in your current voice channel")] -#[arg( - name = "name", - description = "Play sound with the specified name", - kind = "String", - required = false -)] -#[example("`/ambience rain on tent` - play the ambient sound \"rain on tent\" ")] -pub async fn play_ambience( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - args: Args, -) -> CommandResult { - let guild = invoke.guild(ctx.cache.clone()).unwrap(); - - let channel_to_join = guild - .voice_states - .get(&invoke.author_id()) - .and_then(|voice_state| voice_state.channel_id); - - match channel_to_join { - Some(user_channel) => { - let audio_index = ctx.data.read().await.get::().cloned().unwrap(); - - if let Some(search_name) = args.named("name") { - if let Some(filename) = audio_index.get(search_name) { - let (track, track_handler) = create_player( - Input::try_from( - Memory::new(ffmpeg(format!("audio/{}", filename)).await.unwrap()) - .unwrap(), - ) - .unwrap(), - ); - - let (call_handler, _) = join_channel(ctx, guild.clone(), user_channel).await; - let guild_data = ctx.guild_data(guild).await.unwrap(); - - { - let mut lock = call_handler.lock().await; - - lock.play(track); - } - - let _ = track_handler.set_volume(guild_data.read().await.volume as f32 / 100.0); - let _ = track_handler.add_event( - Event::Periodic( - track_handler.metadata().duration.unwrap() - Duration::from_millis(200), - None, - ), - RestartTrack {}, - ); - - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new() - .content(format!("Playing ambience **{}**", search_name)), - ) - .await?; - } else { - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().embed(|e| { - e.title("Not Found").description(format!( - "Could not find ambience sound by name **{}** - -__Available ambience sounds:__ -{}", - search_name, - audio_index - .keys() - .into_iter() - .map(|i| i.as_str()) - .collect::>() - .join("\n") - )) - }), - ) - .await?; - } - } else { - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().embed(|e| { - e.title("Available Sounds").description( - audio_index - .keys() - .into_iter() - .map(|i| i.as_str()) - .collect::>() - .join("\n"), - ) - }), - ) - .await?; - } - } - - None => { - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content("You are not in a voice chat!"), - ) - .await?; - } - } - - Ok(()) -} - -#[command("soundboard")] -#[required_permissions(Managed)] -#[group("Play")] -#[kind(Slash)] -#[description("Get a menu of sounds with buttons to play them")] -#[arg( - name = "1", - description = "Query for sound button 1", - kind = "String", - required = true -)] -#[arg( - name = "2", - description = "Query for sound button 2", - kind = "String", - required = false -)] -#[arg( - name = "3", - description = "Query for sound button 3", - kind = "String", - required = false -)] -#[arg( - name = "4", - description = "Query for sound button 4", - kind = "String", - required = false -)] -#[arg( - name = "5", - description = "Query for sound button 5", - kind = "String", - required = false -)] -#[arg( - name = "6", - description = "Query for sound button 6", - kind = "String", - required = false -)] -#[arg( - name = "7", - description = "Query for sound button 7", - kind = "String", - required = false -)] -#[arg( - name = "8", - description = "Query for sound button 8", - kind = "String", - required = false -)] -#[arg( - name = "9", - description = "Query for sound button 9", - kind = "String", - required = false -)] -#[arg( - name = "10", - description = "Query for sound button 10", - kind = "String", - required = false -)] -#[arg( - name = "11", - description = "Query for sound button 11", - kind = "String", - required = false -)] -#[arg( - name = "12", - description = "Query for sound button 12", - kind = "String", - required = false -)] -#[arg( - name = "13", - description = "Query for sound button 13", - kind = "String", - required = false -)] -#[arg( - name = "14", - description = "Query for sound button 14", - kind = "String", - required = false -)] -#[arg( - name = "15", - description = "Query for sound button 15", - kind = "String", - required = false -)] -#[arg( - name = "16", - description = "Query for sound button 16", - kind = "String", - required = false -)] -#[arg( - name = "17", - description = "Query for sound button 17", - kind = "String", - required = false -)] -#[arg( - name = "18", - description = "Query for sound button 18", - kind = "String", - required = false -)] -#[arg( - name = "19", - description = "Query for sound button 19", - kind = "String", - required = false -)] -#[arg( - name = "20", - description = "Query for sound button 20", - kind = "String", - required = false -)] -#[arg( - name = "21", - description = "Query for sound button 21", - kind = "String", - required = false -)] -#[arg( - name = "22", - description = "Query for sound button 22", - kind = "String", - required = false -)] -#[arg( - name = "23", - description = "Query for sound button 23", - kind = "String", - required = false -)] -#[arg( - name = "24", - description = "Query for sound button 24", - kind = "String", - required = false -)] -#[arg( - name = "25", - description = "Query for sound button 25", - kind = "String", - required = false -)] -#[example("`/soundboard ubercharge` - create a soundboard with a button for the \"ubercharge\" sound effect")] -#[example("`/soundboard 57000 24119 2 1002 13202` - create a soundboard with 5 buttons, for sounds with the IDs presented")] +/// Get a menu of sounds with buttons to play them +#[poise::command(slash_command, rename = "soundboard", category = "Play")] pub async fn soundboard( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - args: Args, -) -> CommandResult { - if let Some(interaction) = invoke.interaction() { - let _ = interaction - .create_interaction_response(&ctx, |r| { - r.kind(InteractionResponseType::DeferredChannelMessageWithSource) - }) - .await; - } + ctx: Context<'_>, + #[description = "Name or ID of sound for button 1"] sound_1: String, + #[description = "Name or ID of sound for button 2"] sound_2: Option, + #[description = "Name or ID of sound for button 3"] sound_3: Option, + #[description = "Name or ID of sound for button 4"] sound_4: Option, + #[description = "Name or ID of sound for button 5"] sound_5: Option, + #[description = "Name or ID of sound for button 6"] sound_6: Option, + #[description = "Name or ID of sound for button 7"] sound_7: Option, + #[description = "Name or ID of sound for button 8"] sound_8: Option, + #[description = "Name or ID of sound for button 9"] sound_9: Option, + #[description = "Name or ID of sound for button 10"] sound_10: Option, + #[description = "Name or ID of sound for button 11"] sound_11: Option, + #[description = "Name or ID of sound for button 12"] sound_12: Option, + #[description = "Name or ID of sound for button 13"] sound_13: Option, + #[description = "Name or ID of sound for button 14"] sound_14: Option, + #[description = "Name or ID of sound for button 15"] sound_15: Option, + #[description = "Name or ID of sound for button 16"] sound_16: Option, + #[description = "Name or ID of sound for button 17"] sound_17: Option, + #[description = "Name or ID of sound for button 18"] sound_18: Option, + #[description = "Name or ID of sound for button 19"] sound_19: Option, + #[description = "Name or ID of sound for button 20"] sound_20: Option, + #[description = "Name or ID of sound for button 21"] sound_21: Option, + #[description = "Name or ID of sound for button 22"] sound_22: Option, + #[description = "Name or ID of sound for button 23"] sound_23: Option, + #[description = "Name or ID of sound for button 24"] sound_24: Option, + #[description = "Name or ID of sound for button 25"] sound_25: Option, +) -> Result<(), Error> { + ctx.defer().await?; - let pool = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("Could not get SQLPool from data"); + let pool = ctx.data().database.clone(); + + let query_terms = [ + Some(sound_1), + sound_2, + sound_3, + sound_4, + sound_5, + sound_6, + sound_7, + sound_8, + sound_9, + sound_10, + sound_11, + sound_12, + sound_13, + sound_14, + sound_15, + sound_16, + sound_17, + sound_18, + sound_19, + sound_20, + sound_21, + sound_22, + sound_23, + sound_24, + sound_25, + ]; let mut sounds = vec![]; - for n in 1..25 { + for sound in query_terms.iter().flatten() { let search = Sound::search_for_sound( - args.named(&n.to_string()).unwrap_or(&"".to_string()), - invoke.guild_id().unwrap(), - invoke.author_id(), + &sound, + ctx.guild_id().unwrap(), + ctx.author().id, pool.clone(), true, ) @@ -396,29 +113,25 @@ pub async fn soundboard( } } - invoke - .followup( - ctx.http.clone(), - CreateGenericResponse::new() - .content("**Play a sound:**") - .components(|c| { - for row in sounds.as_slice().chunks(5) { - let mut action_row: CreateActionRow = Default::default(); - for sound in row { - action_row.create_button(|b| { - b.style(ButtonStyle::Primary) - .label(&sound.name) - .custom_id(sound.id) - }); - } + ctx.send(|m| { + m.content("**Play a sound:**").components(|c| { + for row in sounds.as_slice().chunks(5) { + let mut action_row: CreateActionRow = Default::default(); + for sound in row { + action_row.create_button(|b| { + b.style(ButtonStyle::Primary) + .label(&sound.name) + .custom_id(sound.id) + }); + } - c.add_action_row(action_row); - } + c.add_action_row(action_row); + } - c - }), - ) - .await?; + c + }) + }) + .await?; Ok(()) } diff --git a/src/cmds/search.rs b/src/cmds/search.rs index 2fc468a..4e3a285 100644 --- a/src/cmds/search.rs +++ b/src/cmds/search.rs @@ -1,11 +1,4 @@ -use regex_command_attr::command; -use serenity::{client::Context, framework::standard::CommandResult}; - -use crate::{ - framework::{Args, CommandInvoke, CreateGenericResponse}, - sound::Sound, - MySQL, -}; +use crate::sound::Sound; fn format_search_results(search_results: Vec) -> CreateGenericResponse { let mut current_character_count = 0; diff --git a/src/event_handlers.rs b/src/event_handlers.rs index d39554e..42b5c08 100644 --- a/src/event_handlers.rs +++ b/src/event_handlers.rs @@ -1,26 +1,13 @@ use std::{collections::HashMap, env}; -use serenity::{ - async_trait, - client::{Context, EventHandler}, - model::{ - channel::Channel, - gateway::{Activity, Ready}, - guild::Guild, - id::GuildId, - interactions::{Interaction, InteractionResponseType}, - voice::VoiceState, - }, - utils::shard_id, -}; +use poise::serenity::{async_trait, model::channel::Channel, prelude::Context, utils::shard_id}; use songbird::{Event, EventContext, EventHandler as SongbirdEventHandler}; use crate::{ - framework::{Args, RegexFramework}, guild_data::CtxGuildData, - join_channel, play_audio, play_from_query, + join_channel, play_audio, sound::{JoinSoundCtx, Sound}, - MySQL, ReqwestClient, + Data, Error, }; pub struct RestartTrack; @@ -36,179 +23,111 @@ impl SongbirdEventHandler for RestartTrack { } } -pub struct Handler; +pub async fn listener(ctx: &Context, event: &poise::Event<'_>, data: &Data) -> Result<(), Error> { + match event { + poise::Event::GuildCreate { guild, is_new, .. } => { + if *is_new { + if let Ok(token) = env::var("DISCORDBOTS_TOKEN") { + let shard_count = ctx.cache.shard_count(); + let current_shard_id = shard_id(guild.id.as_u64().to_owned(), shard_count); -#[serenity::async_trait] -impl EventHandler for Handler { - async fn ready(&self, ctx: Context, _: Ready) { - ctx.set_activity(Activity::watching("for /play")).await; - } + let guild_count = ctx + .cache + .guilds() + .iter() + .filter(|g| { + shard_id(g.as_u64().to_owned(), shard_count) == current_shard_id + }) + .count() as u64; - async fn guild_create(&self, ctx: Context, guild: Guild, is_new: bool) { - if is_new { - if let Ok(token) = env::var("DISCORDBOTS_TOKEN") { - let shard_count = ctx.cache.shard_count(); - let current_shard_id = shard_id(guild.id.as_u64().to_owned(), shard_count); + let mut hm = HashMap::new(); + hm.insert("server_count", guild_count); + hm.insert("shard_id", current_shard_id); + hm.insert("shard_count", shard_count); - let guild_count = ctx - .cache - .guilds() - .iter() - .filter(|g| shard_id(g.as_u64().to_owned(), shard_count) == current_shard_id) - .count() as u64; - - let mut hm = HashMap::new(); - hm.insert("server_count", guild_count); - hm.insert("shard_id", current_shard_id); - hm.insert("shard_count", shard_count); - - let client = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("Could not get ReqwestClient from data"); - - let response = client - .post( - format!( - "https://top.gg/api/bots/{}/stats", - ctx.cache.current_user_id().as_u64() + let response = data + .http + .post( + format!( + "https://top.gg/api/bots/{}/stats", + ctx.cache.current_user_id().as_u64() + ) + .as_str(), ) - .as_str(), - ) - .header("Authorization", token) - .json(&hm) - .send() - .await; + .header("Authorization", token) + .json(&hm) + .send() + .await; - if let Err(res) = response { - println!("DiscordBots Response: {:?}", res); + if let Err(res) = response { + println!("DiscordBots Response: {:?}", res); + } } } } - } + poise::Event::VoiceStateUpdate { old, new, .. } => { + if let Some(past_state) = old { + if let (Some(guild_id), None) = (past_state.guild_id, new.channel_id) { + if let Some(channel_id) = past_state.channel_id { + if let Some(Channel::Guild(channel)) = channel_id.to_channel_cached(&ctx) { + if channel.members(&ctx).await.map(|m| m.len()).unwrap_or(0) <= 1 { + let songbird = songbird::get(&ctx).await.unwrap(); - async fn voice_state_update( - &self, - ctx: Context, - guild_id_opt: Option, - old: Option, - new: VoiceState, - ) { - if let Some(past_state) = old { - if let (Some(guild_id), None) = (guild_id_opt, new.channel_id) { - if let Some(channel_id) = past_state.channel_id { - if let Some(Channel::Guild(channel)) = channel_id.to_channel_cached(&ctx) { - if channel.members(&ctx).await.map(|m| m.len()).unwrap_or(0) <= 1 { - let songbird = songbird::get(&ctx).await.unwrap(); - - let _ = songbird.remove(guild_id).await; + let _ = songbird.remove(guild_id).await; + } } } } - } - } else if let (Some(guild_id), Some(user_channel)) = (guild_id_opt, new.channel_id) { - if let Some(guild) = ctx.cache.guild(guild_id) { - let pool = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("Could not get SQLPool from data"); + } else if let (Some(guild_id), Some(user_channel)) = (new.guild_id, new.channel_id) { + if let Some(guild) = ctx.cache.guild(guild_id) { + let pool = data.database.clone(); - let guild_data_opt = ctx.guild_data(guild.id).await; + let guild_data_opt = data.guild_data(guild.id).await; - if let Ok(guild_data) = guild_data_opt { - let volume; - let allowed_greets; + if let Ok(guild_data) = guild_data_opt { + let volume; + let allowed_greets; - { - let read = guild_data.read().await; + { + let read = guild_data.read().await; - volume = read.volume; - allowed_greets = read.allow_greets; - } + volume = read.volume; + allowed_greets = read.allow_greets; + } - if allowed_greets { - if let Some(join_id) = ctx.join_sound(new.user_id).await { - let mut sound = sqlx::query_as_unchecked!( - Sound, - " + if allowed_greets { + if let Some(join_id) = data.join_sound(new.user_id).await { + let mut sound = sqlx::query_as_unchecked!( + Sound, + " SELECT name, id, public, server_id, uploader_id FROM sounds WHERE id = ? ", - join_id - ) - .fetch_one(&pool) - .await - .unwrap(); + join_id + ) + .fetch_one(&pool) + .await + .unwrap(); - let (handler, _) = join_channel(&ctx, guild, user_channel).await; + let (handler, _) = join_channel(&ctx, guild, user_channel).await; - let _ = play_audio( - &mut sound, - volume, - &mut handler.lock().await, - pool, - false, - ) - .await; + let _ = play_audio( + &mut sound, + volume, + &mut handler.lock().await, + pool, + false, + ) + .await; + } } } } } } + _ => {} } - async fn interaction_create(&self, ctx: Context, interaction: Interaction) { - match interaction { - Interaction::ApplicationCommand(application_command) => { - if application_command.guild_id.is_none() { - return; - } - - let framework = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("RegexFramework not found in context"); - - framework.execute(ctx, application_command).await; - } - Interaction::MessageComponent(component) => { - if component.guild_id.is_none() { - return; - } - - let mut args = Args { - args: Default::default(), - }; - args.args - .insert("query".to_string(), component.data.custom_id.clone()); - - play_from_query( - &ctx, - component.guild_id.unwrap().to_guild_cached(&ctx).unwrap(), - component.user.id, - args, - false, - ) - .await; - - component - .create_interaction_response(ctx, |r| { - r.kind(InteractionResponseType::DeferredUpdateMessage) - }) - .await - .unwrap(); - } - _ => {} - } - } + Ok(()) } diff --git a/src/framework.rs b/src/framework.rs deleted file mode 100644 index 777fee9..0000000 --- a/src/framework.rs +++ /dev/null @@ -1,735 +0,0 @@ -use std::{ - collections::{HashMap, HashSet}, - env, fmt, - hash::{Hash, Hasher}, - sync::Arc, -}; - -use log::{debug, error, info, warn}; -use regex::{Match, Regex, RegexBuilder}; -use serde_json::Value; -use serenity::{ - async_trait, - builder::{CreateApplicationCommands, CreateComponents, CreateEmbed}, - cache::Cache, - client::Context, - framework::{standard::CommandResult, Framework}, - futures::prelude::future::BoxFuture, - http::Http, - model::{ - channel::{Channel, GuildChannel, Message}, - guild::{Guild, Member}, - id::{ChannelId, GuildId, RoleId, UserId}, - interactions::{ - application_command::{ - ApplicationCommand, ApplicationCommandInteraction, ApplicationCommandOptionType, - }, - InteractionResponseType, - }, - }, - prelude::TypeMapKey, - Result as SerenityResult, -}; - -use crate::guild_data::CtxGuildData; - -type CommandFn = for<'fut> fn( - &'fut Context, - &'fut (dyn CommandInvoke + Sync + Send), - Args, -) -> BoxFuture<'fut, CommandResult>; - -pub struct Args { - pub args: HashMap, -} - -impl Args { - pub fn from(message: &str, arg_schema: &'static [&'static Arg]) -> Self { - // construct regex from arg schema - let mut re = arg_schema - .iter() - .map(|a| a.to_regex()) - .collect::>() - .join(r#"\s*"#); - - re.push_str("$"); - - let regex = Regex::new(&re).unwrap(); - let capture_names = regex.capture_names(); - let captures = regex.captures(message); - - let mut args = HashMap::new(); - - if let Some(captures) = captures { - for name in capture_names.filter(|n| n.is_some()).map(|n| n.unwrap()) { - if let Some(cap) = captures.name(name) { - args.insert(name.to_string(), cap.as_str().to_string()); - } - } - } - - Self { args } - } - - pub fn named(&self, name: D) -> Option<&String> { - let name = name.to_string(); - - self.args.get(&name) - } -} - -pub struct CreateGenericResponse { - content: String, - embed: Option, - components: Option, -} - -impl CreateGenericResponse { - pub fn new() -> Self { - Self { - content: "".to_string(), - embed: None, - components: None, - } - } - - pub fn content(mut self, content: D) -> Self { - self.content = content.to_string(); - - self - } - - pub fn embed &mut CreateEmbed>(mut self, f: F) -> Self { - let mut embed = CreateEmbed::default(); - f(&mut embed); - - self.embed = Some(embed); - self - } - - pub fn components &mut CreateComponents>( - mut self, - f: F, - ) -> Self { - let mut components = CreateComponents::default(); - f(&mut components); - - self.components = Some(components); - self - } -} - -#[async_trait] -pub trait CommandInvoke { - fn channel_id(&self) -> ChannelId; - fn guild_id(&self) -> Option; - fn guild(&self, cache: Arc) -> Option; - fn author_id(&self) -> UserId; - async fn member(&self, context: &Context) -> SerenityResult; - fn msg(&self) -> Option; - fn interaction(&self) -> Option; - async fn respond( - &self, - http: Arc, - generic_response: CreateGenericResponse, - ) -> SerenityResult<()>; - async fn followup( - &self, - http: Arc, - generic_response: CreateGenericResponse, - ) -> SerenityResult<()>; -} - -#[async_trait] -impl CommandInvoke for Message { - fn channel_id(&self) -> ChannelId { - self.channel_id - } - - fn guild_id(&self) -> Option { - self.guild_id - } - - fn guild(&self, cache: Arc) -> Option { - self.guild(cache) - } - - fn author_id(&self) -> UserId { - self.author.id - } - - async fn member(&self, context: &Context) -> SerenityResult { - self.member(context).await - } - - fn msg(&self) -> Option { - Some(self.clone()) - } - - fn interaction(&self) -> Option { - None - } - - async fn respond( - &self, - http: Arc, - generic_response: CreateGenericResponse, - ) -> SerenityResult<()> { - self.channel_id - .send_message(http, |m| { - m.content(generic_response.content); - - if let Some(embed) = generic_response.embed { - m.set_embed(embed.clone()); - } - - if let Some(components) = generic_response.components { - m.components(|c| { - *c = components; - c - }); - } - - m - }) - .await - .map(|_| ()) - } - - async fn followup( - &self, - http: Arc, - generic_response: CreateGenericResponse, - ) -> SerenityResult<()> { - self.channel_id - .send_message(http, |m| { - m.content(generic_response.content); - - if let Some(embed) = generic_response.embed { - m.set_embed(embed.clone()); - } - - if let Some(components) = generic_response.components { - m.components(|c| { - *c = components; - c - }); - } - - m - }) - .await - .map(|_| ()) - } -} - -#[async_trait] -impl CommandInvoke for ApplicationCommandInteraction { - fn channel_id(&self) -> ChannelId { - self.channel_id - } - - fn guild_id(&self) -> Option { - self.guild_id - } - - fn guild(&self, cache: Arc) -> Option { - if let Some(guild_id) = self.guild_id { - guild_id.to_guild_cached(cache) - } else { - None - } - } - - fn author_id(&self) -> UserId { - self.member.as_ref().unwrap().user.id - } - - async fn member(&self, _: &Context) -> SerenityResult { - Ok(self.member.clone().unwrap()) - } - - fn msg(&self) -> Option { - None - } - - fn interaction(&self) -> Option { - Some(self.clone()) - } - - async fn respond( - &self, - http: Arc, - generic_response: CreateGenericResponse, - ) -> SerenityResult<()> { - self.create_interaction_response(http, |r| { - r.kind(InteractionResponseType::ChannelMessageWithSource) - .interaction_response_data(|d| { - d.content(generic_response.content); - - if let Some(embed) = generic_response.embed { - d.add_embed(embed.clone()); - } - - if let Some(components) = generic_response.components { - d.components(|c| { - *c = components; - c - }); - } - - d - }) - }) - .await - .map(|_| ()) - } - - async fn followup( - &self, - http: Arc, - generic_response: CreateGenericResponse, - ) -> SerenityResult<()> { - self.create_followup_message(http, |d| { - d.content(generic_response.content); - - if let Some(embed) = generic_response.embed { - d.add_embed(embed.clone()); - } - - if let Some(components) = generic_response.components { - d.components(|c| { - *c = components; - c - }); - } - - d - }) - .await - .map(|_| ()) - } -} - -#[derive(Debug, PartialEq)] -pub enum PermissionLevel { - Unrestricted, - Managed, - Restricted, -} - -#[derive(Debug, PartialEq)] -pub enum CommandKind { - Slash, - Both, - Text, -} - -#[derive(Debug)] -pub struct Arg { - pub name: &'static str, - pub description: &'static str, - pub kind: ApplicationCommandOptionType, - pub required: bool, -} - -impl Arg { - pub fn to_regex(&self) -> String { - match self.kind { - ApplicationCommandOptionType::String => format!(r#"(?P<{}>.+?)"#, self.name), - ApplicationCommandOptionType::Integer => format!(r#"(?P<{}>\d+)"#, self.name), - ApplicationCommandOptionType::Boolean => format!(r#"(?P<{0}>{0})?"#, self.name), - ApplicationCommandOptionType::User => format!(r#"<(@|@!)(?P<{}>\d+)>"#, self.name), - ApplicationCommandOptionType::Channel => format!(r#"<#(?P<{}>\d+)>"#, self.name), - ApplicationCommandOptionType::Role => format!(r#"<@&(?P<{}>\d+)>"#, self.name), - ApplicationCommandOptionType::Mentionable => { - format!(r#"<(?P<{0}_pref>@|@!|@&|#)(?P<{0}>\d+)>"#, self.name) - } - _ => String::new(), - } - } -} - -pub struct Command { - pub fun: CommandFn, - - pub names: &'static [&'static str], - - pub desc: &'static str, - pub examples: &'static [&'static str], - pub group: &'static str, - - pub kind: CommandKind, - pub required_permissions: PermissionLevel, - pub args: &'static [&'static Arg], -} - -impl Hash for Command { - fn hash(&self, state: &mut H) { - self.names[0].hash(state) - } -} - -impl PartialEq for Command { - fn eq(&self, other: &Self) -> bool { - self.names[0] == other.names[0] - } -} - -impl Eq for Command {} - -impl Command { - async fn check_permissions(&self, ctx: &Context, guild: &Guild, member: &Member) -> bool { - if self.required_permissions == PermissionLevel::Unrestricted { - true - } else { - let permissions = guild.member_permissions(&ctx, &member.user).await.unwrap(); - - if permissions.manage_guild() { - return true; - } - - if self.required_permissions == PermissionLevel::Managed { - match ctx.guild_data(guild.id).await { - Ok(guild_data) => guild_data.read().await.allowed_role.map_or(true, |role| { - role == guild.id.0 || { - let role_id = RoleId(role); - - member.roles.contains(&role_id) - } - }), - - Err(e) => { - warn!("Unexpected error occurred querying roles: {:?}", e); - - false - } - } - } else { - false - } - } - } -} - -impl fmt::Debug for Command { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Command") - .field("name", &self.names[0]) - .field("required_permissions", &self.required_permissions) - .field("args", &self.args) - .finish() - } -} - -pub struct RegexFramework { - pub commands: HashMap, - pub commands_: HashSet<&'static Command>, - command_matcher: Regex, - default_prefix: String, - client_id: u64, - ignore_bots: bool, - case_insensitive: bool, -} - -impl TypeMapKey for RegexFramework { - type Value = Arc; -} - -impl RegexFramework { - pub fn new>(client_id: T) -> Self { - Self { - commands: HashMap::new(), - commands_: HashSet::new(), - command_matcher: Regex::new(r#"^$"#).unwrap(), - default_prefix: "".to_string(), - client_id: client_id.into(), - ignore_bots: true, - case_insensitive: true, - } - } - - pub fn case_insensitive(mut self, case_insensitive: bool) -> Self { - self.case_insensitive = case_insensitive; - - self - } - - pub fn default_prefix(mut self, new_prefix: T) -> Self { - self.default_prefix = new_prefix.to_string(); - - self - } - - pub fn ignore_bots(mut self, ignore_bots: bool) -> Self { - self.ignore_bots = ignore_bots; - - self - } - - pub fn add_command(mut self, command: &'static Command) -> Self { - self.commands_.insert(command); - - for name in command.names { - self.commands.insert(name.to_string(), command); - } - - self - } - - pub fn build(mut self) -> Self { - let command_names; - - { - let mut command_names_vec = self.commands.keys().map(|k| &k[..]).collect::>(); - - command_names_vec.sort_unstable_by(|a, b| b.len().cmp(&a.len())); - - command_names = command_names_vec.join("|"); - } - - debug!("Command names: {}", command_names); - - { - let match_string = r#"^(?:(?:<@ID>\s*)|(?:<@!ID>\s*)|(?P\S{1,5}?))(?PCOMMANDS)(?:$|\s+(?P.*))$"# - .replace("COMMANDS", command_names.as_str()) - .replace("ID", self.client_id.to_string().as_str()); - - self.command_matcher = RegexBuilder::new(match_string.as_str()) - .case_insensitive(self.case_insensitive) - .dot_matches_new_line(true) - .build() - .unwrap(); - } - - self - } - - fn _populate_commands<'a>( - &self, - commands: &'a mut CreateApplicationCommands, - ) -> &'a mut CreateApplicationCommands { - for command in &self.commands_ { - commands.create_application_command(|c| { - c.name(command.names[0]).description(command.desc); - - for arg in command.args { - c.create_option(|o| { - o.name(arg.name) - .description(arg.description) - .kind(arg.kind) - .required(arg.required) - }); - } - - c - }); - } - - commands - } - - pub async fn build_slash(&self, http: impl AsRef) { - info!("Building slash commands..."); - - match env::var("TEST_GUILD") - .map(|i| i.parse::().ok()) - .ok() - .flatten() - .map(|i| GuildId(i)) - { - None => { - ApplicationCommand::set_global_application_commands(&http, |c| { - self._populate_commands(c) - }) - .await - .unwrap(); - } - Some(debug_guild) => { - debug_guild - .set_application_commands(&http, |c| self._populate_commands(c)) - .await - .unwrap(); - } - } - - info!("Slash commands built!"); - } - - pub async fn execute(&self, ctx: Context, interaction: ApplicationCommandInteraction) { - let command = { - self.commands.get(&interaction.data.name).expect(&format!( - "Received invalid command: {}", - interaction.data.name - )) - }; - - if command - .check_permissions( - &ctx, - &interaction.guild(ctx.cache.clone()).unwrap(), - &interaction.clone().member.unwrap(), - ) - .await - { - let mut args = HashMap::new(); - - for arg in interaction - .data - .options - .iter() - .filter(|o| o.value.is_some()) - { - args.insert( - arg.name.clone(), - match arg.value.clone().unwrap() { - Value::Bool(b) => { - if b { - arg.name.clone() - } else { - String::new() - } - } - Value::Number(n) => n.to_string(), - Value::String(s) => s, - _ => String::new(), - }, - ); - } - - info!( - "[Shard {}] [Guild {}] /{} {:?}", - ctx.shard_id, - interaction.guild_id.unwrap(), - interaction.data.name, - args - ); - - (command.fun)(&ctx, &interaction, Args { args }) - .await - .unwrap(); - } else if command.required_permissions == PermissionLevel::Managed { - let _ = interaction - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content("You must either be an Admin or have a role specified by `/roles` to do this command") - ) - .await; - } else if command.required_permissions == PermissionLevel::Restricted { - let _ = interaction - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content("You must be an Admin to do this command"), - ) - .await; - } - } -} - -enum PermissionCheck { - None, // No permissions - All, // Sufficient permissions -} - -#[async_trait] -impl Framework for RegexFramework { - async fn dispatch(&self, ctx: Context, msg: Message) { - async fn check_self_permissions( - ctx: &Context, - channel: &GuildChannel, - ) -> SerenityResult { - let user_id = ctx.cache.current_user_id(); - - let channel_perms = channel.permissions_for_user(ctx, user_id)?; - - Ok( - if channel_perms.send_messages() && channel_perms.embed_links() { - PermissionCheck::All - } else { - PermissionCheck::None - }, - ) - } - - async fn check_prefix(ctx: &Context, guild: &Guild, prefix_opt: Option>) -> bool { - if let Some(prefix) = prefix_opt { - match ctx.guild_data(guild.id).await { - Ok(guild_data) => prefix.as_str() == guild_data.read().await.prefix, - - Err(_) => prefix.as_str() == "?", - } - } else { - true - } - } - - // gate to prevent analysing messages unnecessarily - if msg.author.bot || msg.content.is_empty() { - } - // Guild Command - else if let (Some(guild), Ok(Channel::Guild(channel))) = - (msg.guild(&ctx), msg.channel(&ctx).await) - { - if let Some(full_match) = self.command_matcher.captures(&msg.content) { - if check_prefix(&ctx, &guild, full_match.name("prefix")).await { - match check_self_permissions(&ctx, &channel).await { - Ok(perms) => match perms { - PermissionCheck::All => { - let command = self - .commands - .get(&full_match.name("cmd").unwrap().as_str().to_lowercase()) - .unwrap(); - - if command.kind != CommandKind::Slash { - let args = full_match - .name("args") - .map(|m| m.as_str()) - .unwrap_or("") - .to_string(); - - let member = guild.member(&ctx, &msg.author).await.unwrap(); - - if command.check_permissions(&ctx, &guild, &member).await { - let _ = msg.channel_id.say( - &ctx, - format!( - "You **must** begin to switch to slash commands. All commands are available via slash commands now. If slash commands don't display in your server, please use this link: https://discord.com/api/oauth2/authorize?client_id={}&permissions=3165184&scope=applications.commands%20bot", - ctx.cache.current_user().id - ) - ).await; - - (command.fun)(&ctx, &msg, Args::from(&args, command.args)) - .await - .unwrap(); - } else if command.required_permissions - == PermissionLevel::Managed - { - let _ = msg.channel_id.say(&ctx, "You must either be an Admin or have a role specified in `?roles` to do this command").await; - } else if command.required_permissions - == PermissionLevel::Restricted - { - let _ = msg - .channel_id - .say(&ctx, "You must be an Admin to do this command") - .await; - } - } - } - - PermissionCheck::None => { - warn!("Missing enough permissions for guild {}", guild.id); - } - }, - - Err(e) => { - error!( - "Error occurred getting permissions in guild {}: {:?}", - guild.id, e - ); - } - } - } - } - } - } -} diff --git a/src/guild_data.rs b/src/guild_data.rs index 4dad567..2ab5efd 100644 --- a/src/guild_data.rs +++ b/src/guild_data.rs @@ -1,10 +1,10 @@ use std::sync::Arc; -use serenity::{async_trait, model::id::GuildId, prelude::Context}; +use poise::serenity::{async_trait, model::id::GuildId}; use sqlx::mysql::MySqlPool; use tokio::sync::RwLock; -use crate::{GuildDataCache, MySQL}; +use crate::{Context, Data}; #[derive(Clone)] pub struct GuildData { @@ -24,31 +24,33 @@ pub trait CtxGuildData { } #[async_trait] -impl CtxGuildData for Context { +impl CtxGuildData for Context<'_> { + async fn guild_data + Send + Sync>( + &self, + guild_id: G, + ) -> Result>, sqlx::Error> { + self.data().guild_data(guild_id).await + } +} + +#[async_trait] +impl CtxGuildData for Data { async fn guild_data + Send + Sync>( &self, guild_id: G, ) -> Result>, sqlx::Error> { let guild_id = guild_id.into(); - let guild_cache = self - .data - .read() - .await - .get::() - .cloned() - .unwrap(); - - let x = if let Some(guild_data) = guild_cache.get(&guild_id) { + let x = if let Some(guild_data) = self.guild_data_cache.get(&guild_id) { Ok(guild_data.clone()) } else { - let pool = self.data.read().await.get::().cloned().unwrap(); + let pool = self.database.clone(); match GuildData::from_id(guild_id, pool).await { Ok(d) => { let lock = Arc::new(RwLock::new(d)); - guild_cache.insert(guild_id, lock.clone()); + self.guild_data_cache.insert(guild_id, lock.clone()); Ok(lock) } diff --git a/src/main.rs b/src/main.rs index f2ca6e8..079671a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,65 +4,41 @@ extern crate lazy_static; mod cmds; mod error; mod event_handlers; -mod framework; mod guild_data; mod sound; -use std::{collections::HashMap, env, sync::Arc}; +use std::{env, sync::Arc}; use dashmap::DashMap; use dotenv::dotenv; -use log::info; -use serenity::{ - client::{bridge::gateway::GatewayIntents, Client, Context}, - http::Http, +use poise::serenity::{ + builder::CreateApplicationCommands, model::{ channel::Channel, + gateway::{Activity, GatewayIntents}, guild::Guild, id::{ChannelId, GuildId, UserId}, }, - prelude::{Mutex, TypeMapKey}, }; use songbird::{create_player, error::JoinResult, tracks::TrackHandle, Call, SerenityInit}; use sqlx::mysql::MySqlPool; -use tokio::sync::{MutexGuard, RwLock}; +use tokio::sync::{Mutex, MutexGuard, RwLock}; use crate::{ - event_handlers::Handler, - framework::{Args, RegexFramework}, + event_handlers::listener, guild_data::{CtxGuildData, GuildData}, sound::Sound, }; -struct MySQL; - -impl TypeMapKey for MySQL { - type Value = MySqlPool; +pub struct Data { + database: MySqlPool, + http: reqwest::Client, + guild_data_cache: DashMap>>, + join_sound_cache: DashMap>, } -struct ReqwestClient; - -impl TypeMapKey for ReqwestClient { - type Value = Arc; -} - -struct AudioIndex; - -impl TypeMapKey for AudioIndex { - type Value = Arc>; -} - -struct GuildDataCache; - -impl TypeMapKey for GuildDataCache { - type Value = Arc>>>; -} - -struct JoinSoundCache; - -impl TypeMapKey for JoinSoundCache { - type Value = Arc>>; -} +type Error = Box; +type Context<'a> = poise::Context<'a, Data, Error>; const THEME_COLOR: u32 = 0x00e0f3; @@ -96,7 +72,7 @@ async fn play_audio( } async fn join_channel( - ctx: &Context, + ctx: &poise::serenity_prelude::Context, guild: Guild, channel_id: ChannelId, ) -> (Arc>, JoinResult<()>) { @@ -139,10 +115,10 @@ async fn join_channel( } async fn play_from_query( - ctx: &Context, + ctx: &Context<'_>, guild: Guild, user_id: UserId, - args: Args, + query: &str, loop_: bool, ) -> String { let guild_id = guild.id; @@ -154,18 +130,10 @@ async fn play_from_query( match channel_to_join { Some(user_channel) => { - let search_term = args.named("query").unwrap(); - - let pool = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("Could not get SQLPool from data"); + let pool = ctx.data().database.clone(); let mut sound_vec = - Sound::search_for_sound(search_term, guild_id, user_id, pool.clone(), true) + Sound::search_for_sound(query, guild_id, user_id, pool.clone(), true) .await .unwrap(); @@ -175,7 +143,7 @@ async fn play_from_query( Some(sound) => { { let (call_handler, _) = - join_channel(ctx, guild.clone(), user_channel).await; + join_channel(ctx.discord(), guild.clone(), user_channel).await; let guild_data = ctx.guild_data(guild_id).await.unwrap(); @@ -203,6 +171,36 @@ async fn play_from_query( } } +pub async fn register_application_commands( + ctx: &poise::serenity::client::Context, + framework: &poise::Framework, + guild_id: Option, +) -> Result<(), poise::serenity::Error> { + let mut commands_builder = CreateApplicationCommands::default(); + let commands = &framework.options().commands; + for command in commands { + if let Some(slash_command) = command.create_as_slash_command() { + commands_builder.add_application_command(slash_command); + } + if let Some(context_menu_command) = command.create_as_context_menu_command() { + commands_builder.add_application_command(context_menu_command); + } + } + let commands_builder = poise::serenity::json::Value::Array(commands_builder.0); + + if let Some(guild_id) = guild_id { + ctx.http + .create_guild_application_commands(guild_id.0, &commands_builder) + .await?; + } else { + ctx.http + .create_global_application_commands(&commands_builder) + .await?; + } + + Ok(()) +} + // entry point #[tokio::main] async fn main() -> Result<(), Box> { @@ -210,141 +208,63 @@ async fn main() -> Result<(), Box> { dotenv()?; - let token = env::var("DISCORD_TOKEN").expect("Missing DISCORD_TOKEN from environment"); + let discord_token = env::var("DISCORD_TOKEN").expect("Missing DISCORD_TOKEN from environment"); - let http = Http::new_with_token(&token); - - let logged_in_id = http.get_current_user().await?.id; - let application_id = http.get_current_application_info().await?.id; - - let audio_index = if let Ok(static_audio) = std::fs::read_to_string("audio/audio.json") { - if let Ok(json) = serde_json::from_str::>(&static_audio) { - Some(json) - } else { - println!( - "Invalid `audio.json` file. Not loading static audio or providing ambience command" - ); - - None - } - } else { - println!("No `audio.json` file. Not loading static audio or providing ambience command"); - - None + let options = poise::FrameworkOptions { + commands: vec![ + cmds::info::info(), + cmds::manage::change_public(), + cmds::manage::upload_new_sound(), + cmds::manage::delete_sound(), + cmds::play::play(), + cmds::play::loop_play(), + cmds::play::soundboard(), + ], + allowed_mentions: None, + listener: |ctx, event, _framework, data| Box::pin(listener(ctx, event, data)), + ..Default::default() }; - let mut framework = RegexFramework::new(logged_in_id) - .default_prefix("?") - .case_insensitive(true) - .ignore_bots(true) - // info commands - .add_command(&cmds::info::HELP_COMMAND) - .add_command(&cmds::info::INFO_COMMAND) - // play commands - .add_command(&cmds::play::LOOP_PLAY_COMMAND) - .add_command(&cmds::play::PLAY_COMMAND) - .add_command(&cmds::play::SOUNDBOARD_COMMAND) - .add_command(&cmds::stop::STOP_PLAYING_COMMAND) - .add_command(&cmds::stop::DISCONNECT_COMMAND) - // sound management commands - .add_command(&cmds::manage::UPLOAD_NEW_SOUND_COMMAND) - .add_command(&cmds::manage::DELETE_SOUND_COMMAND) - .add_command(&cmds::manage::CHANGE_PUBLIC_COMMAND) - // setting commands - .add_command(&cmds::settings::CHANGE_PREFIX_COMMAND) - .add_command(&cmds::settings::SET_ALLOWED_ROLES_COMMAND) - .add_command(&cmds::settings::CHANGE_VOLUME_COMMAND) - .add_command(&cmds::settings::ALLOW_GREET_SOUNDS_COMMAND) - .add_command(&cmds::settings::SET_GREET_SOUND_COMMAND) - // search commands - .add_command(&cmds::search::LIST_SOUNDS_COMMAND) - .add_command(&cmds::search::SEARCH_SOUNDS_COMMAND) - .add_command(&cmds::search::SHOW_RANDOM_SOUNDS_COMMAND); + let database = MySqlPool::connect(&env::var("DATABASE_URL").expect("No database URL provided")) + .await + .unwrap(); - if audio_index.is_some() { - framework = framework.add_command(&cmds::play::PLAY_AMBIENCE_COMMAND); - } + poise::Framework::build() + .token(discord_token) + .user_data_setup(move |ctx, _bot, framework| { + Box::pin(async move { + ctx.set_activity(Activity::watching("for /play")).await; - framework = framework.build(); - - let framework_arc = Arc::new(framework); - - let mut client = - Client::builder(&env::var("DISCORD_TOKEN").expect("Missing token from environment")) - .intents( - GatewayIntents::GUILD_VOICE_STATES - | GatewayIntents::GUILD_MESSAGES - | GatewayIntents::GUILDS, - ) - .framework_arc(framework_arc.clone()) - .application_id(application_id.0) - .event_handler(Handler) - .register_songbird() - .await - .expect("Error occurred creating client"); - - { - let mysql_pool = - MySqlPool::connect(&env::var("DATABASE_URL").expect("No database URL provided")) + register_application_commands( + ctx, + framework, + env::var("DEBUG_GUILD") + .map(|inner| GuildId(inner.parse().expect("DEBUG_GUILD not valid"))) + .ok(), + ) .await .unwrap(); - let guild_data_cache = Arc::new(DashMap::new()); - let join_sound_cache = Arc::new(DashMap::new()); - let mut data = client.data.write().await; - - data.insert::(guild_data_cache); - data.insert::(join_sound_cache); - data.insert::(mysql_pool); - data.insert::(framework_arc.clone()); - data.insert::(Arc::new(reqwest::Client::new())); - - if let Some(audio_index) = audio_index { - data.insert::(Arc::new(audio_index)); - } - } - - framework_arc.build_slash(&client.cache_and_http.http).await; - - if let Ok((Some(lower), Some(upper))) = env::var("SHARD_RANGE").map(|sr| { - let mut split = sr - .split(',') - .map(|val| val.parse::().expect("SHARD_RANGE not an integer")); - - (split.next(), split.next()) - }) { - let total_shards = env::var("SHARD_COUNT") - .map(|shard_count| shard_count.parse::().ok()) - .ok() - .flatten() - .expect("No SHARD_COUNT provided, but SHARD_RANGE was provided"); - - assert!( - lower < upper, - "SHARD_RANGE lower limit is not less than the upper limit" - ); - - info!( - "Starting client fragment with shards {}-{}/{}", - lower, upper, total_shards - ); - - client - .start_shard_range([lower, upper], total_shards) - .await?; - } else if let Ok(total_shards) = env::var("SHARD_COUNT").map(|shard_count| { - shard_count - .parse::() - .expect("SHARD_COUNT not an integer") - }) { - info!("Starting client with {} shards", total_shards); - - client.start_shards(total_shards).await?; - } else { - info!("Starting client as autosharded"); - - client.start_autosharded().await?; - } + Ok(Data { + http: reqwest::Client::new(), + database, + guild_data_cache: Default::default(), + join_sound_cache: Default::default(), + }) + }) + }) + .options(options) + .client_settings(move |client_builder| { + client_builder + .intents( + GatewayIntents::GUILD_VOICE_STATES + | GatewayIntents::GUILD_MESSAGES + | GatewayIntents::GUILDS, + ) + .register_songbird() + }) + .run_autosharded() + .await?; Ok(()) } diff --git a/src/sound.rs b/src/sound.rs index d44c426..b2041db 100644 --- a/src/sound.rs +++ b/src/sound.rs @@ -1,12 +1,12 @@ use std::{env, path::Path}; -use serenity::{async_trait, model::id::UserId, prelude::Context}; +use poise::serenity::{async_trait, model::id::UserId}; use songbird::input::restartable::Restartable; use sqlx::mysql::MySqlPool; use tokio::{fs::File, io::AsyncWriteExt, process::Command}; use super::error::ErrorTypes; -use crate::{JoinSoundCache, MySQL}; +use crate::Data; #[async_trait] pub trait JoinSoundCtx { @@ -19,22 +19,15 @@ pub trait JoinSoundCtx { } #[async_trait] -impl JoinSoundCtx for Context { +impl JoinSoundCtx for Data { async fn join_sound + Send + Sync>(&self, user_id: U) -> Option { let user_id = user_id.into(); - let join_sound_cache = self - .data - .read() - .await - .get::() - .cloned() - .unwrap(); - let x = if let Some(join_sound_id) = join_sound_cache.get(&user_id) { + let x = if let Some(join_sound_id) = self.join_sound_cache.get(&user_id) { join_sound_id.value().clone() } else { let join_sound_id = { - let pool = self.data.read().await.get::().cloned().unwrap(); + let pool = self.database.clone(); let join_id_res = sqlx::query!( " @@ -54,7 +47,7 @@ SELECT join_sound_id } }; - join_sound_cache.insert(user_id, join_sound_id); + self.join_sound_cache.insert(user_id, join_sound_id); join_sound_id }; @@ -68,17 +61,10 @@ SELECT join_sound_id join_id: Option, ) { let user_id = user_id.into(); - let join_sound_cache = self - .data - .read() - .await - .get::() - .cloned() - .unwrap(); - join_sound_cache.insert(user_id, join_id); + self.join_sound_cache.insert(user_id, join_id); - let pool = self.data.read().await.get::().cloned().unwrap(); + let pool = self.database.clone(); let _ = sqlx::query!( " @@ -260,10 +246,12 @@ SELECT src .expect("FFMPEG ERROR!")) } - pub async fn count_user_sounds( - user_id: u64, + pub async fn count_user_sounds>( + user_id: U, db_pool: MySqlPool, ) -> Result { + let user_id = user_id.into(); + let c = sqlx::query!( " SELECT COUNT(1) as count @@ -279,11 +267,13 @@ SELECT COUNT(1) as count Ok(c as u32) } - pub async fn count_named_user_sounds( - user_id: u64, + pub async fn count_named_user_sounds>( + user_id: U, name: &String, db_pool: MySqlPool, ) -> Result { + let user_id = user_id.into(); + let c = sqlx::query!( " SELECT COUNT(1) as count @@ -341,13 +331,16 @@ DELETE Ok(()) } - pub async fn create_anon( + pub async fn create_anon, U: Into>( name: &str, src_url: &str, - server_id: u64, - user_id: u64, + server_id: G, + user_id: U, db_pool: MySqlPool, ) -> Result<(), Box> { + let server_id = server_id.into(); + let user_id = user_id.into(); + async fn process_src(src_url: &str) -> Option> { let output = Command::new("ffmpeg") .kill_on_drop(true) From b350007dae466a1fb42e88356f3cc10c51261439 Mon Sep 17 00:00:00 2001 From: jellywx Date: Wed, 26 Jan 2022 20:33:51 +0000 Subject: [PATCH 2/9] restructured a lot. everything updated to poise. --- src/cmds/info.rs | 2 +- src/cmds/manage.rs | 56 ++++- src/cmds/mod.rs | 24 ++- src/cmds/play.rs | 156 ++++++++++---- src/cmds/search.rs | 180 +++++++--------- src/cmds/settings.rs | 361 ++++++++------------------------- src/cmds/stop.rs | 49 ++--- src/consts.rs | 9 + src/event_handlers.rs | 55 +++-- src/main.rs | 168 +++------------ src/{ => models}/guild_data.rs | 0 src/models/join_sound.rs | 87 ++++++++ src/models/mod.rs | 3 + src/{ => models}/sound.rs | 241 ++++++++++------------ src/utils.rs | 141 +++++++++++++ 15 files changed, 775 insertions(+), 757 deletions(-) create mode 100644 src/consts.rs rename src/{ => models}/guild_data.rs (100%) create mode 100644 src/models/join_sound.rs create mode 100644 src/models/mod.rs rename src/{ => models}/sound.rs (77%) create mode 100644 src/utils.rs diff --git a/src/cmds/info.rs b/src/cmds/info.rs index 72bc8a5..2252c2e 100644 --- a/src/cmds/info.rs +++ b/src/cmds/info.rs @@ -1,4 +1,4 @@ -use crate::{Context, Error, THEME_COLOR}; +use crate::{consts::THEME_COLOR, Context, Error}; /// Get additional information about the bot #[poise::command(slash_command, category = "Information")] diff --git a/src/cmds/manage.rs b/src/cmds/manage.rs index 938619b..3eab28d 100644 --- a/src/cmds/manage.rs +++ b/src/cmds/manage.rs @@ -1,8 +1,14 @@ use std::time::Duration; use poise::serenity::model::id::{GuildId, RoleId}; +use tokio::fs::File; -use crate::{sound::Sound, Context, Error, MAX_SOUNDS, PATREON_GUILD, PATREON_ROLE}; +use crate::{ + cmds::autocomplete_sound, + consts::{MAX_SOUNDS, PATREON_GUILD, PATREON_ROLE}, + models::sound::{Sound, SoundCtx}, + Context, Error, +}; /// Upload a new sound to the bot #[poise::command(slash_command, rename = "upload", category = "Manage")] @@ -123,14 +129,16 @@ pub async fn upload_new_sound( #[poise::command(slash_command, rename = "delete", category = "Manage")] pub async fn delete_sound( ctx: Context<'_>, - #[description = "Name or ID of sound to delete"] name: String, + #[description = "Name or ID of sound to delete"] + #[autocomplete = "autocomplete_sound"] + name: String, ) -> Result<(), Error> { let pool = ctx.data().database.clone(); let uid = ctx.author().id.0; let gid = ctx.guild_id().unwrap().0; - let sound_vec = Sound::search_for_sound(&name, gid, uid, pool.clone(), true).await?; + let sound_vec = ctx.data().search_for_sound(&name, gid, uid, true).await?; let sound_result = sound_vec.first(); match sound_result { @@ -174,14 +182,16 @@ pub async fn delete_sound( #[poise::command(slash_command, rename = "public", category = "Manage")] pub async fn change_public( ctx: Context<'_>, - #[description = "Name or ID of sound to change privacy setting of"] name: String, + #[description = "Name or ID of sound to change privacy setting of"] + #[autocomplete = "autocomplete_sound"] + name: String, ) -> Result<(), Error> { let pool = ctx.data().database.clone(); let uid = ctx.author().id.0; let gid = ctx.guild_id().unwrap().0; - let mut sound_vec = Sound::search_for_sound(&name, gid, uid, pool.clone(), true).await?; + let mut sound_vec = ctx.data().search_for_sound(&name, gid, uid, true).await?; let sound_result = sound_vec.first_mut(); match sound_result { @@ -210,3 +220,39 @@ pub async fn change_public( Ok(()) } + +/// Download a sound file from the bot +#[poise::command(slash_command, rename = "download", category = "Manage")] +pub async fn download_file( + ctx: Context<'_>, + #[description = "Name or ID of sound to download"] + #[autocomplete = "autocomplete_sound"] + name: String, +) -> Result<(), Error> { + ctx.defer().await?; + + let sound = ctx + .data() + .search_for_sound(&name, ctx.guild_id().unwrap(), ctx.author().id, true) + .await?; + + match sound.first() { + Some(sound) => { + let source = sound + .store_sound_source(ctx.data().database.clone()) + .await?; + + let file = File::open(&source).await?; + let name = format!("{}-{}.opus", sound.id, sound.name); + + ctx.send(|m| m.attachment((&file, name.as_str()).into())) + .await?; + } + + None => { + ctx.say("No sound found by specified name/ID").await?; + } + } + + Ok(()) +} diff --git a/src/cmds/mod.rs b/src/cmds/mod.rs index ae5369c..a0cb39c 100644 --- a/src/cmds/mod.rs +++ b/src/cmds/mod.rs @@ -1,6 +1,24 @@ +use crate::{models::sound::SoundCtx, Context}; + pub mod info; pub mod manage; pub mod play; -// pub mod search; -// pub mod settings; -// pub mod stop; +pub mod search; +pub mod settings; +pub mod stop; + +pub async fn autocomplete_sound( + ctx: Context<'_>, + partial: String, +) -> Vec> { + ctx.data() + .autocomplete_user_sounds(&partial, ctx.author().id, ctx.guild_id().unwrap()) + .await + .unwrap_or(vec![]) + .iter() + .map(|s| poise::AutocompleteChoice { + name: s.name.clone(), + value: s.id.to_string(), + }) + .collect() +} diff --git a/src/cmds/play.rs b/src/cmds/play.rs index 0195784..2a7a00f 100644 --- a/src/cmds/play.rs +++ b/src/cmds/play.rs @@ -2,32 +2,58 @@ use poise::serenity::{ builder::CreateActionRow, model::interactions::message_component::ButtonStyle, }; -use crate::{play_from_query, sound::Sound, Context, Error}; +use crate::{ + cmds::autocomplete_sound, models::sound::SoundCtx, utils::play_from_query, Context, Error, +}; /// Play a sound in your current voice channel #[poise::command(slash_command)] pub async fn play( ctx: Context<'_>, - #[description = "Name or ID of sound to play"] name: String, + #[description = "Name or ID of sound to play"] + #[autocomplete = "autocomplete_sound"] + name: String, ) -> Result<(), Error> { let guild = ctx.guild().unwrap(); - ctx.say(play_from_query(&ctx, guild, ctx.author().id, &name, false).await) - .await?; + ctx.say( + play_from_query( + &ctx.discord(), + &ctx.data(), + guild, + ctx.author().id, + &name, + false, + ) + .await, + ) + .await?; Ok(()) } /// Loop a sound in your current voice channel -#[poise::command(slash_command)] +#[poise::command(slash_command, rename = "loop")] pub async fn loop_play( ctx: Context<'_>, - #[description = "Name or ID of sound to loop"] name: String, + #[description = "Name or ID of sound to loop"] + #[autocomplete = "autocomplete_sound"] + name: String, ) -> Result<(), Error> { let guild = ctx.guild().unwrap(); - ctx.say(play_from_query(&ctx, guild, ctx.author().id, &name, true).await) - .await?; + ctx.say( + play_from_query( + &ctx.discord(), + &ctx.data(), + guild, + ctx.author().id, + &name, + true, + ) + .await, + ) + .await?; Ok(()) } @@ -36,36 +62,84 @@ pub async fn loop_play( #[poise::command(slash_command, rename = "soundboard", category = "Play")] pub async fn soundboard( ctx: Context<'_>, - #[description = "Name or ID of sound for button 1"] sound_1: String, - #[description = "Name or ID of sound for button 2"] sound_2: Option, - #[description = "Name or ID of sound for button 3"] sound_3: Option, - #[description = "Name or ID of sound for button 4"] sound_4: Option, - #[description = "Name or ID of sound for button 5"] sound_5: Option, - #[description = "Name or ID of sound for button 6"] sound_6: Option, - #[description = "Name or ID of sound for button 7"] sound_7: Option, - #[description = "Name or ID of sound for button 8"] sound_8: Option, - #[description = "Name or ID of sound for button 9"] sound_9: Option, - #[description = "Name or ID of sound for button 10"] sound_10: Option, - #[description = "Name or ID of sound for button 11"] sound_11: Option, - #[description = "Name or ID of sound for button 12"] sound_12: Option, - #[description = "Name or ID of sound for button 13"] sound_13: Option, - #[description = "Name or ID of sound for button 14"] sound_14: Option, - #[description = "Name or ID of sound for button 15"] sound_15: Option, - #[description = "Name or ID of sound for button 16"] sound_16: Option, - #[description = "Name or ID of sound for button 17"] sound_17: Option, - #[description = "Name or ID of sound for button 18"] sound_18: Option, - #[description = "Name or ID of sound for button 19"] sound_19: Option, - #[description = "Name or ID of sound for button 20"] sound_20: Option, - #[description = "Name or ID of sound for button 21"] sound_21: Option, - #[description = "Name or ID of sound for button 22"] sound_22: Option, - #[description = "Name or ID of sound for button 23"] sound_23: Option, - #[description = "Name or ID of sound for button 24"] sound_24: Option, - #[description = "Name or ID of sound for button 25"] sound_25: Option, + #[description = "Name or ID of sound for button 1"] + #[autocomplete = "autocomplete_sound"] + sound_1: String, + #[description = "Name or ID of sound for button 2"] + #[autocomplete = "autocomplete_sound"] + sound_2: Option, + #[description = "Name or ID of sound for button 3"] + #[autocomplete = "autocomplete_sound"] + sound_3: Option, + #[description = "Name or ID of sound for button 4"] + #[autocomplete = "autocomplete_sound"] + sound_4: Option, + #[description = "Name or ID of sound for button 5"] + #[autocomplete = "autocomplete_sound"] + sound_5: Option, + #[description = "Name or ID of sound for button 6"] + #[autocomplete = "autocomplete_sound"] + sound_6: Option, + #[description = "Name or ID of sound for button 7"] + #[autocomplete = "autocomplete_sound"] + sound_7: Option, + #[description = "Name or ID of sound for button 8"] + #[autocomplete = "autocomplete_sound"] + sound_8: Option, + #[description = "Name or ID of sound for button 9"] + #[autocomplete = "autocomplete_sound"] + sound_9: Option, + #[description = "Name or ID of sound for button 10"] + #[autocomplete = "autocomplete_sound"] + sound_10: Option, + #[description = "Name or ID of sound for button 11"] + #[autocomplete = "autocomplete_sound"] + sound_11: Option, + #[description = "Name or ID of sound for button 12"] + #[autocomplete = "autocomplete_sound"] + sound_12: Option, + #[description = "Name or ID of sound for button 13"] + #[autocomplete = "autocomplete_sound"] + sound_13: Option, + #[description = "Name or ID of sound for button 14"] + #[autocomplete = "autocomplete_sound"] + sound_14: Option, + #[description = "Name or ID of sound for button 15"] + #[autocomplete = "autocomplete_sound"] + sound_15: Option, + #[description = "Name or ID of sound for button 16"] + #[autocomplete = "autocomplete_sound"] + sound_16: Option, + #[description = "Name or ID of sound for button 17"] + #[autocomplete = "autocomplete_sound"] + sound_17: Option, + #[description = "Name or ID of sound for button 18"] + #[autocomplete = "autocomplete_sound"] + sound_18: Option, + #[description = "Name or ID of sound for button 19"] + #[autocomplete = "autocomplete_sound"] + sound_19: Option, + #[description = "Name or ID of sound for button 20"] + #[autocomplete = "autocomplete_sound"] + sound_20: Option, + #[description = "Name or ID of sound for button 21"] + #[autocomplete = "autocomplete_sound"] + sound_21: Option, + #[description = "Name or ID of sound for button 22"] + #[autocomplete = "autocomplete_sound"] + sound_22: Option, + #[description = "Name or ID of sound for button 23"] + #[autocomplete = "autocomplete_sound"] + sound_23: Option, + #[description = "Name or ID of sound for button 24"] + #[autocomplete = "autocomplete_sound"] + sound_24: Option, + #[description = "Name or ID of sound for button 25"] + #[autocomplete = "autocomplete_sound"] + sound_25: Option, ) -> Result<(), Error> { ctx.defer().await?; - let pool = ctx.data().database.clone(); - let query_terms = [ Some(sound_1), sound_2, @@ -97,14 +171,10 @@ pub async fn soundboard( let mut sounds = vec![]; for sound in query_terms.iter().flatten() { - let search = Sound::search_for_sound( - &sound, - ctx.guild_id().unwrap(), - ctx.author().id, - pool.clone(), - true, - ) - .await?; + let search = ctx + .data() + .search_for_sound(&sound, ctx.guild_id().unwrap(), ctx.author().id, true) + .await?; if let Some(sound) = search.first() { if !sounds.contains(sound) { diff --git a/src/cmds/search.rs b/src/cmds/search.rs index 4e3a285..0cc3b06 100644 --- a/src/cmds/search.rs +++ b/src/cmds/search.rs @@ -1,6 +1,13 @@ -use crate::sound::Sound; +use poise::{serenity::constants::MESSAGE_CODE_LIMIT, CreateReply}; + +use crate::{ + models::sound::{Sound, SoundCtx}, + Context, Error, +}; + +fn format_search_results<'a>(search_results: Vec) -> CreateReply<'a> { + let mut builder = CreateReply::default(); -fn format_search_results(search_results: Vec) -> CreateGenericResponse { let mut current_character_count = 0; let title = "Public sounds matching filter:"; @@ -11,49 +18,25 @@ fn format_search_results(search_results: Vec) -> CreateGenericResponse { .filter(|item| { current_character_count += item.0.len() + item.1.len(); - current_character_count <= serenity::constants::MESSAGE_CODE_LIMIT - title.len() + current_character_count <= MESSAGE_CODE_LIMIT - title.len() }); - CreateGenericResponse::new().embed(|e| e.title(title).fields(field_iter)) + builder.embed(|e| e.title(title).fields(field_iter)); + + builder } -#[command("list")] -#[group("Search")] -#[description("Show the sounds uploaded by you or to your server")] -#[arg( - name = "me", - description = "Whether to list your sounds or server sounds (default: server)", - kind = "Boolean", - required = false -)] -#[example("`/list` - list sounds uploaded to the server you're in")] -#[example("`/list [me: True]` - list sounds you have uploaded across all servers")] -pub async fn list_sounds( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - args: Args, -) -> CommandResult { - let pool = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("Could not get SQLPool from data"); - +/// Show the sounds uploaded to this server +#[poise::command(slash_command, rename = "list")] +pub async fn list_sounds(ctx: Context<'_>) -> Result<(), Error> { let sounds; let mut message_buffer; - if args.named("me").map(|i| i.to_owned()) == Some("me".to_string()) { - sounds = Sound::user_sounds(invoke.author_id(), pool).await?; + sounds = ctx.data().guild_sounds(ctx.guild_id().unwrap()).await?; - message_buffer = "All your sounds: ".to_string(); - } else { - sounds = Sound::guild_sounds(invoke.guild_id().unwrap(), pool).await?; - - message_buffer = "All sounds on this server: ".to_string(); - } + message_buffer = "Sounds on this server: ".to_string(); + // todo change this to iterator for sound in sounds { message_buffer.push_str( format!( @@ -65,85 +48,77 @@ pub async fn list_sounds( ); if message_buffer.len() > 2000 { - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content(message_buffer), - ) - .await?; + ctx.say(message_buffer).await?; message_buffer = "".to_string(); } } if message_buffer.len() > 0 { - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content(message_buffer), - ) - .await?; + ctx.say(message_buffer).await?; } Ok(()) } -#[command("search")] -#[group("Search")] -#[description("Search for sounds")] -#[arg( - name = "query", - kind = "String", - description = "Sound name to search for", - required = true -)] -pub async fn search_sounds( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - args: Args, -) -> CommandResult { - let pool = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("Could not get SQLPool from data"); +/// Show all sounds you have uploaded +#[poise::command(slash_command, rename = "me")] +pub async fn list_user_sounds(ctx: Context<'_>) -> Result<(), Error> { + let sounds; + let mut message_buffer; - let query = args.named("query").unwrap(); + sounds = ctx.data().user_sounds(ctx.author().id).await?; - let search_results = Sound::search_for_sound( - query, - invoke.guild_id().unwrap(), - invoke.author_id(), - pool, - false, - ) - .await?; + message_buffer = "Sounds on this server: ".to_string(); - invoke - .respond(ctx.http.clone(), format_search_results(search_results)) - .await?; + // todo change this to iterator + for sound in sounds { + message_buffer.push_str( + format!( + "**{}** ({}), ", + sound.name, + if sound.public { "🔓" } else { "🔒" } + ) + .as_str(), + ); + + if message_buffer.len() > 2000 { + ctx.say(message_buffer).await?; + + message_buffer = "".to_string(); + } + } + + if message_buffer.len() > 0 { + ctx.say(message_buffer).await?; + } Ok(()) } -#[command("random")] -#[group("Search")] -#[description("Show a page of random sounds")] -pub async fn show_random_sounds( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - _args: Args, -) -> CommandResult { - let pool = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("Could not get SQLPool from data"); +/// Search for sounds +#[poise::command(slash_command, rename = "search", category = "Search")] +pub async fn search_sounds( + ctx: Context<'_>, + #[description = "Sound name to search for"] query: String, +) -> Result<(), Error> { + let search_results = ctx + .data() + .search_for_sound(&query, ctx.guild_id().unwrap(), ctx.author().id, false) + .await?; + ctx.send(|m| { + *m = format_search_results(search_results); + m + }) + .await?; + + Ok(()) +} + +/// Show a page of random sounds +#[poise::command(slash_command, rename = "random")] +pub async fn show_random_sounds(ctx: Context<'_>) -> Result<(), Error> { let search_results = sqlx::query_as_unchecked!( Sound, " @@ -154,13 +129,14 @@ SELECT name, id, public, server_id, uploader_id LIMIT 25 " ) - .fetch_all(&pool) - .await - .unwrap(); + .fetch_all(&ctx.data().database) + .await?; - invoke - .respond(ctx.http.clone(), format_search_results(search_results)) - .await?; + ctx.send(|m| { + *m = format_search_results(search_results); + m + }) + .await?; Ok(()) } diff --git a/src/cmds/settings.rs b/src/cmds/settings.rs index 9e15556..c8a8676 100644 --- a/src/cmds/settings.rs +++ b/src/cmds/settings.rs @@ -1,307 +1,126 @@ -use regex_command_attr::command; -use serenity::{client::Context, framework::standard::CommandResult}; - use crate::{ - framework::{Args, CommandInvoke, CreateGenericResponse}, - guild_data::CtxGuildData, - sound::{JoinSoundCtx, Sound}, - MySQL, + models::{guild_data::CtxGuildData, join_sound::JoinSoundCtx, sound::SoundCtx}, + Context, Error, }; -#[command("volume")] -#[aliases("vol")] -#[required_permissions(Managed)] -#[group("Settings")] -#[description("Change the bot's volume in this server")] -#[arg( - name = "volume", - description = "New volume for the bot to use", - kind = "Integer", - required = false -)] -#[example("`/volume` - check the volume on the current server")] -#[example("`/volume 100` - reset the volume on the current server")] -#[example("`/volume 10` - set the volume on the current server to 10%")] +/// Change the bot's volume in this server +#[poise::command(slash_command, rename = "volume")] pub async fn change_volume( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - args: Args, -) -> CommandResult { - let pool = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("Could not get SQLPool from data"); - - let guild_data_opt = ctx.guild_data(invoke.guild_id().unwrap()).await; + ctx: Context<'_>, + #[description = "New volume as a percentage"] volume: Option, +) -> Result<(), Error> { + let guild_data_opt = ctx.guild_data(ctx.guild_id().unwrap()).await; let guild_data = guild_data_opt.unwrap(); - if let Some(volume) = args.named("volume").map(|i| i.parse::().ok()).flatten() { - guild_data.write().await.volume = volume; + if let Some(volume) = volume { + guild_data.write().await.volume = volume as u8; - guild_data.read().await.commit(pool).await?; - - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content(format!("Volume changed to {}%", volume)), - ) + guild_data + .read() + .await + .commit(ctx.data().database.clone()) .await?; + + ctx.say(format!("Volume changed to {}%", volume)).await?; } else { let read = guild_data.read().await; - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content(format!( - "Current server volume: {vol}%. Change the volume with `/volume `", - vol = read.volume - )), - ) - .await?; - } - - Ok(()) -} - -#[command("prefix")] -#[required_permissions(Restricted)] -#[kind(Text)] -#[group("Settings")] -#[description("Change the prefix of the bot for using non-slash commands")] -#[arg( - name = "prefix", - kind = "String", - description = "The new prefix to use for the bot", - required = true -)] -pub async fn change_prefix( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - args: Args, -) -> CommandResult { - let pool = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("Could not get SQLPool from data"); - - let guild_data; - - { - let guild_data_opt = ctx.guild_data(invoke.guild_id().unwrap()).await; - - guild_data = guild_data_opt.unwrap(); - } - - if let Some(prefix) = args.named("prefix") { - if prefix.len() <= 5 && !prefix.is_empty() { - let reply = format!("Prefix changed to `{}`", prefix); - - { - guild_data.write().await.prefix = prefix.to_string(); - } - - { - let read = guild_data.read().await; - - read.commit(pool).await?; - } - - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content(reply), - ) - .await?; - } else { - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new() - .content("Prefix must be less than 5 characters long"), - ) - .await?; - } - } else { - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content(format!( - "Usage: `{prefix}prefix `", - prefix = guild_data.read().await.prefix - )), - ) - .await?; - } - - Ok(()) -} - -#[command("roles")] -#[required_permissions(Restricted)] -#[group("Settings")] -#[description("Change the role allowed to use the bot")] -#[arg( - name = "role", - kind = "Role", - description = "A role to allow to use the bot. Use @everyone to allow all server members", - required = true -)] -#[example("`/roles @everyone` - allow all server members to use the bot")] -#[example("`/roles @DJ` - allow only server members with the 'DJ' role to use the bot")] -pub async fn set_allowed_roles( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - args: Args, -) -> CommandResult { - let pool = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("Could not get SQLPool from data"); - - let role_id = args.named("role").unwrap().parse::().unwrap(); - let guild_data = ctx.guild_data(invoke.guild_id().unwrap()).await.unwrap(); - - guild_data.write().await.allowed_role = Some(role_id); - guild_data.read().await.commit(pool).await?; - - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content(format!("Allowed role set to <@&{}>", role_id)), - ) + ctx.say(format!( + "Current server volume: {vol}%. Change the volume with `/volume `", + vol = read.volume + )) .await?; + } Ok(()) } -#[command("greet")] -#[group("Settings")] -#[description("Set a join sound")] -#[arg( - name = "query", - kind = "String", - description = "Name or ID of sound to set as your greet sound", - required = false -)] -#[example("`/greet` - remove your join sound")] -#[example("`/greet 1523` - set your join sound to sound with ID 1523")] +/// Manage greet sounds on this server +#[poise::command(slash_command, rename = "greet")] +pub async fn greet_sound(_ctx: Context<'_>) -> Result<(), Error> { + Ok(()) +} + +/// Set a join sound +#[poise::command(slash_command, rename = "set")] pub async fn set_greet_sound( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - args: Args, -) -> CommandResult { - let pool = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("Could not get SQLPool from data"); - - let query = args - .named("query") - .map(|s| s.to_owned()) - .unwrap_or(String::new()); - let user_id = invoke.author_id(); - - if query.len() == 0 { - ctx.update_join_sound(user_id, None).await; - - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content("Your greet sound has been unset."), - ) - .await?; - } else { - let sound_vec = Sound::search_for_sound( - &query, - invoke.guild_id().unwrap(), - user_id, - pool.clone(), - true, - ) + ctx: Context<'_>, + #[description = "Name or ID of sound to set as your join sound"] name: String, +) -> Result<(), Error> { + let sound_vec = ctx + .data() + .search_for_sound(&name, ctx.guild_id().unwrap(), ctx.author().id, true) .await?; - match sound_vec.first() { - Some(sound) => { - ctx.update_join_sound(user_id, Some(sound.id)).await; + match sound_vec.first() { + Some(sound) => { + ctx.data() + .update_join_sound(ctx.author().id, Some(sound.id)) + .await; - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content(format!( - "Greet sound has been set to {} (ID {})", - sound.name, sound.id - )), - ) - .await?; - } + ctx.say(format!( + "Greet sound has been set to {} (ID {})", + sound.name, sound.id + )) + .await?; + } - None => { - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new() - .content("Could not find a sound by that name."), - ) - .await?; - } + None => { + ctx.say("Could not find a sound by that name.").await?; } } Ok(()) } -#[command("allow_greet")] -#[group("Settings")] -#[description("Configure whether users should be able to use join sounds")] -#[required_permissions(Restricted)] -#[example("`/allow_greet` - disable greet sounds in the server")] -#[example("`/allow_greet` - re-enable greet sounds in the server")] -pub async fn allow_greet_sounds( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - _args: Args, -) -> CommandResult { - let pool = ctx - .data - .read() - .await - .get::() - .cloned() - .expect("Could not acquire SQL pool from data"); +/// Set a join sound +#[poise::command(slash_command, rename = "unset")] +pub async fn unset_greet_sound(ctx: Context<'_>) -> Result<(), Error> { + ctx.data().update_join_sound(ctx.author().id, None).await; - let guild_data_opt = ctx.guild_data(invoke.guild_id().unwrap()).await; + ctx.say("Greet sound has been unset").await?; + + Ok(()) +} + +/// Disable greet sounds on this server +#[poise::command(slash_command, rename = "disable")] +pub async fn disable_greet_sound(ctx: Context<'_>) -> Result<(), Error> { + let guild_data_opt = ctx.guild_data(ctx.guild_id().unwrap()).await; if let Ok(guild_data) = guild_data_opt { - let current = guild_data.read().await.allow_greets; + guild_data.write().await.allow_greets = false; - { - guild_data.write().await.allow_greets = !current; - } - - guild_data.read().await.commit(pool).await?; - - invoke - .respond( - ctx.http.clone(), - CreateGenericResponse::new().content(format!( - "Greet sounds have been {}abled in this server", - if !current { "en" } else { "dis" } - )), - ) + guild_data + .read() + .await + .commit(ctx.data().database.clone()) .await?; } + ctx.say("Greet sounds have been disabled in this server") + .await?; + + Ok(()) +} + +/// Enable greet sounds on this server +#[poise::command(slash_command, rename = "enable")] +pub async fn enable_greet_sound(ctx: Context<'_>) -> Result<(), Error> { + let guild_data_opt = ctx.guild_data(ctx.guild_id().unwrap()).await; + + if let Ok(guild_data) = guild_data_opt { + guild_data.write().await.allow_greets = true; + + guild_data + .read() + .await + .commit(ctx.data().database.clone()) + .await?; + } + + ctx.say("Greet sounds have been enable in this server") + .await?; + Ok(()) } diff --git a/src/cmds/stop.rs b/src/cmds/stop.rs index dccc318..9a26a5b 100644 --- a/src/cmds/stop.rs +++ b/src/cmds/stop.rs @@ -1,22 +1,12 @@ -use regex_command_attr::command; -use serenity::{client::Context, framework::standard::CommandResult}; use songbird; -use crate::framework::{Args, CommandInvoke, CreateGenericResponse}; +use crate::{Context, Error}; -#[command("stop")] -#[required_permissions(Managed)] -#[group("Stop")] -#[description("Stop the bot from playing")] -pub async fn stop_playing( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - _args: Args, -) -> CommandResult { - let guild_id = invoke.guild_id().unwrap(); - - let songbird = songbird::get(ctx).await.unwrap(); - let call_opt = songbird.get(guild_id); +/// Stop the bot from playing +#[poise::command(slash_command, rename = "stop")] +pub async fn stop_playing(ctx: Context<'_>) -> Result<(), Error> { + let songbird = songbird::get(ctx.discord()).await.unwrap(); + let call_opt = songbird.get(ctx.guild_id().unwrap()); if let Some(call) = call_opt { let mut lock = call.lock().await; @@ -24,31 +14,18 @@ pub async fn stop_playing( lock.stop(); } - invoke - .respond(ctx.http.clone(), CreateGenericResponse::new().content("👍")) - .await?; + ctx.say("👍").await?; Ok(()) } -#[command] -#[aliases("dc")] -#[required_permissions(Managed)] -#[group("Stop")] -#[description("Disconnect the bot")] -pub async fn disconnect( - ctx: &Context, - invoke: &(dyn CommandInvoke + Sync + Send), - _args: Args, -) -> CommandResult { - let guild_id = invoke.guild_id().unwrap(); +/// Disconnect the bot +#[poise::command(slash_command)] +pub async fn disconnect(ctx: Context<'_>) -> Result<(), Error> { + let songbird = songbird::get(ctx.discord()).await.unwrap(); + let _ = songbird.leave(ctx.guild_id().unwrap()).await; - let songbird = songbird::get(ctx).await.unwrap(); - let _ = songbird.leave(guild_id).await; - - invoke - .respond(ctx.http.clone(), CreateGenericResponse::new().content("👍")) - .await?; + ctx.say("👍").await?; Ok(()) } diff --git a/src/consts.rs b/src/consts.rs new file mode 100644 index 0000000..5b7e8fe --- /dev/null +++ b/src/consts.rs @@ -0,0 +1,9 @@ +use std::env; + +pub const THEME_COLOR: u32 = 0x00e0f3; + +lazy_static! { + pub static ref MAX_SOUNDS: u32 = env::var("MAX_SOUNDS").unwrap().parse::().unwrap(); + pub static ref PATREON_GUILD: u64 = env::var("PATREON_GUILD").unwrap().parse::().unwrap(); + pub static ref PATREON_ROLE: u64 = env::var("PATREON_ROLE").unwrap().parse::().unwrap(); +} diff --git a/src/event_handlers.rs b/src/event_handlers.rs index 42b5c08..8ffa91d 100644 --- a/src/event_handlers.rs +++ b/src/event_handlers.rs @@ -1,27 +1,19 @@ use std::{collections::HashMap, env}; -use poise::serenity::{async_trait, model::channel::Channel, prelude::Context, utils::shard_id}; -use songbird::{Event, EventContext, EventHandler as SongbirdEventHandler}; - -use crate::{ - guild_data::CtxGuildData, - join_channel, play_audio, - sound::{JoinSoundCtx, Sound}, - Data, Error, +use poise::serenity::{ + model::{ + channel::Channel, + interactions::{Interaction, InteractionResponseType}, + }, + prelude::Context, + utils::shard_id, }; -pub struct RestartTrack; - -#[async_trait] -impl SongbirdEventHandler for RestartTrack { - async fn act(&self, ctx: &EventContext<'_>) -> Option { - if let EventContext::Track(&[(_state, track)]) = ctx { - let _ = track.seek_time(Default::default()); - } - - None - } -} +use crate::{ + models::{guild_data::CtxGuildData, join_sound::JoinSoundCtx, sound::Sound}, + utils::{join_channel, play_audio, play_from_query}, + Data, Error, +}; pub async fn listener(ctx: &Context, event: &poise::Event<'_>, data: &Data) -> Result<(), Error> { match event { @@ -126,6 +118,29 @@ SELECT name, id, public, server_id, uploader_id } } } + poise::Event::InteractionCreate { interaction } => match interaction { + Interaction::MessageComponent(component) => { + if component.guild_id.is_some() { + play_from_query( + &ctx, + &data, + component.guild_id.unwrap().to_guild_cached(&ctx).unwrap(), + component.user.id, + &component.data.custom_id, + false, + ) + .await; + + component + .create_interaction_response(ctx, |r| { + r.kind(InteractionResponseType::DeferredUpdateMessage) + }) + .await + .unwrap(); + } + } + _ => {} + }, _ => {} } diff --git a/src/main.rs b/src/main.rs index 079671a..89d629b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,10 +2,11 @@ extern crate lazy_static; mod cmds; +mod consts; mod error; mod event_handlers; -mod guild_data; -mod sound; +mod models; +mod utils; use std::{env, sync::Arc}; @@ -14,21 +15,15 @@ use dotenv::dotenv; use poise::serenity::{ builder::CreateApplicationCommands, model::{ - channel::Channel, gateway::{Activity, GatewayIntents}, - guild::Guild, - id::{ChannelId, GuildId, UserId}, + id::{GuildId, UserId}, }, }; -use songbird::{create_player, error::JoinResult, tracks::TrackHandle, Call, SerenityInit}; +use songbird::SerenityInit; use sqlx::mysql::MySqlPool; -use tokio::sync::{Mutex, MutexGuard, RwLock}; +use tokio::sync::RwLock; -use crate::{ - event_handlers::listener, - guild_data::{CtxGuildData, GuildData}, - sound::Sound, -}; +use crate::{event_handlers::listener, models::guild_data::GuildData}; pub struct Data { database: MySqlPool, @@ -40,137 +35,6 @@ pub struct Data { type Error = Box; type Context<'a> = poise::Context<'a, Data, Error>; -const THEME_COLOR: u32 = 0x00e0f3; - -lazy_static! { - static ref MAX_SOUNDS: u32 = env::var("MAX_SOUNDS").unwrap().parse::().unwrap(); - static ref PATREON_GUILD: u64 = env::var("PATREON_GUILD").unwrap().parse::().unwrap(); - static ref PATREON_ROLE: u64 = env::var("PATREON_ROLE").unwrap().parse::().unwrap(); -} - -async fn play_audio( - sound: &mut Sound, - volume: u8, - call_handler: &mut MutexGuard<'_, Call>, - mysql_pool: MySqlPool, - loop_: bool, -) -> Result> { - let (track, track_handler) = - create_player(sound.store_sound_source(mysql_pool.clone()).await?.into()); - - let _ = track_handler.set_volume(volume as f32 / 100.0); - - if loop_ { - let _ = track_handler.enable_loop(); - } else { - let _ = track_handler.disable_loop(); - } - - call_handler.play(track); - - Ok(track_handler) -} - -async fn join_channel( - ctx: &poise::serenity_prelude::Context, - guild: Guild, - channel_id: ChannelId, -) -> (Arc>, JoinResult<()>) { - let songbird = songbird::get(ctx).await.unwrap(); - let current_user = ctx.cache.current_user_id(); - - let current_voice_state = guild - .voice_states - .get(¤t_user) - .and_then(|voice_state| voice_state.channel_id); - - let (call, res) = if current_voice_state == Some(channel_id) { - let call_opt = songbird.get(guild.id); - - if let Some(call) = call_opt { - (call, Ok(())) - } else { - let (call, res) = songbird.join(guild.id, channel_id).await; - - (call, res) - } - } else { - let (call, res) = songbird.join(guild.id, channel_id).await; - - (call, res) - }; - - { - // set call to deafen - let _ = call.lock().await.deafen(true).await; - } - - if let Some(Channel::Guild(channel)) = channel_id.to_channel_cached(&ctx) { - channel - .edit_voice_state(&ctx, ctx.cache.current_user(), |v| v.suppress(false)) - .await; - } - - (call, res) -} - -async fn play_from_query( - ctx: &Context<'_>, - guild: Guild, - user_id: UserId, - query: &str, - loop_: bool, -) -> String { - let guild_id = guild.id; - - let channel_to_join = guild - .voice_states - .get(&user_id) - .and_then(|voice_state| voice_state.channel_id); - - match channel_to_join { - Some(user_channel) => { - let pool = ctx.data().database.clone(); - - let mut sound_vec = - Sound::search_for_sound(query, guild_id, user_id, pool.clone(), true) - .await - .unwrap(); - - let sound_res = sound_vec.first_mut(); - - match sound_res { - Some(sound) => { - { - let (call_handler, _) = - join_channel(ctx.discord(), guild.clone(), user_channel).await; - - let guild_data = ctx.guild_data(guild_id).await.unwrap(); - - let mut lock = call_handler.lock().await; - - play_audio( - sound, - guild_data.read().await.volume, - &mut lock, - pool, - loop_, - ) - .await - .unwrap(); - } - - format!("Playing sound {} with ID {}", sound.name, sound.id) - } - - None => "Couldn't find sound by term provided".to_string(), - } - } - - None => "You are not in a voice chat!".to_string(), - } -} - pub async fn register_application_commands( ctx: &poise::serenity::client::Context, framework: &poise::Framework, @@ -215,10 +79,28 @@ async fn main() -> Result<(), Box> { cmds::info::info(), cmds::manage::change_public(), cmds::manage::upload_new_sound(), + cmds::manage::download_file(), cmds::manage::delete_sound(), cmds::play::play(), cmds::play::loop_play(), cmds::play::soundboard(), + cmds::search::list_sounds(), + cmds::search::list_user_sounds(), + cmds::search::show_random_sounds(), + cmds::search::search_sounds(), + cmds::stop::stop_playing(), + cmds::stop::disconnect(), + cmds::settings::change_volume(), + poise::Command { + subcommands: vec![ + cmds::settings::disable_greet_sound(), + cmds::settings::enable_greet_sound(), + cmds::settings::set_greet_sound(), + cmds::settings::unset_greet_sound(), + cmds::settings::greet_sound(), + ], + ..cmds::settings::greet_sound() + }, ], allowed_mentions: None, listener: |ctx, event, _framework, data| Box::pin(listener(ctx, event, data)), diff --git a/src/guild_data.rs b/src/models/guild_data.rs similarity index 100% rename from src/guild_data.rs rename to src/models/guild_data.rs diff --git a/src/models/join_sound.rs b/src/models/join_sound.rs new file mode 100644 index 0000000..b6c8cd4 --- /dev/null +++ b/src/models/join_sound.rs @@ -0,0 +1,87 @@ +use poise::serenity::{async_trait, model::id::UserId}; + +use crate::Data; + +#[async_trait] +pub trait JoinSoundCtx { + async fn join_sound + Send + Sync>(&self, user_id: U) -> Option; + async fn update_join_sound + Send + Sync>( + &self, + user_id: U, + join_id: Option, + ); +} + +#[async_trait] +impl JoinSoundCtx for Data { + async fn join_sound + Send + Sync>(&self, user_id: U) -> Option { + let user_id = user_id.into(); + + let x = if let Some(join_sound_id) = self.join_sound_cache.get(&user_id) { + join_sound_id.value().clone() + } else { + let join_sound_id = { + let pool = self.database.clone(); + + let join_id_res = sqlx::query!( + " +SELECT join_sound_id + FROM users + WHERE user = ? + ", + user_id.as_u64() + ) + .fetch_one(&pool) + .await; + + if let Ok(row) = join_id_res { + row.join_sound_id + } else { + None + } + }; + + self.join_sound_cache.insert(user_id, join_sound_id); + + join_sound_id + }; + + x + } + + async fn update_join_sound + Send + Sync>( + &self, + user_id: U, + join_id: Option, + ) { + let user_id = user_id.into(); + + self.join_sound_cache.insert(user_id, join_id); + + let pool = self.database.clone(); + + let _ = sqlx::query!( + " +INSERT IGNORE INTO users (user) + VALUES (?) + ", + user_id.as_u64() + ) + .execute(&pool) + .await; + + let _ = sqlx::query!( + " +UPDATE users +SET + join_sound_id = ? +WHERE + user = ? + ", + join_id, + user_id.as_u64() + ) + .execute(&pool) + .await; + } +} diff --git a/src/models/mod.rs b/src/models/mod.rs new file mode 100644 index 0000000..262eedf --- /dev/null +++ b/src/models/mod.rs @@ -0,0 +1,3 @@ +pub mod guild_data; +pub mod join_sound; +pub mod sound; diff --git a/src/sound.rs b/src/models/sound.rs similarity index 77% rename from src/sound.rs rename to src/models/sound.rs index b2041db..86784b6 100644 --- a/src/sound.rs +++ b/src/models/sound.rs @@ -1,96 +1,11 @@ use std::{env, path::Path}; -use poise::serenity::{async_trait, model::id::UserId}; +use poise::serenity::async_trait; use songbird::input::restartable::Restartable; -use sqlx::mysql::MySqlPool; +use sqlx::{mysql::MySqlPool, Error}; use tokio::{fs::File, io::AsyncWriteExt, process::Command}; -use super::error::ErrorTypes; -use crate::Data; - -#[async_trait] -pub trait JoinSoundCtx { - async fn join_sound + Send + Sync>(&self, user_id: U) -> Option; - async fn update_join_sound + Send + Sync>( - &self, - user_id: U, - join_id: Option, - ); -} - -#[async_trait] -impl JoinSoundCtx for Data { - async fn join_sound + Send + Sync>(&self, user_id: U) -> Option { - let user_id = user_id.into(); - - let x = if let Some(join_sound_id) = self.join_sound_cache.get(&user_id) { - join_sound_id.value().clone() - } else { - let join_sound_id = { - let pool = self.database.clone(); - - let join_id_res = sqlx::query!( - " -SELECT join_sound_id - FROM users - WHERE user = ? - ", - user_id.as_u64() - ) - .fetch_one(&pool) - .await; - - if let Ok(row) = join_id_res { - row.join_sound_id - } else { - None - } - }; - - self.join_sound_cache.insert(user_id, join_sound_id); - - join_sound_id - }; - - x - } - - async fn update_join_sound + Send + Sync>( - &self, - user_id: U, - join_id: Option, - ) { - let user_id = user_id.into(); - - self.join_sound_cache.insert(user_id, join_id); - - let pool = self.database.clone(); - - let _ = sqlx::query!( - " -INSERT IGNORE INTO users (user) - VALUES (?) - ", - user_id.as_u64() - ) - .execute(&pool) - .await; - - let _ = sqlx::query!( - " -UPDATE users -SET - join_sound_id = ? -WHERE - user = ? - ", - join_id, - user_id.as_u64() - ) - .execute(&pool) - .await; - } -} +use crate::{error::ErrorTypes, Data}; #[derive(Clone)] pub struct Sound { @@ -107,16 +22,41 @@ impl PartialEq for Sound { } } -impl Sound { - pub async fn search_for_sound, U: Into>( +#[async_trait] +pub trait SoundCtx { + async fn search_for_sound + Send, U: Into + Send>( + &self, + query: &str, + guild_id: G, + user_id: U, + strict: bool, + ) -> Result, sqlx::Error>; + async fn autocomplete_user_sounds + Send, G: Into + Send>( + &self, + query: &str, + user_id: U, + guild_id: G, + ) -> Result, sqlx::Error>; + async fn user_sounds + Send>(&self, user_id: U) + -> Result, sqlx::Error>; + async fn guild_sounds + Send>( + &self, + guild_id: G, + ) -> Result, sqlx::Error>; +} + +#[async_trait] +impl SoundCtx for Data { + async fn search_for_sound + Send, U: Into + Send>( + &self, query: &str, guild_id: G, user_id: U, - db_pool: MySqlPool, strict: bool, ) -> Result, sqlx::Error> { let guild_id = guild_id.into(); let user_id = user_id.into(); + let db_pool = self.database.clone(); fn extract_id(s: &str) -> Option { if s.len() > 3 && s.to_lowercase().starts_with("id:") { @@ -134,7 +74,7 @@ impl Sound { if let Some(id) = extract_id(&query) { let sound = sqlx::query_as_unchecked!( - Self, + Sound, " SELECT name, id, public, server_id, uploader_id FROM sounds @@ -158,7 +98,7 @@ SELECT name, id, public, server_id, uploader_id if strict { sound = sqlx::query_as_unchecked!( - Self, + Sound, " SELECT name, id, public, server_id, uploader_id FROM sounds @@ -179,7 +119,7 @@ SELECT name, id, public, server_id, uploader_id .await?; } else { sound = sqlx::query_as_unchecked!( - Self, + Sound, " SELECT name, id, public, server_id, uploader_id FROM sounds @@ -204,6 +144,70 @@ SELECT name, id, public, server_id, uploader_id } } + async fn autocomplete_user_sounds + Send, G: Into + Send>( + &self, + query: &str, + user_id: U, + guild_id: G, + ) -> Result, Error> { + let db_pool = self.database.clone(); + + sqlx::query_as_unchecked!( + Sound, + " +SELECT name, id, public, server_id, uploader_id +FROM sounds +WHERE name LIKE CONCAT(?, '%') AND (uploader_id = ? OR server_id = ?) +LIMIT 25 + ", + query, + user_id.into(), + guild_id.into(), + ) + .fetch_all(&db_pool) + .await + } + + async fn user_sounds + Send>( + &self, + user_id: U, + ) -> Result, sqlx::Error> { + let sounds = sqlx::query_as_unchecked!( + Sound, + " +SELECT name, id, public, server_id, uploader_id + FROM sounds + WHERE uploader_id = ? + ", + user_id.into() + ) + .fetch_all(&self.database) + .await?; + + Ok(sounds) + } + + async fn guild_sounds + Send>( + &self, + guild_id: G, + ) -> Result, sqlx::Error> { + let sounds = sqlx::query_as_unchecked!( + Sound, + " +SELECT name, id, public, server_id, uploader_id + FROM sounds + WHERE server_id = ? + ", + guild_id.into() + ) + .fetch_all(&self.database) + .await?; + + Ok(sounds) + } +} + +impl Sound { async fn src(&self, db_pool: MySqlPool) -> Vec { struct Src { src: Vec, @@ -229,7 +233,7 @@ SELECT src pub async fn store_sound_source( &self, db_pool: MySqlPool, - ) -> Result> { + ) -> Result> { let caching_location = env::var("CACHING_LOCATION").unwrap_or(String::from("/tmp")); let path_name = format!("{}/sound-{}", caching_location, self.id); @@ -241,6 +245,15 @@ SELECT src file.write_all(&self.src(db_pool).await).await?; } + Ok(path_name) + } + + pub async fn playable( + &self, + db_pool: MySqlPool, + ) -> Result> { + let path_name = self.store_sound_source(db_pool).await?; + Ok(Restartable::ffmpeg(path_name, false) .await .expect("FFMPEG ERROR!")) @@ -397,42 +410,4 @@ INSERT INTO sounds (name, server_id, uploader_id, public, src) None => Err(Box::new(ErrorTypes::InvalidFile)), } } - - pub async fn user_sounds>( - user_id: U, - db_pool: MySqlPool, - ) -> Result, Box> { - let sounds = sqlx::query_as_unchecked!( - Sound, - " -SELECT name, id, public, server_id, uploader_id - FROM sounds - WHERE uploader_id = ? - ", - user_id.into() - ) - .fetch_all(&db_pool) - .await?; - - Ok(sounds) - } - - pub async fn guild_sounds>( - guild_id: G, - db_pool: MySqlPool, - ) -> Result, Box> { - let sounds = sqlx::query_as_unchecked!( - Sound, - " -SELECT name, id, public, server_id, uploader_id - FROM sounds - WHERE server_id = ? - ", - guild_id.into() - ) - .fetch_all(&db_pool) - .await?; - - Ok(sounds) - } } diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..ed5ac71 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,141 @@ +use std::sync::Arc; + +use poise::serenity::model::{ + channel::Channel, + guild::Guild, + id::{ChannelId, UserId}, +}; +use songbird::{create_player, error::JoinResult, tracks::TrackHandle, Call}; +use sqlx::MySqlPool; +use tokio::sync::{Mutex, MutexGuard}; + +use crate::{ + models::{ + guild_data::CtxGuildData, + sound::{Sound, SoundCtx}, + }, + Data, +}; + +pub async fn play_audio( + sound: &mut Sound, + volume: u8, + call_handler: &mut MutexGuard<'_, Call>, + mysql_pool: MySqlPool, + loop_: bool, +) -> Result> { + let (track, track_handler) = create_player(sound.playable(mysql_pool.clone()).await?.into()); + + let _ = track_handler.set_volume(volume as f32 / 100.0); + + if loop_ { + let _ = track_handler.enable_loop(); + } else { + let _ = track_handler.disable_loop(); + } + + call_handler.play(track); + + Ok(track_handler) +} + +pub async fn join_channel( + ctx: &poise::serenity_prelude::Context, + guild: Guild, + channel_id: ChannelId, +) -> (Arc>, JoinResult<()>) { + let songbird = songbird::get(ctx).await.unwrap(); + let current_user = ctx.cache.current_user_id(); + + let current_voice_state = guild + .voice_states + .get(¤t_user) + .and_then(|voice_state| voice_state.channel_id); + + let (call, res) = if current_voice_state == Some(channel_id) { + let call_opt = songbird.get(guild.id); + + if let Some(call) = call_opt { + (call, Ok(())) + } else { + let (call, res) = songbird.join(guild.id, channel_id).await; + + (call, res) + } + } else { + let (call, res) = songbird.join(guild.id, channel_id).await; + + (call, res) + }; + + { + // set call to deafen + let _ = call.lock().await.deafen(true).await; + } + + if let Some(Channel::Guild(channel)) = channel_id.to_channel_cached(&ctx) { + let _ = channel + .edit_voice_state(&ctx, ctx.cache.current_user(), |v| v.suppress(false)) + .await; + } + + (call, res) +} + +pub async fn play_from_query( + ctx: &poise::serenity_prelude::Context, + data: &Data, + guild: Guild, + user_id: UserId, + query: &str, + loop_: bool, +) -> String { + let guild_id = guild.id; + + let channel_to_join = guild + .voice_states + .get(&user_id) + .and_then(|voice_state| voice_state.channel_id); + + match channel_to_join { + Some(user_channel) => { + let pool = data.database.clone(); + + let mut sound_vec = data + .search_for_sound(query, guild_id, user_id, true) + .await + .unwrap(); + + let sound_res = sound_vec.first_mut(); + + match sound_res { + Some(sound) => { + { + let (call_handler, _) = + join_channel(ctx, guild.clone(), user_channel).await; + + let guild_data = data.guild_data(guild_id).await.unwrap(); + + let mut lock = call_handler.lock().await; + + play_audio( + sound, + guild_data.read().await.volume, + &mut lock, + pool, + loop_, + ) + .await + .unwrap(); + } + + format!("Playing sound {} with ID {}", sound.name, sound.id) + } + + None => "Couldn't find sound by term provided".to_string(), + } + } + + None => "You are not in a voice chat!".to_string(), + } +} From d59c50e7a9517ec113f0cc474cb83cd0e1c27322 Mon Sep 17 00:00:00 2001 From: jellywx Date: Thu, 27 Jan 2022 17:15:17 +0000 Subject: [PATCH 3/9] help command. moved list commands to subcommands --- src/cmds/info.rs | 61 ++++++++++++++++++++++++++++++++++++++++------ src/cmds/search.rs | 12 ++++++--- src/main.rs | 11 ++++++--- 3 files changed, 71 insertions(+), 13 deletions(-) diff --git a/src/cmds/info.rs b/src/cmds/info.rs index 2252c2e..2d97a17 100644 --- a/src/cmds/info.rs +++ b/src/cmds/info.rs @@ -1,7 +1,59 @@ use crate::{consts::THEME_COLOR, Context, Error}; +/// View bot commands +#[poise::command(slash_command)] +pub async fn help(ctx: Context<'_>) -> Result<(), Error> { + ctx.send(|m| { + m.embed(|e| { + e.title("Help") + .color(THEME_COLOR) + .footer(|f| { + f.text(concat!( + env!("CARGO_PKG_NAME"), + " ver ", + env!("CARGO_PKG_VERSION") + )) + }) + .description( + "__Info Commands__ +`/help` `/info` +*run these commands with no options* + +__Play Commands__ +`/play` - Play a sound by name or ID +`/loop` - Play a sound on loop +`/disconnect` - Disconnect the bot +`/stop` - Stop playback + +__Library Commands__ +`/upload` - Upload a sound file +`/delete` - Delete a sound file +`/download` - Download a sound file +`/public` - Set a sound as public/private +`/list server` - List sounds on this server +`/list user` - List your sounds + +__Search Commands__ +`/search` - Search for public sounds by name +`/random` - View random public sounds + +__Setting Commands__ +`/greet set/unset` - Set or unset a join sound +`/greet enable/disable` - Enable or disable join sounds on this server +`/volume` - Change the volume + +__Advanced Commands__ +`/soundboard` - Create a soundboard", + ) + }) + }) + .await?; + + Ok(()) +} + /// Get additional information about the bot -#[poise::command(slash_command, category = "Information")] +#[poise::command(slash_command)] pub async fn info(ctx: Context<'_>) -> Result<(), Error> { let current_user = ctx.discord().cache.current_user(); @@ -11,11 +63,7 @@ pub async fn info(ctx: Context<'_>) -> Result<(), Error> { .color(THEME_COLOR) .footer(|f| f .text(concat!(env!("CARGO_PKG_NAME"), " ver ", env!("CARGO_PKG_VERSION")))) - .description(format!("Default prefix: `?` - -Reset prefix: `@{0} prefix ?` - -Invite me: https://discord.com/api/oauth2/authorize?client_id={1}&permissions=3165184&scope=applications.commands%20bot + .description(format!("Invite me: https://discord.com/api/oauth2/authorize?client_id={}&permissions=3165184&scope=applications.commands%20bot **Welcome to SoundFX!** Developer: <@203532103185465344> @@ -23,7 +71,6 @@ Find me on https://discord.jellywx.com/ and on https://github.com/JellyWX :) **An online dashboard is available!** Visit https://soundfx.jellywx.com/dashboard There is a maximum sound limit per user. This can be removed by subscribing at **https://patreon.com/jellywx**", - current_user.name, current_user.id.as_u64())))).await?; Ok(()) diff --git a/src/cmds/search.rs b/src/cmds/search.rs index 0cc3b06..8920be3 100644 --- a/src/cmds/search.rs +++ b/src/cmds/search.rs @@ -26,9 +26,15 @@ fn format_search_results<'a>(search_results: Vec) -> CreateReply<'a> { builder } -/// Show the sounds uploaded to this server +/// Show uploaded sounds #[poise::command(slash_command, rename = "list")] -pub async fn list_sounds(ctx: Context<'_>) -> Result<(), Error> { +pub async fn list_sounds(_ctx: Context<'_>) -> Result<(), Error> { + Ok(()) +} + +/// Show the sounds uploaded to this server +#[poise::command(slash_command, rename = "server")] +pub async fn list_guild_sounds(ctx: Context<'_>) -> Result<(), Error> { let sounds; let mut message_buffer; @@ -62,7 +68,7 @@ pub async fn list_sounds(ctx: Context<'_>) -> Result<(), Error> { } /// Show all sounds you have uploaded -#[poise::command(slash_command, rename = "me")] +#[poise::command(slash_command, rename = "user")] pub async fn list_user_sounds(ctx: Context<'_>) -> Result<(), Error> { let sounds; let mut message_buffer; diff --git a/src/main.rs b/src/main.rs index 89d629b..09e9826 100644 --- a/src/main.rs +++ b/src/main.rs @@ -76,6 +76,7 @@ async fn main() -> Result<(), Box> { let options = poise::FrameworkOptions { commands: vec![ + cmds::info::help(), cmds::info::info(), cmds::manage::change_public(), cmds::manage::upload_new_sound(), @@ -84,8 +85,13 @@ async fn main() -> Result<(), Box> { cmds::play::play(), cmds::play::loop_play(), cmds::play::soundboard(), - cmds::search::list_sounds(), - cmds::search::list_user_sounds(), + poise::Command { + subcommands: vec![ + cmds::search::list_guild_sounds(), + cmds::search::list_user_sounds(), + ], + ..cmds::search::list_sounds() + }, cmds::search::show_random_sounds(), cmds::search::search_sounds(), cmds::stop::stop_playing(), @@ -97,7 +103,6 @@ async fn main() -> Result<(), Box> { cmds::settings::enable_greet_sound(), cmds::settings::set_greet_sound(), cmds::settings::unset_greet_sound(), - cmds::settings::greet_sound(), ], ..cmds::settings::greet_sound() }, From c364343fe9c7451a0adad388bd41105ccfea219e Mon Sep 17 00:00:00 2001 From: jellywx Date: Thu, 27 Jan 2022 17:31:07 +0000 Subject: [PATCH 4/9] configure upload attachment size. remove bitrate compression. --- src/cmds/manage.rs | 4 ++-- src/consts.rs | 4 ++++ src/models/sound.rs | 6 ++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/cmds/manage.rs b/src/cmds/manage.rs index 3eab28d..a50cbe4 100644 --- a/src/cmds/manage.rs +++ b/src/cmds/manage.rs @@ -5,7 +5,7 @@ use tokio::fs::File; use crate::{ cmds::autocomplete_sound, - consts::{MAX_SOUNDS, PATREON_GUILD, PATREON_ROLE}, + consts::{MAX_SOUNDS, PATREON_GUILD, PATREON_ROLE, UPLOAD_MAX_SIZE}, models::sound::{Sound, SoundCtx}, Context, Error, }; @@ -59,7 +59,7 @@ pub async fn upload_new_sound( if permit_upload { let attachment = { - ctx.say("Please now upload an audio file under 1MB in size (larger files will be automatically trimmed):").await?; + ctx.say(format!("Please now upload an audio file under {}MB in size (larger files will be automatically trimmed):", *UPLOAD_MAX_SIZE / (1024u64.pow(2)))).await?; let reply = ctx .channel_id() diff --git a/src/consts.rs b/src/consts.rs index 5b7e8fe..c98f149 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -3,6 +3,10 @@ use std::env; pub const THEME_COLOR: u32 = 0x00e0f3; lazy_static! { + pub static ref UPLOAD_MAX_SIZE: u64 = env::var("UPLOAD_MAX_SIZE") + .unwrap_or_else(|_| "2097152".to_string()) + .parse::() + .unwrap(); pub static ref MAX_SOUNDS: u32 = env::var("MAX_SOUNDS").unwrap().parse::().unwrap(); pub static ref PATREON_GUILD: u64 = env::var("PATREON_GUILD").unwrap().parse::().unwrap(); pub static ref PATREON_ROLE: u64 = env::var("PATREON_ROLE").unwrap().parse::().unwrap(); diff --git a/src/models/sound.rs b/src/models/sound.rs index 86784b6..45e2bce 100644 --- a/src/models/sound.rs +++ b/src/models/sound.rs @@ -5,7 +5,7 @@ use songbird::input::restartable::Restartable; use sqlx::{mysql::MySqlPool, Error}; use tokio::{fs::File, io::AsyncWriteExt, process::Command}; -use crate::{error::ErrorTypes, Data}; +use crate::{consts::UPLOAD_MAX_SIZE, error::ErrorTypes, Data}; #[derive(Clone)] pub struct Sound { @@ -361,12 +361,10 @@ DELETE .arg(src_url) .arg("-loglevel") .arg("error") - .arg("-b:a") - .arg("28000") .arg("-f") .arg("opus") .arg("-fs") - .arg("1048576") + .arg(UPLOAD_MAX_SIZE.to_string()) .arg("pipe:1") .output() .await; From eb5ea3167d54300a521c086732c234bcb82d0e87 Mon Sep 17 00:00:00 2001 From: jellywx Date: Sun, 30 Jan 2022 15:55:53 +0000 Subject: [PATCH 5/9] generics for Database pool --- src/cmds/manage.rs | 17 +++++++---------- src/cmds/settings.rs | 18 +++--------------- src/event_handlers.rs | 6 ++---- src/main.rs | 9 ++++++--- src/models/guild_data.rs | 20 +++++++++----------- src/models/join_sound.rs | 4 +--- src/models/sound.rs | 32 ++++++++++++++++---------------- src/utils.rs | 12 +++++------- 8 files changed, 49 insertions(+), 69 deletions(-) diff --git a/src/cmds/manage.rs b/src/cmds/manage.rs index a50cbe4..e20ce52 100644 --- a/src/cmds/manage.rs +++ b/src/cmds/manage.rs @@ -29,11 +29,10 @@ pub async fn upload_new_sound( if !name.is_empty() && name.len() <= 20 { if !is_numeric(&name) { - let pool = ctx.data().database.clone(); - // need to check the name is not currently in use by the user let count_name = - Sound::count_named_user_sounds(ctx.author().id, &name, pool.clone()).await?; + Sound::count_named_user_sounds(ctx.author().id, &name, &ctx.data().database) + .await?; if count_name > 0 { ctx.say( "You are already using that name. Please choose a unique name for your upload.", @@ -41,7 +40,7 @@ pub async fn upload_new_sound( .await?; } else { // need to check how many sounds user currently has - let count = Sound::count_user_sounds(ctx.author().id, pool.clone()).await?; + let count = Sound::count_user_sounds(ctx.author().id, &ctx.data().database).await?; let mut permit_upload = true; // need to check if user is patreon or nah @@ -93,7 +92,7 @@ pub async fn upload_new_sound( url.as_str(), ctx.guild_id().unwrap(), ctx.author().id, - pool, + &ctx.data().database, ) .await { @@ -160,7 +159,7 @@ pub async fn delete_sound( }; if sound.uploader_id == Some(uid) || has_perms { - sound.delete(pool).await?; + sound.delete(&pool).await?; ctx.say("Sound has been deleted").await?; } else { @@ -209,7 +208,7 @@ pub async fn change_public( ctx.say("Sound has been set to public 🔓").await?; } - sound.commit(pool).await? + sound.commit(&pool).await? } } @@ -238,9 +237,7 @@ pub async fn download_file( match sound.first() { Some(sound) => { - let source = sound - .store_sound_source(ctx.data().database.clone()) - .await?; + let source = sound.store_sound_source(&ctx.data().database).await?; let file = File::open(&source).await?; let name = format!("{}-{}.opus", sound.id, sound.name); diff --git a/src/cmds/settings.rs b/src/cmds/settings.rs index c8a8676..04da24b 100644 --- a/src/cmds/settings.rs +++ b/src/cmds/settings.rs @@ -15,11 +15,7 @@ pub async fn change_volume( if let Some(volume) = volume { guild_data.write().await.volume = volume as u8; - guild_data - .read() - .await - .commit(ctx.data().database.clone()) - .await?; + guild_data.read().await.commit(&ctx.data().database).await?; ctx.say(format!("Volume changed to {}%", volume)).await?; } else { @@ -91,11 +87,7 @@ pub async fn disable_greet_sound(ctx: Context<'_>) -> Result<(), Error> { if let Ok(guild_data) = guild_data_opt { guild_data.write().await.allow_greets = false; - guild_data - .read() - .await - .commit(ctx.data().database.clone()) - .await?; + guild_data.read().await.commit(&ctx.data().database).await?; } ctx.say("Greet sounds have been disabled in this server") @@ -112,11 +104,7 @@ pub async fn enable_greet_sound(ctx: Context<'_>) -> Result<(), Error> { if let Ok(guild_data) = guild_data_opt { guild_data.write().await.allow_greets = true; - guild_data - .read() - .await - .commit(ctx.data().database.clone()) - .await?; + guild_data.read().await.commit(&ctx.data().database).await?; } ctx.say("Greet sounds have been enable in this server") diff --git a/src/event_handlers.rs b/src/event_handlers.rs index 8ffa91d..d19bed3 100644 --- a/src/event_handlers.rs +++ b/src/event_handlers.rs @@ -72,8 +72,6 @@ pub async fn listener(ctx: &Context, event: &poise::Event<'_>, data: &Data) -> R } } else if let (Some(guild_id), Some(user_channel)) = (new.guild_id, new.channel_id) { if let Some(guild) = ctx.cache.guild(guild_id) { - let pool = data.database.clone(); - let guild_data_opt = data.guild_data(guild.id).await; if let Ok(guild_data) = guild_data_opt { @@ -98,7 +96,7 @@ SELECT name, id, public, server_id, uploader_id ", join_id ) - .fetch_one(&pool) + .fetch_one(&data.database) .await .unwrap(); @@ -108,7 +106,7 @@ SELECT name, id, public, server_id, uploader_id &mut sound, volume, &mut handler.lock().await, - pool, + &data.database, false, ) .await; diff --git a/src/main.rs b/src/main.rs index 09e9826..b6d1c41 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,13 +20,16 @@ use poise::serenity::{ }, }; use songbird::SerenityInit; -use sqlx::mysql::MySqlPool; +use sqlx::{MySql, Pool}; use tokio::sync::RwLock; use crate::{event_handlers::listener, models::guild_data::GuildData}; +// Which database driver are we using? +type Database = MySql; + pub struct Data { - database: MySqlPool, + database: Pool, http: reqwest::Client, guild_data_cache: DashMap>>, join_sound_cache: DashMap>, @@ -112,7 +115,7 @@ async fn main() -> Result<(), Box> { ..Default::default() }; - let database = MySqlPool::connect(&env::var("DATABASE_URL").expect("No database URL provided")) + let database = Pool::connect(&env::var("DATABASE_URL").expect("No database URL provided")) .await .unwrap(); diff --git a/src/models/guild_data.rs b/src/models/guild_data.rs index 2ab5efd..883bd7a 100644 --- a/src/models/guild_data.rs +++ b/src/models/guild_data.rs @@ -1,10 +1,10 @@ use std::sync::Arc; use poise::serenity::{async_trait, model::id::GuildId}; -use sqlx::mysql::MySqlPool; +use sqlx::Executor; use tokio::sync::RwLock; -use crate::{Context, Data}; +use crate::{Context, Data, Database}; #[derive(Clone)] pub struct GuildData { @@ -44,9 +44,7 @@ impl CtxGuildData for Data { let x = if let Some(guild_data) = self.guild_data_cache.get(&guild_id) { Ok(guild_data.clone()) } else { - let pool = self.database.clone(); - - match GuildData::from_id(guild_id, pool).await { + match GuildData::from_id(guild_id, &self.database).await { Ok(d) => { let lock = Arc::new(RwLock::new(d)); @@ -66,7 +64,7 @@ impl CtxGuildData for Data { impl GuildData { pub async fn from_id>( guild_id: G, - db_pool: MySqlPool, + db_pool: impl Executor<'_, Database = Database> + Copy, ) -> Result { let guild_id = guild_id.into(); @@ -79,7 +77,7 @@ SELECT id, prefix, volume, allow_greets, allowed_role ", guild_id.as_u64() ) - .fetch_one(&db_pool) + .fetch_one(db_pool) .await; match guild_data { @@ -93,7 +91,7 @@ SELECT id, prefix, volume, allow_greets, allowed_role async fn create_from_guild>( guild_id: G, - db_pool: MySqlPool, + db_pool: impl Executor<'_, Database = Database>, ) -> Result { let guild_id = guild_id.into(); @@ -104,7 +102,7 @@ INSERT INTO servers (id) ", guild_id.as_u64() ) - .execute(&db_pool) + .execute(db_pool) .await?; Ok(GuildData { @@ -118,7 +116,7 @@ INSERT INTO servers (id) pub async fn commit( &self, - db_pool: MySqlPool, + db_pool: impl Executor<'_, Database = Database>, ) -> Result<(), Box> { sqlx::query!( " @@ -137,7 +135,7 @@ WHERE self.allowed_role, self.id ) - .execute(&db_pool) + .execute(db_pool) .await?; Ok(()) diff --git a/src/models/join_sound.rs b/src/models/join_sound.rs index b6c8cd4..8be1278 100644 --- a/src/models/join_sound.rs +++ b/src/models/join_sound.rs @@ -21,8 +21,6 @@ impl JoinSoundCtx for Data { join_sound_id.value().clone() } else { let join_sound_id = { - let pool = self.database.clone(); - let join_id_res = sqlx::query!( " SELECT join_sound_id @@ -31,7 +29,7 @@ SELECT join_sound_id ", user_id.as_u64() ) - .fetch_one(&pool) + .fetch_one(&self.database) .await; if let Ok(row) = join_id_res { diff --git a/src/models/sound.rs b/src/models/sound.rs index 45e2bce..7f57c56 100644 --- a/src/models/sound.rs +++ b/src/models/sound.rs @@ -2,10 +2,10 @@ use std::{env, path::Path}; use poise::serenity::async_trait; use songbird::input::restartable::Restartable; -use sqlx::{mysql::MySqlPool, Error}; +use sqlx::{Error, Executor}; use tokio::{fs::File, io::AsyncWriteExt, process::Command}; -use crate::{consts::UPLOAD_MAX_SIZE, error::ErrorTypes, Data}; +use crate::{consts::UPLOAD_MAX_SIZE, error::ErrorTypes, Data, Database}; #[derive(Clone)] pub struct Sound { @@ -208,7 +208,7 @@ SELECT name, id, public, server_id, uploader_id } impl Sound { - async fn src(&self, db_pool: MySqlPool) -> Vec { + async fn src(&self, db_pool: impl Executor<'_, Database = Database>) -> Vec { struct Src { src: Vec, } @@ -223,7 +223,7 @@ SELECT src ", self.id ) - .fetch_one(&db_pool) + .fetch_one(db_pool) .await .unwrap(); @@ -232,7 +232,7 @@ SELECT src pub async fn store_sound_source( &self, - db_pool: MySqlPool, + db_pool: impl Executor<'_, Database = Database>, ) -> Result> { let caching_location = env::var("CACHING_LOCATION").unwrap_or(String::from("/tmp")); @@ -250,7 +250,7 @@ SELECT src pub async fn playable( &self, - db_pool: MySqlPool, + db_pool: impl Executor<'_, Database = Database>, ) -> Result> { let path_name = self.store_sound_source(db_pool).await?; @@ -261,7 +261,7 @@ SELECT src pub async fn count_user_sounds>( user_id: U, - db_pool: MySqlPool, + db_pool: impl Executor<'_, Database = Database>, ) -> Result { let user_id = user_id.into(); @@ -273,7 +273,7 @@ SELECT COUNT(1) as count ", user_id ) - .fetch_one(&db_pool) + .fetch_one(db_pool) .await? .count; @@ -283,7 +283,7 @@ SELECT COUNT(1) as count pub async fn count_named_user_sounds>( user_id: U, name: &String, - db_pool: MySqlPool, + db_pool: impl Executor<'_, Database = Database>, ) -> Result { let user_id = user_id.into(); @@ -298,7 +298,7 @@ SELECT COUNT(1) as count user_id, name ) - .fetch_one(&db_pool) + .fetch_one(db_pool) .await? .count; @@ -307,7 +307,7 @@ SELECT COUNT(1) as count pub async fn commit( &self, - db_pool: MySqlPool, + db_pool: impl Executor<'_, Database = Database>, ) -> Result<(), Box> { sqlx::query!( " @@ -320,7 +320,7 @@ WHERE self.public, self.id ) - .execute(&db_pool) + .execute(db_pool) .await?; Ok(()) @@ -328,7 +328,7 @@ WHERE pub async fn delete( &self, - db_pool: MySqlPool, + db_pool: impl Executor<'_, Database = Database>, ) -> Result<(), Box> { sqlx::query!( " @@ -338,7 +338,7 @@ DELETE ", self.id ) - .execute(&db_pool) + .execute(db_pool) .await?; Ok(()) @@ -349,7 +349,7 @@ DELETE src_url: &str, server_id: G, user_id: U, - db_pool: MySqlPool, + db_pool: impl Executor<'_, Database = Database>, ) -> Result<(), Box> { let server_id = server_id.into(); let user_id = user_id.into(); @@ -396,7 +396,7 @@ INSERT INTO sounds (name, server_id, uploader_id, public, src) user_id, data ) - .execute(&db_pool) + .execute(db_pool) .await { Ok(_) => Ok(()), diff --git a/src/utils.rs b/src/utils.rs index ed5ac71..2fbcaf9 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -6,7 +6,7 @@ use poise::serenity::model::{ id::{ChannelId, UserId}, }; use songbird::{create_player, error::JoinResult, tracks::TrackHandle, Call}; -use sqlx::MySqlPool; +use sqlx::Executor; use tokio::sync::{Mutex, MutexGuard}; use crate::{ @@ -14,17 +14,17 @@ use crate::{ guild_data::CtxGuildData, sound::{Sound, SoundCtx}, }, - Data, + Data, Database, }; pub async fn play_audio( sound: &mut Sound, volume: u8, call_handler: &mut MutexGuard<'_, Call>, - mysql_pool: MySqlPool, + db_pool: impl Executor<'_, Database = Database>, loop_: bool, ) -> Result> { - let (track, track_handler) = create_player(sound.playable(mysql_pool.clone()).await?.into()); + let (track, track_handler) = create_player(sound.playable(db_pool).await?.into()); let _ = track_handler.set_volume(volume as f32 / 100.0); @@ -99,8 +99,6 @@ pub async fn play_from_query( match channel_to_join { Some(user_channel) => { - let pool = data.database.clone(); - let mut sound_vec = data .search_for_sound(query, guild_id, user_id, true) .await @@ -122,7 +120,7 @@ pub async fn play_from_query( sound, guild_data.read().await.volume, &mut lock, - pool, + &data.database, loop_, ) .await From 821f283969a3087a5ffdc8f84ac6aa0c4c2e4c91 Mon Sep 17 00:00:00 2001 From: jellywx Date: Mon, 31 Jan 2022 12:36:46 +0000 Subject: [PATCH 6/9] updated readme --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ac66497..7353cb7 100644 --- a/README.md +++ b/README.md @@ -6,19 +6,21 @@ efficient and robust package. SoundFX 2 is as asynchronous as it can get, and ru ### Building -Use the Cargo.toml file to build it. Simple as. Don't need anything like MySQL libs and stuff because SQLx includes its -own pure Rust one. Needs Rust 1.43+ +Run the migrations in the `migrations` directory to set up the database. + +Use Cargo to build the executable. ### Running & Config -The bot connects to the MySQL server URL defined in a `.env` file in the working directory of the program. +The bot connects to the MySQL server URL defined in the environment. -Config options: +Environment variables read: * `DISCORD_TOKEN`- your token (required) * `DATABASE_URL`- your database URL (required) -* `DISCONNECT_CYCLES`- specifies the number of inactivity cycles before the bot should disconnect itself from a voice channel -* `DISCONNECT_CYCLE_DELAY`- specifies the delay between cleanup cycles +* `UPLOAD_MAX_SIZE`- specifies the maximum file size to allow in bytes (defaults to 2097152 (2MB)) * `MAX_SOUNDS`- specifies how many sounds a user should be allowed without Patreon * `PATREON_GUILD`- specifies the ID of the guild being used for Patreon benefits * `PATREON_ROLE`- specifies the role being checked for Patreon benefits * `CACHING_LOCATION`- specifies the location in which to cache the audio files (defaults to `/tmp/`) + +The bot will also consider variables in a `.env` file in the working directory. From febeeefb018869d3dc87e736c32c5775fbf94fb1 Mon Sep 17 00:00:00 2001 From: jude Date: Sun, 13 Feb 2022 16:12:42 +0000 Subject: [PATCH 7/9] queue play command --- Cargo.toml | 2 +- src/cmds/play.rs | 163 ++++++++++++++++++++++++++++++++++++++++++ src/cmds/stop.rs | 2 +- src/event_handlers.rs | 5 +- src/main.rs | 1 + src/utils.rs | 19 ++++- 6 files changed, 187 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 015bd0c..a9fae0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ authors = ["jellywx "] edition = "2018" [dependencies] -songbird = { git = "https://github.com/serenity-rs/songbird", branch = "next" } +songbird = { git = "https://github.com/serenity-rs/songbird", branch = "next", features = ["builtin-queue"] } poise = { git = "https://github.com/kangalioo/poise", branch = "master", features = ["collector"] } sqlx = { version = "0.5", default-features = false, features = ["runtime-tokio-rustls", "macros", "mysql", "bigdecimal"] } dotenv = "0.15" diff --git a/src/cmds/play.rs b/src/cmds/play.rs index 2a7a00f..c3dcb37 100644 --- a/src/cmds/play.rs +++ b/src/cmds/play.rs @@ -2,6 +2,8 @@ use poise::serenity::{ builder::CreateActionRow, model::interactions::message_component::ButtonStyle, }; +use crate::models::guild_data::CtxGuildData; +use crate::utils::{join_channel, queue_audio}; use crate::{ cmds::autocomplete_sound, models::sound::SoundCtx, utils::play_from_query, Context, Error, }; @@ -32,6 +34,167 @@ pub async fn play( Ok(()) } +/// Play up to 25 sounds on queue +#[poise::command(slash_command, rename = "queue")] +pub async fn queue_play( + ctx: Context<'_>, + #[description = "Name or ID for queue position 1"] + #[autocomplete = "autocomplete_sound"] + sound_1: String, + #[description = "Name or ID for queue position 2"] + #[autocomplete = "autocomplete_sound"] + sound_2: String, + #[description = "Name or ID for queue position 3"] + #[autocomplete = "autocomplete_sound"] + sound_3: Option, + #[description = "Name or ID for queue position 4"] + #[autocomplete = "autocomplete_sound"] + sound_4: Option, + #[description = "Name or ID for queue position 5"] + #[autocomplete = "autocomplete_sound"] + sound_5: Option, + #[description = "Name or ID for queue position 6"] + #[autocomplete = "autocomplete_sound"] + sound_6: Option, + #[description = "Name or ID for queue position 7"] + #[autocomplete = "autocomplete_sound"] + sound_7: Option, + #[description = "Name or ID for queue position 8"] + #[autocomplete = "autocomplete_sound"] + sound_8: Option, + #[description = "Name or ID for queue position 9"] + #[autocomplete = "autocomplete_sound"] + sound_9: Option, + #[description = "Name or ID for queue position 10"] + #[autocomplete = "autocomplete_sound"] + sound_10: Option, + #[description = "Name or ID for queue position 11"] + #[autocomplete = "autocomplete_sound"] + sound_11: Option, + #[description = "Name or ID for queue position 12"] + #[autocomplete = "autocomplete_sound"] + sound_12: Option, + #[description = "Name or ID for queue position 13"] + #[autocomplete = "autocomplete_sound"] + sound_13: Option, + #[description = "Name or ID for queue position 14"] + #[autocomplete = "autocomplete_sound"] + sound_14: Option, + #[description = "Name or ID for queue position 15"] + #[autocomplete = "autocomplete_sound"] + sound_15: Option, + #[description = "Name or ID for queue position 16"] + #[autocomplete = "autocomplete_sound"] + sound_16: Option, + #[description = "Name or ID for queue position 17"] + #[autocomplete = "autocomplete_sound"] + sound_17: Option, + #[description = "Name or ID for queue position 18"] + #[autocomplete = "autocomplete_sound"] + sound_18: Option, + #[description = "Name or ID for queue position 19"] + #[autocomplete = "autocomplete_sound"] + sound_19: Option, + #[description = "Name or ID for queue position 20"] + #[autocomplete = "autocomplete_sound"] + sound_20: Option, + #[description = "Name or ID for queue position 21"] + #[autocomplete = "autocomplete_sound"] + sound_21: Option, + #[description = "Name or ID for queue position 22"] + #[autocomplete = "autocomplete_sound"] + sound_22: Option, + #[description = "Name or ID for queue position 23"] + #[autocomplete = "autocomplete_sound"] + sound_23: Option, + #[description = "Name or ID for queue position 24"] + #[autocomplete = "autocomplete_sound"] + sound_24: Option, + #[description = "Name or ID for queue position 25"] + #[autocomplete = "autocomplete_sound"] + sound_25: Option, +) -> Result<(), Error> { + let _ = ctx.defer().await; + + let guild = ctx.guild().unwrap(); + + let channel_to_join = guild + .voice_states + .get(&ctx.author().id) + .and_then(|voice_state| voice_state.channel_id); + + match channel_to_join { + Some(user_channel) => { + let (call_handler, _) = join_channel(ctx.discord(), guild.clone(), user_channel).await; + + let guild_data = ctx + .data() + .guild_data(ctx.guild_id().unwrap()) + .await + .unwrap(); + + let mut lock = call_handler.lock().await; + + let query_terms = [ + Some(sound_1), + Some(sound_2), + sound_3, + sound_4, + sound_5, + sound_6, + sound_7, + sound_8, + sound_9, + sound_10, + sound_11, + sound_12, + sound_13, + sound_14, + sound_15, + sound_16, + sound_17, + sound_18, + sound_19, + sound_20, + sound_21, + sound_22, + sound_23, + sound_24, + sound_25, + ]; + + let mut sounds = vec![]; + + for sound in query_terms.iter().flatten() { + let search = ctx + .data() + .search_for_sound(&sound, ctx.guild_id().unwrap(), ctx.author().id, true) + .await?; + + if let Some(sound) = search.first() { + sounds.push(sound.clone()); + } + } + + queue_audio( + &sounds, + guild_data.read().await.volume, + &mut lock, + &ctx.data().database, + ) + .await + .unwrap(); + + ctx.say(format!("Queued {} sounds!", sounds.len())).await?; + } + None => { + ctx.say("You are not in a voice chat!").await?; + } + } + + Ok(()) +} + /// Loop a sound in your current voice channel #[poise::command(slash_command, rename = "loop")] pub async fn loop_play( diff --git a/src/cmds/stop.rs b/src/cmds/stop.rs index 9a26a5b..8c1f266 100644 --- a/src/cmds/stop.rs +++ b/src/cmds/stop.rs @@ -2,7 +2,7 @@ use songbird; use crate::{Context, Error}; -/// Stop the bot from playing +/// Stop the bot from playing and clear the play queue #[poise::command(slash_command, rename = "stop")] pub async fn stop_playing(ctx: Context<'_>) -> Result<(), Error> { let songbird = songbird::get(ctx.discord()).await.unwrap(); diff --git a/src/event_handlers.rs b/src/event_handlers.rs index d19bed3..6242b5f 100644 --- a/src/event_handlers.rs +++ b/src/event_handlers.rs @@ -102,14 +102,15 @@ SELECT name, id, public, server_id, uploader_id let (handler, _) = join_channel(&ctx, guild, user_channel).await; - let _ = play_audio( + play_audio( &mut sound, volume, &mut handler.lock().await, &data.database, false, ) - .await; + .await + .unwrap(); } } } diff --git a/src/main.rs b/src/main.rs index b6d1c41..eef1100 100644 --- a/src/main.rs +++ b/src/main.rs @@ -86,6 +86,7 @@ async fn main() -> Result<(), Box> { cmds::manage::download_file(), cmds::manage::delete_sound(), cmds::play::play(), + cmds::play::queue_play(), cmds::play::loop_play(), cmds::play::soundboard(), poise::Command { diff --git a/src/utils.rs b/src/utils.rs index 2fbcaf9..9593619 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -18,7 +18,7 @@ use crate::{ }; pub async fn play_audio( - sound: &mut Sound, + sound: &Sound, volume: u8, call_handler: &mut MutexGuard<'_, Call>, db_pool: impl Executor<'_, Database = Database>, @@ -39,6 +39,23 @@ pub async fn play_audio( Ok(track_handler) } +pub async fn queue_audio( + sounds: &[Sound], + volume: u8, + call_handler: &mut MutexGuard<'_, Call>, + db_pool: impl Executor<'_, Database = Database> + Copy, +) -> Result<(), Box> { + for sound in sounds { + let (a, b) = create_player(sound.playable(db_pool).await?.into()); + + let _ = b.set_volume(volume as f32 / 100.0); + + call_handler.enqueue(a); + } + + Ok(()) +} + pub async fn join_channel( ctx: &poise::serenity_prelude::Context, guild: Guild, From 0df54660527acdb9d4568daf6f29e830123c01f4 Mon Sep 17 00:00:00 2001 From: jude Date: Sat, 19 Feb 2022 12:40:07 +0000 Subject: [PATCH 8/9] no more message gathering --- .idea/dataSources.local.xml | 2 +- Cargo.lock | 229 +++++++++++++++++------------------- Cargo.toml | 2 +- src/cmds/manage.rs | 66 +++-------- src/main.rs | 6 +- 5 files changed, 126 insertions(+), 179 deletions(-) diff --git a/.idea/dataSources.local.xml b/.idea/dataSources.local.xml index 55767b9..d0c5fe0 100644 --- a/.idea/dataSources.local.xml +++ b/.idea/dataSources.local.xml @@ -1,6 +1,6 @@ - + master_key diff --git a/Cargo.lock b/Cargo.lock index d8c1cd0..9649262 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,15 +140,18 @@ dependencies = [ [[package]] name = "autocfg" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.1.0", +] [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" @@ -248,9 +251,9 @@ checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" [[package]] name = "core-foundation" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ "core-foundation-sys", "libc", @@ -273,9 +276,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2209c310e29876f7f0b2721e7e26b84aff178aa3da5d091f9bfbf47669e60e3" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if", ] @@ -292,9 +295,9 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b979d76c9fcb84dffc80a73f7290da0f83e4c95773494674cb44b76d13a7a110" +checksum = "4dd435b205a4842da59efd07628f921c096bc1cc0a156835b4fa0bcb9a19bcce" dependencies = [ "cfg-if", "crossbeam-utils", @@ -302,9 +305,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120" +checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" dependencies = [ "cfg-if", "lazy_static", @@ -364,17 +367,6 @@ checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" dependencies = [ "cfg-if", "num_cpus", -] - -[[package]] -name = "dashmap" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b799062aaf67eb976af3bdca031ee6f846d2f0a5710ddbb0d2efee33f3cc4760" -dependencies = [ - "cfg-if", - "num_cpus", - "parking_lot", "serde", ] @@ -484,9 +476,9 @@ dependencies = [ [[package]] name = "flume" -version = "0.10.10" +version = "0.10.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d04dafd11240188e146b6f6476a898004cace3be31d4ec5e08e216bf4947ac0" +checksum = "0b279436a715a9de95dcd26b151db590a71961cc06e54918b24fe0dd5b7d3fc4" dependencies = [ "futures-core", "futures-sink", @@ -528,9 +520,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" dependencies = [ "futures-channel", "futures-core", @@ -543,9 +535,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", "futures-sink", @@ -553,15 +545,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" [[package]] name = "futures-executor" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" dependencies = [ "futures-core", "futures-task", @@ -581,15 +573,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" [[package]] name = "futures-macro" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ "proc-macro2", "quote", @@ -598,21 +590,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" [[package]] name = "futures-task" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" [[package]] name = "futures-util" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ "futures-channel", "futures-core", @@ -664,9 +656,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9de88456263e249e241fcd211d3954e2c9b0ef7ccfc235a444eb367cae3689" +checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e" dependencies = [ "bytes", "fnv", @@ -731,7 +723,7 @@ checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" dependencies = [ "bytes", "fnv", - "itoa 1.0.1", + "itoa", ] [[package]] @@ -747,9 +739,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" [[package]] name = "httpdate" @@ -765,9 +757,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.16" +version = "0.14.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" +checksum = "043f0e083e9901b6cc658a77d1eb86f4fc650bbb977a4337dd63192826aa85dd" dependencies = [ "bytes", "futures-channel", @@ -778,7 +770,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 0.4.8", + "itoa", "pin-project-lite", "socket2", "tokio", @@ -795,7 +787,7 @@ checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" dependencies = [ "http", "hyper", - "rustls 0.20.2", + "rustls 0.20.3", "tokio", "tokio-rustls 0.23.2", ] @@ -836,7 +828,7 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "hashbrown", ] @@ -873,12 +865,6 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - [[package]] name = "itoa" version = "1.0.1" @@ -905,21 +891,21 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.114" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0005d08a8f7b65fb8073cb697aa0b12b631ed251ce73d862ce50eeb52ce3b50" +checksum = "06e509672465a0504304aa87f9f176f2b2b716ed8fb105ebe5c02dc6dce96a94" [[package]] name = "libm" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" +checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" dependencies = [ "scopeguard", ] @@ -998,7 +984,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" dependencies = [ "adler", - "autocfg 1.0.1", + "autocfg 1.1.0", ] [[package]] @@ -1069,9 +1055,9 @@ dependencies = [ [[package]] name = "ntapi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" dependencies = [ "winapi", ] @@ -1082,7 +1068,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-integer", "num-traits 0.2.14", ] @@ -1093,7 +1079,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4547ee5541c18742396ae2c895d0717d0f886d8823b8399cdaf7b07d63ad0480" dependencies = [ - "autocfg 0.1.7", + "autocfg 0.1.8", "byteorder", "lazy_static", "libm", @@ -1111,7 +1097,7 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-traits 0.2.14", ] @@ -1121,7 +1107,7 @@ version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-integer", "num-traits 0.2.14", ] @@ -1141,7 +1127,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "libm", ] @@ -1193,7 +1179,7 @@ version = "0.9.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "cc", "libc", "pkg-config", @@ -1332,7 +1318,7 @@ dependencies = [ [[package]] name = "poise" version = "0.1.0" -source = "git+https://github.com/kangalioo/poise?branch=master#9ebc7b541b2deca8efde1c8bcbdf3d415d8e3a9a" +source = "git+https://github.com/kangalioo/poise?branch=master#38bcca284cbc9fb52cd770d7af64fbd4b3495cc8" dependencies = [ "async-trait", "futures-core", @@ -1347,7 +1333,7 @@ dependencies = [ [[package]] name = "poise_macros" version = "0.1.0" -source = "git+https://github.com/kangalioo/poise?branch=master#9ebc7b541b2deca8efde1c8bcbdf3d415d8e3a9a" +source = "git+https://github.com/kangalioo/poise?branch=master#38bcca284cbc9fb52cd770d7af64fbd4b3495cc8" dependencies = [ "darling", "proc-macro2", @@ -1392,14 +1378,13 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -1421,15 +1406,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - [[package]] name = "redox_syscall" version = "0.2.10" @@ -1500,7 +1476,7 @@ dependencies = [ "native-tls", "percent-encoding", "pin-project-lite", - "rustls 0.20.2", + "rustls 0.20.3", "rustls-pemfile", "serde", "serde_json", @@ -1567,9 +1543,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" +checksum = "b323592e3164322f5b193dc4302e4e36cd8d37158a712d664efae1a5c2791700" dependencies = [ "log", "ring", @@ -1652,9 +1628,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d09d3c15d814eda1d6a836f2f2b56a6abc1446c8a34351cb3180d3db92ffe4ce" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" dependencies = [ "bitflags", "core-foundation", @@ -1665,9 +1641,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e90dd10c41c6bfc633da6e0c659bd25d31e0791e5974ac42970267d59eba87f7" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" dependencies = [ "core-foundation-sys", "libc", @@ -1695,11 +1671,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" dependencies = [ - "itoa 1.0.1", + "itoa", "ryu", "serde", ] @@ -1722,7 +1698,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.1", + "itoa", "ryu", "serde", ] @@ -1730,7 +1706,7 @@ dependencies = [ [[package]] name = "serenity" version = "0.10.10" -source = "git+https://github.com/serenity-rs/serenity?branch=next#ad78ab6543c8671f005246c89ce2651bf4809375" +source = "git+https://github.com/serenity-rs/serenity?branch=next#9e3b92cd3f95fbb50f96ac3af36dc7fe947fc833" dependencies = [ "async-trait", "async-tungstenite 0.16.1", @@ -1738,7 +1714,7 @@ dependencies = [ "bitflags", "bytes", "chrono", - "dashmap 5.0.0", + "dashmap", "flate2", "futures", "mime", @@ -1757,7 +1733,7 @@ dependencies = [ [[package]] name = "serenity-voice-model" version = "0.1.1" -source = "git+https://github.com/serenity-rs/serenity?branch=next#ad78ab6543c8671f005246c89ce2651bf4809375" +source = "git+https://github.com/serenity-rs/serenity?branch=next#9e3b92cd3f95fbb50f96ac3af36dc7fe947fc833" dependencies = [ "bitflags", "enum_primitive", @@ -1824,9 +1800,9 @@ checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "socket2" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f82496b90c36d70af5fcd482edaa2e0bd16fade569de1330405fecbbdac736b" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ "libc", "winapi", @@ -1834,14 +1810,14 @@ dependencies = [ [[package]] name = "songbird" -version = "0.2.1" -source = "git+https://github.com/serenity-rs/songbird?branch=next#d3f0974412d217e7047c9681ba85d0217d79e741" +version = "0.2.2" +source = "git+https://github.com/serenity-rs/songbird?branch=next#e0ab49c2ff92cb4c5f3ffc90be7a267fd12c905b" dependencies = [ "async-trait", "async-tungstenite 0.14.0", "audiopus", "byteorder", - "dashmap 4.0.2", + "dashmap", "derivative", "discortp", "flume", @@ -1869,7 +1845,7 @@ dependencies = [ name = "soundfx-rs" version = "1.5.0" dependencies = [ - "dashmap 4.0.2", + "dashmap", "dotenv", "env_logger", "lazy_static", @@ -1963,7 +1939,7 @@ dependencies = [ "hashlink", "hex", "indexmap", - "itoa 1.0.1", + "itoa", "libc", "log", "memchr", @@ -2154,9 +2130,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.15.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" +checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a" dependencies = [ "bytes", "libc", @@ -2208,7 +2184,7 @@ version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" dependencies = [ - "rustls 0.20.2", + "rustls 0.20.3", "tokio", "webpki 0.22.0", ] @@ -2246,9 +2222,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +checksum = "2d8d93354fe2a8e50d5953f5ae2e47a3fc2ef03292e7ea46e3cc38f549525fb9" dependencies = [ "cfg-if", "log", @@ -2259,9 +2235,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" +checksum = "8276d9a4a3a558d7b7ad5303ad50b53d58264641b82914b7ada36bd762e7a716" dependencies = [ "proc-macro2", "quote", @@ -2270,11 +2246,12 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" dependencies = [ "lazy_static", + "valuable", ] [[package]] @@ -2300,9 +2277,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5312f325fe3588e277415f5a6cca1f4ccad0f248c4cd5a4bd33032d7286abc22" +checksum = "74786ce43333fcf51efe947aed9718fbe46d5c7328ec3f1029e818083966d9aa" dependencies = [ "ansi_term", "lazy_static", @@ -2358,7 +2335,7 @@ dependencies = [ "httparse", "log", "rand", - "rustls 0.20.2", + "rustls 0.20.3", "sha-1", "thiserror", "url", @@ -2404,9 +2381,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" [[package]] name = "unicode-xid" @@ -2464,6 +2441,12 @@ dependencies = [ "getrandom", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/Cargo.toml b/Cargo.toml index a9fae0e..dcb7eb2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] songbird = { git = "https://github.com/serenity-rs/songbird", branch = "next", features = ["builtin-queue"] } -poise = { git = "https://github.com/kangalioo/poise", branch = "master", features = ["collector"] } +poise = { git = "https://github.com/kangalioo/poise", branch = "master" } sqlx = { version = "0.5", default-features = false, features = ["runtime-tokio-rustls", "macros", "mysql", "bigdecimal"] } dotenv = "0.15" tokio = { version = "1", features = ["fs", "process", "io-util"] } diff --git a/src/cmds/manage.rs b/src/cmds/manage.rs index e20ce52..e3e613d 100644 --- a/src/cmds/manage.rs +++ b/src/cmds/manage.rs @@ -1,11 +1,9 @@ -use std::time::Duration; - -use poise::serenity::model::id::{GuildId, RoleId}; +use poise::serenity_prelude::{Attachment, GuildId, RoleId}; use tokio::fs::File; use crate::{ cmds::autocomplete_sound, - consts::{MAX_SOUNDS, PATREON_GUILD, PATREON_ROLE, UPLOAD_MAX_SIZE}, + consts::{MAX_SOUNDS, PATREON_GUILD, PATREON_ROLE}, models::sound::{Sound, SoundCtx}, Context, Error, }; @@ -15,6 +13,7 @@ use crate::{ pub async fn upload_new_sound( ctx: Context<'_>, #[description = "Name to upload sound to"] name: String, + #[description = "Sound file (max. 2MB)"] file: Attachment, ) -> Result<(), Error> { fn is_numeric(s: &String) -> bool { for char in s.chars() { @@ -57,53 +56,22 @@ pub async fn upload_new_sound( } if permit_upload { - let attachment = { - ctx.say(format!("Please now upload an audio file under {}MB in size (larger files will be automatically trimmed):", *UPLOAD_MAX_SIZE / (1024u64.pow(2)))).await?; - - let reply = ctx - .channel_id() - .await_reply(&ctx.discord()) - .author_id(ctx.author().id) - .timeout(Duration::from_secs(120)) - .await; - - match reply { - Some(reply_msg) => { - if let Some(attachment) = reply_msg.attachments.get(0) { - Some(attachment.url.clone()) - } else { - ctx.say("Please upload 1 attachment following your upload command. Aborted").await?; - - None - } - } - - None => { - ctx.say("Upload timed out. Please redo the command").await?; - - None - } + match Sound::create_anon( + &name, + file.url.as_str(), + ctx.guild_id().unwrap(), + ctx.author().id, + &ctx.data().database, + ) + .await + { + Ok(_) => { + ctx.say("Sound has been uploaded").await?; } - }; - if let Some(url) = attachment { - match Sound::create_anon( - &name, - url.as_str(), - ctx.guild_id().unwrap(), - ctx.author().id, - &ctx.data().database, - ) - .await - { - Ok(_) => { - ctx.say("Sound has been uploaded").await?; - } - - Err(e) => { - println!("Error occurred during upload: {:?}", e); - ctx.say("Sound failed to upload.").await?; - } + Err(e) => { + println!("Error occurred during upload: {:?}", e); + ctx.say("Sound failed to upload.").await?; } } } else { diff --git a/src/main.rs b/src/main.rs index eef1100..5fdfade 100644 --- a/src/main.rs +++ b/src/main.rs @@ -147,11 +147,7 @@ async fn main() -> Result<(), Box> { .options(options) .client_settings(move |client_builder| { client_builder - .intents( - GatewayIntents::GUILD_VOICE_STATES - | GatewayIntents::GUILD_MESSAGES - | GatewayIntents::GUILDS, - ) + .intents(GatewayIntents::GUILD_VOICE_STATES | GatewayIntents::GUILDS) .register_songbird() }) .run_autosharded() From d82cbf2fd6a7949dd839b825550ae9fbea86bf7d Mon Sep 17 00:00:00 2001 From: jude Date: Thu, 5 May 2022 09:55:44 +0100 Subject: [PATCH 9/9] permissions --- .idea/dataSources.local.xml | 2 +- Cargo.lock | 749 +++++++++++++++++++++--------------- Cargo.toml | 5 +- src/cmds/manage.rs | 7 +- src/cmds/play.rs | 20 +- src/cmds/stop.rs | 4 +- src/event_handlers.rs | 2 +- src/main.rs | 7 +- 8 files changed, 475 insertions(+), 321 deletions(-) diff --git a/.idea/dataSources.local.xml b/.idea/dataSources.local.xml index d0c5fe0..2694069 100644 --- a/.idea/dataSources.local.xml +++ b/.idea/dataSources.local.xml @@ -1,6 +1,6 @@ - + master_key diff --git a/Cargo.lock b/Cargo.lock index 9649262..dac08a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,18 +49,15 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.4.12" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -dependencies = [ - "nodrop", -] +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] name = "async-trait" -version = "0.1.52" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" dependencies = [ "proc-macro2", "quote", @@ -69,34 +66,18 @@ dependencies = [ [[package]] name = "async-tungstenite" -version = "0.14.0" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8645e929ec7964448a901db9da30cd2ae8c7fecf4d6176af427837531dbbb63b" +checksum = "a1b71b31561643aa8e7df3effe284fa83ab1a840e52294c5f4bd7bfd8b2becbb" dependencies = [ "futures-io", "futures-util", "log", "pin-project-lite", "tokio", - "tokio-rustls 0.22.0", - "tungstenite 0.13.0", - "webpki-roots 0.21.1", -] - -[[package]] -name = "async-tungstenite" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5682ea0913e5c20780fe5785abacb85a411e7437bf52a1bedb93ddb3972cb8dd" -dependencies = [ - "futures-io", - "futures-util", - "log", - "pin-project-lite", - "tokio", - "tokio-rustls 0.23.2", - "tungstenite 0.16.0", - "webpki-roots 0.22.2", + "tokio-rustls 0.23.4", + "tungstenite", + "webpki-roots 0.22.3", ] [[package]] @@ -105,7 +86,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5" dependencies = [ - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] @@ -121,19 +102,20 @@ dependencies = [ [[package]] name = "audiopus" -version = "0.2.0" +version = "0.3.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3743519567e9135cf6f9f1a509851cb0c8e4cb9d66feb286668afb1923bec458" +checksum = "ab55eb0e56d7c6de3d59f544e5db122d7725ec33be6a276ee8241f3be6473955" dependencies = [ "audiopus_sys", ] [[package]] name = "audiopus_sys" -version = "0.1.8" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927791de46f70facea982dbfaf19719a41ce6064443403be631a85de6a58fff9" +checksum = "62314a1546a2064e033665d658e88c620a62904be945f8147e6b16c3db9f8651" dependencies = [ + "cmake", "log", "pkg-config", ] @@ -173,7 +155,7 @@ checksum = "d1e50562e37200edf7c6c43e54a08e64a5553bfb59d9c297d5572512aa517256" dependencies = [ "num-bigint", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] @@ -191,12 +173,27 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +dependencies = [ + "generic-array", +] + [[package]] name = "bumpalo" version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +[[package]] +name = "bytemuck" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" + [[package]] name = "byteorder" version = "1.4.3" @@ -211,9 +208,9 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "cc" -version = "1.0.72" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" [[package]] name = "cfg-if" @@ -229,7 +226,7 @@ checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ "libc", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", "serde", "winapi", ] @@ -243,6 +240,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "cmake" +version = "0.1.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" +dependencies = [ + "cc", +] + [[package]] name = "const-oid" version = "0.6.2" @@ -267,9 +273,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cpufeatures" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" dependencies = [ "libc", ] @@ -283,21 +289,11 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-queue" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd435b205a4842da59efd07628f921c096bc1cc0a156835b4fa0bcb9a19bcce" +checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2" dependencies = [ "cfg-if", "crossbeam-utils", @@ -305,9 +301,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" dependencies = [ "cfg-if", "lazy_static", @@ -324,6 +320,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "crypto-common" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "darling" version = "0.12.4" @@ -367,6 +373,17 @@ checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" dependencies = [ "cfg-if", "num_cpus", +] + +[[package]] +name = "dashmap" +version = "5.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391b56fbd302e585b7a9494fb70e40949567b1cf9003a8e4a6041a1687c26573" +dependencies = [ + "cfg-if", + "hashbrown 0.12.1", + "lock_api", "serde", ] @@ -400,6 +417,16 @@ dependencies = [ "generic-array", ] +[[package]] +name = "digest" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "block-buffer 0.10.2", + "crypto-common", +] + [[package]] name = "discortp" version = "0.4.0" @@ -424,9 +451,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "encoding_rs" -version = "0.8.30" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" dependencies = [ "cfg-if", ] @@ -464,9 +491,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af" dependencies = [ "cfg-if", "crc32fast", @@ -476,15 +503,15 @@ dependencies = [ [[package]] name = "flume" -version = "0.10.11" +version = "0.10.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b279436a715a9de95dcd26b151db590a71961cc06e54918b24fe0dd5b7d3fc4" +checksum = "843c03199d0c0ca54bc1ea90ac0d507274c28abcc4f691ae8b4eaa375087c76a" dependencies = [ "futures-core", "futures-sink", "nanorand", "pin-project", - "spin 0.9.2", + "spin 0.9.3", ] [[package]] @@ -568,7 +595,7 @@ checksum = "62007592ac46aa7c2b6416f7deb9a8a8f63a01e0f1d6e1787d5630170db2b63e" dependencies = [ "futures-core", "lock_api", - "parking_lot", + "parking_lot 0.11.2", ] [[package]] @@ -643,22 +670,22 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.10.2+wasi-snapshot-preview1", "wasm-bindgen", ] [[package]] name = "h2" -version = "0.3.11" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e" +checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" dependencies = [ "bytes", "fnv", @@ -669,7 +696,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util", + "tokio-util 0.7.1", "tracing", ] @@ -682,13 +709,19 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" + [[package]] name = "hashlink" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" dependencies = [ - "hashbrown", + "hashbrown 0.11.2", ] [[package]] @@ -717,9 +750,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "http" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb" dependencies = [ "bytes", "fnv", @@ -739,9 +772,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" +checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" [[package]] name = "httpdate" @@ -757,9 +790,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.17" +version = "0.14.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043f0e083e9901b6cc658a77d1eb86f4fc650bbb977a4337dd63192826aa85dd" +checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" dependencies = [ "bytes", "futures-channel", @@ -787,9 +820,9 @@ checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" dependencies = [ "http", "hyper", - "rustls 0.20.3", + "rustls 0.20.4", "tokio", - "tokio-rustls 0.23.2", + "tokio-rustls 0.23.4", ] [[package]] @@ -824,21 +857,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" dependencies = [ "autocfg 1.1.0", - "hashbrown", -] - -[[package]] -name = "input_buffer" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f97967975f448f1a7ddb12b0bc41069d09ed6a1c161a92687e057325db35d413" -dependencies = [ - "bytes", + "hashbrown 0.11.2", ] [[package]] @@ -852,9 +876,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" +checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" [[package]] name = "itertools" @@ -873,9 +897,9 @@ checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] name = "js-sys" -version = "0.3.56" +version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" dependencies = [ "wasm-bindgen", ] @@ -891,9 +915,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.118" +version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e509672465a0504304aa87f9f176f2b2b716ed8fb105ebe5c02dc6dce96a94" +checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" [[package]] name = "libm" @@ -903,18 +927,19 @@ checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" [[package]] name = "lock_api" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" dependencies = [ + "autocfg 1.1.0", "scopeguard", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] @@ -951,9 +976,9 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "mime" @@ -963,9 +988,9 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mime_guess" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" dependencies = [ "mime", "unicase", @@ -979,24 +1004,24 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" dependencies = [ "adler", - "autocfg 1.1.0", ] [[package]] name = "mio" -version = "0.7.14" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" dependencies = [ "libc", "log", "miow", "ntapi", + "wasi 0.11.0+wasi-snapshot-preview1", "winapi", ] @@ -1011,18 +1036,18 @@ dependencies = [ [[package]] name = "nanorand" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729eb334247daa1803e0a094d0a5c55711b85571179f5ec6e53eccfdf7008958" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" dependencies = [ "getrandom", ] [[package]] name = "native-tls" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" +checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" dependencies = [ "lazy_static", "libc", @@ -1036,21 +1061,14 @@ dependencies = [ "tempfile", ] -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - [[package]] name = "nom" -version = "7.1.0" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" dependencies = [ "memchr", "minimal-lexical", - "version_check", ] [[package]] @@ -1070,7 +1088,7 @@ checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" dependencies = [ "autocfg 1.1.0", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] @@ -1085,7 +1103,7 @@ dependencies = [ "libm", "num-integer", "num-iter", - "num-traits 0.2.14", + "num-traits 0.2.15", "rand", "smallvec", "zeroize", @@ -1093,23 +1111,23 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg 1.1.0", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] name = "num-iter" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" dependencies = [ "autocfg 1.1.0", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] @@ -1118,14 +1136,14 @@ version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" dependencies = [ - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg 1.1.0", "libm", @@ -1142,10 +1160,19 @@ dependencies = [ ] [[package]] -name = "once_cell" -version = "1.9.0" +name = "num_threads" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + +[[package]] +name = "once_cell" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" [[package]] name = "opaque-debug" @@ -1155,18 +1182,30 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.38" +version = "0.10.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" +checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" dependencies = [ "bitflags", "cfg-if", "foreign-types", "libc", "once_cell", + "openssl-macros", "openssl-sys", ] +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "openssl-probe" version = "0.1.5" @@ -1175,9 +1214,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.72" +version = "0.9.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" +checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0" dependencies = [ "autocfg 1.1.0", "cc", @@ -1186,6 +1225,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "ordered-float" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" +dependencies = [ + "num-traits 0.2.15", +] + [[package]] name = "parking_lot" version = "0.11.2" @@ -1194,7 +1242,17 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core", + "parking_lot_core 0.8.5", +] + +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.3", ] [[package]] @@ -1211,6 +1269,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "paste" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" + [[package]] name = "pem-rfc7468" version = "0.2.4" @@ -1248,9 +1325,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -1284,9 +1361,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "pnet_base" @@ -1318,11 +1395,13 @@ dependencies = [ [[package]] name = "poise" version = "0.1.0" -source = "git+https://github.com/kangalioo/poise?branch=master#38bcca284cbc9fb52cd770d7af64fbd4b3495cc8" +source = "git+https://github.com/jellywx/poise?branch=jellywx-pv2#3f18e5e29e34f3b5db307605c778036e19f770fd" dependencies = [ "async-trait", + "derivative", "futures-core", "futures-util", + "log", "once_cell", "poise_macros", "regex", @@ -1333,7 +1412,7 @@ dependencies = [ [[package]] name = "poise_macros" version = "0.1.0" -source = "git+https://github.com/kangalioo/poise?branch=master#38bcca284cbc9fb52cd770d7af64fbd4b3495cc8" +source = "git+https://github.com/jellywx/poise?branch=jellywx-pv2#3f18e5e29e34f3b5db307605c778036e19f770fd" dependencies = [ "darling", "proc-macro2", @@ -1360,18 +1439,18 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ "proc-macro2", ] @@ -1408,18 +1487,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "aho-corasick", "memchr", @@ -1452,9 +1531,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.9" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f242f1488a539a79bac6dbe7c8609ae43b7914b7736210f239a37cccb32525" +checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" dependencies = [ "base64", "bytes", @@ -1476,20 +1555,20 @@ dependencies = [ "native-tls", "percent-encoding", "pin-project-lite", - "rustls 0.20.3", + "rustls 0.20.4", "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-native-tls", - "tokio-rustls 0.23.2", - "tokio-util", + "tokio-rustls 0.23.4", + "tokio-util 0.6.9", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.22.2", + "webpki-roots 0.22.3", "winreg", ] @@ -1515,12 +1594,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e05c2603e2823634ab331437001b411b9ed11660fbc4066f3908c84a9439260d" dependencies = [ "byteorder", - "digest", + "digest 0.9.0", "lazy_static", "num-bigint-dig", "num-integer", "num-iter", - "num-traits 0.2.14", + "num-traits 0.2.15", "pkcs1", "pkcs8", "rand", @@ -1543,9 +1622,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b323592e3164322f5b193dc4302e4e36cd8d37158a712d664efae1a5c2791700" +checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" dependencies = [ "log", "ring", @@ -1555,9 +1634,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +checksum = "1ee86d63972a7c661d1536fefe8c3c8407321c3df668891286de28abcd087360" dependencies = [ "base64", ] @@ -1576,9 +1655,9 @@ checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "salsa20" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecbd2eb639fd7cab5804a0837fe373cc2172d15437e804c054a9fb885cb923b0" +checksum = "0c0fbb5f676da676c260ba276a8f43a8dc67cf02d1438423aeb1c677a7212686" dependencies = [ "cipher", "zeroize", @@ -1651,18 +1730,28 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] [[package]] -name = "serde_derive" -version = "1.0.136" +name = "serde-value" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ "proc-macro2", "quote", @@ -1671,9 +1760,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ "itoa", "ryu", @@ -1682,9 +1771,9 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5" +checksum = "a2ad84e47328a31223de7fed7a4f5087f2d6ddfe586cf3ca25b7a165bc0a5aed" dependencies = [ "proc-macro2", "quote", @@ -1705,25 +1794,28 @@ dependencies = [ [[package]] name = "serenity" -version = "0.10.10" -source = "git+https://github.com/serenity-rs/serenity?branch=next#9e3b92cd3f95fbb50f96ac3af36dc7fe947fc833" +version = "0.11.1" +source = "git+https://github.com//serenity-rs/serenity?branch=current#e690ccd17174f2b9dc3f6a1545f69a209a11241f" dependencies = [ "async-trait", - "async-tungstenite 0.16.1", + "async-tungstenite", "base64", "bitflags", "bytes", + "cfg-if", "chrono", - "dashmap", + "dashmap 5.3.3", "flate2", "futures", "mime", "mime_guess", - "parking_lot", + "parking_lot 0.12.0", "percent-encoding", "reqwest", "serde", + "serde-value", "serde_json", + "time", "tokio", "tracing", "typemap_rev", @@ -1733,7 +1825,7 @@ dependencies = [ [[package]] name = "serenity-voice-model" version = "0.1.1" -source = "git+https://github.com/serenity-rs/serenity?branch=next#9e3b92cd3f95fbb50f96ac3af36dc7fe947fc833" +source = "git+https://github.com/serenity-rs/serenity?branch=next#44858608d8a8169791c00bccaaee65b55494452d" dependencies = [ "bitflags", "enum_primitive", @@ -1748,23 +1840,34 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if", "cpufeatures", - "digest", + "digest 0.9.0", "opaque-debug", ] +[[package]] +name = "sha-1" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.3", +] + [[package]] name = "sha2" version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if", "cpufeatures", - "digest", + "digest 0.9.0", "opaque-debug", ] @@ -1788,9 +1891,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" [[package]] name = "smallvec" @@ -1811,25 +1914,24 @@ dependencies = [ [[package]] name = "songbird" version = "0.2.2" -source = "git+https://github.com/serenity-rs/songbird?branch=next#e0ab49c2ff92cb4c5f3ffc90be7a267fd12c905b" +source = "git+https://github.com/serenity-rs/songbird?branch=next#dabf73ba09934d3b1934aad0536b3213cf8fd0ef" dependencies = [ "async-trait", - "async-tungstenite 0.14.0", + "async-tungstenite", "audiopus", "byteorder", - "dashmap", + "dashmap 5.3.3", "derivative", "discortp", "flume", "futures", - "parking_lot", + "parking_lot 0.12.0", "pin-project", "rand", "serde", "serde_json", "serenity", "serenity-voice-model", - "spin_sleep", "streamcatcher", "symphonia-core", "tokio", @@ -1845,7 +1947,7 @@ dependencies = [ name = "soundfx-rs" version = "1.5.0" dependencies = [ - "dashmap", + "dashmap 4.0.2", "dotenv", "env_logger", "lazy_static", @@ -1867,23 +1969,13 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" +checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" dependencies = [ "lock_api", ] -[[package]] -name = "spin_sleep" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a98101bdc3833e192713c2af0b0dd2614f50d1cf1f7a97c5221b7aac052acc7" -dependencies = [ - "once_cell", - "winapi", -] - [[package]] name = "spki" version = "0.4.1" @@ -1906,9 +1998,9 @@ dependencies = [ [[package]] name = "sqlx" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692749de69603d81e016212199d73a2e14ee20e2def7d7914919e8db5d4d48b9" +checksum = "fc15591eb44ffb5816a4a70a7efd5dd87bfd3aa84c4c200401c4396140525826" dependencies = [ "sqlx-core", "sqlx-macros", @@ -1916,9 +2008,9 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518be6f6fff5ca76f985d434f9c37f3662af279642acf730388f271dff7b9016" +checksum = "195183bf6ff8328bb82c0511a83faf60aacf75840103388851db61d7a9854ae3" dependencies = [ "ahash", "atoi", @@ -1926,10 +2018,8 @@ dependencies = [ "bitflags", "byteorder", "bytes", - "crossbeam-channel", "crossbeam-queue", - "crossbeam-utils", - "digest", + "digest 0.9.0", "either", "futures-channel", "futures-core", @@ -1945,12 +2035,12 @@ dependencies = [ "memchr", "num-bigint", "once_cell", - "parking_lot", + "paste", "percent-encoding", "rand", "rsa", "rustls 0.19.1", - "sha-1", + "sha-1 0.9.8", "sha2", "smallvec", "sqlformat", @@ -1965,9 +2055,9 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38e45140529cf1f90a5e1c2e561500ca345821a1c513652c8f486bbf07407cc8" +checksum = "eee35713129561f5e55c554bba1c378e2a7e67f81257b7311183de98c50e6f94" dependencies = [ "dotenv", "either", @@ -1983,9 +2073,9 @@ dependencies = [ [[package]] name = "sqlx-rt" -version = "0.5.10" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8061cbaa91ee75041514f67a09398c65a64efed72c90151ecd47593bad53da99" +checksum = "4db708cd3e459078f85f39f96a00960bd841f66ee2a669e90bf36907f5a79aae" dependencies = [ "once_cell", "tokio", @@ -2027,22 +2117,22 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "symphonia-core" -version = "0.2.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e32b956473d98c601dac257fab8a7700d42e49fdd7a33432dd5dc7fdd2448dd" +checksum = "1edcb254d25e02b688b6f8a290a778153fa5f29674ac50773d03e0a16060391d" dependencies = [ "arrayvec", "bitflags", - "byteorder", + "bytemuck", "lazy_static", "log", ] [[package]] name = "syn" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" dependencies = [ "proc-macro2", "quote", @@ -2077,27 +2167,27 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ "proc-macro2", "quote", @@ -2114,10 +2204,22 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.5.1" +name = "time" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" +dependencies = [ + "itoa", + "libc", + "num_threads", + "serde", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -2130,9 +2232,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.16.1" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a" +checksum = "dce653fb475565de9f6fb0614b28bca8df2c430c0cf84bcd9c843f15de5414cc" dependencies = [ "bytes", "libc", @@ -2142,6 +2244,7 @@ dependencies = [ "once_cell", "pin-project-lite", "signal-hook-registry", + "socket2", "tokio-macros", "winapi", ] @@ -2180,11 +2283,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.2" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ - "rustls 0.20.3", + "rustls 0.20.4", "tokio", "webpki 0.22.0", ] @@ -2214,6 +2317,20 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-util" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + [[package]] name = "tower-service" version = "0.3.1" @@ -2222,9 +2339,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.30" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d8d93354fe2a8e50d5953f5ae2e47a3fc2ef03292e7ea46e3cc38f549525fb9" +checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" dependencies = [ "cfg-if", "log", @@ -2235,9 +2352,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.19" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8276d9a4a3a558d7b7ad5303ad50b53d58264641b82914b7ada36bd762e7a716" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" dependencies = [ "proc-macro2", "quote", @@ -2246,9 +2363,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.22" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" +checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" dependencies = [ "lazy_static", "valuable", @@ -2266,9 +2383,9 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" dependencies = [ "lazy_static", "log", @@ -2277,9 +2394,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74786ce43333fcf51efe947aed9718fbe46d5c7328ec3f1029e818083966d9aa" +checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596" dependencies = [ "ansi_term", "lazy_static", @@ -2301,32 +2418,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "tungstenite" -version = "0.13.0" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe8dada8c1a3aeca77d6b51a4f1314e0f4b8e438b7b1b71e3ddaca8080e4093" -dependencies = [ - "base64", - "byteorder", - "bytes", - "http", - "httparse", - "input_buffer", - "log", - "rand", - "rustls 0.19.1", - "sha-1", - "thiserror", - "url", - "utf-8", - "webpki 0.21.4", - "webpki-roots 0.21.1", -] - -[[package]] -name = "tungstenite" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ad3713a14ae247f22a728a0456a545df14acf3867f905adff84be99e23b3ad1" +checksum = "d96a2dea40e7570482f28eb57afbe42d97551905da6a9400acc5c328d24004f5" dependencies = [ "base64", "byteorder", @@ -2335,8 +2429,8 @@ dependencies = [ "httparse", "log", "rand", - "rustls 0.20.3", - "sha-1", + "rustls 0.20.4", + "sha-1 0.10.0", "thiserror", "url", "utf-8", @@ -2366,9 +2460,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-normalization" @@ -2387,9 +2481,9 @@ checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" [[package]] name = "unicode-xid" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" [[package]] name = "unicode_categories" @@ -2476,10 +2570,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] -name = "wasm-bindgen" -version = "0.2.79" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2487,9 +2587,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.79" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" +checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" dependencies = [ "bumpalo", "lazy_static", @@ -2502,9 +2602,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.29" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" +checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" dependencies = [ "cfg-if", "js-sys", @@ -2514,9 +2614,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.79" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" +checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2524,9 +2624,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.79" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" +checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" dependencies = [ "proc-macro2", "quote", @@ -2537,15 +2637,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.79" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" +checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" [[package]] name = "web-sys" -version = "0.3.56" +version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" +checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" dependencies = [ "js-sys", "wasm-bindgen", @@ -2582,9 +2682,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.2" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" +checksum = "44d8de8415c823c8abd270ad483c6feeac771fad964890779f9a8cb24fbbc1bf" dependencies = [ "webpki 0.22.0", ] @@ -2621,19 +2721,62 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "winreg" -version = "0.7.0" +name = "windows-sys" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ "winapi", ] [[package]] name = "xsalsa20poly1305" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e0f69b133860e3614a4d4fdd6f0d7fe3219e9d67a7e8cd537676a4ebc8313db" +checksum = "e68bcb965d6c650091450b95cea12f07dcd299a01c15e2f9433b0813ea3c0886" dependencies = [ "aead", "poly1305", @@ -2654,9 +2797,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81e8f13fef10b63c06356d65d416b070798ddabcadc10d3ece0c5be9b3c7eddb" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index dcb7eb2..c455269 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] songbird = { git = "https://github.com/serenity-rs/songbird", branch = "next", features = ["builtin-queue"] } -poise = { git = "https://github.com/kangalioo/poise", branch = "master" } +poise = { git = "https://github.com/jellywx/poise", branch = "jellywx-pv2" } sqlx = { version = "0.5", default-features = false, features = ["runtime-tokio-rustls", "macros", "mysql", "bigdecimal"] } dotenv = "0.15" tokio = { version = "1", features = ["fs", "process", "io-util"] } @@ -17,3 +17,6 @@ regex = "1.4" log = "0.4" serde_json = "1.0" dashmap = "4.0" + +[patch."https://github.com/serenity-rs/serenity"] +serenity = { git = "https://github.com//serenity-rs/serenity", branch = "current" } diff --git a/src/cmds/manage.rs b/src/cmds/manage.rs index e3e613d..97b68c4 100644 --- a/src/cmds/manage.rs +++ b/src/cmds/manage.rs @@ -9,7 +9,12 @@ use crate::{ }; /// Upload a new sound to the bot -#[poise::command(slash_command, rename = "upload", category = "Manage")] +#[poise::command( + slash_command, + rename = "upload", + category = "Manage", + required_permissions = "MANAGE_GUILD" +)] pub async fn upload_new_sound( ctx: Context<'_>, #[description = "Name to upload sound to"] name: String, diff --git a/src/cmds/play.rs b/src/cmds/play.rs index c3dcb37..b71d2cd 100644 --- a/src/cmds/play.rs +++ b/src/cmds/play.rs @@ -2,14 +2,15 @@ use poise::serenity::{ builder::CreateActionRow, model::interactions::message_component::ButtonStyle, }; -use crate::models::guild_data::CtxGuildData; -use crate::utils::{join_channel, queue_audio}; use crate::{ - cmds::autocomplete_sound, models::sound::SoundCtx, utils::play_from_query, Context, Error, + cmds::autocomplete_sound, + models::{guild_data::CtxGuildData, sound::SoundCtx}, + utils::{join_channel, play_from_query, queue_audio}, + Context, Error, }; /// Play a sound in your current voice channel -#[poise::command(slash_command)] +#[poise::command(slash_command, required_permissions = "SPEAK")] pub async fn play( ctx: Context<'_>, #[description = "Name or ID of sound to play"] @@ -35,7 +36,7 @@ pub async fn play( } /// Play up to 25 sounds on queue -#[poise::command(slash_command, rename = "queue")] +#[poise::command(slash_command, rename = "queue", required_permissions = "SPEAK")] pub async fn queue_play( ctx: Context<'_>, #[description = "Name or ID for queue position 1"] @@ -196,7 +197,7 @@ pub async fn queue_play( } /// Loop a sound in your current voice channel -#[poise::command(slash_command, rename = "loop")] +#[poise::command(slash_command, rename = "loop", required_permissions = "SPEAK")] pub async fn loop_play( ctx: Context<'_>, #[description = "Name or ID of sound to loop"] @@ -222,7 +223,12 @@ pub async fn loop_play( } /// Get a menu of sounds with buttons to play them -#[poise::command(slash_command, rename = "soundboard", category = "Play")] +#[poise::command( + slash_command, + rename = "soundboard", + category = "Play", + required_permissions = "SPEAK" +)] pub async fn soundboard( ctx: Context<'_>, #[description = "Name or ID of sound for button 1"] diff --git a/src/cmds/stop.rs b/src/cmds/stop.rs index 8c1f266..37a2238 100644 --- a/src/cmds/stop.rs +++ b/src/cmds/stop.rs @@ -3,7 +3,7 @@ use songbird; use crate::{Context, Error}; /// Stop the bot from playing and clear the play queue -#[poise::command(slash_command, rename = "stop")] +#[poise::command(slash_command, rename = "stop", required_permissions = "MANAGE_GUILD")] pub async fn stop_playing(ctx: Context<'_>) -> Result<(), Error> { let songbird = songbird::get(ctx.discord()).await.unwrap(); let call_opt = songbird.get(ctx.guild_id().unwrap()); @@ -20,7 +20,7 @@ pub async fn stop_playing(ctx: Context<'_>) -> Result<(), Error> { } /// Disconnect the bot -#[poise::command(slash_command)] +#[poise::command(slash_command, required_permissions = "SPEAK")] pub async fn disconnect(ctx: Context<'_>) -> Result<(), Error> { let songbird = songbird::get(ctx.discord()).await.unwrap(); let _ = songbird.leave(ctx.guild_id().unwrap()).await; diff --git a/src/event_handlers.rs b/src/event_handlers.rs index 6242b5f..89ab9b8 100644 --- a/src/event_handlers.rs +++ b/src/event_handlers.rs @@ -63,7 +63,7 @@ pub async fn listener(ctx: &Context, event: &poise::Event<'_>, data: &Data) -> R if let Some(channel_id) = past_state.channel_id { if let Some(Channel::Guild(channel)) = channel_id.to_channel_cached(&ctx) { if channel.members(&ctx).await.map(|m| m.len()).unwrap_or(0) <= 1 { - let songbird = songbird::get(&ctx).await.unwrap(); + let songbird = songbird::get(ctx).await.unwrap(); let _ = songbird.remove(guild_id).await; } diff --git a/src/main.rs b/src/main.rs index 5fdfade..8a34c60 100644 --- a/src/main.rs +++ b/src/main.rs @@ -145,11 +145,8 @@ async fn main() -> Result<(), Box> { }) }) .options(options) - .client_settings(move |client_builder| { - client_builder - .intents(GatewayIntents::GUILD_VOICE_STATES | GatewayIntents::GUILDS) - .register_songbird() - }) + .client_settings(move |client_builder| client_builder.register_songbird()) + .intents(GatewayIntents::GUILD_VOICE_STATES | GatewayIntents::GUILDS) .run_autosharded() .await?;