diff --git a/td/generate/scheme/telegram_api.tl b/td/generate/scheme/telegram_api.tl index afc258b1..c6bf83d4 100644 --- a/td/generate/scheme/telegram_api.tl +++ b/td/generate/scheme/telegram_api.tl @@ -580,7 +580,7 @@ inputBotInlineMessageMediaVenue#aaafadc8 flags:# geo_point:InputGeoPoint title:s inputBotInlineMessageMediaContact#2daf01a7 flags:# phone_number:string first_name:string last_name:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage; inputBotInlineMessageGame#4b425864 flags:# reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage; -inputBotInlineResult#2cbbe15a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb_url:flags.4?string content_url:flags.5?string content_type:flags.5?string w:flags.6?int h:flags.6?int duration:flags.7?int send_message:InputBotInlineMessage = InputBotInlineResult; +inputBotInlineResult#88bf9319 flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?InputWebDocument content:flags.5?InputWebDocument send_message:InputBotInlineMessage = InputBotInlineResult; inputBotInlineResultPhoto#a8d864a7 id:string type:string photo:InputPhoto send_message:InputBotInlineMessage = InputBotInlineResult; inputBotInlineResultDocument#fff8fdc4 flags:# id:string type:string title:flags.1?string description:flags.2?string document:InputDocument send_message:InputBotInlineMessage = InputBotInlineResult; inputBotInlineResultGame#4fa417f2 id:string short_name:string send_message:InputBotInlineMessage = InputBotInlineResult; @@ -591,7 +591,7 @@ botInlineMessageMediaGeo#b722de65 flags:# geo:GeoPoint period:int reply_markup:f botInlineMessageMediaVenue#4366232e flags:# geo:GeoPoint title:string address:string provider:string venue_id:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage; botInlineMessageMediaContact#35edb4d4 flags:# phone_number:string first_name:string last_name:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage; -botInlineResult#9bebaeb9 flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb_url:flags.4?string content_url:flags.5?string content_type:flags.5?string w:flags.6?int h:flags.6?int duration:flags.7?int send_message:BotInlineMessage = BotInlineResult; +botInlineResult#11965f3a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?WebDocument content:flags.5?WebDocument send_message:BotInlineMessage = BotInlineResult; botInlineMediaResult#17db940b flags:# id:string type:string photo:flags.0?Photo document:flags.1?Document title:flags.2?string description:flags.3?string send_message:BotInlineMessage = BotInlineResult; messages.botResults#947ca848 flags:# gallery:flags.0?true query_id:long next_offset:flags.1?string switch_pm:flags.2?InlineBotSwitchPM results:Vector cache_time:int users:Vector = messages.BotResults; @@ -722,6 +722,7 @@ paymentRequestedInfo#909c3f94 flags:# name:flags.0?string phone:flags.1?string e paymentSavedCredentialsCard#cdc27a1f id:string title:string = PaymentSavedCredentials; webDocument#c61acbd8 url:string access_hash:long size:int mime_type:string attributes:Vector dc_id:int = WebDocument; +webDocumentNoProxy#f9c8bcc6 url:string size:int mime_type:string attributes:Vector = WebDocument; inputWebDocument#9bed434d url:string size:int mime_type:string attributes:Vector = InputWebDocument; @@ -866,7 +867,7 @@ auth.resendCode#3ef1a9bf phone_number:string phone_code_hash:string = auth.SentC auth.cancelCode#1f040578 phone_number:string phone_code_hash:string = Bool; auth.dropTempAuthKeys#8e48a188 except_auth_keys:Vector = Bool; -account.registerDevice#1389cc token_type:int token:string app_sandbox:Bool other_uids:Vector = Bool; +account.registerDevice#5cbea590 token_type:int token:string app_sandbox:Bool secret:bytes other_uids:Vector = Bool; account.unregisterDevice#3076c4bf token_type:int token:string other_uids:Vector = Bool; account.updateNotifySettings#84be5b93 peer:InputNotifyPeer settings:InputPeerNotifySettings = Bool; account.getNotifySettings#12b3ad31 peer:InputNotifyPeer = PeerNotifySettings; diff --git a/td/generate/scheme/telegram_api.tlo b/td/generate/scheme/telegram_api.tlo index c1372d02..2198dce3 100644 Binary files a/td/generate/scheme/telegram_api.tlo and b/td/generate/scheme/telegram_api.tlo differ diff --git a/td/telegram/DeviceTokenManager.cpp b/td/telegram/DeviceTokenManager.cpp index 88eacfc5..8935c040 100644 --- a/td/telegram/DeviceTokenManager.cpp +++ b/td/telegram/DeviceTokenManager.cpp @@ -328,7 +328,7 @@ void DeviceTokenManager::loop() { create_storer(telegram_api::account_unregisterDevice(token_type, info.token, std::move(other_user_ids)))); } else { net_query = G()->net_query_creator().create(create_storer(telegram_api::account_registerDevice( - token_type, info.token, info.is_app_sandbox, std::move(other_user_ids)))); + token_type, info.token, info.is_app_sandbox, BufferSlice(), std::move(other_user_ids)))); } info.net_query_id = net_query->id(); G()->net_query_dispatcher().dispatch_with_callback(std::move(net_query), actor_shared(this, token_type)); diff --git a/td/telegram/DocumentsManager.cpp b/td/telegram/DocumentsManager.cpp index f0eca601..bbe567a3 100644 --- a/td/telegram/DocumentsManager.cpp +++ b/td/telegram/DocumentsManager.cpp @@ -23,10 +23,12 @@ #include "td/utils/common.h" #include "td/utils/format.h" +#include "td/utils/HttpUrl.h" #include "td/utils/logging.h" #include "td/utils/MimeType.h" #include "td/utils/misc.h" #include "td/utils/PathView.h" +#include "td/utils/Random.h" #include "td/utils/Slice.h" #include "td/utils/StackAllocator.h" #include "td/utils/Status.h" @@ -34,6 +36,7 @@ #include "td/utils/utf8.h" #include +#include namespace td { @@ -55,7 +58,8 @@ tl_object_ptr DocumentsManager::get_document_object(FileId fil } std::pair DocumentsManager::on_get_document( - RemoteDocument remote_document, DialogId owner_dialog_id, MultiPromiseActor *load_data_multipromise_ptr) { + RemoteDocument remote_document, DialogId owner_dialog_id, MultiPromiseActor *load_data_multipromise_ptr, + DocumentType default_document_type) { tl_object_ptr animated; tl_object_ptr video; tl_object_ptr audio; @@ -121,17 +125,22 @@ std::pair DocumentsManager::on_get_docum sticker = nullptr; } - auto document_type = DocumentType::General; + auto document_type = default_document_type; FileType file_type = FileType::Document; Slice default_extension; bool supports_streaming = false; - if (type_attributes == 1) { // not a general document - if (animated != nullptr) { + if (type_attributes == 1 || default_document_type != DocumentType::General) { // not a general document + if (animated != nullptr || default_document_type == DocumentType::Animation) { document_type = DocumentType::Animation; file_type = FileType::Animation; default_extension = "mp4"; - } else if (audio != nullptr) { - if ((audio->flags_ & telegram_api::documentAttributeAudio::Flags::VOICE_MASK) != 0) { + } else if (audio != nullptr || default_document_type == DocumentType::Audio || + default_document_type == DocumentType::VoiceNote) { + bool is_voice_note = default_document_type == DocumentType::VoiceNote; + if (audio != nullptr) { + is_voice_note = (audio->flags_ & telegram_api::documentAttributeAudio::Flags::VOICE_MASK) != 0; + } + if (is_voice_note) { document_type = DocumentType::VoiceNote; file_type = FileType::VoiceNote; default_extension = "oga"; @@ -141,21 +150,28 @@ std::pair DocumentsManager::on_get_docum file_type = FileType::Audio; default_extension = "mp3"; } - } else if (sticker != nullptr) { + } else if (sticker != nullptr || default_document_type == DocumentType::Sticker) { document_type = DocumentType::Sticker; file_type = FileType::Sticker; default_extension = "webp"; owner_dialog_id = DialogId(); file_name.clear(); - } else if (video != nullptr) { - if ((video->flags_ & telegram_api::documentAttributeVideo::ROUND_MESSAGE_MASK) != 0) { + } else if (video != nullptr || default_document_type == DocumentType::Video || + default_document_type == DocumentType::VideoNote) { + bool is_video_note = default_document_type == DocumentType::VideoNote; + if (video != nullptr) { + is_video_note = (video->flags_ & telegram_api::documentAttributeVideo::ROUND_MESSAGE_MASK) != 0; + if (!is_video_note) { + supports_streaming = (video->flags_ & telegram_api::documentAttributeVideo::SUPPORTS_STREAMING_MASK) != 0; + } + } + if (is_video_note) { document_type = DocumentType::VideoNote; file_type = FileType::VideoNote; file_name.clear(); } else { document_type = DocumentType::Video; file_type = FileType::Video; - supports_streaming = (video->flags_ & telegram_api::documentAttributeVideo::SUPPORTS_STREAMING_MASK) != 0; } default_extension = "mp4"; } @@ -173,6 +189,9 @@ std::pair DocumentsManager::on_get_docum string mime_type; PhotoSize thumbnail; FileEncryptionKey encryption_key; + bool is_web = false; + bool is_web_no_proxy = false; + string url; if (remote_document.document != nullptr) { auto document = std::move(remote_document.document); @@ -186,8 +205,7 @@ std::pair DocumentsManager::on_get_docum thumbnail = get_photo_size(td_->file_manager_.get(), FileType::Thumbnail, 0, 0, owner_dialog_id, std::move(document->thumb_)); } - } else { - CHECK(remote_document.secret_file != nullptr); + } else if (remote_document.secret_file != nullptr) { CHECK(remote_document.secret_document != nullptr); auto file = std::move(remote_document.secret_file); auto document = std::move(remote_document.secret_document); @@ -207,10 +225,54 @@ std::pair DocumentsManager::on_get_docum thumbnail = get_thumbnail_photo_size(td_->file_manager_.get(), std::move(document->thumb_), owner_dialog_id, document->thumb_w_, document->thumb_h_); } + } else { + is_web = true; + id = Random::fast(0, std::numeric_limits::max()); + dc_id = 0; + access_hash = 0; + thumbnail = std::move(remote_document.thumbnail); + + auto web_document_ptr = std::move(remote_document.web_document); + switch (web_document_ptr->get_id()) { + case telegram_api::webDocument::ID: { + auto web_document = move_tl_object_as(web_document_ptr); + auto r_http_url = parse_url(web_document->url_); + if (r_http_url.is_error()) { + LOG(ERROR) << "Can't parse URL " << web_document->url_; + return {DocumentType::Unknown, FileId()}; + } + auto http_url = r_http_url.move_as_ok(); + + dc_id = web_document->dc_id_; + access_hash = web_document->access_hash_; + url = http_url.get_url(); + file_name = get_url_query_file_name(http_url.query_); + mime_type = std::move(web_document->mime_type_); + size = web_document->size_; + break; + } + case telegram_api::webDocumentNoProxy::ID: { + is_web_no_proxy = true; + auto web_document = move_tl_object_as(web_document_ptr); + + if (web_document->url_.find('.') == string::npos) { + LOG(ERROR) << "Receive invalid URL " << web_document->url_; + return {DocumentType::Unknown, FileId()}; + } + + url = std::move(web_document->url_); + file_name = get_url_file_name(url); + mime_type = std::move(web_document->mime_type_); + size = web_document->size_; + break; + } + default: + UNREACHABLE(); + } } LOG(DEBUG) << "Receive document with id = " << id << " of type " << static_cast(document_type); - if (!DcId::is_valid(dc_id)) { + if (!is_web_no_proxy && !DcId::is_valid(dc_id)) { LOG(ERROR) << "Wrong dc_id = " << dc_id; return {DocumentType::Unknown, FileId()}; } @@ -224,11 +286,26 @@ std::pair DocumentsManager::on_get_docum suggested_file_name += extension; } } - FileId file_id = td_->file_manager_->register_remote( - FullRemoteFileLocation(file_type, id, access_hash, DcId::internal(dc_id)), FileLocationSource::FromServer, - owner_dialog_id, size, 0, suggested_file_name); - if (!encryption_key.empty()) { - td_->file_manager_->set_encryption_key(file_id, std::move(encryption_key)); + + FileId file_id; + if (!is_web) { + file_id = td_->file_manager_->register_remote( + FullRemoteFileLocation(file_type, id, access_hash, DcId::internal(dc_id)), FileLocationSource::FromServer, + owner_dialog_id, size, 0, suggested_file_name); + if (!encryption_key.empty()) { + td_->file_manager_->set_encryption_key(file_id, std::move(encryption_key)); + } + } else if (!is_web_no_proxy) { + file_id = + td_->file_manager_->register_remote(FullRemoteFileLocation(file_type, url, access_hash, DcId::internal(dc_id)), + FileLocationSource::FromServer, owner_dialog_id, 0, size, file_name); + } else { + auto r_file_id = td_->file_manager_->from_persistent_id(url, file_type); + if (r_file_id.is_error()) { + LOG(ERROR) << "Can't register URL: " << r_file_id.error(); + return {DocumentType::Unknown, FileId()}; + } + file_id = r_file_id.move_as_ok(); } if (dimensions.width != 0 && thumbnail.dimensions.width != 0) { @@ -243,17 +320,17 @@ std::pair DocumentsManager::on_get_docum case DocumentType::Animation: // TODO use has_stickers td_->animations_manager_->create_animation(file_id, std::move(thumbnail), std::move(file_name), - std::move(mime_type), video_duration, dimensions, true); + std::move(mime_type), video_duration, dimensions, !is_web); break; case DocumentType::Audio: CHECK(audio != nullptr); td_->audios_manager_->create_audio(file_id, std::move(thumbnail), std::move(file_name), std::move(mime_type), audio->duration_, std::move(audio->title_), std::move(audio->performer_), - true); + !is_web); break; case DocumentType::General: td_->documents_manager_->create_document(file_id, std::move(thumbnail), std::move(file_name), - std::move(mime_type), true); + std::move(mime_type), !is_web); break; case DocumentType::Sticker: CHECK(sticker != nullptr); @@ -263,15 +340,15 @@ std::pair DocumentsManager::on_get_docum case DocumentType::Video: td_->videos_manager_->create_video(file_id, std::move(thumbnail), has_stickers, vector(), std::move(file_name), std::move(mime_type), video_duration, dimensions, - supports_streaming, true); + supports_streaming, !is_web); break; case DocumentType::VideoNote: - td_->video_notes_manager_->create_video_note(file_id, std::move(thumbnail), video_duration, dimensions, true); + td_->video_notes_manager_->create_video_note(file_id, std::move(thumbnail), video_duration, dimensions, !is_web); break; case DocumentType::VoiceNote: CHECK(audio != nullptr); td_->voice_notes_manager_->create_voice_note(file_id, std::move(mime_type), audio->duration_, - audio->waveform_.as_slice().str(), true); + audio->waveform_.as_slice().str(), !is_web); break; case DocumentType::Unknown: default: diff --git a/td/telegram/DocumentsManager.h b/td/telegram/DocumentsManager.h index 057e31d9..edbc02d6 100644 --- a/td/telegram/DocumentsManager.h +++ b/td/telegram/DocumentsManager.h @@ -40,6 +40,9 @@ class DocumentsManager { // or tl_object_ptr secret_file; tl_object_ptr secret_document; + // or + tl_object_ptr web_document; + PhotoSize thumbnail; vector> attributes; @@ -47,15 +50,29 @@ class DocumentsManager { : document(std::move(server_document)) , secret_file(nullptr) , secret_document(nullptr) + , web_document(nullptr) + , thumbnail() , attributes(std::move(document->attributes_)) { } + RemoteDocument(tl_object_ptr &&web_document, PhotoSize thumbnail, + vector> &&attributes) + : document(nullptr) + , secret_file(nullptr) + , secret_document(nullptr) + , web_document(std::move(web_document)) + , thumbnail(std::move(thumbnail)) + , attributes(std::move(attributes)) { + } + RemoteDocument(tl_object_ptr &&secret_file, tl_object_ptr &&secret_document, vector> &&attributes) : document(nullptr) , secret_file(std::move(secret_file)) , secret_document(std::move(secret_document)) + , web_document(nullptr) + , thumbnail() , attributes(std::move(attributes)) { } }; @@ -63,7 +80,8 @@ class DocumentsManager { tl_object_ptr get_document_object(FileId file_id); std::pair on_get_document(RemoteDocument remote_document, DialogId owner_dialog_id, - MultiPromiseActor *load_data_multipromise_ptr = nullptr); + MultiPromiseActor *load_data_multipromise_ptr = nullptr, + DocumentType default_document_type = DocumentType::General); void create_document(FileId file_id, PhotoSize thumbnail, string file_name, string mime_type, bool replace); diff --git a/td/telegram/InlineQueriesManager.cpp b/td/telegram/InlineQueriesManager.cpp index 03321d73..0dc38094 100644 --- a/td/telegram/InlineQueriesManager.cpp +++ b/td/telegram/InlineQueriesManager.cpp @@ -8,6 +8,7 @@ #include "td/telegram/td_api.h" #include "td/telegram/td_api.hpp" #include "td/telegram/telegram_api.h" +#include "td/telegram/telegram_api.hpp" #include "td/telegram/AccessRights.h" #include "td/telegram/AnimationsManager.h" @@ -477,6 +478,8 @@ void InlineQueriesManager::answer_inline_query(int64 inline_query_id, bool is_pe string thumbnail_url; string content_url; string content_type; + int32 thumbnail_width = 0; + int32 thumbnail_height = 0; int32 width = 0; int32 height = 0; int32 duration = 0; @@ -492,7 +495,7 @@ void InlineQueriesManager::answer_inline_query(int64 inline_query_id, bool is_pe thumbnail_url = std::move(animated_gif->thumbnail_url_); content_url = std::move(animated_gif->gif_url_); content_type = "image/gif"; - duration = animated_gif->gif_duration_; + // duration = animated_gif->gif_duration_; width = animated_gif->gif_width_; height = animated_gif->gif_height_; is_gallery = true; @@ -534,8 +537,8 @@ void InlineQueriesManager::answer_inline_query(int64 inline_query_id, bool is_pe description = std::move(article->description_); thumbnail_url = std::move(article->thumbnail_url_); if (!thumbnail_url.empty()) { - width = article->thumbnail_width_; - height = article->thumbnail_height_; + thumbnail_width = article->thumbnail_width_; + thumbnail_height = article->thumbnail_height_; } force_vertical = true; @@ -576,8 +579,8 @@ void InlineQueriesManager::answer_inline_query(int64 inline_query_id, bool is_pe description = std::move(phone_number); thumbnail_url = std::move(contact->thumbnail_url_); if (!thumbnail_url.empty()) { - width = contact->thumbnail_width_; - height = contact->thumbnail_height_; + thumbnail_width = contact->thumbnail_width_; + thumbnail_height = contact->thumbnail_height_; } force_vertical = true; @@ -594,8 +597,8 @@ void InlineQueriesManager::answer_inline_query(int64 inline_query_id, bool is_pe thumbnail_url = std::move(document->thumbnail_url_); content_url = std::move(document->document_url_); content_type = std::move(document->mime_type_); - width = document->thumbnail_width_; - height = document->thumbnail_height_; + thumbnail_width = document->thumbnail_width_; + thumbnail_height = document->thumbnail_height_; if (content_url.find('.') != string::npos) { if (begins_with(content_type, "application/pdf")) { @@ -637,10 +640,10 @@ void InlineQueriesManager::answer_inline_query(int64 inline_query_id, bool is_pe title = std::move(location->title_); description = to_string(location->location_->latitude_) + " " + to_string(location->location_->longitude_); thumbnail_url = std::move(location->thumbnail_url_); - duration = location->live_period_; + // duration = location->live_period_; if (!thumbnail_url.empty()) { - width = location->thumbnail_width_; - height = location->thumbnail_height_; + thumbnail_width = location->thumbnail_width_; + thumbnail_height = location->thumbnail_height_; } r_inline_message = @@ -693,8 +696,8 @@ void InlineQueriesManager::answer_inline_query(int64 inline_query_id, bool is_pe description = std::move(venue->venue_->address_); thumbnail_url = std::move(venue->thumbnail_url_); if (!thumbnail_url.empty()) { - width = venue->thumbnail_width_; - height = venue->thumbnail_height_; + thumbnail_width = venue->thumbnail_width_; + thumbnail_height = venue->thumbnail_height_; } r_inline_message = @@ -806,35 +809,54 @@ void InlineQueriesManager::answer_inline_query(int64 inline_query_id, bool is_pe return promise.set_error(Status::Error(400, "Strings must be encoded in UTF-8")); } } + tl_object_ptr thumbnail; if (!thumbnail_url.empty()) { - flags |= telegram_api::inputBotInlineResult::THUMB_URL_MASK; + flags |= telegram_api::inputBotInlineResult::THUMB_MASK; if (!clean_input_string(thumbnail_url)) { return promise.set_error(Status::Error(400, "Strings must be encoded in UTF-8")); } + vector> attributes; + if (thumbnail_width > 0 && thumbnail_height > 0) { + attributes.push_back( + make_tl_object(thumbnail_width, thumbnail_height)); + } + thumbnail = make_tl_object(thumbnail_url, 0, "image/jpeg", std::move(attributes)); } + tl_object_ptr content; if (!content_url.empty() || !content_type.empty()) { - static_assert( - telegram_api::inputBotInlineResult::CONTENT_URL_MASK == telegram_api::inputBotInlineResult::CONTENT_TYPE_MASK, - ""); - flags |= telegram_api::inputBotInlineResult::CONTENT_URL_MASK; + flags |= telegram_api::inputBotInlineResult::CONTENT_MASK; if (!clean_input_string(content_url)) { return promise.set_error(Status::Error(400, "Strings must be encoded in UTF-8")); } if (!clean_input_string(content_type)) { return promise.set_error(Status::Error(400, "Strings must be encoded in UTF-8")); } - } - if (width > 0 && height > 0) { - static_assert(telegram_api::inputBotInlineResult::W_MASK == telegram_api::inputBotInlineResult::H_MASK, ""); - flags |= telegram_api::inputBotInlineResult::W_MASK; - } - if (duration > 0) { - flags |= telegram_api::inputBotInlineResult::DURATION_MASK; + + vector> attributes; + if (width > 0 && height > 0) { + if (duration > 0 && !begins_with(content_type, "image/")) { + attributes.push_back(make_tl_object( + 0, false /*ignored*/, false /*ignored*/, duration, width, height)); + } else { + attributes.push_back(make_tl_object(width, height)); + } + } else if (duration > 0) { + if (type == "audio") { + attributes.push_back(make_tl_object( + telegram_api::documentAttributeAudio::TITLE_MASK | telegram_api::documentAttributeAudio::PERFORMER_MASK, + false /*ignored*/, duration, title, description, BufferSlice())); + } else if (type == "voice") { + attributes.push_back(make_tl_object( + telegram_api::documentAttributeAudio::VOICE_MASK, false /*ignored*/, duration, "", "", BufferSlice())); + } + } + attributes.push_back(make_tl_object(get_url_file_name(content_url))); + + content = make_tl_object(content_url, 0, content_type, std::move(attributes)); } - auto result = make_tl_object(flags, id, type, title, description, url, - thumbnail_url, content_url, content_type, width, - height, duration, std::move(inline_message)); + auto result = make_tl_object( + flags, id, type, title, description, url, std::move(thumbnail), std::move(content), std::move(inline_message)); results.push_back(std::move(result)); } @@ -1155,19 +1177,62 @@ tl_object_ptr InlineQueriesManager::decrease_pending return copy(it->second.results); } -tl_object_ptr InlineQueriesManager::register_thumbnail(const string &thumbnail_url, - Dimensions dimensions) const { - if (thumbnail_url.find('.') != string::npos) { - auto r_thumbnail_file_id = td_->file_manager_->from_persistent_id(thumbnail_url, FileType::Temp); - if (r_thumbnail_file_id.is_ok()) { - PhotoSize thumbnail; - thumbnail.type = 't'; - thumbnail.dimensions = dimensions; - thumbnail.file_id = r_thumbnail_file_id.move_as_ok(); - return get_photo_size_object(td_->file_manager_.get(), &thumbnail); - } +tl_object_ptr InlineQueriesManager::register_thumbnail( + tl_object_ptr &&web_document_ptr) const { + PhotoSize thumbnail = get_web_document_photo_size(td_->file_manager_.get(), FileType::Thumbnail, DialogId(), + std::move(web_document_ptr)); + if (!thumbnail.file_id.is_valid()) { + return nullptr; } - return nullptr; + + return get_photo_size_object(td_->file_manager_.get(), &thumbnail); +} + +string InlineQueriesManager::get_web_document_url(const tl_object_ptr &web_document_ptr) { + if (web_document_ptr == nullptr) { + return {}; + } + + string url; + switch (web_document_ptr->get_id()) { + case telegram_api::webDocument::ID: { + auto web_document = static_cast(web_document_ptr.get()); + url = web_document->url_; + break; + } + case telegram_api::webDocumentNoProxy::ID: { + auto web_document = static_cast(web_document_ptr.get()); + url = web_document->url_; + break; + } + default: + UNREACHABLE(); + } + + auto r_http_url = parse_url(url); + if (r_http_url.is_error()) { + LOG(ERROR) << "Can't parse URL " << url; + return {}; + } + return r_http_url.ok().get_url(); +} + +string InlineQueriesManager::get_web_document_content_type( + const tl_object_ptr &web_document_ptr) { + if (web_document_ptr == nullptr) { + return {}; + } + + switch (web_document_ptr->get_id()) { + case telegram_api::webDocument::ID: + return static_cast(web_document_ptr.get())->mime_type_; + case telegram_api::webDocumentNoProxy::ID: + return static_cast(web_document_ptr.get())->mime_type_; + default: + UNREACHABLE(); + } + + return {}; } void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint64 query_hash, @@ -1346,25 +1411,11 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6 } case telegram_api::botInlineResult::ID: { auto result = move_tl_object_as(result_ptr); - Dimensions dimensions; - if (result->flags_ & (1 << 6)) { - dimensions = get_dimensions(result->w_, result->h_); - } // TODO zero fetch init - - int32 duration; - if (result->flags_ & (1 << 7)) { - duration = result->duration_; - if (duration < 0) { - duration = 0; - } - } else { - duration = 0; - } // TODO zero fetch init - + auto content_type = get_web_document_content_type(result->content_); if (result->type_ == "article") { auto article = make_tl_object(); article->id_ = std::move(result->id_); - article->url_ = std::move(result->content_url_); + article->url_ = get_web_document_url(std::move(result->content_)); if (result->url_.empty()) { article->hide_url_ = true; } else { @@ -1374,7 +1425,7 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6 } article->title_ = std::move(result->title_); article->description_ = std::move(result->description_); - article->thumbnail_ = register_thumbnail(result->thumb_url_, dimensions); + article->thumbnail_ = register_thumbnail(std::move(result->thumb_)); if (!register_inline_message_content(results->query_id_, article->id_, FileId(), std::move(result->send_message_), -1)) { @@ -1394,7 +1445,7 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6 Contact c(std::move(result->description_), std::move(result->title_), string(), 0); contact->contact_ = c.get_contact_object(); } - contact->thumbnail_ = register_thumbnail(result->thumb_url_, dimensions); + contact->thumbnail_ = register_thumbnail(std::move(result->thumb_)); if (!register_inline_message_content(results->query_id_, contact->id_, FileId(), std::move(result->send_message_), -1)) { @@ -1415,7 +1466,7 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6 Location l(to_double(coordinates.first), to_double(coordinates.second)); location->location_ = l.get_location_object(); } - location->thumbnail_ = register_thumbnail(result->thumb_url_, dimensions); + location->thumbnail_ = register_thumbnail(std::move(result->thumb_)); if (!register_inline_message_content(results->query_id_, location->id_, FileId(), std::move(result->send_message_), -1)) { @@ -1441,144 +1492,141 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6 Venue v(nullptr, std::move(result->title_), std::move(result->description_), string(), string()); venue->venue_ = v.get_venue_object(); } - venue->thumbnail_ = register_thumbnail(result->thumb_url_, dimensions); + venue->thumbnail_ = register_thumbnail(std::move(result->thumb_)); if (!register_inline_message_content(results->query_id_, venue->id_, FileId(), std::move(result->send_message_), -1)) { continue; } output_result = std::move(venue); + } else if (result->type_ == "photo" && content_type == "image/jpeg") { + auto photo = make_tl_object(); + photo->id_ = std::move(result->id_); + + PhotoSize photo_size = get_web_document_photo_size(td_->file_manager_.get(), FileType::Temp, DialogId(), + std::move(result->content_)); + if (!photo_size.file_id.is_valid()) { + LOG(ERROR) << "Receive invalid web document photo"; + continue; + } + + Photo new_photo; + PhotoSize thumbnail = get_web_document_photo_size(td_->file_manager_.get(), FileType::Thumbnail, DialogId(), + std::move(result->thumb_)); + if (thumbnail.file_id.is_valid()) { + new_photo.photos.push_back(std::move(thumbnail)); + } + new_photo.photos.push_back(std::move(photo_size)); + + photo->photo_ = get_photo_object(td_->file_manager_.get(), &new_photo); + photo->title_ = std::move(result->title_); + photo->description_ = std::move(result->description_); + + if (!register_inline_message_content(results->query_id_, photo->id_, FileId(), + std::move(result->send_message_), td_api::inputMessagePhoto::ID, + &new_photo)) { + continue; + } + output_result = std::move(photo); } else { - auto r_http_url = parse_url(result->content_url_); - if (r_http_url.is_error()) { - LOG(ERROR) << "Can't parse url " << result->content_url_; + if (result->content_ == nullptr) { + LOG(ERROR) << "Unsupported inline query result without content " << to_string(result); continue; } - auto http_url = r_http_url.ok(); - auto url = http_url.get_url(); - auto r_file_id = td_->file_manager_->from_persistent_id(url, FileType::Temp); - if (r_file_id.is_error()) { - LOG(ERROR) << "Can't register url " << url; - continue; - } - auto file_id = r_file_id.move_as_ok(); - auto file_name = get_url_query_file_name(http_url.query_); - PhotoSize thumbnail; - if (result->thumb_url_.find('.') != string::npos) { - auto r_thumbnail_file_id = td_->file_manager_->from_persistent_id(result->thumb_url_, FileType::Temp); - if (r_thumbnail_file_id.is_error()) { - LOG(ERROR) << "Can't register thumbnail url " << result->thumb_url_; - continue; + vector> attributes; + downcast_call(*result->content_, + [&attributes](auto &web_document) { attributes = std::move(web_document.attributes_); }); + + bool is_animation = result->type_ == "gif" && (content_type == "image/gif" || content_type == "video/mp4"); + if (is_animation) { + attributes.push_back(make_tl_object()); + } + auto default_document_type = [type = result->type_, is_animation] { + if (type == "audio") { + return DocumentsManager::DocumentType::Audio; } - thumbnail.type = 't'; - thumbnail.file_id = r_thumbnail_file_id.move_as_ok(); - } + if (is_animation) { + return DocumentsManager::DocumentType::Animation; + } + if (type == "sticker") { + return DocumentsManager::DocumentType::Sticker; + } + if (type == "video") { + return DocumentsManager::DocumentType::Video; + } + if (type == "voice") { + return DocumentsManager::DocumentType::VoiceNote; + } + return DocumentsManager::DocumentType::General; + }(); - if (result->type_ == "audio") { + auto parsed_document = td_->documents_manager_->on_get_document( + {std::move(result->content_), + get_web_document_photo_size(td_->file_manager_.get(), FileType::Thumbnail, DialogId(), + std::move(result->thumb_)), + std::move(attributes)}, + DialogId(), nullptr, default_document_type); + auto file_id = parsed_document.second; + if (!file_id.is_valid()) { + continue; + } + if (result->type_ == "audio" && parsed_document.first == DocumentsManager::DocumentType::Audio) { auto audio = make_tl_object(); audio->id_ = std::move(result->id_); - td_->audios_manager_->create_audio(file_id, std::move(thumbnail), std::move(file_name), - std::move(result->content_type_), duration, std::move(result->title_), - std::move(result->description_), false); audio->audio_ = td_->audios_manager_->get_audio_object(file_id); - if (!register_inline_message_content(results->query_id_, audio->id_, file_id, std::move(result->send_message_), td_api::inputMessageAudio::ID)) { continue; } output_result = std::move(audio); - } else if (result->type_ == "file") { - thumbnail.dimensions = dimensions; - + } else if (result->type_ == "file" && parsed_document.first == DocumentsManager::DocumentType::General) { auto document = make_tl_object(); document->id_ = std::move(result->id_); - td_->documents_manager_->create_document(file_id, std::move(thumbnail), std::move(file_name), - std::move(result->content_type_), false); document->document_ = td_->documents_manager_->get_document_object(file_id); document->title_ = std::move(result->title_); document->description_ = std::move(result->description_); - if (!register_inline_message_content(results->query_id_, document->id_, file_id, std::move(result->send_message_), td_api::inputMessageDocument::ID)) { continue; } output_result = std::move(document); - } else if (result->type_ == "gif" && - (result->content_type_ == "image/gif" || result->content_type_ == "video/mp4")) { + } else if (is_animation && parsed_document.first == DocumentsManager::DocumentType::Animation) { auto animation = make_tl_object(); animation->id_ = std::move(result->id_); - td_->animations_manager_->create_animation(file_id, std::move(thumbnail), std::move(file_name), - std::move(result->content_type_), duration, dimensions, false); animation->animation_ = td_->animations_manager_->get_animation_object(file_id, "inlineQueryResultAnimationCached"); animation->title_ = std::move(result->title_); - if (!register_inline_message_content(results->query_id_, animation->id_, file_id, std::move(result->send_message_), td_api::inputMessageAnimation::ID)) { continue; } output_result = std::move(animation); - } else if (result->type_ == "photo" && result->content_type_ == "image/jpeg") { - auto photo = make_tl_object(); - photo->id_ = std::move(result->id_); - - // TODO create_photo - Photo new_photo; - PhotoSize s; - s.type = 'u'; - s.dimensions = dimensions; - s.size = 0; - s.file_id = file_id; - - if (thumbnail.file_id.is_valid()) { - new_photo.photos.push_back(std::move(thumbnail)); - } - new_photo.photos.push_back(std::move(s)); - - photo->photo_ = get_photo_object(td_->file_manager_.get(), &new_photo); - photo->title_ = std::move(result->title_); - photo->description_ = std::move(result->description_); - - if (!register_inline_message_content(results->query_id_, photo->id_, FileId(), - std::move(result->send_message_), td_api::inputMessagePhoto::ID, - &new_photo)) { - continue; - } - output_result = std::move(photo); - } else if (result->type_ == "sticker") { + } else if (result->type_ == "sticker" && parsed_document.first == DocumentsManager::DocumentType::Sticker) { auto sticker = make_tl_object(); sticker->id_ = std::move(result->id_); - td_->stickers_manager_->create_sticker(file_id, std::move(thumbnail), dimensions, true, nullptr, nullptr); sticker->sticker_ = td_->stickers_manager_->get_sticker_object(file_id); - if (!register_inline_message_content(results->query_id_, sticker->id_, file_id, std::move(result->send_message_), td_api::inputMessageSticker::ID)) { continue; } output_result = std::move(sticker); - } else if (result->type_ == "video") { + } else if (result->type_ == "video" && parsed_document.first == DocumentsManager::DocumentType::Video) { auto video = make_tl_object(); video->id_ = std::move(result->id_); - td_->videos_manager_->create_video(file_id, std::move(thumbnail), false, {}, std::move(file_name), - std::move(result->content_type_), duration, dimensions, false, false); video->video_ = td_->videos_manager_->get_video_object(file_id); video->title_ = std::move(result->title_); video->description_ = std::move(result->description_); - if (!register_inline_message_content(results->query_id_, video->id_, file_id, std::move(result->send_message_), td_api::inputMessageVideo::ID)) { continue; } output_result = std::move(video); - } else if (result->type_ == "voice") { + } else if (result->type_ == "voice" && parsed_document.first == DocumentsManager::DocumentType::VoiceNote) { auto voice_note = make_tl_object(); voice_note->id_ = std::move(result->id_); - td_->voice_notes_manager_->create_voice_note(file_id, std::move(result->content_type_), duration, string(), - false); voice_note->voice_note_ = td_->voice_notes_manager_->get_voice_note_object(file_id); voice_note->title_ = std::move(result->title_); - if (!register_inline_message_content(results->query_id_, voice_note->id_, file_id, std::move(result->send_message_), td_api::inputMessageVoiceNote::ID)) { continue; diff --git a/td/telegram/InlineQueriesManager.h b/td/telegram/InlineQueriesManager.h index c7cc2eb1..97548c41 100644 --- a/td/telegram/InlineQueriesManager.h +++ b/td/telegram/InlineQueriesManager.h @@ -100,7 +100,11 @@ class InlineQueriesManager : public Actor { tl_object_ptr &&inline_message, int32 allowed_media_content_id, Photo *photo = nullptr, Game *game = nullptr); - tl_object_ptr register_thumbnail(const string &thumbnail_url, Dimensions dimensions) const; + tl_object_ptr register_thumbnail( + tl_object_ptr &&web_document_ptr) const; + + static string get_web_document_url(const tl_object_ptr &web_document_ptr); + static string get_web_document_content_type(const tl_object_ptr &web_document_ptr); bool update_bot_usage(UserId bot_user_id); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 6a1a8189..6af16762 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -20233,62 +20233,17 @@ static tl_object_ptr secret_to_telegram(FromT &from) { return res; } -Photo MessagesManager::get_web_document_photo(tl_object_ptr web_document, +Photo MessagesManager::get_web_document_photo(tl_object_ptr web_document, DialogId owner_dialog_id) const { + PhotoSize s = + get_web_document_photo_size(td_->file_manager_.get(), FileType::Photo, owner_dialog_id, std::move(web_document)); Photo photo; - photo.id = -2; - - if (web_document == nullptr) { - return photo; + if (!s.file_id.is_valid()) { + photo.id = -2; + } else { + photo.id = 0; + photo.photos.push_back(s); } - if (!DcId::is_valid(web_document->dc_id_)) { - LOG(ERROR) << "Wrong dc_id = " << web_document->dc_id_; - return photo; - } - - auto r_http_url = parse_url(web_document->url_); - if (r_http_url.is_error()) { - LOG(ERROR) << "Can't parse url " << web_document->url_; - return photo; - } - auto http_url = r_http_url.move_as_ok(); - auto url = http_url.get_url(); - // TODO real file name - FileId file_id = td_->file_manager_->register_remote( - FullRemoteFileLocation(FileType::Photo, url, web_document->access_hash_, DcId::internal(web_document->dc_id_)), - FileLocationSource::FromServer, owner_dialog_id, 0, web_document->size_, ""); - - Dimensions dimensions; - for (auto &attribute : web_document->attributes_) { - switch (attribute->get_id()) { - case telegram_api::documentAttributeImageSize::ID: { - auto image_size = move_tl_object_as(attribute); - dimensions = get_dimensions(image_size->w_, image_size->h_); - break; - } - case telegram_api::documentAttributeAnimated::ID: - case telegram_api::documentAttributeHasStickers::ID: - case telegram_api::documentAttributeSticker::ID: - case telegram_api::documentAttributeVideo::ID: - case telegram_api::documentAttributeAudio::ID: - LOG(ERROR) << "Unexpected web document attribute " << to_string(attribute); - break; - case telegram_api::documentAttributeFilename::ID: - break; - default: - UNREACHABLE(); - } - } - - PhotoSize s; - s.type = 'u'; - s.dimensions = dimensions; - s.size = web_document->size_; - s.file_id = file_id; - - photo.id = 0; - photo.photos.push_back(s); - return photo; } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index d45861dc..2dddbbb8 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2229,7 +2229,7 @@ class MessagesManager : public Actor { static FormattedText get_secret_media_caption(string &&message_text, string &&message_caption); - Photo get_web_document_photo(tl_object_ptr web_document, DialogId owner_dialog_id) const; + Photo get_web_document_photo(tl_object_ptr web_document, DialogId owner_dialog_id) const; unique_ptr get_secret_message_document( tl_object_ptr file, diff --git a/td/telegram/Photo.cpp b/td/telegram/Photo.cpp index a3de5734..0983eede 100644 --- a/td/telegram/Photo.cpp +++ b/td/telegram/Photo.cpp @@ -14,6 +14,7 @@ #include "td/utils/common.h" #include "td/utils/format.h" +#include "td/utils/HttpUrl.h" #include "td/utils/logging.h" #include "td/utils/misc.h" #include "td/utils/Random.h" @@ -286,6 +287,92 @@ PhotoSize get_photo_size(FileManager *file_manager, FileType file_type, int64 id return res; } +PhotoSize get_web_document_photo_size(FileManager *file_manager, FileType file_type, DialogId owner_dialog_id, + tl_object_ptr web_document_ptr) { + if (web_document_ptr == nullptr) { + return {}; + } + + FileId file_id; + vector> attributes; + int32 size = 0; + switch (web_document_ptr->get_id()) { + case telegram_api::webDocument::ID: { + auto web_document = move_tl_object_as(web_document_ptr); + if (!DcId::is_valid(web_document->dc_id_)) { + LOG(ERROR) << "Wrong dc_id = " << web_document->dc_id_; + return {}; + } + + auto r_http_url = parse_url(web_document->url_); + if (r_http_url.is_error()) { + LOG(ERROR) << "Can't parse URL " << web_document->url_; + return {}; + } + auto http_url = r_http_url.move_as_ok(); + auto url = http_url.get_url(); + file_id = file_manager->register_remote( + FullRemoteFileLocation(file_type, url, web_document->access_hash_, DcId::internal(web_document->dc_id_)), + FileLocationSource::FromServer, owner_dialog_id, 0, web_document->size_, + get_url_query_file_name(http_url.query_)); + + size = web_document->size_; + attributes = std::move(web_document->attributes_); + break; + } + case telegram_api::webDocumentNoProxy::ID: { + auto web_document = move_tl_object_as(web_document_ptr); + if (web_document->url_.find('.') == string::npos) { + LOG(ERROR) << "Receive invalid URL " << web_document->url_; + return {}; + } + + auto r_file_id = file_manager->from_persistent_id(web_document->url_, file_type); + if (r_file_id.is_error()) { + LOG(ERROR) << "Can't register URL: " << r_file_id.error(); + return {}; + } + file_id = r_file_id.move_as_ok(); + + size = web_document->size_; + attributes = std::move(web_document->attributes_); + break; + } + default: + UNREACHABLE(); + } + CHECK(file_id.is_valid()); + + Dimensions dimensions; + for (auto &attribute : attributes) { + switch (attribute->get_id()) { + case telegram_api::documentAttributeImageSize::ID: { + auto image_size = move_tl_object_as(attribute); + dimensions = get_dimensions(image_size->w_, image_size->h_); + break; + } + case telegram_api::documentAttributeAnimated::ID: + case telegram_api::documentAttributeHasStickers::ID: + case telegram_api::documentAttributeSticker::ID: + case telegram_api::documentAttributeVideo::ID: + case telegram_api::documentAttributeAudio::ID: + LOG(ERROR) << "Unexpected web document attribute " << to_string(attribute); + break; + case telegram_api::documentAttributeFilename::ID: + break; + default: + UNREACHABLE(); + } + } + + PhotoSize s; + s.type = file_type == FileType::Thumbnail ? 't' : 'u'; + s.dimensions = dimensions; + s.size = size; + s.file_id = file_id; + return s; +} + tl_object_ptr get_photo_size_object(FileManager *file_manager, const PhotoSize *photo_size) { if (photo_size == nullptr || !photo_size->file_id.is_valid()) { return nullptr; diff --git a/td/telegram/Photo.h b/td/telegram/Photo.h index 16a9fa5e..def1318e 100644 --- a/td/telegram/Photo.h +++ b/td/telegram/Photo.h @@ -82,6 +82,8 @@ PhotoSize get_thumbnail_photo_size(FileManager *file_manager, BufferSlice bytes, int32 height); PhotoSize get_photo_size(FileManager *file_manager, FileType file_type, int64 id, int64 access_hash, DialogId owner_dialog_id, tl_object_ptr &&size_ptr); +PhotoSize get_web_document_photo_size(FileManager *file_manager, FileType file_type, DialogId owner_dialog_id, + tl_object_ptr web_document_ptr); tl_object_ptr get_photo_size_object(FileManager *file_manager, const PhotoSize *photo_size); bool operator==(const PhotoSize &lhs, const PhotoSize &rhs);