Compare commits
10 commits
92507d10e6
...
7872513949
Author | SHA1 | Date | |
---|---|---|---|
|
7872513949 | ||
|
1db9ebdde2 | ||
|
df60ac6aae | ||
|
5d2f9a777c | ||
|
fff7611e9b | ||
|
8d8662be75 | ||
|
86cc799988 | ||
|
5caf820dc0 | ||
|
12b934fcb4 | ||
|
8ac7702d8c |
232
Cargo.lock
generated
232
Cargo.lock
generated
|
@ -165,16 +165,16 @@ checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
|
|||
|
||||
[[package]]
|
||||
name = "cached"
|
||||
version = "0.38.0"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27e6092f8c7ba6e65a46f6f26d7d7997201d3a6f0e69ff5d2440b930d7c0513a"
|
||||
checksum = "5e5877db5d1af7fae60d06b5db9430b68056a69b3582a0be8e3691e87654aeb6"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"async_once",
|
||||
"cached_proc_macro",
|
||||
"cached_proc_macro_types",
|
||||
"futures",
|
||||
"hashbrown",
|
||||
"hashbrown 0.13.2",
|
||||
"instant",
|
||||
"lazy_static",
|
||||
"once_cell",
|
||||
|
@ -184,12 +184,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cached_proc_macro"
|
||||
version = "0.15.0"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "751f7f4e7a091545e7f6c65bacc404eaee7e87bfb1f9ece234a1caa173dc16f2"
|
||||
checksum = "e10ca87c81aaa3a949dbbe2b5e6c2c45dbc94ba4897e45ea31ff9ec5087be3dc"
|
||||
dependencies = [
|
||||
"cached_proc_macro_types",
|
||||
"darling 0.13.4",
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
@ -391,43 +392,19 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.13.4"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
|
||||
checksum = "c0808e1bd8671fb44a113a14e13497557533369847788fa2ae912b6ebfce9fa8"
|
||||
dependencies = [
|
||||
"darling_core 0.13.4",
|
||||
"darling_macro 0.13.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02"
|
||||
dependencies = [
|
||||
"darling_core 0.14.1",
|
||||
"darling_macro 0.14.1",
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.13.4"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "649c91bc01e8b1eac09fb91e8dbc7d517684ca6be8ebc75bb9cafc894f9fdb6f"
|
||||
checksum = "001d80444f28e193f30c2f293455da62dcf9a6b29918a4253152ae2b1de592cb"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
|
@ -439,22 +416,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.13.4"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
|
||||
checksum = "b36230598a2d5de7ec1c6f51f72d8a99a9208daff41de2084d06e3fd3ea56685"
|
||||
dependencies = [
|
||||
"darling_core 0.13.4",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5"
|
||||
dependencies = [
|
||||
"darling_core 0.14.1",
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
@ -466,7 +432,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "3495912c9c1ccf2e18976439f4443f3fee0fd61f424ff99fde6a66b15ecb448f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"hashbrown",
|
||||
"hashbrown 0.12.3",
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
"serde",
|
||||
|
@ -761,6 +727,12 @@ dependencies = [
|
|||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
|
@ -891,7 +863,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
"hashbrown 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1074,11 +1046,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lru"
|
||||
version = "0.7.8"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a"
|
||||
checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909"
|
||||
dependencies = [
|
||||
"hashbrown",
|
||||
"hashbrown 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1142,14 +1114,14 @@ dependencies = [
|
|||
"libc",
|
||||
"log",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys",
|
||||
"windows-sys 0.36.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mysql_async"
|
||||
version = "0.30.0"
|
||||
version = "0.31.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "456207bb9636a0fdade67a64cea7bdebe6730c3c16ee5e34f2c481838ee5a39e"
|
||||
checksum = "2975442c70450b8f3a0400216321f6ab7b8bda177579f533d312ac511f913655"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"crossbeam",
|
||||
|
@ -1166,6 +1138,7 @@ dependencies = [
|
|||
"pem",
|
||||
"percent-encoding",
|
||||
"pin-project",
|
||||
"priority-queue",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"socket2",
|
||||
|
@ -1179,9 +1152,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mysql_common"
|
||||
version = "0.29.1"
|
||||
version = "0.29.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "522f2f30f72de409fc04f88df25a031f98cfc5c398a94e0b892cabb33a1464cb"
|
||||
checksum = "9006c95034ccf7b903d955f210469119f6c3477fc9c9e7a7845ce38a3e665c2a"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bigdecimal",
|
||||
|
@ -1205,7 +1178,7 @@ dependencies = [
|
|||
"saturating",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha-1",
|
||||
"sha1",
|
||||
"sha2",
|
||||
"smallvec",
|
||||
"subprocess",
|
||||
|
@ -1380,7 +1353,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a"
|
||||
dependencies = [
|
||||
"dlv-list",
|
||||
"hashbrown",
|
||||
"hashbrown 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1403,7 +1376,7 @@ dependencies = [
|
|||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-sys",
|
||||
"windows-sys 0.36.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1517,9 +1490,9 @@ checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
|
|||
|
||||
[[package]]
|
||||
name = "poise"
|
||||
version = "0.3.0"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6c01d22dcda434b0dfe956c60f6ac9b0352c4c2f4af852afb3155a971cd306d"
|
||||
checksum = "2ca787e4e516076de1995a83ee05fbdfed71d072ea0da3df018318db42a87803"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"derivative",
|
||||
|
@ -1536,11 +1509,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "poise_macros"
|
||||
version = "0.3.0"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52ff861b6a52ec47bc54eb17424c025feeb040e82836036276c25dda045a8a0c"
|
||||
checksum = "b80c1f4e04114527f9d41ed6bb31707a095276f51bb0aef3ca11f062b25a67c4"
|
||||
dependencies = [
|
||||
"darling 0.14.1",
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
|
@ -1552,6 +1525,16 @@ version = "0.2.16"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
|
||||
[[package]]
|
||||
name = "priority-queue"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca9c6be70d989d21a136eb86c2d83e4b328447fac4a88dace2143c179c86267"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.19"
|
||||
|
@ -1560,9 +1543,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.43"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
|
||||
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -1790,7 +1773,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"windows-sys",
|
||||
"windows-sys 0.36.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1928,6 +1911,17 @@ dependencies = [
|
|||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "006769ba83e921b3085caa8334186b00cf92b4cb1a6cf4632fbccc8eff5c7549"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.2"
|
||||
|
@ -1956,13 +1950,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "simplelog"
|
||||
version = "0.11.2"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1348164456f72ca0116e4538bdaabb0ddb622c7d9f16387c725af3e96d6001c"
|
||||
checksum = "48dfff04aade74dd495b007c831cd6f4e0cee19c344dd9dc0884c0289b70a786"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"log",
|
||||
"termcolor",
|
||||
"time 0.3.13",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2099,8 +2093,15 @@ dependencies = [
|
|||
"libc",
|
||||
"num_threads",
|
||||
"serde",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
|
@ -2118,9 +2119,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.20.1"
|
||||
version = "1.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581"
|
||||
checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes",
|
||||
|
@ -2128,12 +2129,11 @@ dependencies = [
|
|||
"memchr",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"winapi",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2513,43 +2513,109 @@ version = "0.36.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_aarch64_msvc 0.36.1",
|
||||
"windows_i686_gnu 0.36.1",
|
||||
"windows_i686_msvc 0.36.1",
|
||||
"windows_x86_64_gnu 0.36.1",
|
||||
"windows_x86_64_msvc 0.36.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc 0.42.1",
|
||||
"windows_i686_gnu 0.42.1",
|
||||
"windows_i686_msvc 0.42.1",
|
||||
"windows_x86_64_gnu 0.42.1",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc 0.42.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.10.1"
|
||||
|
|
|
@ -6,16 +6,16 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
cached = "0.38"
|
||||
cached = "0.42"
|
||||
chrono = "0.4"
|
||||
config = "0.13"
|
||||
futures = { version = "0.3", default-features = false }
|
||||
glob = "0.3"
|
||||
lazy_static = "1"
|
||||
log = "0.4"
|
||||
mysql_async = "0.30"
|
||||
simplelog = "0.11.1"
|
||||
poise = { version = "0.3", features = ["collector"] }
|
||||
mysql_async = "0.31"
|
||||
simplelog = "0.12"
|
||||
poise = { version = "0.5", features = ["collector"] }
|
||||
rand = "0.8"
|
||||
regex = {version="1"}
|
||||
reqwest = "0.11"
|
||||
|
|
BIN
data/database.db
BIN
data/database.db
Binary file not shown.
|
@ -9,8 +9,6 @@ async fn autocomplete_command<'a>(ctx: Context<'_>, partial: &'a str) -> Vec<Str
|
|||
};
|
||||
|
||||
let stmt = conn.prep("SELECT sign FROM commands WHERE sign LIKE CONCAT('%', :partial, '%') AND enabled ORDER BY priority DESC, sign ASC LIMIT 25").await.unwrap();
|
||||
// let ding = con.exec(&stmt, params! {partial}).await?;
|
||||
// let iter = ding.into_iter().map(|a| a.to_string());
|
||||
let result = match conn.exec_iter(stmt, params! {partial}).await {
|
||||
Ok(blah) => blah
|
||||
.map_and_drop(|row| from_row::<String>(row))
|
||||
|
@ -29,7 +27,7 @@ pub async fn get_command(sign: &str, con: &mut Conn) -> Result<Option<String>, m
|
|||
Ok(a)
|
||||
}
|
||||
|
||||
// F1TV links throughout the seasons
|
||||
/// Run any of a collection of arbitrary commands
|
||||
#[poise::command(slash_command)]
|
||||
pub async fn coms(
|
||||
ctx: Context<'_>,
|
||||
|
@ -74,11 +72,11 @@ fn sky(input: &str) -> String {
|
|||
|
||||
fn sky_open(input: &str) -> Option<(String, String)> {
|
||||
match input.rsplit_once('{') {
|
||||
None => (return None),
|
||||
None => return None,
|
||||
Some((left, end)) => {
|
||||
if left.ends_with('\\') {
|
||||
match sky_open(left) {
|
||||
None => (return None),
|
||||
None => return None,
|
||||
Some((left, right)) => {
|
||||
let mut end: String = end.to_string();
|
||||
end.push('{');
|
||||
|
@ -95,11 +93,11 @@ fn sky_open(input: &str) -> Option<(String, String)> {
|
|||
|
||||
fn sky_closed(input: &str) -> Option<(String, String)> {
|
||||
match input.split_once('}') {
|
||||
None => (return None),
|
||||
None => return None,
|
||||
Some((left, end)) => {
|
||||
if left.ends_with('\\') {
|
||||
match sky_closed(end) {
|
||||
None => (return None),
|
||||
None => return None,
|
||||
Some((mid, right)) => {
|
||||
let mut start: String = left.to_string();
|
||||
start.push('}');
|
||||
|
|
|
@ -8,14 +8,11 @@ struct Message {
|
|||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct InviteData {
|
||||
// id: String,
|
||||
// token: String,
|
||||
// isUsed: bool,
|
||||
#[serde(rename = "isHighTier")]
|
||||
is_high_tier: bool,
|
||||
// isCustom: bool,
|
||||
}
|
||||
|
||||
/// Get information about an invite
|
||||
#[poise::command(slash_command, ephemeral)]
|
||||
pub async fn invites(
|
||||
ctx: Context<'_>,
|
||||
|
|
148
src/commands/links/all.rs
Normal file
148
src/commands/links/all.rs
Normal file
|
@ -0,0 +1,148 @@
|
|||
use crate::{commands::utils, Context, Error};
|
||||
use cached::proc_macro::cached;
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::info;
|
||||
|
||||
use super::{
|
||||
cmore::{self, CmoreEvent},
|
||||
eurosport::{self, ESEvents},
|
||||
nfl::{self, NFLEvent},
|
||||
viaplay::{self, ViaplayEvent},
|
||||
Timeframe,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Events {
|
||||
EuroSport(ESEvents),
|
||||
Viaplay(ViaplayEvent),
|
||||
NFL(NFLEvent),
|
||||
Cmore(CmoreEvent),
|
||||
}
|
||||
|
||||
impl Events {
|
||||
fn filter(&self, filter: &str) -> bool {
|
||||
if filter.is_empty() {
|
||||
return true;
|
||||
};
|
||||
match self {
|
||||
Events::EuroSport(event) => event.filter(&filter),
|
||||
Events::Viaplay(event) => event.filter(&filter),
|
||||
Events::NFL(event) => event.filter(&filter),
|
||||
Events::Cmore(event) => event.filter(&filter),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
Events::EuroSport(event) => event.to_string(),
|
||||
Events::Viaplay(event) => event.to_string(),
|
||||
Events::NFL(event) => event.to_string(),
|
||||
Events::Cmore(event) => event.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_key(&self) -> (DateTime<Utc>, String) {
|
||||
match self {
|
||||
Events::EuroSport(event) => event.get_key(),
|
||||
Events::Viaplay(event) => event.get_key(),
|
||||
Events::NFL(event) => event.get_key(),
|
||||
Events::Cmore(event) => event.get_key(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn comp(&self, when: &Timeframe) -> bool {
|
||||
match self {
|
||||
Events::EuroSport(event) => event.comp(when),
|
||||
Events::Viaplay(event) => event.comp(when),
|
||||
Events::NFL(event) => event.comp(when),
|
||||
Events::Cmore(event) => event.comp(when),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_euro() -> Vec<Events> {
|
||||
let url = super::super::super::SETTINGS
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_table("eurosport")
|
||||
.expect("Expecting an eurosport section in the config")
|
||||
.get("url")
|
||||
.expect("Config error, please set the eurosport[url] value")
|
||||
.clone()
|
||||
.into_string()
|
||||
.expect("Config error, please make sure eurosport[url] is a string");
|
||||
let events = eurosport::get_eurosport_events(url).await;
|
||||
match events {
|
||||
Some(events) => events
|
||||
.iter()
|
||||
.map(|e| Events::EuroSport(e.to_owned()))
|
||||
.collect(),
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_viaplay() -> Vec<Events> {
|
||||
match viaplay::get_schedule().await {
|
||||
Some(events) => events
|
||||
.iter()
|
||||
.map(|e| Events::Viaplay(e.to_owned()))
|
||||
.collect(),
|
||||
None => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_nfl() -> Vec<Events> {
|
||||
match nfl::get_current_schedule().await {
|
||||
Some(events) => events.iter().map(|e| Events::NFL(e.to_owned())).collect(),
|
||||
None => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_cmore() -> Vec<Events> {
|
||||
match cmore::get_schedule().await {
|
||||
Some(events) => events.iter().map(|e| Events::Cmore(e.to_owned())).collect(),
|
||||
None => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
#[cached(time = 3600)]
|
||||
async fn get_events() -> Vec<Events> {
|
||||
let mut events: Vec<Events> = vec![];
|
||||
events.extend(get_euro().await);
|
||||
events.extend(get_viaplay().await);
|
||||
events.extend(get_nfl().await);
|
||||
events.extend(get_cmore().await);
|
||||
events.sort_unstable_by_key(|event| (event.get_key()));
|
||||
events
|
||||
}
|
||||
|
||||
/// All events filtered (Eurosport, NFL, Viaplay)
|
||||
#[poise::command(slash_command, ephemeral)]
|
||||
pub async fn all(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Filter sessions for when they are/were happening"] timeframe: Timeframe,
|
||||
#[description = "Content to filter on"] filter: Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
let events = get_events().await;
|
||||
match events {
|
||||
events if events.len() == 0 => {
|
||||
ctx.say("No events found. Either it's not among the implemented providers or your search is too stringent").await?;
|
||||
}
|
||||
events => {
|
||||
info!("Found {} events from all events", events.len());
|
||||
let strings = events
|
||||
.into_iter()
|
||||
.filter(|e| e.comp(&timeframe))
|
||||
.filter(|e| match &filter {
|
||||
None => true,
|
||||
Some(f) => e.filter(f.as_str()),
|
||||
})
|
||||
.map(|e| e.to_string())
|
||||
.collect();
|
||||
let pages = utils::paginator(strings, 1900, "\n".to_string());
|
||||
|
||||
utils::paginate_string(ctx, pages).await?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
184
src/commands/links/cmore.rs
Normal file
184
src/commands/links/cmore.rs
Normal file
|
@ -0,0 +1,184 @@
|
|||
use crate::{commands::utils, Context, Error};
|
||||
use cached::proc_macro::cached;
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::{info, warn};
|
||||
use reqwest::header::AUTHORIZATION;
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::Timeframe;
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct CmoreEvent {
|
||||
#[serde(rename = "assetId")]
|
||||
id: u32,
|
||||
#[serde(rename = "asset")]
|
||||
data: CmoreData,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct CmoreData {
|
||||
#[serde(default)]
|
||||
description: String,
|
||||
title: String,
|
||||
subtitle: String,
|
||||
duration: i64,
|
||||
#[serde(rename = "liveBroadcastTime")]
|
||||
#[serde(with = "cmore_date")]
|
||||
start: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl CmoreEvent {
|
||||
pub fn filter(&self, filter: &str) -> bool {
|
||||
if filter.is_empty() {
|
||||
return true;
|
||||
};
|
||||
if self.data.description.contains(filter) {
|
||||
return true;
|
||||
}
|
||||
if self.data.title.contains(filter) {
|
||||
return true;
|
||||
}
|
||||
if self.data.subtitle.contains(filter) {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn comp(&self, when: &Timeframe) -> bool {
|
||||
let now = Utc::now();
|
||||
match when {
|
||||
Timeframe::Everything => true,
|
||||
Timeframe::Current => {
|
||||
self.data.start <= now
|
||||
&& self.data.start + chrono::Duration::seconds(self.data.duration) >= now
|
||||
}
|
||||
Timeframe::Future => {
|
||||
self.data.start + chrono::Duration::seconds(self.data.duration) >= now
|
||||
}
|
||||
Timeframe::Past => {
|
||||
self.data.start + chrono::Duration::seconds(self.data.duration) <= now
|
||||
} // _ => self.data.times.end >= now,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> String {
|
||||
format!(
|
||||
"```md\n[{title}]({subtitle})```(<t:{start}:R>-<t:{end}:R>) https://tom.al/ms/cm/{id}",
|
||||
title = self.data.title,
|
||||
subtitle = self.data.subtitle,
|
||||
start = self.data.start.timestamp(),
|
||||
end = self.data.start.timestamp() + self.data.duration,
|
||||
id = self.id
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_key(&self) -> (DateTime<Utc>, String) {
|
||||
(self.data.start, self.data.description.clone())
|
||||
}
|
||||
}
|
||||
|
||||
mod cmore_date {
|
||||
use chrono::{DateTime, TimeZone, Utc};
|
||||
use serde::{self, Deserialize, Deserializer};
|
||||
|
||||
const FORMAT: &'static str = "%Y-%m-%dT%H:%M:%SZ";
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
Utc.datetime_from_str(&s, FORMAT)
|
||||
.map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
#[cached(time = 3600)]
|
||||
pub async fn get_schedule() -> Option<Vec<CmoreEvent>> {
|
||||
let token = super::super::super::SETTINGS
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_table("morningstreams")
|
||||
.unwrap()
|
||||
.get("token")
|
||||
.expect("Config error, please set the morningstreams[token] value")
|
||||
.clone()
|
||||
.into_string()
|
||||
.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/hightier/cmore/schedule"
|
||||
))
|
||||
.header(AUTHORIZATION, token)
|
||||
.send()
|
||||
.await;
|
||||
|
||||
let result: Option<Vec<CmoreEvent>> = match req {
|
||||
Err(e) => {
|
||||
warn!("Error getting Cmore schedule {}", e);
|
||||
None
|
||||
}
|
||||
Ok(req) if req.status().as_u16() == 404 => {
|
||||
warn!("404 on getting cmore events");
|
||||
None
|
||||
}
|
||||
Ok(req) if req.status().as_u16() == 200 => {
|
||||
let data = req.json::<Vec<CmoreEvent>>().await;
|
||||
match data {
|
||||
Ok(d) => {
|
||||
Some(d) // .iter().map(|e| e.asset.clone()).collect())
|
||||
}
|
||||
|
||||
Err(e) => {
|
||||
warn!("Error getting Cmore schedule {}", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(req) => {
|
||||
warn!(
|
||||
"Unhandled status when parsing Cmore request {}",
|
||||
req.status()
|
||||
);
|
||||
None
|
||||
}
|
||||
};
|
||||
result
|
||||
}
|
||||
|
||||
/// Cmore events listing
|
||||
#[poise::command(slash_command, ephemeral)]
|
||||
pub async fn cmore(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Filter sessions for when they are/were happening, defaults to future"]
|
||||
timeframe: Option<super::Timeframe>,
|
||||
#[description = "Content to filter on"] filter: Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
let tf = match timeframe {
|
||||
None => Timeframe::Future,
|
||||
Some(tf) => tf,
|
||||
};
|
||||
let events: Option<Vec<CmoreEvent>> = get_schedule().await;
|
||||
match events {
|
||||
None => {
|
||||
ctx.say("Unable to get the events, try again later (it's cached so wait a bit...)")
|
||||
.await?;
|
||||
}
|
||||
Some(evs) => {
|
||||
info!("Found {} events from cmore", evs.len());
|
||||
let filtered: Vec<String> = evs
|
||||
.into_iter()
|
||||
.filter(|e| e.comp(&tf))
|
||||
.filter(|e| match &filter {
|
||||
None => true,
|
||||
Some(f) => e.filter(f.as_str()),
|
||||
})
|
||||
.map(|e| e.to_string())
|
||||
.collect();
|
||||
let pages = utils::paginator(filtered, 1900, "\n".to_string());
|
||||
utils::paginate_string(ctx, pages).await?;
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
|
@ -108,7 +108,7 @@ struct Eurosport {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct ESEvents {
|
||||
pub struct ESEvents {
|
||||
id: String,
|
||||
sport: Option<String>,
|
||||
name: String,
|
||||
|
@ -119,7 +119,7 @@ struct ESEvents {
|
|||
}
|
||||
|
||||
impl ESEvents {
|
||||
fn filter(&self, filter: &str) -> bool {
|
||||
pub fn filter(&self, filter: &str) -> bool {
|
||||
if self.name.to_lowercase().contains(filter) {
|
||||
return true;
|
||||
};
|
||||
|
@ -137,20 +137,19 @@ impl ESEvents {
|
|||
return false;
|
||||
}
|
||||
|
||||
fn comp(&self, when: &Option<Timeframe>) -> bool {
|
||||
pub fn comp(&self, when: &Timeframe) -> bool {
|
||||
let now = Utc::now();
|
||||
match when {
|
||||
Some(Timeframe::Everything) => true,
|
||||
Some(Timeframe::Current) => self.start <= now && self.end >= now,
|
||||
Some(Timeframe::Future) => self.end >= now,
|
||||
Some(Timeframe::Past) => self.end <= now,
|
||||
_ => self.end >= now,
|
||||
Timeframe::Everything => true,
|
||||
Timeframe::Current => self.start <= now && self.end >= now,
|
||||
Timeframe::Future => self.end >= now,
|
||||
Timeframe::Past => self.end <= now,
|
||||
// _ => self.end >= now,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_string(&self) -> String {
|
||||
pub fn to_string(&self) -> String {
|
||||
match &self.sport {
|
||||
// None => format!("```md\n({}) {}```\n", self.name, self.secondary),
|
||||
None => format!(
|
||||
"```md\n({}) {}```(<t:{}:R>-<t:{}:R>) {}\n https://tom.al/ms/euro/{}",
|
||||
self.name,
|
||||
|
@ -172,6 +171,10 @@ impl ESEvents {
|
|||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_key(&self) -> (DateTime<Utc>, String) {
|
||||
(self.start, self.name.clone())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_events(v: Eurosport) -> Result<Vec<ESEvents>, serde_json::Error> {
|
||||
|
@ -233,7 +236,7 @@ fn get_events(v: Eurosport) -> Result<Vec<ESEvents>, serde_json::Error> {
|
|||
|
||||
#[cached(time = 3600)]
|
||||
#[allow(dead_code)]
|
||||
async fn get_eurosport_events(url: String) -> Option<Vec<ESEvents>> {
|
||||
pub async fn get_eurosport_events(url: String) -> Option<Vec<ESEvents>> {
|
||||
let cookie = super::super::super::SETTINGS
|
||||
.read()
|
||||
.unwrap()
|
||||
|
@ -282,19 +285,30 @@ async fn get_eurosport_events(url: String) -> Option<Vec<ESEvents>> {
|
|||
}
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
Ok(req) => {
|
||||
warn!(
|
||||
"Eurosport Unhandled request result {}",
|
||||
req.status().as_u16()
|
||||
);
|
||||
None
|
||||
}
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
// Eurosport player events
|
||||
#[poise::command(slash_command)]
|
||||
/// Eurosport player events
|
||||
#[poise::command(slash_command, ephemeral)]
|
||||
pub async fn eurosport(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Filter sessions for when they are/were happening, defaults to future"]
|
||||
timeframe: Option<Timeframe>,
|
||||
#[description = "Content to filter on"] filter: Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
let tf = match timeframe {
|
||||
None => Timeframe::Future,
|
||||
Some(tf) => tf,
|
||||
};
|
||||
|
||||
let url = super::super::super::SETTINGS
|
||||
.read()
|
||||
.unwrap()
|
||||
|
@ -314,7 +328,7 @@ pub async fn eurosport(
|
|||
info!("Found {} events from eurosport", evs.len());
|
||||
let strings = evs
|
||||
.into_iter()
|
||||
.filter(|e| e.comp(&timeframe))
|
||||
.filter(|e| e.comp(&tf))
|
||||
.filter(|e| match &filter {
|
||||
None => true,
|
||||
Some(f) => e.filter(f.as_str()),
|
||||
|
@ -336,6 +350,10 @@ pub async fn proc_olympics(
|
|||
timeframe: Option<Timeframe>,
|
||||
filter: Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
let tf = match timeframe {
|
||||
None => Timeframe::Future,
|
||||
Some(tf) => tf,
|
||||
};
|
||||
let url = super::super::super::SETTINGS
|
||||
.read()
|
||||
.unwrap()
|
||||
|
@ -355,7 +373,7 @@ pub async fn proc_olympics(
|
|||
info!("Found {} events from eurosport olympics ", evs.len());
|
||||
let strings = evs
|
||||
.into_iter()
|
||||
.filter(|e| e.comp(&timeframe))
|
||||
.filter(|e| e.comp(&tf))
|
||||
.filter(|e| match &filter {
|
||||
None => true,
|
||||
Some(f) => e.filter(f.as_str()),
|
||||
|
|
|
@ -12,6 +12,7 @@ async fn autocomplete_season<'a>(
|
|||
) -> impl Iterator<Item = String> + 'a {
|
||||
(1981..2023)
|
||||
.map(|n: u32| n.to_string())
|
||||
.rev()
|
||||
.filter(move |e| e.starts_with(&partial))
|
||||
.map(|e| e.to_string())
|
||||
}
|
||||
|
@ -31,7 +32,6 @@ impl MSEvent {
|
|||
fn get_title(&self) -> String {
|
||||
let title = &self.metadata.attributes.series.replace("FORMULA", "F");
|
||||
format!("**{}: {}**", title, self.metadata.brief)
|
||||
// format!("", sport=self.content.format.sport, title=self.content.title, synopsis=self.content.synopsis, start=self.times.start.timestamp(), end=self.times.end.timestamp(), desc=self.content.description, id=self.system.product_key)
|
||||
}
|
||||
|
||||
fn get_value(&self) -> String {
|
||||
|
@ -194,8 +194,8 @@ async fn get_sessions(season: String) -> Option<Season> {
|
|||
result
|
||||
}
|
||||
|
||||
// F1TV links throughout the seasons
|
||||
#[poise::command(slash_command)]
|
||||
/// F1TV links throughout the seasons
|
||||
#[poise::command(slash_command, ephemeral)]
|
||||
pub async fn f1(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Which season to pull from?"]
|
||||
|
@ -237,7 +237,7 @@ pub async fn f1(
|
|||
})
|
||||
.await?;
|
||||
|
||||
while let Some(mci) = serenity::CollectComponentInteraction::new(ctx.discord())
|
||||
while let Some(mci) = serenity::CollectComponentInteraction::new(ctx)
|
||||
.channel_id(ctx.channel_id())
|
||||
.filter(move |mci| mci.data.custom_id == content_id.to_string())
|
||||
.await
|
||||
|
@ -247,7 +247,7 @@ pub async fn f1(
|
|||
let ses = get_event(session).await;
|
||||
println!("Now responding to interaction");
|
||||
match mci
|
||||
.create_interaction_response(ctx.discord(), |ir| {
|
||||
.create_interaction_response(ctx, |ir| {
|
||||
ir.kind(serenity::InteractionResponseType::UpdateMessage)
|
||||
.interaction_response_data(|m| match ses {
|
||||
None => m.content("Unable to get these events :("),
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
use crate::{Context, Error};
|
||||
|
||||
mod all;
|
||||
mod cmore;
|
||||
mod eurosport;
|
||||
mod f1;
|
||||
mod nfl;
|
||||
mod viaplay;
|
||||
mod wrc;
|
||||
|
||||
|
@ -17,49 +20,19 @@ pub enum Timeframe {
|
|||
Everything,
|
||||
}
|
||||
|
||||
// #[derive(Debug, poise::ChoiceParameter)]
|
||||
// pub enum Source {
|
||||
// #[name = "Get links for the Eurosport player"]
|
||||
// Eurosport,
|
||||
// // #[name = "Get links for the apocalympics Eurosport player"]
|
||||
// // Olympics,
|
||||
// #[name = "Get WRC links for the WRC player"]
|
||||
// WRC,
|
||||
// #[name = "Get Viaplay links for the Viaplay player"]
|
||||
// Viaplay,
|
||||
// // #[name = "F1 content for the weekend"]
|
||||
// // F1,
|
||||
// }
|
||||
|
||||
/// Get links for high tier commands.
|
||||
// #[poise::command(slash_command)]
|
||||
// pub async fn links2(
|
||||
// ctx: Context<'_>,
|
||||
// #[description = "Where to git the juicy links from?"] source: Source,
|
||||
// #[description = "Filter sessions for when they are/were happening, defaults to future"]
|
||||
// timeframe: Option<Timeframe>,
|
||||
// #[description = "Content to filter on"] filter: Option<String>,
|
||||
// ) -> Result<(), Error> {
|
||||
// if !utils::high_tier(ctx).await {
|
||||
// ctx.say("This command can only be used in high tier channels for security")
|
||||
// .await?;
|
||||
// return Ok(());
|
||||
// }
|
||||
|
||||
// match source {
|
||||
// Source::Eurosport => eurosport::proc_eurosport(ctx, timeframe, filter).await,
|
||||
// // Source::Olympics => eurosport::proc_olympics(ctx, timeframe, filter).await,
|
||||
// Source::WRC => wrc::wrc(ctx).await,
|
||||
// Source::Viaplay => viaplay::viaplay(ctx, timeframe, filter).await,
|
||||
// // Source::F1 => f1::proc_f1(ctx, timeframe, filter).await,
|
||||
// }
|
||||
|
||||
// // Ok(())
|
||||
// }
|
||||
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
subcommands("viaplay::viaplay", "eurosport::eurosport", "wrc::wrc", "f1::f1")
|
||||
subcommands(
|
||||
"viaplay::viaplay",
|
||||
"viaplay::viaplay_schedule",
|
||||
"eurosport::eurosport",
|
||||
"wrc::wrc",
|
||||
"f1::f1",
|
||||
"nfl::nfl",
|
||||
"cmore::cmore",
|
||||
"all::all"
|
||||
),
|
||||
ephemeral
|
||||
)]
|
||||
pub async fn links(ctx: Context<'_>) -> Result<(), Error> {
|
||||
ctx.say("Hello there!").await?;
|
||||
|
|
240
src/commands/links/nfl.rs
Normal file
240
src/commands/links/nfl.rs
Normal file
|
@ -0,0 +1,240 @@
|
|||
use crate::{commands::utils, Context, Error};
|
||||
use cached::proc_macro::cached;
|
||||
use chrono::{DateTime, Duration, Utc};
|
||||
use log::{info, warn};
|
||||
use reqwest::header::AUTHORIZATION;
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::Timeframe;
|
||||
|
||||
mod str_to_u8 {
|
||||
use serde::{self, Deserialize, Deserializer};
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<u8, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
Ok(s.parse::<u8>().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
mod nfl_date {
|
||||
use chrono::{DateTime, TimeZone, Utc};
|
||||
use serde::{self, Deserialize, Deserializer};
|
||||
|
||||
const FORMAT: &'static str = "%Y-%m-%dT%H:%M:%S.%fZ";
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
Utc.datetime_from_str(&s, FORMAT)
|
||||
.map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct NFLContext {
|
||||
#[serde(with = "str_to_u8")]
|
||||
current_week: u8,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct NFLEvent {
|
||||
home_nick_name: String,
|
||||
visitor_nick_name: String,
|
||||
#[serde(with = "nfl_date")]
|
||||
game_date_time_utc: DateTime<Utc>,
|
||||
video: NFLVideo,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct NFLVideo {
|
||||
title: String,
|
||||
video_id: String,
|
||||
}
|
||||
|
||||
impl NFLEvent {
|
||||
pub fn filter(&self, filter: &str) -> bool {
|
||||
if filter.is_empty() {
|
||||
return true;
|
||||
};
|
||||
if self.video.title.contains(filter) {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn comp(&self, when: &Timeframe) -> bool {
|
||||
let now = Utc::now();
|
||||
match when {
|
||||
Timeframe::Everything => true,
|
||||
Timeframe::Current => {
|
||||
self.game_date_time_utc <= now
|
||||
&& (self.game_date_time_utc + Duration::minutes(240)) >= now
|
||||
}
|
||||
Timeframe::Future => (self.game_date_time_utc + Duration::minutes(240)) >= now,
|
||||
Timeframe::Past => self.game_date_time_utc <= now,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> String {
|
||||
format!(
|
||||
"```fix\n{home}-{away} ||{title}```<t:{time}:R> https://tom.al/ms/nfl/{id}",
|
||||
title = self.video.title,
|
||||
id = self.video.video_id,
|
||||
time = self.game_date_time_utc.timestamp(),
|
||||
home = self.home_nick_name,
|
||||
away = self.visitor_nick_name,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_key(&self) -> (DateTime<Utc>, String) {
|
||||
(self.game_date_time_utc, self.video.title.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
#[cached(time = 3600)]
|
||||
async fn get_week() -> Option<NFLContext> {
|
||||
let token = super::super::super::SETTINGS
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_table("morningstreams")
|
||||
.unwrap()
|
||||
.get("token")
|
||||
.expect("Config error, please set the morningstreams[token] value")
|
||||
.clone()
|
||||
.into_string()
|
||||
.expect("Config error, please make sure morningstreams[token] is a string");
|
||||
let client = reqwest::Client::new();
|
||||
let req = client
|
||||
.get("https://api.morningstreams.com/api/hightier/nfl/current-context")
|
||||
.header(AUTHORIZATION, token)
|
||||
.send()
|
||||
.await;
|
||||
|
||||
match req {
|
||||
Err(e) => {
|
||||
warn!("Error getting NFL context {}", e);
|
||||
None
|
||||
}
|
||||
Ok(req) => match req.json::<NFLContext>().await {
|
||||
Ok(data) => Some(data),
|
||||
Err(e) => {
|
||||
warn!("Error parsing NFL context {}", e);
|
||||
None
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_current_schedule() -> Option<Vec<NFLEvent>> {
|
||||
match get_week().await {
|
||||
None => return None,
|
||||
Some(w) => return get_schedule(w.current_week).await,
|
||||
}
|
||||
}
|
||||
|
||||
#[cached(time = 3600)]
|
||||
async fn get_schedule(week: u8) -> Option<Vec<NFLEvent>> {
|
||||
let token = super::super::super::SETTINGS
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_table("morningstreams")
|
||||
.unwrap()
|
||||
.get("token")
|
||||
.expect("Config error, please set the morningstreams[token] value")
|
||||
.clone()
|
||||
.into_string()
|
||||
.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/hightier/nfl/schedule/{}",
|
||||
week
|
||||
))
|
||||
.header(AUTHORIZATION, token)
|
||||
.send()
|
||||
.await;
|
||||
|
||||
let result: Option<Vec<NFLEvent>> = match req {
|
||||
Err(e) => {
|
||||
warn!("Error getting NFL schedule {}", e);
|
||||
None
|
||||
}
|
||||
Ok(req) if req.status().as_u16() == 404 => {
|
||||
warn!("404 on getting NFL events");
|
||||
None
|
||||
}
|
||||
Ok(req) if req.status().as_u16() == 200 => {
|
||||
let data = req.json::<Vec<NFLEvent>>().await;
|
||||
match data {
|
||||
Ok(d) => Some(d),
|
||||
Err(e) => {
|
||||
warn!("Error getting NFL schedule {}", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(req) => {
|
||||
warn!("Unhandled status when parsing NFL request {}", req.status());
|
||||
None
|
||||
}
|
||||
};
|
||||
result
|
||||
}
|
||||
|
||||
/// NFL events listing
|
||||
#[poise::command(slash_command, ephemeral)]
|
||||
pub async fn nfl(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Filter sessions for when they are/were happening, defaults to future"]
|
||||
timeframe: Option<super::Timeframe>,
|
||||
#[description = "Content to filter on"] filter: Option<String>,
|
||||
#[description = "Which game week? (Defaults to current)"] week: Option<u8>,
|
||||
) -> Result<(), Error> {
|
||||
let tf = match timeframe {
|
||||
None => Timeframe::Future,
|
||||
Some(tf) => tf,
|
||||
};
|
||||
|
||||
let get_week: u8 = match week {
|
||||
Some(w) => w,
|
||||
None => match get_week().await {
|
||||
None => {
|
||||
ctx.say("Error getting current week data, try setting one manually")
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
Some(w) => w.current_week,
|
||||
},
|
||||
};
|
||||
|
||||
let events: Option<Vec<NFLEvent>> = get_schedule(get_week).await;
|
||||
match events {
|
||||
None => {
|
||||
ctx.say("Unable to get the events, try a different game week or try again later (it's cached so wait a bit...)")
|
||||
.await?;
|
||||
}
|
||||
Some(evs) => {
|
||||
info!("Found {} events from NFL", evs.len());
|
||||
let filtered: Vec<String> = evs
|
||||
.into_iter()
|
||||
.filter(|e| e.comp(&tf))
|
||||
.filter(|e| match &filter {
|
||||
None => true,
|
||||
Some(f) => e.filter(f.as_str()),
|
||||
})
|
||||
.map(|e| e.to_string())
|
||||
.collect();
|
||||
let pages = utils::paginator(filtered, 1900, "\n".to_string());
|
||||
utils::paginate_string(ctx, pages).await?;
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
|
@ -2,7 +2,7 @@ use std::{collections::HashSet, fmt};
|
|||
|
||||
use crate::{commands::utils, Context, Error};
|
||||
use cached::proc_macro::cached;
|
||||
use chrono::{DateTime, Utc};
|
||||
use chrono::{DateTime, Duration, NaiveDate, Utc};
|
||||
use futures::{Stream, StreamExt};
|
||||
use log::{info, warn};
|
||||
use reqwest::header::AUTHORIZATION;
|
||||
|
@ -10,21 +10,8 @@ use serde::Deserialize;
|
|||
|
||||
use super::Timeframe;
|
||||
|
||||
// const translations: HashMap<String, String> = HashMap::from([
|
||||
// ("Valioliiga", "Premier league"),
|
||||
// ("Gjensidige Kvindeliga", "Mutual Women's League (Norway)"),
|
||||
// ("Tanskan 1. divisioona", "Danish 1st Division"),
|
||||
// ("Bundesliiga", "Bundesliga"),
|
||||
// ("2. Bundesliiga", "2. Bundesliga"),
|
||||
// ]);
|
||||
|
||||
// #[derive(Deserialize, Clone)]
|
||||
// struct ViaplaySchedule {
|
||||
// events: Vec<ViaplayEvent>,
|
||||
// }
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
struct ViaplayEvent {
|
||||
pub struct ViaplayEvent {
|
||||
content: Content,
|
||||
#[serde(rename = "epg")]
|
||||
times: EPG,
|
||||
|
@ -32,28 +19,37 @@ struct ViaplayEvent {
|
|||
}
|
||||
|
||||
impl ViaplayEvent {
|
||||
fn filter(&self, filter: &str) -> bool {
|
||||
pub fn filter(&self, filter: &str) -> bool {
|
||||
if filter.is_empty() {
|
||||
return true;
|
||||
};
|
||||
if self.content.format.sport.contains(filter) {
|
||||
return true;
|
||||
}
|
||||
if self.content.description.contains(filter) {
|
||||
return true;
|
||||
}
|
||||
if self.content.title.contains(filter) {
|
||||
return true;
|
||||
}
|
||||
if self.content.synopsis.contains(filter) {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn comp(&self, when: &Option<Timeframe>) -> bool {
|
||||
pub fn comp(&self, when: &Timeframe) -> bool {
|
||||
let now = Utc::now();
|
||||
match when {
|
||||
Some(Timeframe::Everything) => true,
|
||||
Some(Timeframe::Current) => self.times.start <= now && self.times.end >= now,
|
||||
Some(Timeframe::Future) => self.times.end >= now,
|
||||
Some(Timeframe::Past) => self.times.end <= now,
|
||||
_ => self.times.end >= now,
|
||||
Timeframe::Everything => true,
|
||||
Timeframe::Current => self.times.start <= now && self.times.end >= now,
|
||||
Timeframe::Future => self.times.end >= now,
|
||||
Timeframe::Past => self.times.end <= now,
|
||||
// _ => self.times.end >= now,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_string(&self) -> String {
|
||||
pub fn to_string(&self) -> String {
|
||||
format!("```md\n[{sport}]({title}) {synopsis}```(<t:{start}:R>-<t:{end}:R>) {desc}\nhttps://tom.al/ms/vp/{id}", sport=self.content.format.sport, title=self.content.title, synopsis=self.content.synopsis, start=self.times.start.timestamp(), end=self.times.end.timestamp(), desc=self.content.description, id=self.system.product_key)
|
||||
}
|
||||
|
||||
|
@ -63,18 +59,20 @@ impl ViaplayEvent {
|
|||
Some(s) => self.content.format.sport.contains(s),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_key(&self) -> (DateTime<Utc>, String) {
|
||||
(self.times.start, self.content.title.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ViaplayEvent {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// Use `self.number` to refer to each positional data point.
|
||||
// write!(f, "```md\n[{sport}]({title}) {synopsis}```(<t:{start}:R>-<t:{end}:R>) {desc}\nhttps://tom.al/ms/vp/{id}", sport=self.content.format.sport, title=self.content.title, synopsis=self.content.synopsis, start=self.times.start.timestamp(), end=self.times.end.timestamp(), desc=self.content.description, id=self.system.product_key)
|
||||
write!(f, "{}", self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
struct Content {
|
||||
pub struct Content {
|
||||
format: Format,
|
||||
title: String,
|
||||
#[serde(rename = "originalTitle")]
|
||||
|
@ -96,7 +94,7 @@ struct Format {
|
|||
sport: String,
|
||||
}
|
||||
#[derive(Deserialize, Clone)]
|
||||
struct EPG {
|
||||
pub struct EPG {
|
||||
#[serde(with = "viaplay_date")]
|
||||
start: DateTime<Utc>,
|
||||
#[serde(with = "viaplay_date")]
|
||||
|
@ -139,13 +137,16 @@ mod viaplay_sport {
|
|||
"Bundesliiga" => Ok("Bundesliga".to_string()),
|
||||
"2. Bundesliiga" => Ok("2. Bundesliga".to_string()),
|
||||
"Hevosurheilu" => Ok("Equestrian sport".to_string()),
|
||||
"Skotlannin Valioliiga" => Ok("Scottish Premier League".to_string()),
|
||||
"Käsipallon Bundesliiga" => Ok("Handball Bundesliga".to_string()),
|
||||
"Tanskan Bundesliiga" => Ok("Danish Superliga".to_string()),
|
||||
_ => Ok(s.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cached(time = 3600)]
|
||||
async fn get_schedule() -> Option<Vec<ViaplayEvent>> {
|
||||
#[cached(time = 7200)]
|
||||
pub async fn get_schedule() -> Option<Vec<ViaplayEvent>> {
|
||||
let token = super::super::super::SETTINGS
|
||||
.read()
|
||||
.unwrap()
|
||||
|
@ -195,7 +196,60 @@ async fn get_schedule() -> Option<Vec<ViaplayEvent>> {
|
|||
result
|
||||
}
|
||||
|
||||
#[cached(time = 3600)]
|
||||
#[cached(time = 36000)]
|
||||
pub async fn get_schedule_date(date: NaiveDate) -> Option<Vec<ViaplayEvent>> {
|
||||
let client = reqwest::Client::new();
|
||||
let req = client
|
||||
.get(format!(
|
||||
"https://content.viaplay.fi/pcdash-fi/urheilu?date={}",
|
||||
date.format("%Y-%m-%d")
|
||||
))
|
||||
.send()
|
||||
.await;
|
||||
|
||||
let result: Option<Vec<ViaplayEvent>> = match req {
|
||||
Err(e) => {
|
||||
warn!("Error getting Viaplay schedule {}", e);
|
||||
None
|
||||
}
|
||||
Ok(req) if req.status().as_u16() == 404 => {
|
||||
warn!("404 on getting VP events");
|
||||
None
|
||||
}
|
||||
Ok(req) if req.status().as_u16() == 200 => {
|
||||
let data = req.json::<serde_json::Value>().await;
|
||||
Some(
|
||||
serde_json::from_value::<Vec<ViaplayEvent>>(
|
||||
data.unwrap_or(serde_json::Value::Null)
|
||||
.get("_embedded")
|
||||
.unwrap_or(&serde_json::Value::Null)
|
||||
.get("viaplay:blocks")
|
||||
.unwrap_or(&serde_json::Value::Null)
|
||||
.as_array()
|
||||
.unwrap_or(&vec![])
|
||||
.last()
|
||||
.unwrap_or(&serde_json::Value::Null)
|
||||
.get("_embedded")
|
||||
.unwrap_or(&serde_json::Value::Null)
|
||||
.get("viaplay:products")
|
||||
.unwrap_or(&serde_json::Value::Null)
|
||||
.clone(),
|
||||
)
|
||||
.unwrap_or(vec![]),
|
||||
)
|
||||
}
|
||||
Ok(req) => {
|
||||
warn!(
|
||||
"Unhandled status when parsing viaplay request {}",
|
||||
req.status()
|
||||
);
|
||||
None
|
||||
}
|
||||
};
|
||||
result
|
||||
}
|
||||
|
||||
#[cached(time = 7200)]
|
||||
pub async fn get_sports() -> Vec<String> {
|
||||
// let events = get_schedule();
|
||||
if let Some(events) = get_schedule().await {
|
||||
|
@ -209,15 +263,6 @@ pub async fn get_sports() -> Vec<String> {
|
|||
}
|
||||
}
|
||||
|
||||
// #[allow(dead_code)]
|
||||
// async fn autocomplete_sport(_ctx: Context<'_>, partial: String) -> impl Stream<Item = String> {
|
||||
// // futures::stream::iter(get_sports().iter())
|
||||
// // .filter(move |name| futures::future::ready(name.contains(&partial)))
|
||||
// // .map(|name| name.to_string())
|
||||
// futures::stream::iter(get_sports().await)
|
||||
// .filter(move |name| futures::future::ready(name.contains(&partial)))
|
||||
// }
|
||||
|
||||
async fn autocomplete_sport<'a>(
|
||||
_ctx: Context<'_>,
|
||||
partial: &'a str,
|
||||
|
@ -227,8 +272,8 @@ async fn autocomplete_sport<'a>(
|
|||
.map(|name| name.to_string())
|
||||
}
|
||||
|
||||
//Viaplay events listing
|
||||
#[poise::command(slash_command)]
|
||||
/// Viaplay schedule for the day
|
||||
#[poise::command(slash_command, ephemeral)]
|
||||
pub async fn viaplay(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Filter sessions for when they are/were happening, defaults to future"]
|
||||
|
@ -238,6 +283,10 @@ pub async fn viaplay(
|
|||
#[autocomplete = "autocomplete_sport"]
|
||||
sport: Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
let tf = match timeframe {
|
||||
None => Timeframe::Future,
|
||||
Some(tf) => tf,
|
||||
};
|
||||
let events: Option<Vec<ViaplayEvent>> = get_schedule().await;
|
||||
match events {
|
||||
None => {
|
||||
|
@ -248,7 +297,7 @@ pub async fn viaplay(
|
|||
info!("Found {} events from viaplay", evs.len());
|
||||
let filtered: Vec<String> = evs
|
||||
.into_iter()
|
||||
.filter(|e| e.comp(&timeframe))
|
||||
.filter(|e| e.comp(&tf))
|
||||
.filter(|e| e.check_sport(&sport))
|
||||
.filter(|e| match &filter {
|
||||
None => true,
|
||||
|
@ -263,19 +312,40 @@ pub async fn viaplay(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// /// Another subcommand of `parent`
|
||||
// #[poise::command(slash_command)]
|
||||
// pub async fn child3(
|
||||
// ctx: Context<'_>,
|
||||
// #[description = "Where to git the juicy links from?"]
|
||||
// _source: super::Source,
|
||||
// #[description = "Filter sessions for when they are/were happening, defaults to future"]
|
||||
// _timeframe: Option<super::Timeframe>,
|
||||
// #[description = "Content to filter on"] filter: Option<String>,
|
||||
// #[description = "Filter for which sport to list (only Viaplay)"]
|
||||
// #[autocomplete = "autocomplete_sport"]
|
||||
// sport: Option<String>,
|
||||
// ) -> Result<(), Error> {
|
||||
// ctx.say("You invoked the second child command!").await?;
|
||||
// Ok(())
|
||||
// }
|
||||
/// Viaplay schedule for specified date
|
||||
#[poise::command(slash_command, ephemeral)]
|
||||
pub async fn viaplay_schedule(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Offset for amount fo days from today (0 for current day)"] offset: Option<i8>,
|
||||
#[description = "Content to filter on"] filter: Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
let offset: i8 = offset.unwrap_or_default();
|
||||
let date = Utc::now()
|
||||
.date_naive()
|
||||
.checked_add_signed(Duration::days(offset.into()))
|
||||
.expect("Expected an existing date as result");
|
||||
|
||||
let schedule = get_schedule_date(date).await;
|
||||
let title = format!("`Viaplay schedule for {}`", date.format("%d-%m-%Y"));
|
||||
match schedule {
|
||||
None => {
|
||||
ctx.say("Unable to get the events, try again later (it's cached so wait a bit...)")
|
||||
.await?;
|
||||
}
|
||||
Some(evs) => {
|
||||
info!("Found {} events from viaplay", evs.len());
|
||||
let filtered: Vec<String> = evs
|
||||
.into_iter()
|
||||
.filter(|e| match &filter {
|
||||
None => true,
|
||||
Some(f) => e.filter(f.as_str()),
|
||||
})
|
||||
.map(|e| e.to_string())
|
||||
.collect();
|
||||
let pages = utils::paginator_title(title, filtered, 1900, "\n".to_string());
|
||||
utils::paginate_string(ctx, pages).await?;
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -22,10 +22,6 @@ mod wrc_date {
|
|||
|
||||
#[derive(Deserialize)]
|
||||
struct WRC {
|
||||
// #[serde(rename = "earliestPlayableStart")]
|
||||
// #[serde(with = "es_date_time")]
|
||||
// earliest_playable_start: DateTime<Utc>,
|
||||
// id: u32,
|
||||
name: String,
|
||||
#[serde(rename = "eventDays")]
|
||||
days: Vec<WRCDays>,
|
||||
|
@ -33,7 +29,6 @@ struct WRC {
|
|||
|
||||
#[derive(Deserialize)]
|
||||
struct WRCDays {
|
||||
// id: u32,
|
||||
#[serde(rename = "eventDay")]
|
||||
event_day: String,
|
||||
#[serde(rename = "spottChannel")]
|
||||
|
@ -42,20 +37,15 @@ struct WRCDays {
|
|||
|
||||
#[derive(Deserialize)]
|
||||
struct WRCChannel {
|
||||
// id: u32,
|
||||
// #[serde(rename = "displayName")]
|
||||
// name: String,
|
||||
assets: Vec<WRCAssets>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct WRCAssets {
|
||||
// id: u32,
|
||||
#[serde(with = "wrc_date")]
|
||||
start: DateTime<Utc>,
|
||||
#[serde(with = "wrc_date")]
|
||||
end: DateTime<Utc>,
|
||||
// duration: u32,
|
||||
content: WRCContent,
|
||||
}
|
||||
|
||||
|
@ -84,13 +74,10 @@ async fn get_schedule() -> Result<Option<WRC>, Error> {
|
|||
}
|
||||
}
|
||||
|
||||
// WRC sessions
|
||||
#[poise::command(slash_command)]
|
||||
/// WRC sessions
|
||||
#[poise::command(slash_command, ephemeral)]
|
||||
pub async fn wrc(
|
||||
ctx: Context<'_>,
|
||||
// #[description = "Filter sessions for when they are/were happening, defaults to future"]
|
||||
// timeframe: Option<super::Timeframe>,
|
||||
// #[description = "Content to filter on"] filter: Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
let wrc = get_schedule().await?;
|
||||
match wrc {
|
||||
|
@ -107,7 +94,7 @@ pub async fn wrc(
|
|||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
events.push(format!("{}: <t:{}:R>- <t:{}:R>: [{}](https://morningstreams.com/wrcplayer.html?id={}) {} {}", day.event_day, session.start.timestamp(), session.end.timestamp(), session.content.id, session.content.id, session.content.title, desc));
|
||||
events.push(format!("{}: <t:{}:R>- <t:{}:R>: [{}](https://tom.al/ms/wrc/{}) {} {}", day.event_day, session.start.timestamp(), session.end.timestamp(), session.content.id, session.content.id, session.content.title, desc));
|
||||
}
|
||||
}
|
||||
let pages = utils::paginator(events, 2400, "\n".to_owned());
|
||||
|
|
|
@ -3,8 +3,8 @@ use poise::serenity_prelude as serenity;
|
|||
|
||||
pub mod invites;
|
||||
mod links;
|
||||
// pub mod planning;
|
||||
pub mod coms;
|
||||
pub mod roles;
|
||||
pub mod schedule;
|
||||
pub mod utils;
|
||||
|
||||
|
@ -27,16 +27,15 @@ pub async fn boop(ctx: Context<'_>) -> Result<(), Error> {
|
|||
.await?;
|
||||
|
||||
let mut boop_count: i32 = 0;
|
||||
while let Some(mci) = serenity::CollectComponentInteraction::new(ctx.discord())
|
||||
while let Some(mci) = serenity::CollectComponentInteraction::new(ctx)
|
||||
.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| {
|
||||
msg.edit(ctx, |m| {
|
||||
m.content(match boop_count {
|
||||
2 => "Boop count: <:HamSmile:738765923401596991>".to_string(),
|
||||
3 => "Boop 3".to_string(),
|
||||
|
@ -60,7 +59,7 @@ pub async fn boop(ctx: Context<'_>) -> Result<(), Error> {
|
|||
})
|
||||
.await?;
|
||||
|
||||
mci.create_interaction_response(ctx.discord(), |ir| {
|
||||
mci.create_interaction_response(ctx, |ir| {
|
||||
ir.kind(serenity::InteractionResponseType::DeferredUpdateMessage)
|
||||
})
|
||||
.await?;
|
||||
|
@ -69,6 +68,7 @@ pub async fn boop(ctx: Context<'_>) -> Result<(), Error> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Imaginary fix button
|
||||
#[poise::command(track_edits, slash_command)]
|
||||
pub async fn fix(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let uuid_fix = ctx.id();
|
||||
|
@ -88,21 +88,20 @@ pub async fn fix(ctx: Context<'_>) -> Result<(), Error> {
|
|||
.await?;
|
||||
|
||||
let mut fix_count: i32 = 0;
|
||||
while let Some(mci) = serenity::CollectComponentInteraction::new(ctx.discord())
|
||||
while let Some(mci) = serenity::CollectComponentInteraction::new(ctx)
|
||||
.channel_id(ctx.channel_id())
|
||||
// .timeout(std::time::Duration::from_secs(1200))
|
||||
.filter(move |mci| mci.data.custom_id == uuid_fix.to_string())
|
||||
.await
|
||||
{
|
||||
fix_count += 1;
|
||||
|
||||
let mut msg = mci.message.clone();
|
||||
msg.edit(ctx.discord(), |m| {
|
||||
msg.edit(ctx, |m| {
|
||||
m.content(format!("Fixing failed try again. Attempt {}", fix_count))
|
||||
})
|
||||
.await?;
|
||||
|
||||
mci.create_interaction_response(ctx.discord(), |ir| {
|
||||
mci.create_interaction_response(ctx, |ir| {
|
||||
ir.kind(serenity::InteractionResponseType::DeferredUpdateMessage)
|
||||
})
|
||||
.await?;
|
||||
|
@ -114,14 +113,5 @@ pub async fn fix(ctx: Context<'_>) -> Result<(), Error> {
|
|||
pub fn get_links(
|
||||
) -> poise::Command<super::Data, Box<(dyn std::error::Error + std::marker::Send + Sync + 'static)>>
|
||||
{
|
||||
// poise::Command {
|
||||
// subcommands: vec![
|
||||
// links::eurosport::eurosport(),
|
||||
// links::eurosport::olympics(),
|
||||
// links::links(),
|
||||
// // Let's make sure poise isn't confused by the duplicate names!
|
||||
// ],
|
||||
// ..links::links()
|
||||
// };
|
||||
links::links()
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ pub async fn series(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug, poise::SlashChoiceParameter)]
|
||||
#[derive(Debug, poise::ChoiceParameter)]
|
||||
pub enum Timeframe {
|
||||
#[name = "Currently happening"]
|
||||
Current,
|
||||
|
|
91
src/commands/roles.rs
Normal file
91
src/commands/roles.rs
Normal file
|
@ -0,0 +1,91 @@
|
|||
use crate::{Context, Error};
|
||||
use poise::serenity_prelude::RoleId;
|
||||
|
||||
#[derive(Debug, poise::ChoiceParameter)]
|
||||
pub enum Action {
|
||||
#[name = "Add specified role."]
|
||||
Add,
|
||||
#[name = "Remove specified role."]
|
||||
Remove,
|
||||
#[name = "Toggle specified role (default)."]
|
||||
Toggle,
|
||||
}
|
||||
|
||||
async fn autocomplete_role<'a>(
|
||||
ctx: Context<'_>,
|
||||
partial: &'a str,
|
||||
) -> impl Iterator<Item = String> + 'a {
|
||||
let mut roles: Vec<String> = match super::super::SETTINGS
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_table("roles")
|
||||
.unwrap()
|
||||
.get(&ctx.guild_id().expect("Not in a guild").to_string())
|
||||
{
|
||||
None => {
|
||||
vec![]
|
||||
}
|
||||
Some(val) => match val.clone().into_table() {
|
||||
Err(_) => {
|
||||
vec![]
|
||||
}
|
||||
Ok(val) => val
|
||||
.into_keys()
|
||||
.filter(|str| str.contains(partial))
|
||||
.collect(),
|
||||
},
|
||||
};
|
||||
|
||||
roles.sort_unstable();
|
||||
|
||||
roles.into_iter() //.map(|a| a.to_owned())
|
||||
}
|
||||
|
||||
#[poise::command(slash_command, ephemeral, guild_only)]
|
||||
pub async fn roles(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Which role to add or remove?"]
|
||||
#[autocomplete = "autocomplete_role"]
|
||||
role: String,
|
||||
#[description = "Remove or add role (default to add)"] action: Option<Action>,
|
||||
) -> Result<(), Error> {
|
||||
let role = super::super::SETTINGS
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_table("roles")
|
||||
.unwrap()
|
||||
.get(&ctx.guild_id().unwrap().to_string())
|
||||
.expect("Command is only supported in a server")
|
||||
.clone()
|
||||
.into_table()
|
||||
.expect("Config error, something in the configuration is wrong. Please contact someone to fix the bot.")
|
||||
.get(&role)
|
||||
.expect("Configured role does not exist")
|
||||
.clone()
|
||||
.into_uint()
|
||||
.expect("Config error, specified role does not have the role_id configured.");
|
||||
let role_ding = RoleId(role);
|
||||
let mut member = ctx.author_member().await.expect("Where's my member....");
|
||||
let mem = member.to_mut();
|
||||
// if let Some(mut author) = ctx.author_member().await.as_mut().expect("Somehow there's no member object attached...") {
|
||||
match action {
|
||||
Some(Action::Remove) => {
|
||||
mem.remove_role(ctx, role_ding).await?;
|
||||
ctx.say(format!("Role {} Added", role)).await?
|
||||
}
|
||||
Some(Action::Add) => {
|
||||
mem.add_role(ctx, role_ding).await?;
|
||||
ctx.say(format!("Role {} Added", role)).await?
|
||||
}
|
||||
_ => {
|
||||
if mem.roles.contains(&role_ding) {
|
||||
mem.remove_role(ctx, role_ding).await?;
|
||||
ctx.say(format!("Role {} Added", role)).await?
|
||||
} else {
|
||||
mem.add_role(ctx, role_ding).await?;
|
||||
ctx.say(format!("Role {} Added", role)).await?
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
|
@ -31,14 +31,14 @@ impl MSEvent {
|
|||
fn get_value(&self, high_tier: bool) -> String {
|
||||
let link = if high_tier {
|
||||
format!(
|
||||
"[{id}](https://morningstreams.com/hightier/f1/session/{id})\n",
|
||||
"[{id}](https://morningstreams.com/hightier/f1/session/{id})",
|
||||
id = self.id
|
||||
)
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
format!(
|
||||
"{link}Start: <t:{start}:R>\nEnd: <t:{end}:R>",
|
||||
"{link}\nStart: <t:{start}:R>\nEnd: <t:{end}:R>",
|
||||
link = link,
|
||||
start = self.metadata.attributes.start.timestamp(),
|
||||
end = self.metadata.attributes.end.timestamp()
|
||||
|
@ -136,7 +136,8 @@ async fn get_schedule() -> Option<MSReq> {
|
|||
result
|
||||
}
|
||||
|
||||
#[poise::command(slash_command)]
|
||||
// Get the most recent F1 schedule
|
||||
#[poise::command(slash_command, ephemeral)]
|
||||
pub async fn schedule(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let events: Option<MSReq> = get_schedule().await;
|
||||
let ht: bool = utils::high_tier(ctx).await;
|
||||
|
|
|
@ -11,13 +11,13 @@ pub async fn high_tier(ctx: Context<'_>) -> bool {
|
|||
_ => (),
|
||||
}
|
||||
|
||||
match ctx.discord().cache.guild_channel(ctx.channel_id()) {
|
||||
match ctx.serenity_context().cache.guild_channel(ctx.channel_id()) {
|
||||
None => return false,
|
||||
Some(chan) => match chan.parent_id {
|
||||
None => return false,
|
||||
Some(cat_id) => match cat_id {
|
||||
ChannelId(547551264498515978) => return true,
|
||||
ChannelId(884698356360818708) => return true,
|
||||
ChannelId(547551264498515978) => return true, // MS high tier
|
||||
ChannelId(884698356360818708) => return true, // Private server
|
||||
_ => return false,
|
||||
},
|
||||
},
|
||||
|
@ -44,6 +44,32 @@ pub fn paginator(input: Vec<String>, chunk_size: usize, join_string: String) ->
|
|||
return result;
|
||||
}
|
||||
|
||||
pub fn paginator_title(
|
||||
title: String,
|
||||
input: Vec<String>,
|
||||
chunk_size: usize,
|
||||
join_string: String,
|
||||
) -> Vec<String> {
|
||||
if input.len() == 0 {
|
||||
return vec![];
|
||||
}
|
||||
let mut result: Vec<String> = vec![];
|
||||
let mut part: String = title.clone();
|
||||
let filler = &join_string.chars().count();
|
||||
for i in input {
|
||||
if part.chars().count() + i.chars().count() + filler >= chunk_size {
|
||||
result.push(part);
|
||||
part = title.to_string();
|
||||
part.push_str(&i.to_string());
|
||||
} else {
|
||||
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<String>) -> Result<(), Error> {
|
||||
let uuid_command = ctx.id().to_string();
|
||||
let page_count = pages.len();
|
||||
|
@ -60,43 +86,40 @@ pub async fn paginate_string(ctx: Context<'_>, pages: Vec<String>) -> Result<(),
|
|||
_ => {}
|
||||
};
|
||||
|
||||
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))
|
||||
let reply_handle = 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();
|
||||
.await?;
|
||||
|
||||
let mut page = 0;
|
||||
while let Some(mci) = serenity::CollectComponentInteraction::new(ctx.discord())
|
||||
// .author_id(ctx.author().id)
|
||||
while let Some(mci) = serenity::CollectComponentInteraction::new(ctx)
|
||||
.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) {
|
||||
|
@ -115,18 +138,18 @@ pub async fn paginate_string(ctx: Context<'_>, pages: Vec<String>) -> Result<(),
|
|||
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?;
|
||||
reply_handle
|
||||
.edit(ctx, |m| {
|
||||
m.content(format!(
|
||||
"{}\n\nPage: {}/{}",
|
||||
pages.get(page).unwrap(),
|
||||
page + 1,
|
||||
page_count
|
||||
))
|
||||
})
|
||||
.await?;
|
||||
|
||||
mci.create_interaction_response(ctx.discord(), |ir| {
|
||||
mci.create_interaction_response(ctx, |ir| {
|
||||
ir.kind(serenity::InteractionResponseType::DeferredUpdateMessage)
|
||||
})
|
||||
.await?;
|
||||
|
@ -149,7 +172,6 @@ pub async fn paginate_string_embed(
|
|||
return Ok(());
|
||||
}
|
||||
1 => {
|
||||
// ctx.say(pages.get(0).unwrap()).await?;
|
||||
ctx.send(|m| m.embed(|e| e.title(title).description(pages.get(0).unwrap())))
|
||||
.await?;
|
||||
return Ok(());
|
||||
|
@ -157,47 +179,38 @@ pub async fn paginate_string_embed(
|
|||
_ => {}
|
||||
};
|
||||
|
||||
ctx.send(|m| {
|
||||
// m.content(format!(
|
||||
// "{}\n\nPage: {}/{}",
|
||||
// pages.get(0).unwrap(),
|
||||
// 1,
|
||||
// page_count
|
||||
// ))
|
||||
m.embed(|e| {
|
||||
e.title(format!("{} Page 1/{}", title, page_count))
|
||||
.description(pages.get(0).unwrap())
|
||||
})
|
||||
.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))
|
||||
let reply_handle = ctx
|
||||
.send(|m| {
|
||||
m.embed(|e| {
|
||||
e.title(format!("{} Page 1/{}", title, page_count))
|
||||
.description(pages.get(0).unwrap())
|
||||
})
|
||||
.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();
|
||||
.await?;
|
||||
|
||||
let mut page = 0;
|
||||
while let Some(mci) = serenity::CollectComponentInteraction::new(ctx.discord())
|
||||
// .author_id(ctx.author().id)
|
||||
while let Some(mci) = serenity::CollectComponentInteraction::new(ctx)
|
||||
.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) {
|
||||
|
@ -216,16 +229,16 @@ pub async fn paginate_string_embed(
|
|||
page = 0;
|
||||
}
|
||||
|
||||
let mut msg = mci.message.clone();
|
||||
msg.edit(ctx.discord(), |m| {
|
||||
m.embed(|e| {
|
||||
e.title(format!("{} Page {}/{}", title, page + 1, page_count))
|
||||
.description(pages.get(page).unwrap())
|
||||
reply_handle
|
||||
.edit(ctx, |m| {
|
||||
m.embed(|e| {
|
||||
e.title(format!("{} Page {}/{}", title, page + 1, page_count))
|
||||
.description(pages.get(page).unwrap())
|
||||
})
|
||||
})
|
||||
})
|
||||
.await?;
|
||||
.await?;
|
||||
|
||||
mci.create_interaction_response(ctx.discord(), |ir| {
|
||||
mci.create_interaction_response(ctx, |ir| {
|
||||
ir.kind(serenity::InteractionResponseType::DeferredUpdateMessage)
|
||||
})
|
||||
.await?;
|
||||
|
|
93
src/main.rs
93
src/main.rs
|
@ -74,7 +74,7 @@ async fn register(
|
|||
"Purging global commands, must have been a mistake eh?"
|
||||
))
|
||||
.await?;
|
||||
ctx.discord()
|
||||
ctx.serenity_context()
|
||||
.http
|
||||
.create_global_application_commands(&serenity::json::Value::Null)
|
||||
.await?;
|
||||
|
@ -85,7 +85,7 @@ async fn register(
|
|||
commands.len()
|
||||
))
|
||||
.await?;
|
||||
ctx.discord()
|
||||
ctx.serenity_context()
|
||||
.http
|
||||
.create_global_application_commands(&commands_builder)
|
||||
.await?;
|
||||
|
@ -111,7 +111,7 @@ async fn register(
|
|||
commands.len()
|
||||
))
|
||||
.await?;
|
||||
ctx.discord()
|
||||
ctx.serenity_context()
|
||||
.http
|
||||
.create_guild_application_commands(guild.id.0, &commands_builder)
|
||||
.await?;
|
||||
|
@ -122,12 +122,93 @@ async fn register(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Use the default configuration for setting up commands.
|
||||
#[poise::command(
|
||||
prefix_command,
|
||||
hide_in_help,
|
||||
// required_permissions = "MANAGE_MESSAGES | ADMINISTRATOR",
|
||||
owners_only=true,
|
||||
)]
|
||||
async fn default_register(ctx: Context<'_>) -> Result<(), Error> {
|
||||
// poise::builtins::register_application_commands(ctx, global).await?;
|
||||
let is_bot_owner = ctx.framework().options().owners.contains(&ctx.author().id);
|
||||
let mut commands_builder_guild = serenity::CreateApplicationCommands::default();
|
||||
let commands = &ctx.framework().options().commands;
|
||||
ctx.say(format!("Commands: {}", commands.len())).await?;
|
||||
|
||||
fn globals_filter(name: &String) -> bool {
|
||||
name.starts_with("invite") || name.starts_with("boop") || name.starts_with("fix")
|
||||
}
|
||||
|
||||
// If the user is the bot owner, also correct the global commands.
|
||||
if is_bot_owner {
|
||||
let mut commands_builder_global = serenity::CreateApplicationCommands::default();
|
||||
// let global_commands = commands; //.iter().filter(|com| com.name.starts_with("invite")).collect();
|
||||
let mut global_count = 0;
|
||||
for command in commands {
|
||||
if globals_filter(&command.name) {
|
||||
global_count += 1;
|
||||
if let Some(slash_command) = command.create_as_slash_command() {
|
||||
commands_builder_global.add_application_command(slash_command);
|
||||
}
|
||||
if let Some(context_menu_command) = command.create_as_context_menu_command() {
|
||||
commands_builder_global.add_application_command(context_menu_command);
|
||||
}
|
||||
}
|
||||
}
|
||||
let commands_build_global = serenity::json::Value::Array(commands_builder_global.0);
|
||||
ctx.serenity_context()
|
||||
.http
|
||||
.create_global_application_commands(&commands_build_global)
|
||||
.await?;
|
||||
ctx.say(format!("Registered {} as global commands", global_count))
|
||||
.await?;
|
||||
}
|
||||
let mut command_count: u8 = 0;
|
||||
for command in commands {
|
||||
if !globals_filter(&command.name) {
|
||||
command_count += 1;
|
||||
if let Some(slash_command) = command.create_as_slash_command() {
|
||||
commands_builder_guild.add_application_command(slash_command);
|
||||
}
|
||||
if let Some(context_menu_command) = command.create_as_context_menu_command() {
|
||||
commands_builder_guild.add_application_command(context_menu_command);
|
||||
}
|
||||
}
|
||||
}
|
||||
let commands_builder = serenity::json::Value::Array(commands_builder_guild.0);
|
||||
let guild = match ctx.guild() {
|
||||
Some(x) => x,
|
||||
None => {
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let is_guild_owner = ctx.author().id == guild.owner_id;
|
||||
|
||||
if !is_guild_owner && !is_bot_owner {
|
||||
ctx.say("Can only be used by server owner").await?;
|
||||
return Ok(());
|
||||
}
|
||||
ctx.say(format!(
|
||||
"Registering {} commands out of {}...",
|
||||
command_count,
|
||||
commands.len()
|
||||
))
|
||||
.await?;
|
||||
ctx.serenity_context()
|
||||
.http
|
||||
.create_guild_application_commands(guild.id.0, &commands_builder)
|
||||
.await?;
|
||||
ctx.say("Done!").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::Setup { error, .. } => panic!("Failed to start bot: {:?}", error),
|
||||
poise::FrameworkError::Command { error, ctx } => {
|
||||
println!("Error in command `{}`: {:?}", ctx.command().name, error,);
|
||||
}
|
||||
|
@ -180,8 +261,10 @@ async fn app() -> Result<(), Error> {
|
|||
let commands = vec![
|
||||
help(),
|
||||
register(),
|
||||
default_register(),
|
||||
commands::invites::invites(),
|
||||
commands::schedule::schedule(),
|
||||
commands::roles::roles(),
|
||||
commands::boop(),
|
||||
commands::fix(),
|
||||
// commands::planning::get_command(),
|
||||
|
@ -245,7 +328,7 @@ async fn app() -> Result<(), Error> {
|
|||
|
||||
let framework = poise::Framework::builder()
|
||||
.token(token)
|
||||
.user_data_setup(move |_ctx, _ready, _framework| {
|
||||
.setup(move |_ctx, _ready, _framework| {
|
||||
// Box::pin(async move { Ok(Data { database: database }) })
|
||||
Box::pin(async move { Ok(Data { database: db }) })
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue