diff --git a/README.md b/README.md index 353c351..7a53e44 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![npm](https://img.shields.io/npm/dt/typescript-telegram-bot-api)](https://www.npmjs.com/package/typescript-telegram-bot-api) [![codecov](https://codecov.io/github/Borodin/typescript-telegram-bot-api/graph/badge.svg?token=509N5AZDTV)](https://codecov.io/github/Borodin/typescript-telegram-bot-api) [![codesandbox](https://img.shields.io/badge/Open_in-sandbox-eaff96)](https://codesandbox.io/p/sandbox/interesting-wave-qgspfs) -[![GitHub](https://img.shields.io/badge/Bot_API-v7.11-0088cc)](https://core.telegram.org/bots/api#october-31-2024) +[![GitHub](https://img.shields.io/badge/Bot_API-v8.0-0088cc)](https://core.telegram.org/bots/api#november-17-2024) This is a TypeScript wrapper for the [Telegram Bot API](https://core.telegram.org/bots/api) Node.js and browsers. It allows you to easily interact with the Telegram Bot API using TypeScript. diff --git a/package.json b/package.json index 18fbde3..3e82f5a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "type": "commonjs", "name": "typescript-telegram-bot-api", - "version": "0.4.1", + "version": "0.5.0", "description": "Telegram Bot API wrapper for Node.js written in TypeScript", "repository": "github:Borodin/typescript-telegram-bot-api", "main": "dist/index.js", diff --git a/src/index.ts b/src/index.ts index 716f1b3..9aa37bd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -64,6 +64,7 @@ import { InputPaidMedia, WebhookInfo, Currencies, + Gifts, } from './types/'; import * as TelegramTypes from './types/'; @@ -1157,6 +1158,20 @@ export class TelegramBot extends EventEmitter { return await this.callApi('getUserProfilePhotos', options); } + /** + * ## setUserEmojiStatus + * Changes the emoji status for a given user that previously allowed the bot to manage their emoji status via the + * Mini App method requestEmojiStatusAccess. Returns True on success. + * @see https://core.telegram.org/bots/api#setuseremojistatus + */ + async setUserEmojiStatus(options: { + user_id: number; + emoji_status_custom_emoji_id?: string; + emoji_status_expiration_date?: number; + }): Promise { + return await this.callApi('setUserEmojiStatus', options); + } + /** * ## getFile * Use this method to get basic information about a file and prepare it for downloading. For the moment, bots can @@ -2388,12 +2403,14 @@ export class TelegramBot extends EventEmitter { * @see https://core.telegram.org/bots/api#createinvoicelink */ async createInvoiceLink(options: { + business_connection_id?: string; title: string; description: string; payload: string; provider_token?: string; currency: T; prices: T extends 'XTR' ? [LabeledPrice] : LabeledPrice[]; + subscription_period?: T extends 'XTR' ? number : never; max_tip_amount?: T extends 'XTR' ? never : number; suggested_tip_amounts?: number[]; provider_data?: string; @@ -2476,6 +2493,19 @@ export class TelegramBot extends EventEmitter { return await this.callApi('refundStarPayment', options); } + /** + * ## editUserStarSubscription + * Allows the bot to cancel or re-enable extension of a subscription paid in Telegram Stars. Returns True on success. + * @see https://core.telegram.org/bots/api#edituserstarsubscription + */ + async editUserStarSubscription(options: { + user_id: number; + telegram_payment_charge_id: string; + is_canceled: boolean; + }): Promise { + return await this.callApi('editUserStarSubscription', options); + } + /** * ## setPassportDataErrors * Informs a user that some of the Telegram Passport elements they provided contains errors. The user will not be able @@ -2557,6 +2587,33 @@ export class TelegramBot extends EventEmitter { return await this.callApi('getGameHighScores', options); } + /** + * ## getAvailableGifts + * Returns the list of gifts that can be sent by the bot to users. Requires no parameters. Returns a Gifts object. + * @see https://core.telegram.org/bots/api#getavailablegifts + */ + async getAvailableGifts(): Promise { + return await this.callApi('getAvailableGifts'); + } + + /** + * ## sendGift + * Sends a gift to the given user. The gift can't be converted to Telegram Stars by the user. Returns True on success. + * @see https://core.telegram.org/bots/api#sendgift + */ + async sendGift(options: { + user_id: number; + gift_id: string; + text?: string; + text_parse_mode?: ParseMode; + text_entities?: MessageEntity[]; + }): Promise { + return await this.callApi('sendGift', { + ...options, + text_entities: new JSONSerialized(options.text_entities), + }); + } + on(event: U, listener: (eventData: NonNullable) => void): this { return super.on(event, listener) as this; } diff --git a/src/types/Gift.ts b/src/types/Gift.ts new file mode 100644 index 0000000..de810fc --- /dev/null +++ b/src/types/Gift.ts @@ -0,0 +1,33 @@ +import { Sticker } from './'; + +/** + * ## Gift + * This object represents a gift that can be sent by the bot. + * @see https://core.telegram.org/bots/api#gift + */ +export type Gift = { + /** + * Unique identifier of the gift + */ + id: string; + + /** + * The sticker that represents the gift + */ + sticker: Sticker; + + /** + * The number of Telegram Stars that must be paid to send the sticker + */ + star_count: number; + + /** + * Optional. The total number of the gifts of this type that can be sent; for limited gifts only + */ + total_count?: number; + + /** + * Optional. The number of remaining gifts of this type that can be sent; for limited gifts only + */ + remaining_count?: number; +}; diff --git a/src/types/Gifts.ts b/src/types/Gifts.ts new file mode 100644 index 0000000..609336a --- /dev/null +++ b/src/types/Gifts.ts @@ -0,0 +1,13 @@ +import { Gift } from './'; + +/** + * ## Gifts + * This object represent a list of gifts. + * @see https://core.telegram.org/bots/api#gifts + */ +export type Gifts = { + /** + * The list of gifts + */ + gifts: Gift[]; +}; diff --git a/src/types/SuccessfulPayment.ts b/src/types/SuccessfulPayment.ts index 6c4638d..901aaa1 100644 --- a/src/types/SuccessfulPayment.ts +++ b/src/types/SuccessfulPayment.ts @@ -23,6 +23,21 @@ export type SuccessfulPayment = { */ invoice_payload: string; + /** + * Optional. Expiration date of the subscription, in Unix time; for recurring payments only + */ + subscription_expiration_date?: number; + + /** + * Optional. True, if the payment is a recurring payment for a subscription + */ + is_recurring?: boolean; + + /** + * Optional. True, if the payment is the first payment for a subscription + */ + is_first_recurring?: boolean; + /** * Optional. Identifier of the shipping option chosen by the user */ diff --git a/src/types/TransactionPartnerUser.ts b/src/types/TransactionPartnerUser.ts index a089576..9885d60 100644 --- a/src/types/TransactionPartnerUser.ts +++ b/src/types/TransactionPartnerUser.ts @@ -1,5 +1,6 @@ import { User } from './User'; import { PaidMedia } from './PaidMedia'; +import { Gift } from './Gift'; /** * ## TransactionPartnerUser @@ -22,6 +23,11 @@ export type TransactionPartnerUser = { */ invoice_payload: string; + /** + * Optional. The duration of the paid subscription + */ + subscription_period?: number; + /** * Optional. Information about the paid media bought by the user */ @@ -31,4 +37,9 @@ export type TransactionPartnerUser = { * Optional. Bot-specified paid media payload */ paid_media_payload: string; + + /** + * Optional. The gift sent to the user by the bot + */ + gift?: Gift; }; diff --git a/src/types/index.ts b/src/types/index.ts index d3ee496..9e3bc01 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -75,6 +75,8 @@ export * from './Game'; export * from './GameHighScore'; export * from './GeneralForumTopicHidden'; export * from './GeneralForumTopicUnhidden'; +export * from './Gift'; +export * from './Gifts'; export * from './Giveaway'; export * from './GiveawayCompleted'; export * from './GiveawayCreated'; diff --git a/tests/index.test.ts b/tests/index.test.ts index e0027b6..cc50592 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -727,6 +727,17 @@ describe('.getUserProfilePhotos()', () => { }); }); +describe('.setUserEmojiStatus()', () => { + test('should set user emoji status', async () => { + await expect( + bot.setUserEmojiStatus({ + user_id: USERID, + emoji_status_custom_emoji_id: '', + }), + ).rejects.toThrow("403 Forbidden: not enough rights to change the user's emoji status"); + }); +}); + describe('.getFile()', () => { test('should get file', async () => { await expect( @@ -1951,7 +1962,19 @@ describe('.refundStarPayment()', () => { user_id: USERID, telegram_payment_charge_id: 'PAYMENT_ID', }), - ).rejects.toThrow('400 Bad Request: CHARGE_NOT_FOUND'); + ).rejects.toThrow('400 Bad Request: CHARGE_ID_EMPTY'); + }); +}); + +describe('.editUserStarSubscription()', () => { + test('should edit user star subscription', async () => { + await expect( + bot.editUserStarSubscription({ + user_id: USERID, + telegram_payment_charge_id: 'CHARGE_ID', + is_canceled: true, + }), + ).rejects.toThrow('400 Bad Request: CHARGE_ID_INVALID'); }); }); @@ -2387,3 +2410,23 @@ describe('.setPassportDataErrors()', () => { ).rejects.toThrow('400 Bad Request: DATA_HASH_SIZE_INVALID'); }); }); + +describe('.getAvailableGifts()', () => { + test('should get available gifts', async () => { + await expect(bot.getAvailableGifts()).resolves.toHaveProperty('gifts'); + }); +}); + +describe('.sendGift()', () => { + test('should send gift', async () => { + const gifts = (await bot.getAvailableGifts()).gifts; + + await expect( + bot.sendGift({ + user_id: USERID, + gift_id: gifts[0].id, + text: 'text', + }), + ).rejects.toThrow('400 Bad Request: BALANCE_TOO_LOW'); + }); +});