UNPKG

@grammyjs/commands

Version:
139 lines (138 loc) 5.95 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MyCommandParams = void 0; exports.commands = commands; const array_js_1 = require("./utils/array.js"); const jaro_winkler_js_1 = require("./utils/jaro-winkler.js"); const set_bot_commands_js_1 = require("./utils/set-bot-commands.js"); /** * Installs the commands flavor into the context. */ function commands() { return (ctx, next) => { ctx.setMyCommands = async (commands, options) => { if (!ctx.chat) { throw new Error("cannot call `ctx.setMyCommands` on an update with no `chat` property"); } const { uncompliantCommands, commandsParams: currentChatCommandParams, } = MyCommandParams.from((0, array_js_1.ensureArray)(commands), ctx.chat.id); await (0, set_bot_commands_js_1.setBotCommands)(ctx.api, currentChatCommandParams, uncompliantCommands, options); }; ctx.getNearestCommand = (commands, options) => { if (!ctx.has(":text")) { throw new Error("cannot call `ctx.getNearestCommand` on an update with no `text`"); } const results = (0, array_js_1.ensureArray)(commands) .map((commands) => { var _a; const firstMatch = ctx.getCommandEntities(commands)[0]; const commandLike = (firstMatch === null || firstMatch === void 0 ? void 0 : firstMatch.text.replace(firstMatch.prefix, "")) || ""; const result = (0, jaro_winkler_js_1.fuzzyMatch)(commandLike, commands, { ...options, language: !(options === null || options === void 0 ? void 0 : options.ignoreLocalization) ? (_a = ctx.from) === null || _a === void 0 ? void 0 : _a.language_code : undefined, }); return result; }).sort((a, b) => { var _a, _b; return ((_a = b === null || b === void 0 ? void 0 : b.similarity) !== null && _a !== void 0 ? _a : 0) - ((_b = a === null || a === void 0 ? void 0 : a.similarity) !== null && _b !== void 0 ? _b : 0); }); const result = results[0]; if (!result || !result.command) return null; return result.command.prefix + result.command.command; }; ctx.getCommandEntities = (commands) => { if (!ctx.has(":text")) { throw new Error("cannot call `ctx.commandEntities` on an update with no `text`"); } const text = ctx.msg.text; if (!text) return []; const prefixes = (0, array_js_1.ensureArray)(commands).flatMap((cmds) => cmds.prefixes); if (!prefixes.length) return []; const regexes = prefixes.map((prefix) => (0, array_js_1.getCommandsRegex)(prefix)); const entities = regexes.flatMap((regex) => { let match; const matches = []; while ((match = regex.exec(text)) !== null) { const text = match[0].trim(); matches.push({ text, offset: match.index, prefix: match.groups.prefix, type: "bot_command", length: text.length, }); } return matches; }); return entities; }; return next(); }; } /** * Static class for getting and manipulating {@link SetMyCommandsParams}. * The main function is {@link from} */ class MyCommandParams { /** * Merges and serialize one or more Commands instances into a single array * of commands params that can be used to set the commands menu displayed to the user. * @example ```ts const adminCommands = new CommandGroup(); const userCommands = new CommandGroup(); adminCommands .command("do a", "a description", (ctx) => ctx.doA()); userCommands .command("do b", "b description", (ctx) => ctx.doB()); const mergedParams = MyCommandParams.from([a, b], someChatId); ``` * @param commands An array of one or more Commands instances. * @returns an array of {@link SetMyCommandsParams} grouped by language */ static from(commands, chat_id) { const serializedCommands = commands.map((cmds) => cmds.toArgs(chat_id)); const commandsParams = serializedCommands .map(({ scopes }) => scopes) .flat(); const uncompliantCommands = serializedCommands .map(({ uncompliantCommands }) => uncompliantCommands) .flat(); return { commandsParams: this.merge(commandsParams), uncompliantCommands, }; } /** * Iterates over an array of CommandsParams * merging their respective {@link SetMyCommandsParams.commands} * when they are from the same language and scope * * @param params a flattened array of commands params coming from one or more Commands instances * @returns an array containing all commands grouped by language */ static merge(params) { if (!params.length) return []; const map = new Map(); params.forEach((curr) => { if (!curr.scope) return; const key = `${curr.scope.type},${curr.language_code}`; const old = map.get(key); if (old) { curr.commands = curr.commands.concat(old.commands); } map.set(key, curr); }); return [...map.values()]; } } exports.MyCommandParams = MyCommandParams;