Add permission checks to p.prefix command
This commit is contained in:
Generated
+15
-292
@@ -363,11 +363,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
|
checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-core",
|
|
||||||
"memchr",
|
"memchr",
|
||||||
"pin-project-lite",
|
|
||||||
"tokio",
|
|
||||||
"tokio-util",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -471,36 +467,6 @@ dependencies = [
|
|||||||
"parking_lot_core",
|
"parking_lot_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "deadpool"
|
|
||||||
version = "0.12.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5ed5957ff93768adf7a65ab167a17835c3d2c3c50d084fe305174c112f468e2f"
|
|
||||||
dependencies = [
|
|
||||||
"deadpool-runtime",
|
|
||||||
"num_cpus",
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "deadpool-redis"
|
|
||||||
version = "0.22.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c0965b977f1244bc3783bb27cd79cfcff335a8341da18f79232d00504b18eb1a"
|
|
||||||
dependencies = [
|
|
||||||
"deadpool",
|
|
||||||
"redis",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "deadpool-runtime"
|
|
||||||
version = "0.1.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b"
|
|
||||||
dependencies = [
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deranged"
|
name = "deranged"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@@ -510,17 +476,6 @@ dependencies = [
|
|||||||
"powerfmt",
|
"powerfmt",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "displaydoc"
|
|
||||||
version = "0.2.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dotenvy"
|
name = "dotenvy"
|
||||||
version = "0.15.7"
|
version = "0.15.7"
|
||||||
@@ -771,12 +726,6 @@ version = "0.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hermit-abi"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "1.3.1"
|
version = "1.3.1"
|
||||||
@@ -912,119 +861,12 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_collections"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"
|
|
||||||
dependencies = [
|
|
||||||
"displaydoc",
|
|
||||||
"potential_utf",
|
|
||||||
"yoke",
|
|
||||||
"zerofrom",
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_locale_core"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
|
|
||||||
dependencies = [
|
|
||||||
"displaydoc",
|
|
||||||
"litemap",
|
|
||||||
"tinystr",
|
|
||||||
"writeable",
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_normalizer"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979"
|
|
||||||
dependencies = [
|
|
||||||
"displaydoc",
|
|
||||||
"icu_collections",
|
|
||||||
"icu_normalizer_data",
|
|
||||||
"icu_properties",
|
|
||||||
"icu_provider",
|
|
||||||
"smallvec",
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_normalizer_data"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_properties"
|
|
||||||
version = "2.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b"
|
|
||||||
dependencies = [
|
|
||||||
"displaydoc",
|
|
||||||
"icu_collections",
|
|
||||||
"icu_locale_core",
|
|
||||||
"icu_properties_data",
|
|
||||||
"icu_provider",
|
|
||||||
"potential_utf",
|
|
||||||
"zerotrie",
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_properties_data"
|
|
||||||
version = "2.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_provider"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"
|
|
||||||
dependencies = [
|
|
||||||
"displaydoc",
|
|
||||||
"icu_locale_core",
|
|
||||||
"stable_deref_trait",
|
|
||||||
"tinystr",
|
|
||||||
"writeable",
|
|
||||||
"yoke",
|
|
||||||
"zerofrom",
|
|
||||||
"zerotrie",
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ident_case"
|
name = "ident_case"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "idna"
|
|
||||||
version = "1.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
|
|
||||||
dependencies = [
|
|
||||||
"idna_adapter",
|
|
||||||
"smallvec",
|
|
||||||
"utf8_iter",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "idna_adapter"
|
|
||||||
version = "1.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
|
|
||||||
dependencies = [
|
|
||||||
"icu_normalizer",
|
|
||||||
"icu_properties",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "include_dir"
|
name = "include_dir"
|
||||||
version = "0.7.4"
|
version = "0.7.4"
|
||||||
@@ -1203,12 +1045,6 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "litemap"
|
|
||||||
version = "0.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.13"
|
version = "0.4.13"
|
||||||
@@ -1310,31 +1146,12 @@ version = "2.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d"
|
checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-bigint"
|
|
||||||
version = "0.4.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
|
||||||
dependencies = [
|
|
||||||
"num-integer",
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-conv"
|
name = "num-conv"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-integer"
|
|
||||||
version = "0.1.46"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
|
||||||
dependencies = [
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
@@ -1344,16 +1161,6 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num_cpus"
|
|
||||||
version = "1.17.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_threads"
|
name = "num_threads"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
@@ -1431,14 +1238,13 @@ checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "payphone"
|
name = "payphone"
|
||||||
version = "4.0.15"
|
version = "4.0.25"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
"clap",
|
"clap",
|
||||||
"colored",
|
"colored",
|
||||||
"csv",
|
"csv",
|
||||||
"deadpool-redis",
|
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"include_dir",
|
"include_dir",
|
||||||
"itertools",
|
"itertools",
|
||||||
@@ -1452,11 +1258,11 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
"scc",
|
"scc",
|
||||||
"scylla",
|
"scylla",
|
||||||
"serde",
|
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.12",
|
||||||
"time",
|
"time",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
|
"twilight-cache-inmemory",
|
||||||
"twilight-gateway",
|
"twilight-gateway",
|
||||||
"twilight-http",
|
"twilight-http",
|
||||||
"twilight-model",
|
"twilight-model",
|
||||||
@@ -1490,15 +1296,6 @@ version = "0.3.32"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "potential_utf"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
|
|
||||||
dependencies = [
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "powerfmt"
|
name = "powerfmt"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@@ -1576,27 +1373,6 @@ dependencies = [
|
|||||||
"rand_core",
|
"rand_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "redis"
|
|
||||||
version = "0.32.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7cd3650deebc68526b304898b192fa4102a4ef0b9ada24da096559cb60e0eef8"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"cfg-if",
|
|
||||||
"combine",
|
|
||||||
"futures-util",
|
|
||||||
"itoa",
|
|
||||||
"num-bigint",
|
|
||||||
"percent-encoding",
|
|
||||||
"pin-project-lite",
|
|
||||||
"ryu",
|
|
||||||
"socket2 0.6.0",
|
|
||||||
"tokio",
|
|
||||||
"tokio-util",
|
|
||||||
"url",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.5.17"
|
version = "0.5.17"
|
||||||
@@ -2166,16 +1942,6 @@ dependencies = [
|
|||||||
"time-core",
|
"time-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tinystr"
|
|
||||||
version = "0.8.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
|
|
||||||
dependencies = [
|
|
||||||
"displaydoc",
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.47.1"
|
version = "1.47.1"
|
||||||
@@ -2343,6 +2109,19 @@ version = "0.2.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "twilight-cache-inmemory"
|
||||||
|
version = "0.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc9de5f02fa89a48d3fa989811d67a3f3cc3179a46ce71089afa5412ff21fb41"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.1",
|
||||||
|
"dashmap",
|
||||||
|
"serde",
|
||||||
|
"twilight-model",
|
||||||
|
"twilight-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "twilight-gateway"
|
name = "twilight-gateway"
|
||||||
version = "0.16.0"
|
version = "0.16.0"
|
||||||
@@ -2477,23 +2256,6 @@ version = "0.9.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "url"
|
|
||||||
version = "2.5.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
|
|
||||||
dependencies = [
|
|
||||||
"form_urlencoded",
|
|
||||||
"idna",
|
|
||||||
"percent-encoding",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "utf8_iter"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@@ -2944,12 +2706,6 @@ dependencies = [
|
|||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "writeable"
|
|
||||||
version = "0.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yoke"
|
name = "yoke"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@@ -3020,36 +2776,3 @@ name = "zeroize"
|
|||||||
version = "1.8.1"
|
version = "1.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerotrie"
|
|
||||||
version = "0.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
|
|
||||||
dependencies = [
|
|
||||||
"displaydoc",
|
|
||||||
"yoke",
|
|
||||||
"zerofrom",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerovec"
|
|
||||||
version = "0.11.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"
|
|
||||||
dependencies = [
|
|
||||||
"yoke",
|
|
||||||
"zerofrom",
|
|
||||||
"zerovec-derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerovec-derive"
|
|
||||||
version = "0.11.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|||||||
+2
-3
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "payphone"
|
name = "payphone"
|
||||||
version = "4.0.15"
|
version = "4.0.25"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
default-run = "payphone"
|
default-run = "payphone"
|
||||||
|
|
||||||
@@ -10,7 +10,6 @@ axum = "0.8.4"
|
|||||||
clap = { version = "4.5.42", features = ["derive", "env", "string"] }
|
clap = { version = "4.5.42", features = ["derive", "env", "string"] }
|
||||||
colored = "3.0.0"
|
colored = "3.0.0"
|
||||||
csv = "1.3.1"
|
csv = "1.3.1"
|
||||||
deadpool-redis = "0.22.0"
|
|
||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
include_dir = "0.7.4"
|
include_dir = "0.7.4"
|
||||||
itertools = "0.14.0"
|
itertools = "0.14.0"
|
||||||
@@ -24,11 +23,11 @@ rand_chacha = { version = "0.9.0", features = ["os_rng"] }
|
|||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
scc = "2.3.4"
|
scc = "2.3.4"
|
||||||
scylla = { version = "1.3.1", features = ["time-03"] }
|
scylla = { version = "1.3.1", features = ["time-03"] }
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
|
||||||
thiserror = "2.0.12"
|
thiserror = "2.0.12"
|
||||||
time = { version = "0.3.41", features = ["formatting", "local-offset", "macros"] }
|
time = { version = "0.3.41", features = ["formatting", "local-offset", "macros"] }
|
||||||
tokio = { version = "1.47.1", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1.47.1", features = ["macros", "rt-multi-thread"] }
|
||||||
tower-http = { version = "0.6.6", features = ["fs"] }
|
tower-http = { version = "0.6.6", features = ["fs"] }
|
||||||
|
twilight-cache-inmemory = { version = "0.16.0", features = ["permission-calculator"] }
|
||||||
twilight-gateway = "0.16.0"
|
twilight-gateway = "0.16.0"
|
||||||
twilight-http = { version = "0.16.0", features = ["simd-json"] }
|
twilight-http = { version = "0.16.0", features = ["simd-json"] }
|
||||||
twilight-model = "0.16.0"
|
twilight-model = "0.16.0"
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: redis
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: redis-config
|
||||||
|
namespace: redis
|
||||||
|
data:
|
||||||
|
update-node.sh: |
|
||||||
|
#!/bin/sh
|
||||||
|
REDIS_NODES="/data/nodes.conf"
|
||||||
|
sed -i -e "/myself/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/${POD_IP}/" ${REDIS_NODES}
|
||||||
|
exec "$@"
|
||||||
|
redis.conf: |+
|
||||||
|
cluster-enabled yes
|
||||||
|
cluster-require-full-coverage no
|
||||||
|
cluster-node-timeout 15000
|
||||||
|
cluster-config-file /data/nodes.conf
|
||||||
|
cluster-migration-barrier 1
|
||||||
|
save ""
|
||||||
|
appendonly no
|
||||||
|
protected-mode no
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: redis-cluster
|
||||||
|
namespace: redis
|
||||||
|
spec:
|
||||||
|
serviceName: redis-cluster
|
||||||
|
replicas: 6
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: redis-cluster
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: redis-cluster
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: redis
|
||||||
|
image: redis:alpine
|
||||||
|
ports:
|
||||||
|
- containerPort: 6379
|
||||||
|
name: client
|
||||||
|
- containerPort: 16379
|
||||||
|
name: gossip
|
||||||
|
command: ["/conf/update-node.sh", "redis-server", "/conf/redis.conf"]
|
||||||
|
env:
|
||||||
|
- name: POD_IP
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: status.podIP
|
||||||
|
volumeMounts:
|
||||||
|
- name: conf
|
||||||
|
mountPath: /conf
|
||||||
|
readOnly: false
|
||||||
|
- name: data
|
||||||
|
mountPath: /data
|
||||||
|
readOnly: false
|
||||||
|
volumes:
|
||||||
|
- name: conf
|
||||||
|
configMap:
|
||||||
|
name: redis-config
|
||||||
|
defaultMode: 0755
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- metadata:
|
||||||
|
name: data
|
||||||
|
spec:
|
||||||
|
storageClassName: local-path
|
||||||
|
accessModes: [ "ReadWriteOnce" ]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: redis-cluster
|
||||||
|
namespace: redis
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 6379
|
||||||
|
targetPort: 6379
|
||||||
|
name: client
|
||||||
|
- port: 16379
|
||||||
|
targetPort: 16379
|
||||||
|
name: gossip
|
||||||
|
selector:
|
||||||
|
app: redis-cluster
|
||||||
@@ -8,4 +8,5 @@ uv run ansible-playbook -i inventory.ini playbooks/04-prometheus-operator.yml
|
|||||||
uv run ansible-playbook -i inventory.ini playbooks/05-scylla-operator.yml
|
uv run ansible-playbook -i inventory.ini playbooks/05-scylla-operator.yml
|
||||||
uv run ansible-playbook -i inventory.ini playbooks/06-scylla-cluster.yml
|
uv run ansible-playbook -i inventory.ini playbooks/06-scylla-cluster.yml
|
||||||
uv run ansible-playbook -i inventory.ini playbooks/07-scylla-manager.yml
|
uv run ansible-playbook -i inventory.ini playbooks/07-scylla-manager.yml
|
||||||
uv run ansible-playbook -i inventory.ini playbooks/08-payphone.yml --vault-password-file playbooks/00-vault-pwd.txt
|
uv run ansible-playbook -i inventory.ini playbooks/08-redis.yml
|
||||||
|
uv run ansible-playbook -i inventory.ini playbooks/09-payphone.yml --vault-password-file playbooks/00-vault-pwd.txt
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
- name: Set Up Redis Cluster
|
||||||
|
hosts: init
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Create Redis Config Map
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
state: present
|
||||||
|
src: /tmp/k8s/redis/01-config-map.yml
|
||||||
|
kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||||
|
|
||||||
|
- name: Create Redis Nodes
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
state: present
|
||||||
|
src: /tmp/k8s/redis/02-redis.yml
|
||||||
|
kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||||
|
|
||||||
|
- name: Wait for Redis Nodes
|
||||||
|
ansible.builtin.command:
|
||||||
|
kubectl -n=redis rollout status --timeout=10m sts/redis-cluster
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Create ClusterIP Service
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
state: present
|
||||||
|
src: /tmp/k8s/redis/03-cluster-ip.yml
|
||||||
|
kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||||
|
|
||||||
|
- name: Grab Node IPs
|
||||||
|
ansible.builtin.shell:
|
||||||
|
echo $(kubectl get pods -l app=redis-cluster -n redis -o json | jq -r '.items | map(.status.podIP) | join(":6379 ")'):6379
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: redis_node_ips
|
||||||
|
changed_when: false
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
- name: Display Node IPs
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ redis_node_ips.stdout }}"
|
||||||
|
|
||||||
|
- name: Check if Redis cluster is already active
|
||||||
|
ansible.builtin.shell: >
|
||||||
|
set -o pipefail
|
||||||
|
kubectl exec redis-cluster-0 -n redis -- redis-cli -p 6379 cluster info | grep cluster_state
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: redis_cluster_state
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Activate Redis Cluster
|
||||||
|
ansible.builtin.shell: >
|
||||||
|
kubectl exec redis-cluster-0 -n redis -- redis-cli --cluster create --cluster-replicas 1 {{ redis_node_ips.stdout }} --cluster-yes
|
||||||
|
when: "'cluster_state:ok' not in redis_cluster_state.stdout"
|
||||||
|
changed_when: false
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
"--shard",
|
"--shard",
|
||||||
"$(SHARD_ID):$(SHARD_COUNT)",
|
"$(SHARD_ID):$(SHARD_COUNT)",
|
||||||
"--database-addr",
|
"--database-addr",
|
||||||
"scylladb-client.scylla.svc.cluster.local",
|
"scylladb-client.scylla",
|
||||||
"--database-username",
|
"--database-username",
|
||||||
"cassandra",
|
"cassandra",
|
||||||
"--database-password",
|
"--database-password",
|
||||||
@@ -1,432 +0,0 @@
|
|||||||
use std::{collections::HashMap, sync::Arc};
|
|
||||||
|
|
||||||
use clap::Parser;
|
|
||||||
use payphone::{
|
|
||||||
database::{
|
|
||||||
self,
|
|
||||||
models::{
|
|
||||||
MessageData, Report as PayphoneReport, ReportResolution, Server as PayphoneServer,
|
|
||||||
UserIncident, UserIncidentType,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
utils::{Bye, get_random_u64, u64_to_i64},
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use time::OffsetDateTime;
|
|
||||||
use tokio::{sync::Semaphore, time::Instant};
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
|
||||||
struct Args {
|
|
||||||
dir: String,
|
|
||||||
|
|
||||||
#[arg(long, default_value_t = String::from("127.0.0.1"))]
|
|
||||||
database_addr: String,
|
|
||||||
|
|
||||||
#[arg(long)]
|
|
||||||
database_username: Option<String>,
|
|
||||||
|
|
||||||
#[arg(long)]
|
|
||||||
database_password: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
struct Report {
|
|
||||||
id: u64,
|
|
||||||
message_id: u64,
|
|
||||||
message_content: String,
|
|
||||||
channel_id: u64,
|
|
||||||
user_id: u64,
|
|
||||||
created_at: String,
|
|
||||||
resolved: String,
|
|
||||||
resolved_at: Option<String>,
|
|
||||||
resolved_by_id: Option<u64>,
|
|
||||||
user_avatar_url: String,
|
|
||||||
user_name: String,
|
|
||||||
reply_user_name: Option<String>,
|
|
||||||
reply_message_content: Option<String>,
|
|
||||||
reply_user_avatar_url: Option<String>,
|
|
||||||
reply_user_id: Option<u64>,
|
|
||||||
reported_by_id: Option<u64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
struct User {
|
|
||||||
id: u64,
|
|
||||||
is_masked: String,
|
|
||||||
is_moderator: String,
|
|
||||||
is_supporter_until: String,
|
|
||||||
warns_count: u64,
|
|
||||||
bans_count: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
struct Ban {
|
|
||||||
id: u64,
|
|
||||||
user_id: u64,
|
|
||||||
created_at: String,
|
|
||||||
expires_at: Option<String>,
|
|
||||||
created_by_id: u64,
|
|
||||||
expired_by_id: Option<u64>,
|
|
||||||
report_id: Option<u64>,
|
|
||||||
reason: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
struct Server {
|
|
||||||
id: u64,
|
|
||||||
prefix: String,
|
|
||||||
language: String,
|
|
||||||
name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
struct Warn {
|
|
||||||
id: u64,
|
|
||||||
user_id: u64,
|
|
||||||
reason: String,
|
|
||||||
created_at: String,
|
|
||||||
created_by_id: u64,
|
|
||||||
report_id: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() {
|
|
||||||
let args = Args::parse();
|
|
||||||
|
|
||||||
println!("Testing DB connection...");
|
|
||||||
|
|
||||||
let db = Arc::new(
|
|
||||||
database::init(
|
|
||||||
args.database_addr,
|
|
||||||
args.database_username,
|
|
||||||
args.database_password,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.expect("Failed to initialize database"),
|
|
||||||
);
|
|
||||||
|
|
||||||
println!("Reading migration file {}/reports.csv", args.dir);
|
|
||||||
|
|
||||||
let mut rdr = csv::Reader::from_path(format!("{}/reports.csv", args.dir))
|
|
||||||
.expect("Failed to open reports file");
|
|
||||||
|
|
||||||
let mut reports = Vec::new();
|
|
||||||
|
|
||||||
let format = time::format_description::parse(
|
|
||||||
"[year]-[month]-[day] [hour]:[minute]:[second].[subsecond][offset_hour]",
|
|
||||||
)
|
|
||||||
.expect("Failed to parse format description");
|
|
||||||
|
|
||||||
for result in rdr.deserialize() {
|
|
||||||
let report: Report = result.expect("Failed to deserialize report");
|
|
||||||
reports.push(report);
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("Finished reading reports, found {} reports", reports.len());
|
|
||||||
println!("Reading migration file {}/users.csv", args.dir);
|
|
||||||
|
|
||||||
let mut rdr = csv::Reader::from_path(format!("{}/users.csv", args.dir))
|
|
||||||
.expect("Failed to open users file");
|
|
||||||
|
|
||||||
let mut users = HashMap::new();
|
|
||||||
|
|
||||||
for result in rdr.deserialize() {
|
|
||||||
let user: User = result.expect("Failed to deserialize user");
|
|
||||||
users.insert(user.id, user).bye();
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("Finished reading users, found {} users", users.len());
|
|
||||||
println!("Reading migration file {}/bans.csv", args.dir);
|
|
||||||
|
|
||||||
let mut rdr =
|
|
||||||
csv::Reader::from_path(format!("{}/bans.csv", args.dir)).expect("Failed to open bans file");
|
|
||||||
|
|
||||||
let mut bans = HashMap::new();
|
|
||||||
|
|
||||||
for result in rdr.deserialize() {
|
|
||||||
let ban: Ban = result.expect("Failed to deserialize ban");
|
|
||||||
bans.insert(ban.id, ban).bye();
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("Finished reading bans, found {} bans", bans.len());
|
|
||||||
println!("Reading migration file {}/servers.csv", args.dir);
|
|
||||||
|
|
||||||
let mut rdr = csv::Reader::from_path(format!("{}/servers.csv", args.dir))
|
|
||||||
.expect("Failed to open servers file");
|
|
||||||
|
|
||||||
let mut servers = HashMap::new();
|
|
||||||
|
|
||||||
for result in rdr.deserialize() {
|
|
||||||
let server: Server = result.expect("Failed to deserialize server");
|
|
||||||
servers.insert(server.id, server).bye();
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("Finished reading servers, found {} servers", servers.len());
|
|
||||||
println!("Reading migration file {}/warns.csv", args.dir);
|
|
||||||
|
|
||||||
let mut rdr = csv::Reader::from_path(format!("{}/warns.csv", args.dir))
|
|
||||||
.expect("Failed to open warns file");
|
|
||||||
|
|
||||||
let mut warns = HashMap::new();
|
|
||||||
|
|
||||||
for result in rdr.deserialize() {
|
|
||||||
let warn: Warn = result.expect("Failed to deserialize warn");
|
|
||||||
warns.insert(warn.id, warn).bye();
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("Finished reading warns, found {} warns", warns.len());
|
|
||||||
println!("Starting migration...");
|
|
||||||
println!("Inserting server configurations...");
|
|
||||||
|
|
||||||
let semaphore = Arc::new(Semaphore::new(50));
|
|
||||||
let mut tasks = Vec::new();
|
|
||||||
|
|
||||||
for (i, server) in servers.values().enumerate() {
|
|
||||||
let payphone_server = PayphoneServer {
|
|
||||||
id: server.id,
|
|
||||||
prefix: server.prefix.clone(),
|
|
||||||
language: server.language.clone(),
|
|
||||||
name: server.name.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let task_db = db.clone();
|
|
||||||
let task_semaphore = semaphore.clone();
|
|
||||||
|
|
||||||
tasks.push(tokio::spawn(async move {
|
|
||||||
let _permit = task_semaphore.acquire().await;
|
|
||||||
|
|
||||||
let start = Instant::now();
|
|
||||||
payphone_server
|
|
||||||
.insert(&task_db)
|
|
||||||
.await
|
|
||||||
.expect("Failed to insert server");
|
|
||||||
|
|
||||||
let duration = start.elapsed();
|
|
||||||
println!(
|
|
||||||
"({i}) Inserted server {} in {:?}",
|
|
||||||
payphone_server.id, duration
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
let bans = Arc::new(bans);
|
|
||||||
let warns = Arc::new(warns);
|
|
||||||
let reports = Arc::new(reports);
|
|
||||||
|
|
||||||
for (i, report) in reports.iter().enumerate() {
|
|
||||||
let task_db = db.clone();
|
|
||||||
let task_semaphore = semaphore.clone();
|
|
||||||
let task_report = report.clone();
|
|
||||||
let task_bans = bans.clone();
|
|
||||||
let task_warns = warns.clone();
|
|
||||||
let task_format = format.clone();
|
|
||||||
|
|
||||||
tasks.push(tokio::spawn(async move {
|
|
||||||
let _permit = task_semaphore.acquire().await;
|
|
||||||
|
|
||||||
let start = Instant::now();
|
|
||||||
|
|
||||||
let resolution = if task_report.resolved == "t" {
|
|
||||||
if task_bans.iter().any(|(_id, ban)| {
|
|
||||||
ban.report_id
|
|
||||||
.map(|report_id| task_report.id == report_id)
|
|
||||||
.unwrap_or(false)
|
|
||||||
}) {
|
|
||||||
Some(ReportResolution::Ban)
|
|
||||||
} else if task_warns
|
|
||||||
.iter()
|
|
||||||
.any(|(_id, warn)| warn.report_id == task_report.id)
|
|
||||||
{
|
|
||||||
Some(ReportResolution::Warn)
|
|
||||||
} else {
|
|
||||||
Some(ReportResolution::Skip)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let payphone_report = PayphoneReport {
|
|
||||||
id: task_report.id,
|
|
||||||
user_id: task_report.user_id,
|
|
||||||
message: MessageData {
|
|
||||||
id: u64_to_i64(task_report.message_id),
|
|
||||||
call_id: 0,
|
|
||||||
author_id: u64_to_i64(task_report.user_id),
|
|
||||||
author_name: task_report.user_name,
|
|
||||||
author_avatar_url: task_report.user_avatar_url,
|
|
||||||
author_mask: None,
|
|
||||||
content: task_report.message_content,
|
|
||||||
attachments: vec![],
|
|
||||||
sticker: None,
|
|
||||||
propagation_message_id: None,
|
|
||||||
propagation_channel_id: None,
|
|
||||||
replying_to_message_id: None,
|
|
||||||
is_deleted: false,
|
|
||||||
is_edited: false,
|
|
||||||
is_censored: false,
|
|
||||||
},
|
|
||||||
created_at: OffsetDateTime::parse(&task_report.created_at, &task_format)
|
|
||||||
.expect("Failed to parse created_at")
|
|
||||||
.to_utc(),
|
|
||||||
created_by_ids: task_report
|
|
||||||
.reported_by_id
|
|
||||||
.map(|id| vec![id])
|
|
||||||
.unwrap_or_default(),
|
|
||||||
replying_to: None,
|
|
||||||
reviewed_at: task_report.resolved_at.as_ref().map(|s| {
|
|
||||||
OffsetDateTime::parse(s, &task_format)
|
|
||||||
.expect("Failed to parse resolved_at")
|
|
||||||
.to_utc()
|
|
||||||
}),
|
|
||||||
resolution,
|
|
||||||
reviewed_by_id: task_report.resolved_by_id,
|
|
||||||
};
|
|
||||||
|
|
||||||
payphone_report
|
|
||||||
.insert(&task_db)
|
|
||||||
.await
|
|
||||||
.expect("Failed to insert report");
|
|
||||||
|
|
||||||
let duration = start.elapsed();
|
|
||||||
println!(
|
|
||||||
"({i}) Inserted report {} in {:?}",
|
|
||||||
payphone_report.id, duration
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i, ban) in bans.values().enumerate() {
|
|
||||||
let task_semaphore = semaphore.clone();
|
|
||||||
let task_format = format.clone();
|
|
||||||
let task_db = db.clone();
|
|
||||||
let task_reports = reports.clone();
|
|
||||||
let task_ban = Arc::new(ban.clone());
|
|
||||||
|
|
||||||
tasks.push(tokio::spawn(async move {
|
|
||||||
let _permit = task_semaphore.acquire().await;
|
|
||||||
|
|
||||||
let start = Instant::now();
|
|
||||||
|
|
||||||
let message = task_reports
|
|
||||||
.iter()
|
|
||||||
.find(|report| {
|
|
||||||
task_ban
|
|
||||||
.report_id
|
|
||||||
.map(|id| id == report.id)
|
|
||||||
.unwrap_or(false)
|
|
||||||
})
|
|
||||||
.map(|report| MessageData {
|
|
||||||
id: u64_to_i64(report.message_id),
|
|
||||||
call_id: 0,
|
|
||||||
author_id: u64_to_i64(report.user_id),
|
|
||||||
author_name: report.user_name.clone(),
|
|
||||||
author_avatar_url: report.user_avatar_url.clone(),
|
|
||||||
author_mask: None,
|
|
||||||
content: report.message_content.clone(),
|
|
||||||
attachments: vec![],
|
|
||||||
sticker: None,
|
|
||||||
propagation_message_id: None,
|
|
||||||
propagation_channel_id: None,
|
|
||||||
replying_to_message_id: None,
|
|
||||||
is_deleted: false,
|
|
||||||
is_edited: false,
|
|
||||||
is_censored: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
let payphone_incident = UserIncident {
|
|
||||||
incident_id: get_random_u64(),
|
|
||||||
user_id: task_ban.user_id,
|
|
||||||
report_id: task_ban.report_id,
|
|
||||||
r#type: UserIncidentType::Ban,
|
|
||||||
message,
|
|
||||||
reason: task_ban.reason.clone(),
|
|
||||||
created_at: OffsetDateTime::parse(&task_ban.created_at, &task_format)
|
|
||||||
.expect("Failed to parse created_at")
|
|
||||||
.to_utc(),
|
|
||||||
created_by_id: Some(task_ban.created_by_id),
|
|
||||||
duration: None,
|
|
||||||
expires_at: task_ban.expires_at.as_ref().map(|expires_at| {
|
|
||||||
OffsetDateTime::parse(expires_at, &task_format)
|
|
||||||
.expect("Failed to parse expires_at")
|
|
||||||
.to_utc()
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
payphone_incident
|
|
||||||
.insert(&task_db)
|
|
||||||
.await
|
|
||||||
.expect("Failed to insert ban");
|
|
||||||
|
|
||||||
let duration = start.elapsed();
|
|
||||||
println!(
|
|
||||||
"({i}) Inserted incident (ban) {} in {:?}",
|
|
||||||
payphone_incident.incident_id, duration
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i, warn) in warns.values().enumerate() {
|
|
||||||
let task_semaphore = semaphore.clone();
|
|
||||||
let task_format = format.clone();
|
|
||||||
let task_db = db.clone();
|
|
||||||
let task_reports = reports.clone();
|
|
||||||
let task_warn = Arc::new(warn.clone());
|
|
||||||
|
|
||||||
tasks.push(tokio::spawn(async move {
|
|
||||||
let _permit = task_semaphore.acquire().await;
|
|
||||||
|
|
||||||
let start = Instant::now();
|
|
||||||
|
|
||||||
let message = task_reports
|
|
||||||
.iter()
|
|
||||||
.find(|report| report.id == task_warn.report_id)
|
|
||||||
.map(|report| MessageData {
|
|
||||||
id: u64_to_i64(report.message_id),
|
|
||||||
call_id: 0,
|
|
||||||
author_id: u64_to_i64(report.user_id),
|
|
||||||
author_name: report.user_name.clone(),
|
|
||||||
author_avatar_url: report.user_avatar_url.clone(),
|
|
||||||
author_mask: None,
|
|
||||||
content: report.message_content.clone(),
|
|
||||||
attachments: vec![],
|
|
||||||
sticker: None,
|
|
||||||
propagation_message_id: None,
|
|
||||||
propagation_channel_id: None,
|
|
||||||
replying_to_message_id: None,
|
|
||||||
is_deleted: false,
|
|
||||||
is_edited: false,
|
|
||||||
is_censored: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
let payphone_incident = UserIncident {
|
|
||||||
incident_id: get_random_u64(),
|
|
||||||
user_id: task_warn.user_id,
|
|
||||||
report_id: Some(task_warn.report_id),
|
|
||||||
r#type: UserIncidentType::Warning,
|
|
||||||
message,
|
|
||||||
reason: task_warn.reason.clone(),
|
|
||||||
created_at: OffsetDateTime::parse(&task_warn.created_at, &task_format)
|
|
||||||
.expect("Failed to parse created_at")
|
|
||||||
.to_utc(),
|
|
||||||
created_by_id: Some(task_warn.created_by_id),
|
|
||||||
duration: None,
|
|
||||||
expires_at: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
payphone_incident
|
|
||||||
.insert(&task_db)
|
|
||||||
.await
|
|
||||||
.expect("Failed to insert warn");
|
|
||||||
|
|
||||||
let duration = start.elapsed();
|
|
||||||
println!(
|
|
||||||
"({i}) Inserted incident (warn) {} in {:?}",
|
|
||||||
payphone_incident.incident_id, duration
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
for task in tasks {
|
|
||||||
task.await.expect("Failed to join task");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+3
-10
@@ -196,21 +196,14 @@ pub enum Commands {
|
|||||||
database_addr: String,
|
database_addr: String,
|
||||||
|
|
||||||
/// The username to use when connecting to the database.
|
/// The username to use when connecting to the database.
|
||||||
#[arg(
|
#[arg(long, env = "PAYPHONE_DATABASE_USERNAME", value_name = "USERNAME")]
|
||||||
long,
|
|
||||||
env = "PAYPHONE_DATABASE_USERNAME",
|
|
||||||
value_name = "USERNAME"
|
|
||||||
)]
|
|
||||||
database_username: Option<String>,
|
database_username: Option<String>,
|
||||||
|
|
||||||
/// The password to use when connecting to the database.
|
/// The password to use when connecting to the database.
|
||||||
#[arg(
|
#[arg(long, env = "PAYPHONE_DATABASE_PASSWORD", value_name = "PASSWORD")]
|
||||||
long,
|
|
||||||
env = "PAYPHONE_DATABASE_PASSWORD",
|
|
||||||
value_name = "PASSWORD"
|
|
||||||
)]
|
|
||||||
database_password: Option<String>,
|
database_password: Option<String>,
|
||||||
|
|
||||||
|
/// The current shard being run.
|
||||||
#[arg(
|
#[arg(
|
||||||
long,
|
long,
|
||||||
short,
|
short,
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ CREATE TABLE IF NOT EXISTS payphone.user_incidents (
|
|||||||
expires_at TIMESTAMP,
|
expires_at TIMESTAMP,
|
||||||
duration ASCII,
|
duration ASCII,
|
||||||
|
|
||||||
PRIMARY KEY (user_id)
|
PRIMARY KEY (user_id, incident_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS payphone.server_incidents (
|
CREATE TABLE IF NOT EXISTS payphone.server_incidents (
|
||||||
|
|||||||
+25
-1
@@ -2,6 +2,7 @@ use std::{fmt::Debug, sync::Arc};
|
|||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use twilight_cache_inmemory::{DefaultInMemoryCache, ResourceType};
|
||||||
use twilight_gateway::{Event, EventTypeFlags, Intents, Shard, ShardId, StreamExt};
|
use twilight_gateway::{Event, EventTypeFlags, Intents, Shard, ShardId, StreamExt};
|
||||||
use twilight_http::Client;
|
use twilight_http::Client;
|
||||||
|
|
||||||
@@ -88,11 +89,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Bot<T: Send + Sync = ()> {
|
pub struct Bot<T: Send + Sync> {
|
||||||
shard: ShardId,
|
shard: ShardId,
|
||||||
state: Arc<T>,
|
state: Arc<T>,
|
||||||
prefixes: Arc<dyn PrefixGetter<T> + Send + Sync>,
|
prefixes: Arc<dyn PrefixGetter<T> + Send + Sync>,
|
||||||
intents: Intents,
|
intents: Intents,
|
||||||
|
cached_resource_types: Vec<ResourceType>,
|
||||||
commands: Vec<Arc<dyn Command<T>>>,
|
commands: Vec<Arc<dyn Command<T>>>,
|
||||||
components: Vec<Arc<dyn Component<T>>>,
|
components: Vec<Arc<dyn Component<T>>>,
|
||||||
on_ready_handlers: Vec<Arc<dyn OnReadyHandler<T>>>,
|
on_ready_handlers: Vec<Arc<dyn OnReadyHandler<T>>>,
|
||||||
@@ -113,6 +115,7 @@ impl<T: 'static + Send + Sync> Bot<T> {
|
|||||||
state: Arc::new(state),
|
state: Arc::new(state),
|
||||||
prefixes: Arc::new(prefixes),
|
prefixes: Arc::new(prefixes),
|
||||||
intents: Intents::empty(),
|
intents: Intents::empty(),
|
||||||
|
cached_resource_types: Vec::new(),
|
||||||
commands: Vec::new(),
|
commands: Vec::new(),
|
||||||
components: Vec::new(),
|
components: Vec::new(),
|
||||||
on_ready_handlers: Vec::new(),
|
on_ready_handlers: Vec::new(),
|
||||||
@@ -147,6 +150,14 @@ impl<T: 'static + Send + Sync> Bot<T> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cache_resource_type(mut self, resource_type: ResourceType) -> Self {
|
||||||
|
if !self.cached_resource_types.contains(&resource_type) {
|
||||||
|
self.cached_resource_types.push(resource_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn on_ready(mut self, handler: impl OnReadyHandler<T> + 'static) -> Self {
|
pub fn on_ready(mut self, handler: impl OnReadyHandler<T> + 'static) -> Self {
|
||||||
self.on_ready_handlers.push(Arc::new(handler));
|
self.on_ready_handlers.push(Arc::new(handler));
|
||||||
self
|
self
|
||||||
@@ -219,6 +230,16 @@ impl<T: 'static + Send + Sync> Bot<T> {
|
|||||||
|
|
||||||
let bot = Arc::new(self);
|
let bot = Arc::new(self);
|
||||||
|
|
||||||
|
let mut resource_types = ResourceType::empty();
|
||||||
|
|
||||||
|
for resource_type in &bot.cached_resource_types {
|
||||||
|
resource_types.insert(*resource_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
let cache = DefaultInMemoryCache::builder()
|
||||||
|
.resource_types(resource_types)
|
||||||
|
.build();
|
||||||
|
|
||||||
let runtime = Arc::new(Runtime {
|
let runtime = Arc::new(Runtime {
|
||||||
http,
|
http,
|
||||||
app,
|
app,
|
||||||
@@ -226,6 +247,7 @@ impl<T: 'static + Send + Sync> Bot<T> {
|
|||||||
state: bot.state.clone(),
|
state: bot.state.clone(),
|
||||||
prefixes: bot.prefixes.clone(),
|
prefixes: bot.prefixes.clone(),
|
||||||
commands: bot.commands.clone(),
|
commands: bot.commands.clone(),
|
||||||
|
cache,
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut gateway = Shard::new(bot.shard, token.to_string(), bot.intents);
|
let mut gateway = Shard::new(bot.shard, token.to_string(), bot.intents);
|
||||||
@@ -236,6 +258,8 @@ impl<T: 'static + Send + Sync> Bot<T> {
|
|||||||
let task_bot = bot.clone();
|
let task_bot = bot.clone();
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
task_rt.cache.update(&event);
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
Event::Ready(event) => {
|
Event::Ready(event) => {
|
||||||
for handler in &task_bot.on_ready_handlers {
|
for handler in &task_bot.on_ready_handlers {
|
||||||
|
|||||||
Vendored
-3
@@ -1,3 +0,0 @@
|
|||||||
pub struct RedisCache {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -33,6 +33,9 @@ pub enum CommandError {
|
|||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
DiscordDeserializationFailed(#[from] DeserializeBodyError),
|
DiscordDeserializationFailed(#[from] DeserializeBodyError),
|
||||||
|
|
||||||
|
#[error("The cache's state was inconsistent.")]
|
||||||
|
CacheStateInconsistent,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
|||||||
@@ -158,7 +158,6 @@
|
|||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
pub mod bot;
|
pub mod bot;
|
||||||
pub mod cache;
|
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
pub mod events;
|
pub mod events;
|
||||||
pub mod interactions;
|
pub mod interactions;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use twilight_cache_inmemory::InMemoryCache;
|
||||||
use twilight_http::Client;
|
use twilight_http::Client;
|
||||||
use twilight_model::oauth::Application;
|
use twilight_model::oauth::Application;
|
||||||
|
|
||||||
@@ -45,6 +46,8 @@ pub struct Runtime<T> {
|
|||||||
|
|
||||||
/// The application state.
|
/// The application state.
|
||||||
pub state: Arc<T>,
|
pub state: Arc<T>,
|
||||||
|
|
||||||
|
pub cache: InMemoryCache,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Runtime<T> {
|
impl<T> Runtime<T> {
|
||||||
|
|||||||
@@ -3,4 +3,8 @@ idiot
|
|||||||
stupid
|
stupid
|
||||||
dumb
|
dumb
|
||||||
moron
|
moron
|
||||||
fool
|
fool
|
||||||
|
stfu
|
||||||
|
syfm
|
||||||
|
sybau
|
||||||
|
gtfo
|
||||||
@@ -75,6 +75,8 @@ goonbeam
|
|||||||
goonbeaming
|
goonbeaming
|
||||||
gooncream
|
gooncream
|
||||||
gooncreaming
|
gooncreaming
|
||||||
|
goonbud
|
||||||
|
goonbuds
|
||||||
boty hole
|
boty hole
|
||||||
suck my pp
|
suck my pp
|
||||||
ass cracker
|
ass cracker
|
||||||
@@ -97,4 +99,23 @@ whre
|
|||||||
tickle your pickle
|
tickle your pickle
|
||||||
tickle yr pickle
|
tickle yr pickle
|
||||||
tickle his pickle
|
tickle his pickle
|
||||||
tickle my pickle
|
tickle my pickle
|
||||||
|
peg
|
||||||
|
peged
|
||||||
|
peging
|
||||||
|
butbang
|
||||||
|
butbanged
|
||||||
|
eat my ass
|
||||||
|
eat my ahh
|
||||||
|
eat mi ass
|
||||||
|
eat my ahh
|
||||||
|
eat my bum
|
||||||
|
eat mi bum
|
||||||
|
ima touch you
|
||||||
|
ima touch u
|
||||||
|
il touch you
|
||||||
|
il touch u
|
||||||
|
im going to touch you
|
||||||
|
im going to touch u
|
||||||
|
im gonna touch you
|
||||||
|
im gonna touch u
|
||||||
@@ -32,15 +32,17 @@ dumb fck
|
|||||||
dumb fuk
|
dumb fuk
|
||||||
dumb fuh
|
dumb fuh
|
||||||
dumb fuhk
|
dumb fuhk
|
||||||
stfu
|
shut the fvck up
|
||||||
|
shut the fck up
|
||||||
shut the fuck up
|
shut the fuck up
|
||||||
syfm
|
|
||||||
shut your fucking mouth
|
shut your fucking mouth
|
||||||
sybau
|
shut your fcking mouth
|
||||||
|
shut your fvcking mouth
|
||||||
shut your bitch as up
|
shut your bitch as up
|
||||||
shut your bih as up
|
shut your bih as up
|
||||||
gtfo
|
|
||||||
get the fuck out
|
get the fuck out
|
||||||
|
get the fvck out
|
||||||
|
get the fck out
|
||||||
|
get tfo
|
||||||
blackie
|
blackie
|
||||||
motherfucker
|
motherfucker
|
||||||
mf
|
|
||||||
@@ -8,7 +8,9 @@ use crate::{
|
|||||||
Command, CommandError,
|
Command, CommandError,
|
||||||
arguments::{Argument, GreedyString, ParseArguments},
|
arguments::{Argument, GreedyString, ParseArguments},
|
||||||
context::CommandContext,
|
context::CommandContext,
|
||||||
|
permissions::Permission,
|
||||||
},
|
},
|
||||||
|
groups::servers::permissions::{GuildOnlyPermission, ServerModeratorPermission},
|
||||||
state::State,
|
state::State,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -37,6 +39,13 @@ impl Command<State> for PrefixCommand {
|
|||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn permissions(&self) -> Vec<Box<dyn Permission<State> + Send + Sync + 'static>> {
|
||||||
|
vec![
|
||||||
|
Box::new(GuildOnlyPermission),
|
||||||
|
Box::new(ServerModeratorPermission),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
async fn execute(
|
async fn execute(
|
||||||
&self,
|
&self,
|
||||||
ctx: CommandContext<'_, State>,
|
ctx: CommandContext<'_, State>,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use twilight_model::guild::Permissions;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
framework::commands::{CommandError, context::CommandContext, permissions::Permission},
|
framework::commands::{CommandError, context::CommandContext, permissions::Permission},
|
||||||
@@ -11,7 +12,15 @@ pub struct GuildOnlyPermission;
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Permission<State> for GuildOnlyPermission {
|
impl Permission<State> for GuildOnlyPermission {
|
||||||
async fn check(&self, ctx: &CommandContext<State>) -> Result<bool, CommandError> {
|
async fn check(&self, ctx: &CommandContext<State>) -> Result<bool, CommandError> {
|
||||||
Ok(ctx.event.guild_id.is_none())
|
Ok(ctx.event.guild_id.is_some())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn on_handle_denied(&self, ctx: &CommandContext<State>) -> Result<(), CommandError> {
|
||||||
|
ctx.send()
|
||||||
|
.content("❌ This command can only be used in a server.")
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,7 +29,37 @@ pub struct ServerModeratorPermission;
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Permission<State> for ServerModeratorPermission {
|
impl Permission<State> for ServerModeratorPermission {
|
||||||
async fn check(&self, _ctx: &CommandContext<State>) -> Result<bool, CommandError> {
|
async fn check(&self, ctx: &CommandContext<State>) -> Result<bool, CommandError> {
|
||||||
Ok(true)
|
if let Some(guild_id) = ctx.event.guild_id {
|
||||||
|
let permissions = ctx
|
||||||
|
.rt
|
||||||
|
.cache
|
||||||
|
.permissions()
|
||||||
|
.root(ctx.event.author.id, guild_id);
|
||||||
|
|
||||||
|
if let Ok(permissions) = permissions {
|
||||||
|
let guild = ctx
|
||||||
|
.rt
|
||||||
|
.cache
|
||||||
|
.guild(guild_id)
|
||||||
|
.ok_or(CommandError::CacheStateInconsistent)?;
|
||||||
|
|
||||||
|
Ok(permissions
|
||||||
|
.contains(Permissions::MANAGE_CHANNELS | Permissions::MANAGE_MESSAGES)
|
||||||
|
|| guild.owner_id() == ctx.event.author.id)
|
||||||
|
} else {
|
||||||
|
Err(CommandError::CacheStateInconsistent)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn on_handle_denied(&self, ctx: &CommandContext<State>) -> Result<(), CommandError> {
|
||||||
|
ctx.send()
|
||||||
|
.content("❌ This command can only be run by a server moderator.\n-# 🛈 Moderators must have permission to manage messages and to manage channels.")
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
pub mod cli;
|
|
||||||
pub mod constants;
|
|
||||||
pub mod database;
|
|
||||||
pub mod discord;
|
|
||||||
pub mod framework;
|
|
||||||
pub mod groups;
|
|
||||||
pub mod logging;
|
|
||||||
pub mod state;
|
|
||||||
pub mod utils;
|
|
||||||
+7
-1
@@ -113,6 +113,7 @@ use clap::Parser;
|
|||||||
use notify::{Event, EventKind, Watcher};
|
use notify::{Event, EventKind, Watcher};
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use tower_http::services::ServeDir;
|
use tower_http::services::ServeDir;
|
||||||
|
use twilight_cache_inmemory::ResourceType;
|
||||||
use twilight_gateway::{Intents, ShardId};
|
use twilight_gateway::{Intents, ShardId};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -227,7 +228,7 @@ async fn start(
|
|||||||
.await
|
.await
|
||||||
.expect("Could not connect to the database!");
|
.expect("Could not connect to the database!");
|
||||||
|
|
||||||
log::info!("Database connection established successfully!");
|
log::info!("Database connection established successfully.");
|
||||||
|
|
||||||
let state = State { db };
|
let state = State { db };
|
||||||
|
|
||||||
@@ -235,6 +236,7 @@ async fn start(
|
|||||||
.shard(shard)
|
.shard(shard)
|
||||||
.intent(Intents::GUILDS)
|
.intent(Intents::GUILDS)
|
||||||
.intent(Intents::GUILD_MESSAGES)
|
.intent(Intents::GUILD_MESSAGES)
|
||||||
|
.intent(Intents::GUILD_MEMBERS)
|
||||||
.intent(Intents::MESSAGE_CONTENT)
|
.intent(Intents::MESSAGE_CONTENT)
|
||||||
.command(HelpCommand)
|
.command(HelpCommand)
|
||||||
.command(CallCommand::new())
|
.command(CallCommand::new())
|
||||||
@@ -243,6 +245,10 @@ async fn start(
|
|||||||
.command(FriendRequestCommand)
|
.command(FriendRequestCommand)
|
||||||
.command(PrefixCommand)
|
.command(PrefixCommand)
|
||||||
.component(HelpGoBackButton)
|
.component(HelpGoBackButton)
|
||||||
|
.cache_resource_type(ResourceType::GUILD)
|
||||||
|
.cache_resource_type(ResourceType::CHANNEL)
|
||||||
|
.cache_resource_type(ResourceType::MEMBER)
|
||||||
|
.cache_resource_type(ResourceType::ROLE)
|
||||||
.on_ready(ReadyHandler)
|
.on_ready(ReadyHandler)
|
||||||
.on_reconnect(ReconnectHandler)
|
.on_reconnect(ReconnectHandler)
|
||||||
.on_message(CallMessageHandler)
|
.on_message(CallMessageHandler)
|
||||||
|
|||||||
Reference in New Issue
Block a user