diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index a5f2863c5..48e0c36ae 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2789,7 +2789,7 @@ inputInvoiceName name:string = InputInvoice; inputInvoiceTelegram purpose:TelegramPaymentPurpose = InputInvoice; -//@class MessageExtendedMedia @description Describes a media, which is attached to an invoice +//@class MessageExtendedMedia @description Describes a paid media //@description The media is hidden until the invoice is paid //@width Media width; 0 if unknown @@ -3490,6 +3490,27 @@ textEntityTypeMediaTimestamp media_timestamp:int32 = TextEntityType; inputThumbnail thumbnail:InputFile width:int32 height:int32 = InputThumbnail; +//@class InputMessageExtendedMediaType @description Describes type of paid media to sent + +//@description The media is a photo. The photo must be at most 10 MB in size. The photo's width and height must not exceed 10000 in total. Width and height ratio must be at most 20 +inputMessageExtendedMediaTypePhoto = InputMessageExtendedMediaType; + +//@description The media is a video +//@duration Duration of the video, in seconds +//@supports_streaming True, if the video is supposed to be streamed +inputMessageExtendedMediaTypeVideo duration:int32 supports_streaming:Bool = InputMessageExtendedMediaType; + + +//@description Describes a paid media to be sent +//@type Type of the media +//@media Photo or video to be sent +//@thumbnail Media thumbnail; pass null to skip thumbnail uploading +//@added_sticker_file_ids File identifiers of the stickers added to the media, if applicable +//@width Media width +//@height Media height +inputMessageExtendedMedia type:InputMessageExtendedMediaType media:InputFile thumbnail:inputThumbnail added_sticker_file_ids:vector width:int32 height:int32 = InputMessageExtendedMedia; + + //@class MessageSchedulingState @description Contains information about the time when a scheduled message will be sent //@description The message will be sent at the specified date @send_date Point in time (Unix timestamp) when the message will be sent. The date must be within 367 days in the future @@ -3645,8 +3666,9 @@ inputMessageGame bot_user_id:int53 game_short_name:string = InputMessageContent; //@provider_token Payment provider token; may be empty for payments in Telegram Stars //@provider_data JSON-encoded data about the invoice, which will be shared with the payment provider //@start_parameter Unique invoice bot deep link parameter for the generation of this invoice. If empty, it would be possible to pay directly from forwards of the invoice message -//@extended_media_content The content of extended media attached to the invoice. The content of the message to be sent. Must be one of the following types: inputMessagePhoto, inputMessageVideo -inputMessageInvoice invoice:invoice title:string description:string photo_url:string photo_size:int32 photo_width:int32 photo_height:int32 payload:bytes provider_token:string provider_data:string start_parameter:string extended_media_content:InputMessageContent = InputMessageContent; +//@paid_media The content of paid media attached to the invoice; pass null if none +//@paid_media_caption Paid media caption; pass null to use an empty caption; 0-getOption("message_caption_length_max") characters +inputMessageInvoice invoice:invoice title:string description:string photo_url:string photo_size:int32 photo_width:int32 photo_height:int32 payload:bytes provider_token:string provider_data:string start_parameter:string paid_media:inputMessageExtendedMedia paid_media_caption:formattedText = InputMessageContent; //@description A message with a poll. Polls can't be sent to secret chats. Polls can be sent only to a private chat with a bot //@question Poll question; 1-255 characters (up to 300 characters for bots). Only custom emoji entities are allowed to be added and only by Premium users diff --git a/td/telegram/InlineQueriesManager.cpp b/td/telegram/InlineQueriesManager.cpp index bdbff723f..ca3ca1591 100644 --- a/td/telegram/InlineQueriesManager.cpp +++ b/td/telegram/InlineQueriesManager.cpp @@ -391,7 +391,7 @@ Result> InlineQueriesManager: } if (constructor_id == td_api::inputMessageInvoice::ID) { TRY_RESULT(input_invoice, - InputInvoice::process_input_message_invoice(std::move(input_message_content), td_, DialogId(), false)); + InputInvoice::process_input_message_invoice(std::move(input_message_content), td_, DialogId())); return input_invoice.get_input_bot_inline_message_media_invoice(std::move(input_reply_markup), td_); } if (constructor_id == td_api::inputMessageLocation::ID) { diff --git a/td/telegram/InputInvoice.cpp b/td/telegram/InputInvoice.cpp index 10cb7697f..62555b8c5 100644 --- a/td/telegram/InputInvoice.cpp +++ b/td/telegram/InputInvoice.cpp @@ -6,6 +6,7 @@ // #include "td/telegram/InputInvoice.h" +#include "td/telegram/AuthManager.h" #include "td/telegram/Dimensions.h" #include "td/telegram/files/FileManager.h" #include "td/telegram/files/FileType.h" @@ -100,8 +101,7 @@ InputInvoice::InputInvoice(tl_object_ptr InputInvoice::process_input_message_invoice( - td_api::object_ptr &&input_message_content, Td *td, DialogId owner_dialog_id, - bool is_premium) { + td_api::object_ptr &&input_message_content, Td *td, DialogId owner_dialog_id) { CHECK(input_message_content != nullptr); CHECK(input_message_content->get_id() == td_api::inputMessageInvoice::ID); auto input_invoice = move_tl_object_as(input_message_content); @@ -230,16 +230,21 @@ Result InputInvoice::process_input_message_invoice( result.provider_token_ = std::move(input_invoice->provider_token_); result.provider_data_ = std::move(input_invoice->provider_data_); - TRY_RESULT(extended_media, MessageExtendedMedia::get_message_extended_media( - td, std::move(input_invoice->extended_media_content_), owner_dialog_id, is_premium)); + bool is_bot = td->auth_manager_->is_bot(); + TRY_RESULT(extended_media_caption, + get_formatted_text(td, owner_dialog_id, std::move(input_invoice->paid_media_caption_), is_bot, true, false, + false)); + TRY_RESULT(extended_media, + MessageExtendedMedia::get_message_extended_media(td, std::move(input_invoice->paid_media_), + std::move(extended_media_caption), owner_dialog_id)); result.extended_media_ = std::move(extended_media); return result; } -tl_object_ptr InputInvoice::get_message_invoice_object(Td *td, bool skip_bot_commands, - int32 max_media_timestamp) const { - return make_tl_object( +td_api::object_ptr InputInvoice::get_message_invoice_object(Td *td, bool skip_bot_commands, + int32 max_media_timestamp) const { + return td_api::make_object( get_product_info_object(td, title_, description_, photo_), invoice_.currency_, total_amount_, start_parameter_, invoice_.is_test_, invoice_.need_shipping_address_, receipt_message_id_.get(), extended_media_.get_message_extended_media_object(td), diff --git a/td/telegram/InputInvoice.h b/td/telegram/InputInvoice.h index 88059294d..975d829b3 100644 --- a/td/telegram/InputInvoice.h +++ b/td/telegram/InputInvoice.h @@ -79,11 +79,10 @@ class InputInvoice { DialogId owner_dialog_id); static Result process_input_message_invoice( - td_api::object_ptr &&input_message_content, Td *td, DialogId owner_dialog_id, - bool is_premium); + td_api::object_ptr &&input_message_content, Td *td, DialogId owner_dialog_id); - tl_object_ptr get_message_invoice_object(Td *td, bool skip_bot_commands, - int32 max_media_timestamp) const; + td_api::object_ptr get_message_invoice_object(Td *td, bool skip_bot_commands, + int32 max_media_timestamp) const; tl_object_ptr get_input_media_invoice( Td *td, tl_object_ptr input_file, diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 300151d9e..509fc6ec5 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -2758,7 +2758,7 @@ static Result create_input_message_content( bool has_stickers = !sticker_file_ids.empty(); td->animations_manager_->create_animation( - file_id, string(), thumbnail, AnimationSize(), has_stickers, std::move(sticker_file_ids), + file_id, string(), std::move(thumbnail), AnimationSize(), has_stickers, std::move(sticker_file_ids), std::move(file_name), std::move(mime_type), input_animation->duration_, get_dimensions(input_animation->width_, input_animation->height_, nullptr), false); @@ -2775,8 +2775,8 @@ static Result create_input_message_content( return Status::Error(400, "Audio performer must be encoded in UTF-8"); } - td->audios_manager_->create_audio(file_id, string(), thumbnail, std::move(file_name), std::move(mime_type), - input_audio->duration_, std::move(input_audio->title_), + td->audios_manager_->create_audio(file_id, string(), std::move(thumbnail), std::move(file_name), + std::move(mime_type), input_audio->duration_, std::move(input_audio->title_), std::move(input_audio->performer_), 0, false); content = make_unique(file_id, std::move(caption)); @@ -2792,8 +2792,8 @@ static Result create_input_message_content( break; } case td_api::inputMessageDocument::ID: - td->documents_manager_->create_document(file_id, string(), thumbnail, std::move(file_name), std::move(mime_type), - false); + td->documents_manager_->create_document(file_id, string(), std::move(thumbnail), std::move(file_name), + std::move(mime_type), false); content = make_unique(file_id, std::move(caption)); break; @@ -2815,7 +2815,7 @@ static Result create_input_message_content( emoji = std::move(input_sticker->emoji_); - td->stickers_manager_->create_sticker(file_id, FileId(), string(), thumbnail, + td->stickers_manager_->create_sticker(file_id, FileId(), string(), std::move(thumbnail), get_dimensions(input_sticker->width_, input_sticker->height_, nullptr), nullptr, nullptr, StickerFormat::Unknown, nullptr); @@ -2829,7 +2829,7 @@ static Result create_input_message_content( self_destruct_type = std::move(input_video->self_destruct_type_); bool has_stickers = !sticker_file_ids.empty(); - td->videos_manager_->create_video(file_id, string(), thumbnail, AnimationSize(), has_stickers, + td->videos_manager_->create_video(file_id, string(), std::move(thumbnail), AnimationSize(), has_stickers, std::move(sticker_file_ids), std::move(file_name), std::move(mime_type), input_video->duration_, input_video->duration_, get_dimensions(input_video->width_, input_video->height_, nullptr), @@ -2847,7 +2847,7 @@ static Result create_input_message_content( return Status::Error(400, "Wrong video note length"); } - td->video_notes_manager_->create_video_note(file_id, string(), thumbnail, input_video_note->duration_, + td->video_notes_manager_->create_video_note(file_id, string(), std::move(thumbnail), input_video_note->duration_, get_dimensions(length, length, nullptr), string(), false); content = make_unique(file_id, false); @@ -2898,8 +2898,8 @@ static Result create_input_message_content( return Status::Error(400, "Invoices can be sent only by bots"); } - TRY_RESULT(input_invoice, InputInvoice::process_input_message_invoice(std::move(input_message_content), td, - dialog_id, is_premium)); + TRY_RESULT(input_invoice, + InputInvoice::process_input_message_invoice(std::move(input_message_content), td, dialog_id)); content = make_unique(std::move(input_invoice)); break; } diff --git a/td/telegram/MessageExtendedMedia.cpp b/td/telegram/MessageExtendedMedia.cpp index 68bdabf02..50633bc12 100644 --- a/td/telegram/MessageExtendedMedia.cpp +++ b/td/telegram/MessageExtendedMedia.cpp @@ -6,17 +6,23 @@ // #include "td/telegram/MessageExtendedMedia.h" +#include "td/telegram/Dimensions.h" #include "td/telegram/Document.h" #include "td/telegram/DocumentsManager.h" +#include "td/telegram/files/FileManager.h" #include "td/telegram/MessageContent.h" #include "td/telegram/MessageContentType.h" +#include "td/telegram/Photo.h" #include "td/telegram/PhotoSize.h" +#include "td/telegram/StickersManager.h" #include "td/telegram/Td.h" #include "td/telegram/telegram_api.h" #include "td/telegram/VideosManager.h" #include "td/utils/algorithm.h" #include "td/utils/logging.h" +#include "td/utils/MimeType.h" +#include "td/utils/PathView.h" namespace td { @@ -108,36 +114,69 @@ void MessageExtendedMedia::init_from_media(Td *td, telegram_api::object_ptr MessageExtendedMedia::get_message_extended_media( - Td *td, td_api::object_ptr &&extended_media_content, DialogId owner_dialog_id, - bool is_premium) { - if (extended_media_content == nullptr) { + Td *td, td_api::object_ptr &&paid_media, FormattedText &&caption, + DialogId owner_dialog_id) { + if (paid_media == nullptr) { return MessageExtendedMedia(); } if (!owner_dialog_id.is_valid()) { return Status::Error(400, "Extended media can't be added to the invoice"); } - - auto input_content_type = extended_media_content->get_id(); - if (input_content_type != td_api::inputMessagePhoto::ID && input_content_type != td_api::inputMessageVideo::ID) { - return Status::Error("Invalid extended media content specified"); - } - TRY_RESULT(input_message_content, - get_input_message_content(owner_dialog_id, std::move(extended_media_content), td, is_premium)); - if (!input_message_content.ttl.is_empty()) { - return Status::Error("Can't use self-destructing extended media"); + if (paid_media->type_ == nullptr) { + return Status::Error(400, "Paid media type must be non-empty"); } - auto content = input_message_content.content.get(); - auto content_type = content->get_type(); MessageExtendedMedia result; - CHECK(content_type == MessageContentType::Photo || content_type == MessageContentType::Video); - result.caption_ = *get_message_content_caption(content); - if (content_type == MessageContentType::Photo) { - result.type_ = Type::Photo; - result.photo_ = *get_message_content_photo(content); - } else { - result.type_ = Type::Video; - result.video_file_id_ = get_message_content_upload_file_id(content); + result.caption_ = std::move(caption); + + auto file_type = FileType::None; + switch (paid_media->type_->get_id()) { + case td_api::inputMessageExtendedMediaTypePhoto::ID: + file_type = FileType::Photo; + result.type_ = Type::Photo; + break; + case td_api::inputMessageExtendedMediaTypeVideo::ID: + file_type = FileType::Video; + result.type_ = Type::Video; + break; + default: + UNREACHABLE(); + break; + } + + TRY_RESULT(file_id, td->file_manager_->get_input_file_id(file_type, std::move(paid_media->media_), owner_dialog_id, + false, false)); + CHECK(file_id.is_valid()); + + auto sticker_file_ids = td->stickers_manager_->get_attached_sticker_file_ids(paid_media->added_sticker_file_ids_); + auto thumbnail = + get_input_thumbnail_photo_size(td->file_manager_.get(), paid_media->thumbnail_.get(), owner_dialog_id, false); + + switch (result.type_) { + case Type::Photo: { + TRY_RESULT(photo, create_photo(td->file_manager_.get(), file_id, std::move(thumbnail), paid_media->width_, + paid_media->height_, std::move(sticker_file_ids))); + result.photo_ = std::move(photo); + break; + } + case Type::Video: { + auto type = static_cast(paid_media->type_.get()); + FileView file_view = td->file_manager_->get_file_view(file_id); + auto suggested_path = file_view.suggested_path(); + const PathView path_view(suggested_path); + string file_name = path_view.file_name().str(); + string mime_type = MimeType::from_extension(path_view.extension()); + + bool has_stickers = !sticker_file_ids.empty(); + td->videos_manager_->create_video( + file_id, string(), std::move(thumbnail), AnimationSize(), has_stickers, std::move(sticker_file_ids), + std::move(file_name), std::move(mime_type), type->duration_, type->duration_, + get_dimensions(paid_media->width_, paid_media->height_, nullptr), type->supports_streaming_, false, 0, false); + result.video_file_id_ = file_id; + break; + } + default: + UNREACHABLE(); } return result; } diff --git a/td/telegram/MessageExtendedMedia.h b/td/telegram/MessageExtendedMedia.h index 3da3788d8..574b14391 100644 --- a/td/telegram/MessageExtendedMedia.h +++ b/td/telegram/MessageExtendedMedia.h @@ -59,8 +59,8 @@ class MessageExtendedMedia { MessageExtendedMedia(Td *td, telegram_api::object_ptr &&media, DialogId owner_dialog_id); static Result get_message_extended_media( - Td *td, td_api::object_ptr &&extended_media_content, DialogId owner_dialog_id, - bool is_premium); + Td *td, td_api::object_ptr &&paid_media, FormattedText &&caption, + DialogId owner_dialog_id); bool is_empty() const { return type_ == Type::Empty; diff --git a/td/telegram/Payments.cpp b/td/telegram/Payments.cpp index 0a533013d..332d6e9a4 100644 --- a/td/telegram/Payments.cpp +++ b/td/telegram/Payments.cpp @@ -1125,7 +1125,7 @@ void export_invoice(Td *td, td_api::object_ptr &&in return promise.set_error(Status::Error(400, "Invoice must be non-empty")); } TRY_RESULT_PROMISE(promise, input_invoice, - InputInvoice::process_input_message_invoice(std::move(invoice), td, DialogId(), false)); + InputInvoice::process_input_message_invoice(std::move(invoice), td, DialogId())); auto input_media = input_invoice.get_input_media_invoice(td, nullptr, nullptr); CHECK(input_media != nullptr); td->create_handler(std::move(promise))->send(std::move(input_media));