UNPKG

@zerospacegg/vynthra

Version:
126 lines 4.75 kB
const { renderSearchResultAsMarkdown, searchEntities, } = require("../../lib/index.cjs"); const statsSubcommand = { name: "stats", description: "Get stats for a unit, building, faction, or map", builder: (subcommand) => subcommand .setName("stats") .setDescription("Get stats for a unit, building, faction, or map") .addStringOption((option) => option .setName("query") .setDescription("Search term (unit name, building, faction, etc.)") .setRequired(true)) .addBooleanOption((option) => option .setName("public") .setDescription("Show publicly (default: private)") .setRequired(false)), async execute(interaction) { const query = interaction.options.getString("query", true); const isPublic = interaction.options.getBoolean("public") ?? false; try { // Use public flag to determine ephemeral behavior if (!interaction.deferred) { await interaction.deferReply({ ephemeral: !isPublic }); } const result = searchEntities(query); const markdown = renderSearchResultAsMarkdown(result); // Discord has a 2000 character limit for messages // If the response is too long, we'll need to truncate or split it if (markdown.length <= 2000) { await interaction.editReply(markdown); } else { // Split the message into chunks const chunks = splitMessage(markdown, 2000); // Send the first chunk as the reply await interaction.editReply(chunks[0]); // Send additional chunks as follow-up messages (match the ephemeral setting) for (let i = 1; i < chunks.length; i++) { await interaction.followUp({ content: chunks[i], ephemeral: !isPublic, }); } } } catch (error) { console.error("Error processing stats command:", error); // If we haven't deferred yet, defer as ephemeral for errors if (!interaction.deferred) { await interaction.deferReply({ ephemeral: true }); } await interaction.editReply({ content: `❌ Error searching for "${query}": ${error instanceof Error ? error.message : "Unknown error"}`, }); } }, }; /** * Split a message into chunks that fit within Discord's character limit * Tries to split at logical boundaries (newlines) when possible */ function splitMessage(message, maxLength) { if (message.length <= maxLength) { return [message]; } const chunks = []; let currentChunk = ""; const lines = message.split("\n"); for (const line of lines) { // If adding this line would exceed the limit if (currentChunk.length + line.length + 1 > maxLength) { // If we have content in the current chunk, save it if (currentChunk.trim()) { chunks.push(currentChunk.trim()); currentChunk = ""; } // If this single line is too long, we need to split it if (line.length > maxLength) { const lineParts = splitLongLine(line, maxLength); chunks.push(...lineParts.slice(0, -1)); currentChunk = lineParts[lineParts.length - 1]; } else { currentChunk = line; } } else { // Add the line to current chunk if (currentChunk) { currentChunk += "\n" + line; } else { currentChunk = line; } } } // Don't forget the last chunk if (currentChunk.trim()) { chunks.push(currentChunk.trim()); } return chunks; } /** * Split a single long line into multiple parts */ function splitLongLine(line, maxLength) { const parts = []; let remaining = line; while (remaining.length > maxLength) { // Try to find a good break point (space, comma, etc.) let breakPoint = maxLength; for (let i = maxLength - 1; i > maxLength * 0.7; i--) { if (/\s|,|;|\|/.test(remaining[i])) { breakPoint = i; break; } } parts.push(remaining.substring(0, breakPoint).trim()); remaining = remaining.substring(breakPoint).trim(); } if (remaining) { parts.push(remaining); } return parts; } //# sourceMappingURL=stats.js.map exports.statsSubcommand = statsSubcommand;