diff --git a/src/client/BaseClient.ts b/src/client/BaseClient.ts index 17748c2..d957a45 100644 --- a/src/client/BaseClient.ts +++ b/src/client/BaseClient.ts @@ -27,6 +27,7 @@ import { ChatInviteLink, Gifts, PreparedInlineMessage, + PreparedKeyboardButton, StarAmount, OwnedGifts, Story, @@ -153,6 +154,9 @@ interface EventHandlers { purchasedPaidMedia: ( paidMedia: import("../structures/PaidMediaPurchased").PaidMediaPurchased, ) => PossiblyAsync; + managedBot: ( + managedBot: import("../structures/ManagedBotUpdated").ManagedBotUpdated, + ) => PossiblyAsync; } type EventHandlerParameters = @@ -173,7 +177,8 @@ type EventHandlerParameters = | import("../structures/ChatJoinRequest").ChatJoinRequest | import("../structures/ChatBoostUpdated").ChatBoostUpdated | import("../structures/ChatBoostRemoved").ChatBoostRemoved - | import("../structures/PaidMediaPurchased").PaidMediaPurchased; + | import("../structures/PaidMediaPurchased").PaidMediaPurchased + | import("../structures/ManagedBotUpdated").ManagedBotUpdated; class BaseClient extends EventEmitter { public readonly rest: Rest; @@ -1978,6 +1983,36 @@ class BaseClient extends EventEmitter { .then((res) => new PreparedInlineMessage(res)); } + + /** Use this method to get the current token of a managed bot. Returns the token on success. */ + async getManagedBotToken( + params: MethodParameters["getManagedBotToken"], + ): Promise { + return this.rest.request( + "getManagedBotToken", + toSnakeCase(params), + ); + } + + /** Use this method to replace the token of a managed bot. Returns the new token on success. */ + async replaceManagedBotToken( + params: MethodParameters["replaceManagedBotToken"], + ): Promise { + return this.rest.request( + "replaceManagedBotToken", + toSnakeCase(params), + ); + } + + /** Stores a keyboard button that can be sent by a user of a Mini App. Returns a PreparedKeyboardButton object. */ + async savePreparedKeyboardButton( + params: MethodParameters["savePreparedKeyboardButton"], + ): Promise { + return this.rest + .request("savePreparedKeyboardButton", toSnakeCase(params)) + .then((res) => new PreparedKeyboardButton(this, res)); + } + /** Use this method to send invoices. On success, the sent Message is returned. */ async sendInvoice( params: MethodParameters["sendInvoice"], diff --git a/src/client/WorkerClient.ts b/src/client/WorkerClient.ts index 8d573f9..d21c576 100644 --- a/src/client/WorkerClient.ts +++ b/src/client/WorkerClient.ts @@ -17,6 +17,7 @@ import { CallbackQuery } from "../structures/CallbackQuery"; import { BusinessConnection } from "../structures/business/BusinessConnection"; import { BusinessMessagesDeleted } from "../structures/business/BusinessMessagesDeleted"; import { PaidMediaPurchased } from "../structures/PaidMediaPurchased"; +import { ManagedBotUpdated } from "../structures/ManagedBotUpdated"; import type { TelegramClient } from "./TelegramClient"; /** @@ -53,6 +54,7 @@ class WorkerClient { | ChatBoostUpdated | ChatBoostRemoved | PaidMediaPurchased + | ManagedBotUpdated | undefined { this.client.emit( Events.RawUpdate, @@ -136,6 +138,9 @@ class WorkerClient { if ("purchased_paid_media" in data) { return this.onPurchasedPaidMedia(data.purchased_paid_media); } + if ("managed_bot" in (data as unknown as Record)) { + return this.onManagedBot((data as any).managed_bot); + } return; } @@ -458,6 +463,15 @@ class WorkerClient { return paidMedia; } + + onManagedBot(data: any): ManagedBotUpdated | undefined { + if (!data) return; + + const managedBot = new ManagedBotUpdated(this.client, data); + this.client.emit(Events.ManagedBot, managedBot); + + return managedBot; + } } export { WorkerClient }; diff --git a/src/client/interfaces/Markup.ts b/src/client/interfaces/Markup.ts index 55c1cf5..1557343 100644 --- a/src/client/interfaces/Markup.ts +++ b/src/client/interfaces/Markup.ts @@ -174,6 +174,10 @@ export declare namespace KeyboardButton { /** 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. */ request_poll: KeyboardButtonPollType; } + export interface RequestManagedBotButton extends CommonButton { + /** If specified, pressing the button will allow the user to select a manager bot and create a managed bot in a service message. Available in private chats only. */ + request_managed_bot: KeyboardButtonRequestManagedBot; + } export interface WebAppButton extends CommonButton { /** If specified, the described Web App 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. */ web_app: WebAppInfo; @@ -188,6 +192,7 @@ export type KeyboardButton = | KeyboardButton.RequestContactButton | KeyboardButton.RequestLocationButton | KeyboardButton.RequestPollButton + | KeyboardButton.RequestManagedBotButton | KeyboardButton.WebAppButton | string; @@ -197,6 +202,19 @@ export interface KeyboardButtonPollType { type?: "quiz" | "regular"; } + +/** This object defines the criteria used to request a managed bot. Information about the selected manager bot and created managed bot will be shared with the bot when the corresponding button is pressed. */ +export interface KeyboardButtonRequestManagedBot { + /** Signed 32-bit identifier of the request, which will be received back in the ManagedBotCreated object. Must be unique within the message */ + request_id: number; + /** The username of the manager bot that can be used to create the managed bot. */ + manager_bot_username?: string; + /** Suggested username for the managed bot. */ + bot_username?: string; + /** Suggested name for the managed bot. */ + bot_name?: string; +} + /** Upon receiving a message with this object, Telegram clients will remove the current custom keyboard and display the default letter-keyboard. By default, custom keyboards are displayed until a new keyboard is sent by a bot. An exception is made for one-time keyboards that are hidden immediately after the user presses a button (see ReplyKeyboardMarkup). Not supported in channels and for messages sent on behalf of a Telegram Business account. */ export interface ReplyKeyboardRemove { /** Requests clients to remove the custom keyboard (user will not be able to summon this keyboard; if you want to hide the keyboard from sight but keep it accessible, use one_time_keyboard in ReplyKeyboardMarkup) */ diff --git a/src/client/interfaces/Message.ts b/src/client/interfaces/Message.ts index e3ee25c..647aaa9 100644 --- a/src/client/interfaces/Message.ts +++ b/src/client/interfaces/Message.ts @@ -13,11 +13,13 @@ export interface User { /** User's or bot's username */ username?: string; /** IETF language tag of the user's language */ - language_code?: LanguageCode; + language_code?: LanguageCode | string; /** True, if this user is a Telegram Premium user */ is_premium?: true; /** True, if this user added the bot to the attachment menu */ added_to_attachment_menu?: true; + /** True, if the bot can be invited to create managed bots */ + can_manage_bots?: true; } /** Describes the options used for link preview generation. */ @@ -121,6 +123,8 @@ export interface ReplyParameters { chat_id?: number | string; /** Identifier of the specific checklist task to be replied to */ checklist_task_id?: number; + /** Identifier of the poll option to be replied to */ + poll_option_id?: number; /** Pass True if the message should be sent even if the specified message to be replied to is not found; can be used only for replies in the same chat and forum topic. Always True for messages sent on behalf of a business account. */ allow_sending_without_reply?: boolean; /** Quoted part of the message to be replied to; 0-1024 characters after entities parsing. The quote must be an exact substring of the message to be replied to, including bold, italic, underline, strikethrough, spoiler, and custom_emoji entities. The message will fail to send if the quote isn't found in the original message. */ diff --git a/src/client/interfaces/Methods.ts b/src/client/interfaces/Methods.ts index e304e4e..bb219aa 100644 --- a/src/client/interfaces/Methods.ts +++ b/src/client/interfaces/Methods.ts @@ -952,19 +952,33 @@ export type ApiMethods = { isAnonymous?: boolean; /** Poll type, “quiz” or “regular”, defaults to “regular” */ type?: "quiz" | "regular"; - /** True, if the poll allows multiple answers, ignored for polls in quiz mode, defaults to False */ + /** True, if the poll allows multiple answers, defaults to False */ allowsMultipleAnswers?: boolean; - /** 0-based identifier of the correct answer option, required for polls in quiz mode */ - correctOptionId?: number; + /** 0-based identifiers of the correct answer options, required for polls in quiz mode */ + correctOptionIds?: number[]; + /** True, if users can change their answers after voting */ + allowsRevoting?: boolean; + /** True, if poll options should be shuffled */ + shuffleOptions?: boolean; + /** True, if users are allowed to add options */ + allowAddingOptions?: boolean; + /** True, if results should be hidden until the poll is closed */ + hideResultsUntilCloses?: boolean; /** Text that is shown when a user chooses an incorrect answer or taps on the lamp icon in a quiz-style poll, 0-200 characters with at most 2 line feeds after entities parsing */ explanation?: string; /** Mode for parsing entities in the explanation. See formatting options for more details. */ explanationParseMode?: ParseMode; /** A list of special entities that appear in the poll explanation. It can be specified instead of explanationParseMode */ explanationEntities?: MessageEntity[]; - /** Amount of time in seconds the poll will be active after creation, 5-600. Can't be used together with closeDate. */ + /** Poll description, 0-200 characters */ + description?: string; + /** Mode for parsing entities in the poll description */ + descriptionParseMode?: ParseMode; + /** List of special entities that appear in the poll description */ + descriptionEntities?: MessageEntity[]; + /** Amount of time in seconds the poll will be active after creation, 5-2628000. Can't be used together with closeDate. */ openPeriod?: number; - /** Point in time (Unix timestamp) when the poll will be automatically closed. Must be at least 5 and no more than 600 seconds in the future. Can't be used together with openPeriod. */ + /** Point in time (Unix timestamp) when the poll will be automatically closed. Must be at least 5 and no more than 2628000 seconds in the future. Can't be used together with openPeriod. */ closeDate?: number; /** Pass True if the poll needs to be immediately closed. This can be useful for poll preview. */ isClosed?: boolean; @@ -2298,6 +2312,35 @@ export type ApiMethods = { allowChannelChats?: boolean; }): import("../../structures/misc/PreparedInlineMessage").PreparedInlineMessage; + + /** Use this method to get the current token of a managed bot. */ + getManagedBotToken(args: { + /** Identifier of the managed bot */ + botId: number | string; + }): string; + + /** Use this method to replace the token of a managed bot. */ + replaceManagedBotToken(args: { + /** Identifier of the managed bot */ + botId: number | string; + }): string; + + /** Stores a keyboard button that can be sent by a user of a Mini App. */ + savePreparedKeyboardButton(args: { + /** Unique identifier of the target user that can use the prepared button */ + userId: string | number; + /** The keyboard button to prepare */ + button: import("./Markup").KeyboardButton; + /** Pass True if the button can be sent to private chats with users */ + allowUserChats?: boolean; + /** Pass True if the button can be sent to private chats with bots */ + allowBotChats?: boolean; + /** Pass True if the button can be sent to group and supergroup chats */ + allowGroupChats?: boolean; + /** Pass True if the button can be sent to channel chats */ + allowChannelChats?: boolean; + }): import("../../structures/misc/PreparedKeyboardButton").PreparedKeyboardButton; + /** Use this method to send invoices. On success, the sent Message is returned. */ sendInvoice(args: { /** Unique identifier for the target chat or username of the target channel (in the format @channelusername) */ diff --git a/src/structures/ManagedBotCreated.js b/src/structures/ManagedBotCreated.js new file mode 100644 index 0000000..03520db --- /dev/null +++ b/src/structures/ManagedBotCreated.js @@ -0,0 +1,18 @@ +// @ts-check +const { Base } = require("./Base"); + +class ManagedBotCreated extends Base { + /** + * @param {import("../client/TelegramClient").TelegramClient | import("../client/BaseClient").BaseClient} client + * @param {any} data + */ + constructor(client, data) { + super(client); + + this.requestId = data.request_id; + this.manager = this.client.users._add(data.manager_bot); + this.bot = this.client.users._add(data.bot); + } +} + +module.exports = { ManagedBotCreated }; diff --git a/src/structures/ManagedBotUpdated.js b/src/structures/ManagedBotUpdated.js new file mode 100644 index 0000000..7dad113 --- /dev/null +++ b/src/structures/ManagedBotUpdated.js @@ -0,0 +1,18 @@ +// @ts-check +const { Base } = require("./Base"); + +class ManagedBotUpdated extends Base { + /** + * @param {import("../client/TelegramClient").TelegramClient | import("../client/BaseClient").BaseClient} client + * @param {any} data + */ + constructor(client, data) { + super(client); + + if ("bot" in data) this.bot = this.client.users._add(data.bot); + if ("manager_bot" in data) this.manager = this.client.users._add(data.manager_bot); + if ("token" in data) this.token = data.token; + } +} + +module.exports = { ManagedBotUpdated }; diff --git a/src/structures/PollAnswer.js b/src/structures/PollAnswer.js index cc6249f..e64ac86 100644 --- a/src/structures/PollAnswer.js +++ b/src/structures/PollAnswer.js @@ -30,6 +30,9 @@ class PollAnswer extends Base { /** 0-based identifiers of chosen answer options. May be empty if the vote was retracted */ this.ids = data.option_ids; + + /** Persistent identifiers of chosen answer options. May be empty if the vote was retracted */ + this.persistentIds = (/** @type {any} */ (data)).option_persistent_ids || []; } } diff --git a/src/structures/PollOptionAdded.js b/src/structures/PollOptionAdded.js new file mode 100644 index 0000000..98970e5 --- /dev/null +++ b/src/structures/PollOptionAdded.js @@ -0,0 +1,16 @@ +// @ts-check +const { Base } = require("./Base"); + +class PollOptionAdded extends Base { + /** + * @param {import("../client/TelegramClient").TelegramClient | import("../client/BaseClient").BaseClient} client + * @param {any} data + */ + constructor(client, data) { + super(client); + this.pollId = data.poll_id; + this.optionId = data.option_id; + } +} + +module.exports = { PollOptionAdded }; diff --git a/src/structures/PollOptionDeleted.js b/src/structures/PollOptionDeleted.js new file mode 100644 index 0000000..4acdcc5 --- /dev/null +++ b/src/structures/PollOptionDeleted.js @@ -0,0 +1,16 @@ +// @ts-check +const { Base } = require("./Base"); + +class PollOptionDeleted extends Base { + /** + * @param {import("../client/TelegramClient").TelegramClient | import("../client/BaseClient").BaseClient} client + * @param {any} data + */ + constructor(client, data) { + super(client); + this.pollId = data.poll_id; + this.optionId = data.option_id; + } +} + +module.exports = { PollOptionDeleted }; diff --git a/src/structures/index.js b/src/structures/index.js index d6b4349..1b41b68 100644 --- a/src/structures/index.js +++ b/src/structures/index.js @@ -146,3 +146,9 @@ module.exports.Story = require("./story/Story").Story; module.exports.PaidMedia = require("./media/paid/PaidMedia").PaidMedia; module.exports.PaidMediaInfo = require("./media/paid/PaidMediaInfo").PaidMediaInfo; +module.exports.ManagedBotCreated = require("./ManagedBotCreated").ManagedBotCreated; +module.exports.ManagedBotUpdated = require("./ManagedBotUpdated").ManagedBotUpdated; +module.exports.PollOptionAdded = require("./PollOptionAdded").PollOptionAdded; +module.exports.PollOptionDeleted = require("./PollOptionDeleted").PollOptionDeleted; +module.exports.PreparedKeyboardButton = + require("./misc/PreparedKeyboardButton").PreparedKeyboardButton; diff --git a/src/structures/media/Poll.js b/src/structures/media/Poll.js index 16c7b0d..a9ffca8 100644 --- a/src/structures/media/Poll.js +++ b/src/structures/media/Poll.js @@ -57,6 +57,10 @@ class Poll extends Base { * @property {string} text - Option text, 1-100 characters * @property {MessageEntities} entities - Special entities that appear in the option text. Currently, only custom emoji entities are allowed in poll option texts * @property {number} voterCount - Number of users that voted for this option + * @property {string} [persistentId] - Persistent identifier for the option + * @property {import("../misc/User").User} [addedByUser] - User who added the option + * @property {import("../chat/Chat").Chat} [addedByChat] - Chat which added the option + * @property {number} [additionDate] - Date when the option was added */ /** @type {PollOptions[]} */ @@ -64,18 +68,23 @@ class Poll extends Base { if (Array.isArray(data.options)) { for (const opts of data.options) { + const optionData = /** @type {any} */ (opts); /** @type {PollOptions} */ const result = {}; - result.text = opts.text; - if ("text_entities" in opts) { + result.text = optionData.text; + if ("text_entities" in optionData) { result.entities = new MessageEntities( this.client, - opts.text, - opts.text_entities, + optionData.text, + optionData.text_entities, ); } - result.voterCount = opts.voter_count; + result.voterCount = optionData.voter_count; + if ("persistent_id" in optionData) result.persistentId = optionData.persistent_id; + if ("added_by_user" in optionData) result.addedByUser = this.client.users._add(optionData.added_by_user); + if ("added_by_chat" in optionData) result.addedByChat = this.client.chats._add(optionData.added_by_chat); + if ("addition_date" in optionData) result.additionDate = optionData.addition_date; options.push(result); } } @@ -87,12 +96,12 @@ class Poll extends Base { this.options = options; } - if ("correct_option_id" in data) { + if ("correct_option_ids" in data) { /** - * 0-based identifier of the correct answer option. Available only for polls in the quiz mode, which are closed, or was sent (not forwarded) by the bot or to the private chat with the bot - * @type {number | undefined} + * 0-based identifiers of the correct answer options. Available only for polls in the quiz mode + * @type {number[] | undefined} */ - this.correctId = data.correct_option_id; + this.correctIds = /** @type {number[]} */ ((/** @type {any} */ (data)).correct_option_ids); } if ("explanation" in data) { @@ -115,6 +124,30 @@ class Poll extends Base { } } + if ("allows_revoting" in data) { + /** + * True, if users can change their answers after voting + * @type {boolean | undefined} + */ + this.allowsRevoting = /** @type {boolean} */ ((/** @type {any} */ (data)).allows_revoting); + } + + if ("description" in data) { + /** + * Poll description + * @type {string | undefined} + */ + this.description = /** @type {string} */ ((/** @type {any} */ (data)).description); + + if ("description_entities" in data) { + this.descriptionEntities = new MessageEntities( + this.client, + /** @type {any} */ (data).description, + /** @type {any} */ (data).description_entities, + ); + } + } + if ("open_period" in data) { /** * Amount of time in seconds the poll will be active after creation diff --git a/src/structures/message/Message.js b/src/structures/message/Message.js index cf760bd..092da42 100644 --- a/src/structures/message/Message.js +++ b/src/structures/message/Message.js @@ -50,6 +50,9 @@ const { const { ReactionType } = require("../misc/ReactionType"); const { GiftInfo } = require("../gift/GiftInfo"); const { UniqueGiftInfo } = require("../gift/UniqueGiftInfo"); +const { ManagedBotCreated } = require("../ManagedBotCreated"); +const { PollOptionAdded } = require("../PollOptionAdded"); +const { PollOptionDeleted } = require("../PollOptionDeleted"); const { TelegramError } = require("../../errors/TelegramError"); const { ErrorCodes } = require("../../errors/ErrorCodes"); const { Collection } = require("@telegram.ts/collection"); @@ -253,6 +256,14 @@ class Message extends Base { this.checklistTaskId = data.reply_to_checklist_task_id; } + if ("reply_to_poll_option_id" in data) { + /** + * Identifier of the specific poll option that is being replied to + * @type {number | undefined} + */ + this.pollOptionId = /** @type {number} */ ((/** @type {any} */ (data)).reply_to_poll_option_id); + } + if ("is_paid_post" in data) { /** * True, if the message is a paid post. Note that such posts must not be deleted for 24 hours to receive the payment and can't be edited. @@ -509,6 +520,30 @@ class Message extends Base { this.chatShared = new ChatShared(this.client, data.chat_shared); } + if ("managed_bot_created" in data) { + /** + * Service message: a managed bot was created + * @type {ManagedBotCreated | undefined} + */ + this.managedBotCreated = new ManagedBotCreated(this.client, data.managed_bot_created); + } + + if ("poll_option_added" in data) { + /** + * Service message: a poll option was added + * @type {PollOptionAdded | undefined} + */ + this.pollOptionAdded = new PollOptionAdded(this.client, data.poll_option_added); + } + + if ("poll_option_deleted" in data) { + /** + * Service message: a poll option was deleted + * @type {PollOptionDeleted | undefined} + */ + this.pollOptionDeleted = new PollOptionDeleted(this.client, data.poll_option_deleted); + } + if ("connected_website" in data) { /** * The domain name of the website on which the user has logged in. More about Telegram Login @@ -1202,6 +1237,7 @@ class Message extends Base { replyParameters: { message_id: this.id, ...(this.checklistTaskId && { checklistTaskId: this.checklistTaskId }), + ...(this.pollOptionId && { pollOptionId: this.pollOptionId }), }, ...options, }); diff --git a/src/structures/misc/PreparedKeyboardButton.js b/src/structures/misc/PreparedKeyboardButton.js new file mode 100644 index 0000000..b20e076 --- /dev/null +++ b/src/structures/misc/PreparedKeyboardButton.js @@ -0,0 +1,28 @@ +// @ts-check +const { Base } = require("../Base"); + +class PreparedKeyboardButton extends Base { + /** + * @param {import("../../client/TelegramClient").TelegramClient | import("../../client/BaseClient").BaseClient} client + * @param {any} data + */ + constructor(client, data) { + super(client); + + /** Unique identifier of the prepared button */ + this.id = data.id; + + /** Expiration date of the prepared button, in Unix time */ + this.expiresUnixTime = data.expiration_date; + } + + get expiresTimestamp() { + return this.expiresUnixTime * 1000; + } + + get expiresAt() { + return new Date(this.expiresTimestamp); + } +} + +module.exports = { PreparedKeyboardButton }; diff --git a/src/structures/misc/User.js b/src/structures/misc/User.js index 3afa992..b326a5e 100644 --- a/src/structures/misc/User.js +++ b/src/structures/misc/User.js @@ -57,7 +57,7 @@ class User extends Base { * IETF language tag of the user's language * @type {LanguageCode | undefined} */ - this.language = data.language_code; + this.language = /** @type {LanguageCode} */ (data.language_code); } /** @@ -72,6 +72,12 @@ class User extends Base { */ this.inAttachmentMenu = Boolean(data.added_to_attachment_menu); + /** + * True, if this user can manage bots + * @type {boolean} + */ + this.canManageBots = Boolean((/** @type {any} */ (data)).can_manage_bots); + return data; } diff --git a/src/util/Constants.ts b/src/util/Constants.ts index ea57271..a6f82a1 100644 --- a/src/util/Constants.ts +++ b/src/util/Constants.ts @@ -62,6 +62,7 @@ const Events = { ChatBoost: "chatBoost", RemovedChatBoost: "removedChatBoost", PurchasedPaidMedia: "purchasedPaidMedia", + ManagedBot: "managedBot", } as const; const RestEvents = { diff --git a/src/util/markup/KeyboardBuilder.ts b/src/util/markup/KeyboardBuilder.ts index bea4885..52cd742 100644 --- a/src/util/markup/KeyboardBuilder.ts +++ b/src/util/markup/KeyboardBuilder.ts @@ -3,6 +3,7 @@ import type { KeyboardButtonPollType, KeyboardButtonRequestChat, KeyboardButtonRequestUsers, + KeyboardButtonRequestManagedBot, ReplyKeyboardMarkup, } from "../../client/interfaces/Markup"; @@ -202,6 +203,39 @@ class KeyboardBuilder { return { text, request_poll: { type } }; } + + /** + * Adds a request managed bot button to the keyboard. + * @param text - The button text. + * @param requestId - The request ID. + * @param options - Additional options for the button. + * @returns The current instance for chaining. + */ + requestManagedBot( + text: string, + requestId: number, + options: Omit = {}, + ): this { + return this.add( + KeyboardBuilder.requestManagedBot(text, requestId, options), + ); + } + + /** + * Creates a request managed bot button. + * @param text - The button text. + * @param requestId - The request ID. + * @param options - Additional options for the button. + * @returns The created request managed bot button. + */ + static requestManagedBot( + text: string, + requestId: number, + options: Omit = {}, + ): KeyboardButton.RequestManagedBotButton { + return { text, request_managed_bot: { request_id: requestId, ...options } }; + } + /** * Adds a web app button to the keyboard. * @param text - The button text. diff --git a/typings/telegram/Markup.d.ts b/typings/telegram/Markup.d.ts index 55c1cf5..1557343 100644 --- a/typings/telegram/Markup.d.ts +++ b/typings/telegram/Markup.d.ts @@ -174,6 +174,10 @@ export declare namespace KeyboardButton { /** 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. */ request_poll: KeyboardButtonPollType; } + export interface RequestManagedBotButton extends CommonButton { + /** If specified, pressing the button will allow the user to select a manager bot and create a managed bot in a service message. Available in private chats only. */ + request_managed_bot: KeyboardButtonRequestManagedBot; + } export interface WebAppButton extends CommonButton { /** If specified, the described Web App 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. */ web_app: WebAppInfo; @@ -188,6 +192,7 @@ export type KeyboardButton = | KeyboardButton.RequestContactButton | KeyboardButton.RequestLocationButton | KeyboardButton.RequestPollButton + | KeyboardButton.RequestManagedBotButton | KeyboardButton.WebAppButton | string; @@ -197,6 +202,19 @@ export interface KeyboardButtonPollType { type?: "quiz" | "regular"; } + +/** This object defines the criteria used to request a managed bot. Information about the selected manager bot and created managed bot will be shared with the bot when the corresponding button is pressed. */ +export interface KeyboardButtonRequestManagedBot { + /** Signed 32-bit identifier of the request, which will be received back in the ManagedBotCreated object. Must be unique within the message */ + request_id: number; + /** The username of the manager bot that can be used to create the managed bot. */ + manager_bot_username?: string; + /** Suggested username for the managed bot. */ + bot_username?: string; + /** Suggested name for the managed bot. */ + bot_name?: string; +} + /** Upon receiving a message with this object, Telegram clients will remove the current custom keyboard and display the default letter-keyboard. By default, custom keyboards are displayed until a new keyboard is sent by a bot. An exception is made for one-time keyboards that are hidden immediately after the user presses a button (see ReplyKeyboardMarkup). Not supported in channels and for messages sent on behalf of a Telegram Business account. */ export interface ReplyKeyboardRemove { /** Requests clients to remove the custom keyboard (user will not be able to summon this keyboard; if you want to hide the keyboard from sight but keep it accessible, use one_time_keyboard in ReplyKeyboardMarkup) */ diff --git a/typings/telegram/Message.d.ts b/typings/telegram/Message.d.ts index e3ee25c..647aaa9 100644 --- a/typings/telegram/Message.d.ts +++ b/typings/telegram/Message.d.ts @@ -13,11 +13,13 @@ export interface User { /** User's or bot's username */ username?: string; /** IETF language tag of the user's language */ - language_code?: LanguageCode; + language_code?: LanguageCode | string; /** True, if this user is a Telegram Premium user */ is_premium?: true; /** True, if this user added the bot to the attachment menu */ added_to_attachment_menu?: true; + /** True, if the bot can be invited to create managed bots */ + can_manage_bots?: true; } /** Describes the options used for link preview generation. */ @@ -121,6 +123,8 @@ export interface ReplyParameters { chat_id?: number | string; /** Identifier of the specific checklist task to be replied to */ checklist_task_id?: number; + /** Identifier of the poll option to be replied to */ + poll_option_id?: number; /** Pass True if the message should be sent even if the specified message to be replied to is not found; can be used only for replies in the same chat and forum topic. Always True for messages sent on behalf of a business account. */ allow_sending_without_reply?: boolean; /** Quoted part of the message to be replied to; 0-1024 characters after entities parsing. The quote must be an exact substring of the message to be replied to, including bold, italic, underline, strikethrough, spoiler, and custom_emoji entities. The message will fail to send if the quote isn't found in the original message. */ diff --git a/typings/telegram/Methods.d.ts b/typings/telegram/Methods.d.ts index b160575..a6a2e7f 100644 --- a/typings/telegram/Methods.d.ts +++ b/typings/telegram/Methods.d.ts @@ -952,19 +952,33 @@ export type ApiMethods = { isAnonymous?: boolean; /** Poll type, “quiz” or “regular”, defaults to “regular” */ type?: "quiz" | "regular"; - /** True, if the poll allows multiple answers, ignored for polls in quiz mode, defaults to False */ + /** True, if the poll allows multiple answers, defaults to False */ allowsMultipleAnswers?: boolean; - /** 0-based identifier of the correct answer option, required for polls in quiz mode */ - correctOptionId?: number; + /** 0-based identifiers of the correct answer options, required for polls in quiz mode */ + correctOptionIds?: number[]; + /** True, if users can change their answers after voting */ + allowsRevoting?: boolean; + /** True, if poll options should be shuffled */ + shuffleOptions?: boolean; + /** True, if users are allowed to add options */ + allowAddingOptions?: boolean; + /** True, if results should be hidden until the poll is closed */ + hideResultsUntilCloses?: boolean; /** Text that is shown when a user chooses an incorrect answer or taps on the lamp icon in a quiz-style poll, 0-200 characters with at most 2 line feeds after entities parsing */ explanation?: string; /** Mode for parsing entities in the explanation. See formatting options for more details. */ explanationParseMode?: ParseMode; /** A list of special entities that appear in the poll explanation. It can be specified instead of explanationParseMode */ explanationEntities?: MessageEntity[]; - /** Amount of time in seconds the poll will be active after creation, 5-600. Can't be used together with closeDate. */ + /** Poll description, 0-200 characters */ + description?: string; + /** Mode for parsing entities in the poll description */ + descriptionParseMode?: ParseMode; + /** List of special entities that appear in the poll description */ + descriptionEntities?: MessageEntity[]; + /** Amount of time in seconds the poll will be active after creation, 5-2628000. Can't be used together with closeDate. */ openPeriod?: number; - /** Point in time (Unix timestamp) when the poll will be automatically closed. Must be at least 5 and no more than 600 seconds in the future. Can't be used together with openPeriod. */ + /** Point in time (Unix timestamp) when the poll will be automatically closed. Must be at least 5 and no more than 2628000 seconds in the future. Can't be used together with openPeriod. */ closeDate?: number; /** Pass True if the poll needs to be immediately closed. This can be useful for poll preview. */ isClosed?: boolean; @@ -2296,6 +2310,35 @@ export type ApiMethods = { allowChannelChats?: boolean; }): import("../index").PreparedInlineMessage; + + /** Use this method to get the current token of a managed bot. */ + getManagedBotToken(args: { + /** Identifier of the managed bot */ + botId: number | string; + }): string; + + /** Use this method to replace the token of a managed bot. */ + replaceManagedBotToken(args: { + /** Identifier of the managed bot */ + botId: number | string; + }): string; + + /** Stores a keyboard button that can be sent by a user of a Mini App. */ + savePreparedKeyboardButton(args: { + /** Unique identifier of the target user that can use the prepared button */ + userId: string | number; + /** The keyboard button to prepare */ + button: import("./Markup").KeyboardButton; + /** Pass True if the button can be sent to private chats with users */ + allowUserChats?: boolean; + /** Pass True if the button can be sent to private chats with bots */ + allowBotChats?: boolean; + /** Pass True if the button can be sent to group and supergroup chats */ + allowGroupChats?: boolean; + /** Pass True if the button can be sent to channel chats */ + allowChannelChats?: boolean; + }): import("../../structures/misc/PreparedKeyboardButton").PreparedKeyboardButton; + /** Use this method to send invoices. On success, the sent Message is returned. */ sendInvoice(args: { /** Unique identifier for the target chat or username of the target channel (in the format @channelusername) */