diff --git a/Cargo.lock b/Cargo.lock
index e3c6f52..5a4c974 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -185,6 +185,12 @@ version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
+[[package]]
+name = "bytecount"
+version = "0.6.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205"
+
[[package]]
name = "bytemuck"
version = "1.14.0"
@@ -203,6 +209,37 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
+[[package]]
+name = "camino"
+version = "1.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "cargo_metadata"
+version = "0.14.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa"
+dependencies = [
+ "camino",
+ "cargo-platform",
+ "semver",
+ "serde",
+ "serde_json",
+]
+
[[package]]
name = "cc"
version = "1.0.83"
@@ -254,7 +291,7 @@ dependencies = [
[[package]]
name = "command_attr"
version = "0.5.0"
-source = "git+https://github.com/GnomedDev/serenity?branch=typesize#01f16c1d7563fdc4b8881f9917218167bd162b49"
+source = "git+https://github.com/GnomedDev/serenity?branch=typesize#45e8aa2c86028a1b172c405b4d4c267c10fc1beb"
dependencies = [
"proc-macro2",
"quote",
@@ -528,6 +565,7 @@ dependencies = [
"tokio",
"toml",
"tracing",
+ "typesize",
]
[[package]]
@@ -644,6 +682,15 @@ dependencies = [
"windows-sys",
]
+[[package]]
+name = "error-chain"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
+dependencies = [
+ "version_check",
+]
+
[[package]]
name = "etcetera"
version = "0.8.0"
@@ -872,6 +919,12 @@ version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
+[[package]]
+name = "glob"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+
[[package]]
name = "h2"
version = "0.3.22"
@@ -1241,6 +1294,21 @@ dependencies = [
"unicase",
]
+[[package]]
+name = "mini-moka"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23e0b72e7c9042467008b10279fc732326bd605459ae03bda88825909dd19b56"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-utils",
+ "dashmap",
+ "skeptic",
+ "smallvec",
+ "tagptr",
+ "triomphe",
+]
+
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@@ -1580,6 +1648,17 @@ dependencies = [
"unicode-ident",
]
+[[package]]
+name = "pulldown-cmark"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998"
+dependencies = [
+ "bitflags 1.3.2",
+ "memchr",
+ "unicase",
+]
+
[[package]]
name = "quote"
version = "1.0.33"
@@ -1917,6 +1996,15 @@ dependencies = [
"cipher",
]
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
[[package]]
name = "schannel"
version = "0.1.22"
@@ -1981,11 +2069,20 @@ dependencies = [
"libc",
]
+[[package]]
+name = "semver"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "serde"
-version = "1.0.192"
+version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001"
+checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
dependencies = [
"serde_derive",
]
@@ -2013,9 +2110,9 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.192"
+version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1"
+checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [
"proc-macro2",
"quote",
@@ -2068,7 +2165,7 @@ dependencies = [
[[package]]
name = "serenity"
version = "0.12.0-rc"
-source = "git+https://github.com/GnomedDev/serenity?branch=typesize#01f16c1d7563fdc4b8881f9917218167bd162b49"
+source = "git+https://github.com/GnomedDev/serenity?branch=typesize#45e8aa2c86028a1b172c405b4d4c267c10fc1beb"
dependencies = [
"arrayvec",
"async-trait",
@@ -2103,7 +2200,7 @@ dependencies = [
[[package]]
name = "serenity-voice-model"
version = "0.1.1"
-source = "git+https://github.com/GnomedDev/serenity?branch=typesize#01f16c1d7563fdc4b8881f9917218167bd162b49"
+source = "git+https://github.com/GnomedDev/serenity?branch=typesize#45e8aa2c86028a1b172c405b4d4c267c10fc1beb"
dependencies = [
"bitflags 2.4.1",
"num-traits",
@@ -2152,6 +2249,21 @@ dependencies = [
"libc",
]
+[[package]]
+name = "skeptic"
+version = "0.13.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8"
+dependencies = [
+ "bytecount",
+ "cargo_metadata",
+ "error-chain",
+ "glob",
+ "pulldown-cmark",
+ "tempfile",
+ "walkdir",
+]
+
[[package]]
name = "slab"
version = "0.4.9"
@@ -2599,6 +2711,12 @@ dependencies = [
"libc",
]
+[[package]]
+name = "tagptr"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
+
[[package]]
name = "tempfile"
version = "3.8.1"
@@ -2915,6 +3033,12 @@ dependencies = [
"strength_reduce",
]
+[[package]]
+name = "triomphe"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee8098afad3fb0c54a9007aab6804558410503ad676d4633f9c2559a00ac0f"
+
[[package]]
name = "try-lock"
version = "0.2.4"
@@ -3019,13 +3143,15 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "typesize"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ca73864118741e554b48344182b9b8a76332e9899976c0319118d8139dbde5c"
+checksum = "3e43a952445d2d9df648a822545093c01699df209ceda4df5ac78fef8969c61c"
dependencies = [
"chrono",
"dashmap",
"hashbrown",
+ "mini-moka",
+ "parking_lot",
"secrecy",
"serde_json",
"time",
@@ -3035,11 +3161,10 @@ dependencies = [
[[package]]
name = "typesize-derive"
-version = "0.1.0"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "952e2645c35faf5f361c03b235a068caace146d889dc3fc464efde95cc5f2260"
+checksum = "5274e4d582fd16b83bf7949cc44d6610d3b0290e441d9e5c337fdda9a003849f"
dependencies = [
- "either",
"proc-macro2",
"quote",
"syn 2.0.39",
@@ -3160,6 +3285,16 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+[[package]]
+name = "walkdir"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
[[package]]
name = "want"
version = "0.3.1"
@@ -3311,6 +3446,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+[[package]]
+name = "winapi-util"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
+dependencies = [
+ "winapi",
+]
+
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
diff --git a/Cargo.toml b/Cargo.toml
index 803c543..4e9d678 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -30,6 +30,7 @@ strum_macros = "0.25"
arrayvec = "0.7.4"
bitflags = "2.4.1"
paste = "1.0.14"
+typesize = "0.1.2"
[dependencies.symphonia]
features = ["mp3", "ogg", "wav", "pcm"]
diff --git a/src/commands/owner.rs b/src/commands/owner.rs
index d8bef00..4a2614f 100644
--- a/src/commands/owner.rs
+++ b/src/commands/owner.rs
@@ -14,14 +14,22 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use std::{borrow::Cow, collections::HashSet, num::NonZeroU16, sync::atomic::Ordering::SeqCst};
+use std::{
+ borrow::Cow,
+ collections::{HashMap, HashSet},
+ num::NonZeroU16,
+ sync::atomic::Ordering::SeqCst,
+};
use self::serenity::builder::*;
use num_format::{Locale, ToFormattedString};
use poise::{futures_util::TryStreamExt, serenity_prelude as serenity, CreateReply};
+use rand::{rngs::ThreadRng, Rng};
+use typesize::TypeSize;
use crate::{
funcs::dm_generic,
+ opt_ext::OptionTryUnwrap,
structs::{Command, CommandResult, Context, PrefixContext, TTSModeChoice},
};
@@ -327,28 +335,96 @@ pub async fn leave(ctx: Context<'_>) -> CommandResult {
.map_err(Into::into)
}
+fn choose_random<'a, T>(rng: &mut ThreadRng, container: &'a [T]) -> &'a T {
+ let index = rng.gen_range(0..container.len());
+ &container[index]
+}
+
+fn choose_random_map<'a, K: std::hash::Hash + Eq, V>(
+ rng: &mut ThreadRng,
+ map: &'a HashMap,
+) -> Option<&'a V> {
+ map.get(map.keys().nth(rng.gen_range(0..map.len()))?)
+}
+
+fn random_guild<'a>(
+ rng: &mut ThreadRng,
+ cache: &'a serenity::Cache,
+) -> Option> {
+ cache.guild(choose_random(rng, &cache.guilds()))
+}
+
#[poise::command(prefix_command, owners_only)]
-pub async fn cache_info(ctx: Context<'_>) -> CommandResult {
- let mut embed = CreateEmbed::default().title("Cache Statistics");
- for cache in ctx.cache().get_statistics() {
- let size = (cache.size / 1000).to_formatted_string(&Locale::en);
- let (count, size_per) = if cache.count == 0 {
- (Cow::Borrowed("0"), Cow::Borrowed("N/A"))
- } else {
- let count = cache.count.to_formatted_string(&Locale::en);
- let mut size_per = (cache.size / cache.count).to_formatted_string(&Locale::en);
- size_per.push('b');
+pub async fn cache_info(ctx: Context<'_>, kind: Option) -> CommandResult {
+ struct Field {
+ name: String,
+ size: usize,
+ value: String,
+ is_collection: bool,
+ }
- (Cow::Owned(count), Cow::Owned(size_per))
+ let serenity_cache = ctx.cache();
+ let cache_stats = {
+ let mut rng = rand::thread_rng();
+ match kind.as_deref() {
+ Some("guild") => random_guild(&mut rng, serenity_cache)
+ .try_unwrap()?
+ .get_size_details(),
+ Some("channel") => {
+ let guild = random_guild(&mut rng, serenity_cache).try_unwrap()?;
+ choose_random_map(&mut rng, &guild.channels)
+ .try_unwrap()?
+ .get_size_details()
+ }
+ Some("role") => {
+ let guild = random_guild(&mut rng, serenity_cache).try_unwrap()?;
+ choose_random_map(&mut rng, &guild.roles)
+ .try_unwrap()?
+ .get_size_details()
+ }
+ _ => serenity_cache.get_size_details(),
+ }
+ };
+
+ let mut fields = Vec::new();
+ for field in cache_stats {
+ let name = format!("`{}`", field.name);
+ let size = field.size.to_formatted_string(&Locale::en);
+ if let Some(count) = field.collection_items {
+ let (count, size_per) = if count == 0 {
+ (Cow::Borrowed("0"), Cow::Borrowed("N/A"))
+ } else {
+ let count_fmt = count.to_formatted_string(&Locale::en);
+ let mut size_per = (field.size / count).to_formatted_string(&Locale::en);
+ size_per.push('b');
+
+ (Cow::Owned(count_fmt), Cow::Owned(size_per))
+ };
+
+ fields.push(Field {
+ name,
+ size: field.size,
+ is_collection: true,
+ value: format!("Size: `{size}b`\nCount: `{count}`\nSize per model: `{size_per}`"),
+ });
+ } else {
+ fields.push(Field {
+ name,
+ size: field.size,
+ is_collection: false,
+ value: format!("Size: `{size}b`"),
+ });
};
-
- embed = embed.field(
- cache.name,
- format!("Size: `{size}kb`\nCount: `{count}`\nSize per model: `{size_per}`"),
- false,
- );
}
+ fields.sort_by_key(|field| field.size);
+ fields.sort_by_key(|field| field.is_collection);
+ fields.reverse();
+
+ let embed = CreateEmbed::default()
+ .title("Cache Statistics")
+ .fields(fields.into_iter().map(|f| (f.name, f.value, true)));
+
ctx.send(CreateReply::default().embed(embed)).await?;
Ok(())
}