From a521516b5fe4cea3a6f2b60b05f1cf063f938bbb Mon Sep 17 00:00:00 2001 From: Agatha Rose Date: Sun, 22 Nov 2020 22:51:15 +0200 Subject: [PATCH] Update to serenity v0.9.1 and make the bot fully async --- Cargo.lock | 454 ++++++++++++++++++++++---------------- Cargo.toml | 17 +- src/commands/brainfuck.rs | 62 +++--- src/commands/define.rs | 31 +-- src/commands/embed.rs | 128 +++++------ src/commands/emote.rs | 15 +- src/commands/help.rs | 95 ++++---- src/commands/lyrics.rs | 32 +-- src/commands/pinned.rs | 68 +++--- src/commands/ship.rs | 29 +-- src/main.rs | 384 ++++++++++++++++++-------------- 11 files changed, 739 insertions(+), 576 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 61234f4..db6c590 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,6 +21,33 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" +[[package]] +name = "async-trait" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b246867b8b3b6ae56035f1eb1ed557c1d8eae97f0d53696138a50fa0e3a3b8c0" +dependencies = [ + "proc-macro2", + "quote 1.0.3", + "syn 1.0.48", +] + +[[package]] +name = "async-tungstenite" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce503a5cb1e7450af7d211b86b84807791b251f335b2f43f1e26b85a416f315" +dependencies = [ + "futures-io", + "futures-util", + "log 0.4.8", + "pin-project 1.0.1", + "tokio", + "tokio-rustls", + "tungstenite", + "webpki-roots", +] + [[package]] name = "atty" version = "0.2.14" @@ -48,18 +75,18 @@ dependencies = [ "safemem", ] -[[package]] -name = "base64" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" - [[package]] name = "base64" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + [[package]] name = "bitflags" version = "0.9.1" @@ -83,9 +110,9 @@ dependencies = [ [[package]] name = "brainfrick" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c064ec9b9efbe8e711d8edce078facdfc2e99b5147572e616ecdb76c5686d43" +checksum = "b24bc4629eeab19ec9771bb4899b3e7916e320dd1825b5e715c1db6e5328bc10" dependencies = [ "itertools", ] @@ -128,19 +155,10 @@ checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" dependencies = [ "num-integer", "num-traits 0.2.11", - "serde 1.0.116", + "serde 1.0.117", "time", ] -[[package]] -name = "cloudabi" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467" -dependencies = [ - "bitflags 1.2.1", -] - [[package]] name = "colored" version = "2.0.0" @@ -154,13 +172,23 @@ dependencies = [ [[package]] name = "command_attr" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c27d6155f93d880b6379d93ddc9b2417b3b69b715360c5f25525e4576338a381" +checksum = "8dc8da29004a4dd9b89d21b2e17ccd372c1ff085bdab9e22b989096db1289d01" dependencies = [ "proc-macro2", "quote 1.0.3", - "syn 1.0.36", + "syn 1.0.48", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211" +dependencies = [ + "cfg-if", + "wasm-bindgen", ] [[package]] @@ -276,6 +304,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "form_urlencoded" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00" +dependencies = [ + "matches", + "percent-encoding 2.1.0", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -298,6 +336,20 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +[[package]] +name = "futures" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.5" @@ -305,6 +357,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -328,7 +381,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2", "quote 1.0.3", - "syn 1.0.36", + "syn 1.0.48", ] [[package]] @@ -352,12 +405,14 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", + "futures-sink", "futures-task", "memchr", - "pin-project", + "pin-project 0.4.8", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -476,7 +531,7 @@ dependencies = [ "itoa 0.4.5", "log 0.4.8", "net2", - "pin-project", + "pin-project 0.4.8", "time", "tokio", "tower-service", @@ -504,7 +559,7 @@ dependencies = [ "futures-util", "hyper 0.13.4", "log 0.4.8", - "rustls 0.18.0", + "rustls", "tokio", "tokio-rustls", "webpki", @@ -563,15 +618,6 @@ dependencies = [ "bytes", ] -[[package]] -name = "instant" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66" -dependencies = [ - "cfg-if", -] - [[package]] name = "iovec" version = "0.1.4" @@ -610,9 +656,9 @@ checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" [[package]] name = "js-sys" -version = "0.3.37" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055" +checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" dependencies = [ "wasm-bindgen", ] @@ -651,15 +697,6 @@ version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" -[[package]] -name = "lock_api" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" -dependencies = [ - "scopeguard", -] - [[package]] name = "log" version = "0.3.9" @@ -904,32 +941,6 @@ dependencies = [ "regex", ] -[[package]] -name = "parking_lot" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" -dependencies = [ - "cfg-if", - "cloudabi", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi 0.3.8", -] - [[package]] name = "percent-encoding" version = "1.0.1" @@ -948,7 +959,16 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7804a463a8d9572f13453c516a5faea534a2403d7ced2f0c7e100eeff072772c" dependencies = [ - "pin-project-internal", + "pin-project-internal 0.4.8", +] + +[[package]] +name = "pin-project" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee41d838744f60d959d7074e3afb6b35c7456d0f61cad38a24e35e6553f73841" +dependencies = [ + "pin-project-internal 1.0.1", ] [[package]] @@ -959,7 +979,18 @@ checksum = "385322a45f2ecf3410c68d2a549a4a2685e8051d0f278e39743ff4e451cb9b3f" dependencies = [ "proc-macro2", "quote 1.0.3", - "syn 1.0.36", + "syn 1.0.48", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81a4ffa594b66bff340084d4081df649a7dc049ac8d7fc458d8e628bfbbb2f86" +dependencies = [ + "proc-macro2", + "quote 1.0.3", + "syn 1.0.48", ] [[package]] @@ -968,6 +999,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" +[[package]] +name = "pin-project-lite" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c" + [[package]] name = "pin-utils" version = "0.1.0" @@ -1000,9 +1037,9 @@ checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" [[package]] name = "proc-macro2" -version = "1.0.19" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" dependencies = [ "unicode-xid 0.2.0", ] @@ -1108,9 +1145,9 @@ checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" [[package]] name = "regex" -version = "1.3.9" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" +checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" dependencies = [ "aho-corasick", "memchr", @@ -1120,9 +1157,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.18" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" +checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" [[package]] name = "remove_dir_all" @@ -1150,11 +1187,11 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9eaa17ac5d7b838b7503d118fa16ad88f440498bf9ffe5424e621f93190d61e" +checksum = "fb15d6255c792356a0f578d8a645c677904dc02e862bebe2ecc18e0c01b9a0ce" dependencies = [ - "base64 0.12.3", + "base64 0.13.0", "bytes", "encoding_rs", "futures-core", @@ -1172,17 +1209,18 @@ dependencies = [ "mime_guess", "native-tls 0.2.4", "percent-encoding 2.1.0", - "pin-project-lite", - "rustls 0.18.0", - "serde 1.0.116", + "pin-project-lite 0.2.0", + "rustls", + "serde 1.0.117", "serde_json 1.0.48", - "serde_urlencoded 0.6.1", + "serde_urlencoded 0.7.0", "tokio", "tokio-rustls", "tokio-tls", - "url 2.1.1", + "url 2.2.0", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-bindgen-test", "web-sys", "webpki-roots", "winreg", @@ -1214,27 +1252,15 @@ dependencies = [ "percent-encoding 2.1.0", "rand 0.7.3", "regex", - "reqwest 0.10.8", - "serde 1.0.116", + "reqwest 0.10.9", + "serde 1.0.117", "serenity", "sys-info", + "tokio", "toml", "urbandict", ] -[[package]] -name = "rustls" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1" -dependencies = [ - "base64 0.11.0", - "log 0.4.8", - "ring", - "sct", - "webpki", -] - [[package]] name = "rustls" version = "0.18.0" @@ -1271,10 +1297,10 @@ dependencies = [ ] [[package]] -name = "scopeguard" -version = "1.1.0" +name = "scoped-tls" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" [[package]] name = "sct" @@ -1338,11 +1364,11 @@ checksum = "34b623917345a631dc9608d5194cc206b3fe6c3554cd1c75b937e55e285254af" [[package]] name = "serde" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5" +checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a" dependencies = [ - "serde_derive 1.0.116", + "serde_derive 1.0.117", ] [[package]] @@ -1367,13 +1393,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8" +checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e" dependencies = [ "proc-macro2", "quote 1.0.3", - "syn 1.0.36", + "syn 1.0.48", ] [[package]] @@ -1396,7 +1422,7 @@ checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" dependencies = [ "itoa 0.4.5", "ryu", - "serde 1.0.116", + "serde 1.0.117", ] [[package]] @@ -1413,41 +1439,41 @@ dependencies = [ [[package]] name = "serde_urlencoded" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" +checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" dependencies = [ - "dtoa", + "form_urlencoded", "itoa 0.4.5", - "serde 1.0.116", - "url 2.1.1", + "ryu", + "serde 1.0.117", ] [[package]] name = "serenity" -version = "0.8.7" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e304a606c9601e538849c67b19af64e114e14ac633093e5e05188a9274f507c2" +checksum = "9fbd2938b8859261d418ba8325a795000e37e9cba1b19d4e978775c5e34dc997" dependencies = [ - "base64 0.12.3", + "async-trait", + "async-tungstenite", + "base64 0.13.0", "bitflags 1.2.1", + "bytes", "chrono", "command_attr", "flate2", - "log 0.4.8", - "parking_lot", - "reqwest 0.10.8", - "rustls 0.17.0", - "serde 1.0.116", + "futures", + "reqwest 0.10.9", + "serde 1.0.117", "serde_json 1.0.48", "static_assertions", - "threadpool", - "tungstenite", - "typemap", - "url 2.1.1", + "tokio", + "tracing", + "tracing-futures", + "typemap_rev", + "url 2.2.0", "uwl", - "webpki", - "webpki-roots", ] [[package]] @@ -1500,9 +1526,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.36" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cdb98bcb1f9d81d07b536179c269ea15999b5d14ea958196413869445bb5250" +checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac" dependencies = [ "proc-macro2", "quote 1.0.3", @@ -1561,15 +1587,6 @@ dependencies = [ "lazy_static 1.4.0", ] -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - [[package]] name = "time" version = "0.1.42" @@ -1583,9 +1600,9 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd" +checksum = "a6d7ad61edd59bfcc7e80dababf0f4aed2e6d5e0ba1659356ae889752dfc12ff" dependencies = [ "bytes", "fnv", @@ -1594,8 +1611,20 @@ dependencies = [ "memchr", "mio", "num_cpus", - "pin-project-lite", + "pin-project-lite 0.1.4", "slab", + "tokio-macros", +] + +[[package]] +name = "tokio-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" +dependencies = [ + "proc-macro2", + "quote 1.0.3", + "syn 1.0.48", ] [[package]] @@ -1605,7 +1634,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "228139ddd4fea3fa345a29233009635235833e52807af7ea6448ead03890d6a9" dependencies = [ "futures-core", - "rustls 0.18.0", + "rustls", "tokio", "webpki", ] @@ -1630,17 +1659,17 @@ dependencies = [ "futures-core", "futures-sink", "log 0.4.8", - "pin-project-lite", + "pin-project-lite 0.1.4", "tokio", ] [[package]] name = "toml" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" +checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645" dependencies = [ - "serde 1.0.116", + "serde 1.0.117", ] [[package]] @@ -1649,6 +1678,48 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" +[[package]] +name = "tracing" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27" +dependencies = [ + "cfg-if", + "pin-project-lite 0.1.4", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada" +dependencies = [ + "proc-macro2", + "quote 1.0.3", + "syn 1.0.48", +] + +[[package]] +name = "tracing-core" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f" +dependencies = [ + "lazy_static 1.4.0", +] + +[[package]] +name = "tracing-futures" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c" +dependencies = [ + "pin-project 0.4.8", + "tracing", +] + [[package]] name = "traitobject" version = "0.1.0" @@ -1676,7 +1747,7 @@ dependencies = [ "log 0.4.8", "rand 0.7.3", "sha-1", - "url 2.1.1", + "url 2.2.0", "utf-8", ] @@ -1687,13 +1758,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" [[package]] -name = "typemap" -version = "0.3.3" +name = "typemap_rev" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6" -dependencies = [ - "unsafe-any", -] +checksum = "078d41124321488746becfa144977b9b54667af408ff933cbbce9d83e7796ac9" [[package]] name = "typenum" @@ -1749,15 +1817,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -[[package]] -name = "unsafe-any" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f" -dependencies = [ - "traitobject", -] - [[package]] name = "untrusted" version = "0.7.0" @@ -1789,10 +1848,11 @@ dependencies = [ [[package]] name = "url" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" +checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e" dependencies = [ + "form_urlencoded", "idna 0.2.0", "matches", "percent-encoding 2.1.0", @@ -1846,36 +1906,36 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasm-bindgen" -version = "0.2.60" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f" +checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" dependencies = [ "cfg-if", - "serde 1.0.116", + "serde 1.0.117", "serde_json 1.0.48", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.60" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd" +checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" dependencies = [ "bumpalo", "lazy_static 1.4.0", "log 0.4.8", "proc-macro2", "quote 1.0.3", - "syn 1.0.36", + "syn 1.0.48", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.10" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7add542ea1ac7fdaa9dc25e031a6af33b7d63376292bd24140c637d00d1c312a" +checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da" dependencies = [ "cfg-if", "js-sys", @@ -1885,9 +1945,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.60" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4" +checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" dependencies = [ "quote 1.0.3", "wasm-bindgen-macro-support", @@ -1895,22 +1955,46 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.60" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931" +checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" dependencies = [ "proc-macro2", "quote 1.0.3", - "syn 1.0.36", + "syn 1.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.60" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639" +checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" + +[[package]] +name = "wasm-bindgen-test" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34d1cdc8b98a557f24733d50a1199c4b0635e465eecba9c45b214544da197f64" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "scoped-tls", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8fb9c67be7439ee8ab1b7db502a49c05e51e2835b66796c705134d9b8e1a585" +dependencies = [ + "proc-macro2", + "quote 1.0.3", +] [[package]] name = "web-sys" @@ -1934,9 +2018,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8eff4b7516a57307f9349c64bf34caa34b940b66fed4b2fb3136cb7386e5739" +checksum = "0f20dea7535251981a9670857150d571846545088359b28e4951d350bdaf179f" dependencies = [ "webpki", ] diff --git a/Cargo.toml b/Cargo.toml index b81f667..d01eb68 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,25 +7,30 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -serenity = "0.8.7" +serenity = "0.9.1" rand = "0.7.3" -toml = "0.5.6" +toml = "0.5.7" sys-info = "0.7.0" urbandict = "0.2.0" owoify = "0.1.5" lazy_static = "1.4.0" colored = "2.0.0" -brainfrick = "1.1.1" +brainfrick = "1.1.2" percent-encoding = "2.1.0" -regex = "1.3.9" +regex = "1.4.2" [patch.crates-io] openssl = { git = "https://github.com/ishitatsuyuki/rust-openssl", branch = "0.9.x" } [dependencies.serde] -version = "1.0.116" +version = "1.0.117" features = ["derive"] [dependencies.reqwest] -version = "0.10.8" +version = "0.10.9" features = ["blocking", "json"] + + +[dependencies.tokio] +version = "0.2.23" +features = ["macros"] \ No newline at end of file diff --git a/src/commands/brainfuck.rs b/src/commands/brainfuck.rs index fc45723..f4b163a 100644 --- a/src/commands/brainfuck.rs +++ b/src/commands/brainfuck.rs @@ -1,5 +1,5 @@ use serenity::{ - framework::standard::{macros::command, Args, CommandError, CommandResult}, + framework::standard::{macros::command, Args, CommandResult}, model::channel::Message, prelude::*, }; @@ -7,12 +7,12 @@ use serenity::{ // brainfuck interpreter #[command] #[aliases("bf", "brainfrick")] -fn brainfuck(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { +async fn brainfuck(ctx: &Context, message: &Message, args: Args) -> CommandResult { use brainfrick::Brainfuck; let input = match args.rest().trim() { "" => { - return Err(CommandError(s!("Called without input!"))); + return Err("Called without input!".into()); } v => v, }; @@ -20,33 +20,43 @@ fn brainfuck(ctx: &mut Context, message: &Message, args: Args) -> CommandResult match output { Ok(v) => { - let _ = message.channel_id.send_message(&ctx.http, |m| { - m.embed(|e| { - e.title("Brainfuck interpreter") - .description(format!( - "Input\n```brainfuck\n{}\n```\nOutput:\n```{}\n```", - input, v - )) - .author(|a| { - a.name(&message.author.name) - .icon_url(message.author.avatar_url().unwrap()) - }) - .colour(0xffd1dc) + let _ = message + .channel_id + .send_message(&ctx.http, |m| { + m.embed(|e| { + e.title("Brainfuck interpreter") + .description(format!( + "Input\n```brainfuck\n{}\n```\nOutput:\n```{}\n```", + input, v + )) + .author(|a| { + a.name(&message.author.name) + .icon_url(message.author.avatar_url().unwrap()) + }) + .colour(0xffd1dc) + }) }) - }); + .await; } Err(err) => { - let _ = message.channel_id.send_message(&ctx.http, |m| { - m.embed(|e| { - e.title("Brainfuck interpreter") - .description(format!("Error at:\n```\n{}:{}\n```", err.line(), err.col())) - .author(|a| { - a.name(&message.author.name) - .icon_url(message.author.avatar_url().unwrap()) - }) - .colour(0xff6961) + let _ = message + .channel_id + .send_message(&ctx.http, |m| { + m.embed(|e| { + e.title("Brainfuck interpreter") + .description(format!( + "Error at:\n```\n{}:{}\n```", + err.line(), + err.col() + )) + .author(|a| { + a.name(&message.author.name) + .icon_url(message.author.avatar_url().unwrap()) + }) + .colour(0xff6961) + }) }) - }); + .await; } } diff --git a/src/commands/define.rs b/src/commands/define.rs index e376416..52db49a 100644 --- a/src/commands/define.rs +++ b/src/commands/define.rs @@ -1,5 +1,5 @@ use serenity::{ - framework::standard::{macros::command, Args, CommandError, CommandResult}, + framework::standard::{macros::command, Args, CommandResult}, model::channel::Message, prelude::*, }; @@ -7,30 +7,33 @@ use serenity::{ // Urban Dictionary lookup #[command] #[aliases("what's this")] -fn define(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { +async fn define(ctx: &Context, message: &Message, args: Args) -> CommandResult { let text: String = args.rest().trim().to_string(); let defs = &urbandict::get_definitions(&text); if !args.is_empty() { match defs { Err(_e) => { - return Err(CommandError(s!("Invalid query >w<"))); + return Err("Invalid query >w<".into()); } Ok(v) => { if !v.is_empty() { let def = &v[0]; - let _ = message.channel_id.send_message(&ctx.http, |m| { - m.embed(|e| { - e.title(format!("Query: {}, Author: {}", text, def.author)) - .field( - "Definition: ", - def.definition.replace(|c| c == '[' || c == ']', ""), - false, - ) - .color(0xffd1dc) + let _ = message + .channel_id + .send_message(&ctx.http, |m| { + m.embed(|e| { + e.title(format!("Query: {}, Author: {}", text, def.author)) + .field( + "Definition: ", + def.definition.replace(|c| c == '[' || c == ']', ""), + false, + ) + .color(0xffd1dc) + }) }) - }); + .await; } else { - return Err(CommandError(s!("No results!"))); + return Err("No results!".into()); } } } diff --git a/src/commands/embed.rs b/src/commands/embed.rs index 4b48344..0b3aa1e 100644 --- a/src/commands/embed.rs +++ b/src/commands/embed.rs @@ -1,10 +1,10 @@ use serenity::{ - framework::standard::{macros::command, Args, CommandError, CommandResult}, + framework::standard::{macros::command, Args, CommandResult}, model::channel::Message, prelude::*, }; #[command] -fn embed(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { +async fn embed(ctx: &Context, message: &Message, args: Args) -> CommandResult { use serde::Deserialize; use serenity::utils::Colour; use std::{fs, io::prelude::*}; @@ -29,7 +29,7 @@ fn embed(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { let mut help_string = String::new(); file.read_to_string(&mut help_string)?; - let _ = message.channel_id.say(&ctx.http, help_string); + let _ = message.channel_id.say(&ctx.http, help_string).await; return Ok(()); } @@ -37,82 +37,86 @@ fn embed(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { let input_embed: EmbedProperties = match toml::from_str(&args.rest().trim()) { Ok(v) => v, Err(e) => { - return Err(CommandError(format!("Deserialization error: {:?}", e))); + return Err(format!("Deserialization error: {:?}", e).into()); } }; - let _ = message.channel_id.send_message(&ctx.http, |m| { - m.embed(|e| { - // Set embed author unless empty - if input_embed.author.is_some() { - let auth = input_embed.author.unwrap(); - e.author(|a| { - //assuming first array element is name and second is icon url - a.name(auth.0); - a.icon_url(auth.1); + let _ = message + .channel_id + .send_message(&ctx.http, |m| { + m.embed(|e| { + // Set embed author unless empty + if input_embed.author.is_some() { + let auth = input_embed.author.unwrap(); + e.author(|a| { + //assuming first array element is name and second is icon url + a.name(auth.0); + a.icon_url(auth.1); - a - }); - } + a + }); + } - // Set embed colour unless empty - if input_embed.colour.is_some() { - e.color(Colour::new( - u32::from_str_radix(&input_embed.colour.unwrap(), 16) - .ok() - .unwrap_or(0x000000), - )); - } + // Set embed colour unless empty + if input_embed.colour.is_some() { + e.color(Colour::new( + u32::from_str_radix(&input_embed.colour.unwrap(), 16) + .ok() + .unwrap_or(0x000000), + )); + } - // Set embed description unless empty - if input_embed.description.is_some() { - e.description(input_embed.description.unwrap()); - } - // Set embed fields unless empty - if input_embed.fields.is_some() { - e.fields(input_embed.fields.unwrap()); - } + // Set embed description unless empty + if input_embed.description.is_some() { + e.description(input_embed.description.unwrap()); + } + // Set embed fields unless empty + if input_embed.fields.is_some() { + e.fields(input_embed.fields.unwrap()); + } - // Set embed footer unless empty - if input_embed.footer.is_some() { - let foot = input_embed.footer.unwrap(); - e.footer(|f| { - //assuming first array element is name and second is icon url - f.text(foot.0); - f.icon_url(foot.1); + // Set embed footer unless empty + if input_embed.footer.is_some() { + let foot = input_embed.footer.unwrap(); + e.footer(|f| { + //assuming first array element is name and second is icon url + f.text(foot.0); + f.icon_url(foot.1); - f - }); - } + f + }); + } - if input_embed.image.is_some() { - e.image(input_embed.image.unwrap()); - } + if input_embed.image.is_some() { + e.image(input_embed.image.unwrap()); + } - if input_embed.thumbnail.is_some() { - e.thumbnail(input_embed.thumbnail.unwrap()); - } + if input_embed.thumbnail.is_some() { + e.thumbnail(input_embed.thumbnail.unwrap()); + } - if input_embed.timestamp.is_some() { - e.timestamp(input_embed.timestamp.unwrap()); - } + if input_embed.timestamp.is_some() { + e.timestamp(input_embed.timestamp.unwrap()); + } - if input_embed.title.is_some() { - e.title(input_embed.title.unwrap()); - } + if input_embed.title.is_some() { + e.title(input_embed.title.unwrap()); + } - if input_embed.url.is_some() { - e.url(input_embed.url.unwrap()); - } + if input_embed.url.is_some() { + e.url(input_embed.url.unwrap()); + } - e - }); - m - }); + e + }); + m + }) + .await; let _ = message .channel_id - .say(&ctx.http, format!("Embed requested by: {}", message.author)); + .say(&ctx.http, format!("Embed requested by: {}", message.author)) + .await; Ok(()) } diff --git a/src/commands/emote.rs b/src/commands/emote.rs index 223d8a3..643c65a 100644 --- a/src/commands/emote.rs +++ b/src/commands/emote.rs @@ -1,6 +1,6 @@ use regex::Regex; use serenity::{ - framework::standard::{macros::command, Args, CommandError, CommandResult}, + framework::standard::{macros::command, Args, CommandResult}, model::channel::Message, prelude::*, utils::parse_emoji, @@ -8,29 +8,24 @@ use serenity::{ #[command] #[aliases("e")] -fn emote(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { +async fn emote(ctx: &Context, message: &Message, args: Args) -> CommandResult { let input = match args.rest().trim() { "" => { - return Err(CommandError(s!("Called without input!"))); + return Err("Called without input!".into()); } v => v, }; - dbg!(input); - let re = Regex::new(r"").unwrap(); let emojis = match re.captures(input) { None => { - return Err(CommandError(s!("No custom emojis found in the message!"))); + return Err("No custom emojis found in the message!".into()); } Some(v) => v, }; - dbg!(&emojis); - let url = parse_emoji(&emojis[0]).unwrap().url(); - - let _ = message.channel_id.say(&ctx.http, url); + let _ = message.channel_id.say(&ctx.http, url).await; Ok(()) } diff --git a/src/commands/help.rs b/src/commands/help.rs index a2d2779..311d510 100644 --- a/src/commands/help.rs +++ b/src/commands/help.rs @@ -5,53 +5,56 @@ use serenity::{ }; #[command] -fn help(ctx: &mut Context, message: &Message) -> CommandResult { - let _ = message.channel_id.send_message(&ctx.http, |m| { - m.embed(|e| { - e.title("Availble commands:") - .description("All commands are case-insensitive") - .fields(vec![ - ("owo!init", "Introduce me", true), - ("owo!ping", "Pong", true), - ("owo!sausage", "Sosig", true), - ("owo!help", "Help the fellow humanz!", true), - ("owo!info", "Show information about me!", true), - ( - "owo!what's this ``word``", - "Find a definition of word", - true, - ), - ( - "owo!embed ``[args]`` *OR* help", - "Create an embed from a Toml object", - true, - ), - ("owo!desc", "Display channel's topic", true), - ( - "owo!pinned ``num`` ````", - "Display channel's Nth pinned message. Channel name is optional", - true, - ), - ("owo!pfp ``@username``", "Post user's profile picture", true), - ("owo!brainfuck ``input``", "Execute input code", true), - ("owo!ship ``[names]``", "*Shipping intensifies*", true), - ("owo!headpat ``name``", "Headpat someone", true), - ("owo!owo ``text``", "owoify input text", true), - ("owo!lyrics ``name``", "Get song lyrics", true), - ( - "owo!e ``emote``", - "Get a bigger version of a custom emote", - true, - ), - ("\u{200B}", "**Admin commands:**", false), - ("owo!halt", "Kill the bot process", true), - ("owo!status ``[args]``", "Sets the bot status", true), - ("owo!servers", "List the servers I'm in", true), - ("owo!host", "Display host info", true), - ]) - .color(0xffd1dc) +async fn help(ctx: &Context, message: &Message) -> CommandResult { + let _ = message + .channel_id + .send_message(&ctx.http, |m| { + m.embed(|e| { + e.title("Availble commands:") + .description("All commands are case-insensitive") + .fields(vec![ + ("owo!init", "Introduce me", true), + ("owo!ping", "Pong", true), + ("owo!sausage", "Sosig", true), + ("owo!help", "Help the fellow humanz!", true), + ("owo!info", "Show information about me!", true), + ( + "owo!what's this ``word``", + "Find a definition of word", + true, + ), + ( + "owo!embed ``[args]`` *OR* help", + "Create an embed from a Toml object", + true, + ), + ("owo!desc", "Display channel's topic", true), + ( + "owo!pinned ``num`` ````", + "Display channel's Nth pinned message. Channel name is optional", + true, + ), + ("owo!pfp ``@username``", "Post user's profile picture", true), + ("owo!brainfuck ``input``", "Execute input code", true), + ("owo!ship ``[names]``", "*Shipping intensifies*", true), + ("owo!headpat ``name``", "Headpat someone", true), + ("owo!owo ``text``", "owoify input text", true), + ("owo!lyrics ``name``", "Get song lyrics", true), + ( + "owo!e ``emote``", + "Get a bigger version of a custom emote", + true, + ), + ("\u{200B}", "**Admin commands:**", false), + ("owo!halt", "Kill the bot process", true), + ("owo!status ``[args]``", "Sets the bot status", true), + ("owo!servers", "List the servers I'm in", true), + ("owo!host", "Display host info", true), + ]) + .color(0xffd1dc) + }) }) - }); + .await; Ok(()) } diff --git a/src/commands/lyrics.rs b/src/commands/lyrics.rs index f35714f..12e9733 100644 --- a/src/commands/lyrics.rs +++ b/src/commands/lyrics.rs @@ -1,10 +1,11 @@ use percent_encoding::{percent_encode, NON_ALPHANUMERIC}; use serde::Deserialize; use serenity::{ - framework::standard::{macros::command, Args, CommandError, CommandResult}, + framework::standard::{macros::command, Args, CommandResult}, model::channel::Message, prelude::*, }; +use std::env; #[derive(Deserialize)] struct Response { @@ -19,35 +20,38 @@ struct Content { } #[command] -fn lyrics(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { - // the website used to get song lyrics +async fn lyrics(ctx: &Context, message: &Message, args: Args) -> CommandResult { + // TODO: use https://orion.apiseeds.com/api/music/lyric/:artist/:track instead let mut url = String::from("https://mourits.xyz:2096/?q="); // check if input is not empty let input = match args.rest().trim() { "" => { - return Err(CommandError(s!("Called without input!"))); + return Err("Called without input!".into()); } v => v, }; // encode into url url += &s!(percent_encode(input.as_bytes(), NON_ALPHANUMERIC)); - let request = match reqwest::blocking::get(&url) { + let request = match reqwest::get(&url).await { Ok(v) => v, - Err(e) => return Err(CommandError(s!(e))), + Err(e) => return Err(e.into()), }; - let resp: Response = match request.json() { + let resp: Response = match request.json().await { Ok(v) => v, - Err(_) => return Err(CommandError(s!("Could not find lyrics"))), + Err(_) => return Err("Could not find lyrics".into()), }; - let _ = message.channel_id.send_message(&ctx.http, |m| { - m.embed(|e| { - e.title(format!("{} by {}", resp.song, resp.artist)) - .description(resp.result.lyrics) - .colour(0xffd1dc) + let _ = message + .channel_id + .send_message(&ctx.http, |m| { + m.embed(|e| { + e.title(format!("{} by {}", resp.song, resp.artist)) + .description(resp.result.lyrics) + .colour(0xffd1dc) + }) }) - }); + .await; Ok(()) } diff --git a/src/commands/pinned.rs b/src/commands/pinned.rs index a6de9ae..1f0bf8f 100644 --- a/src/commands/pinned.rs +++ b/src/commands/pinned.rs @@ -1,73 +1,69 @@ use serenity::{ - framework::standard::{macros::command, Args, CommandError, CommandResult}, + framework::standard::{macros::command, Args, CommandResult}, model::{channel::Message, id::ChannelId}, prelude::*, }; // Prints Nth pinned message #[command] -fn pinned(ctx: &mut Context, message: &Message, mut args: Args) -> CommandResult { +#[only_in(guilds)] +async fn pinned(ctx: &Context, message: &Message, mut args: Args) -> CommandResult { // defaults to latest pinned message if no args are provided let mut idx = args.single::().unwrap_or(1); // Makes pinned messages 1-indexed if idx != 0 { idx -= 1; } + let target_channel = match args.single::() { Ok(v) => v, Err(_) => message.channel_id, }; - let pinned = match target_channel.pins(&ctx.http) { + let pinned = match target_channel.pins(&ctx.http).await { Ok(v) => v, Err(e) => { - return Err(CommandError(s!(format!( - "Could not get pinned messages! Error: {}", - e - )))); + return Err(format!("Could not get pinned messages! Error: {}", e).into()); } }; if pinned.is_empty() { - return Err(CommandError(s!("No pinned messages found!"))); + return Err("No pinned messages found!".into()); } if idx > pinned.len() - 1 { - return Err(CommandError(s!("Index out of bounds!"))); + return Err("Index out of bounds!".into()); } - let channel = match pinned[idx].channel(&ctx) { - Some(g) => g, - None => return Err(CommandError(s!("Could not get Channel"))), + let guild_id = match message.guild_id { + Some(id) => id, + None => return Err("Could not find Guild Id".into()), }; - let guild_arc = match channel.guild() { - Some(a) => a, - None => return Err(CommandError(s!("Could not find Guild Arc"))), - }; - let guild = guild_arc.read(); - let guild_id = guild.guild_id; - let msg_link = format!( - "https://discordapp.com/channels/{}/{}/{}", + "https://discord.com/channels/{}/{}/{}", guild_id, &pinned[idx].channel_id, &pinned[idx].id ); - let _ = message.channel_id.send_message(&ctx.http, |m| { - m.embed(|e| { - e.title(format!("Pinned message #{}", idx + 1)) - .description(&pinned[idx].content) - .field("🔗 link", format!("[original message]({})", msg_link), true) - .timestamp(&pinned[idx].timestamp); - e.author(|a| { - a.name(&pinned[idx].author.name) - .icon_url(&pinned[idx].author.avatar_url().unwrap()) - }); - e.colour(0xffd1dc); - if !&pinned[idx].attachments.is_empty() { - e.image(&pinned[idx].attachments[0].url); - } + // TODO: change link formatting + let _ = message + .channel_id + .send_message(&ctx.http, |m| { + m.embed(|e| { + e.title(format!("Pinned message #{}", idx + 1)) + .description(&pinned[idx].content) + .field("🔗 link", format!("[original message]({})", msg_link), true) + .timestamp(&pinned[idx].timestamp); + e.author(|a| { + a.name(&pinned[idx].author.name) + .icon_url(&pinned[idx].author.avatar_url().unwrap()) + }); + e.colour(0xffd1dc); + if !&pinned[idx].attachments.is_empty() { + e.image(&pinned[idx].attachments[0].url); + } - e + e + }) }) - }); + .await; Ok(()) } diff --git a/src/commands/ship.rs b/src/commands/ship.rs index 41c2bd6..6abdba9 100644 --- a/src/commands/ship.rs +++ b/src/commands/ship.rs @@ -7,7 +7,7 @@ use serenity::{ }; #[command] -fn ship(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { +async fn ship(ctx: &Context, message: &Message, args: Args) -> CommandResult { use rand::{rngs::StdRng, SeedableRng}; // Get input names @@ -42,20 +42,23 @@ fn ship(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { }; if let Err(e) = shipname { - let _ = message.channel_id.say(&ctx.http, e); + let _ = message.channel_id.say(&ctx.http, e).await; } else { - let _ = message.channel_id.send_message(&ctx.http, |m| { - m.embed(|e| { - e.title(format!("Original names: {}", args.rest().trim())) - .description(format!( - "Ship name:\n**{}**\nCompatibility: **{}%**\n{}", - shipname.unwrap(), - compat, - compbar - )) - .color(0xffd1dc) + let _ = message + .channel_id + .send_message(&ctx.http, |m| { + m.embed(|e| { + e.title(format!("Original names: {}", args.rest().trim())) + .description(format!( + "Ship name:\n**{}**\nCompatibility: **{}%**\n{}", + shipname.unwrap(), + compat, + compbar + )) + .color(0xffd1dc) + }) }) - }); + .await; } Ok(()) diff --git a/src/main.rs b/src/main.rs index 2fd3bb2..3d34381 100755 --- a/src/main.rs +++ b/src/main.rs @@ -7,16 +7,21 @@ extern crate lazy_static; use colored::*; use rand::Rng; use serenity::{ + async_trait, client::{ - bridge::gateway::{ShardId, ShardManager}, + bridge::gateway::{GatewayIntents, ShardId, ShardManager}, Client, }, framework::standard::{ - macros::{check, command, group}, - Args, CheckResult, CommandError, CommandOptions, CommandResult, DispatchError, Reason, - StandardFramework, + macros::{check, command, group, hook}, + Args, CheckResult, CommandOptions, CommandResult, DispatchError, Reason, StandardFramework, + }, + model::{ + channel::{Message, ReactionType}, + gateway::Ready, + id::UserId, + user::OnlineStatus, }, - model::{channel::Message, gateway::Ready, id::UserId, user::OnlineStatus}, prelude::*, }; use std::{env, process, sync::Arc}; @@ -38,8 +43,9 @@ impl TypeMapKey for ShardManagerContainer { type Value = Arc>; } +#[async_trait] impl EventHandler for Handler { - fn ready(&self, ctx: Context, ready: Ready) { + async fn ready(&self, ctx: Context, ready: Ready) { if let Some(shard) = ready.shard { println!( "INFO: {} is connected on shard {}/{}!\nuwu", @@ -50,16 +56,64 @@ impl EventHandler for Handler { let activity = Activity::listening("catgirls nyaaing"); let status = OnlineStatus::Online; - ctx.set_presence(Some(activity), status); + ctx.set_presence(Some(activity), status).await; } } - fn message(&self, ctx: Context, message: Message) { + async fn message(&self, ctx: Context, message: Message) { let text = &message.content.to_lowercase(); if text.contains("good") && (text.contains("discordinator") || text.contains("discordinyator")) { - let _ = message.channel_id.say(&ctx.http, "nyaa~ 💞"); + let _ = message.channel_id.say(&ctx.http, "nyaa~ 💞").await; + } + } +} + +#[hook] +async fn dispatch_error(ctx: &Context, msg: &Message, error: DispatchError) { + if let DispatchError::CheckFailed("Owner", Reason::Unknown) = error { + // triggers if user is not owner + let _ = msg.channel_id.say(&ctx.http, "nyo").await; + } else if let DispatchError::Ratelimited(_) = error { + // triggers if rate limited + eprintln!( + "{}", + format!( + "Rate limited in {} with message {}", + s!(msg.channel_id).purple().bold(), + msg.content.purple() + ) + ); + } +} + +#[hook] +async fn after(ctx: &Context, msg: &Message, command_name: &str, command_result: CommandResult) { + // prints error in chat + match command_result { + Ok(()) => (), + Err(why) => { + let _ = msg + .channel_id + .send_message(&ctx.http, |m| { + m.embed(|e| { + e.title(format!("Error in **{}**", command_name)) + .description(&why.to_string()) + /*.thumbnail("https://i.imgur.com/VzOEz2E.png") oh no */ + .colour(0xff6961) + }) + }) + .await; + // prints error in console + eprintln!( + "{}", + format!( + "Error in {}: {}", + command_name.purple(), + &why.to_string().red().bold() + ) + ); } } } @@ -77,71 +131,46 @@ lazy_static! { vec![UserId(254310746450690048), UserId(687740609703706630)]; } -fn main() { - let mut client = Client::new(&env::var("DISCORD_TOKEN").expect("Invalid token"), Handler) +#[tokio::main] +async fn main() { + let framework = StandardFramework::new() + .configure(|c| { + c.with_whitespace(true) + .owners(OWNERS.clone().into_iter().collect()) + .prefixes(vec!["owo!", "OwO!", "aga"]) + .no_dm_prefix(true) + .case_insensitivity(true) + .by_space(false) + }) + .group(&GENERAL_GROUP) + .on_dispatch_error(dispatch_error) + .after(after); + + let mut client = Client::builder(&env::var("DISCORD_TOKEN").expect("Invalid token")) + .event_handler(Handler) + .framework(framework) + .intents({ + let mut intents = GatewayIntents::all(); + intents.remove(GatewayIntents::GUILD_PRESENCES); + intents + }) + .await .expect("Error creating client"); // Updates stored data, used for ping command { - let mut data = client.data.write(); + let mut data = client.data.write().await; data.insert::(Arc::clone(&client.shard_manager)); } - client.with_framework( - StandardFramework::new() - .configure(|c| { - c.with_whitespace(true) - .owners(OWNERS.clone().into_iter().collect()) - .prefixes(vec!["owo!", "OwO!", "aga"]) - .no_dm_prefix(true) - .case_insensitivity(true) - .by_space(false) - }) - .on_dispatch_error(|ctx, msg, error| { - if let DispatchError::CheckFailed("Owner", Reason::Unknown) = error { - // triggers if user is not owner - let _ = msg.channel_id.say(&ctx.http, "nyo"); - } else if let DispatchError::Ratelimited(_) = error { - // triggers if rate limited - eprintln!( - "{}", - format!( - "Rate limited in {} with message {}", - s!(msg.channel_id).purple().bold(), - msg.content.purple() - ) - ); - } - }) - .after(|ctx, msg, cmd_name, error| { - // prints error in chat - if let Err(why) = error { - let _ = msg.channel_id.send_message(&ctx.http, |m| { - m.embed(|e| { - e.title(format!("Error in **{}**", cmd_name)) - .description(&why.0) - /*.thumbnail("https://i.imgur.com/VzOEz2E.png") oh no */ - .colour(0xff6961) - }) - }); - // prints error in console - eprintln!( - "{}", - format!("Error in {}: {}", cmd_name.purple(), &why.0.red().bold()) - ); - } - }) - .group(&GENERAL_GROUP), - ); - - if let Err(e) = client.start() { + if let Err(e) = client.start().await { eprintln!("An error occurred while running the client: {:?}", e); } } #[check] #[name = "Owner"] -fn owner_check(_: &mut Context, msg: &Message, _: &mut Args, _: &CommandOptions) -> CheckResult { +async fn owner_check(_: &Context, msg: &Message, _: &mut Args, _: &CommandOptions) -> CheckResult { if OWNERS.clone().contains(&msg.author.id) { CheckResult::Success } else { @@ -151,75 +180,72 @@ fn owner_check(_: &mut Context, msg: &Message, _: &mut Args, _: &CommandOptions) #[check] #[name = "Server"] -fn server_check(_: &mut Context, msg: &Message, _: &mut Args, _: &CommandOptions) -> CheckResult { +async fn server_check(_: &Context, msg: &Message, _: &mut Args, _: &CommandOptions) -> CheckResult { (msg.guild_id == Some(serenity::model::id::GuildId(687011389294116875))).into() } #[command] -fn init(ctx: &mut Context, message: &Message) -> CommandResult { +async fn init(ctx: &Context, message: &Message) -> CommandResult { let responses = [ "Discordinator9000 is gonna hug nya'll!", "Nyaa~!", "Hewwo uwu", ]; let num = rand::thread_rng().gen_range(0, responses.len()); - let _ = message.channel_id.say(&ctx.http, responses[num]); + let _ = message.channel_id.say(&ctx.http, responses[num]).await; Ok(()) } #[command] -fn ping(ctx: &mut Context, message: &Message) -> CommandResult { +async fn ping(ctx: &Context, message: &Message) -> CommandResult { // I have no idea if this works but its 5æm and I need to sleep help - let data = ctx.data.read(); + let data = ctx.data.read().await; let shard_manager = match data.get::() { Some(v) => v, - None => { - return Err(CommandError(s!( - "There was a problem getting the shard manager!" - ))) - } + None => return Err("There was a problem getting the shard manager!".into()), }; - let manager = shard_manager.lock(); - let runners = manager.runners.lock(); + let manager = shard_manager.lock().await; + let runners = manager.runners.lock().await; let runner = match runners.get(&ShardId(ctx.shard_id)) { Some(v) => v, - None => return Err(CommandError(s!("No shard found!"))), + None => return Err("No shard found!".into()), }; let ping = match runner.latency { Some(v) => v.as_millis(), - None => return Err(CommandError(s!("Could not get latency!"))), + None => return Err("Could not get latency!".into()), }; let _ = message .channel_id - .say(&ctx, format!("Pong! Latency: {}ms", ping)); + .say(&ctx, format!("Pong! Latency: {}ms", ping)) + .await; Ok(()) } #[command] #[checks(Owner)] -fn echo(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { +async fn echo(ctx: &Context, message: &Message, args: Args) -> CommandResult { let input: String = args.rest().trim().to_string(); if args.is_empty() { - return Err(CommandError(s!("Called without input"))); + return Err("Called without input".into()); } - let _ = message.channel_id.say(&ctx.http, input); + let _ = message.channel_id.say(&ctx.http, input).await; Ok(()) } #[command] #[checks(Owner)] -fn halt(ctx: &mut Context) -> CommandResult { +async fn halt(ctx: &Context) -> CommandResult { // Workaround for discord not doing this automatically - ctx.set_presence(None, OnlineStatus::Offline); + ctx.set_presence(None, OnlineStatus::Offline).await; use std::{thread, time}; // Sleep for 1s @@ -231,11 +257,11 @@ fn halt(ctx: &mut Context) -> CommandResult { // set bot's status to input text #[command] #[checks(Owner)] -fn status(ctx: &mut Context, message: &Message, mut args: Args) -> CommandResult { +async fn status(ctx: &Context, message: &Message, mut args: Args) -> CommandResult { use serenity::model::gateway::Activity; if args.is_empty() { - return Err(CommandError(s!("Called without args!"))); + return Err("Called without args!".into()); } let mut input = args.single::()?; @@ -256,60 +282,70 @@ fn status(ctx: &mut Context, message: &Message, mut args: Args) -> CommandResult }; let status = OnlineStatus::Online; - ctx.set_presence(Some(activity), status); - let _ = message.react(&ctx.http, "💜"); + ctx.set_presence(Some(activity), status).await; + let _ = message + .react(&ctx.http, ReactionType::Unicode("💜".into())) + .await; Ok(()) } #[command] #[checks(Owner)] -fn servers(ctx: &mut Context, message: &Message) -> CommandResult { +async fn servers(ctx: &Context, message: &Message) -> CommandResult { let mut list = String::new(); - let cache = ctx.cache.read(); - for (index, guild_lock) in cache.guilds.values().enumerate() { - let guild = guild_lock.read(); - list += &format!("{}: {}\n", index, guild.name); + let cache = &ctx.cache; + for (index, guild) in cache.guilds().await.iter().enumerate() { + let name = guild + .name(&ctx.cache) + .await + .unwrap_or_else(|| s!("unknown")); + list += &format!("{}: {}\n", index, name); } let _ = message .channel_id // Add zero width space to all mentions - .say(&ctx.http, list.replace("@", "@\u{200B}")); + .say(&ctx.http, list.replace("@", "@\u{200B}")) + .await; Ok(()) } #[command] #[checks(Owner)] -fn host(ctx: &mut Context, message: &Message) -> CommandResult { - let _ = message.channel_id.say( - &ctx.http, - format!( - "OS: {os}; {release}\nHost: {host}\nCPU: {cpu}MHz", - os = sys_info::os_type()?, - host = sys_info::hostname()?, - release = sys_info::linux_os_release()? - .pretty_name - .unwrap_or_else(|| s!("Unknown")), - cpu = sys_info::cpu_speed()? - ), - ); +async fn host(ctx: &Context, message: &Message) -> CommandResult { + let _ = message + .channel_id + .say( + &ctx.http, + format!( + "OS: {os}; {release}\nHost: {host}\nCPU: {cpu}MHz", + os = sys_info::os_type()?, + host = sys_info::hostname()?, + release = sys_info::linux_os_release()? + .pretty_name + .unwrap_or_else(|| s!("Unknown")), + cpu = sys_info::cpu_speed()? + ), + ) + .await; Ok(()) } // generate a random number using a keysmash as seed #[command] -fn bottom_rng(ctx: &mut Context, message: &Message, mut args: Args) -> CommandResult { +async fn bottom_rng(ctx: &Context, message: &Message, mut args: Args) -> CommandResult { use rand::{rngs::StdRng, SeedableRng}; // get N last messages, otherwise 10 let num = args.single::().unwrap_or(10); let messages = message .channel_id - .messages(&ctx.http, |get| get.before(message.id).limit(num)); + .messages(&ctx.http, |get| get.before(message.id).limit(num)) + .await; if let Err(e) = messages { - return Err(CommandError(s!(format!("Error: {}", e)))); + return Err(format!("Error: {}", e).into()); } else { let mut messages = messages?; // remove all messages by other users @@ -319,13 +355,16 @@ fn bottom_rng(ctx: &mut Context, message: &Message, mut args: Args) -> CommandRe input += &format!("{} ", msg.content); } let result: u64 = StdRng::seed_from_u64(calculate_hash(&input)).gen_range(0, 100); - let _ = message.channel_id.send_message(&ctx.http, |m| { - m.embed(|e| { - e.title("Bottom RNG") - .description(format!("Result: {}", result)) - .color(0x800869) + let _ = message + .channel_id + .send_message(&ctx.http, |m| { + m.embed(|e| { + e.title("Bottom RNG") + .description(format!("Result: {}", result)) + .color(0x800869) + }) }) - }); + .await; } Ok(()) @@ -333,11 +372,11 @@ fn bottom_rng(ctx: &mut Context, message: &Message, mut args: Args) -> CommandRe #[command] #[aliases("pat")] -fn headpat(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { +async fn headpat(ctx: &Context, message: &Message, args: Args) -> CommandResult { let args = args.rest().trim(); if args.is_empty() { - return Err(CommandError(s!("Please specify a username!"))); + return Err("Please specify a username!".into()); } // Get username from first mention, otherwise use input text @@ -346,16 +385,20 @@ fn headpat(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { _ => message.mentions[0].name.as_str(), }; - if let Err(e) = message.channel_id.send_message(&ctx.http, |m| { - m.embed(|e| { - e.title(format!("Sending headpats to **{}**...", name)) + if let Err(e) = message + .channel_id + .send_message(&ctx.http, |m| { + m.embed(|e| { + e.title(format!("Sending headpats to **{}**...", name)) .image( "https://i.pinimg.com/originals/83/1a/90/831a903eab6d827dcfd298b9e3196e30.jpg", ) .description("[Source](https://www.pinterest.com/pin/377809856242075277/)") + }) }) - }) { - let _ = message.channel_id.say(&ctx.http, format!("{:?}", e)); + .await + { + let _ = message.channel_id.say(&ctx.http, format!("{:?}", e)).await; }; Ok(()) @@ -363,7 +406,7 @@ fn headpat(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { // send a random uwu image #[command] -fn uwu(ctx: &mut Context, message: &Message) -> CommandResult { +async fn uwu(ctx: &Context, message: &Message) -> CommandResult { let images = [ "https://i.redditmedia.com/qDD9W7NJqTAk31y061TuRW9R8qOcCuEmmCWyOsUEavE.png?fit=crop&crop=faces%2Centropy&arh=2&w=640&s=ebdd3f1970b4fe70ccd24a1958e7fc32", "https://www.shitpostbot.com/img/sourceimages/smash-that-mfuckn-uwu-button-57b5aa1de9fe4.jpeg", @@ -377,59 +420,65 @@ fn uwu(ctx: &mut Context, message: &Message) -> CommandResult { "https://i.redd.it/ifwsmbme48q41.jpg" ]; let num = rand::thread_rng().gen_range(0, images.len()); - let _ = message.channel_id.send_message(&ctx.http, |m| { - m.embed(|e| { - e.image(images[num]); - e.footer(|f| f.text(format!("Source: {}", images[num]))); + let _ = message + .channel_id + .send_message(&ctx.http, |m| { + m.embed(|e| { + e.image(images[num]); + e.footer(|f| f.text(format!("Source: {}", images[num]))); - e + e + }) }) - }); + .await; Ok(()) } #[command] -fn gayculator(ctx: &mut Context, message: &Message, mut args: Args) -> CommandResult { +async fn gayculator(ctx: &Context, message: &Message, mut args: Args) -> CommandResult { let number_32: i32 = args.single::().unwrap_or(1); let result = if number_32 % 2 == 0 { "much straight" } else { "large gay" }; - let _ = message.channel_id.send_message(&ctx.http, |m| { - m.embed(|e| { - e.title("Gayness level:") - .description(result) - .color(0xffd1dc) + let _ = message + .channel_id + .send_message(&ctx.http, |m| { + m.embed(|e| { + e.title("Gayness level:") + .description(result) + .color(0xffd1dc) + }) }) - }); + .await; Ok(()) } #[command] #[aliases("sosig")] -fn sausage(ctx: &mut Context, message: &Message) -> CommandResult { +async fn sausage(ctx: &Context, message: &Message) -> CommandResult { let _ = message.channel_id.send_message(&ctx.http, |m| { m.embed(|e| { e .title("Dongle!") .image("https://cdn.discordapp.com/attachments/689023662489468966/712283397015470120/26029881886330_4.gif") }) - }); + }).await; Ok(()) } #[command] -fn info(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { +async fn info(ctx: &Context, message: &Message, args: Args) -> CommandResult { if !args.is_empty() { - return Err(CommandError(s!("Called with args!"))); + return Err("Called with args!".into()); } - let num = ctx.cache.read().guilds.len(); + let num = ctx.cache.guilds().await.len(); // get developer's username - let aganame = OWNERS.clone()[0].to_user(ctx.http.clone())?.tag(); + let aganame = OWNERS.clone()[0].to_user(ctx.http.clone()).await?.tag(); let _ = message.channel_id.send_message(&ctx.http, |m| m .embed(|e| e .title("Discordinator9000's info:") @@ -441,12 +490,12 @@ fn info(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { .text("Written in Rust using Serenity, OwOify and a few other libraries")) .thumbnail("https://cdn.discordapp.com/attachments/687011390434967621/704118007563157544/discordinator.png") .color(0xffd1dc) - )); + )).await; Ok(()) } #[command] -fn pfp(ctx: &mut Context, message: &Message) -> CommandResult { +async fn pfp(ctx: &Context, message: &Message) -> CommandResult { // Get username from first mention, otherwise use current username let user = match message.mentions.len() { 0 => &message.author, @@ -455,31 +504,35 @@ fn pfp(ctx: &mut Context, message: &Message) -> CommandResult { let pfp = match user.avatar_url() { Some(v) => v, - None => return Err(CommandError(s!("The user does not have an avatar"))), + None => return Err("The user does not have an avatar".into()), }; - let _ = message.channel_id.send_message(&ctx.http, |m| { - m.embed(|e| { - e.title(format!("{}'s profile picture", user.name)) - .image(pfp) - .color(0xffd1dc) + let _ = message + .channel_id + .send_message(&ctx.http, |m| { + m.embed(|e| { + e.title(format!("{}'s profile picture", user.name)) + .image(pfp) + .color(0xffd1dc) + }) }) - }); + .await; Ok(()) } // Text owoification #[command] -fn owo(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { +async fn owo(ctx: &Context, message: &Message, args: Args) -> CommandResult { use owoify::OwOifiable; let lastmsg = match message .channel_id .messages(&ctx.http, |get| get.before(message.id).limit(1)) + .await { Ok(v) => v, - Err(_) => return Err(CommandError(s!("Could not get last message!"))), + Err(_) => return Err("Could not get last message!".into()), }; let lastmsg = &lastmsg[0].content; @@ -488,28 +541,28 @@ fn owo(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { true => s!(lastmsg), false => args.rest().trim().to_string(), }; - let _ = message.channel_id.say(&ctx.http, input.owoify()); + let _ = message.channel_id.say(&ctx.http, input.owoify()).await; Ok(()) } // Prints channel topic #[command] +#[only_in(guilds)] #[aliases("description", "topic")] -fn desc(ctx: &mut Context, message: &Message) -> CommandResult { - let channel_lock = match message.channel(&ctx) { +async fn desc(ctx: &Context, message: &Message) -> CommandResult { + let channel = match message.channel(&ctx).await { Some(ch) => ch, None => { - return Err(CommandError(s!("Could not get channel!"))); + return Err("Could not get channel!".into()); } }; - let channel_lock = match channel_lock.guild() { + let channel = match channel.guild() { Some(g) => g, None => { - return Err(CommandError(s!("Could not get guild!"))); + return Err("Could not get guild channel!".into()); } }; - let channel = channel_lock.read(); let topic = if channel.topic.clone().unwrap() != "" { channel.topic.clone().unwrap() @@ -517,13 +570,16 @@ fn desc(ctx: &mut Context, message: &Message) -> CommandResult { String::from("No channel topic found") }; - let _ = message.channel_id.send_message(&ctx.http, |m| { - m.embed(|e| { - e.title("Channel's topic:") - .description(topic) - .color(0xffd1dc) + let _ = message + .channel_id + .send_message(&ctx.http, |m| { + m.embed(|e| { + e.title("Channel's topic:") + .description(topic) + .color(0xffd1dc) + }) }) - }); + .await; Ok(()) }