UNPKG

@gramio/keyboards

Version:

Framework-agnostic Telegram bot keyboard builder with many cool features!

1,256 lines (1,244 loc) 44.3 kB
'use strict'; const keyboardsFeatureFlagsMap = { enableSetterKeyboardHelpers: process.env.GRAMIO_KEYBOARDS_HELPERS_SETTER === "true" }; function chunk(array, size) { const flatArray = array.flat(); const chunks = []; for (let i = 0; i < flatArray.length; i += size) { chunks.push(flatArray.slice(i, i + size)); } return chunks; } function customWrap(array, fn) { const flatArray = array.flat(); const chunks = []; let currentChunk = []; for (const [index, button] of flatArray.entries()) { if (fn({ button, index, row: currentChunk, rowIndex: chunks.length })) { chunks.push(currentChunk); currentChunk = []; } currentChunk.push(button); } return currentChunk.length ? [...chunks, currentChunk] : chunks; } function pattern(array, pattern2) { return customWrap( array, ({ row, rowIndex }) => row.length === pattern2[rowIndex] ); } function filter(array, fn) { const chunks = []; for (const [rowIndex, row] of array.entries()) { const filtered = row.filter( (button, index) => fn({ button, index, row, rowIndex }) ); if (filtered.length) chunks.push(filtered); } return chunks; } class BaseKeyboardConstructor { rows = []; currentRow = []; featureFlags = keyboardsFeatureFlagsMap; constructor(featureFlags) { this.featureFlags = featureFlags ?? keyboardsFeatureFlagsMap; } wrapOptions = { columns: void 0, fn: void 0, filter: void 0, pattern: void 0 }; appliedHelper; // Can be combined with other helpers appliedFilter; get keyboard() { let keyboard = this.currentRow.length ? [...this.rows, this.currentRow] : this.rows; if (this.featureFlags.enableSetterKeyboardHelpers) return keyboard; if (this.wrapOptions.columns) keyboard = chunk(keyboard, this.wrapOptions.columns); if (this.wrapOptions.fn) keyboard = customWrap(keyboard, this.wrapOptions.fn); if (this.wrapOptions.pattern) keyboard = pattern(keyboard, this.wrapOptions.pattern); if (this.wrapOptions.filter) keyboard = filter(keyboard, this.wrapOptions.filter); return keyboard; } /** * Adds a `line break`. Call this method to make sure that the next added buttons will be on a new row. * @example * ```ts * new InlineKeyboard() * .text("first row", "payload") * .row() * .text("second row", "payload"); * ``` */ row() { if (!this.currentRow.length) return this; this.rows.push(this.currentRow); this.currentRow = []; return this; } /** * Allows you to limit the number of columns in the keyboard. * @example * ```ts * new InlineKeyboard() * .columns(1) * .text("first row", "payload") * .text("second row", "payload"); * .text("third row", "payload"); * ``` */ columns(length) { this.wrapOptions.columns = length; if (length) this.appliedHelper = { type: "columns", columns: length }; else this.appliedHelper = void 0; return this; } /** * A custom handler that controls row wrapping. * @example * ```ts * new InlineKeyboard() * .wrap(({ button }) => button.callback_data === "2") * .text("first row", "1") * .text("first row", "1"); * .text("second row", "2"); * ``` */ wrap(fn) { this.wrapOptions.fn = fn; if (fn) this.appliedHelper = { type: "wrap", fn }; else this.appliedHelper = void 0; return this; } /** * A handler that helps filter keyboard buttons * @example * ```ts * new InlineKeyboard() * .filter(({ button }) => button.callback_data !== "hidden") * .text("button", "pass") * .text("button", "hidden") * .text("button", "pass"); * ``` */ filter(fn) { this.wrapOptions.filter = fn; this.appliedFilter = fn; return this; } /** * An array with the number of columns per row. Allows you to set a "template" * @example * ```ts * new InlineKeyboard() * .pattern([1, 3, 2]) * .text("1", "payload") * .text("2", "payload") * .text("2", "payload") * .text("2", "payload") * .text("3", "payload") * .text("3", "payload"); * ``` */ pattern(pattern2) { this.wrapOptions.pattern = pattern2; if (pattern2) this.appliedHelper = { type: "pattern", pattern: pattern2 }; else this.appliedHelper = void 0; return this; } /** * Allows you to add multiple buttons in raw format. * @example * ```ts * const labels = ["some", "buttons"]; * * new InlineKeyboard() * .add({ text: "raw button", callback_data: "payload" }) * .add(InlineKeyboard.text("raw button by InlineKeyboard.text", "payload")) * .add(...labels.map((x) => InlineKeyboard.text(x, `${x}payload`))); * ``` */ // TODO: cleanup and refactor add(...buttons) { if (this.featureFlags.enableSetterKeyboardHelpers) { const applyFilter = this.appliedFilter ? (button) => this.appliedFilter?.({ button, index: this.currentRow.length - 1, row: this.currentRow, rowIndex: this.rows.length - 1 }) : void 0; if (this.appliedHelper?.type === "columns") { for (const button of buttons) { if (applyFilter && !applyFilter(button)) continue; this.currentRow.push(button); if (this.currentRow.length === this.appliedHelper.columns) { this.row(); } } } else if (this.appliedHelper?.type === "wrap") { for (const button of buttons) { if (applyFilter && !applyFilter(button)) continue; this.currentRow.push(button); if (this.appliedHelper.fn({ button, index: this.currentRow.length - 1, row: this.currentRow, rowIndex: this.rows.length - 1 })) { this.row(); } } } else if (this.appliedHelper?.type === "pattern") { for (const button of buttons) { if (applyFilter && !applyFilter(button)) continue; this.currentRow.push(button); if (this.appliedHelper && this.currentRow.length >= this.appliedHelper.pattern[0]) { this.row(); this.appliedHelper.pattern.shift(); if (this.appliedHelper.pattern.length === 0) this.appliedHelper = void 0; } } } else { if (this.appliedFilter) { for (const button of buttons) { if (applyFilter && !applyFilter(button)) continue; this.currentRow.push(button); } } else this.currentRow.push(...buttons); } } else this.currentRow.push(...buttons); return this; } /** * Allows you to dynamically substitute buttons depending on something * @example * ```ts * const labels = ["some", "buttons"]; * const isAdmin = true; * * new InlineKeyboard() * .addIf(1 === 2, { text: "raw button", callback_data: "payload" }) * .addIf( * isAdmin, * InlineKeyboard.text("raw button by InlineKeyboard.text", "payload") * ) * .addIf( * ({ index, rowIndex }) => rowIndex === index, * ...labels.map((x) => InlineKeyboard.text(x, `${x}payload`)) * ); * ``` */ addIf(condition, ...buttons) { const isShow = typeof condition === "boolean" ? condition : condition({ rowIndex: this.rows.length - 1, index: this.currentRow.length - 1 }); if (isShow) this.add(...buttons); return this; } /** * Allows you to create a button matrix. * @example * ```ts * import { randomInt } from "node:crypto"; * * const bomb = [randomInt(0, 9), randomInt(0, 9)] as const; * * new InlineKeyboard().matrix(10, 10, ({ rowIndex, index }) => * InlineKeyboard.text( * rowIndex === bomb[0] && index === bomb[1] ? "💣" : "ㅤ", * "payload" * ) *); * ``` */ matrix(rows, columns, fn) { if (rows < 1 || columns < 1) throw new Error("The number of rows and columns must be greater than 0"); this.row(); for (let rowIndex = 0; rowIndex < rows; rowIndex++) { this.add( ...[...new Array(columns)].map((_, index) => fn({ rowIndex, index })) ); this.row(); } return this; } resetHelpers() { this.appliedHelper = void 0; this.appliedFilter = void 0; return this; } } class Keyboard extends BaseKeyboardConstructor { options = { isOneTime: false, isPersistent: false, isResized: true, isSelective: false, placeholder: void 0 }; /** * Text of the button. It will be sent as a message when the button is pressed * @example * ```ts * new Keyboard().text("some button text"); * ``` */ text(text, options) { return this.add(Keyboard.text(text, options)); } /** * Text of the button. It will be sent as a message when the button is pressed */ static text(text, options) { return { text, ...options }; } /** * If specified, pressing the button will open a list of suitable users. Identifiers of selected users will be sent to the bot in a “users\_shared” service message. Available in private chats only. * @example * ```ts * new Keyboard().requestUsers("some button text", 228, { * user_is_premium: true, * }); * ``` */ requestUsers(text, requestId, options = {}, buttonOptions) { return this.add(Keyboard.requestUsers(text, requestId, options, buttonOptions)); } /** * If specified, pressing the button will open a list of suitable users. Identifiers of selected users will be sent to the bot in a “users\_shared” service message. Available in private chats only. */ static requestUsers(text, requestId, options = {}, buttonOptions) { return { text, request_users: { ...options, request_id: requestId }, ...buttonOptions }; } /** * If specified, pressing the button will open a list of suitable chats. Tapping on a chat will send its identifier to the bot in a “chat\_shared” service message. Available in private chats only. * @example * ```ts * new Keyboard().requestChat("gramio", 255, { * chat_is_forum: true, * }); * ``` */ requestChat(text, requestId, options, buttonOptions) { return this.add(Keyboard.requestChat(text, requestId, options, buttonOptions)); } /** * If specified, pressing the button will open a list of suitable chats. Tapping on a chat will send its identifier to the bot in a “chat\_shared” service message. Available in private chats only. */ static requestChat(text, requestId, options, buttonOptions) { return { text, request_chat: { // [INFO] Why not false by default? chat_is_channel: false, ...options, request_id: requestId }, ...buttonOptions }; } /** * If *True*, the user's phone number will be sent as a contact when the button is pressed. Available in private chats only. * @example * ```ts * new Keyboard().requestContact("some button text"); * ``` */ requestContact(text, options) { return this.add(Keyboard.requestContact(text, options)); } /** * If *True*, the user's phone number will be sent as a contact when the button is pressed. Available in private chats only. */ static requestContact(text, options) { return { text, request_contact: true, ...options }; } /** * If *True*, the user's current location will be sent when the button is pressed. Available in private chats only. * @example * ```ts * new Keyboard().requestLocation("some button text"); * ``` */ requestLocation(text, options) { return this.add(Keyboard.requestLocation(text, options)); } /** * If *True*, the user's current location will be sent when the button is pressed. Available in private chats only. */ static requestLocation(text, options) { return { text, request_location: true, ...options }; } /** * If specified, the user will be asked to create a poll and send it to the bot when the button is pressed. Available in private chats only. * * If *quiz* is passed, the user will be allowed to create only polls in the quiz mode. If *regular* is passed, only regular polls will be allowed. Otherwise, the user will be allowed to create a poll of any type. * @example * ```ts * new Keyboard().requestPoll("some button text", "quiz"); * ``` */ requestPoll(text, type, options) { return this.add(Keyboard.requestPoll(text, type, options)); } /** * If specified, the user will be asked to create a poll and send it to the bot when the button is pressed. Available in private chats only. * * If *quiz* is passed, the user will be allowed to create only polls in the quiz mode. If *regular* is passed, only regular polls will be allowed. Otherwise, the user will be allowed to create a poll of any type. */ static requestPoll(text, type, options) { return { text, request_poll: { type }, ...options }; } /** * If specified, the described [Web App](https://core.telegram.org/bots/webapps) will be launched when the button is pressed. The Web App will be able to send a “web\_app\_data” service message. Available in private chats only. * @example * ```ts * new Keyboard().webApp("some button text", "https://..."); * ``` */ webApp(text, url, options) { return this.add(Keyboard.webApp(text, url, options)); } /** * If specified, the described [Web App](https://core.telegram.org/bots/webapps) will be launched when the button is pressed. The Web App will be able to send a “web\_app\_data” service message. Available in private chats only. */ static webApp(text, url, options) { return { text, web_app: { url }, ...options }; } /** * Requests clients to hide the keyboard as soon as it's been used. The keyboard will still be available, but clients will automatically display the usual letter-keyboard in the chat - the user can press a special button in the input field to see the custom keyboard again. Defaults to *false*. * @example * ```ts * new Keyboard().text("some text").oneTime(); // to enable * new Keyboard().text("some text").oneTime(false); // to disable * ``` */ oneTime(isEnabled = true) { this.options.isOneTime = isEnabled; return this; } /** * Requests clients to always show the keyboard when the regular keyboard is hidden. Defaults to *false*, in which case the custom keyboard can be hidden and opened with a keyboard icon. * @example * ```ts * new Keyboard().text("some text").persistent(); // to enable * new Keyboard().text("some text").persistent(false); // to disable * ``` */ persistent(isEnabled = true) { this.options.isPersistent = isEnabled; return this; } /** * The placeholder to be shown in the input field when the keyboard is active; 1-64 characters * @example * ```ts * new Keyboard().text("some text").placeholder("some text"); // to enable * new Keyboard().text("some text").placeholder(); // to disable * ``` */ placeholder(value) { this.options.placeholder = value; return this; } /** * !**Note** Keyboard is resized by default! For disable it you can use `.resized(false)` * * Requests clients to resize the keyboard vertically for optimal fit (e.g., make the keyboard smaller if there are just two rows of buttons). Defaults to *false*, in which case the custom keyboard is always of the same height as the app's standard keyboard. * @example * ```ts * new Keyboard().text("some text").resized(); // to enable * new Keyboard().text("some text").resized(false); // to disable * ``` */ resized(isEnabled = true) { this.options.isResized = isEnabled; return this; } /** * Use this parameter if you want to show the keyboard to specific users only. Targets: 1) users that are \@mentioned in the *text* of the [Message](https://core.telegram.org/bots/api/#message) object; 2) if the bot's message is a reply to a message in the same chat and forum topic, sender of the original message. * * *Example:* A user requests to change the bot's language, bot replies to the request with a keyboard to select the new language. Other users in the group don't see the keyboard. * @example * ```ts * new Keyboard().text("some text").selective(); // to enable * new Keyboard().text("some text").selective(false); // to disable * ``` */ selective(isEnabled = true) { this.options.isSelective = isEnabled; return this; } /** * Allows you to combine keyboards. Only keyboards are combined. You need to call the `.row()` method to line-break after combine. * * @example * ```ts * new Keyboard() * .combine(new Keyboard().text("first")) * .row() * .combine(new Keyboard().text("second").row().text("third")) * ``` */ combine(keyboard) { const json = "toJSON" in keyboard ? keyboard.toJSON() : keyboard; const buttons = Array.isArray(json) ? json : json.keyboard; for (const row of buttons) { if (row.length) this.row().add(...row); } return this; } /** * Return {@link TelegramReplyKeyboardMarkup} as object */ build() { return this.toJSON(); } /** * Serializing a class into an {@link TelegramReplyKeyboardMarkup} object (used by JSON.stringify) */ toJSON() { return { keyboard: this.keyboard, one_time_keyboard: this.options.isOneTime, is_persistent: this.options.isPersistent, input_field_placeholder: this.options.placeholder, selective: this.options.isSelective, resize_keyboard: this.options.isResized }; } } class InlineKeyboard extends BaseKeyboardConstructor { /** * Text button with data to be sent in a [callback query](https://core.telegram.org/bots/api/#callbackquery) to the bot when button is pressed, 1-64 bytes * @example * ```ts * new InlineKeyboard().text("some text", "payload"); * // or * new InlineKeyboard().text("some text", { * json: "payload", * }); // it uses JSON.stringify * ``` */ text(text, payload, options) { return this.add(InlineKeyboard.text(text, payload, options)); } /** * Text button with data to be sent in a [callback query](https://core.telegram.org/bots/api/#callbackquery) to the bot when button is pressed, 1-64 bytes */ static text(text, payload, options) { return { text, callback_data: typeof payload === "object" ? JSON.stringify(payload) : payload, ...options }; } /** * HTTP or tg:// URL to be opened when the button is pressed. Links `tg://user?id=<user_id>` can be used to mention a user by their identifier without using a username, if this is allowed by their privacy settings. * @example * ```ts * new InlineKeyboard().url("GitHub", "https://github.com/gramiojs/gramio"); * ``` */ url(text, url, options) { return this.add(InlineKeyboard.url(text, url, options)); } /** * HTTP or tg:// URL to be opened when the button is pressed. Links `tg://user?id=<user_id>` can be used to mention a user by their identifier without using a username, if this is allowed by their privacy settings. */ static url(text, url, options) { return { text, url, ...options }; } /** * Description of the [Web App](https://core.telegram.org/bots/webapps) that will be launched when the user presses the button. The Web App will be able to send an arbitrary message on behalf of the user using the method [answerWebAppQuery](https://core.telegram.org/bots/api/#answerwebappquery). Available only in private chats between a user and the bot. * @example * ```ts * new InlineKeyboard().webApp("some text", "https://..."); * ``` */ webApp(text, url, options) { return this.add(InlineKeyboard.webApp(text, url, options)); } /** * Description of the [Web App](https://core.telegram.org/bots/webapps) that will be launched when the user presses the button. The Web App will be able to send an arbitrary message on behalf of the user using the method [answerWebAppQuery](https://core.telegram.org/bots/api/#answerwebappquery). Available only in private chats between a user and the bot. */ static webApp(text, url, options) { return { text, web_app: { url }, ...options }; } /** * An HTTPS URL used to automatically authorize the user. Can be used as a replacement for the [Telegram Login Widget](https://core.telegram.org/widgets/login). * @example * ```ts * new InlineKeyboard().login("some text", "https://..."); * // or * new InlineKeyboard().login("some text", { * url: "https://...", * request_write_access: true, *}); * ``` */ login(text, url, options) { return this.add(InlineKeyboard.login(text, url, options)); } /** * An HTTPS URL used to automatically authorize the user. Can be used as a replacement for the [Telegram Login Widget](https://core.telegram.org/widgets/login). */ static login(text, url, options) { return { text, login_url: typeof url === "string" ? { url } : url, ...options }; } /** * Send a [Pay button](https://core.telegram.org/bots/api/#payments). * * **NOTE:** This type of button **must** always be the first button in the first row and can only be used in invoice messages. * @example * ```ts * new InlineKeyboard().pay("5 coins"); * ``` */ pay(text, options) { if (this.rows.length || this.currentRow.length) throw new Error( "This type of button must always be the first button in the first row and can only be used in invoice messages." ); return this.add(InlineKeyboard.pay(text, options)); } /** * Send a [Pay button](https://core.telegram.org/bots/api/#payments). * * **NOTE:** This type of button **must** always be the first button in the first row and can only be used in invoice messages. */ static pay(text, options) { return { text, pay: true, ...options }; } /** * Pressing the button will prompt the user to select one of their chats, open that chat and insert the bot's username and the specified inline query in the input field. * * By default empty, in which case just the bot's username will be inserted. * @example * ```ts * new InlineKeyboard().switchToChat("Select chat"); * // or * new InlineKeyboard().switchToChat("Select chat", "InlineQuery"); * ``` */ switchToChat(text, query = "", options) { return this.add(InlineKeyboard.switchToChat(text, query, options)); } /** * If set, pressing the button will prompt the user to select one of their chats, open that chat and insert the bot's username and the specified inline query in the input field. * * By default empty, in which case just the bot's username will be inserted. */ static switchToChat(text, query = "", options) { return { text, switch_inline_query: query, ...options }; } /** * Pressing the button will prompt the user to select one of their chats of the specified type, open that chat and insert the bot's username and the specified inline query in the input field * @example * ```ts * new InlineKeyboard().switchToChosenChat("Select chat"); * // or * new InlineKeyboard().switchToChosenChat("Select chat", "InlineQuery"); * // or * new InlineKeyboard().switchToChosenChat("Select chat", { * query: "InlineQuery", * allow_channel_chats: true, * allow_group_chats: true, * allow_bot_chats: true, * allow_user_chats: true, * }); * ``` */ switchToChosenChat(text, query = "", options) { return this.add(InlineKeyboard.switchToChosenChat(text, query, options)); } /** * Pressing the button will prompt the user to select one of their chats of the specified type, open that chat and insert the bot's username and the specified inline query in the input field */ static switchToChosenChat(text, query = "", options) { return { text, switch_inline_query_chosen_chat: typeof query === "string" ? { query } : query, ...options }; } /** * Pressing the button will insert the bot's username and the specified inline query in the current chat's input field. May be empty, in which case only the bot's username will be inserted. * * This offers a quick way for the user to open your bot in inline mode in the same chat - good for selecting something from multiple options. * @example * ```ts * new InlineKeyboard().switchToChosenChat("Open Inline mod"); * // or * new InlineKeyboard().switchToChosenChat("Open Inline mod", "InlineQuery"); * ``` */ switchToCurrentChat(text, query = "", options) { return this.add(InlineKeyboard.switchToCurrentChat(text, query, options)); } /** * Pressing the button will insert the bot's username and the specified inline query in the current chat's input field. May be empty, in which case only the bot's username will be inserted. * * This offers a quick way for the user to open your bot in inline mode in the same chat - good for selecting something from multiple options. */ static switchToCurrentChat(text, query = "", options) { return { text, switch_inline_query_current_chat: query, ...options }; } /** * Description of the game that will be launched when the user presses the button. * * **NOTE:** This type of button **must** always be the first button in the first row. * @example * ```ts * new InlineKeyboard().game("text", ???); * ``` */ game(text, gameOptions = {}, options) { if (this.rows.length || this.currentRow.length) throw new Error( "This type of button must always be the first button in the first row." ); return this.add(InlineKeyboard.game(text, gameOptions, options)); } /** * Description of the game that will be launched when the user presses the button. * * **NOTE:** This type of button **must** always be the first button in the first row. */ static game(text, gameOptions = {}, options) { return { text, callback_game: gameOptions, ...options }; } copy(text, textToCopy, options) { return this.add(InlineKeyboard.copy(text, textToCopy, options)); } static copy(text, textToCopy, options) { return { text, copy_text: typeof textToCopy === "string" ? { text: textToCopy } : textToCopy, ...options }; } /** * Allows you to combine keyboards. Only keyboards are combined. You need to call the `.row()` method to line-break after combine. * * @example * ```ts * new InlineKeyboard() * .combine(new InlineKeyboard().text("some", "payload")) * .row() * .combine( * new InlineKeyboard() * .text("test", "payload") * .row() * .text("second row???", "payload"), * ) * ``` */ combine(keyboard) { const json = "toJSON" in keyboard ? keyboard.toJSON() : keyboard; const buttons = Array.isArray(json) ? json : json.inline_keyboard; for (const row of buttons) { this.row().add(...row); } return this; } /** * Return {@link TelegramInlineKeyboardMarkup} as JSON */ build() { return this.toJSON(); } /** * Serializing a class into an {@link TelegramInlineKeyboardMarkupFix} object (used by JSON.stringify) */ toJSON() { return { inline_keyboard: this.keyboard }; } } class RemoveKeyboard { options = { isSelective: false }; /** * Use this parameter if you want to remove the keyboard for specific users only. Targets: 1) users that are \@mentioned in the *text* of the [Message](https://core.telegram.org/bots/api/#message) object; 2) if the bot's message is a reply to a message in the same chat and forum topic, sender of the original message. * * *Example:* A user votes in a poll, bot returns confirmation message in reply to the vote and removes the keyboard for that user, while still showing the keyboard with poll options to users who haven't voted yet. * @example * ```ts * new RemoveKeyboard().selective(); // to enable * new RemoveKeyboard().selective(false); // to disable * ``` */ selective(isEnabled = true) { this.options.isSelective = isEnabled; return this; } /** * Return {@link TelegramReplyKeyboardRemove} as object */ build() { return this.toJSON(); } /** * Serializing a class into an {@link TelegramReplyKeyboardRemove} object (used by JSON.stringify) */ toJSON() { return { remove_keyboard: true, selective: this.options.isSelective }; } } class ForceReplyKeyboard { options = { isSelective: false, placeholder: void 0 }; /** * Use this parameter if you want to force reply from specific users only. Targets: 1) users that are \@mentioned in the *text* of the [Message](https://core.telegram.org/bots/api/#message) object; 2) if the bot's message is a reply to a message in the same chat and forum topic, sender of the original message. * @example * ```ts * new ForceReplyKeyboard().selective(); // to enable * new ForceReplyKeyboard().selective(false); // to disable * ``` */ selective(isEnabled = true) { this.options.isSelective = isEnabled; return this; } /** * The placeholder to be shown in the input field when the reply is active; 1-64 characters * @example * ```ts * new Keyboard().placeholder("some text"); // to enable * new Keyboard().placeholder(); // to disable * ``` */ placeholder(value) { this.options.placeholder = value; return this; } /** * Return {@link TelegramForceReply} as JSON */ build() { return this.toJSON(); } /** * Serializing a class into an {@link TelegramForceReply} object (used by JSON.stringify) */ toJSON() { return { force_reply: true, selective: this.options.isSelective, input_field_placeholder: this.options.placeholder }; } } class InputMessageContent { /** * Represents the [content](https://core.telegram.org/bots/api/#inputmessagecontent) of a text message to be sent as the result of an inline query. * * [Documentation](https://core.telegram.org/bots/api/#inputtextmessagecontent) */ static text(text, options) { return { message_text: text, ...options }; } /** * Represents the [content](https://core.telegram.org/bots/api/#inputmessagecontent) of a location message to be sent as the result of an inline query. * * [Documentation](https://core.telegram.org/bots/api/#inputlocationmessagecontent) */ static location(latitude, longitude, options) { return { latitude, longitude, ...options }; } /** * Represents the [content](https://core.telegram.org/bots/api/#inputmessagecontent) of a venue message to be sent as the result of an inline query. * * [Documentation](https://core.telegram.org/bots/api/#inputvenuemessagecontent) */ static venue(options) { return options; } /** * Represents the [content](https://core.telegram.org/bots/api/#inputmessagecontent) of a contact message to be sent as the result of an inline query. * * [Documentation](https://core.telegram.org/bots/api/#inputcontactmessagecontent) */ static contact(phoneNumber, firstName, options) { return { phone_number: phoneNumber, first_name: firstName, ...options }; } /** * Represents the [content](https://core.telegram.org/bots/api/#inputmessagecontent) of an invoice message to be sent as the result of an inline query. * * [Documentation](https://core.telegram.org/bots/api/#inputinvoicemessagecontent) */ static invoice(options) { return options; } } class InlineQueryResultCached { /** * Represents a link to an MP3 audio file stored on the Telegram servers. By default, this audio file will be sent by the user. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the audio. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultcachedaudio) */ static audio(id, fileId, options) { return { type: "audio", id, audio_file_id: fileId, ...options }; } /** * Represents a link to a file stored on the Telegram servers. By default, this file will be sent by the user with an optional caption. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the file. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultcacheddocument) */ static document(id, title, fileId, options) { return { type: "document", id, title, document_file_id: fileId, ...options }; } /** * Represents a link to an animated GIF file stored on the Telegram servers. By default, this animated GIF file will be sent by the user with an optional caption. Alternatively, you can use *input\_message\_content* to send a message with specified content instead of the animation. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultcachedgif) */ static gif(id, fileId, options) { return { type: "gif", id, gif_file_id: fileId, ...options }; } /** * Represents a link to a video animation (H.264/MPEG-4 AVC video without sound) stored on the Telegram servers. By default, this animated MPEG-4 file will be sent by the user with an optional caption. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the animation. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultcachedmpeg4gif) */ static mpeg4Gif(id, fileId, options) { return { type: "mpeg4_gif", id, mpeg4_file_id: fileId, ...options }; } /** * Represents a link to a photo stored on the Telegram servers. By default, this photo will be sent by the user with an optional caption. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the photo. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultcachedphoto) */ static photo(id, fileId, options) { return { type: "photo", id, photo_file_id: fileId, ...options }; } /** * Represents a link to a sticker stored on the Telegram servers. By default, this sticker will be sent by the user. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the sticker. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultcachedsticker) */ static sticker(id, fileId, options) { return { type: "sticker", id, sticker_file_id: fileId, ...options }; } /** * Represents a link to a video file stored on the Telegram servers. By default, this video file will be sent by the user with an optional caption. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the video. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultcachedvideo) */ static video(id, title, fileId, options) { return { type: "video", id, title, video_file_id: fileId, ...options }; } /** * Represents a link to a voice message stored on the Telegram servers. By default, this voice message will be sent by the user. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the voice message. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultcachedvoice) */ static voice(id, title, fileId, options) { return { type: "voice", id, title, voice_file_id: fileId, ...options }; } } class InlineQueryResult { /** Cached result of InlineQuery builder. */ static cached = InlineQueryResultCached; /** * Represents a link to an article or web page. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultarticle) */ static article(id, title, inputMessageContent, options) { return { type: "article", id, title, input_message_content: inputMessageContent, ...options }; } /** * Represents a link to an MP3 audio file. By default, this audio file will be sent by the user. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the audio. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultaudio) */ static audio(id, title, audioUrl, options) { return { type: "audio", id, title, audio_url: audioUrl, ...options }; } /** * Represents a contact with a phone number. By default, this contact will be sent by the user. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the contact. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultcontact) */ static contact(id, phoneNumber, firstName, options) { return { type: "contact", id, first_name: firstName, phone_number: phoneNumber, ...options }; } /** * Represents a [Game](https://core.telegram.org/bots/api/#games). * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultgame) */ static game(id, gameShortName, options) { return { type: "game", id, game_short_name: gameShortName, ...options }; } /** * Represents a link to a file. By default, this file will be sent by the user with an optional caption. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the file. Currently, only **.PDF** and **.ZIP** files can be sent using this method. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultdocument) */ static documentPdf(id, title, url, options) { return { type: "document", id, title, document_url: url, mime_type: "application/pdf", ...options }; } /** * Represents a link to a file. By default, this file will be sent by the user with an optional caption. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the file. Currently, only **.PDF** and **.ZIP** files can be sent using this method. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultdocument) */ static documentZip(id, title, url, options) { return { type: "document", id, title, document_url: url, mime_type: "application/zip", ...options }; } /** * Represents a link to an animated GIF file. By default, this animated GIF file will be sent by the user with optional caption. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the animation. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultgif) */ static gif(id, gifUrl, thumbnailUrl, options) { return { type: "gif", id, gif_url: gifUrl, thumbnail_url: thumbnailUrl, ...options }; } /** * Represents a location on a map. By default, the location will be sent by the user. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the location. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultlocation) */ static location(id, latitude, longitude, title, options) { return { type: "location", id, latitude, longitude, title, ...options }; } /** * Represents a link to a video animation (H.264/MPEG-4 AVC video without sound). By default, this animated MPEG-4 file will be sent by the user with optional caption. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the animation. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultmpeg4gif) */ static mpeg4Gif(id, mpeg4Url, thumbnailUrl, options) { return { type: "mpeg4_gif", id, mpeg4_url: mpeg4Url, thumbnail_url: thumbnailUrl, ...options }; } /** * Represents a link to a photo. By default, this photo will be sent by the user with optional caption. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the photo. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultphoto) */ static photo(id, photoUrl, thumbnailUrl, options) { return { type: "photo", id, photo_url: photoUrl, thumbnail_url: thumbnailUrl, ...options }; } /** * Represents a venue. By default, the venue will be sent by the user. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the venue. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultvenue) */ static venue(id, options) { return { type: "venue", id, ...options }; } /** * Represents a link to a page containing an embedded video player or a video file. By default, this video file will be sent by the user with an optional caption. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the video. * * If an InlineQueryResultVideo message contains an embedded video (e.g., YouTube), you **must** replace its content using *input\_message\_content*. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultvideo) */ static videoHtml(id, title, videoUrl, thumbnailUrl, options) { return { type: "video", id, title, video_url: videoUrl, thumbnail_url: thumbnailUrl, mime_type: "text/html", ...options }; } /** * Represents a link to a page containing an embedded video player or a video file. By default, this video file will be sent by the user with an optional caption. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the video. * * If an InlineQueryResultVideo message contains an embedded video (e.g., YouTube), you **must** replace its content using *input\_message\_content*. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultvideo) */ static videoMp4(id, title, videoUrl, thumbnailUrl, options) { return { type: "video", id, title, video_url: videoUrl, thumbnail_url: thumbnailUrl, mime_type: "video/mp4", ...options }; } /** * Represents a link to a voice recording in an .OGG container encoded with OPUS. By default, this voice recording will be sent by the user. Alternatively, you can use *input\_message\_content* to send a message with the specified content instead of the the voice message. * * [Documentation](https://core.telegram.org/bots/api/#inlinequeryresultvoice) */ static voice(id, title, url, options) { return { type: "voice", id, title, voice_url: url, ...options }; } } Symbol.metadata ??= Symbol("Symbol.metadata"); exports.BaseKeyboardConstructor = BaseKeyboardConstructor; exports.ForceReplyKeyboard = ForceReplyKeyboard; exports.InlineKeyboard = InlineKeyboard; exports.InlineQueryResult = InlineQueryResult; exports.InputMessageContent = InputMessageContent; exports.Keyboard = Keyboard; exports.RemoveKeyboard = RemoveKeyboard; exports.chunk = chunk; exports.customWrap = customWrap; exports.filter = filter; exports.keyboardsFeatureFlagsMap = keyboardsFeatureFlagsMap; exports.pattern = pattern;