///|
/// The limits Discord documents for the embeds of one message, including the
/// 6000-unit total across all of them.
pub fn embed_limit_violations(embeds : Array[Embed]) -> Array[LimitViolation] {
let checker = LimitChecker::new()
checker.count("embeds", Some(embeds.length()), min=0, max=10)
let mut total_length = 0
for embed_index, embed in embeds {
let path = "embeds[\{embed_index}]"
total_length += checker.embed_text("\{path}.title", embed.title, max=256)
total_length += checker.embed_text(
"\{path}.description",
embed.description,
max=4096,
)
checker.count(
"\{path}.fields",
embed.fields.map(fields => fields.length()),
min=0,
max=25,
)
if embed.fields is Some(fields) {
for field_index, field in fields {
let field_path = "\{path}.fields[\{field_index}]"
total_length += checker.embed_text(
"\{field_path}.name",
Some(field.name),
max=256,
)
total_length += checker.embed_text(
"\{field_path}.value",
Some(field.value),
max=1024,
)
}
}
if embed.footer is Some(footer) {
total_length += checker.embed_text(
"\{path}.footer.text",
Some(footer.text),
max=2048,
)
}
if embed.author is Some(author) {
total_length += checker.embed_text(
"\{path}.author.name",
Some(author.name),
max=256,
)
}
}
if total_length > 6000 {
checker.report(
"embeds",
"\{total_length} units across all title, description, field.name, field.value, footer.text, and author.name values (at most 6000)",
)
}
checker.violations
}
///|
/// Discord trims leading and trailing whitespace before applying embed text
/// limits, so this returns the same length used for the per-field and total checks.
fn LimitChecker::embed_text(
self : LimitChecker,
path : String,
text : String?,
max~ : Int,
) -> Int {
guard text is Some(text) else { return 0 }
let trimmed = text.trim().to_owned()
self.text(path, Some(trimmed), max~)
trimmed.length()
}