commit b6a3bea2c49e40b8540025295ecf9cdc3c24f3db Author: Tom Date: Thu Feb 3 14:55:56 2022 +0100 Initial recommit to poise diff --git a/.env b/.env new file mode 100644 index 0000000..7d755c8 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +DATABASE_URL=sqlite:data/database.db diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5664357 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +/data/config +/.vscode \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..fc8135b --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2496 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "aliasable" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + +[[package]] +name = "async-mutex" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-rwlock" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261803dcc39ba9e72760ba6e16d0199b1eef9fc44e81bffabbebb9f5aea3906c" +dependencies = [ + "async-mutex", + "event-listener", +] + +[[package]] +name = "async-stream" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-trait" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-tungstenite" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5682ea0913e5c20780fe5785abacb85a411e7437bf52a1bedb93ddb3972cb8dd" +dependencies = [ + "futures-io", + "futures-util", + "log", + "pin-project-lite", + "tokio", + "tokio-rustls 0.23.2", + "tungstenite", + "webpki-roots 0.22.2", +] + +[[package]] +name = "atoi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5" +dependencies = [ + "num-traits 0.2.14", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bae" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b8de67cc41132507eeece2584804efcb15f85ba516e34c944b7667f480397a" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cached" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2bc2fd249a24a9cdd4276f3a3e0461713271ab63b0e9e656e200e8e21c8c927" +dependencies = [ + "async-mutex", + "async-rwlock", + "async-trait", + "cached_proc_macro", + "cached_proc_macro_types", + "futures", + "hashbrown", + "once_cell", +] + +[[package]] +name = "cached_proc_macro" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3531903b39df48a378a7ed515baee7c1fff32488489c7d0725eb1749b22a91" +dependencies = [ + "cached_proc_macro_types", + "darling 0.13.1", + "quote", + "syn", +] + +[[package]] +name = "cached_proc_macro_types" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663" + +[[package]] +name = "cc" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits 0.2.14", + "serde 1.0.136", + "time", + "winapi", +] + +[[package]] +name = "config" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1b9d958c2b1368a663f05538fc1b5975adce1e19f435acceae987aceeeb369" +dependencies = [ + "lazy_static", + "nom 5.1.2", + "rust-ini", + "serde 1.0.136", + "serde-hjson", + "serde_json", + "toml", + "yaml-rust", +] + +[[package]] +name = "core-foundation" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "cpufeatures" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" + +[[package]] +name = "crc32fast" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2209c310e29876f7f0b2721e7e26b84aff178aa3da5d091f9bfbf47669e60e3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b979d76c9fcb84dffc80a73f7290da0f83e4c95773494674cb44b76d13a7a110" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "darling" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c" +dependencies = [ + "darling_core 0.12.4", + "darling_macro 0.12.4", +] + +[[package]] +name = "darling" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" +dependencies = [ + "darling_core 0.13.1", + "darling_macro 0.13.1", +] + +[[package]] +name = "darling_core" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_core" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a" +dependencies = [ + "darling_core 0.12.4", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" +dependencies = [ + "darling_core 0.13.1", + "quote", + "syn", +] + +[[package]] +name = "dashmap" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b799062aaf67eb976af3bdca031ee6f846d2f0a5710ddbb0d2efee33f3cc4760" +dependencies = [ + "cfg-if", + "num_cpus", + "parking_lot", + "serde 1.0.136", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +dependencies = [ + "serde 1.0.136", +] + +[[package]] +name = "encoding_rs" +version = "0.8.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "event-listener" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" + +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + +[[package]] +name = "flate2" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide", +] + +[[package]] +name = "flume" +version = "0.10.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d04dafd11240188e146b6f6476a898004cace3be31d4ec5e08e216bf4947ac0" +dependencies = [ + "futures-core", + "futures-sink", + "pin-project", + "spin 0.9.2", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" + +[[package]] +name = "futures-executor" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62007592ac46aa7c2b6416f7deb9a8a8f63a01e0f1d6e1787d5630170db2b63e" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] +name = "futures-io" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" + +[[package]] +name = "futures-macro" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" + +[[package]] +name = "futures-task" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" + +[[package]] +name = "futures-util" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "h2" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashlink" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "http" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.1", +] + +[[package]] +name = "http-body" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa 0.4.8", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" +dependencies = [ + "http", + "hyper", + "rustls 0.20.2", + "tokio", + "tokio-rustls 0.23.2", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ipnet" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" + +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "js-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lexical-core" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" +dependencies = [ + "arrayvec 0.5.2", + "bitflags", + "cfg-if", + "ryu", + "static_assertions", +] + +[[package]] +name = "libc" +version = "0.2.116" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "565dbd88872dbe4cc8a46e527f26483c1d1f7afa6b884a3bd6cd893d4f98da74" + +[[package]] +name = "libsqlite3-sys" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cafc7c74096c336d9d27145f7ebd4f4b6f95ba16aa5a282387267e6925cb58" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" + +[[package]] +name = "lock_api" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mime_guess" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +dependencies = [ + "mime", + "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.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "mio" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "native-tls" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "nom" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +dependencies = [ + "lexical-core", + "memchr", + "version_check", +] + +[[package]] +name = "nom" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" +dependencies = [ + "memchr", + "minimal-lexical", + "version_check", +] + +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" +dependencies = [ + "autocfg", + "num-integer", + "num-traits 0.2.14", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits 0.2.14", +] + +[[package]] +name = "num-traits" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" +dependencies = [ + "num-traits 0.2.14", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "ol_rusty" +version = "0.1.0" +dependencies = [ + "cached", + "chrono", + "config", + "futures", + "glob", + "lazy_static", + "log", + "poise", + "regex", + "reqwest", + "sea-orm", + "serde 1.0.136", + "serde_json", + "simplelog", + "sqlx", + "tokio", +] + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "openssl" +version = "0.10.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-sys", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "ouroboros" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06562f88448f4f22a6cfb76b3d0d01af62e82e3dacb2a88c1a3a8a1694a501c6" +dependencies = [ + "aliasable", + "ouroboros_macro", + "stable_deref_trait", +] + +[[package]] +name = "ouroboros_macro" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cdc8f765173c2dad6c1f371d0997c2d21003bd14949da99d910ad409d88a85" +dependencies = [ + "Inflector", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "pin-project" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + +[[package]] +name = "poise" +version = "0.1.0" +source = "git+https://github.com/kangalioo/poise?branch=develop#eeda0e61b5b6e027f791e0965d6dc1c3d031c3bb" +dependencies = [ + "async-trait", + "futures-core", + "futures-util", + "once_cell", + "poise_macros", + "regex", + "serenity", + "tokio", +] + +[[package]] +name = "poise_macros" +version = "0.1.0" +source = "git+https://github.com/kangalioo/poise?branch=develop#eeda0e61b5b6e027f791e0965d6dc1c3d031c3bb" +dependencies = [ + "darling 0.12.4", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "reqwest" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f242f1488a539a79bac6dbe7c8609ae43b7914b7736210f239a37cccb32525" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "hyper-tls", + "ipnet", + "js-sys", + "lazy_static", + "log", + "mime", + "mime_guess", + "native-tls", + "percent-encoding", + "pin-project-lite", + "rustls 0.20.2", + "rustls-pemfile", + "serde 1.0.136", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tokio-rustls 0.23.2", + "tokio-util", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 0.22.2", + "winreg", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rust-ini" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2" + +[[package]] +name = "rust_decimal" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0593ce4677e3800ddafb3de917e8397b1348e06e688128ade722d88fbe11ebf" +dependencies = [ + "arrayvec 0.7.2", + "num-traits 0.2.14", + "serde 1.0.136", +] + +[[package]] +name = "rustls" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +dependencies = [ + "base64", + "log", + "ring", + "sct 0.6.1", + "webpki 0.21.4", +] + +[[package]] +name = "rustls" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" +dependencies = [ + "log", + "ring", + "sct 0.7.0", + "webpki 0.22.0", +] + +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64", +] + +[[package]] +name = "rustversion" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" + +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "schannel" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +dependencies = [ + "lazy_static", + "winapi", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sea-orm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5452736ac11d11f9dcf1980897d3a6302d78ee2bfcb928b0f9c03569f2e6b12c" +dependencies = [ + "async-stream", + "async-trait", + "chrono", + "futures", + "futures-util", + "once_cell", + "ouroboros", + "rust_decimal", + "sea-orm-macros", + "sea-query", + "sea-strum", + "serde 1.0.136", + "serde_json", + "sqlx", + "tracing", + "url", + "uuid", +] + +[[package]] +name = "sea-orm-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8b7b6d423b591bf447685e9ea7cecd65e0c282e18dc5ddc7438425cd296faa8" +dependencies = [ + "bae", + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sea-query" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83e4a0dd79545b61c6ca453a28d0a88829487869a8559a35a3192f1b6aacad8" +dependencies = [ + "chrono", + "rust_decimal", + "sea-query-derive", + "serde_json", + "uuid", +] + +[[package]] +name = "sea-query-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cdc022b4f606353fe5dc85b09713a04e433323b70163e81513b141c6ae6eb5" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", + "thiserror", +] + +[[package]] +name = "sea-strum" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391d06a6007842cfe79ac6f7f53911b76dfd69fc9a6769f1cf6569d12ce20e1b" +dependencies = [ + "sea-strum_macros", +] + +[[package]] +name = "sea-strum_macros" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b4397b825df6ccf1e98bcdabef3bbcfc47ff5853983467850eeab878384f21" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "security-framework" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d09d3c15d814eda1d6a836f2f2b56a6abc1446c8a34351cb3180d3db92ffe4ce" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e90dd10c41c6bfc633da6e0c659bd25d31e0791e5974ac42970267d59eba87f7" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-hjson" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8" +dependencies = [ + "lazy_static", + "num-traits 0.1.43", + "regex", + "serde 0.8.23", +] + +[[package]] +name = "serde_derive" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085" +dependencies = [ + "indexmap", + "itoa 1.0.1", + "ryu", + "serde 1.0.136", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa 1.0.1", + "ryu", + "serde 1.0.136", +] + +[[package]] +name = "serenity" +version = "0.10.10" +source = "git+https://github.com/serenity-rs/serenity?branch=next#e7567464e09806aec8f6ee9317d33c808d39eea3" +dependencies = [ + "async-trait", + "async-tungstenite", + "base64", + "bitflags", + "bytes", + "chrono", + "dashmap", + "flate2", + "futures", + "mime", + "mime_guess", + "parking_lot", + "percent-encoding", + "reqwest", + "serde 1.0.136", + "serde_json", + "tokio", + "tracing", + "typemap_rev", + "url", +] + +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "simplelog" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1348164456f72ca0116e4538bdaabb0ddb622c7d9f16387c725af3e96d6001c" +dependencies = [ + "chrono", + "log", + "termcolor", +] + +[[package]] +name = "slab" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" +dependencies = [ + "lock_api", +] + +[[package]] +name = "sqlformat" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" +dependencies = [ + "itertools", + "nom 7.1.0", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692749de69603d81e016212199d73a2e14ee20e2def7d7914919e8db5d4d48b9" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "518be6f6fff5ca76f985d434f9c37f3662af279642acf730388f271dff7b9016" +dependencies = [ + "ahash", + "atoi", + "bitflags", + "byteorder", + "bytes", + "chrono", + "crc", + "crossbeam-channel", + "crossbeam-queue", + "crossbeam-utils", + "either", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "hashlink", + "hex", + "indexmap", + "itoa 1.0.1", + "libc", + "libsqlite3-sys", + "log", + "memchr", + "num-bigint", + "once_cell", + "parking_lot", + "percent-encoding", + "rust_decimal", + "rustls 0.19.1", + "serde 1.0.136", + "serde_json", + "sha2", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "tokio-stream", + "url", + "uuid", + "webpki 0.21.4", + "webpki-roots 0.21.1", +] + +[[package]] +name = "sqlx-macros" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e45140529cf1f90a5e1c2e561500ca345821a1c513652c8f486bbf07407cc8" +dependencies = [ + "dotenv", + "either", + "heck", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde 1.0.136", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-rt", + "syn", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8061cbaa91ee75041514f67a09398c65a64efed72c90151ecd47593bad53da99" +dependencies = [ + "once_cell", + "tokio", + "tokio-rustls 0.22.0", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stringprep" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "tinyvec" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a" +dependencies = [ + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "pin-project-lite", + "signal-hook-registry", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +dependencies = [ + "rustls 0.19.1", + "tokio", + "webpki 0.21.4", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" +dependencies = [ + "rustls 0.20.2", + "tokio", + "webpki 0.22.0", +] + +[[package]] +name = "tokio-stream" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde 1.0.136", +] + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + +[[package]] +name = "tracing" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "tungstenite" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ad3713a14ae247f22a728a0456a545df14acf3867f905adff84be99e23b3ad1" +dependencies = [ + "base64", + "byteorder", + "bytes", + "http", + "httparse", + "log", + "rand", + "rustls 0.20.2", + "sha-1", + "thiserror", + "url", + "utf-8", + "webpki 0.22.0", +] + +[[package]] +name = "typemap_rev" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5b74f0a24b5454580a79abb6994393b09adf0ab8070f15827cb666255de155" + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", + "serde 1.0.136", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom", + "serde 1.0.136", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasm-bindgen" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" + +[[package]] +name = "web-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" +dependencies = [ + "webpki 0.21.4", +] + +[[package]] +name = "webpki-roots" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" +dependencies = [ + "webpki 0.22.0", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "winreg" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +dependencies = [ + "winapi", +] + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b70ed95 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "ol_rusty" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +cached = "0.26" +chrono = "0.4" +config = "0.11" +futures = { version = "0.3.13", default-features = false } +glob = "0.3" +lazy_static = "1" +log = "0.4.14" +simplelog = "0.11.1" +poise = { git = "https://github.com/kangalioo/poise", branch = "develop", features = ["collector"] } +regex = {version="1"} +reqwest = "0.11" +sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "offline"] } +sea-orm = { version = "^0", features = [ "sqlx-sqlite", "runtime-tokio-rustls", "macros" ], default-features = false } +serde_json = "1" +serde = "1" +tokio = { version = "1.4.0", features = ["rt-multi-thread", "process"] } diff --git a/data/database.db b/data/database.db new file mode 100644 index 0000000..81d319e Binary files /dev/null and b/data/database.db differ diff --git a/migrations/20220127114757_init.sql b/migrations/20220127114757_init.sql new file mode 100644 index 0000000..65eeb55 --- /dev/null +++ b/migrations/20220127114757_init.sql @@ -0,0 +1,47 @@ +CREATE TABLE IF NOT EXISTS Locations ( + id TEXT NOT NULL, + name TEXT NOT NULL, + description TEXT, + PRIMARY KEY(id) +); + +CREATE TABLE IF NOT EXISTS Series ( + id TEXT NOT NULL, + name TEXT NOT NULL, + description TEXT, + PRIMARY KEY(id) +); + +CREATE TABLE IF NOT EXISTS Sessions ( + id TEXT NOT NULL, + name TEXT NOT NULL, + start INTEGER NOT NULL, + duration_minutes INTEGER NOT NULL, + location TEXT, + location_name TEXT, + series TEXT NOT NULL, + series_name TEXT NOT NULL, + PRIMARY KEY(id), + FOREIGN KEY(location) REFERENCES locations(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS Events ( + id TEXT NOT NULL, + start_date TEXT NOT NULL, + end_date TEXT, + description TEXT NOT NULL, + series TEXT NOT NULL, + series_name TEXT NOT NULL, + location TEXT, + location_name TEXT, + FOREIGN KEY(location) REFERENCES locations(id) ON DELETE CASCADE, + PRIMARY KEY(id), + FOREIGN KEY(series) REFERENCES series(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS Updates ( + window_start INTEGER NOT NULL, + time INTEGER NOT NULL, + date TEXT, + PRIMARY KEY(window_start) +); \ No newline at end of file diff --git a/src/commands/invites.rs b/src/commands/invites.rs new file mode 100644 index 0000000..d8cd426 --- /dev/null +++ b/src/commands/invites.rs @@ -0,0 +1,152 @@ +use crate::{Context, Error}; +use serde::Deserialize; + +// pub mod invites; + +#[derive(Debug, Deserialize)] +struct InviteUser { + // #[serde(rename = "_id")] + // id: String, + #[serde(rename = "showUsername")] + name: String, +} + +#[derive(Debug, Deserialize)] +struct InviteInfo { + // #[serde(rename = "_id")] + // id: String, + #[serde(rename = "fromUser")] + from_user: InviteUser, + #[serde(rename = "usedBy")] + used_by: Option, + token: String, + high_tier: bool, + custom: bool, + #[serde(rename = "isUsed")] + used: bool, +} + +async fn get_invite(invite: &str) -> Result, Error> { + let client = reqwest::Client::new(); + let req = client + .get(format!( + "https://api.morningstreams.com/api/invites/{}", + invite + )) + .send() + .await?; + if req.status().as_u16() == 404 { + // debug!("Error 404 on getting the invites, this just means invite not found"); + Ok(None) + } else if req.status().as_u16() == 200 { + let data: InviteInfo = req.json().await?; + // debug!("invite data: {:#?}", data); + Ok(Some(data)) + } else { + Ok(None) + } +} + +#[derive(Debug, poise::SlashChoiceParameter)] +pub enum InviteActions { + #[name = "Does this invite exist?"] + Exist, + #[name = "Is this invite valid?"] + Valid, + // If no name is given, the variant name is used + #[name = "Get invite information"] + Info, + #[name = "Which user used the invite?"] + User, +} + +#[poise::command(slash_command)] +pub async fn invites( + ctx: Context<'_>, + #[description = "Action to perform with invite"] action: InviteActions, + #[description = "The invite to check"] invite: String, +) -> Result<(), Error> { + let invite_res = get_invite(&invite).await; + match invite_res { + Err(e) => { + ctx.say(format!("Error getting invite: {}", e)).await?; + } + Ok(invite_opt) => { + ctx.send(|b| { + match action { + InviteActions::Exist => { + b.content(match invite_opt { + None => "Invite not found", + Some(_) => "Invite found", + }); + } + InviteActions::Valid => { + b.content(match invite_opt { + None => "Invite not found", + Some(i) => { + if !i.used { + "✅ Invite is valid and not used yet" + } else { + "❌ Invite is valid but is already used" + } + } + }); + } + InviteActions::Info => { + b.content(match invite_opt { + None => "Invite not found".to_owned(), + Some(i) => { + if !i.used { + "Ooh this invite is still up for grabs, go quickly claim it!" + .to_owned() + } else { + match i.used_by { + None => { + "Invite is already used but can not find the user..." + .to_owned() + } + Some(user) => format!( + "This invite has already been used by {}", + user.name + ), + } + } + } + }); + } + InviteActions::User => { + match invite_opt { + None => b.content("Invite not found"), + Some(i) => { + b.embed(|e| { + e.title("Invite information"); + e.description(format!("Invite: {}", i.token)); + if i.used { + e.field("Used", "Yes", true); + if let Some(user) = i.used_by { + e.field("Used by", user.name, true); + } + } else { + e.field("Used", "No", true); + } + e.field( + "High tier", + if i.high_tier { "Yes" } else { "No" }, + true, + ); + e.field("Custom", if i.custom { "Yes" } else { "No" }, true); + e.field("Given out by", i.from_user.name, true); + e + }); + b.content("Embed:") + } + }; + } + } + b + }) + .await?; + } + }; + Ok(()) +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs new file mode 100644 index 0000000..a782477 --- /dev/null +++ b/src/commands/mod.rs @@ -0,0 +1,50 @@ +use crate::{Context, Error}; +use poise::serenity_prelude as serenity; + +pub mod invites; +pub mod planning; +pub mod schedule; +pub mod utils; + +/// Boop the bot! +#[poise::command(prefix_command, track_edits, slash_command)] +pub async fn boop(ctx: Context<'_>) -> Result<(), Error> { + let uuid_boop = ctx.id(); + + ctx.send(|m| { + m.content("I want some boops!").components(|c| { + c.create_action_row(|ar| { + ar.create_button(|b| { + b.style(serenity::ButtonStyle::Primary) + .label("Boop me!") + .custom_id(uuid_boop) + }) + }) + }) + }) + .await?; + + let mut boop_count = 0; + while let Some(mci) = serenity::CollectComponentInteraction::new(ctx.discord()) + .author_id(ctx.author().id) + .channel_id(ctx.channel_id()) + .timeout(std::time::Duration::from_secs(120)) + .filter(move |mci| mci.data.custom_id == uuid_boop.to_string()) + .await + { + boop_count += 1; + + let mut msg = mci.message.clone(); + msg.edit(ctx.discord(), |m| { + m.content(format!("Boop count: {}", boop_count)) + }) + .await?; + + mci.create_interaction_response(ctx.discord(), |ir| { + ir.kind(serenity::InteractionResponseType::DeferredUpdateMessage) + }) + .await?; + } + + Ok(()) +} diff --git a/src/commands/planning.rs b/src/commands/planning.rs new file mode 100644 index 0000000..976f0be --- /dev/null +++ b/src/commands/planning.rs @@ -0,0 +1,249 @@ +use super::utils; +use crate::{Context, Error}; +use futures::{Stream, StreamExt}; + +#[allow(dead_code)] +async fn autocomplete_series(_ctx: Context<'_>, partial: String) -> impl Stream { + futures::stream::iter(&[ + "Formula 1", + "Formula", + "MotoGP", + "Moto", + "IndyCar", + "World Rally Championship", + ]) + .filter(move |name| futures::future::ready(name.starts_with(&partial))) + .map(|name| name.to_string()) +} + +#[allow(dead_code)] +async fn autocomplete_session(_ctx: Context<'_>, partial: String) -> impl Stream { + futures::stream::iter(&[ + "Race", + "Qualifying", + "Free practice 3", + "Free practice 2", + "Free practice 1", + "Sprint race", + ]) + .filter(move |name| futures::future::ready(name.starts_with(&partial))) + .map(|name| name.to_string()) +} + +/// Get a list of supported racing series +#[poise::command{slash_command}] +pub async fn series( + ctx: Context<'_>, + #[description = "Filter for series (These are suggestions)"] + #[autocomplete = "autocomplete_series"] + serie: Option, +) -> Result<(), Error> { + let filter: String = match serie { + None => "%".to_string(), + Some(s) if s.is_empty() => "%".to_string(), + Some(s) => { + format!("%{}%", s) + } + }; + let query = sqlx::query!("SELECT name FROM Series WHERE name like ?", filter) + .fetch_many(&ctx.data().database); + + let serie_list = query + .filter_map(|result| async move { result.ok()?.right() }) + .map(|record| record.name) + .collect() + .await; + + let pages = utils::paginator(serie_list, 1000, ", ".to_string()); + + print!("{:?}", pages); + + utils::paginate_string(ctx, pages).await?; + + Ok(()) +} + +#[derive(Debug, poise::SlashChoiceParameter)] +pub enum Timeframe { + #[name = "Currently happening"] + Current, + #[name = "Currently happening or starting in the future"] + Future, + #[name = "Currently happening or already ended"] + Past, + #[name = "Everything"] + Everything, +} + +#[derive(sqlx::FromRow)] +struct Session { + name: String, + start: i64, + duration_minutes: i64, + #[sqlx(rename = "series_name")] + series: String, + #[sqlx(rename = "location_name")] + location: Option, +} + +impl Session { + fn to_string(&self) -> String { + match &self.location { + None => format!( + " - | **{}** `{}`", + self.start, + (self.start + 60 * self.duration_minutes), + self.series, + self.name + ), + Some(l) => format!( + " - | **{}** `{}` @*{}*", + self.start, + (self.start + 60 * self.duration_minutes), + self.series, + self.name, + l + ), + } + } +} + +/// Get a list of racing sessions +#[poise::command{slash_command}] +pub async fn sessions( + ctx: Context<'_>, + #[description = "Filter for the session"] filter: Option, + #[description = "Filter sessions for when they are/were happening, defaults to future"] + timeframe: Option, +) -> Result<(), Error> { + let filter_f: String = match filter { + None => "%".to_string(), + Some(s) if s.is_empty() => "%".to_string(), + Some(s) => { + format!("%{}%", s) + } + }; + + let mut base_query: String = "SELECT name, start, duration_minutes, series_name, location_name FROM sessions WHERE (series_name LIKE ? or location_name like ? or name like ?)".to_string(); + + let time_query = match timeframe { + Some(Timeframe::Everything) => " ORDER BY abs(julianday() - julianday(start, 'unixepoch')) ASC", + Some(Timeframe::Current) => " AND (DATETIME(start, 'unixepoch') > DATETIME() AND DATETIME((start+60*duration_minutes), 'unixepoch') < DATETIME()) ORDER BY start ASC", + Some(Timeframe::Past) => " AND DATETIME(start, 'unixepoch') < DATETIME() ORDER BY start DESC", + _ => " AND DATETIME((start+60*duration_minutes), 'unixepoch') > DATETIME() ORDER BY start ASC", + }; + + base_query.push_str(time_query); + + let stream: Vec = sqlx::query_as::<_, Session>(&base_query) + .bind(&filter_f) + .bind(&filter_f) + .bind(&filter_f) + .fetch_all(&ctx.data().database) + .await?; + + let sessions: Vec = stream.iter().map(|s| s.to_string()).collect(); + let pages = utils::paginator(sessions, 1900, "\n".to_string()); + utils::paginate_string(ctx, pages).await?; + + Ok(()) +} + +#[derive(sqlx::FromRow)] +struct Event { + // name: String, + #[sqlx(rename = "start_date")] + start: String, + #[sqlx(rename = "end_date")] + end: Option, + description: String, + #[sqlx(rename = "series_name")] + series: String, + #[sqlx(rename = "location_name")] + location: Option, +} + +impl Event { + fn to_string(&self) -> String { + let mut result: String = match &self.end { + None => format!("`{}`", self.start), + Some(end) => format!("`{}` - `{}`", self.start, end), + }; + + result.push_str(&format!(" | **{}** {}", self.series, self.description)); + + if let Some(loc) = &self.location { + result.push_str(&format!("Location: {}", loc)); + }; + + return result; + } +} + +/// Get a list of racing events +#[poise::command{slash_command}] +pub async fn events( + ctx: Context<'_>, + #[description = "Filter for the session"] filter: Option, + #[description = "Filter events for when they are/were happening, defaults to future"] + timeframe: Option, +) -> Result<(), Error> { + let filter_f: String = match filter { + None => "%".to_string(), + Some(s) if s.is_empty() => "%".to_string(), + Some(s) => { + format!("%{}%", s) + } + }; + + let mut base_query: String = "SELECT start_date, end_date, description, series_name, location_name FROM events WHERE (series_name LIKE ? or location_name like ? or description like ?)".to_string(); + + let time_query = match timeframe { + Some(Timeframe::Everything) => " ORDER BY abs(julianday() - julianday(start_date)) ASC", + Some(Timeframe::Current) => " AND ((end_date is NULL and start_date == date()) OR (start_date <= date() AND end_date >= date())) ORDER BY start_date ASC, end_date ASC", + Some(Timeframe::Past) => " AND JULIANDAY(start_date) - JULIANDAY(date()) <= 0 ORDER BY start DESC", + _ => " AND start_date >= DATE() ORDER BY start_date ASC, end_date ASC", + }; + + base_query.push_str(time_query); + + let stream: Vec = sqlx::query_as::<_, Event>(&base_query) + .bind(&filter_f) + .bind(&filter_f) + .bind(&filter_f) + .fetch_all(&ctx.data().database) + .await?; + + let events: Vec = stream.iter().map(|e| e.to_string()).collect(); + + let pages = utils::paginator(events, 1900, "\n".to_string()); + + utils::paginate_string(ctx, pages).await?; + + Ok(()) +} + +/// Overall information about racing events and sessions +#[poise::command(slash_command)] +pub async fn planning(ctx: Context<'_>) -> Result<(), Error> { + ctx.say("Hey this is a parent command, how'd you get here?") + .await?; + + Ok(()) +} + +pub fn get_command() -> poise::Command< + super::super::Data, + Box<(dyn std::error::Error + Sync + std::marker::Send + 'static)>, +> { + poise::Command { + subcommands: vec![ + series(), + sessions(), + events(), + // Let's make sure poise isn't confused by the duplicate names! + // planning(), + ], + ..planning() + } +} diff --git a/src/commands/schedule.rs b/src/commands/schedule.rs new file mode 100644 index 0000000..67cb3fc --- /dev/null +++ b/src/commands/schedule.rs @@ -0,0 +1,409 @@ +use crate::{Context, Error}; +use cached::proc_macro::cached; +use futures::{Stream, StreamExt}; +use log::*; + +use chrono::{DateTime, NaiveDateTime, TimeZone, Utc}; +use poise::serenity_prelude::CreateEmbed; +use reqwest::header::AUTHORIZATION; +use reqwest::Error as reqError; +use serde::Deserialize; +use std::cmp::Ordering::{Greater, Less}; + +#[derive(Debug, Clone)] +struct Event { + name: String, + series: String, + _lower_series: String, + session: String, + _lower_session: String, + date: DateTime, +} + +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +struct F1Data { + #[serde(rename = "seasonContext")] + season_context: SeasonContext, + race: Race, +} +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +struct SeasonContext { + timetables: Vec, +} + +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +struct Race { + #[serde(rename = "meetingOfficialName")] + name: String, + #[serde(rename = "meetingCountryName")] + country: String, +} +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +struct TimeTable { + state: String, + session: String, + #[serde(rename = "gmtOffset")] + offset: String, + #[serde(rename = "startTime")] + start: String, + #[serde(rename = "endTime")] + end: String, +} + +impl Event { + fn create(name: String, series: String, session: String, date: DateTime) -> Event { + Event { + name, + _lower_series: series.to_ascii_lowercase(), + series, + _lower_session: session.to_ascii_lowercase(), + session, + date, + } + } + + fn deref(&self) -> Event { + Event { + name: self.name.to_string(), + _lower_series: self._lower_series.to_string(), + series: self.series.to_string(), + _lower_session: self._lower_session.to_string(), + session: self.session.to_string(), + date: self.date.clone(), + } + } + + fn check_series(&self, series: String) -> bool { + return self._lower_series.contains(&series); + } + + fn check_session(&self, session: String) -> bool { + return self._lower_session.contains(&session); + } + + #[allow(dead_code)] + fn check(&self, series: String, session: String) -> bool { + if self._lower_session.contains(&session) { + if self._lower_series.contains(&series) { + return true; + } + } + return false; + } +} + +fn parse_time(time: String) -> Option> { + let tim = NaiveDateTime::parse_from_str(&*time, "%Y-%m-%dT%H:%M:%S.%fZ"); + match tim { + Ok(t) => Some(Utc.from_utc_datetime(&t)), + Err(e) => { + warn!("Error on parsing time: {}", e); + None + } + } +} + +fn parse_f1_time(mut time: String, offset: &String) -> Option> { + time.push_str(offset); + let tim = DateTime::parse_from_str(&time, "%Y-%m-%dT%H:%M:%S%:z"); + match tim { + Ok(t) => Some(t.with_timezone(&Utc)), + Err(e) => { + warn!("Error on parsing time: {}", e); + None + } + } +} + +// Use cached to cache the requests, don't repeatedly redo this call. Caches for 1 hour. +#[cached(time = 3600)] +async fn get_api_events() -> Vec { + let token = super::super::SETTINGS + .read() + .unwrap() + .get_table("morningstreams") + .unwrap() + .get("token") + .expect("Config error, please set the morningstreams[token] value") + .clone() + .into_str() + .expect("Config error, please make sure morningstreams[token] is a string"); + let client = reqwest::Client::new(); + let req = client + .get(format!("https://api.morningstreams.com/api/events")) + .header(AUTHORIZATION, token) + .send() + .await; + #[derive(Debug, Deserialize)] + struct Data { + category: String, + name: String, + session: String, + date: String, + } + + let result: Option> = match req { + Err(e) => { + warn!("Error getting schedule {}", e); + None + } + Ok(req) => { + info!("Did MS event request status code {}", req.status().as_u16()); + if req.status().as_u16() == 404 { + warn!("404 on getting MS events"); + None + } else if req.status().as_u16() == 200 { + let data: Result, reqError> = req.json().await; + match data { + Err(e) => { + warn!("Error parsing morningstreams event: {}", e); + None + } + Ok(dat) => { + let mut result: Vec = Vec::new(); + for d in dat { + let t = parse_time(d.date.to_string()); + if let Some(tim) = t { + result.push(Event::create( + d.name.to_string(), + d.category.to_string(), + d.session.to_string(), + tim, + )); + } + } + if result.len() > 0 { + result.sort_by(|a, b| a.date.cmp(&b.date)); + Some(result) + } else { + None + } + } + } + } else { + None + } + } + }; + match result { + None => { + return Vec::new(); + } + Some(events) => return events, + } +} + +#[allow(dead_code)] +#[cached(time = 3600)] +async fn get_f1_events() -> Option> { + let token = super::super::SETTINGS + .read() + .unwrap() + .get_table("morningstreams") + .unwrap() + .get("token") + .expect("Config error, please set the morningstreams[token] value") + .clone() + .into_str() + .expect("Config error, please make sure morningstreams[token] is a string"); + let client = reqwest::Client::new(); + let req = client + .get(format!( + "https://api.morningstreams.com/api/events/f1/event-tracker" + )) + .header(AUTHORIZATION, token) + .send() + .await; + + let result: Option> = match req { + Err(e) => { + warn!("Error getting schedule {}", e); + None + } + Ok(req) => { + info!("Did MS F1 request status code {}", req.status().as_u16()); + if req.status().as_u16() == 404 { + warn!("404 on getting F1 events"); + return None; + } else if req.status().as_u16() == 200 { + let data: Result = req.json().await; + match data { + Err(e) => { + warn!("Error parsing morningstreams event: {}", e); + None + } + Ok(dat) => { + // return Some(dat); + let mut events: Vec = Vec::new(); + // let mut sessions: Vec = Vec::new(); + for ses in dat.season_context.timetables { + if let Some(start) = parse_f1_time(ses.start, &ses.offset) { + events.push(Event::create( + dat.race.name.to_string(), + "Formula 1".to_string(), + ses.session, + start, + )) + } + } + return Some(events); + } + } + } else { + None + } + } + }; + return result; +} + +#[cached(size = 5, time = 3600)] +async fn filter_events(series: String, session: String) -> (Option, Option) { + let mut events: Vec = get_api_events().await; + + if let Some(mut e) = get_f1_events().await { + events.append(&mut e); + } + if events.len() == 0 { + return (None, None); + } else { + let mut next_event: Option<&Event> = None; + let mut previous_event: Option<&Event> = None; + let now = Utc::now(); + for e in &events { + if e.check_series(series.to_string()) && e.check_session(session.to_string()) { + match now.cmp(&e.date) { + // Now is greater (after) event + Greater => { + if let Some(p) = previous_event { + if p.date.cmp(&e.date) == Less { + previous_event = Some(e) + }; + } else { + previous_event = Some(e); + } + } + Less => { + if let Some(f) = next_event { + if f.date.cmp(&e.date) == Greater { + next_event = Some(e) + } + } else { + next_event = Some(e); + } + } + _ => { + next_event = Some(e); + previous_event = Some(e); + } + }; + } + } + + let first: Option = match previous_event { + None => None, + Some(e) => Some(e.deref()), + }; + let second: Option = match next_event { + None => None, + Some(e) => Some(e.deref()), + }; + (first, second) + } +} + +#[allow(dead_code)] +fn build_embed<'a>(event: Event, e: &'a mut CreateEmbed) -> &'a mut CreateEmbed { + e.title(format!("{} | {}", event.series, event.name)); + + // e.description(format!("{}", event.session)); + e.field("Session", &event.session, true); + e.field( + "Starts in", + format!("", &event.date.timestamp()), + true, + ); + e.field( + "Date and time", + format!("", &event.date.timestamp()), + true, + ); + + e.timestamp(event.date); + e +} + +#[allow(dead_code)] +async fn autocomplete_series(_ctx: Context<'_>, partial: String) -> impl Stream { + futures::stream::iter(&["Formula 1", "MotoGP", "IndyCar"]) + .filter(move |name| futures::future::ready(name.starts_with(&partial))) + .map(|name| name.to_string()) +} + +#[allow(dead_code)] +async fn autocomplete_session(_ctx: Context<'_>, partial: String) -> impl Stream { + futures::stream::iter(&[ + "Race", + "Qualifying", + "Free practice 3", + "Free practice 2", + "Free practice 1", + "Sprint race", + ]) + .filter(move |name| futures::future::ready(name.starts_with(&partial))) + .map(|name| name.to_string()) +} + +#[poise::command(slash_command)] +pub async fn schedule( + ctx: Context<'_>, + #[description = "Which series to look for"] + #[autocomplete = "autocomplete_series"] + series: Option, + #[description = "Which session to look for"] + #[autocomplete = "autocomplete_session"] + session: Option, +) -> Result<(), Error> { + let serie: String = match series { + None => "".to_string(), + Some(ser) => { + if vec![ + "f1".to_string(), + "formula 1".to_string(), + "formula1".to_string(), + ] + .contains(&ser.to_ascii_lowercase()) + { + "formula 1".to_string() + } else { + ser.to_ascii_lowercase() + } + } + }; + let session: String = match session { + None => "".to_string(), + Some(s) => s.to_ascii_lowercase(), + }; + // Get the events (This will hopefully be cached) + let (previous_event, next_event) = filter_events(serie, session.to_string()).await; + + // Do the event sending thingy... + if let Some(e) = next_event { + ctx.send(|b| b.embed(|em| build_embed(e, em))).await?; + } else if let Some(e) = previous_event { + ctx.send(|b| { + b.embed(|em| build_embed(e, em)); + b.content("No future events found, showing most recent") + }) + .await?; + } else { + ctx.say("No future events found, showing most recent") + .await?; + }; + + Ok(()) +} diff --git a/src/commands/utils.rs b/src/commands/utils.rs new file mode 100644 index 0000000..76afafb --- /dev/null +++ b/src/commands/utils.rs @@ -0,0 +1,114 @@ +use std::vec; + +use crate::{Context, Error}; +use poise::serenity_prelude as serenity; + +pub fn paginator(input: Vec, chunk_size: usize, join_string: String) -> Vec { + if input.len() == 0 { + return vec![]; + } + let mut result: Vec = vec![]; + let mut part: String = "".to_string(); + let filler = &join_string.chars().count(); + for i in input { + if part.chars().count() + i.chars().count() + filler >= chunk_size { + result.push(part); + part = i.to_string(); + } + part.push_str(&join_string); + part.push_str(&i.to_string()); + } + result.push(part); + return result; +} + +pub async fn paginate_string(ctx: Context<'_>, pages: Vec) -> Result<(), Error> { + let uuid_command = ctx.id().to_string(); + let page_count = pages.len(); + + match pages.len() { + 0 => { + ctx.say("No data found :(").await?; + return Ok(()); + } + 1 => { + ctx.say(pages.get(0).unwrap()).await?; + return Ok(()); + } + _ => {} + }; + + ctx.send(|m| { + m.content(format!( + "{}\n\nPage: {}/{}", + pages.get(0).unwrap(), + 1, + page_count + )) + .components(|c| { + c.create_action_row(|ar| { + ar.create_button(|b| { + b.style(serenity::ButtonStyle::Primary) + .label("Previous page") + .custom_id(format!("{}_previous", uuid_command)) + }); + ar.create_button(|b| { + b.style(serenity::ButtonStyle::Primary) + .label("Next page") + .custom_id(format!("{}_next", uuid_command)) + }); + ar.create_button(|b| { + b.style(serenity::ButtonStyle::Secondary) + .label("Reset") + .custom_id(format!("{}_close", uuid_command)) + }) + }) + }) + }) + .await?; + // let interaction1 = if let ReplyHandle::Application { http, interaction } = msg.unwrap(){Some(interaction)} else {None}; + // let interaction = interaction1.unwrap(); + + let mut page = 0; + while let Some(mci) = serenity::CollectComponentInteraction::new(ctx.discord()) + // .author_id(ctx.author().id) + .channel_id(ctx.channel_id()) + .timeout(std::time::Duration::from_secs(1200)) + // .filter(move |mci| mci.data.custom_id == uuid_command.to_string()) + .await + { + if !mci.data.custom_id.contains(&uuid_command) { + continue; + } + + if mci.data.custom_id.contains("_previous") { + if page == 0 { + page = page_count - 1; + } else { + page = (page - 1) % page_count; + } + } else if mci.data.custom_id.contains("_next") { + page = (page + 1) % page_count; + } else if mci.data.custom_id.contains("_close") { + page = 0; + } + + let mut msg = mci.message.clone(); + msg.edit(ctx.discord(), |m| { + m.content(format!( + "{}\n\nPage: {}/{}", + pages.get(page).unwrap(), + page + 1, + page_count + )) + }) + .await?; + + mci.create_interaction_response(ctx.discord(), |ir| { + ir.kind(serenity::InteractionResponseType::DeferredUpdateMessage) + }) + .await?; + } + + Ok(()) +} diff --git a/src/entity/events.rs b/src/entity/events.rs new file mode 100644 index 0000000..e1a92fa --- /dev/null +++ b/src/entity/events.rs @@ -0,0 +1,52 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.5.0 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)] +#[sea_orm(table_name = "events")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + pub start_date: String, + pub end_date: Option, + pub description: String, + pub series: String, + pub series_name: String, + pub location: Option, + pub location_name: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::series::Entity", + from = "Column::Series", + to = "super::series::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Series, + #[sea_orm( + belongs_to = "super::locations::Entity", + from = "Column::Location", + to = "super::locations::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Locations, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Series.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Locations.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/entity/locations.rs b/src/entity/locations.rs new file mode 100644 index 0000000..1988786 --- /dev/null +++ b/src/entity/locations.rs @@ -0,0 +1,35 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.5.0 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)] +#[sea_orm(table_name = "locations")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + pub name: String, + pub description: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::sessions::Entity")] + Sessions, + #[sea_orm(has_many = "super::events::Entity")] + Events, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Sessions.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Events.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/entity/mod.rs b/src/entity/mod.rs new file mode 100644 index 0000000..b5d5ffc --- /dev/null +++ b/src/entity/mod.rs @@ -0,0 +1,8 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.5.0 + +pub mod prelude; + +pub mod events; +pub mod locations; +pub mod series; +pub mod sessions; diff --git a/src/entity/prelude.rs b/src/entity/prelude.rs new file mode 100644 index 0000000..85ffee3 --- /dev/null +++ b/src/entity/prelude.rs @@ -0,0 +1,6 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.5.0 + +pub use super::events::Entity as Events; +pub use super::locations::Entity as Locations; +pub use super::series::Entity as Series; +pub use super::sessions::Entity as Sessions; diff --git a/src/entity/series.rs b/src/entity/series.rs new file mode 100644 index 0000000..a763b64 --- /dev/null +++ b/src/entity/series.rs @@ -0,0 +1,27 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.5.0 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)] +#[sea_orm(table_name = "series")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + pub name: String, + pub description: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::events::Entity")] + Events, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Events.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/entity/sessions.rs b/src/entity/sessions.rs new file mode 100644 index 0000000..98d33f8 --- /dev/null +++ b/src/entity/sessions.rs @@ -0,0 +1,38 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.5.0 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)] +#[sea_orm(table_name = "sessions")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + pub name: String, + pub start: i32, + pub duration_minutes: Option, + pub location: Option, + pub location_name: Option, + pub series: String, + pub series_name: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::locations::Entity", + from = "Column::Location", + to = "super::locations::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Locations, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Locations.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..5a65496 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,241 @@ +use config::{Config, File}; +use glob::glob; +use lazy_static::lazy_static; +use log::LevelFilter; +use poise::serenity_prelude as serenity; +use poise::serenity_prelude::UserId; +use regex::Regex; +use simplelog::SimpleLogger; +use std::{collections::HashSet, sync::RwLock}; + +// mod entity; + +// Types used by all command functions +type Error = Box; +type Context<'a> = poise::Context<'a, Data, Error>; + +mod commands; + +// Custom user data passed to all command functions +pub struct Data { + database: sqlx::SqlitePool, +} + +lazy_static! { + static ref SETTINGS: RwLock = RwLock::new(Config::default()); +} + +/// Register application commands in this guild or globally +/// +/// Run with no arguments to register in guild, run with argument "global" to register globally. +#[poise::command( + prefix_command, + hide_in_help, + // required_permissions = "MANAGE_MESSAGES | ADMINISTRATOR", + owners_only=true, +)] +async fn register(ctx: Context<'_>, #[flag] global: bool) -> Result<(), Error> { + poise::builtins::register_application_commands(ctx, global).await?; + + Ok(()) +} + +/// Boop the bot! +#[poise::command(prefix_command, track_edits, slash_command)] +pub async fn boop(ctx: Context<'_>) -> Result<(), Error> { + let uuid_boop = ctx.id(); + + ctx.send(|m| { + m.content("I want some boops!").components(|c| { + c.create_action_row(|ar| { + ar.create_button(|b| { + b.style(serenity::ButtonStyle::Primary) + .label("Boop me!") + .custom_id(uuid_boop) + }) + }) + }) + }) + .await?; + + let mut boop_count = 0; + while let Some(mci) = serenity::CollectComponentInteraction::new(ctx.discord()) + .author_id(ctx.author().id) + .channel_id(ctx.channel_id()) + .timeout(std::time::Duration::from_secs(1200)) + .filter(move |mci| mci.data.custom_id == uuid_boop.to_string()) + .await + { + boop_count += 1; + + let mut msg = mci.message.clone(); + msg.edit(ctx.discord(), |m| { + m.content(format!("Boop count: {}", boop_count)) + }) + .await?; + + mci.create_interaction_response(ctx.discord(), |ir| { + ir.kind(serenity::InteractionResponseType::DeferredUpdateMessage) + }) + .await?; + } + + Ok(()) +} + +async fn on_error(error: poise::FrameworkError<'_, Data, Error>) { + // This is our custom error handler + // They are many errors that can occur, so we only handle the ones we want to customize + // and forward the rest to the default handler + match error { + poise::FrameworkError::Setup { error } => panic!("Failed to start bot: {:?}", error), + poise::FrameworkError::Command { error, ctx } => { + println!("Error in command `{}`: {:?}", ctx.command().name, error,); + } + error => { + if let Err(e) = poise::builtins::on_error(error).await { + println!("Error while handling error: {}", e) + } + } + } +} + +/// Show this help menu +#[poise::command(prefix_command, track_edits, slash_command)] +async fn help( + ctx: Context<'_>, + #[description = "Specific command to show help about"] + #[autocomplete = "poise::builtins::autocomplete_command"] + command: Option, +) -> Result<(), Error> { + poise::builtins::help( + ctx, + command.as_deref(), + poise::builtins::HelpConfiguration { + extra_text_at_bottom: "\ +This bot is very much a work in progress. Commands will change and may break.", + show_context_menu_commands: true, + ..Default::default() + }, + ) + .await?; + Ok(()) +} + +fn setup_config() -> Result<(), Error> { + SETTINGS + .write() + .unwrap() + .merge( + glob("data/config/*") + .unwrap() + .map(|path| File::from(path.unwrap())) + .collect::>(), + ) + .unwrap(); + + println!("{:#?}", SETTINGS.read()); + Ok(()) +} + +async fn app() -> Result<(), Error> { + let discord = SETTINGS.read().unwrap().get_table("discord").unwrap(); + + let mut owners: HashSet = HashSet::new(); + owners.insert(UserId(117992484310745097)); + + let prefix: String = discord + .get("prefix") + .expect("Config error, please set the discord[token] value") + .clone() + .into_str() + .expect("Config error, please make sure discord[token] is a string"); + let options = poise::FrameworkOptions { + commands: vec![ + help(), + register(), + commands::invites::invites(), + commands::schedule::schedule(), + commands::boop(), + commands::planning::get_command(), + // poise::Command { + // subcommands: vec![ + // commands::planning::series(), + // commands::planning::sessions(), + // commands::planning::events(), + // // Let's make sure poise isn't confused by the duplicate names! + // // commands::planning::planning(), + // ], + // ..commands::planning::planning() + // }, + ], + prefix_options: poise::PrefixFrameworkOptions { + prefix: Some(prefix.into()), + edit_tracker: Some(poise::EditTracker::for_timespan( + std::time::Duration::from_secs(3600), + )), + additional_prefixes: vec![ + poise::Prefix::Regex(Regex::new("(?i)ol'? rusty please").unwrap()), + poise::Prefix::Regex(Regex::new("(?i)Oi Rusty please").unwrap()), + ], + ..Default::default() + }, + on_error: |error| Box::pin(on_error(error)), + pre_command: |ctx| { + Box::pin(async move { + println!("Executing command {}...", ctx.command().qualified_name); + }) + }, + post_command: |ctx| { + Box::pin(async move { + println!("Executed command {}!", ctx.command().qualified_name); + }) + }, + owners, + ..Default::default() + }; + + // let discord = SETTINGS.read().unwrap().get_table("discord").unwrap(); + let token = discord + .get("token") + .expect("Config error, please set the discord[token] value") + .clone() + .into_str() + .expect("Config error, please make sure discord[token] is a string"); + + let database = sqlx::sqlite::SqlitePoolOptions::new() + .max_connections(5) + .connect_with( + "sqlite:data/database.db" + .parse::()? + .create_if_missing(true), + ) + .await?; + sqlx::migrate!("./migrations").run(&database).await?; + + poise::Framework::build() + .token(token) + .user_data_setup(move |_ctx, _ready, _framework| { + Box::pin(async move { Ok(Data { database: database }) }) + }) + .options(options) + .run() + .await + .unwrap(); + + Ok(()) +} + +#[tokio::main] +async fn main() { + print!("Starting the bot"); + setup_config().unwrap(); + // env_logger::init(); + // init_log(); + SimpleLogger::init(LevelFilter::Warn, simplelog::Config::default()).unwrap(); + + if let Err(e) = app().await { + log::error!("{}", e); + std::process::exit(1); + } +}