UNPKG

@m3rcena/weky

Version:

A fun npm package to play games within Discord with buttons!

309 lines (308 loc) 13.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const chalk_1 = tslib_1.__importDefault(require("chalk")); const discord_js_1 = require("discord.js"); const mathjs_1 = require("mathjs"); const functions_js_1 = require("../../functions/functions.js"); const OptionChecking_js_1 = require("../../functions/OptionChecking.js"); const Calculator = async (options) => { // Validate calculator options (0, OptionChecking_js_1.OptionsChecking)(options, "Calculator"); let message = options.message; if (!message) throw new Error(chalk_1.default.red("[@m3rcena/weky] Calculator Error:") + " No message provided."); let client = options.client; let str = " "; let stringify = "```\n" + str + "\n```"; const text = ["DC", "RND", "SIN", "COS", "TAN", "^", "LG", "LN", "(", ")", "SQRT", "%", "÷", "AC", "⌫", "x!", "7", "8", "9", "x"]; const text2 = ["1/x", "4", "5", "6", " - ", "π", "1", "2", "3", " + ", "ans", "e", "0", ".", "="]; let disabled = true; let lastInput; // Handle modal inputs for special operations (log, sin, etc.) const handleModalInput = async (interact, modalId, operation) => { const modal = new discord_js_1.ModalBuilder().setTitle(modalId).setCustomId(`md${modalId}`); const input = new discord_js_1.TextInputBuilder().setCustomId(`number${modalId}`).setLabel(`Enter the number for ${operation}`).setStyle(discord_js_1.TextInputStyle.Short).setRequired(true); modal.addComponents(new discord_js_1.ActionRowBuilder().addComponents(input)); await interact.showModal(modal); return new Promise((resolve) => { const modalHandler = async (modal) => { if (!modal.isModalSubmit() || modal.customId !== `md${modalId}`) return; client.off("interactionCreate", modalHandler); await modal.deferUpdate(); resolve(modal.fields.getTextInputValue(`number${modalId}`)); }; client.on("interactionCreate", modalHandler); setTimeout(() => client.off("interactionCreate", modalHandler), 300000); }); }; // Process calculations using mathjs const handleCalculation = (input) => { try { const result = (0, mathjs_1.evaluate)(input); // Handle special cases if (typeof result === "number") { if (isNaN(result)) { return { result: null, error: "Invalid calculation (NaN)" }; } if (!isFinite(result)) { if (result === Infinity) { return { result: null, error: "Result too large (∞)" }; } if (result === -Infinity) { return { result: null, error: "Result too small (-∞)" }; } return { result: null, error: "Result is infinite" }; } // Check if result is extremely large (more than 15 digits) if (Math.abs(result) > 1e15) { return { result: null, error: "Result too large to display" }; } } return { result, error: null }; } catch (e) { return { result: null, error: options.invalidQuery || "Invalid calculation" }; } }; // Set up calculator display using Components V2 if (!message.channel || !message.channel.isTextBased() || !message.channel.isSendable()) { throw new Error(chalk_1.default.red("[@m3rcena/weky] Calculator Error:") + " Message must be a text-based channel."); } const channel = message.channel; // Create Components V2 structure const createCalculatorContainer = (displayText, buttonsEnabled) => { const container = new discord_js_1.ContainerBuilder() .setAccentColor(typeof options.embed.color === "number" ? options.embed.color : 0x5865f2) // Use embed color or default blurple .addTextDisplayComponents((textDisplay) => textDisplay.setContent(displayText)); // First container: text array buttons (25 buttons = 5 rows) for (let i = 0; i < text.length; i += 5) { const rowButtons = text.slice(i, i + 5).map((text) => (buttonsEnabled ? (0, functions_js_1.createButton)(text, false) : (0, functions_js_1.createDisabledButton)(text))); container.addActionRowComponents((actionRow) => actionRow.setComponents(...rowButtons)); } return container; }; const createCalculatorContainer2 = (buttonsEnabled) => { const container = new discord_js_1.ContainerBuilder() .setAccentColor(typeof options.embed.color === "number" ? options.embed.color : 0x5865f2) // Use embed color or default blurple .addTextDisplayComponents((textDisplay) => textDisplay.setContent("\u200B")); // Invisible content using Zero Width Space // Second container: text2 array buttons (15 buttons = 3 rows) for (let i = 0; i < text2.length; i += 5) { const rowButtons = text2.slice(i, i + 5).map((text) => (buttonsEnabled ? (0, functions_js_1.createButton)(text, false) : (0, functions_js_1.createDisabledButton)(text))); container.addActionRowComponents((actionRow) => actionRow.setComponents(...rowButtons)); } return container; }; // Message-based calculator setup using Components V2 const msg = await message.reply({ components: [createCalculatorContainer(stringify, true)], flags: discord_js_1.MessageFlags.IsComponentsV2, allowedMentions: { repliedUser: false }, }); // Send second message with additional buttons const msg2 = await message.channel.send({ components: [createCalculatorContainer2(true)], flags: discord_js_1.MessageFlags.IsComponentsV2, }); // Calculator logic async function edit() { if (msg.editable) { await msg.edit({ components: [createCalculatorContainer(stringify, !disabled)], flags: discord_js_1.MessageFlags.IsComponentsV2, allowedMentions: { repliedUser: false }, }); } else { await message.reply({ content: `An error occured while trying to edit the calculator.`, }); } } async function edit2() { if (msg2.editable) { await msg2.edit({ components: [createCalculatorContainer2(!disabled)], flags: discord_js_1.MessageFlags.IsComponentsV2, }); } } async function lock(disabled) { if (msg.editable) { await msg.edit({ components: [createCalculatorContainer(stringify, false)], flags: discord_js_1.MessageFlags.IsComponentsV2, allowedMentions: { repliedUser: false }, }); } else { await message.reply({ content: `An error occured while trying to lock the calculator.`, }); } if (msg2.editable) { await msg2.edit({ components: [createCalculatorContainer2(false)], flags: discord_js_1.MessageFlags.IsComponentsV2, }); } } let id = message.author.id; const calc = channel.createMessageComponentCollector({ componentType: discord_js_1.ComponentType.Button, time: 300000, }); let answer = "0"; calc.on("collect", async (interact) => { if (interact.user.id !== id) { return interact.reply({ embeds: [ new discord_js_1.EmbedBuilder() .setTitle(options.embed.title ? options.embed.title : "Error | Weky Calculator") .setDescription(`You are not allowed to interact with this calculator as you are not the user who initiated the command.\n\n**Note:** This calculator is only for the user <@${id}>`) .setColor("Red") .setTimestamp(options.embed.timestamp ? new Date() : null), ], flags: [discord_js_1.MessageFlags.Ephemeral], }); } if (interact.customId !== "calLG" && interact.customId !== "calSQRT" && interact.customId !== "calRND" && interact.customId !== "calSIN" && interact.customId !== "calCOS" && interact.customId !== "calTAN" && interact.customId !== "calLN" && interact.customId !== "cal1/x" && interact.customId !== "calx!") await interact.deferUpdate(); switch (interact.customId) { case "calAC": lastInput = null; str = " "; stringify = "```\n" + str + "\n```"; edit(); edit2(); break; case "calx": lastInput = interact.customId; str += " * "; stringify = "```\n" + str + "\n```"; edit(); edit2(); break; case "cal÷": lastInput = interact.customId; str += " / "; stringify = "```\n" + str + "\n```"; edit(); edit2(); break; case "cal⌫": if (str === " " || str === "" || str === null || str === undefined) { lastInput = null; return; } lastInput = interact.customId; if (str.slice(0, -1) === " " || str.slice(0, -1) === "" || str.slice(0, -1) === null || str.slice(0, -1) === undefined) { lastInput = null; } str = str.slice(-1) === " " ? str.slice(0, -3) : str.slice(0, -1); stringify = "```\n" + str + "\n```"; edit(); edit2(); break; case "cal=": lastInput = null; if (str === " " || str === "" || str === null || str === undefined) { return; } const { result, error } = handleCalculation(str); if (result !== null) { answer = result; str += " = " + result; } else { str = error; answer = "0"; } stringify = "```\n" + str + "\n```"; edit(); edit2(); str = " "; stringify = "```\n" + str + "\n```"; break; case "calLG": case "calSQRT": case "calRND": case "calSIN": case "calCOS": case "calTAN": case "calLN": case "cal1/x": case "calx!": { const operationMap = { calLG: ["Log", "logarithm 10", "log10"], calSQRT: ["Sqrt", "square root", "sqrt"], calRND: ["Rnd", "round", "round"], calSIN: ["Sin", "sine", "sin"], calCOS: ["Cos", "cosine", "cos"], calTAN: ["Tan", "tangent", "tan"], calLN: ["Ln", "natural logarithm", "log"], "cal1/x": ["Reciprocal", "reciprocal", "1/"], "calx!": ["Factorial", "factorial", "!"], }; const [modalTitle, operation, func] = operationMap[interact.customId]; const number = await handleModalInput(interact, modalTitle, operation); if (number) { str += func === "!" ? number + func : `${func}(${number})`; stringify = "```\n" + str + "\n```"; lastInput = interact.customId; edit(); edit2(); } break; } case "calπ": lastInput = interact.customId; str += "pi"; stringify = "```\n" + str + "\n```"; edit(); edit2(); break; case "cale": lastInput = interact.customId; str += "e"; stringify = "```\n" + str + "\n```"; edit(); edit2(); break; case "calans": lastInput = interact.customId; str += `${answer}`; stringify = "```\n" + str + "\n```"; edit(); edit2(); break; case "calDC": calc.stop(); break; default: lastInput = interact.customId; str += interact.customId.replace("cal", ""); stringify = "```\n" + str + "\n```"; edit(); edit2(); break; } if (disabled === true && lastInput !== null && lastInput !== undefined) { disabled = false; } else if (((disabled === false && lastInput === null) || lastInput === undefined) && interact.customId !== "calDC") { disabled = true; } }); calc.on("end", async () => { str = "Calculator has been stopped"; stringify = "```\n" + str + "\n```"; edit(); edit2(); lock(true); }); // Check for package updates (0, functions_js_1.checkPackageUpdates)("Calculator", options.notifyUpdate); }; exports.default = Calculator;