huge changes
This commit is contained in:
99
utils.js
99
utils.js
@@ -275,7 +275,106 @@ function replaceVariables(template, context = {}) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Sanitize user input for safe embedding in Discord code blocks. */
|
||||
function sanitizeEmbedText(str) {
|
||||
if (str == null) return '';
|
||||
return String(str).replace(/```/g, "'''").trim();
|
||||
}
|
||||
|
||||
// --- EMBED TRUNCATION ---
|
||||
|
||||
/** Truncate a string for use as an embed field value (max 1024). */
|
||||
function truncateEmbedField(str, max = 1024) {
|
||||
if (str == null) return '';
|
||||
const s = String(str);
|
||||
return s.length > max ? s.slice(0, max - 3) + '...' : s;
|
||||
}
|
||||
|
||||
/** Truncate a string for use as an embed description (max 4096). */
|
||||
function truncateEmbedDescription(str, max = 4096) {
|
||||
if (str == null) return '';
|
||||
const s = String(str);
|
||||
return s.length > max ? s.slice(0, max - 3) + '...' : s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforce the 6 000 char total embed limit across an array of EmbedBuilder
|
||||
* instances. Mutates in place: trims the largest description first, then
|
||||
* largest field values, until the total is under 6 000 chars.
|
||||
* Returns the same array for chaining.
|
||||
*/
|
||||
function enforceEmbedLimit(embeds) {
|
||||
const charCount = (e) => {
|
||||
const d = e.data || {};
|
||||
let total = 0;
|
||||
if (d.title) total += d.title.length;
|
||||
if (d.description) total += d.description.length;
|
||||
if (d.footer?.text) total += d.footer.text.length;
|
||||
if (d.author?.name) total += d.author.name.length;
|
||||
if (d.fields) {
|
||||
for (const f of d.fields) {
|
||||
if (f.name) total += f.name.length;
|
||||
if (f.value) total += f.value.length;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
};
|
||||
|
||||
const LIMIT = 6000;
|
||||
|
||||
const totalChars = () => embeds.reduce((sum, e) => sum + charCount(e), 0);
|
||||
|
||||
// Trim largest descriptions first
|
||||
while (totalChars() > LIMIT) {
|
||||
let largestIdx = -1;
|
||||
let largestLen = 0;
|
||||
for (let i = 0; i < embeds.length; i++) {
|
||||
const desc = embeds[i].data?.description;
|
||||
if (desc && desc.length > largestLen) {
|
||||
largestLen = desc.length;
|
||||
largestIdx = i;
|
||||
}
|
||||
}
|
||||
if (largestIdx === -1 || largestLen <= 4) break;
|
||||
const excess = totalChars() - LIMIT;
|
||||
const newLen = Math.max(1, largestLen - excess - 3);
|
||||
embeds[largestIdx].setDescription(
|
||||
embeds[largestIdx].data.description.slice(0, newLen) + '...'
|
||||
);
|
||||
if (totalChars() <= LIMIT) break;
|
||||
// If still over, loop will pick next largest
|
||||
}
|
||||
|
||||
// Trim largest field values
|
||||
while (totalChars() > LIMIT) {
|
||||
let targetEmbed = null;
|
||||
let targetFieldIdx = -1;
|
||||
let targetLen = 0;
|
||||
for (const e of embeds) {
|
||||
const fields = e.data?.fields || [];
|
||||
for (let fi = 0; fi < fields.length; fi++) {
|
||||
if (fields[fi].value && fields[fi].value.length > targetLen) {
|
||||
targetLen = fields[fi].value.length;
|
||||
targetEmbed = e;
|
||||
targetFieldIdx = fi;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!targetEmbed || targetLen <= 4) break;
|
||||
const excess = totalChars() - LIMIT;
|
||||
const newLen = Math.max(1, targetLen - excess - 3);
|
||||
targetEmbed.data.fields[targetFieldIdx].value =
|
||||
targetEmbed.data.fields[targetFieldIdx].value.slice(0, newLen) + '...';
|
||||
}
|
||||
|
||||
return embeds;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
sanitizeEmbedText,
|
||||
truncateEmbedField,
|
||||
truncateEmbedDescription,
|
||||
enforceEmbedLimit,
|
||||
BLOCK_TAG_REGEX,
|
||||
escapeRegex,
|
||||
escapeHtml,
|
||||
|
||||
Reference in New Issue
Block a user