From 46c6a25164e6ca831fd3fc27330603a1ce78c5de Mon Sep 17 00:00:00 2001 From: Louis Hollingworth Date: Sun, 29 Oct 2023 14:40:12 +0000 Subject: [PATCH] (#8) Reporting now added, admin commands are also here Signed-off-by: Louis Hollingworth --- Cargo.lock | 720 +++++++++++++++++++++++- Cargo.toml | 2 + build.rs | 9 + migrations/20231028165341_init.down.sql | 6 + migrations/20231028165341_init.up.sql | 10 + src/commands/admin.rs | 70 +++ src/commands/mod.rs | 2 + src/commands/report.rs | 44 ++ src/commands/threads.rs | 1 - src/lib.rs | 24 +- src/main.rs | 10 +- src/models/db/guild.rs | 65 +++ src/models/db/mod.rs | 5 + src/models/mod.rs | 1 + 14 files changed, 962 insertions(+), 7 deletions(-) create mode 100644 build.rs create mode 100644 migrations/20231028165341_init.down.sql create mode 100644 migrations/20231028165341_init.up.sql create mode 100644 src/commands/admin.rs create mode 100644 src/commands/report.rs create mode 100644 src/models/db/guild.rs create mode 100644 src/models/db/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 093b4ce..5bf73ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,19 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.2" @@ -29,6 +42,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -77,6 +96,15 @@ dependencies = [ "webpki-roots 0.22.6", ] +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -110,6 +138,12 @@ version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bitflags" version = "1.3.2" @@ -121,6 +155,9 @@ name = "bitflags" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +dependencies = [ + "serde", +] [[package]] name = "block-buffer" @@ -177,6 +214,12 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "const-oid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" + [[package]] name = "core-foundation" version = "0.9.3" @@ -202,6 +245,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" + [[package]] name = "crc32fast" version = "1.3.2" @@ -211,6 +269,25 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -270,6 +347,17 @@ dependencies = [ "serde", ] +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "deranged" version = "0.3.9" @@ -298,7 +386,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", + "subtle", ] [[package]] @@ -307,6 +397,15 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +dependencies = [ + "serde", +] + [[package]] name = "encoding_rs" version = "0.8.33" @@ -316,6 +415,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "er" version = "2.0.0" @@ -326,8 +431,10 @@ dependencies = [ "reqwest", "serde", "serde_json", + "sqlx", "thiserror", "tokio", + "uuid", ] [[package]] @@ -340,12 +447,35 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "fastrand" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +[[package]] +name = "finl_unicode" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" + [[package]] name = "flate2" version = "1.0.28" @@ -356,6 +486,17 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" @@ -416,6 +557,28 @@ version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +[[package]] +name = "futures-executor" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + [[package]] name = "futures-io" version = "0.3.29" @@ -502,7 +665,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.3", "slab", "tokio", "tokio-util", @@ -520,6 +683,28 @@ name = "hashbrown" version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown 0.14.2", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] [[package]] name = "hermit-abi" @@ -527,6 +712,39 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys", +] + [[package]] name = "http" version = "0.2.9" @@ -661,12 +879,31 @@ dependencies = [ "hashbrown 0.12.3", ] +[[package]] +name = "indexmap" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +dependencies = [ + "equivalent", + "hashbrown 0.14.2", +] + [[package]] name = "ipnet" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.9" @@ -687,6 +924,9 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "libc" @@ -694,6 +934,23 @@ version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libsqlite3-sys" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.4.10" @@ -716,6 +973,16 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + [[package]] name = "memchr" version = "2.6.4" @@ -738,6 +1005,12 @@ dependencies = [ "unicase", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -776,6 +1049,54 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.17" @@ -783,6 +1104,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -886,6 +1208,21 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.0" @@ -904,6 +1241,27 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.27" @@ -1114,6 +1472,26 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "rsa" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ef35bf3e7fe15a53c4ab08a998e42271eab13eb0db224126bc7bc4c4bad96d" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -1332,6 +1710,28 @@ dependencies = [ "digest", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -1341,6 +1741,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "slab" version = "0.4.9" @@ -1387,6 +1797,244 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlformat" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b7b278788e7be4d0d29c0f39497a0eef3fba6bbc8e70d8bf7fde46edeaa9e85" +dependencies = [ + "itertools", + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e50c216e3624ec8e7ecd14c6a6a6370aad6ee5d8cfc3ab30b5162eeeef2ed33" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d6753e460c998bbd4cd8c6f0ed9a64346fcca0723d6e75e52fdc351c5d2169d" +dependencies = [ + "ahash", + "atoi", + "byteorder", + "bytes", + "chrono", + "crc", + "crossbeam-queue", + "dotenvy", + "either", + "event-listener", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashlink", + "hex", + "indexmap 2.0.2", + "log", + "memchr", + "once_cell", + "paste", + "percent-encoding", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlformat", + "thiserror", + "tokio", + "tokio-stream", + "tracing", + "url", + "uuid", +] + +[[package]] +name = "sqlx-macros" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a793bb3ba331ec8359c1853bd39eed32cdd7baaf22c35ccf5c92a7e8d1189ec" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 1.0.109", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a4ee1e104e00dedb6aa5ffdd1343107b0a4702e862a84320ee7cc74782d96fc" +dependencies = [ + "dotenvy", + "either", + "heck", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", + "syn 1.0.109", + "tempfile", + "tokio", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "864b869fdf56263f4c95c45483191ea0af340f9f3e3e7b4d57a61c7c87a970db" +dependencies = [ + "atoi", + "base64 0.21.5", + "bitflags 2.4.1", + "byteorder", + "bytes", + "chrono", + "crc", + "digest", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand", + "rsa", + "serde", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "uuid", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb7ae0e6a97fb3ba33b23ac2671a5ce6e3cabe003f451abd5a56e7951d975624" +dependencies = [ + "atoi", + "base64 0.21.5", + "bitflags 2.4.1", + "byteorder", + "chrono", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand", + "serde", + "serde_json", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "uuid", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59dc83cf45d89c555a577694534fcd1b55c545a816c816ce51f20bbe56a4f3f" +dependencies = [ + "atoi", + "chrono", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "sqlx-core", + "tracing", + "url", + "uuid", +] + +[[package]] +name = "stringprep" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +dependencies = [ + "finl_unicode", + "unicode-bidi", + "unicode-normalization", +] [[package]] name = "strsim" @@ -1394,6 +2042,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + [[package]] name = "syn" version = "1.0.109" @@ -1575,6 +2229,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.10" @@ -1696,6 +2361,18 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "untrusted" version = "0.7.1" @@ -1726,6 +2403,15 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "uuid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" +dependencies = [ + "getrandom", +] + [[package]] name = "vcpkg" version = "0.2.15" @@ -1867,6 +2553,12 @@ version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" +[[package]] +name = "whoami" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" + [[package]] name = "winapi" version = "0.3.9" @@ -1973,3 +2665,29 @@ dependencies = [ "cfg-if", "windows-sys", ] + +[[package]] +name = "zerocopy" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7d7c7970ca2215b8c1ccf4d4f354c4733201dfaaba72d44ae5b37472e4901" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b27b1bb92570f989aac0ab7e9cbfbacdd65973f7ee920d9f0e71ebac878fd0b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" diff --git a/Cargo.toml b/Cargo.toml index ea0b5ab..6bfebdc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,5 +21,7 @@ poise = "0.5.6" reqwest = "0.11.22" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" +sqlx = { version = "0.7.2", features = ["postgres", "macros", "uuid", "chrono", "json", "runtime-tokio"] } thiserror = "1.0.50" tokio = { version = "1.32.0", features = ["full"] } +uuid = { version = "1.5.0", features = ["v4"] } diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..cd8ce74 --- /dev/null +++ b/build.rs @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Louis Hollingworth +// +// SPDX-License-Identifier: GPL-3.0-or-later + +// generated by `sqlx migrate build-script` +fn main() { + // trigger recompilation when a new migration is added + println!("cargo:rerun-if-changed=migrations"); +} diff --git a/migrations/20231028165341_init.down.sql b/migrations/20231028165341_init.down.sql new file mode 100644 index 0000000..8628c20 --- /dev/null +++ b/migrations/20231028165341_init.down.sql @@ -0,0 +1,6 @@ +-- SPDX-FileCopyrightText: 2023 Louis Hollingworth +-- +-- SPDX-License-Identifier: GPL-3.0-or-later + +-- Add down migration script here +DROP TABLE "guild"; diff --git a/migrations/20231028165341_init.up.sql b/migrations/20231028165341_init.up.sql new file mode 100644 index 0000000..80a0464 --- /dev/null +++ b/migrations/20231028165341_init.up.sql @@ -0,0 +1,10 @@ +-- SPDX-FileCopyrightText: 2023 Louis Hollingworth +-- +-- SPDX-License-Identifier: GPL-3.0-or-later + +-- Add up migration script here +CREATE TABLE "guild" ( + "id" TEXT PRIMARY KEY NOT NULL, + "name" TEXT NOT NULL, + "reports_channel_id" TEXT +); diff --git a/src/commands/admin.rs b/src/commands/admin.rs new file mode 100644 index 0000000..21973f9 --- /dev/null +++ b/src/commands/admin.rs @@ -0,0 +1,70 @@ +// SPDX-FileCopyrightText: 2023 Louis Hollingworth +// +// SPDX-License-Identifier: GPL-3.0-or-later + +use poise::serenity_prelude as serenity; + +#[poise::command( + slash_command, + subcommands("admin_reports", "admin_setup"), + subcommand_required, + guild_only, + default_member_permissions = "ADMINISTRATOR" +)] +pub async fn admin(_: crate::Context<'_>) -> Result<(), crate::Error> { + Ok(()) +} + +/// Set or get the configured channel for reports +#[poise::command(slash_command, rename = "reports")] +pub async fn admin_reports( + ctx: crate::Context<'_>, + #[description = "Set where the reports should be sent"] reports_channel: Option< + serenity::Channel, + >, +) -> Result<(), crate::Error> { + ctx.defer_ephemeral().await.unwrap(); + let pool = &ctx.framework().user_data.db_pool; + match reports_channel { + None => { + let dbg = crate::models::db::guild::Guild::get_by_id( + ctx.guild_id().unwrap().to_string(), + pool.clone(), + ) + .await + .unwrap(); + ctx.reply(format!( + "<#{}> is currently receiving reports for this guild.", + dbg.reports_channel_id.unwrap_or("0000000".to_string()) + )) + .await + .unwrap(); + } + Some(cnl) => { + crate::models::db::guild::Guild::update_reports_channel( + ctx.guild_id().unwrap().to_string(), + Some(cnl.id().to_string()), + pool.clone(), + ) + .await + .unwrap(); + ctx.reply(format!( + "<#{}> is now setup to receive reports.", + cnl.id().to_string() + )) + .await + .unwrap(); + } + }; + Ok(()) +} + +/// This command shouldn't be needed for anything other than development +#[poise::command(slash_command, rename = "setup")] +pub async fn admin_setup(ctx: crate::Context<'_>) -> Result<(), crate::Error> { + let pool = &ctx.framework().user_data.db_pool; + let g = ctx.guild().unwrap(); + crate::models::db::guild::Guild::create(g.id.to_string(), g.name, pool.clone()).await?; + ctx.reply("Setup complete, never run this again. See the [issue tracker](https://git.ludoviko.ch/lucxjo/er/issues) if you are still having issues").await.unwrap(); + Ok(()) +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index f8f1b73..bbdc2c9 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -2,4 +2,6 @@ // // SPDX-License-Identifier: GPL-3.0-or-later +pub mod admin; +pub mod report; pub mod threads; diff --git a/src/commands/report.rs b/src/commands/report.rs new file mode 100644 index 0000000..c933d42 --- /dev/null +++ b/src/commands/report.rs @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: 2023 Louis Hollingworth +// +// SPDX-License-Identifier: GPL-3.0-or-later + +use poise::serenity_prelude as serenity; + +/// Report a user to the guild staff +#[poise::command(slash_command, guild_only)] +pub async fn report( + ctx: crate::Context<'_>, + #[description = "The user to report"] user: serenity::Member, + #[description = "Why you are reporting the user"] reason: String, +) -> Result<(), crate::Error> { + ctx.defer_ephemeral().await?; + let pool = &ctx.framework().user_data.db_pool; + let g = crate::models::db::guild::Guild::get_by_id( + ctx.guild_id().unwrap().to_string(), + pool.clone(), + ) + .await?; + match g.reports_channel_id { + None => { + ctx.reply("It looks like your guild staff haven't enabled this feature") + .await?; + } + Some(rcid) => { + let cid = serenity::ChannelId::from(rcid.parse::().unwrap()); + cid.send_message(ctx.http(), |m| { + m.embed(|embed| { + embed.title("Member Report"); + embed.author(|a| { + a.icon_url(ctx.author().avatar_url().unwrap()); + a.name(ctx.author().name.clone()) + }); + embed.colour(0xd1021a); + embed.description(format!("{}: {}", user, reason)) + }) + }) + .await?; + ctx.reply("Report sent").await?; + } + } + Ok(()) +} diff --git a/src/commands/threads.rs b/src/commands/threads.rs index 221ae9d..411111d 100644 --- a/src/commands/threads.rs +++ b/src/commands/threads.rs @@ -3,7 +3,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later use crate::models::discord::{DiscordThreadsResp, DiscordThreadsRespThread, EDiscordThreadsResp}; -use poise::serenity_prelude as serenity; /// Displays current active threads #[poise::command(slash_command)] diff --git a/src/lib.rs b/src/lib.rs index 5f094c1..06fdfba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,26 @@ pub mod commands; pub mod models; pub type Error = Box; -pub type Context<'a> = poise::Context<'a, Data, Error>; +pub type Context<'a> = poise::Context<'a, AppState, Error>; -pub struct Data {} +pub struct AppState { + pub db_pool: sqlx::Pool, +} + +impl AppState { + pub async fn new() -> Result { + let pool = establish_db_pool().await?; + sqlx::migrate!().run(&pool).await?; + Ok(AppState { db_pool: pool }) + } +} + +pub async fn establish_db_pool() -> Result, sqlx::Error> { + dotenvy::dotenv().ok(); + + let url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set"); + Ok(sqlx::postgres::PgPoolOptions::new() + .max_connections(5) + .connect(&url) + .await?) +} diff --git a/src/main.rs b/src/main.rs index aabec09..4f66bd3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later use dotenvy::dotenv; -use er::{commands, Data}; +use er::commands; use poise::serenity_prelude as serenity; #[tokio::main] @@ -12,7 +12,11 @@ async fn main() { let framework = poise::Framework::builder() .options(poise::FrameworkOptions { - commands: vec![commands::threads::threads()], + commands: vec![ + commands::threads::threads(), + commands::admin::admin(), + commands::report::report(), + ], ..Default::default() }) .token(std::env::var("DISCORD_TOKEN").expect("missing DISCORD_TOKEN")) @@ -26,7 +30,7 @@ async fn main() { .setup(|ctx, _ready, fw| { Box::pin(async move { poise::builtins::register_globally(ctx, &fw.options().commands).await?; - Ok(Data {}) + Ok(er::AppState::new().await?) }) }); diff --git a/src/models/db/guild.rs b/src/models/db/guild.rs new file mode 100644 index 0000000..d7b4ab2 --- /dev/null +++ b/src/models/db/guild.rs @@ -0,0 +1,65 @@ +// SPDX-FileCopyrightText: 2023 Louis Hollingworth +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#[derive(sqlx::FromRow)] +pub struct NewGuild { + pub id: String, + pub name: String, +} + +#[derive(sqlx::FromRow)] +pub struct Guild { + pub id: String, + pub name: String, + pub reports_channel_id: Option, +} + +impl Guild { + pub async fn create( + id: String, + name: String, + pool: sqlx::Pool, + ) -> Result<(), sqlx::Error> { + sqlx::query_as!( + NewGuild, + "INSERT INTO guild (id, name) VALUES ($1, $2)", + id, + name + ) + .execute(&pool) + .await + .unwrap(); + Ok(()) + } + pub async fn get_by_id( + id: String, + pool: sqlx::Pool, + ) -> Result { + let guild = sqlx::query_as!( + Self, + "SELECT id, name, reports_channel_id FROM guild WHERE id = $1", + id + ) + .fetch_one(&pool) + .await + .unwrap(); + Ok(guild) + } + pub async fn update_reports_channel( + gid: String, + rcid: Option, + pool: sqlx::Pool, + ) -> Result<(), sqlx::Error> { + sqlx::query!( + "UPDATE guild SET reports_channel_id = $1 WHERE id = $2", + rcid, + gid + ) + .execute(&pool) + .await + .unwrap(); + + Ok(()) + } +} diff --git a/src/models/db/mod.rs b/src/models/db/mod.rs new file mode 100644 index 0000000..3cb09f5 --- /dev/null +++ b/src/models/db/mod.rs @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 Louis Hollingworth +// +// SPDX-License-Identifier: GPL-3.0-or-later + +pub mod guild; diff --git a/src/models/mod.rs b/src/models/mod.rs index 318349a..9390cb6 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -2,4 +2,5 @@ // // SPDX-License-Identifier: GPL-3.0-or-later +pub mod db; pub mod discord;