diff --git a/CHANGELOG.md b/CHANGELOG.md index 908ef2e2..4a361848 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# 1.21.0 + +- πŸ€– Bot API 7.6 +- Added methods to register callbacks for handling paid media in bot messages: + - `Bot.onPaidMedia`: Registers a callback for whenever any type of paid media + is received in messages. + - `Bot.onPaidMediaVideo`: Registers a callback for whenever paid media videos + are received in messages. + - `Bot.onPaidMediaPhoto`: Registers a callback for whenever paid media photos + are received in messages. +- New method `RawAPI.sendPaidMedia` is added to send paid media. + # 1.20.0 - πŸ₯³ Support for Custom Context diff --git a/README.md b/README.md index 61af39fa..6f5aec0d 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Pub Version](https://img.shields.io/pub/v/televerse?color=blue&logo=blue)](https://pub.dev/packages/televerse) ![GitHub](https://img.shields.io/github/license/HeySreelal/televerse?color=green) -![](https://shields.io/badge/Latest-Bot%20API%207.5-blue) +![](https://shields.io/badge/Latest-Bot%20API%207.6-blue) @@ -13,7 +13,7 @@ --- -πŸ€– `Bot API version: Bot API 7.5 (June 18, 2024)` +πŸ€– `Bot API version: Bot API 7.6 (July 1, 2024)` Televerse is a powerful, easy-to-use, and highly customizable Telegram bot framework built with Dart programming language. It provides a complete and @@ -23,9 +23,20 @@ public interface, making it easy for developers to write strictly typed code. ## πŸ”₯ What's latest? -### πŸ—“οΈ June 28, 2024 +### πŸ€– Bot API 7.6 -πŸŽ‰ Support for Custom Contexts! +(πŸ—“οΈ July 1, 2024) + +In a nutshell, the updates include support for the new Paid Media messages. +Brings the new `sendPaidMedia` message to send paid media messages. Introduces +`TransactionPartnerTelegramAds`, new field in `ChatFullInfo`, and more. + +Checkout [changelog](https://core.telegram.org/bots/api#july-1-2024) for more +details! πŸš€ + +### πŸŽ‰ Support for Custom Contexts! + +(πŸ—“οΈ June 28, 2024) Televerse now lets you build even more powerful bots with custom contexts! @@ -39,25 +50,15 @@ constructors to create context objects with personalized behaviors and capabilities. This update allows you to tailor your bot's responses, handle complex workflows, and integrate additional features seamlessly. -### πŸ—“οΈ June 22, 2024 - -Introducing Middleware & Transformer support! You can now use the `Bot.use` -method to attach middlewares to your bot. These middlewares will be processed -before your main handler runs, allowing you to pre-process or even decide -whether to execute the main handler. Additionally, using a `Transformer` lets -you directly modify the request payload, reducing redundant code and simplifying -your coding experience. +### Introducing Middleware & Transformer support! -### πŸ—“οΈ June 18, 2024 +(πŸ—“οΈ June 22, 2024) -In a nutshell, the updates include new Payment system with -[Telegram Stars](https://t.me/BotNews/90). Includes a bunch of new models -related to Star Payments and new method to get Bot's Star Payment history. This -update also includes support for Business Bots to edit messages as well as -accept callback and inline queries. - -Checkout [changelog](https://core.telegram.org/bots/api#june-18-2024) for more -details! πŸš€ +You can now use the `Bot.use` method to attach middlewares to your bot. These +middlewares will be processed before your main handler runs, allowing you to +pre-process or even decide whether to execute the main handler. Additionally, +using a `Transformer` lets you directly modify the request payload, reducing +redundant code and simplifying your coding experience.
diff --git a/lib/src/telegram/models/abstracts/input_paid_media.dart b/lib/src/telegram/models/abstracts/input_paid_media.dart new file mode 100644 index 00000000..772a7ba8 --- /dev/null +++ b/lib/src/telegram/models/abstracts/input_paid_media.dart @@ -0,0 +1,20 @@ +part of '../models.dart'; + +/// This object describes the paid media to be sent. +/// Currently, it can be one of [InputPaidMediaPhoto] or [InputPaidMediaVideo]. +sealed class InputPaidMedia { + /// Type of the media. + InputPaidMediaType get type; + + /// File to send. + /// Pass a file_id to send a file that exists on the Telegram servers (recommended), + /// pass an HTTP URL for Telegram to get a file from the Internet, or pass β€œattach://” + /// to upload a new one using multipart/form-data under name. + final InputFile media; + + /// Creates a new [InputPaidMedia] object from JSON. + const InputPaidMedia(this.media); + + /// Converts an [InputPaidMedia] to a [Map] for JSON encoding. + Map toJson(); +} diff --git a/lib/src/telegram/models/abstracts/menu_button.dart b/lib/src/telegram/models/abstracts/menu_button.dart index 202da91f..12ac58cc 100644 --- a/lib/src/telegram/models/abstracts/menu_button.dart +++ b/lib/src/telegram/models/abstracts/menu_button.dart @@ -10,14 +10,11 @@ abstract class MenuButton { /// Creates a new [MenuButton] object. /// This method decides which [MenuButton] subclass to use based on the [type] field. static MenuButton create(Map json) { - switch (json['type']) { - case 'commands': - return MenuButtonCommands.fromJson(json); - case 'web_app': - return MenuButtonWebApp.fromJson(json); - default: - return MenuButtonDefault.fromJson(json); - } + return switch (json['type']) { + 'commands' => MenuButtonCommands.fromJson(json), + 'web_app' => MenuButtonWebApp.fromJson(json), + _ => MenuButtonDefault.fromJson(json), + }; } /// Creates a new [MenuButton] object. diff --git a/lib/src/telegram/models/abstracts/paid_media.dart b/lib/src/telegram/models/abstracts/paid_media.dart new file mode 100644 index 00000000..a8e4b501 --- /dev/null +++ b/lib/src/telegram/models/abstracts/paid_media.dart @@ -0,0 +1,25 @@ +part of '../models.dart'; + +/// This object describes paid media. +/// Currently, it can be one of [PaidMediaPreview], [PaidMediaPhoto], [PaidMediaVideo]. +abstract class PaidMedia { + /// Type of the paid media. + PaidMediaType get type; + + /// Creates a new [PaidMedia] object. + /// This method decides which [PaidMedia] subclass to use based on the [type] field. + static PaidMedia fromJson(Map json) { + return switch (json['type']) { + 'preview' => PaidMediaPreview.fromJson(json), + 'photo' => PaidMediaPhoto.fromJson(json), + 'video' => PaidMediaVideo.fromJson(json), + _ => throw ArgumentError('Invalid paid media type') + }; + } + + /// Creates a new [PaidMedia] object from JSON. + const PaidMedia(); + + /// Converts a [PaidMedia] to a [Map] for JSON encoding. + Map toJson(); +} diff --git a/lib/src/telegram/models/abstracts/transaction_partner.dart b/lib/src/telegram/models/abstracts/transaction_partner.dart index 373c44bf..3ab1dc2d 100644 --- a/lib/src/telegram/models/abstracts/transaction_partner.dart +++ b/lib/src/telegram/models/abstracts/transaction_partner.dart @@ -13,6 +13,7 @@ abstract class TransactionPartner { 'fragment' => TransactionPartnerFragment.fromJson(json), 'user' => TransactionPartnerUser.fromJson(json), 'other' => TransactionPartnerOther.fromJson(json), + 'telegram_ads' => TransactionPartnerTelegramAds.fromJson(json), _ => throw ArgumentError('Invalid transaction partner type') }; } diff --git a/lib/src/telegram/models/chat_full_info.dart b/lib/src/telegram/models/chat_full_info.dart index 1e5630c7..a27d1d59 100644 --- a/lib/src/telegram/models/chat_full_info.dart +++ b/lib/src/telegram/models/chat_full_info.dart @@ -110,6 +110,9 @@ class ChatFullInfo extends Chat implements WithID { /// The maximum number of reactions that can be set on a message in the chat final int maxReactionCount; + /// Optional. True, if paid media messages can be sent or forwarded to the channel chat. The field is available only for channel chats. + final bool? canSendPaidMedia; + /// Constructs a [Chat] object. const ChatFullInfo({ required super.id, @@ -155,6 +158,7 @@ class ChatFullInfo extends Chat implements WithID { this.personalChat, this.birthdate, this.maxReactionCount = 0, + this.canSendPaidMedia, }); /// Creates a [Chat] object from json. @@ -225,6 +229,7 @@ class ChatFullInfo extends Chat implements WithID { ? null : Birthdate.fromJson(json['birthdate']), maxReactionCount: json["max_reaction_count"], + canSendPaidMedia: json["can_send_paid_media"], ); } @@ -277,6 +282,7 @@ class ChatFullInfo extends Chat implements WithID { 'business_opening_hours': businessOpeningHours?.toJson(), 'personal_chat': personalChat?.toJson(), 'birthdate': birthdate?.toJson(), + 'can_send_paid_media': canSendPaidMedia, }..removeWhere(_nullFilter); } } diff --git a/lib/src/telegram/models/external_reply_info.dart b/lib/src/telegram/models/external_reply_info.dart index 637ebd73..71adb29c 100644 --- a/lib/src/telegram/models/external_reply_info.dart +++ b/lib/src/telegram/models/external_reply_info.dart @@ -71,6 +71,9 @@ class ExternalReplyInfo { /// Optional. Message is a venue, information about the venue final Venue? venue; + /// Optional. Message contains paid media; information about the paid media + final PaidMediaInfo? paidMedia; + /// Constructs the [ExternalReplyInfo] const ExternalReplyInfo({ required this.origin, @@ -96,6 +99,7 @@ class ExternalReplyInfo { this.location, this.poll, this.venue, + this.paidMedia, }); /// Converts instance of [ExternalReplyInfo] into JSON encodable [Map]. @@ -124,6 +128,7 @@ class ExternalReplyInfo { 'location': location?.toJson(), 'poll': poll?.toJson(), 'venue': venue?.toJson(), + 'paid_media': paidMedia?.toJson(), }..removeWhere(_nullFilter); } @@ -169,6 +174,9 @@ class ExternalReplyInfo { json['location'] != null ? Location.fromJson(json['location']) : null, poll: json['poll'] != null ? Poll.fromJson(json['poll']) : null, venue: json['venue'] != null ? Venue.fromJson(json['venue']) : null, + paidMedia: json['paid_media'] != null + ? PaidMediaInfo.fromJson(json['paid_media']) + : null, ); } } diff --git a/lib/src/telegram/models/input_paid_media_photo.dart b/lib/src/telegram/models/input_paid_media_photo.dart new file mode 100644 index 00000000..12590b04 --- /dev/null +++ b/lib/src/telegram/models/input_paid_media_photo.dart @@ -0,0 +1,28 @@ +part of 'models.dart'; + +/// The paid media to send is a photo. +class InputPaidMediaPhoto implements InputPaidMedia { + @override + InputPaidMediaType get type => InputPaidMediaType.photo; + + /// File to send. + /// Pass a file_id to send a file that exists on the Telegram servers (recommended), + /// pass an HTTP URL for Telegram to get a file from the Internet, or pass β€œattach://” + /// to upload a new one using multipart/form-data under name. + @override + final InputFile media; + + /// Constructs a [InputPaidMediaPhoto] object. + const InputPaidMediaPhoto({ + required this.media, + }); + + /// Converts a [InputPaidMediaPhoto] object to JSON. + @override + Map toJson() { + return { + 'type': type, + 'media': media.getValue('media'), + }; + } +} diff --git a/lib/src/telegram/models/input_paid_media_video.dart b/lib/src/telegram/models/input_paid_media_video.dart new file mode 100644 index 00000000..268bad62 --- /dev/null +++ b/lib/src/telegram/models/input_paid_media_video.dart @@ -0,0 +1,53 @@ +part of 'models.dart'; + +/// The paid media to send is a video. +class InputPaidMediaVideo implements InputPaidMedia { + @override + InputPaidMediaType get type => InputPaidMediaType.video; + + /// File to send. + /// Pass a file_id to send a file that exists on the Telegram servers (recommended), + /// pass an HTTP URL for Telegram to get a file from the Internet, or pass β€œattach://” + /// to upload a new one using multipart/form-data under name. + @override + final InputFile media; + + /// Optional. Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. + final InputFile? thumbnail; + + /// Optional. Video width. + final int? width; + + /// Optional. Video height. + final int? height; + + /// Optional. Video duration in seconds. + final int? duration; + + /// Optional. Pass True if the uploaded video is suitable for streaming. + final bool? supportsStreaming; + + /// Constructs a [InputPaidMediaVideo] object. + const InputPaidMediaVideo({ + required this.media, + this.thumbnail, + this.width, + this.height, + this.duration, + this.supportsStreaming, + }); + + /// Converts a [InputPaidMediaVideo] object to JSON. + @override + Map toJson() { + return { + 'type': type, + 'media': media.getValue('media'), + 'thumbnail': thumbnail?.getValue('thumbnail'), + 'width': width, + 'height': height, + 'duration': duration, + 'supports_streaming': supportsStreaming, + }..removeWhere(_nullFilter); + } +} diff --git a/lib/src/telegram/models/menu_button_web_app.dart b/lib/src/telegram/models/menu_button_web_app.dart index c7390f50..97a986be 100644 --- a/lib/src/telegram/models/menu_button_web_app.dart +++ b/lib/src/telegram/models/menu_button_web_app.dart @@ -9,7 +9,9 @@ class MenuButtonWebApp extends MenuButton { /// Text on the button final String text; - /// Description of the Web App 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. + /// Description of the Web App 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`. + /// + /// Alternatively, a `t.me` link to a Web App of the bot can be specified in the object instead of the Web App's URL, in which case the Web App will be opened as if the user pressed the link. final WebAppInfo webApp; /// Constructs a [MenuButtonWebApp] object diff --git a/lib/src/telegram/models/message.dart b/lib/src/telegram/models/message.dart index 90579822..4fc43402 100644 --- a/lib/src/telegram/models/message.dart +++ b/lib/src/telegram/models/message.dart @@ -259,6 +259,9 @@ class Message implements MaybeInaccessibleMessage, WithUser { /// Optional. True, if the caption must be shown above the message media final bool? showCaptionAboveMedia; + /// Optional. Message contains paid media; information about the paid media + final PaidMediaInfo? paidMedia; + /// Creates a Message object. const Message({ this.from, @@ -344,6 +347,7 @@ class Message implements MaybeInaccessibleMessage, WithUser { this.chatBackgroundSet, this.effectId, this.showCaptionAboveMedia, + this.paidMedia, }); /// Creates a [Message] object from json map. @@ -530,6 +534,9 @@ class Message implements MaybeInaccessibleMessage, WithUser { : null, effectId: json["effect_id"], showCaptionAboveMedia: json["show_caption_above_media"], + paidMedia: json['paid_media'] != null + ? PaidMediaInfo.fromJson(json['paid_media']) + : null, ); } @@ -621,6 +628,7 @@ class Message implements MaybeInaccessibleMessage, WithUser { 'chat_background_set': chatBackgroundSet?.toJson(), 'effect_id': effectId, 'show_caption_above_media': showCaptionAboveMedia, + 'paid_media': paidMedia?.toJson(), }..removeWhere(_nullFilter); } diff --git a/lib/src/telegram/models/models.dart b/lib/src/telegram/models/models.dart index b5a9953d..03a98db6 100644 --- a/lib/src/telegram/models/models.dart +++ b/lib/src/telegram/models/models.dart @@ -254,3 +254,14 @@ part 'abstracts/revenue_withdrawal_state.dart'; part 'revenue_withdrawal_state_pending.dart'; part 'revenue_withdrawal_state_succeeded.dart'; part 'revenue_withdrawal_state_failed.dart'; + +// Bot API 7.6 +part 'abstracts/paid_media.dart'; +part 'paid_media_video.dart'; +part 'paid_media_photo.dart'; +part 'paid_media_preview.dart'; +part 'paid_media_info.dart'; +part 'abstracts/input_paid_media.dart'; +part 'input_paid_media_photo.dart'; +part 'input_paid_media_video.dart'; +part 'transaction_partner_telegram_ads.dart'; diff --git a/lib/src/telegram/models/paid_media_info.dart b/lib/src/telegram/models/paid_media_info.dart new file mode 100644 index 00000000..7119f0bd --- /dev/null +++ b/lib/src/telegram/models/paid_media_info.dart @@ -0,0 +1,34 @@ +part of 'models.dart'; + +/// Describes the paid media added to a message. +class PaidMediaInfo { + /// The number of Telegram Stars that must be paid to buy access to the media. + final int starCount; + + /// Information about the paid media. + final List paidMedia; + + /// Constructs a [PaidMediaInfo] object. + const PaidMediaInfo({ + required this.starCount, + required this.paidMedia, + }); + + /// Creates a [PaidMediaInfo] object from JSON. + factory PaidMediaInfo.fromJson(Map json) { + return PaidMediaInfo( + starCount: json['star_count'], + paidMedia: (json['paid_media'] as List) + .map((item) => PaidMedia.fromJson(item)) + .toList(), + ); + } + + /// Converts a [PaidMediaInfo] object to JSON. + Map toJson() { + return { + 'star_count': starCount, + 'paid_media': paidMedia.map((item) => item.toJson()).toList(), + }; + } +} diff --git a/lib/src/telegram/models/paid_media_photo.dart b/lib/src/telegram/models/paid_media_photo.dart new file mode 100644 index 00000000..76b8a522 --- /dev/null +++ b/lib/src/telegram/models/paid_media_photo.dart @@ -0,0 +1,33 @@ +part of 'models.dart'; + +/// The paid media is a photo. +class PaidMediaPhoto extends PaidMedia { + @override + PaidMediaType get type => PaidMediaType.photo; + + /// The photo. + final List photo; + + /// Constructs a [PaidMediaPhoto] object. + const PaidMediaPhoto({ + required this.photo, + }); + + /// Creates a [PaidMediaPhoto] object from JSON. + factory PaidMediaPhoto.fromJson(Map json) { + return PaidMediaPhoto( + photo: (json['photo'] as List) + .map((item) => PhotoSize.fromJson(item)) + .toList(), + ); + } + + /// Converts a [PaidMediaPhoto] object to JSON. + @override + Map toJson() { + return { + 'type': type, + 'photo': photo.map((item) => item.toJson()).toList(), + }; + } +} diff --git a/lib/src/telegram/models/paid_media_preview.dart b/lib/src/telegram/models/paid_media_preview.dart new file mode 100644 index 00000000..65c9908c --- /dev/null +++ b/lib/src/telegram/models/paid_media_preview.dart @@ -0,0 +1,43 @@ +part of 'models.dart'; + +/// The paid media isn't available before the payment. +class PaidMediaPreview extends PaidMedia { + @override + PaidMediaType get type => PaidMediaType.preview; + + /// Optional. Media width as defined by the sender. + final int? width; + + /// Optional. Media height as defined by the sender. + final int? height; + + /// Optional. Duration of the media in seconds as defined by the sender. + final int? duration; + + /// Constructs a [PaidMediaPreview] object. + const PaidMediaPreview({ + this.width, + this.height, + this.duration, + }); + + /// Creates a [PaidMediaPreview] object from JSON. + factory PaidMediaPreview.fromJson(Map json) { + return PaidMediaPreview( + width: json['width'], + height: json['height'], + duration: json['duration'], + ); + } + + /// Converts a [PaidMediaPreview] object to JSON. + @override + Map toJson() { + return { + 'type': type, + 'width': width, + 'height': height, + 'duration': duration, + }..removeWhere(_nullFilter); + } +} diff --git a/lib/src/telegram/models/paid_media_video.dart b/lib/src/telegram/models/paid_media_video.dart new file mode 100644 index 00000000..5a186fad --- /dev/null +++ b/lib/src/telegram/models/paid_media_video.dart @@ -0,0 +1,31 @@ +part of 'models.dart'; + +/// The paid media is a video. +class PaidMediaVideo extends PaidMedia { + @override + PaidMediaType get type => PaidMediaType.video; + + /// The video. + final Video video; + + /// Constructs a [PaidMediaVideo] object. + const PaidMediaVideo({ + required this.video, + }); + + /// Creates a [PaidMediaVideo] object from JSON. + factory PaidMediaVideo.fromJson(Map json) { + return PaidMediaVideo( + video: Video.fromJson(json['video']), + ); + } + + /// Converts a [PaidMediaVideo] object to JSON. + @override + Map toJson() { + return { + 'type': type, + 'video': video.toJson(), + }; + } +} diff --git a/lib/src/telegram/models/transaction_partner_telegram_ads.dart b/lib/src/telegram/models/transaction_partner_telegram_ads.dart new file mode 100644 index 00000000..56a87e09 --- /dev/null +++ b/lib/src/telegram/models/transaction_partner_telegram_ads.dart @@ -0,0 +1,23 @@ +part of 'models.dart'; + +/// Describes a withdrawal transaction to the Telegram Ads platform. +class TransactionPartnerTelegramAds extends TransactionPartner { + @override + TransactionPartnerType get type => TransactionPartnerType.telegramAds; + + /// Constructs a [TransactionPartnerTelegramAds] object. + const TransactionPartnerTelegramAds(); + + /// Creates a [TransactionPartnerTelegramAds] object from JSON. + factory TransactionPartnerTelegramAds.fromJson(Map json) { + return TransactionPartnerTelegramAds(); + } + + /// Converts a [TransactionPartnerTelegramAds] object to JSON. + @override + Map toJson() { + return { + 'type': type.toJson(), + }; + } +} diff --git a/lib/src/telegram/models/transaction_partner_user.dart b/lib/src/telegram/models/transaction_partner_user.dart index 38a970e4..a7b0d44d 100644 --- a/lib/src/telegram/models/transaction_partner_user.dart +++ b/lib/src/telegram/models/transaction_partner_user.dart @@ -8,15 +8,20 @@ class TransactionPartnerUser extends TransactionPartner { /// Information about the user. final User user; + /// Bot-specified invoice payload. + final String? invoicePayload; + /// Constructs a [TransactionPartnerUser] object. const TransactionPartnerUser({ required this.user, + this.invoicePayload, }); /// Creates a [TransactionPartnerUser] object from JSON. factory TransactionPartnerUser.fromJson(Map json) { return TransactionPartnerUser( user: User.fromJson(json['user']), + invoicePayload: json['invoice_payload'], ); } @@ -24,8 +29,9 @@ class TransactionPartnerUser extends TransactionPartner { @override Map toJson() { return { - 'type': type, + 'type': type.toJson(), 'user': user.toJson(), - }; + 'invoice_payload': invoicePayload, + }..removeWhere(_nullFilter); } } diff --git a/lib/src/televerse/api/raw_api.dart b/lib/src/televerse/api/raw_api.dart index 95beaee7..e1af6b87 100644 --- a/lib/src/televerse/api/raw_api.dart +++ b/lib/src/televerse/api/raw_api.dart @@ -3938,4 +3938,53 @@ class RawAPI { return StarTransactions.fromJson(response); } + + /// Use this method to send paid media to channel chats. + /// On success, the sent Message is returned. + Future sendPaidMedia( + ID chatId, + int starCount, + List media, { + String? caption, + String? parseMode, + List? captionEntities, + bool? showCaptionAboveMedia, + bool? disableNotification, + bool? protectContent, + ReplyParameters? replyParameters, + ReplyMarkup? replyMarkup, + }) async { + final params = { + "chat_id": chatId.id, + "star_count": starCount, + "caption": caption, + "parse_mode": parseMode, + "caption_entities": captionEntities?.map((e) => e.toJson()).toList(), + "show_caption_above_media": showCaptionAboveMedia, + "disable_notification": disableNotification, + "protect_content": protectContent, + "reply_parameters": replyParameters?.toJson(), + "reply_markup": replyMarkup?.toJson(), + }; + + List<_MultipartHelper> helpers = []; + List> mediaList = []; + final length = media.length; + + for (int i = 0; i < length; i++) { + final m = media[i]; + mediaList.add(m.toJson()); + helpers.add(_MultipartHelper(m.media, "media$i")); + } + + final files = _getFiles(helpers); + params["media"] = mediaList; + + final response = await _makeApiCall>( + APIMethod.sendPaidMedia, + payload: Payload(params, files), + ); + + return Message.fromJson(response); + } } diff --git a/lib/src/televerse/bot/bot.dart b/lib/src/televerse/bot/bot.dart index a5ea34ce..bcd9e68c 100644 --- a/lib/src/televerse/bot/bot.dart +++ b/lib/src/televerse/bot/bot.dart @@ -2637,4 +2637,70 @@ class Bot { _handlerScopes.removeAt(ix); return true; } + + /// Registers a callback for whenever paid media is received. + void onPaidMedia( + Handler callback, { + bool includeChannelPosts = false, + bool onlyChannelPosts = false, + ID? chatId, + ScopeOptions? options, + }) { + return _internalSubMessageHandler( + callback, + (ctx) { + return ctx.msg?.paidMedia != null; + }, + includeChannelPosts: includeChannelPosts, + onlyChannelPosts: onlyChannelPosts, + chatId: chatId, + options: options, + ); + } + + /// Registers a callback for whenever paid media video is received. + void onPaidMediaVideo( + Handler callback, { + bool includeChannelPosts = false, + bool onlyChannelPosts = false, + ID? chatId, + ScopeOptions? options, + }) { + return _internalSubMessageHandler( + callback, + (ctx) { + return ctx.msg?.paidMedia != null && + ctx.msg!.paidMedia!.paidMedia.any( + (media) => media is PaidMediaVideo, + ); + }, + includeChannelPosts: includeChannelPosts, + onlyChannelPosts: onlyChannelPosts, + chatId: chatId, + options: options, + ); + } + + /// Registers a callback for whenever paid media photo is received. + void onPaidMediaPhoto( + Handler callback, { + bool includeChannelPosts = false, + bool onlyChannelPosts = false, + ID? chatId, + ScopeOptions? options, + }) { + return _internalSubMessageHandler( + callback, + (ctx) { + return ctx.msg?.paidMedia?.paidMedia != null && + ctx.msg!.paidMedia!.paidMedia.any( + (media) => media is PaidMediaPhoto, + ); + }, + includeChannelPosts: includeChannelPosts, + onlyChannelPosts: onlyChannelPosts, + chatId: chatId, + options: options, + ); + } } diff --git a/lib/src/televerse/context/methods.dart b/lib/src/televerse/context/methods.dart index 9c188491..a9097588 100644 --- a/lib/src/televerse/context/methods.dart +++ b/lib/src/televerse/context/methods.dart @@ -1848,4 +1848,38 @@ extension ContextAwareMethods on Context { languageCode: languageCode, ); } + + /// Sends paid media to a specified chat. + Future replyWithPaidMedia( + int starCount, + List media, { + String? caption, + String? parseMode, + List? captionEntities, + bool? showCaptionAboveMedia, + bool? disableNotification, + bool? protectContent, + ReplyParameters? replyParameters, + ReplyMarkup? replyMarkup, + }) async { + api._addContext(this); + _verifyInfo( + [_chatId], + APIMethod.sendPaidMedia, + ); + + return api.sendPaidMedia( + id, + starCount, + media, + caption: caption, + parseMode: parseMode, + captionEntities: captionEntities, + showCaptionAboveMedia: showCaptionAboveMedia, + disableNotification: disableNotification, + protectContent: protectContent, + replyParameters: replyParameters, + replyMarkup: replyMarkup, + ); + } } diff --git a/lib/src/types/input_paid_media_type.dart b/lib/src/types/input_paid_media_type.dart new file mode 100644 index 00000000..11f9ed6f --- /dev/null +++ b/lib/src/types/input_paid_media_type.dart @@ -0,0 +1,27 @@ +part of 'types.dart'; + +/// This object represents the type of the input paid media. +enum InputPaidMediaType { + /// Represents a photo paid media. + photo("photo"), + + /// Represents a video paid media. + video("video"), + ; + + /// The value of this enum. + final String value; + + /// Constructs a new [InputPaidMediaType]. + const InputPaidMediaType(this.value); + + /// Constructs a new [InputPaidMediaType] from a [String]. + static InputPaidMediaType fromJson(String value) { + return InputPaidMediaType.values.firstWhere((e) => e.value == value); + } + + /// Converts this [InputPaidMediaType] to a [String]. + String toJson() { + return value; + } +} diff --git a/lib/src/types/methods.dart b/lib/src/types/methods.dart index eeafcfb9..7c75dd28 100644 --- a/lib/src/types/methods.dart +++ b/lib/src/types/methods.dart @@ -376,6 +376,9 @@ enum APIMethod { /// Returns the bot's Telegram Star transactions in chronological order getStarTransactions._("getStarTransactions"), + + /// Sends paid media + sendPaidMedia._("sendPaidMedia"), ; /// The name of the method. @@ -418,6 +421,7 @@ enum APIMethod { APIMethod.sendChatAction, APIMethod.sendSticker, APIMethod.sendGame, + APIMethod.sendPaidMedia, ]; } diff --git a/lib/src/types/paid_media_type.dart b/lib/src/types/paid_media_type.dart new file mode 100644 index 00000000..887923d8 --- /dev/null +++ b/lib/src/types/paid_media_type.dart @@ -0,0 +1,30 @@ +part of 'types.dart'; + +/// This object represents the type of the paid media. +enum PaidMediaType { + /// Represents a preview of paid media. + preview("preview"), + + /// Represents a photo paid media. + photo("photo"), + + /// Represents a video paid media. + video("video"), + ; + + /// The value of this enum. + final String value; + + /// Constructs a new [PaidMediaType]. + const PaidMediaType(this.value); + + /// Constructs a new [PaidMediaType] from a [String]. + static PaidMediaType fromJson(String value) { + return PaidMediaType.values.firstWhere((e) => e.value == value); + } + + /// Converts this [PaidMediaType] to a [String]. + String toJson() { + return value; + } +} diff --git a/lib/src/types/transaction_partner_type.dart b/lib/src/types/transaction_partner_type.dart index 73c68579..c10996a9 100644 --- a/lib/src/types/transaction_partner_type.dart +++ b/lib/src/types/transaction_partner_type.dart @@ -8,6 +8,9 @@ enum TransactionPartnerType { /// Represents a transaction with a user. user("user"), + /// Represents a withdrawal transaction to the Telegram Ads platform. + telegramAds("telegram_ads"), + /// Represents a transaction with an unknown source or recipient. other("other"), ; diff --git a/lib/src/types/types.dart b/lib/src/types/types.dart index 8f7d2cac..5cd70355 100644 --- a/lib/src/types/types.dart +++ b/lib/src/types/types.dart @@ -31,3 +31,5 @@ part 'background_fill_type.dart'; part 'background_type_type.dart'; part 'transaction_partner_type.dart'; part 'revenue_withdrawal_state_type.dart'; +part 'paid_media_type.dart'; +part 'input_paid_media_type.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 3bfa8b71..d43ef541 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: televerse -description: Televerse lets you create your own efficient Telegram bots with ease in Dart. Supports latest Telegram Bot API - 7.5! -version: 1.20.0 +description: Televerse lets you create your own efficient Telegram bots with ease in Dart. Supports latest Telegram Bot API - 7.6! +version: 1.21.0 homepage: https://github.com/HeySreelal/televerse topics: - telegram