From 58f796b5ba5e0d7f606d86aa16df0cc9104e4512 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 30 Aug 2020 16:42:44 +0300 Subject: [PATCH 01/39] Improve documentation. GitOrigin-RevId: 489f91624378aa455cb9253dfd4669d4d406a4e7 --- td/generate/scheme/td_api.tl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 94dcb3fbe..5d93382cb 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -293,7 +293,7 @@ contact phone_number:string first_name:string last_name:string vcard:string user //@description Describes a location on planet Earth @latitude Latitude of the location in degrees; as defined by the sender @longitude Longitude of the location, in degrees; as defined by the sender location latitude:double longitude:double = Location; -//@description Describes a venue @location Venue location; as defined by the sender @title Venue name; as defined by the sender @address Venue address; as defined by the sender @provider Provider of the venue database; as defined by the sender. Currently only "foursquare" and "gplaces" (Google Places) needs to be supported +//@description Describes a venue @location Venue location; as defined by the sender @title Venue name; as defined by the sender @address Venue address; as defined by the sender @provider Provider of the venue database; as defined by the sender. Currently only "foursquare" and "gplaces" (Google Places) need to be supported //@id Identifier of the venue in the provider database; as defined by the sender @type Type of the venue in the provider database; as defined by the sender venue location:location title:string address:string provider:string id:string type:string = Venue; @@ -2801,7 +2801,7 @@ networkStatistics since_date:int32 entries:vector = Netw //@max_video_file_size The maximum size of a video file to be auto-downloaded //@max_other_file_size The maximum size of other file types to be auto-downloaded //@video_upload_bitrate The maximum suggested bitrate for uploaded videos -//@preload_large_videos True, if the beginning of videos needs to be preloaded for instant playback +//@preload_large_videos True, if the beginning of video files needs to be preloaded for instant playback //@preload_next_audio True, if the next audio track needs to be preloaded while the user is listening to an audio file //@use_less_data_for_calls True, if "use less data for calls" option needs to be enabled autoDownloadSettings is_auto_download_enabled:Bool max_photo_file_size:int32 max_video_file_size:int32 max_other_file_size:int32 video_upload_bitrate:int32 preload_large_videos:Bool preload_next_audio:Bool use_less_data_for_calls:Bool = AutoDownloadSettings; @@ -3655,7 +3655,7 @@ sendInlineQueryResultMessage chat_id:int53 reply_to_message_id:int53 options:mes //@options Options to be used to send the messages //@as_album True, if the messages should be grouped into an album after forwarding. For this to work, no more than 10 messages may be forwarded, and all of them must be photo or video messages //@send_copy True, if content of the messages needs to be copied without links to the original messages. Always true if the messages are forwarded to a secret chat -//@remove_caption True, if media captions of message copies needs to be removed. Ignored if send_copy is false +//@remove_caption True, if media caption of message copies needs to be removed. Ignored if send_copy is false forwardMessages chat_id:int53 from_chat_id:int53 message_ids:vector options:messageSendOptions as_album:Bool send_copy:Bool remove_caption:Bool = Messages; //@description Resends messages which failed to send. Can be called only for messages for which messageSendingStateFailed.can_retry is true and after specified in messageSendingStateFailed.retry_after time passed. @@ -3937,7 +3937,7 @@ setChatClientData chat_id:int53 client_data:string = Ok; setChatDescription chat_id:int53 description:string = Ok; //@description Changes the discussion group of a channel chat; requires can_change_info rights in the channel if it is specified @chat_id Identifier of the channel chat. Pass 0 to remove a link from the supergroup passed in the second argument to a linked channel chat (requires can_pin_messages rights in the supergroup) @discussion_chat_id Identifier of a new channel's discussion group. Use 0 to remove the discussion group. -//-Use the method getSuitableDiscussionChats to find all suitable groups. Basic group chats needs to be first upgraded to supergroup chats. If new chat members don't have access to old messages in the supergroup, then toggleSupergroupIsAllHistoryAvailable needs to be used first to change that +//-Use the method getSuitableDiscussionChats to find all suitable groups. Basic group chats need to be first upgraded to supergroup chats. If new chat members don't have access to old messages in the supergroup, then toggleSupergroupIsAllHistoryAvailable needs to be used first to change that setChatDiscussionGroup chat_id:int53 discussion_chat_id:int53 = Ok; //@description Changes the location of a chat. Available only for some location-based supergroups, use supergroupFullInfo.can_set_location to check whether the method is allowed to use @chat_id Chat identifier @location New location for the chat; must be valid and not null @@ -4351,7 +4351,7 @@ deleteSavedCredentials = Ok; getSupportUser = User; -//@description Returns backgrounds installed by the user @for_dark_theme True, if the backgrounds needs to be ordered for dark theme +//@description Returns backgrounds installed by the user @for_dark_theme True, if the backgrounds need to be ordered for dark theme getBackgrounds for_dark_theme:Bool = Backgrounds; //@description Constructs a persistent HTTP URL for a background @name Background name @type Background type @@ -4476,7 +4476,7 @@ getDatabaseStatistics = DatabaseStatistics; //@file_types If not empty, only files with the given type(s) are considered. By default, all types except thumbnails, profile photos, stickers and wallpapers are deleted //@chat_ids If not empty, only files from the given chats are considered. Use 0 as chat identifier to delete files not belonging to any chat (e.g., profile photos) //@exclude_chat_ids If not empty, files from the given chats are excluded. Use 0 as chat identifier to exclude all files not belonging to any chat (e.g., profile photos) -//@return_deleted_file_statistics Pass true if deleted file statistics needs to be returned instead of the whole storage usage statistics. Affects only returned statistics +//@return_deleted_file_statistics Pass true if deleted file statistics need to be returned instead of the whole storage usage statistics. Affects only returned statistics //@chat_limit Same as in getStorageStatistics. Affects only returned statistics optimizeStorage size:int53 ttl:int32 count:int32 immunity_delay:int32 file_types:vector chat_ids:vector exclude_chat_ids:vector return_deleted_file_statistics:Bool chat_limit:int32 = StorageStatistics; From 77678b730c2f720debb67dfaa95ea4210fb839ce Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 2 Sep 2020 15:40:47 +0300 Subject: [PATCH 02/39] Send acknowledgements immediately if hane many of them. GitOrigin-RevId: e7759150942e8fcdde57b1113e5b6c0375023f91 --- td/mtproto/SessionConnection.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/td/mtproto/SessionConnection.cpp b/td/mtproto/SessionConnection.cpp index a1f6f84d6..8c94fb8d7 100644 --- a/td/mtproto/SessionConnection.cpp +++ b/td/mtproto/SessionConnection.cpp @@ -824,6 +824,11 @@ void SessionConnection::send_ack(uint64 message_id) { // an easiest way to eliminate duplicated acks for gzipped packets if (to_ack_.empty() || to_ack_.back() != ack) { to_ack_.push_back(ack); + + constexpr size_t MAX_UNACKED_PACKETS = 100; + if (to_ack_.size() >= MAX_UNACKED_PACKETS) { + send_before(Time::now_cached()); + } } } @@ -970,8 +975,8 @@ void SessionConnection::flush_packet() { } } - to_ack_.clear(); - if (to_send_.empty()) { + if (to_send_.empty() && to_ack_.empty() && to_get_state_info_.empty() && to_resend_answer_.empty() && + to_cancel_answer_.empty()) { force_send_at_ = 0; } } From 07237a18beec303d160775afa7e8b2f4c5390a4f Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 2 Sep 2020 17:10:10 +0300 Subject: [PATCH 03/39] Fix Logger const-correctness. GitOrigin-RevId: 437ed337638a9841f7695fd77b89191f1b36c584 --- tdnet/td/net/SslStream.cpp | 2 +- tdutils/td/utils/format.h | 4 ++-- tdutils/td/utils/logging.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tdnet/td/net/SslStream.cpp b/tdnet/td/net/SslStream.cpp index 92d68e363..64f3af931 100644 --- a/tdnet/td/net/SslStream.cpp +++ b/tdnet/td/net/SslStream.cpp @@ -124,7 +124,7 @@ int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) { int err = X509_STORE_CTX_get_error(ctx); auto warning = PSTRING() << "verify error:num=" << err << ":" << X509_verify_cert_error_string(err) - << ":depth=" << X509_STORE_CTX_get_error_depth(ctx) << ":" << buf; + << ":depth=" << X509_STORE_CTX_get_error_depth(ctx) << ":" << Slice(buf, std::strlen(buf)); double now = Time::now(); static std::mutex warning_mutex; diff --git a/tdutils/td/utils/format.h b/tdutils/td/utils/format.h index f6bbc4063..a3b5b3a46 100644 --- a/tdutils/td/utils/format.h +++ b/tdutils/td/utils/format.h @@ -174,7 +174,7 @@ inline StringBuilder &operator<<(StringBuilder &logger, Time t) { while (i + 1 < durations_n && t.seconds_ > 10 * durations[i + 1].value) { i++; } - logger << StringBuilder::FixedDouble(t.seconds_ / durations[i].value, 1) << durations[i].name; + logger << StringBuilder::FixedDouble(t.seconds_ / durations[i].value, 1) << Slice(durations[i].name); return logger; } @@ -200,7 +200,7 @@ inline StringBuilder &operator<<(StringBuilder &logger, Size t) { while (i + 1 < sizes_n && t.size_ > 10 * sizes[i + 1].value) { i++; } - logger << t.size_ / sizes[i].value << sizes[i].name; + logger << t.size_ / sizes[i].value << Slice(sizes[i].name); return logger; } diff --git a/tdutils/td/utils/logging.h b/tdutils/td/utils/logging.h index 94a20c13e..07d37c384 100644 --- a/tdutils/td/utils/logging.h +++ b/tdutils/td/utils/logging.h @@ -251,7 +251,7 @@ class Logger { Logger(LogInterface &log, const LogOptions &options, int log_level, Slice file_name, int line_num, Slice comment); template - Logger &operator<<(const T &other) { + Logger &operator<<(T &&other) { sb_ << other; return *this; } From d46fa34869b9053d99920c5f1caebea2f4c18183 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 2 Sep 2020 17:22:30 +0300 Subject: [PATCH 04/39] Fix Linux CE. GitOrigin-RevId: 7758d3fe4cc16210338f739e2dcc748d55e808a5 --- tdutils/td/utils/port/detail/Epoll.cpp | 2 +- tdutils/td/utils/port/detail/EventFdBsd.cpp | 2 +- tdutils/td/utils/port/uname.cpp | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tdutils/td/utils/port/detail/Epoll.cpp b/tdutils/td/utils/port/detail/Epoll.cpp index e30b87336..d15eccfd6 100644 --- a/tdutils/td/utils/port/detail/Epoll.cpp +++ b/tdutils/td/utils/port/detail/Epoll.cpp @@ -112,7 +112,7 @@ void Epoll::run(int timeout_ms) { flags = flags | PollFlags::Error(); } if (event->events) { - LOG(FATAL) << "Unsupported epoll events: " << event->events; + LOG(FATAL) << "Unsupported epoll events: " << static_cast(event->events); } //LOG(DEBUG) << "Epoll event " << tag("fd", event->data.fd) << tag("flags", format::as_binary(flags)); auto pollable_fd = PollableFd::from_list_node(static_cast(event->data.ptr)); diff --git a/tdutils/td/utils/port/detail/EventFdBsd.cpp b/tdutils/td/utils/port/detail/EventFdBsd.cpp index 3544069d9..0eb9e5a84 100644 --- a/tdutils/td/utils/port/detail/EventFdBsd.cpp +++ b/tdutils/td/utils/port/detail/EventFdBsd.cpp @@ -77,7 +77,7 @@ void EventFdBsd::release() { } size_t size = result.ok(); if (size != sizeof(value)) { - LOG(FATAL) << "EventFdBsd write returned " << value << " instead of " << sizeof(value); + LOG(FATAL) << "EventFdBsd write returned " << size << " instead of " << sizeof(value); } } diff --git a/tdutils/td/utils/port/uname.cpp b/tdutils/td/utils/port/uname.cpp index 4a35b6897..ee0fde119 100644 --- a/tdutils/td/utils/port/uname.cpp +++ b/tdutils/td/utils/port/uname.cpp @@ -16,6 +16,8 @@ #if TD_PORT_POSIX +#include + #if TD_ANDROID #include #else @@ -99,7 +101,8 @@ Slice get_operating_system_version() { utsname name; int err = uname(&name); if (err == 0) { - auto os_name = trim(PSTRING() << name.sysname << " " << name.release); + auto os_name = trim(PSTRING() << Slice(name.sysname, std::strlen(name.sysname)) << " " + << Slice(name.release, std::strlen(name.release))); if (!os_name.empty()) { return os_name; } From 39a42bfd749cb7adb6b11f40accccc189eb44fb8 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 2 Sep 2020 23:35:54 +0300 Subject: [PATCH 05/39] Return previous actor context before stopping Td just in case. GitOrigin-RevId: 1737f25bd1990fbffe16c075c87cbfa23b3e0d85 --- td/telegram/Td.cpp | 5 +++-- td/telegram/Td.h | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 1d7aba6b9..56430d0a7 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -3007,6 +3007,7 @@ class SetBackgroundRequest : public RequestActor<> { Td::Td(unique_ptr callback, Options options) : callback_(std::move(callback)), td_options_(std::move(options)) { + CHECK(callback_ != nullptr); } Td::~Td() = default; @@ -3724,7 +3725,7 @@ void Td::start_up() { } VLOG(td_init) << "Create Global"; - set_context(std::make_shared()); + old_context_ = set_context(std::make_shared()); G()->set_net_query_stats(td_options_.net_query_stats); inc_request_actor_refcnt(); // guard inc_actor_refcnt(); // guard @@ -3847,6 +3848,7 @@ void Td::dec_stop_cnt() { stop_cnt_--; if (stop_cnt_ == 0) { LOG(WARNING) << "Stop Td"; + set_context(std::move(old_context_)); stop(); } } @@ -4512,7 +4514,6 @@ void Td::send_result(uint64 id, tl_object_ptr object) { void Td::send_error_impl(uint64 id, tl_object_ptr error) { CHECK(id != 0); - CHECK(callback_ != nullptr); CHECK(error != nullptr); auto it = request_set_.find(id); if (it != request_set_.end()) { diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 39fe607b6..e93651f89 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -347,6 +347,8 @@ class Td final : public NetQueryCallback { std::shared_ptr upload_file_callback_; + std::shared_ptr old_context_; + static int *get_log_verbosity_level(Slice name); template From 517387cecc8b0e82cdbb56711628b7e2851a234e Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 2 Sep 2020 23:37:53 +0300 Subject: [PATCH 06/39] Add actor context change logging. GitOrigin-RevId: a440d115f0d30ec54a73cb8e6cf06c1435764191 --- tdactor/td/actor/impl/ActorInfo.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tdactor/td/actor/impl/ActorInfo.h b/tdactor/td/actor/impl/ActorInfo.h index bb58d82c3..c1e6ef64d 100644 --- a/tdactor/td/actor/impl/ActorInfo.h +++ b/tdactor/td/actor/impl/ActorInfo.h @@ -40,6 +40,7 @@ inline void ActorInfo::init(int32 sched_id, Slice name, ObjectPool::O if (!is_lite) { context_ = Scheduler::context()->this_ptr_.lock(); + VLOG(actor) << "Set context " << context_.get() << " for " << name; #ifdef TD_DEBUG name_ = name.str(); #endif @@ -77,6 +78,7 @@ inline void ActorInfo::clear() { // NB: must be in non migrating state // store invalid scheduler id. sched_id_.store((1 << 30) - 1, std::memory_order_relaxed); + VLOG(actor) << "Clear context " << context_.get() << " for " << get_name(); context_.reset(); } From 51f8ed3526e2399ef57838e307d5c498232f3570 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 3 Sep 2020 00:16:49 +0300 Subject: [PATCH 07/39] Fix FileLoader closing. GitOrigin-RevId: 85ee2acb100e160fd13752ef8fb238dcd63e1f35 --- td/telegram/files/FileLoader.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/td/telegram/files/FileLoader.cpp b/td/telegram/files/FileLoader.cpp index 462c8e966..f4ed1f865 100644 --- a/td/telegram/files/FileLoader.cpp +++ b/td/telegram/files/FileLoader.cpp @@ -42,7 +42,11 @@ size_t FileLoader::get_part_size() const { } void FileLoader::hangup() { - delay_dispatcher_.reset(); + if (delay_dispatcher_.empty()) { + stop(); + } else { + delay_dispatcher_.reset(); + } } void FileLoader::hangup_shared() { From 9d6458945666f74b8f73e7da8227bdab1d2293fd Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 3 Sep 2020 07:21:01 +0300 Subject: [PATCH 08/39] Fix NetQueryDebug.state_timestamp_ initialization. GitOrigin-RevId: 7cd96ac1d2e423767b8ae4a9d8f1ef5347fa41e8 --- td/telegram/net/NetQuery.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/td/telegram/net/NetQuery.h b/td/telegram/net/NetQuery.h index 79d3c67b5..246c1d497 100644 --- a/td/telegram/net/NetQuery.h +++ b/td/telegram/net/NetQuery.h @@ -352,8 +352,9 @@ class NetQuery : public TsListNode { , answer_(std::move(answer)) , tl_constructor_(tl_constructor) , total_timeout_limit_(total_timeout_limit) { - get_data_unsafe().my_id_ = get_my_id(); - get_data_unsafe().start_timestamp_ = Time::now(); + auto &data = get_data_unsafe(); + data.my_id_ = get_my_id(); + data.start_timestamp_ = data.state_timestamp_ = Time::now(); LOG(INFO) << *this; if (stats) { nq_counter_ = stats->register_query(this); From 6d379b0fd5a3cc5caa749e4ce229019c866b06e9 Mon Sep 17 00:00:00 2001 From: Arseny Smirnov Date: Thu, 24 Sep 2020 15:31:35 +0300 Subject: [PATCH 09/39] bench_crypto: test raw openssl ctr GitOrigin-RevId: c173a74a094c294e75c6a2c09e3ad10676499611 --- benchmark/bench_crypto.cpp | 45 +++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/benchmark/bench_crypto.cpp b/benchmark/bench_crypto.cpp index c7d34adb4..eaca9c8e2 100644 --- a/benchmark/bench_crypto.cpp +++ b/benchmark/bench_crypto.cpp @@ -14,6 +14,7 @@ #include "td/utils/UInt.h" #include +#include #include #include @@ -164,6 +165,47 @@ class AesCtrBench : public td::Benchmark { } }; +class AesCtrOpenSSLBench : public td::Benchmark { + public: + alignas(64) unsigned char data[DATA_SIZE]; + alignas(64) unsigned char dest[DATA_SIZE]; + td::UInt256 key; + td::UInt128 iv; + + std::string get_description() const override { + return PSTRING() << "AES CTR RAW OpenSSL [" << (DATA_SIZE >> 10) << "KB]"; + } + + void start_up() override { + for (int i = 0; i < DATA_SIZE; i++) { + data[i] = 123; + } + td::Random::secure_bytes(key.raw, sizeof(key)); + td::Random::secure_bytes(iv.raw, sizeof(iv)); + } + + void run(int n) override { + EVP_CIPHER_CTX *ctx; + int len; + ctx = EVP_CIPHER_CTX_new(); + EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key.raw, iv.raw); + + td::MutableSlice data_slice(data, DATA_SIZE); + td::MutableSlice dest_slice(dest, DATA_SIZE); + td::AesCtrState state; + state.init(as_slice(key), as_slice(iv)); + for (int i = 0; i < n; i++) { + //state.encrypt(data_slice, data_slice); + len = (int)data_slice.size(); + EVP_EncryptUpdate(ctx, dest_slice.ubegin(), &len, data_slice.ubegin(), len); + } + + //EVP_EncryptFinal_ex(ctx, ciphertext + len, &len); + + EVP_CIPHER_CTX_free(ctx); + } +}; + class AesCbcBench : public td::Benchmark { public: alignas(64) unsigned char data[DATA_SIZE]; @@ -346,13 +388,14 @@ class Crc64Bench : public td::Benchmark { int main() { td::init_openssl_threads(); + td::bench(AesCtrBench()); + td::bench(AesCtrOpenSSLBench()); td::bench(AesIgeShortBench()); td::bench(AesIgeShortBench()); td::bench(AesIgeEncryptBench()); td::bench(AesIgeDecryptBench()); td::bench(AesEcbBench()); - td::bench(AesCtrBench()); td::bench(Pbkdf2Bench()); td::bench(RandBench()); From 23b3eb49318477bbe120aae300d44b25770bfb8b Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 31 Jul 2020 05:50:11 +0300 Subject: [PATCH 10/39] Update layer to 118. Support message forward count. GitOrigin-RevId: 10f59fede8b4a86c871949fc721fedd1d615c4bf --- td/generate/scheme/td_api.tl | 13 +- td/generate/scheme/td_api.tlo | Bin 178636 -> 178864 bytes td/generate/scheme/telegram_api.tl | 30 +++- td/generate/scheme/telegram_api.tlo | Bin 210492 -> 213116 bytes td/telegram/CallbackQueriesManager.cpp | 3 +- td/telegram/MessagesManager.cpp | 200 ++++++++++++++++--------- td/telegram/MessagesManager.h | 21 ++- td/telegram/Photo.cpp | 16 ++ td/telegram/ReplyMarkup.cpp | 2 +- td/telegram/SecretChatActor.cpp | 12 +- td/telegram/UpdatesManager.cpp | 18 ++- td/telegram/UpdatesManager.h | 1 + td/telegram/Version.h | 2 +- test/secret.cpp | 4 +- 14 files changed, 226 insertions(+), 96 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 5d93382cb..2213ac164 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -633,6 +633,11 @@ messageForwardOriginChannel chat_id:int53 message_id:int53 author_signature:stri //@from_message_id For messages forwarded to the chat with the current user (Saved Messages) or to the channel's discussion group, the identifier of the original message from which the new message was forwarded last time; 0 if unknown messageForwardInfo origin:MessageForwardOrigin date:int32 public_service_announcement_type:string from_chat_id:int53 from_message_id:int53 = MessageForwardInfo; +//@description Contains information about interactions with a message +//@view_count Number of times the message was viewed +//@forward_count Number of times the message was forwarded +messageInteractionInfo view_count:int32 forward_count:int32 = MessageInteractionInfo; + //@class MessageSendingState @description Contains information about the sending state of the message @@ -660,17 +665,17 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool r //@date Point in time (Unix timestamp) when the message was sent //@edit_date Point in time (Unix timestamp) when the message was last edited //@forward_info Information about the initial message sender; may be null +//@interaction_info Information about interactions with the message; may be null //@reply_to_message_id If non-zero, the identifier of the message this message is replying to; can be the identifier of a deleted message //@ttl For self-destructing messages, the message's TTL (Time To Live), in seconds; 0 if none. TDLib will send updateDeleteMessages or updateMessageContent once the TTL expires //@ttl_expires_in Time left before the message expires, in seconds //@via_bot_user_id If non-zero, the user identifier of the bot through which this message was sent //@author_signature For channel posts, optional author signature -//@views Number of times this message was viewed //@media_album_id Unique identifier of an album this message belongs to. Only photos and videos can be grouped together in albums //@restriction_reason If non-empty, contains a human-readable description of the reason why access to this message must be restricted //@content Content of the message //@reply_markup Reply markup for the message; may be null -message id:int53 sender_user_id:int32 chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool is_channel_post:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo reply_to_message_id:int53 ttl:int32 ttl_expires_in:double via_bot_user_id:int32 author_signature:string views:int32 media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message; +message id:int53 sender_user_id:int32 chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool is_channel_post:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo interaction_info:messageInteractionInfo reply_to_message_id:int53 ttl:int32 ttl_expires_in:double via_bot_user_id:int32 author_signature:string media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message; //@description Contains a list of messages @total_count Approximate total count of messages found @messages List of messages; messages may be null messages total_count:int32 messages:vector = Messages; @@ -3052,8 +3057,8 @@ updateMessageContent chat_id:int53 message_id:int53 new_content:MessageContent = //@description A message was edited. Changes in the message content will come in a separate updateMessageContent @chat_id Chat identifier @message_id Message identifier @edit_date Point in time (Unix timestamp) when the message was edited @reply_markup New message reply markup; may be null updateMessageEdited chat_id:int53 message_id:int53 edit_date:int32 reply_markup:ReplyMarkup = Update; -//@description The view count of the message has changed @chat_id Chat identifier @message_id Message identifier @views New value of the view count -updateMessageViews chat_id:int53 message_id:int53 views:int32 = Update; +//@description The information about interactions with a message has changed @chat_id Chat identifier @message_id Message identifier @interaction_info New information about interactions with the message +updateMessageInteractionInfo chat_id:int53 message_id:int53 interaction_info:messageInteractionInfo = Update; //@description The message content was opened. Updates voice note messages to "listened", video note messages to "viewed" and starts the TTL timer for self-destructing messages @chat_id Chat identifier @message_id Message identifier updateMessageContentOpened chat_id:int53 message_id:int53 = Update; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index fcd50d6d52a5cc985aa7e5a3d3fbb06f79a56e02..0aa7bb80fa85e9b6717435f412467cdbfc09e648 100644 GIT binary patch delta 2787 zcmai0ZA?>F81_9DtXQ)uezY0UW~*71%jhz*kXc<5iECz;l}rcOx>zD?kbn~HlKx;x zU5K(-lP=fvkPNdfF&mqI>e#%fMT%Bo3Rc;_OBDw!og57nk(WvEs$8d|kDZ{{;IaWYh^Q{oyd z(1GkJ3%D05CUMeAlzq|GQ15S)7u<}2xwTO9=Km-SFP!fT z2$*7SzP7U(c2?F{(ZLq~uMWS(!Ghk5<~8&aX72|NdOI{M*To#%z8MUBx*t#{KHIO# zz~u;mhr1Z6!h`3?Ax|gp%sDVAI*W##PQ$!Kat@GeN($RgYz6NbfE8FiF+k%?4}cdj zPlCo#B4P>Hh>oWTs6xwkk~N_f9;Eb2Baa8chYr_y>QKoNJx{UO^OW9rfyn*~gyqSi zqgIF{NdrTYe9k2Ck0+_ByfPJHYwgE2d#ejd-n~?MLpsM0{lmUxZmj zW1WsCE~!T%GDHP!L*T{<149McRq*j4s6>Z;n8@~FP<84aF4*#V{_T%!C4X-iUJ*lX zBM+_)O2ddo z8G$y$bfao}q9r7V;jKpAG)ns+I0|LRijI=(Y2x$QQQ8U{uhNL#tAriZu(*ajBP?Hw zyROk(0nG}nlDp1cqa-U*M9KBajzEeWu{lQyJnNr7`MVB{7MI}3-`3pHxPU%E!25rN zavZ7idcn6z$A1`uaxr>F$EU87qAg=oy?c!IYi5ijnHeKVgd4>3-k_5ly8(9XqsDl} zZuTlSq)Gm&G(|L}A%y+RXx`XY%+7n(gH>$*$i}1N(2We|O|TT?9IS-bc=#qs-=|r* zn6#n*PB^658MJL=8MZ-w5D#+e6|er7%Y;z=*ZA5kklO08E|2kV}i&{6Lb#x zCMfCC2|8@9+k^#f(=etx1xEnHns--o-yPa`0ojQqj^Cj(W6aW|Raq+5sbR4!9gUf+ zwk~%mw(BnCOWuV}%ekisBmjuHhMK#hv$ zAgrc*pq8FXX^;cNSfYr-1K6&z9#Y|yq^1~o2zBVRJt|nSMf|`$*v=hhaPjF!5JZaq zG4&9AOrxd=i%dcb(%L3zr}~UUOHPu8Qp=wIdW1So%d= zN&h-~wp8&%9L%E_(hdh}0AyRXFgt?No7uBv2r75AQrPKXGtXht(Ha(8{5%-_gw1R~ zu=^kjD3)Y8#HJX6$_*y}hM7d)JNWY?)qTUPY8S!7Yzld8AvUKbP9!xQVX>FcEfWPU gYq*ZL9%F~G%Iq;_EH%;BD*qQ!cza9MldMPoFP9M-8UO$Q delta 2630 zcmZWrZ%k8H6!%^?!E5@|IO(CCu7Cb*=?^a(x1$WE0(WITl4B~Z%Ed4@fOGW(af~S>jw_Cm~&zb zwzoXl_U>lQ-Qp@PSdM}9UK<)guLljGR5$#((Go4KF2FqZFQ)g`s0GqLDyyt4JyfRJ zV?CLL>!eS2uU2Z(poB@~vdA6jaAxU}&p#+TS}FZK@B;5mhaWTwrNRXH7M`~es?;L%to**#`na2W>c~^gUMu4$ssu#ugL+cQj`PX6WTo7qCg&6B?{OzOGt_~>Dtq_Q4`9omE;te6lMXWyr*~`>ib-Fa^*pszJgo6tq zSi<*Sf_E@hz69B5*=*qE);4-AXw$pn{x*^v%j9Ud4EdURlB?J?KieLrVp<7vfMxOe zFk~Uc&tV!Z-po9RIlEG(5_w}6joaTv-%g|QH#2>W9JxX@k^+f5as|9dC0?Zt)eOme zz#+NHP3Q|>omb|WswLg?9M$KUO=>u>K$L_Lv}gQlL;4!F06xEl>e zxQE)cU#DRAb!fmgr>_&Kd=zqdeuSj+L{g;7;g=$?4KrpUU^f;v;}?5j2Y2^Ua80jX zL%Glkb$}_kedI3hOMXdhc?SEa)#*N{M$Few4L0;cD`EvV2-C!uZxF%b8`QZl0B-xj zz42f6i8nKFZxmOS9mYLTJ3vK41C$*fpao#LNto*pduqYFb6=NbYxdK-tpVU%Kgm5*)Wi6K(nI!qab!%(mD z4X2!MOZmQG*vfPNg2(8!kI>HdZ)c(u`$^!nBeb-dMo8!G5t3tWgi45`;71a9l(6V1 z4P+jprgF!i0^pIND%K3=D7n+7&mt(l~g+B zSj+QcG=V2Z#C0(!$AqUbn#wvs#VRIrOp<@p*L`fl_zshlT0Kd0fk~)CI_F)&ymz4; zFI;bWuukEs-zhyiwiQ#LMXnK*`GO2 z4LI>7BvMZBS5}RfFNY01AF9l}%$}}5T>B{qyL3h+cNg;kdgR^Ap;^k%ZuWGQ5nhCr zeIJ`$fGJh`S#a4xu-3z7w;)(^oZzQ!@*g{s%ApxefpT diff --git a/td/generate/scheme/telegram_api.tl b/td/generate/scheme/telegram_api.tl index 348026e44..af17ed2c4 100644 --- a/td/generate/scheme/telegram_api.tl +++ b/td/generate/scheme/telegram_api.tl @@ -128,7 +128,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto; chatPhoto#d20b9f3c flags:# has_video:flags.0?true photo_small:FileLocation photo_big:FileLocation dc_id:int = ChatPhoto; messageEmpty#83e5de54 id:int = Message; -message#452c0e65 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector = Message; +message#f52e6b7f flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector views:flags.10?int forwards:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector = Message; messageService#9e19a1f6 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?int to_id:Peer reply_to_msg_id:flags.3?int date:int action:MessageAction = Message; messageMediaEmpty#3ded6320 = MessageMedia; @@ -179,6 +179,7 @@ photoSizeEmpty#e17e23c type:string = PhotoSize; photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize; photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize; photoStrippedSize#e0b0bc2e type:string bytes:bytes = PhotoSize; +photoSizeProgressive#5aa86a51 type:string location:FileLocation w:int h:int sizes:Vector = PhotoSize; geoPointEmpty#1117dd5f = GeoPoint; geoPoint#296f104 long:double lat:double access_hash:long = GeoPoint; @@ -345,6 +346,7 @@ updateDialogFilterOrder#a5d72105 order:Vector = Update; updateDialogFilters#3504914f = Update; updatePhoneCallSignalingData#2661bf09 phone_call_id:long data:bytes = Update; updateChannelParticipant#65d2b464 flags:# channel_id:int date:int user_id:int prev_participant:flags.0?ChannelParticipant new_participant:flags.1?ChannelParticipant qts:int = Update; +updateChannelMessageForwards#6e8a84df channel_id:int id:int forwards:int = Update; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; @@ -534,7 +536,7 @@ botInfo#98e81d3a user_id:int description:string commands:Vector = Bo keyboardButton#a2fa4880 text:string = KeyboardButton; keyboardButtonUrl#258aff05 text:string url:string = KeyboardButton; -keyboardButtonCallback#683a5e46 text:string data:bytes = KeyboardButton; +keyboardButtonCallback#35bbdb6b flags:# requires_password:flags.0?true text:string data:bytes = KeyboardButton; keyboardButtonRequestPhone#b16a6c29 text:string = KeyboardButton; keyboardButtonRequestGeoLocation#fc796b3f text:string = KeyboardButton; keyboardButtonSwitchInline#568a748 flags:# same_peer:flags.0?true text:string query:string = KeyboardButton; @@ -1137,6 +1139,17 @@ stats.megagroupStats#ef7ff916 period:StatsDateRangeDays members:StatsAbsValueAnd globalPrivacySettings#bea2f424 flags:# archive_and_mute_new_noncontact_peers:flags.0?Bool = GlobalPrivacySettings; +messageViews#6d24f493 views:int forwards:int = MessageViews; + +stats.messageStats#8999f295 views_graph:StatsGraph = stats.MessageStats; + +help.countryCode#4203c5ef flags:# country_code:string prefixes:flags.0?Vector patterns:flags.1?Vector = help.CountryCode; + +help.country#c3878e23 flags:# hidden:flags.0?true iso2:string default_name:string name:flags.1?string country_codes:Vector = help.Country; + +help.countriesListNotModified#93cc1f32 = help.CountriesList; +help.countriesList#87d0759e countries:Vector hash:int = help.CountriesList; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -1286,8 +1299,8 @@ messages.acceptEncryption#3dbc0415 peer:InputEncryptedChat g_b:bytes key_fingerp messages.discardEncryption#edd923c5 chat_id:int = Bool; messages.setEncryptedTyping#791451ed peer:InputEncryptedChat typing:Bool = Bool; messages.readEncryptedHistory#7f4b690a peer:InputEncryptedChat max_date:int = Bool; -messages.sendEncrypted#a9776773 peer:InputEncryptedChat random_id:long data:bytes = messages.SentEncryptedMessage; -messages.sendEncryptedFile#9a901b66 peer:InputEncryptedChat random_id:long data:bytes file:InputEncryptedFile = messages.SentEncryptedMessage; +messages.sendEncrypted#44fa7a15 flags:# silent:flags.0?true peer:InputEncryptedChat random_id:long data:bytes = messages.SentEncryptedMessage; +messages.sendEncryptedFile#5559481d flags:# silent:flags.0?true peer:InputEncryptedChat random_id:long data:bytes file:InputEncryptedFile = messages.SentEncryptedMessage; messages.sendEncryptedService#32d439a4 peer:InputEncryptedChat random_id:long data:bytes = messages.SentEncryptedMessage; messages.receivedQueue#55a5bb66 max_qts:int = Vector; messages.reportEncryptedSpam#4b0c8c0f peer:InputEncryptedChat = Bool; @@ -1302,10 +1315,10 @@ messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet messages.installStickerSet#c78fe460 stickerset:InputStickerSet archived:Bool = messages.StickerSetInstallResult; messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool; messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_param:string = Updates; -messages.getMessagesViews#c4c8a55d peer:InputPeer id:Vector increment:Bool = Vector; +messages.getMessagesViews#fdac5dba peer:InputPeer id:Vector increment:Bool = Vector; messages.editChatAdmin#a9e69f2e chat_id:int user_id:InputUser is_admin:Bool = Bool; messages.migrateChat#15a3b8e3 chat_id:int = Updates; -messages.searchGlobal#bf7225a4 flags:# folder_id:flags.0?int q:string offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages; +messages.searchGlobal#734dd16d flags:# folder_id:flags.0?int q:string filter:MessagesFilter offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages; messages.reorderStickerSets#78337739 flags:# masks:flags.0?true order:Vector = Bool; messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document; messages.getSavedGifs#83bf3d52 hash:int = messages.SavedGifs; @@ -1316,7 +1329,7 @@ messages.sendInlineBotResult#220815b0 flags:# silent:flags.5?true background:fla messages.getMessageEditData#fda68d36 peer:InputPeer id:int = messages.MessageEditData; messages.editMessage#48f71778 flags:# no_webpage:flags.1?true peer:InputPeer id:int message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector schedule_date:flags.15?int = Updates; messages.editInlineBotMessage#83557dba flags:# no_webpage:flags.1?true id:InputBotInlineMessageID message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector = Bool; -messages.getBotCallbackAnswer#810a9fec flags:# game:flags.1?true peer:InputPeer msg_id:int data:flags.0?bytes = messages.BotCallbackAnswer; +messages.getBotCallbackAnswer#9342ca07 flags:# game:flags.1?true peer:InputPeer msg_id:int data:flags.0?bytes password:flags.2?InputCheckPasswordSRP = messages.BotCallbackAnswer; messages.setBotCallbackAnswer#d58f130a flags:# alert:flags.1?true query_id:long message:flags.0?string url:flags.2?string cache_time:int = Bool; messages.getPeerDialogs#e470bcfd peers:Vector = messages.PeerDialogs; messages.saveDraft#bc39e14b flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?int peer:InputPeer message:string entities:flags.3?Vector = Bool; @@ -1421,6 +1434,7 @@ help.editUserInfo#66b91b70 user_id:InputUser message:string entities:Vector = messages.AffectedMessages; @@ -1498,3 +1512,5 @@ folders.deleteFolder#1c295881 folder_id:int = Updates; stats.getBroadcastStats#ab42441a flags:# dark:flags.0?true channel:InputChannel = stats.BroadcastStats; stats.loadAsyncGraph#621d5fa0 flags:# token:string x:flags.0?long = StatsGraph; stats.getMegagroupStats#dcdf8607 flags:# dark:flags.0?true channel:InputChannel = stats.MegagroupStats; +stats.getMessagePublicForwards#5630281b channel:InputChannel msg_id:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages; +stats.getMessageStats#b6e0a3f5 flags:# dark:flags.0?true channel:InputChannel msg_id:int = stats.MessageStats; diff --git a/td/generate/scheme/telegram_api.tlo b/td/generate/scheme/telegram_api.tlo index 4ca7e201b8940f53b8ff71eb8fa3c5faf0085bf8..d8d4c7c1bd133aab24077c0d8bb0d3b48e00bc4a 100644 GIT binary patch delta 4225 zcmaJ^e{hRw9?$nlQmsvQqFOCt`?}UNw-=YSTSnrjK(Mn5KAx z!P0r&89wilbx})GXGWHx-?oF9Z>PA*{2~7|-!iXGXQYetnN7AqrsUK`qt+UeJ`8wD zLtfo96)yS7=H$%A`IhvwGH*p-M4`WGVW`sQ4LW_n5cTT^_RIOh$}^?}+R}AxgERhf zRzJy{2p0N1UPfqo@^(>5=7vXKtV#=pN<+aBnt#)jk9AuIHaQ9$0Pi>bZgg;fQ3*vy z+lsPjmUFrq7!5e31i0DheD>9pJ7trBhaZ_*KhdB>+2o;tGBr80zQ@iFrtVyR2zT44 zyIZm=xf9uJf2(gv`R${l2b6o4&i0p9dL~tcLjHw?r4<#kOXrm96kh6b*!%UX^e(FM zReFQ70;R#=5`QJ0ItKlztJjV-g~CGv4`{N=w3f3@9fna zjk|7m`Xb_fYURw~>-qHf)3xfy1{ZLf8)~3SMKA;!MBN|Raol_`W8+y!!G8ga;vBgI ziq(@`L!c#zr`yqC8>Uu4%a4+t&&o&q&}RW}D}{FRT$*zb!kh3vd3|395R~%3gyCep zg*rYkqA?Y&sLHS-6(oKNbQ3#9@4`;3=nK{z-ERW#+k<9k9XdqqTg`ydw?SrH!4yLT zFP(rK8V(w9XddJl6kLwv!{!3D-sqkS>r<4}4t@yVQKn+FztlFFc#7HzZ8 z*jSC$J&*aO$RVRO@>8@7a^t!P(`Cia%_PUJuqF1()cHF4muOgLSTjvq7hBN24+=O(**?L`T({x!M?}JyU6?lS7gWc7Xyy`6;uw=~VsyWV zX>*hCGtvY_oY~YYsC8SIdUyP@wpp`5Yj#>N+6?2kfcb!CQFa^v2{`CEC^Sn+kcIUJ zh5F7o!7Phncw|kpTqlD`(@=j%gd_nQBll`Enht@4jz*ZwZMY8$8!HZr8a_EJ!hfL& znvV!|u_LftQ*cx$=$a<7d+aD!<7IkzAC?>gtDf~C&BlC;$Y7)PBNEo!Be`fh1e2-z z5pT%q;|Ucv;LtXhh4!P6jDaKI;2sp8NMK>s4*!fgwpupk0Sj2u(#=>nv+bnlrIwST zMx7^x+pEif5fCrDqq zx;G8&07mRN&1QMrY2k<`eyX$U^YQp;*u{OQIP-jnFBxoeiwM!tB6?zdi|C0+3yjfv zqWdhnjYK>zFV3cOVy40wkdHm*;P2dzhkq9NVMgp27^XL4-A0nGd3jz7gf+JfBjO7m zo(J2jb7Z>!)>l(2F1#+k4HsTln;6r~Ju_VtRd2W`k{!unDek!lOE^pQH-b?A4Q%F^ zqg7Ktqbn^K`=bc7zE$Kp+6p1gTXZR*=MA{%GL&P*2at|WF0p?LwO6t(3o%xX5FWb> zt(>stikPAB714?huL$Ss?-1?Qaz+JTAS(EFMqihL2XQ{NU^U~3mH&6B4y|c>o$UEG z(FLlk?W*{6Ulp!J&lA?BSK*gD4%4@Spk8}{7U6DfoS=i*=t%To`H$q;y(8UxU4lz)3U_O7!V2!6`IZQ> zE>mC4vF2NXFLq1Z+t%B!)9kq|oZEDpZDVTWk8g|ab6q0&)OR=s!~0<<&fE>zc<2tS z7_YD;?j!eBtX^oTQg`^mveJbMy%pM${R@BP61LJR`;;Q1Z5#aFRkk)hb+Y3wgpEd3 zEB#CL$c-_!EEe3?{>0>(`(V|sBz9acJN^od?|t@8b}JpC?)!5R9|*tlho<;FzPUcH zN2gOB5sJ;k%UHn@ecw_QUCAFB&*_QF62?6EZ})zh5+|$Dn3o0vjmk?zhp-(+T3^)r z?2*C+mohO0qY~PUNo78d2fr_e9HYS(^uL1>uYjeG$2+&Qsv<^-E(7cy~1S8(M$kzx{habhhQOzZdcF?#3v zs=YK2wPM$4Vq#EIQfVmUtz1a!Ca74tK@pc@5;3Il#oC=gs?j})9D4rKEH@MoiSP92 z7)NT+^&aU|d1Urk#?=@{NSKn(o1y>hs7Ku`oHx{#X z9ebvd!6uOig+*?jL9+PMOpbm`LYldv5~6LI46H@dOcLdWV>1cgQg*mMAsTZWLxzRq zVmFHsek1qulHk-~J6HZXn4xyxJa4Elu>qfT9l@_o6C0*(ha7{_9dh+SV#zl2xj2d9 zrgmbbY=gnhcCv;#ZW!^)FUTAC#7NB8>?i4R&2>^{G8~!N*n^$lkwZr1*`brazE8Fe zGAwAD5=3V&k!bq9;W)et`eS1+Tf!?QvE|fqk0i?vdr1I{8O#1Vc>n_F2N-pI7H>XH zW6SK=m8Bnp<3R7Cu7+fE6TR6mr0Am$H-bJ_bx5JhjBd>vKGK~;39}(Wp(*OVf delta 3298 zcmaJ@Z){W770Eup^jVe{s%5+X~N+wL> z30CEUC!x*LGR^8ubHbXcd;p1V9d&V*mkyJ>fCrSiU`U|+NrE>;Ths+9+xmeI0e0WJ z?-~a|-luba=iJ}am96HmR=J~UYb>%Y-d3?Cv+MDUEt6i| zT%GZL&kyiirv0hTr6v(!*M3q z6N{R$QGH(J!dLSiQ^15D+_dm#2WD4-;xrNvDP8>5L#;n}bwiYP-E!SyTlhA}RJpBi zuE1>{7fS4hZa3V6IPX|C$}=jB--&Vc%pD#@DXw<{a4)hSyrwZGc9QycZo%*QDh0q9 zQ3sgg*Z{FGx_?YXrvyQcMD9ka~|n zl0)H-m^0H{dC7N4H+ zvKQB+$#XQ-X2;OG#LYK*jx4Y`|LZ199bt_&11=t617J#yjKIPffu%B_a&0bSMS!yz zQ3(Hlu!{{qoZHPXtQ1luj!uJ@-e_Jy)4%Xz;gZO#@E2<*%RR<7#s{scV&5P%b8LFB zENxWW#6gprom>~z1eyPj;KoB5G+Gg87B>xVSFw4Bjk=j%<0ryF_!9_oEGIB(^k#01 z$k@GCm^J>@^1z7d>8Bw z=CF z1f1wN%Pg|Dhz%#sitEmG4!osC0FLe>tGS0g=gK-H;piz?jfHB-f#Gvtr?E>i=9dy% zZ-HIfW<8aH2sK!M{T!PsSTmrpM*4w+kqhM~3~RTNI{Sjr)Gr98*$dFXH+jay@opXy zSYm9k(q)-lDKUb7KgQxu>(Fp_%p&89?cYBR>OK3ZJ?=!;MUnBki&mUwh4W9dy7pg$ z01tRtDA94LblHnbnHJyjVQQ4UZ9?z4?*=q~NwiFPrXII`0XsNX?hEm2P+tTe^}gn! z>J}%4E{i&KT^7@D;4*acO$}EBX3p}5{{>}XnFmS+iCLne{i?W7JXfu*Q9bB(mA^t3 zv?+O2M8zF!B3^V{6C_@CUQ6Wz{LgN(3?n6N*R`_X*5HjBWEGG4CR054C^bxojKdS+ z8km_7RE|m5!&$l~h27Ak)sWt)#fTfHL@u!@_8Kz>IzJ`KVEo*C*I~xQwOkR>m6e7` z1>N}4S`2*&4jlTYxUAI~=)t~!S=Wrlmi|U9wrWy zBgA?bw!Tifc!~xO&b5&!-?l&z*FxLLkPIzabqDF(JUC1oE9BYtANnOaCt0WW?j&ol zeUkk4?R_@QJ4K>)`IUpGbJ+7G8AAOCacHgoCOwbI2cCFy1iz}36ihY|ANs4LX3SSf zHZ5Hx#X#=dzWW38*d&DpuDh_mS_&~fOg~Q?^6Se}e?Vuonet_query_creator().create(telegram_api::messages_getBotCallbackAnswer( - flags, false /*ignored*/, std::move(input_peer), message_id.get_server_message_id().get(), std::move(data))); + flags, false /*ignored*/, std::move(input_peer), message_id.get_server_message_id().get(), std::move(data), + nullptr)); net_query->need_resend_on_503_ = false; send_query(std::move(net_query)); } diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index b93c4e704..0f8fbf51a 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -1264,8 +1264,8 @@ class GetMessagesViewsQuery : public Td::ResultHandler { auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read); if (input_peer == nullptr) { - LOG(ERROR) << "Can't update message views because doesn't have info about the " << dialog_id; - return on_error(0, Status::Error(500, "Can't update message views")); + LOG(ERROR) << "Can't update message view count because doesn't have info about the " << dialog_id; + return on_error(0, Status::Error(500, "Can't update message view count")); } LOG(INFO) << "View " << message_ids_.size() << " messages in " << dialog_id @@ -1280,14 +1280,13 @@ class GetMessagesViewsQuery : public Td::ResultHandler { return on_error(id, result_ptr.move_as_error()); } - vector views = result_ptr.move_as_ok(); - LOG(INFO) << "Receive result for GetMessagesViewsQuery: " << format::as_array(views); - if (message_ids_.size() != views.size()) { + auto interaction_infos = result_ptr.move_as_ok(); + if (message_ids_.size() != interaction_infos.size()) { return on_error(id, Status::Error(500, "Wrong number of message views returned")); } - for (size_t i = 0; i < message_ids_.size(); i++) { - td->messages_manager_->on_update_message_views({dialog_id_, message_ids_[i]}, views[i]); + td->messages_manager_->on_update_message_interaction_info( + {dialog_id_, message_ids_[i]}, interaction_infos[i]->views_, interaction_infos[i]->forwards_); } } @@ -1671,9 +1670,9 @@ class SearchMessagesGlobalQuery : public Td::ResultHandler { if (!ignore_folder_id) { flags |= telegram_api::messages_searchGlobal::FOLDER_ID_MASK; } - send_query(G()->net_query_creator().create( - telegram_api::messages_searchGlobal(flags, folder_id.get(), query, offset_date_, std::move(input_peer), - offset_message_id.get_server_message_id().get(), limit))); + send_query(G()->net_query_creator().create(telegram_api::messages_searchGlobal( + flags, folder_id.get(), query, make_tl_object(), offset_date_, + std::move(input_peer), offset_message_id.get_server_message_id().get(), limit))); } void on_result(uint64 id, BufferSlice packet) override { @@ -4107,7 +4106,7 @@ void MessagesManager::Message::store(StorerT &storer) const { bool is_reply = reply_to_message_id.is_valid(); bool is_reply_to_random_id = reply_to_random_id != 0; bool is_via_bot = via_bot_user_id.is_valid(); - bool has_views = views > 0; + bool has_view_count = view_count > 0; bool has_reply_markup = reply_markup != nullptr; bool has_ttl = ttl != 0; bool has_author_signature = !author_signature.empty(); @@ -4124,6 +4123,7 @@ void MessagesManager::Message::store(StorerT &storer) const { bool has_legacy_layer = legacy_layer != 0; bool has_restriction_reasons = !restriction_reasons.empty(); bool has_forward_psa_type = is_forwarded && !forward_info->psa_type.empty(); + bool has_forward_count = forward_count > 0; BEGIN_STORE_FLAGS(); STORE_FLAG(is_channel_post); STORE_FLAG(is_outgoing); @@ -4142,7 +4142,7 @@ void MessagesManager::Message::store(StorerT &storer) const { STORE_FLAG(is_reply); STORE_FLAG(is_reply_to_random_id); STORE_FLAG(is_via_bot); - STORE_FLAG(has_views); + STORE_FLAG(has_view_count); STORE_FLAG(has_reply_markup); STORE_FLAG(has_ttl); STORE_FLAG(has_author_signature); @@ -4172,6 +4172,7 @@ void MessagesManager::Message::store(StorerT &storer) const { STORE_FLAG(is_from_scheduled); STORE_FLAG(is_copy); STORE_FLAG(has_forward_psa_type); + STORE_FLAG(has_forward_count); END_STORE_FLAGS(); } @@ -4221,8 +4222,11 @@ void MessagesManager::Message::store(StorerT &storer) const { if (is_via_bot) { store(via_bot_user_id, storer); } - if (has_views) { - store(views, storer); + if (has_view_count) { + store(view_count, storer); + } + if (has_forward_count) { + store(forward_count, storer); } if (has_ttl) { store(ttl, storer); @@ -4267,7 +4271,7 @@ void MessagesManager::Message::parse(ParserT &parser) { bool is_reply; bool is_reply_to_random_id; bool is_via_bot; - bool has_views; + bool has_view_count; bool has_reply_markup; bool has_ttl; bool has_author_signature; @@ -4283,6 +4287,7 @@ void MessagesManager::Message::parse(ParserT &parser) { bool has_legacy_layer = false; bool has_restriction_reasons = false; bool has_forward_psa_type = false; + bool has_forward_count = false; BEGIN_PARSE_FLAGS(); PARSE_FLAG(is_channel_post); PARSE_FLAG(is_outgoing); @@ -4301,7 +4306,7 @@ void MessagesManager::Message::parse(ParserT &parser) { PARSE_FLAG(is_reply); PARSE_FLAG(is_reply_to_random_id); PARSE_FLAG(is_via_bot); - PARSE_FLAG(has_views); + PARSE_FLAG(has_view_count); PARSE_FLAG(has_reply_markup); PARSE_FLAG(has_ttl); PARSE_FLAG(has_author_signature); @@ -4331,6 +4336,7 @@ void MessagesManager::Message::parse(ParserT &parser) { PARSE_FLAG(is_from_scheduled); PARSE_FLAG(is_copy); PARSE_FLAG(has_forward_psa_type); + PARSE_FLAG(has_forward_count); END_PARSE_FLAGS(); } @@ -4386,8 +4392,11 @@ void MessagesManager::Message::parse(ParserT &parser) { if (is_via_bot) { parse(via_bot_user_id, parser); } - if (has_views) { - parse(views, parser); + if (has_view_count) { + parse(view_count, parser); + } + if (has_forward_count) { + parse(forward_count, parser); } if (has_ttl) { parse(ttl, parser); @@ -5936,27 +5945,29 @@ void MessagesManager::on_update_channel_too_long(tl_object_ptr d->last_new_message_id && - dialog_id.get_type() == DialogType::Channel) { - get_channel_difference(dialog_id, d->pts, true, "on_update_message_views"); - } +void MessagesManager::on_update_message_view_count(FullMessageId full_message_id, int32 view_count) { + if (view_count < 0) { + LOG(ERROR) << "Receive " << view_count << " views in updateChannelMessageViews for " << full_message_id; return; } + update_message_interaction_info(full_message_id, view_count, -1); +} - if (update_message_views(dialog_id, m, views)) { - on_message_changed(d, m, true, "on_update_message_views"); +void MessagesManager::on_update_message_forward_count(FullMessageId full_message_id, int32 forward_count) { + if (forward_count < 0) { + LOG(ERROR) << "Receive " << forward_count << " forwards in updateChannelMessageForwards for " << full_message_id; + return; } + update_message_interaction_info(full_message_id, -1, forward_count); +} + +void MessagesManager::on_update_message_interaction_info(FullMessageId full_message_id, int32 view_count, + int32 forward_count) { + if (view_count < 0 || forward_count < 0) { + LOG(ERROR) << "Receive " << view_count << "/" << forward_count << " interaction counters for " << full_message_id; + return; + } + update_message_interaction_info(full_message_id, view_count, forward_count); } void MessagesManager::on_pending_message_views_timeout(DialogId dialog_id) { @@ -5984,14 +5995,60 @@ void MessagesManager::on_pending_message_views_timeout(DialogId dialog_id) { d->increment_view_counter = false; } -bool MessagesManager::update_message_views(DialogId dialog_id, Message *m, int32 views) { +void MessagesManager::update_message_interaction_info(FullMessageId full_message_id, int32 view_count, + int32 forward_count) { + auto dialog_id = full_message_id.get_dialog_id(); + Dialog *d = get_dialog_force(dialog_id); + if (d == nullptr) { + return; + } + auto message_id = full_message_id.get_message_id(); + Message *m = get_message_force(d, message_id, "update_message_interaction_info"); + if (m == nullptr) { + LOG(INFO) << "Ignore message interaction info about unknown " << full_message_id; + if (!message_id.is_scheduled() && message_id > d->last_new_message_id && + dialog_id.get_type() == DialogType::Channel) { + get_channel_difference(dialog_id, d->pts, true, "update_message_interaction_info"); + } + return; + } + + if (update_message_interaction_info(dialog_id, m, view_count >= 0 ? view_count : m->view_count, + forward_count >= 0 ? forward_count : m->forward_count)) { + on_message_changed(d, m, true, "on_update_message_view_count"); + } +} + +td_api::object_ptr MessagesManager::get_message_interaction_info_object( + DialogId dialog_id, const Message *m) const { + if (m->view_count == 0 && m->forward_count == 0) { + return nullptr; + } + if (m->message_id.is_scheduled() && (m->forward_info == nullptr || is_broadcast_channel(dialog_id))) { + return nullptr; + } + if (m->message_id.is_local() && m->forward_info == nullptr) { + return nullptr; + } + + return td_api::make_object(m->view_count, m->forward_count); +} + +bool MessagesManager::update_message_interaction_info(DialogId dialog_id, Message *m, int32 view_count, + int32 forward_count) { CHECK(m != nullptr); - if (views > m->views) { - LOG(DEBUG) << "Update views of " << FullMessageId{dialog_id, m->message_id} << " from " << m->views << " to " - << views; - m->views = views; + if (view_count > m->view_count || forward_count > m->forward_count) { + LOG(DEBUG) << "Update interaction info of " << FullMessageId{dialog_id, m->message_id} << " from " << m->view_count + << '/' << m->forward_count << " to " << view_count << '/' << forward_count; + if (view_count > m->view_count) { + m->view_count = view_count; + } + if (forward_count > m->forward_count) { + m->forward_count = forward_count; + } send_closure(G()->td(), &Td::send_update, - make_tl_object(dialog_id.get(), m->message_id.get(), m->views)); + make_tl_object( + dialog_id.get(), m->message_id.get(), get_message_interaction_info_object(dialog_id, m))); return true; } return false; @@ -11805,8 +11862,9 @@ MessagesManager::MessageInfo MessagesManager::parse_telegram_api_message( message_info.via_bot_user_id = UserId(); } } - if (message->flags_ & MESSAGE_FLAG_HAS_VIEWS) { - message_info.views = message->views_; + if (message->flags_ & MESSAGE_FLAG_HAS_INTERACTION_INFO) { + message_info.view_count = message->views_; + message_info.forward_count = message->forwards_; } if (message->flags_ & MESSAGE_FLAG_HAS_EDIT_DATE) { message_info.edit_date = message->edit_date_; @@ -11974,10 +12032,15 @@ std::pair> MessagesManager::creat ttl = max(ttl, get_message_content_duration(message_info.content.get(), td_) + 1); } - int32 views = message_info.views; - if (views < 0) { - LOG(ERROR) << "Wrong views = " << views << " received in " << message_id << " in " << dialog_id; - views = 0; + int32 view_count = message_info.view_count; + if (view_count < 0) { + LOG(ERROR) << "Wrong view_count = " << view_count << " received in " << message_id << " in " << dialog_id; + view_count = 0; + } + int32 forward_count = message_info.forward_count; + if (forward_count < 0) { + LOG(ERROR) << "Wrong forward_count = " << forward_count << " received in " << message_id << " in " << dialog_id; + forward_count = 0; } bool has_forward_info = message_info.forward_header != nullptr; @@ -12009,7 +12072,8 @@ std::pair> MessagesManager::creat message->is_content_secret = is_content_secret; message->hide_edit_date = hide_edit_date; message->is_from_scheduled = is_from_scheduled; - message->views = views; + message->view_count = view_count; + message->forward_count = forward_count; message->legacy_layer = (is_legacy ? MTPROTO_LAYER : 0); message->content = std::move(message_info.content); message->reply_markup = get_reply_markup(std::move(message_info.reply_markup), td_->auth_manager_->is_bot(), false, @@ -17112,7 +17176,7 @@ Status MessagesManager::view_messages(DialogId dialog_id, const vectormessage_id.is_server() && m->views > 0) { + if (m->message_id.is_server() && m->view_count > 0) { d->pending_viewed_message_ids.insert(m->message_id); } @@ -19969,20 +20033,13 @@ tl_object_ptr MessagesManager::get_message_object(DialogId dial auto live_location_date = m->is_failed_to_send ? 0 : m->date; auto date = is_scheduled ? 0 : m->date; auto edit_date = m->hide_edit_date ? 0 : m->edit_date; - auto views = m->views; - if (m->message_id.is_scheduled()) { - if (m->forward_info == nullptr || is_broadcast_channel(dialog_id)) { - views = 0; - } - } else if (m->message_id.is_local() && m->forward_info == nullptr) { - views = 0; - } return make_tl_object( m->message_id.get(), td_->contacts_manager_->get_user_id_object(m->sender_user_id, "sender_user_id"), dialog_id.get(), std::move(sending_state), std::move(scheduling_state), is_outgoing, can_be_edited, can_be_forwarded, can_delete_for_self, can_delete_for_all_users, m->is_channel_post, contains_unread_mention, - date, edit_date, get_message_forward_info_object(m->forward_info), reply_to_message_id, ttl, ttl_expires_in, - td_->contacts_manager_->get_user_id_object(m->via_bot_user_id, "via_bot_user_id"), m->author_signature, views, + date, edit_date, get_message_forward_info_object(m->forward_info), + get_message_interaction_info_object(dialog_id, m), reply_to_message_id, ttl, ttl_expires_in, + td_->contacts_manager_->get_user_id_object(m->via_bot_user_id, "via_bot_user_id"), m->author_signature, media_album_id, get_restriction_reason_description(m->restriction_reasons), get_message_content_object(m->content.get(), td_, live_location_date, m->is_content_secret), get_reply_markup_object(m->reply_markup)); @@ -20046,7 +20103,8 @@ MessagesManager::Message *MessagesManager::get_message_to_send( m->is_channel_post = is_channel_post; m->is_outgoing = is_scheduled || dialog_id != DialogId(my_id); m->from_background = options.from_background; - m->views = is_channel_post && !is_scheduled ? 1 : 0; + m->view_count = is_channel_post && !is_scheduled ? 1 : 0; + m->forward_count = 0; m->content = std::move(content); m->forward_info = std::move(forward_info); m->is_copy = is_copy || forward_info != nullptr; @@ -23022,7 +23080,7 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i for (size_t i = 0; i < message_ids.size(); i++) { MessageId message_id = get_persistent_message_id(from_dialog, message_ids[i]); - const Message *forwarded_message = get_message_force(from_dialog, message_id, "forward_messages"); + Message *forwarded_message = get_message_force(from_dialog, message_id, "forward_messages"); if (forwarded_message == nullptr) { LOG(INFO) << "Can't find " << message_id << " to forward"; continue; @@ -23108,9 +23166,16 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i m->real_forward_from_message_id = message_id; m->via_bot_user_id = forwarded_message->via_bot_user_id; m->in_game_share = in_game_share; - if (forwarded_message->views > 0 && m->forward_info != nullptr && m->views == 0 && + if (forwarded_message->view_count > 0 && is_broadcast_channel(from_dialog_id)) { + if (update_message_interaction_info(from_dialog_id, forwarded_message, forwarded_message->view_count, + forwarded_message->forward_count + 1)) { + on_message_changed(from_dialog, forwarded_message, true, "forward_messages"); + } + } + if (forwarded_message->view_count > 0 && m->forward_info != nullptr && m->view_count == 0 && !(m->message_id.is_scheduled() && is_broadcast_channel(to_dialog_id))) { - m->views = forwarded_message->views; + m->view_count = forwarded_message->view_count; + m->forward_count = forwarded_message->forward_count; } if (is_game) { @@ -23517,7 +23582,8 @@ Result MessagesManager::add_local_message( m->is_outgoing = dialog_id != DialogId(my_id) && sender_user_id == my_id; m->disable_notification = disable_notification; m->from_background = false; - m->views = 0; + m->view_count = 0; + m->forward_count = 0; m->content = std::move(message_content.content); m->disable_web_page_preview = message_content.disable_web_page_preview; m->clear_draft = message_content.clear_draft; @@ -25796,8 +25862,8 @@ void MessagesManager::fail_send_message(FullMessageId full_message_id, int error } else { CHECK(message->message_id.is_valid()); } - if (message->forward_info == nullptr && message->views == 1) { - message->views = 0; + if (message->forward_info == nullptr && message->view_count == 1) { + message->view_count = 0; } message->is_failed_to_send = true; message->send_error_code = error_code; @@ -29863,7 +29929,7 @@ bool MessagesManager::update_message(Dialog *d, Message *old_message, unique_ptr update_message_contains_unread_mention(d, old_message, new_message->contains_unread_mention, "update_message")) { need_send_update = true; } - if (update_message_views(dialog_id, old_message, new_message->views)) { + if (update_message_interaction_info(dialog_id, old_message, new_message->view_count, new_message->forward_count)) { need_send_update = true; } if (old_message->restriction_reasons != new_message->restriction_reasons) { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index c267253cb..0103d6700 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -151,7 +151,7 @@ class MessagesManager : public Actor { static constexpr int32 MESSAGE_FLAG_HAS_ENTITIES = 1 << 7; static constexpr int32 MESSAGE_FLAG_HAS_FROM_ID = 1 << 8; static constexpr int32 MESSAGE_FLAG_HAS_MEDIA = 1 << 9; - static constexpr int32 MESSAGE_FLAG_HAS_VIEWS = 1 << 10; + static constexpr int32 MESSAGE_FLAG_HAS_INTERACTION_INFO = 1 << 10; static constexpr int32 MESSAGE_FLAG_IS_SENT_VIA_BOT = 1 << 11; static constexpr int32 MESSAGE_FLAG_IS_SILENT = 1 << 13; static constexpr int32 MESSAGE_FLAG_IS_POST = 1 << 14; @@ -323,7 +323,11 @@ class MessagesManager : public Actor { void on_update_channel_too_long(tl_object_ptr &&update, bool force_apply); - void on_update_message_views(FullMessageId full_message_id, int32 views); + void on_update_message_view_count(FullMessageId full_message_id, int32 view_count); + + void on_update_message_forward_count(FullMessageId full_message_id, int32 forward_count); + + void on_update_message_interaction_info(FullMessageId full_message_id, int32 view_count, int32 forward_count); void on_update_live_location_viewed(FullMessageId full_message_id); @@ -887,7 +891,8 @@ class MessagesManager : public Actor { tl_object_ptr forward_header; MessageId reply_to_message_id; UserId via_bot_user_id; - int32 views = 0; + int32 view_count = 0; + int32 forward_count = 0; int32 flags = 0; int32 edit_date = 0; vector restriction_reasons; @@ -999,7 +1004,8 @@ class MessagesManager : public Actor { NotificationId notification_id; NotificationId removed_notification_id; - int32 views = 0; + int32 view_count = 0; + int32 forward_count = 0; int32 legacy_layer = 0; int32 send_error_code = 0; @@ -1820,7 +1826,12 @@ class MessagesManager : public Actor { void on_pending_message_views_timeout(DialogId dialog_id); - bool update_message_views(DialogId dialog_id, Message *m, int32 views); + void update_message_interaction_info(FullMessageId full_message_id, int32 view_count, int32 forward_count); + + td_api::object_ptr get_message_interaction_info_object(DialogId dialog_id, + const Message *m) const; + + bool update_message_interaction_info(DialogId dialog_id, Message *m, int32 view_count, int32 forward_count); bool update_message_contains_unread_mention(Dialog *d, Message *m, bool contains_unread_mention, const char *source); diff --git a/td/telegram/Photo.cpp b/td/telegram/Photo.cpp index 0d7ab0ea1..b14b6023f 100644 --- a/td/telegram/Photo.cpp +++ b/td/telegram/Photo.cpp @@ -395,6 +395,22 @@ Variant get_photo_size(FileManager *file_manager, PhotoSizeSo auto size = move_tl_object_as(size_ptr); return size->bytes_.as_slice().str(); } + case telegram_api::photoSizeProgressive::ID: { + auto size = move_tl_object_as(size_ptr); + + if (size->sizes_.empty()) { + LOG(ERROR) << "Receive " << to_string(size); + return std::move(res); + } + std::sort(size->sizes_.begin(), size->sizes_.end()); + + type = std::move(size->type_); + location = std::move(size->location_); + res.dimensions = get_dimensions(size->w_, size->h_); + res.size = size->sizes_.back(); + + break; + } default: UNREACHABLE(); break; diff --git a/td/telegram/ReplyMarkup.cpp b/td/telegram/ReplyMarkup.cpp index 65deae1a0..12f37fa3d 100644 --- a/td/telegram/ReplyMarkup.cpp +++ b/td/telegram/ReplyMarkup.cpp @@ -618,7 +618,7 @@ static tl_object_ptr get_inline_keyboard_button( case InlineKeyboardButton::Type::Url: return make_tl_object(keyboard_button.text, keyboard_button.data); case InlineKeyboardButton::Type::Callback: - return make_tl_object(keyboard_button.text, + return make_tl_object(0, false /*ignored*/, keyboard_button.text, BufferSlice(keyboard_button.data)); case InlineKeyboardButton::Type::CallbackGame: return make_tl_object(keyboard_button.text); diff --git a/td/telegram/SecretChatActor.cpp b/td/telegram/SecretChatActor.cpp index 06f0a71fb..a46f7bd5b 100644 --- a/td/telegram/SecretChatActor.cpp +++ b/td/telegram/SecretChatActor.cpp @@ -1468,13 +1468,13 @@ NetQueryPtr SecretChatActor::create_net_query(const logevent::OutboundSecretMess message.encrypted_message.clone())); } else if (message.file.empty()) { query = create_net_query( - QueryType::Message, - telegram_api::messages_sendEncrypted(get_input_chat(), message.random_id, message.encrypted_message.clone())); + QueryType::Message, telegram_api::messages_sendEncrypted(0, false /*ignored*/, get_input_chat(), + message.random_id, message.encrypted_message.clone())); } else { - query = create_net_query( - QueryType::Message, - telegram_api::messages_sendEncryptedFile(get_input_chat(), message.random_id, message.encrypted_message.clone(), - message.file.as_input_encrypted_file())); + query = create_net_query(QueryType::Message, + telegram_api::messages_sendEncryptedFile( + 0, false /*ignored*/, get_input_chat(), message.random_id, + message.encrypted_message.clone(), message.file.as_input_encrypted_file())); } if (!message.is_rewritable) { query->total_timeout_limit_ = 1000000000; // inf. We will re-sent it immediately anyway diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 8eb33dc54..954a229c8 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -696,7 +696,7 @@ void UpdatesManager::on_get_updates(tl_object_ptr &&updat false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, update->id_, from_id, make_tl_object(update->user_id_), std::move(update->fwd_from_), update->via_bot_id_, update->reply_to_msg_id_, update->date_, update->message_, nullptr, nullptr, - std::move(update->entities_), 0, 0, "", 0, Auto()), + std::move(update->entities_), 0, 0, 0, "", 0, Auto()), update->pts_, update->pts_count_), 0, "telegram_api::updatesShortMessage"); break; @@ -720,7 +720,7 @@ void UpdatesManager::on_get_updates(tl_object_ptr &&updat false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, update->id_, update->from_id_, make_tl_object(update->chat_id_), std::move(update->fwd_from_), update->via_bot_id_, update->reply_to_msg_id_, update->date_, - update->message_, nullptr, nullptr, std::move(update->entities_), 0, 0, "", 0, Auto()), + update->message_, nullptr, nullptr, std::move(update->entities_), 0, 0, 0, "", 0, Auto()), update->pts_, update->pts_count_), 0, "telegram_api::updatesShortChatMessage"); break; @@ -1684,7 +1684,19 @@ void UpdatesManager::on_update(tl_object_ptrmessages_manager_->on_update_message_views({dialog_id, MessageId(ServerMessageId(update->id_))}, update->views_); + td_->messages_manager_->on_update_message_view_count({dialog_id, MessageId(ServerMessageId(update->id_))}, + update->views_); +} + +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { + ChannelId channel_id(update->channel_id_); + if (!channel_id.is_valid()) { + LOG(ERROR) << "Receive invalid " << channel_id; + return; + } + DialogId dialog_id(channel_id); + td_->messages_manager_->on_update_message_forward_count({dialog_id, MessageId(ServerMessageId(update->id_))}, + update->forwards_); } void UpdatesManager::on_update(tl_object_ptr update, diff --git a/td/telegram/UpdatesManager.h b/td/telegram/UpdatesManager.h index 91c50760c..a0c931705 100644 --- a/td/telegram/UpdatesManager.h +++ b/td/telegram/UpdatesManager.h @@ -243,6 +243,7 @@ class UpdatesManager : public Actor { void on_update(tl_object_ptr update, bool /*force_apply*/); void on_update(tl_object_ptr update, bool force_apply); void on_update(tl_object_ptr update, bool force_apply); + void on_update(tl_object_ptr update, bool force_apply); void on_update(tl_object_ptr update, bool /*force_apply*/); void on_update(tl_object_ptr update, bool /*force_apply*/); diff --git a/td/telegram/Version.h b/td/telegram/Version.h index d5436e02d..9891f0e48 100644 --- a/td/telegram/Version.h +++ b/td/telegram/Version.h @@ -8,7 +8,7 @@ namespace td { -constexpr int32 MTPROTO_LAYER = 117; +constexpr int32 MTPROTO_LAYER = 118; enum class Version : int32 { Initial, // 0 diff --git a/test/secret.cpp b/test/secret.cpp index b6041789e..170f4317a 100644 --- a/test/secret.cpp +++ b/test/secret.cpp @@ -177,6 +177,7 @@ class messages_sendEncryptedService final { class messages_sendEncrypted final { public: + int32 flags_; tl_object_ptr peer_; int64 random_id_{}; BufferSlice data_; @@ -185,7 +186,8 @@ class messages_sendEncrypted final { static const int32 ID = -1451792525; explicit messages_sendEncrypted(TlBufferParser &p) - : peer_(TlFetchBoxed, -247351839>::parse(p)) + : flags_(TlFetchInt::parse(p)) + , peer_(TlFetchBoxed, -247351839>::parse(p)) , random_id_(TlFetchLong::parse(p)) , data_(TlFetchBytes::parse(p)) { } From 8e77eacc725cc6cfe6455d22dde0fdbee6d44318 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 31 Jul 2020 20:03:57 +0300 Subject: [PATCH 11/39] Update message interaction info after receiving channel statistics. GitOrigin-RevId: 6ec1b365c9f1299da1849fa6767f4ec79b627f90 --- td/telegram/ContactsManager.cpp | 12 ++++++++---- td/telegram/ContactsManager.h | 5 +++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index d3614bd37..b2b0af710 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -2742,7 +2742,7 @@ tl_object_ptr ContactsManager::convert_stats_absolute_v get_percentage_value(obj->current_ - obj->previous_, obj->previous_)); } -tl_object_ptr ContactsManager::convert_megagroup_stats( +tl_object_ptr ContactsManager::convert_megagroup_stats( tl_object_ptr obj) { CHECK(obj != nullptr); @@ -2785,7 +2785,7 @@ tl_object_ptr ContactsManager::convert_megagroup_stats( std::move(top_inviters)); } -tl_object_ptr ContactsManager::convert_broadcast_stats( +tl_object_ptr ContactsManager::convert_broadcast_stats( tl_object_ptr obj) { CHECK(obj != nullptr); @@ -2874,8 +2874,12 @@ class GetBroadcastStatsQuery : public Td::ResultHandler { return on_error(id, result_ptr.move_as_error()); } - auto result = result_ptr.move_as_ok(); - promise_.set_value(ContactsManager::convert_broadcast_stats(std::move(result))); + auto result = ContactsManager::convert_broadcast_stats(result_ptr.move_as_ok()); + for (auto &info : result->recent_message_interactions_) { + td->messages_manager_->on_update_message_interaction_info({DialogId(channel_id_), MessageId(info->message_id_)}, + info->view_count_, info->forward_count_); + } + promise_.set_value(std::move(result)); } void on_error(uint64 id, Status status) override { diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 8850e85eb..3dba1c087 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -564,9 +564,10 @@ class ContactsManager : public Actor { static tl_object_ptr convert_stats_absolute_value( const tl_object_ptr &obj); - tl_object_ptr convert_megagroup_stats(tl_object_ptr obj); + tl_object_ptr convert_megagroup_stats( + tl_object_ptr obj); - static tl_object_ptr convert_broadcast_stats( + static tl_object_ptr convert_broadcast_stats( tl_object_ptr obj); private: From 53ca6e4f4a37bda5713e923627c832379d58d492 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 1 Aug 2020 05:19:54 +0300 Subject: [PATCH 12/39] Add td_api::getMessageStatistics. GitOrigin-RevId: f5d32ef829b91aa1fea59ea88b665fe39d32642c --- td/generate/scheme/td_api.tl | 24 +++++--- td/generate/scheme/td_api.tlo | Bin 178864 -> 179228 bytes td/telegram/ContactsManager.cpp | 98 +++++++++++++++++++++++++++++++- td/telegram/ContactsManager.h | 12 ++++ td/telegram/MessagesManager.cpp | 27 +++++++-- td/telegram/MessagesManager.h | 4 ++ td/telegram/Td.cpp | 9 ++- td/telegram/Td.h | 4 +- td/telegram/cli.cpp | 14 ++++- 9 files changed, 172 insertions(+), 20 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 2213ac164..0b3e3257a 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -576,7 +576,7 @@ supergroup id:int32 username:string date:int32 status:ChatMemberStatus member_co //@can_set_username True, if the chat username can be changed //@can_set_sticker_set True, if the supergroup sticker set can be changed //@can_set_location True, if the supergroup location can be changed -//@can_view_statistics True, if the channel statistics is available +//@can_view_statistics True, if the supergroup or channel statistics is available //@is_all_history_available True, if new chat members will have access to old messages. In public or discussion groups and both public and private channels, old messages are always available, so this option affects only private supergroups without a linked chat. The value of this field is only available for chat administrators //@sticker_set_id Identifier of the supergroup sticker set; 0 if none //@location Location to which the supergroup is connected; may be null @@ -660,6 +660,7 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool r //@can_be_forwarded True, if the message can be forwarded //@can_be_deleted_only_for_self True, if the message can be deleted only for the current user while other users will continue to see it //@can_be_deleted_for_all_users True, if the message can be deleted for all users +//@can_view_statistics True, if the message statistics is available //@is_channel_post True, if the message is a channel post. All messages to channels are channel posts, all other messages are not channel posts //@contains_unread_mention True, if the message contains an unread mention for the current user //@date Point in time (Unix timestamp) when the message was sent @@ -675,7 +676,7 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool r //@restriction_reason If non-empty, contains a human-readable description of the reason why access to this message must be restricted //@content Content of the message //@reply_markup Reply markup for the message; may be null -message id:int53 sender_user_id:int32 chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool is_channel_post:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo interaction_info:messageInteractionInfo reply_to_message_id:int53 ttl:int32 ttl_expires_in:double via_bot_user_id:int32 author_signature:string media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message; +message id:int53 sender_user_id:int32 chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_view_statistics:Bool is_channel_post:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo interaction_info:messageInteractionInfo reply_to_message_id:int53 ttl:int32 ttl_expires_in:double via_bot_user_id:int32 author_signature:string media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message; //@description Contains a list of messages @total_count Approximate total count of messages found @messages List of messages; messages may be null messages total_count:int32 messages:vector = Messages; @@ -1993,7 +1994,7 @@ call id:int32 user_id:int32 is_outgoing:Bool is_video:Bool state:CallState = Cal //@description Contains settings for the authentication of the user's phone number //@allow_flash_call Pass true if the authentication code may be sent via flash call to the specified phone number //@is_current_phone_number Pass true if the authenticated phone number is used on the current device -//@allow_sms_retriever_api For official applications only. True, if the app can use Android SMS Retriever API (requires Google Play Services >= 10.2) to automatically receive the authentication code from the SMS. See https://developers.google.com/identity/sms-retriever/ for more details +//@allow_sms_retriever_api For official applications only. True, if the application can use Android SMS Retriever API (requires Google Play Services >= 10.2) to automatically receive the authentication code from the SMS. See https://developers.google.com/identity/sms-retriever/ for more details phoneNumberAuthenticationSettings allow_flash_call:Bool is_current_phone_number:Bool allow_sms_retriever_api:Bool = PhoneNumberAuthenticationSettings; @@ -2796,7 +2797,7 @@ networkStatisticsEntryFile file_type:FileType network_type:NetworkType sent_byte //@sent_bytes Total number of bytes sent @received_bytes Total number of bytes received @duration Total call duration, in seconds networkStatisticsEntryCall network_type:NetworkType sent_bytes:int53 received_bytes:int53 duration:double = NetworkStatisticsEntry; -//@description A full list of available network statistic entries @since_date Point in time (Unix timestamp) when the app began collecting statistics @entries Network statistics entries +//@description A full list of available network statistic entries @since_date Point in time (Unix timestamp) from which the statistics is collected @entries Network statistics entries networkStatistics since_date:int32 entries:vector = NetworkStatistics; @@ -2960,7 +2961,7 @@ statisticsValue value:double previous_value:double growth_rate_percentage:double //@description A graph data @json_data Graph data in JSON format @zoom_token If non-empty, a token which can be used to receive a zoomed in graph statisticsGraphData json_data:string zoom_token:string = StatisticsGraph; -//@description The graph data to be asynchronously loaded through getChatStatisticsGraph @token The token to use for data loading +//@description The graph data to be asynchronously loaded through getStatisticsGraph @token The token to use for data loading statisticsGraphAsync token:string = StatisticsGraph; //@description An error message to be shown to the user instead of the graph @error_message The error message @@ -3032,6 +3033,10 @@ chatStatisticsSupergroup period:dateRange member_count:statisticsValue message_c chatStatisticsChannel period:dateRange member_count:statisticsValue mean_view_count:statisticsValue mean_share_count:statisticsValue enabled_notifications_percentage:double member_count_graph:StatisticsGraph join_graph:StatisticsGraph mute_graph:StatisticsGraph view_count_by_hour_graph:StatisticsGraph view_count_by_source_graph:StatisticsGraph join_by_source_graph:StatisticsGraph language_graph:StatisticsGraph message_interaction_graph:StatisticsGraph instant_view_interaction_graph:StatisticsGraph recent_message_interactions:vector = ChatStatistics; +//@description A detailed statistics about a message @message_interaction_graph A graph containing number of message views and shares +messageStatistics message_interaction_graph:StatisticsGraph = MessageStatistics; + + //@class Update @description Contains notifications about data changes //@description The user authorization state has changed @authorization_state New authorization state @@ -4457,11 +4462,14 @@ reportChat chat_id:int53 reason:ChatReportReason message_ids:vector = Ok; //@description Returns an HTTP URL with the chat statistics. Currently this method of getting the statistics is disabled and can be deleted in the future @chat_id Chat identifier @parameters Parameters from "tg://statsrefresh?params=******" link @is_dark Pass true if a URL with the dark theme must be returned getChatStatisticsUrl chat_id:int53 parameters:string is_dark:Bool = HttpUrl; -//@description Returns detailed statistics about a chat. Currently this method can be used only for supergroups and channels. Requires administrator rights in the channel @chat_id Chat identifier @is_dark Pass true if a dark theme is used by the app +//@description Returns detailed statistics about a chat. Currently this method can be used only for supergroups and channels. Can be used only if SupergroupFullInfo.can_view_statistics == true @chat_id Chat identifier @is_dark Pass true if a dark theme is used by the application getChatStatistics chat_id:int53 is_dark:Bool = ChatStatistics; -//@description Loads asynchronous or zoomed in chat statistics graph @chat_id Chat identifier @token The token for graph loading @x X-value for zoomed in graph or 0 otherwise -getChatStatisticsGraph chat_id:int53 token:string x:int53 = StatisticsGraph; +//@description Returns detailed statistics about a message. Can be used only if Message.can_view_statistics == true @chat_id Chat identifier @message_id Message identifier @is_dark Pass true if a dark theme is used by the application +getMessageStatistics chat_id:int53 message_id:int53 is_dark:Bool = MessageStatistics; + +//@description Loads asynchronous or zoomed in chat or message statistics graph @chat_id Chat identifier @token The token for graph loading @x X-value for zoomed in graph or 0 otherwise +getStatisticsGraph chat_id:int53 token:string x:int53 = StatisticsGraph; //@description Returns storage usage statistics. Can be called before authorization @chat_limit The maximum number of chats with the largest storage usage for which separate statistics should be returned. All other chats will be grouped in entries with chat_id == 0. If the chat info database is not used, the chat_limit is ignored and is always set to 0 diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 0aa7bb80fa85e9b6717435f412467cdbfc09e648..cec8f988da3fa69253a81d8f5ff8a55dd10f8006 100644 GIT binary patch delta 830 zcmZXSPiPZS5XLjpG}$JGtaXL97D*u`(Iz&BLR3t$pkTlhV*ebJ2n}Wlg(}tL5U^kl z#Xyavy5c*uwDDFnLNv&Wh>(JM5hRBQ3Lc7h5%$o7Vh|zj?%Ot^d;0A+GvAvx^C~}V zYb~4O%j)P!lko{p9rk|nOV@I{I@sTYo@dS*XZDXvnT)*U@ltv7_yEnD;XaV~ z26U4r8{naW1*TB1q;niZS%XBpfMZk{f-(;2Z5mdS*<^M$lbyYsF_|=7vjtgN3hujp z+T!Cvx3)Bu6y1>1Ey>OVx~O*;IF8fW0Cf~3?}tG;<%j4J%PCP%7_HP`agPFouR%8* ze*p!HF3RGxNc-wgj=)X&rVT&4SZ=)wzv@Ic&G?#4kIWy%H5TSa(91~Ga!QVL^$Q8SDR zO^7(h@6}8(a-YXmM+<1<+I=}64%-qRA3i@Pq@}F(VAQ4ly$O94#N~oGDMr-OwH?sh z1Xg-Femc>`1jfLM?O)#Bv_#%T@Gfm!!txQ8moFe&8~t5Cg*^(QUn*dQJ~cI_W zP2Q8B0AV~xh=DL15}}L*P{yXD8V`uJhE*Ic?3>4gd?Y6?v=iRG zfrW7jo)&jH3M z_KbB~Co+9!hNyqg$D}j;01KnW^am_V6To8IOIVqXKmuXcontacts_manager_->convert_megagroup_stats(std::move(result))); + promise_.set_value(td->contacts_manager_->convert_megagroup_stats(result_ptr.move_as_ok())); } void on_error(uint64 id, Status status) override { @@ -2888,6 +2887,51 @@ class GetBroadcastStatsQuery : public Td::ResultHandler { } }; +tl_object_ptr ContactsManager::convert_message_stats( + tl_object_ptr obj) { + return make_tl_object(convert_stats_graph(std::move(obj->views_graph_))); +} + +class GetMessageStatsQuery : public Td::ResultHandler { + Promise> promise_; + ChannelId channel_id_; + + public: + explicit GetMessageStatsQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(ChannelId channel_id, MessageId message_id, bool is_dark, DcId dc_id) { + channel_id_ = channel_id; + + auto input_channel = td->contacts_manager_->get_input_channel(channel_id); + CHECK(input_channel != nullptr); + + int32 flags = 0; + if (is_dark) { + flags |= telegram_api::stats_getMessageStats::DARK_MASK; + } + send_query(G()->net_query_creator().create( + telegram_api::stats_getMessageStats(flags, false /*ignored*/, std::move(input_channel), + message_id.get_server_message_id().get()), + dc_id)); + } + + void on_result(uint64 id, BufferSlice packet) override { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(id, result_ptr.move_as_error()); + } + + promise_.set_value(td->contacts_manager_->convert_message_stats(result_ptr.move_as_ok())); + } + + void on_error(uint64 id, Status status) override { + td->contacts_manager_->on_get_channel_error(channel_id_, status, "GetMessageStatsQuery"); + promise_.set_error(std::move(status)); + } +}; + class LoadAsyncGraphQuery : public Td::ResultHandler { Promise> promise_; @@ -6066,6 +6110,56 @@ void ContactsManager::send_get_channel_stats_query(DcId dc_id, ChannelId channel } } +bool ContactsManager::can_get_channel_message_statistics(DialogId dialog_id) { + if (dialog_id.get_type() != DialogType::Channel) { + return false; + } + + auto channel_id = dialog_id.get_channel_id(); + const Channel *c = get_channel(channel_id); + if (c == nullptr || c->is_megagroup) { + return false; + } + + auto channel_full = get_channel_full_force(channel_id, "can_get_channel_message_statistics"); + if (channel_full == nullptr) { + return c->status.is_administrator(); + } + return channel_full->stats_dc_id.is_exact(); +} + +void ContactsManager::get_channel_message_statistics(FullMessageId full_message_id, bool is_dark, + Promise> &&promise) { + auto dc_id_promise = PromiseCreator::lambda([actor_id = actor_id(this), full_message_id, is_dark, + promise = std::move(promise)](Result r_dc_id) mutable { + if (r_dc_id.is_error()) { + return promise.set_error(r_dc_id.move_as_error()); + } + send_closure(actor_id, &ContactsManager::send_get_channel_message_stats_query, r_dc_id.move_as_ok(), + full_message_id, is_dark, std::move(promise)); + }); + get_channel_statistics_dc_id(full_message_id.get_dialog_id(), false, std::move(dc_id_promise)); +} + +void ContactsManager::send_get_channel_message_stats_query( + DcId dc_id, FullMessageId full_message_id, bool is_dark, + Promise> &&promise) { + if (G()->close_flag()) { + return promise.set_error(Status::Error(500, "Request aborted")); + } + + auto dialog_id = full_message_id.get_dialog_id(); + if (!td_->messages_manager_->have_message_force(full_message_id, "send_get_channel_message_stats_query")) { + return promise.set_error(Status::Error(400, "Message not found")); + } + if (!td_->messages_manager_->can_get_message_statistics(full_message_id)) { + return promise.set_error(Status::Error(400, "Message statistics is inaccessible")); + } + CHECK(dialog_id.get_type() == DialogType::Channel); + td_->create_handler(std::move(promise)) + ->send(dialog_id.get_channel_id(), full_message_id.get_message_id(), is_dark, dc_id); +} + void ContactsManager::load_statistics_graph(DialogId dialog_id, const string &token, int64 x, Promise> &&promise) { auto dc_id_promise = PromiseCreator::lambda( diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 3dba1c087..e93fe36d7 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -20,6 +20,7 @@ #include "td/telegram/files/FileId.h" #include "td/telegram/files/FileSourceId.h" #include "td/telegram/FolderId.h" +#include "td/telegram/FullMessageId.h" #include "td/telegram/Location.h" #include "td/telegram/MessageId.h" #include "td/telegram/net/DcId.h" @@ -373,6 +374,11 @@ class ContactsManager : public Actor { void get_channel_statistics(DialogId dialog_id, bool is_dark, Promise> &&promise); + bool can_get_channel_message_statistics(DialogId dialog_id); + + void get_channel_message_statistics(FullMessageId full_message_id, bool is_dark, + Promise> &&promise); + void load_statistics_graph(DialogId dialog_id, const string &token, int64 x, Promise> &&promise); @@ -570,6 +576,9 @@ class ContactsManager : public Actor { static tl_object_ptr convert_broadcast_stats( tl_object_ptr obj); + static tl_object_ptr convert_message_stats( + tl_object_ptr obj); + private: struct User { string first_name; @@ -1426,6 +1435,9 @@ class ContactsManager : public Actor { void send_get_channel_stats_query(DcId dc_id, ChannelId channel_id, bool is_dark, Promise> &&promise); + void send_get_channel_message_stats_query(DcId dc_id, FullMessageId full_message_id, bool is_dark, + Promise> &&promise); + void send_load_async_graph_query(DcId dc_id, string token, int64 x, Promise> &&promise); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 0f8fbf51a..5ff335773 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -8935,6 +8935,22 @@ bool MessagesManager::can_forward_message(DialogId from_dialog_id, const Message return can_forward_message_content(m->content.get()); } +bool MessagesManager::can_get_message_statistics(FullMessageId full_message_id) { + return can_get_message_statistics(full_message_id.get_dialog_id(), + get_message_force(full_message_id, "can_get_message_statistics")); +} + +bool MessagesManager::can_get_message_statistics(DialogId dialog_id, const Message *m) const { + if (td_->auth_manager_->is_bot()) { + return false; + } + if (m == nullptr || m->message_id.is_scheduled() || !m->message_id.is_server() || m->view_count == 0 || + m->had_forward_info || (m->forward_info != nullptr && m->forward_info->dialog_id.is_valid())) { + return false; + } + return td_->contacts_manager_->can_get_channel_message_statistics(dialog_id); +} + bool MessagesManager::can_delete_channel_message(DialogParticipantStatus status, const Message *m, bool is_bot) { if (m == nullptr) { return true; @@ -20027,6 +20043,8 @@ tl_object_ptr MessagesManager::get_message_object(DialogId dial auto scheduling_state = is_scheduled ? get_message_scheduling_state_object(m->date) : nullptr; bool can_be_edited = for_event_log ? false : can_edit_message(dialog_id, m, false, td_->auth_manager_->is_bot()); bool can_be_forwarded = for_event_log ? false : can_forward_message(dialog_id, m); + bool can_get_statistics = for_event_log ? false : can_get_message_statistics(dialog_id, m); + auto via_bot_user_id = td_->contacts_manager_->get_user_id_object(m->via_bot_user_id, "via_bot_user_id"); auto media_album_id = for_event_log ? static_cast(0) : m->media_album_id; auto reply_to_message_id = for_event_log ? static_cast(0) : m->reply_to_message_id.get(); bool contains_unread_mention = for_event_log ? false : m->contains_unread_mention; @@ -20036,11 +20054,10 @@ tl_object_ptr MessagesManager::get_message_object(DialogId dial return make_tl_object( m->message_id.get(), td_->contacts_manager_->get_user_id_object(m->sender_user_id, "sender_user_id"), dialog_id.get(), std::move(sending_state), std::move(scheduling_state), is_outgoing, can_be_edited, - can_be_forwarded, can_delete_for_self, can_delete_for_all_users, m->is_channel_post, contains_unread_mention, - date, edit_date, get_message_forward_info_object(m->forward_info), - get_message_interaction_info_object(dialog_id, m), reply_to_message_id, ttl, ttl_expires_in, - td_->contacts_manager_->get_user_id_object(m->via_bot_user_id, "via_bot_user_id"), m->author_signature, - media_album_id, get_restriction_reason_description(m->restriction_reasons), + can_be_forwarded, can_delete_for_self, can_delete_for_all_users, can_get_statistics, m->is_channel_post, + contains_unread_mention, date, edit_date, get_message_forward_info_object(m->forward_info), + get_message_interaction_info_object(dialog_id, m), reply_to_message_id, ttl, ttl_expires_in, via_bot_user_id, + m->author_signature, media_album_id, get_restriction_reason_description(m->restriction_reasons), get_message_content_object(m->content.get(), td_, live_location_date, m->is_content_secret), get_reply_markup_object(m->reply_markup)); } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 0103d6700..36f8e06b4 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -532,6 +532,8 @@ class MessagesManager : public Actor { vector get_common_dialogs(UserId user_id, DialogId offset_dialog_id, int32 limit, bool force, Promise &&promise); + bool can_get_message_statistics(FullMessageId full_message_id); + bool have_message_force(FullMessageId full_message_id, const char *source); void get_message(FullMessageId full_message_id, Promise &&promise); @@ -1765,6 +1767,8 @@ class MessagesManager : public Actor { static bool can_forward_message(DialogId from_dialog_id, const Message *m); + bool can_get_message_statistics(DialogId dialog_id, const Message *m) const; + static bool can_delete_channel_message(DialogParticipantStatus status, const Message *m, bool is_bot); bool can_delete_message(DialogId dialog_id, const Message *m) const; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 56430d0a7..a12cb98f4 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6728,7 +6728,14 @@ void Td::on_request(uint64 id, const td_api::getChatStatistics &request) { contacts_manager_->get_channel_statistics(DialogId(request.chat_id_), request.is_dark_, std::move(promise)); } -void Td::on_request(uint64 id, td_api::getChatStatisticsGraph &request) { +void Td::on_request(uint64 id, const td_api::getMessageStatistics &request) { + CHECK_IS_USER(); + CREATE_REQUEST_PROMISE(); + contacts_manager_->get_channel_message_statistics({DialogId(request.chat_id_), MessageId(request.message_id_)}, + request.is_dark_, std::move(promise)); +} + +void Td::on_request(uint64 id, td_api::getStatisticsGraph &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); CLEAN_INPUT_STRING(request.token_); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index e93651f89..f736e1e19 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -915,7 +915,9 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, const td_api::getChatStatistics &request); - void on_request(uint64 id, td_api::getChatStatisticsGraph &request); + void on_request(uint64 id, const td_api::getMessageStatistics &request); + + void on_request(uint64 id, td_api::getStatisticsGraph &request); void on_request(uint64 id, const td_api::getMapThumbnailFile &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index c75908cc1..73be604c3 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4017,15 +4017,23 @@ class CliClient final : public Actor { std::tie(chat_id, is_dark) = split(args); send_request(td_api::make_object(as_chat_id(chat_id), as_bool(is_dark))); - } else if (op == "gcstg") { + } else if (op == "gmst") { + string chat_id; + string message_id; + string is_dark; + std::tie(chat_id, args) = split(args); + std::tie(message_id, is_dark) = split(args); + + send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), + as_bool(is_dark))); + } else if (op == "gstg") { string chat_id; string token; string x; std::tie(chat_id, args) = split(args); std::tie(token, x) = split(args); - send_request( - td_api::make_object(as_chat_id(chat_id), token, to_integer(x))); + send_request(td_api::make_object(as_chat_id(chat_id), token, to_integer(x))); } else if (op == "hsa" || op == "glu" || op == "glua") { send_request(td_api::make_object(as_suggested_action(args))); } else if (op == "glui" || op == "glu" || op == "glua") { From a9fa751689efd7ec5c06920a81e127e4473abdf7 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 1 Aug 2020 05:54:39 +0300 Subject: [PATCH 13/39] Automatically update forward count wnen receiving a forwarded message. GitOrigin-RevId: a33ceb0a90cea9de89ec84c6d98c39078f3b115b --- td/telegram/MessagesManager.cpp | 19 +++++++++++++++++++ td/telegram/MessagesManager.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 5ff335773..247620883 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -29270,6 +29270,10 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq } } } + if (!td_->auth_manager_->is_bot() && from_update && m->forward_info != nullptr && + m->forward_info->dialog_id.is_valid() && m->forward_info->message_id.is_valid()) { + update_forward_count(m->forward_info->dialog_id, m->forward_info->message_id); + } return result_message; } @@ -32468,6 +32472,21 @@ void MessagesManager::update_top_dialogs(DialogId dialog_id, const Message *m) { } } +void MessagesManager::update_forward_count(DialogId dialog_id, MessageId message_id) { + Dialog *d = get_dialog(dialog_id); + CHECK(d != nullptr); + Message *m = get_message_force(d, message_id, "update_forward_count"); + if (m != nullptr && !m->message_id.is_scheduled() && m->message_id.is_server() && m->view_count > 0) { + if (m->forward_count == 0 && update_message_interaction_info(dialog_id, m, m->view_count, 1)) { + on_message_changed(d, m, true, "update_forward_count"); + } + + if (d->pending_viewed_message_ids.insert(m->message_id).second) { + pending_message_views_timeout_.add_timeout_in(dialog_id.get(), 0.0); + } + } +} + void MessagesManager::try_hide_distance(DialogId dialog_id, const Message *m) { CHECK(m != nullptr); if (!m->is_outgoing && dialog_id != get_my_dialog_id()) { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 36f8e06b4..0c627bd99 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2705,6 +2705,8 @@ class MessagesManager : public Actor { void update_top_dialogs(DialogId dialog_id, const Message *m); + void update_forward_count(DialogId dialog_id, MessageId message_id); + void try_hide_distance(DialogId dialog_id, const Message *m); string get_message_search_text(const Message *m) const; From 3c83aae127ab5386686ac615cb95752fd6270fc6 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 18 Aug 2020 09:32:37 +0300 Subject: [PATCH 14/39] Add CallbackWithPassword buttons support. GitOrigin-RevId: 99e79f8975d50a9a87183dd78f2641711bbad28d --- td/generate/scheme/td_api.tl | 14 +++++-- td/generate/scheme/td_api.tlo | Bin 179228 -> 179496 bytes td/telegram/CallbackQueriesManager.cpp | 49 ++++++++++++++++++++++--- td/telegram/CallbackQueriesManager.h | 7 +++- td/telegram/ReplyMarkup.cpp | 14 ++++++- td/telegram/ReplyMarkup.h | 11 +++++- td/telegram/Td.cpp | 3 +- td/telegram/cli.cpp | 15 +++++++- 8 files changed, 98 insertions(+), 15 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 0b3e3257a..26a2ca72a 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -907,10 +907,13 @@ inlineKeyboardButtonTypeUrl url:string = InlineKeyboardButtonType; //@description A button that opens a specified URL and automatically logs in in current user if they allowed to do that @url An HTTP URL to open @id Unique button identifier @forward_text If non-empty, new text of the button in forwarded messages inlineKeyboardButtonTypeLoginUrl url:string id:int32 forward_text:string = InlineKeyboardButtonType; -//@description A button that sends a special callback query to a bot @data Data to be sent to the bot via a callback query +//@description A button that sends a callback query to a bot @data Data to be sent to the bot via a callback query inlineKeyboardButtonTypeCallback data:bytes = InlineKeyboardButtonType; -//@description A button with a game that sends a special callback query to a bot. This button must be in the first column and row of the keyboard and can be attached only to a message with content of the type messageGame +//@description A button that asks for password of the current user and then sends a callback query to a bot @data Data to be sent to the bot via a callback query +inlineKeyboardButtonTypeCallbackWithPassword data:bytes = InlineKeyboardButtonType; + +//@description A button with a game that sends a callback query to a bot. This button must be in the first column and row of the keyboard and can be attached only to a message with content of the type messageGame inlineKeyboardButtonTypeCallbackGame = InlineKeyboardButtonType; //@description A button that forces an inline query to the bot to be inserted in the input field @query Inline query to be sent to the bot @in_current_chat True, if the inline query should be sent from the current chat @@ -2131,10 +2134,13 @@ inlineQueryResults inline_query_id:int64 next_offset:string results:vectorwq6XZCMdCZd^Zc?7SW`hSr>c<8X2m|CekQ!vic{s_N=}i8+ zUSe|ZMh;;#2ZDVI)CJL=ve7~UW(CNIB4;)o4%@baU{zZ-T0m5N*cbs}_-xX_sl0i@ urtK3pF-91GJvLon2cyDtp2v)L5ZvuNPZ&i)S;1jBSvE+1yNe~$jV1u`9Hx>0 delta 319 zcmZ4Si)+pgt_@RICF3rvIWFRyn3I!~n4BG0np#vDkXV_MpO`XvBD3`76Ra&fEc_;a zFHQ~+l3`? &payload, - int64 result_id) { + tl_object_ptr &&password, int64 result_id) { result_id_ = result_id; dialog_id_ = dialog_id; message_id_ = message_id; @@ -54,6 +55,12 @@ class GetBotCallbackAnswerQuery : public Td::ResultHandler { flags = telegram_api::messages_getBotCallbackAnswer::DATA_MASK; data = BufferSlice(static_cast(payload.get())->data_); break; + case td_api::callbackQueryPayloadDataWithPassword::ID: + CHECK(password != nullptr); + flags = telegram_api::messages_getBotCallbackAnswer::DATA_MASK | + telegram_api::messages_getBotCallbackAnswer::PASSWORD_MASK; + data = BufferSlice(static_cast(payload.get())->data_); + break; case td_api::callbackQueryPayloadGame::ID: flags = telegram_api::messages_getBotCallbackAnswer::GAME_MASK; break; @@ -63,7 +70,7 @@ class GetBotCallbackAnswerQuery : public Td::ResultHandler { auto net_query = G()->net_query_creator().create(telegram_api::messages_getBotCallbackAnswer( flags, false /*ignored*/, std::move(input_peer), message_id.get_server_message_id().get(), std::move(data), - nullptr)); + std::move(password))); net_query->need_resend_on_503_ = false; send_query(std::move(net_query)); } @@ -221,7 +228,7 @@ void CallbackQueriesManager::on_new_inline_query( } int64 CallbackQueriesManager::send_callback_query(FullMessageId full_message_id, - const tl_object_ptr &payload, + tl_object_ptr &&payload, Promise &&promise) { if (td_->auth_manager_->is_bot()) { promise.set_error(Status::Error(5, "Bot can't send callback queries to other bot")); @@ -259,12 +266,44 @@ int64 CallbackQueriesManager::send_callback_query(FullMessageId full_message_id, } while (callback_query_answers_.find(result_id) != callback_query_answers_.end()); callback_query_answers_[result_id]; // reserve place for result - td_->create_handler(std::move(promise)) - ->send(dialog_id, full_message_id.get_message_id(), payload, result_id); + if (payload->get_id() == td_api::callbackQueryPayloadDataWithPassword::ID) { + auto password = static_cast(payload.get())->password_; + send_closure(td_->password_manager_, &PasswordManager::get_input_check_password_srp, std::move(password), + PromiseCreator::lambda( + [this, full_message_id, payload = std::move(payload), result_id, promise = std::move(promise)]( + Result> result) mutable { + if (result.is_error()) { + return promise.set_error(result.move_as_error()); + } + if (G()->close_flag()) { + return promise.set_error(Status::Error(500, "Request aborted")); + } + + send_get_callback_answer_query(full_message_id, std::move(payload), result.move_as_ok(), + result_id, std::move(promise)); + })); + } else { + send_get_callback_answer_query(full_message_id, std::move(payload), nullptr, result_id, std::move(promise)); + } return result_id; } +void CallbackQueriesManager::send_get_callback_answer_query( + FullMessageId full_message_id, tl_object_ptr &&payload, + tl_object_ptr &&password, int64 result_id, Promise &&promise) { + auto dialog_id = full_message_id.get_dialog_id(); + if (!td_->messages_manager_->have_input_peer(dialog_id, AccessRights::Read)) { + return promise.set_error(Status::Error(400, "Can't access the chat")); + } + if (!td_->messages_manager_->have_message_force(full_message_id, "send_callback_query")) { + return promise.set_error(Status::Error(5, "Message not found")); + } + + td_->create_handler(std::move(promise)) + ->send(dialog_id, full_message_id.get_message_id(), payload, std::move(password), result_id); +} + void CallbackQueriesManager::on_get_callback_query_answer( int64 result_id, tl_object_ptr &&answer) { LOG(INFO) << "Receive answer for callback query " << result_id; diff --git a/td/telegram/CallbackQueriesManager.h b/td/telegram/CallbackQueriesManager.h index c05bd2215..c859cbf6f 100644 --- a/td/telegram/CallbackQueriesManager.h +++ b/td/telegram/CallbackQueriesManager.h @@ -39,7 +39,7 @@ class CallbackQueriesManager { tl_object_ptr &&inline_message_id, BufferSlice &&data, int64 chat_instance, string &&game_short_name); - int64 send_callback_query(FullMessageId full_message_id, const tl_object_ptr &payload, + int64 send_callback_query(FullMessageId full_message_id, tl_object_ptr &&payload, Promise &&promise); void on_get_callback_query_answer(int64 result_id, tl_object_ptr &&answer); @@ -60,6 +60,11 @@ class CallbackQueriesManager { tl_object_ptr get_query_payload(int32 flags, BufferSlice &&data, string &&game_short_name); + void send_get_callback_answer_query(FullMessageId full_message_id, + tl_object_ptr &&payload, + tl_object_ptr &&password, int64 result_id, + Promise &&promise); + std::unordered_map callback_query_answers_; Td *td_; diff --git a/td/telegram/ReplyMarkup.cpp b/td/telegram/ReplyMarkup.cpp index 12f37fa3d..42ad336ca 100644 --- a/td/telegram/ReplyMarkup.cpp +++ b/td/telegram/ReplyMarkup.cpp @@ -84,6 +84,9 @@ static StringBuilder &operator<<(StringBuilder &string_builder, const InlineKeyb case InlineKeyboardButton::Type::UrlAuth: string_builder << "UrlAuth, id = " << keyboard_button.id; break; + case InlineKeyboardButton::Type::CallbackWithPassword: + string_builder << "CallbackWithPassword"; + break; default: UNREACHABLE(); } @@ -219,7 +222,8 @@ static InlineKeyboardButton get_inline_keyboard_button( } case telegram_api::keyboardButtonCallback::ID: { auto keyboard_button = move_tl_object_as(keyboard_button_ptr); - button.type = InlineKeyboardButton::Type::Callback; + button.type = keyboard_button->requires_password_ ? InlineKeyboardButton::Type::CallbackWithPassword + : InlineKeyboardButton::Type::Callback; button.text = std::move(keyboard_button->text_); button.data = keyboard_button->data_.as_slice().str(); break; @@ -435,6 +439,8 @@ static Result get_inline_keyboard_button(tl_object_ptr(button->type_); if (!switch_inline_buttons_allowed) { @@ -653,6 +659,9 @@ static tl_object_ptr get_inline_keyboard_button( keyboard_button.forward_text, keyboard_button.data, std::move(input_user)); } + case InlineKeyboardButton::Type::CallbackWithPassword: + UNREACHABLE(); + break; default: UNREACHABLE(); return nullptr; @@ -762,6 +771,9 @@ static tl_object_ptr get_inline_keyboard_button_ob type = make_tl_object(keyboard_button.data, keyboard_button.id, keyboard_button.forward_text); break; + case InlineKeyboardButton::Type::CallbackWithPassword: + type = make_tl_object(keyboard_button.data); + break; default: UNREACHABLE(); return nullptr; diff --git a/td/telegram/ReplyMarkup.h b/td/telegram/ReplyMarkup.h index 79e15f574..9c2729ddb 100644 --- a/td/telegram/ReplyMarkup.h +++ b/td/telegram/ReplyMarkup.h @@ -31,7 +31,16 @@ struct KeyboardButton { struct InlineKeyboardButton { // append only - enum class Type : int32 { Url, Callback, CallbackGame, SwitchInline, SwitchInlineCurrentDialog, Buy, UrlAuth }; + enum class Type : int32 { + Url, + Callback, + CallbackGame, + SwitchInline, + SwitchInlineCurrentDialog, + Buy, + UrlAuth, + CallbackWithPassword + }; Type type; int32 id = 0; // UrlAuth only, button_id or (2 * request_write_access - 1) * bot_user_id string text; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index a12cb98f4..f30ff3b5f 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -2901,7 +2901,8 @@ class GetCallbackQueryAnswerRequest : public RequestOnceActor { int64 result_id_; void do_run(Promise &&promise) override { - result_id_ = td->callback_queries_manager_->send_callback_query(full_message_id_, payload_, std::move(promise)); + result_id_ = + td->callback_queries_manager_->send_callback_query(full_message_id_, std::move(payload_), std::move(promise)); } void do_send_result() override { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 73be604c3..19eaf6856 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3100,7 +3100,7 @@ class CliClient final : public Actor { auto chat = as_chat_id(chat_id); send_request(td_api::make_object( chat, 0, default_message_send_options(), to_integer(query_id), result_id, op == "siqrh")); - } else if (op == "gcqr") { + } else if (op == "gcqa") { string chat_id; string message_id; string data; @@ -3108,7 +3108,18 @@ class CliClient final : public Actor { std::tie(message_id, data) = split(args); send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(message_id), td_api::make_object(data))); - } else if (op == "gcgqr") { + } else if (op == "gcpqa") { + string chat_id; + string message_id; + string password; + string data; + std::tie(chat_id, args) = split(args); + std::tie(message_id, args) = split(args); + std::tie(password, data) = split(args); + send_request(td_api::make_object( + as_chat_id(chat_id), as_message_id(message_id), + td_api::make_object(password, data))); + } else if (op == "gcgqa") { string chat_id; string message_id; std::tie(chat_id, message_id) = split(args); From 5e20f6f90b6f2b51e562e73b88923dc63dfac679 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 18 Aug 2020 14:19:03 +0300 Subject: [PATCH 15/39] Rename can_view_statistics to can_get_statistics. GitOrigin-RevId: 1b18ac1fbe89cfb64743600e92511c4a03eafe09 --- td/generate/scheme/td_api.tl | 12 ++++++------ td/generate/scheme/td_api.tlo | Bin 179496 -> 179496 bytes 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 26a2ca72a..24311f540 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -576,14 +576,14 @@ supergroup id:int32 username:string date:int32 status:ChatMemberStatus member_co //@can_set_username True, if the chat username can be changed //@can_set_sticker_set True, if the supergroup sticker set can be changed //@can_set_location True, if the supergroup location can be changed -//@can_view_statistics True, if the supergroup or channel statistics is available +//@can_get_statistics True, if the supergroup or channel statistics is available //@is_all_history_available True, if new chat members will have access to old messages. In public or discussion groups and both public and private channels, old messages are always available, so this option affects only private supergroups without a linked chat. The value of this field is only available for chat administrators //@sticker_set_id Identifier of the supergroup sticker set; 0 if none //@location Location to which the supergroup is connected; may be null //@invite_link Invite link for this chat //@upgraded_from_basic_group_id Identifier of the basic group from which supergroup was upgraded; 0 if none //@upgraded_from_max_message_id Identifier of the last message in the basic group from which supergroup was upgraded; 0 if none -supergroupFullInfo photo:chatPhoto description:string member_count:int32 administrator_count:int32 restricted_count:int32 banned_count:int32 linked_chat_id:int53 slow_mode_delay:int32 slow_mode_delay_expires_in:double can_get_members:Bool can_set_username:Bool can_set_sticker_set:Bool can_set_location:Bool can_view_statistics:Bool is_all_history_available:Bool sticker_set_id:int64 location:chatLocation invite_link:string upgraded_from_basic_group_id:int32 upgraded_from_max_message_id:int53 = SupergroupFullInfo; +supergroupFullInfo photo:chatPhoto description:string member_count:int32 administrator_count:int32 restricted_count:int32 banned_count:int32 linked_chat_id:int53 slow_mode_delay:int32 slow_mode_delay_expires_in:double can_get_members:Bool can_set_username:Bool can_set_sticker_set:Bool can_set_location:Bool can_get_statistics:Bool is_all_history_available:Bool sticker_set_id:int64 location:chatLocation invite_link:string upgraded_from_basic_group_id:int32 upgraded_from_max_message_id:int53 = SupergroupFullInfo; //@class SecretChatState @description Describes the current secret chat state @@ -660,7 +660,7 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool r //@can_be_forwarded True, if the message can be forwarded //@can_be_deleted_only_for_self True, if the message can be deleted only for the current user while other users will continue to see it //@can_be_deleted_for_all_users True, if the message can be deleted for all users -//@can_view_statistics True, if the message statistics is available +//@can_get_statistics True, if the message statistics is available //@is_channel_post True, if the message is a channel post. All messages to channels are channel posts, all other messages are not channel posts //@contains_unread_mention True, if the message contains an unread mention for the current user //@date Point in time (Unix timestamp) when the message was sent @@ -676,7 +676,7 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool r //@restriction_reason If non-empty, contains a human-readable description of the reason why access to this message must be restricted //@content Content of the message //@reply_markup Reply markup for the message; may be null -message id:int53 sender_user_id:int32 chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_view_statistics:Bool is_channel_post:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo interaction_info:messageInteractionInfo reply_to_message_id:int53 ttl:int32 ttl_expires_in:double via_bot_user_id:int32 author_signature:string media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message; +message id:int53 sender_user_id:int32 chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_get_statistics:Bool is_channel_post:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo interaction_info:messageInteractionInfo reply_to_message_id:int53 ttl:int32 ttl_expires_in:double via_bot_user_id:int32 author_signature:string media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message; //@description Contains a list of messages @total_count Approximate total count of messages found @messages List of messages; messages may be null messages total_count:int32 messages:vector = Messages; @@ -4468,10 +4468,10 @@ reportChat chat_id:int53 reason:ChatReportReason message_ids:vector = Ok; //@description Returns an HTTP URL with the chat statistics. Currently this method of getting the statistics is disabled and can be deleted in the future @chat_id Chat identifier @parameters Parameters from "tg://statsrefresh?params=******" link @is_dark Pass true if a URL with the dark theme must be returned getChatStatisticsUrl chat_id:int53 parameters:string is_dark:Bool = HttpUrl; -//@description Returns detailed statistics about a chat. Currently this method can be used only for supergroups and channels. Can be used only if SupergroupFullInfo.can_view_statistics == true @chat_id Chat identifier @is_dark Pass true if a dark theme is used by the application +//@description Returns detailed statistics about a chat. Currently this method can be used only for supergroups and channels. Can be used only if SupergroupFullInfo.can_get_statistics == true @chat_id Chat identifier @is_dark Pass true if a dark theme is used by the application getChatStatistics chat_id:int53 is_dark:Bool = ChatStatistics; -//@description Returns detailed statistics about a message. Can be used only if Message.can_view_statistics == true @chat_id Chat identifier @message_id Message identifier @is_dark Pass true if a dark theme is used by the application +//@description Returns detailed statistics about a message. Can be used only if Message.can_get_statistics == true @chat_id Chat identifier @message_id Message identifier @is_dark Pass true if a dark theme is used by the application getMessageStatistics chat_id:int53 message_id:int53 is_dark:Bool = MessageStatistics; //@description Loads asynchronous or zoomed in chat or message statistics graph @chat_id Chat identifier @token The token for graph loading @x X-value for zoomed in graph or 0 otherwise diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index f20efe5b6ca54572cf299e68f2d98a5ce8ee624d..f7c81db5e9d820c09935a6ab432efdf8a32bce9b 100644 GIT binary patch delta 775 zcmZ8fJxCj280LMO#7k^xlvrXL=z&*>aK^JOw1d!;ItX=;HZ4-5ZPegmMM#DWA{jdL z2iv1p`0Au74uTo3T;QuA7KOC5a6_Oj1&53sQgCnxPQClyL?zqvywCf*f8V!x9N0V# znBiVex-tCEiu8tp9{HBFW8ECERS{$69>lHD$5N-D#zaykV5Vf_V{+t_9GxYJ=~Klj zPEU=AJS()7d(z{!>Ufb#r;~Fj7ytRuJ$~7^`>2oGUU&&o_e^r(*<32aUd^MzmpUMU z!p-;nFh-MdxevsN{7E0sErCRjv*}a8azm;%gA{y9>EJLPmb{zG2^s^6DCx z?R^S)2!n9(pP!*{Nfc*#31s$Z8*HM7CD54s4Z_SU0d2^gSlLITIJes9qRy_7XMaQF zIyrM6P-V`3QC9b&PU$%xR<4m;8^kQzRZ$`OSHA>2PHMGjuk@aO^sceg=h>&xgd4p-@AdGHR-LQ|Dc6Nne$IN5b#Nf3Je z02^&FUVMm&KznfZDP}y)!zg&0&K#b>gMP|vyvD3RJo5(Y^xRC0rmtXgtl|nP&9M&N xVV#WjdyEhg2cDOlZPXhm8|S}IQNfCi=0$(&pZVBc49D58b$mahl&w96zouKDn*KI+6D){EXF18Vef*DQ{_-st2g(wOc0_`Gn$mkFuLx<9(-hD4=OL6t3(z70{Tp+pLhZ(k}Vwl1|DnFw^-$){bIb_D^%vNn zhi76mV;);$73VSB8f$9-8)U4$!Vn>G;0Kbujd}?c^ThWFDp)bl>h!k%o` Date: Tue, 18 Aug 2020 15:10:03 +0300 Subject: [PATCH 16/39] Use string new_offset in FoundMessages. GitOrigin-RevId: b0d013e7d2513cc39f1c07013c837e6adb7e924a --- td/generate/scheme/td_api.tl | 8 ++++---- td/generate/scheme/td_api.tlo | Bin 179496 -> 179480 bytes td/telegram/MessagesManager.cpp | 15 +++++++++++---- td/telegram/MessagesManager.h | 8 ++++---- td/telegram/Td.cpp | 20 ++++++++++---------- td/telegram/cli.cpp | 7 +++---- 6 files changed, 32 insertions(+), 26 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 24311f540..ea0458d96 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -681,8 +681,8 @@ message id:int53 sender_user_id:int32 chat_id:int53 sending_state:MessageSending //@description Contains a list of messages @total_count Approximate total count of messages found @messages List of messages; messages may be null messages total_count:int32 messages:vector = Messages; -//@description Contains a list of messages found by a search @messages List of messages @next_from_search_id Value to pass as from_search_id to get more results -foundMessages messages:vector next_from_search_id:int64 = FoundMessages; +//@description Contains a list of messages found by a search @messages List of messages @next_offset The offset for the next request. If empty, there are no more results +foundMessages messages:vector next_offset:string = FoundMessages; //@class NotificationSettingsScope @description Describes the types of chats to which notification settings are applied @@ -3595,10 +3595,10 @@ searchMessages chat_list:ChatList query:string offset_date:int32 offset_chat_id: //@description Searches for messages in secret chats. Returns the results in reverse chronological order. For optimal performance the number of returned messages is chosen by the library //@chat_id Identifier of the chat in which to search. Specify 0 to search in all secret chats @query Query to search for. If empty, searchChatMessages should be used instead -//@from_search_id The identifier from the result of a previous request, use 0 to get results from the last message +//@offset Offset of the first entry to return; use empty string to get results from the last message //@limit The maximum number of messages to be returned; up to 100. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached //@filter A filter for the content of messages in the search results -searchSecretMessages chat_id:int53 query:string from_search_id:int64 limit:int32 filter:SearchMessagesFilter = FoundMessages; +searchSecretMessages chat_id:int53 query:string offset:string limit:int32 filter:SearchMessagesFilter = FoundMessages; //@description Searches for call messages. Returns the results in reverse chronological order (i. e., in order of decreasing message_id). For optimal performance the number of returned messages is chosen by the library //@from_message_id Identifier of the message from which to search; use 0 to get results from the last message diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index f7c81db5e9d820c09935a6ab432efdf8a32bce9b..66c70304dfa45d0bd87b09b3333957b13717126c 100644 GIT binary patch delta 138 zcmZ4Si)+R&t_?>7SS%DTF5G-V;Ll765Q{f0zceq!H?_DpF+H`IfdM2o`OYer$s&6c zCL8#0fR#6gtll27nz7)H!W|CNb$uS7=~Tn110Q Yqs(N7>8#Up8=0KJ#%y2E!PH>_0HZuNLI3~& delta 163 zcmbR7i)+O%t_?>7SWa?y*Ka-{@Moq3h{cGQGRZGacW{wa>nG3yTvDO$l?GS(Co8%yU%LIf;%i*ZFA;KKhVx30T!P=ft5*T wdd(w71ztWRz46l> MessagesManager::offline_search_messages( - DialogId dialog_id, const string &query, int64 from_search_id, int32 limit, +std::pair> MessagesManager::offline_search_messages( + DialogId dialog_id, const string &query, const string &offset, int32 limit, const tl_object_ptr &filter, int64 &random_id, Promise<> &&promise) { if (!G()->parameters().use_message_db) { promise.set_error(Status::Error(400, "Message database is required to search messages in secret chats")); @@ -19032,7 +19032,14 @@ std::pair> MessagesManager::offline_search_messages fts_query.query = query; fts_query.dialog_id = dialog_id; fts_query.index_mask = search_messages_filter_index_mask(get_search_messages_filter(filter)); - fts_query.from_search_id = from_search_id; + if (!offset.empty()) { + auto r_from_search_id = to_integer_safe(offset); + if (r_from_search_id.is_error()) { + promise.set_error(Status::Error(400, "Wrong offset specified")); + return {}; + } + fts_query.from_search_id = r_from_search_id.ok(); + } fts_query.limit = limit; do { @@ -19074,7 +19081,7 @@ void MessagesManager::on_messages_db_fts_result(Result resu } } - it->second.first = fts_result.next_search_id; + it->second.first = fts_result.next_search_id <= 1 ? string() : to_string(fts_result.next_search_id); promise.set_value(Unit()); } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 0c627bd99..52a03bf55 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -653,8 +653,8 @@ class MessagesManager : public Actor { const tl_object_ptr &filter, int64 &random_id, bool use_db, Promise &&promise); - std::pair> offline_search_messages( - DialogId dialog_id, const string &query, int64 from_search_id, int32 limit, + std::pair> offline_search_messages( + DialogId dialog_id, const string &query, const string &offset, int32 limit, const tl_object_ptr &filter, int64 &random_id, Promise<> &&promise); std::pair> search_messages(FolderId folder_id, bool ignore_folder_id, @@ -2931,8 +2931,8 @@ class MessagesManager : public Actor { std::unordered_map>> found_dialog_recent_location_messages_; // random_id -> [total_count, [message_id]...] - std::unordered_map>> - found_fts_messages_; // random_id -> [from_search_id, [full_message_id]...] + std::unordered_map>> + found_fts_messages_; // random_id -> [next_offset, [full_message_id]...] std::unordered_map, FullMessageIdHash> public_message_links_[2]; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index f30ff3b5f..730da7a58 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1465,19 +1465,19 @@ class SearchChatMessagesRequest : public RequestActor<> { } }; -class OfflineSearchMessagesRequest : public RequestActor<> { +class SearchSecretMessagesRequest : public RequestActor<> { DialogId dialog_id_; string query_; - int64 from_search_id_; + string offset_; int32 limit_; tl_object_ptr filter_; int64 random_id_; - std::pair> messages_; + std::pair> messages_; void do_run(Promise &&promise) override { - messages_ = td->messages_manager_->offline_search_messages(dialog_id_, query_, from_search_id_, limit_, filter_, - random_id_, std::move(promise)); + messages_ = td->messages_manager_->offline_search_messages(dialog_id_, query_, offset_, limit_, filter_, random_id_, + std::move(promise)); } void do_send_result() override { @@ -1487,16 +1487,16 @@ class OfflineSearchMessagesRequest : public RequestActor<> { result.push_back(td->messages_manager_->get_message_object(full_message_id)); } - send_result(make_tl_object(std::move(result), messages_.first)); + send_result(make_tl_object(std::move(result), std::move(messages_.first))); } public: - OfflineSearchMessagesRequest(ActorShared td, uint64 request_id, int64 dialog_id, string query, - int64 from_search_id, int32 limit, tl_object_ptr filter) + SearchSecretMessagesRequest(ActorShared td, uint64 request_id, int64 dialog_id, string query, string offset, + int32 limit, tl_object_ptr filter) : RequestActor(std::move(td), request_id) , dialog_id_(dialog_id) , query_(std::move(query)) - , from_search_id_(from_search_id) + , offset_(std::move(offset)) , limit_(limit) , filter_(std::move(filter)) , random_id_(0) { @@ -5463,7 +5463,7 @@ void Td::on_request(uint64 id, td_api::searchChatMessages &request) { void Td::on_request(uint64 id, td_api::searchSecretMessages &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.query_); - CREATE_REQUEST(OfflineSearchMessagesRequest, request.chat_id_, std::move(request.query_), request.from_search_id_, + CREATE_REQUEST(SearchSecretMessagesRequest, request.chat_id_, std::move(request.query_), std::move(request.offset_), request.limit_, std::move(request.filter_)); } diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 19eaf6856..5300c31e0 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2913,19 +2913,18 @@ class CliClient final : public Actor { } } else if (op == "ssm") { string chat_id; - string from_search_id; + string offset; string limit; string filter; string query; std::tie(chat_id, args) = split(args); - std::tie(from_search_id, args) = split(args); + std::tie(offset, args) = split(args); std::tie(limit, args) = split(args); std::tie(filter, query) = split(args); send_request(td_api::make_object( - as_chat_id(chat_id), query, to_integer(from_search_id), to_integer(limit), - get_search_messages_filter(filter))); + as_chat_id(chat_id), query, offset, to_integer(limit), get_search_messages_filter(filter))); } else if (op == "ssd") { schedule_date_ = args; } else if (op == "sm" || op == "sms" || op == "smr" || op == "smf") { From f9c0ddae062b629a0f32abc3850bce33fd2bcd7f Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 21 Aug 2020 14:47:43 +0300 Subject: [PATCH 17/39] Add getMessagePublicForwards method. GitOrigin-RevId: a0b16c241bcf3276c245423f7fff3f41751883b6 --- td/generate/scheme/td_api.tl | 14 ++- td/generate/scheme/td_api.tlo | Bin 179480 -> 179680 bytes td/telegram/MessagesManager.cpp | 185 +++++++++++++++++++++++++++++++- td/telegram/MessagesManager.h | 24 ++++- td/telegram/Td.cpp | 54 +++++++--- td/telegram/Td.h | 2 + td/telegram/cli.cpp | 12 +++ 7 files changed, 266 insertions(+), 25 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index ea0458d96..0b1d48f3f 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3590,12 +3590,13 @@ searchChatMessages chat_id:int53 query:string sender_user_id:int32 from_message_ //@offset_date The date of the message starting from which the results should be fetched. Use 0 or any date in the future to get results from the last message //@offset_chat_id The chat identifier of the last found message, or 0 for the first request //@offset_message_id The message identifier of the last found message, or 0 for the first request -//@limit The maximum number of messages to be returned, up to 100. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached +//@limit The maximum number of messages to be returned; up to 100. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached searchMessages chat_list:ChatList query:string offset_date:int32 offset_chat_id:int53 offset_message_id:int53 limit:int32 = Messages; //@description Searches for messages in secret chats. Returns the results in reverse chronological order. For optimal performance the number of returned messages is chosen by the library -//@chat_id Identifier of the chat in which to search. Specify 0 to search in all secret chats @query Query to search for. If empty, searchChatMessages should be used instead -//@offset Offset of the first entry to return; use empty string to get results from the last message +//@chat_id Identifier of the chat in which to search. Specify 0 to search in all secret chats +//@query Query to search for. If empty, searchChatMessages should be used instead +//@offset Offset of the first entry to return as received from the previous request; use empty string to get first chunk of results //@limit The maximum number of messages to be returned; up to 100. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached //@filter A filter for the content of messages in the search results searchSecretMessages chat_id:int53 query:string offset:string limit:int32 filter:SearchMessagesFilter = FoundMessages; @@ -3620,6 +3621,13 @@ getChatMessageCount chat_id:int53 filter:SearchMessagesFilter return_local:Bool //@description Returns all scheduled messages in a chat. The messages are returned in a reverse chronological order (i.e., in order of decreasing message_id) @chat_id Chat identifier getChatScheduledMessages chat_id:int53 = Messages; +//@description Returns forwarded copies of a channel message to another public channels. For optimal performance the number of returned messages is chosen by the library +//@chat_id Chat identifier of the message +//@message_id Message identifier +//@offset Offset of the first entry to return as received from the previous request; use empty string to get first chunk of results +//@limit The maximum number of messages to be returned; must be positive and can't be greater than 100. Fewer messages may be returned than specified by the limit, even if the end of the list has not been reached +getMessagePublicForwards chat_id:int53 message_id:int53 offset:string limit:int32 = FoundMessages; + //@description Removes an active notification from notification list. Needs to be called only if the notification is removed by the current user @notification_group_id Identifier of notification group to which the notification belongs @notification_id Identifier of removed notification removeNotification notification_group_id:int32 notification_id:int32 = Ok; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 66c70304dfa45d0bd87b09b3333957b13717126c..051116aefffa6866b8541a5ecc8699d234de41b2 100644 GIT binary patch delta 88 zcmV-e0H^<$`U>Ft3V?(Gv;vd?0f4ua0RkgZBuS|TU>Ij*bWLS*b75y?P<3K#X=6rj ua(7{JWOD!j05~Dhp_f3s0Z^ALCjt promise_; + DialogId dialog_id_; + int32 limit_; + int64 random_id_; + + public: + explicit GetMessagePublicForwardsQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(FullMessageId full_message_id, int32 offset_date, DialogId offset_dialog_id, + ServerMessageId offset_message_id, int32 limit, int64 random_id) { + dialog_id_ = full_message_id.get_dialog_id(); + limit_ = limit; + random_id_ = random_id; + + auto input_peer = MessagesManager::get_input_peer_force(offset_dialog_id); + CHECK(input_peer != nullptr); + + send_query(G()->net_query_creator().create(telegram_api::stats_getMessagePublicForwards( + td->contacts_manager_->get_input_channel(dialog_id_.get_channel_id()), + full_message_id.get_message_id().get_server_message_id().get(), offset_date, std::move(input_peer), + offset_message_id.get(), limit))); + } + + void on_result(uint64 id, BufferSlice packet) override { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(id, result_ptr.move_as_error()); + } + + auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "GetMessagePublicForwardsQuery"); + LOG_IF(ERROR, !info.is_channel_messages) << "Receive ordinary messages in GetMessagePublicForwardsQuery"; + td->messages_manager_->on_get_message_public_forwards_result(random_id_, info.total_count, + std::move(info.messages)); + + promise_.set_value(Unit()); + } + + void on_error(uint64 id, Status status) override { + td->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetMessagePublicForwardsQuery"); + td->messages_manager_->on_failed_get_message_public_forwards(random_id_); + promise_.set_error(std::move(status)); + } +}; + class HidePromoDataQuery : public Td::ResultHandler { DialogId dialog_id_; @@ -8838,6 +8884,48 @@ void MessagesManager::on_get_recent_locations_failed(int64 random_id) { found_dialog_recent_location_messages_.erase(it); } +void MessagesManager::on_get_message_public_forwards_result(int64 random_id, int32 total_count, + vector> &&messages) { + LOG(INFO) << "Receive " << messages.size() << " forwarded messages"; + auto it = found_message_public_forwards_.find(random_id); + CHECK(it != found_message_public_forwards_.end()); + + auto &result = it->second.full_message_ids; + CHECK(result.empty()); + FullMessageId last_full_message_id; + for (auto &message : messages) { + auto dialog_id = get_message_dialog_id(message); + auto new_full_message_id = on_get_message(std::move(message), false, dialog_id.get_type() == DialogType::Channel, + false, false, false, "get message public forwards"); + if (new_full_message_id != FullMessageId()) { + CHECK(dialog_id == new_full_message_id.get_dialog_id()); + result.push_back(new_full_message_id); + last_full_message_id = new_full_message_id; + } else { + total_count--; + } + } + if (total_count < static_cast(result.size())) { + LOG(ERROR) << "Receive " << result.size() << " valid messages out of " << total_count << " in " << messages.size() + << " messages"; + total_count = static_cast(result.size()); + } + if (!result.empty()) { + auto m = get_message(last_full_message_id); + CHECK(m != nullptr); + it->second.next_offset = PSTRING() << m->date << "," << last_full_message_id.get_dialog_id().get() << "," + << m->message_id.get_server_message_id().get(); + } + + // it->second.total_count = total_count; +} + +void MessagesManager::on_failed_get_message_public_forwards(int64 random_id) { + auto it = found_message_public_forwards_.find(random_id); + CHECK(it != found_message_public_forwards_.end()); + found_message_public_forwards_.erase(it); +} + void MessagesManager::delete_messages_from_updates(const vector &message_ids) { std::unordered_map, DialogIdHash> deleted_message_ids; std::unordered_map need_update_dialog_pos; @@ -18994,7 +19082,21 @@ void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, Dialo promise.set_value(Unit()); } -std::pair> MessagesManager::offline_search_messages( +td_api::object_ptr MessagesManager::get_found_messages_object( + const FoundMessages &found_messages) { + vector> result; + result.reserve(found_messages.full_message_ids.size()); + for (auto full_message_id : found_messages.full_message_ids) { + auto message = get_message_object(full_message_id); + if (message != nullptr) { + result.push_back(std::move(message)); + } + } + + return td_api::make_object(std::move(result), found_messages.next_offset); +} + +MessagesManager::FoundMessages MessagesManager::offline_search_messages( DialogId dialog_id, const string &query, const string &offset, int32 limit, const tl_object_ptr &filter, int64 &random_id, Promise<> &&promise) { if (!G()->parameters().use_message_db) { @@ -19070,7 +19172,7 @@ void MessagesManager::on_messages_db_fts_result(Result resu auto it = found_fts_messages_.find(random_id); CHECK(it != found_fts_messages_.end()); - auto &res = it->second.second; + auto &res = it->second.full_message_ids; res.reserve(fts_result.messages.size()); for (auto &message : fts_result.messages) { @@ -19081,7 +19183,7 @@ void MessagesManager::on_messages_db_fts_result(Result resu } } - it->second.first = fts_result.next_search_id <= 1 ? string() : to_string(fts_result.next_search_id); + it->second.next_offset = fts_result.next_search_id <= 1 ? string() : to_string(fts_result.next_search_id); promise.set_value(Unit()); } @@ -19930,6 +20032,83 @@ void MessagesManager::on_get_scheduled_messages_from_database(DialogId dialog_id } } +MessagesManager::FoundMessages MessagesManager::get_message_public_forwards(FullMessageId full_message_id, + const string &offset, int32 limit, + int64 &random_id, Promise &&promise) { + if (random_id != 0) { + // request has already been sent before + auto it = found_message_public_forwards_.find(random_id); + CHECK(it != found_message_public_forwards_.end()); + auto result = std::move(it->second); + found_message_public_forwards_.erase(it); + promise.set_value(Unit()); + return result; + } + + auto dialog_id = full_message_id.get_dialog_id(); + Dialog *d = get_dialog_force(dialog_id); + if (d == nullptr) { + promise.set_error(Status::Error(5, "Chat not found")); + return {}; + } + + const Message *m = get_message_force(d, full_message_id.get_message_id(), "get_message_public_forwards"); + if (m == nullptr) { + promise.set_error(Status::Error(5, "Message not found")); + return {}; + } + + if (m->view_count == 0 || m->forward_info != nullptr || m->had_forward_info || m->message_id.is_scheduled() || + !m->message_id.is_server()) { + promise.set_error(Status::Error(5, "Message forwards are inaccessible")); + return {}; + } + + FoundMessages result; + if (limit <= 0) { + promise.set_error(Status::Error(3, "Parameter limit must be positive")); + return {}; + } + if (limit > MAX_SEARCH_MESSAGES) { + limit = MAX_SEARCH_MESSAGES; + } + + int32 offset_date = std::numeric_limits::max(); + DialogId offset_dialog_id; + ServerMessageId offset_message_id; + + if (!offset.empty()) { + auto parts = full_split(offset, ','); + if (parts.size() != 3) { + promise.set_error(Status::Error(3, "Wrong offset specified")); + return {}; + } + auto r_offset_date = to_integer_safe(parts[0]); + auto r_offset_dialog_id = to_integer_safe(parts[1]); + auto r_offset_message_id = to_integer_safe(parts[2]); + if (r_offset_date.is_error() || r_offset_dialog_id.is_error() || r_offset_message_id.is_error()) { + promise.set_error(Status::Error(3, "Wrong offset specified")); + return {}; + } + + offset_date = r_offset_date.ok(); + offset_dialog_id = DialogId(r_offset_dialog_id.ok()); + offset_message_id = ServerMessageId(r_offset_message_id.ok()); + } + + do { + random_id = Random::secure_int64(); + } while (random_id == 0 || found_message_public_forwards_.find(random_id) != found_message_public_forwards_.end()); + found_message_public_forwards_[random_id]; // reserve place for result + + LOG(DEBUG) << "Get public message forwards from date " << offset_date << ", " << offset_dialog_id + << ", server message " << offset_message_id.get() << " and with limit " << limit; + + td_->create_handler(std::move(promise)) + ->send(full_message_id, offset_date, offset_dialog_id, offset_message_id, limit, random_id); + return {}; +} + Result MessagesManager::get_message_schedule_date( td_api::object_ptr &&scheduling_state) { if (scheduling_state == nullptr) { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 52a03bf55..196bd9df0 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -246,6 +246,10 @@ class MessagesManager : public Actor { vector> &&messages); void on_get_recent_locations_failed(int64 random_id); + void on_get_message_public_forwards_result(int64 random_id, int32 total_count, + vector> &&messages); + void on_failed_get_message_public_forwards(int64 random_id); + // if message is from_update, flags have_previous and have_next are ignored and should be both true FullMessageId on_get_message(tl_object_ptr message_ptr, bool from_update, bool is_channel_message, bool is_scheduled, bool have_previous, bool have_next, @@ -653,9 +657,16 @@ class MessagesManager : public Actor { const tl_object_ptr &filter, int64 &random_id, bool use_db, Promise &&promise); - std::pair> offline_search_messages( - DialogId dialog_id, const string &query, const string &offset, int32 limit, - const tl_object_ptr &filter, int64 &random_id, Promise<> &&promise); + struct FoundMessages { + vector full_message_ids; + string next_offset; + }; + + td_api::object_ptr get_found_messages_object(const FoundMessages &found_messages); + + FoundMessages offline_search_messages(DialogId dialog_id, const string &query, const string &offset, int32 limit, + const tl_object_ptr &filter, int64 &random_id, + Promise<> &&promise); std::pair> search_messages(FolderId folder_id, bool ignore_folder_id, const string &query, int32 offset_date, @@ -683,6 +694,9 @@ class MessagesManager : public Actor { vector get_dialog_scheduled_messages(DialogId dialog_id, bool force, bool ignore_result, Promise &&promise); + FoundMessages get_message_public_forwards(FullMessageId full_message_id, const string &offset, int32 limit, + int64 &random_id, Promise &&promise); + tl_object_ptr get_dialog_message_by_date_object(int64 random_id); tl_object_ptr get_message_object(FullMessageId full_message_id); @@ -2931,8 +2945,8 @@ class MessagesManager : public Actor { std::unordered_map>> found_dialog_recent_location_messages_; // random_id -> [total_count, [message_id]...] - std::unordered_map>> - found_fts_messages_; // random_id -> [next_offset, [full_message_id]...] + std::unordered_map found_fts_messages_; // random_id -> FoundMessages + std::unordered_map found_message_public_forwards_; // random_id -> FoundMessages std::unordered_map, FullMessageIdHash> public_message_links_[2]; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 730da7a58..f0887f540 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1473,21 +1473,15 @@ class SearchSecretMessagesRequest : public RequestActor<> { tl_object_ptr filter_; int64 random_id_; - std::pair> messages_; + MessagesManager::FoundMessages found_messages_; void do_run(Promise &&promise) override { - messages_ = td->messages_manager_->offline_search_messages(dialog_id_, query_, offset_, limit_, filter_, random_id_, - std::move(promise)); + found_messages_ = td->messages_manager_->offline_search_messages(dialog_id_, query_, offset_, limit_, filter_, + random_id_, std::move(promise)); } void do_send_result() override { - vector> result; - result.reserve(messages_.second.size()); - for (auto full_message_id : messages_.second) { - result.push_back(td->messages_manager_->get_message_object(full_message_id)); - } - - send_result(make_tl_object(std::move(result), std::move(messages_.first))); + send_result(td->messages_manager_->get_found_messages_object(found_messages_)); } public: @@ -1685,6 +1679,34 @@ class GetChatScheduledMessagesRequest : public RequestActor<> { } }; +class GetMessagePublicForwardsRequest : public RequestActor<> { + FullMessageId full_message_id_; + string offset_; + int32 limit_; + int64 random_id_; + + MessagesManager::FoundMessages messages_; + + void do_run(Promise &&promise) override { + messages_ = td->messages_manager_->get_message_public_forwards(full_message_id_, offset_, limit_, random_id_, + std::move(promise)); + } + + void do_send_result() override { + send_result(td->messages_manager_->get_found_messages_object(messages_)); + } + + public: + GetMessagePublicForwardsRequest(ActorShared td, uint64 request_id, int64 dialog_id, int64 message_id, + string offset, int32 limit) + : RequestActor(std::move(td), request_id) + , full_message_id_(DialogId(dialog_id), MessageId(message_id)) + , offset_(std::move(offset)) + , limit_(limit) + , random_id_(0) { + } +}; + class GetWebPagePreviewRequest : public RequestOnceActor { td_api::object_ptr text_; @@ -1875,10 +1897,6 @@ class GetChatMemberRequest : public RequestActor<> { send_result(td->contacts_manager_->get_chat_member_object(dialog_participant_)); } - void do_send_error(Status &&status) override { - send_error(std::move(status)); - } - public: GetChatMemberRequest(ActorShared td, uint64 request_id, int64 dialog_id, int32 user_id) : RequestActor(std::move(td), request_id), dialog_id_(dialog_id), user_id_(user_id), random_id_(0) { @@ -5463,6 +5481,7 @@ void Td::on_request(uint64 id, td_api::searchChatMessages &request) { void Td::on_request(uint64 id, td_api::searchSecretMessages &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.query_); + CLEAN_INPUT_STRING(request.offset_); CREATE_REQUEST(SearchSecretMessagesRequest, request.chat_id_, std::move(request.query_), std::move(request.offset_), request.limit_, std::move(request.filter_)); } @@ -5508,6 +5527,13 @@ void Td::on_request(uint64 id, const td_api::getChatScheduledMessages &request) CREATE_REQUEST(GetChatScheduledMessagesRequest, request.chat_id_); } +void Td::on_request(uint64 id, td_api::getMessagePublicForwards &request) { + CHECK_IS_USER(); + CLEAN_INPUT_STRING(request.offset_); + CREATE_REQUEST(GetMessagePublicForwardsRequest, request.chat_id_, request.message_id_, request.offset_, + request.limit_); +} + void Td::on_request(uint64 id, const td_api::removeNotification &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index f736e1e19..208c02933 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -585,6 +585,8 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, const td_api::getChatScheduledMessages &request); + void on_request(uint64 id, td_api::getMessagePublicForwards &request); + void on_request(uint64 id, const td_api::removeNotification &request); void on_request(uint64 id, const td_api::removeNotificationGroup &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 5300c31e0..fc32b541f 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1843,6 +1843,18 @@ class CliClient final : public Actor { } else if (op == "gcsm") { string chat_id = args; send_request(td_api::make_object(as_chat_id(chat_id))); + } else if (op == "gmpf") { + string chat_id; + string message_id; + string offset; + string limit; + + std::tie(chat_id, args) = split(args); + std::tie(message_id, args) = split(args); + std::tie(offset, limit) = split(args); + + send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), + offset, to_integer(limit))); } else if (op == "ghf") { get_history_chat_id_ = as_chat_id(args); From ca3d263c25589310c0b1807d297f8c33eb067274 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 21 Aug 2020 15:08:47 +0300 Subject: [PATCH 18/39] Add total_count to FoundMessages. GitOrigin-RevId: ade2685b5d19dfb5cf31d4e952074879393915ee --- td/generate/scheme/td_api.tl | 4 ++-- td/generate/scheme/td_api.tlo | Bin 179680 -> 179716 bytes td/telegram/MessagesManager.cpp | 17 +++++++++++------ td/telegram/MessagesManager.h | 4 +++- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 0b1d48f3f..aeb600c45 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -681,8 +681,8 @@ message id:int53 sender_user_id:int32 chat_id:int53 sending_state:MessageSending //@description Contains a list of messages @total_count Approximate total count of messages found @messages List of messages; messages may be null messages total_count:int32 messages:vector = Messages; -//@description Contains a list of messages found by a search @messages List of messages @next_offset The offset for the next request. If empty, there are no more results -foundMessages messages:vector next_offset:string = FoundMessages; +//@description Contains a list of messages found by a search @total_count Approximate total count of messages found; -1 if unknown @messages List of messages @next_offset The offset for the next request. If empty, there are no more results +foundMessages total_count:int32 messages:vector next_offset:string = FoundMessages; //@class NotificationSettingsScope @description Describes the types of chats to which notification settings are applied diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 051116aefffa6866b8541a5ecc8699d234de41b2..d9239b42266c9f9399070678801cc6506cae2966 100644 GIT binary patch delta 122 zcmaFxo2%sy*M_44%=@z+Y(63Iccu)G!JC#}nwR36T3no%o?6VnU;z}nc}&QMd3vK7 zWBhalWk#0C3ad3idYXM!Z}(Zv*t-J6neMQMF<`n*2$L&_x4k5UN!J7{K7o} NrdF_cL?=^+2>|vEGuZ$D delta 131 zcmZqq!}Z`d*M_44%!(HmZayLKccu)G!JC#}nwR36T3no%o?6VnU;z}nc}&QMY5GYu zM(fEAt93!jn+sNNFIdgky8^_S7Q!?YL~oxF!lY}$0oA}dS+GWZdV)2R!t^%}8D*v` WG%}e?Z)jo?VF4Mry{40?!vp|oP&EMn diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 5e8639290..0425eda55 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -8917,7 +8917,7 @@ void MessagesManager::on_get_message_public_forwards_result(int64 random_id, int << m->message_id.get_server_message_id().get(); } - // it->second.total_count = total_count; + it->second.total_count = total_count; } void MessagesManager::on_failed_get_message_public_forwards(int64 random_id) { @@ -19093,7 +19093,8 @@ td_api::object_ptr MessagesManager::get_found_messages_ob } } - return td_api::make_object(std::move(result), found_messages.next_offset); + return td_api::make_object(found_messages.total_count, std::move(result), + found_messages.next_offset); } MessagesManager::FoundMessages MessagesManager::offline_search_messages( @@ -19151,16 +19152,17 @@ MessagesManager::FoundMessages MessagesManager::offline_search_messages( G()->td_db()->get_messages_db_async()->get_messages_fts( std::move(fts_query), - PromiseCreator::lambda([random_id, promise = std::move(promise)](Result fts_result) mutable { + PromiseCreator::lambda([random_id, offset = std::move(offset), limit, + promise = std::move(promise)](Result fts_result) mutable { send_closure(G()->messages_manager(), &MessagesManager::on_messages_db_fts_result, std::move(fts_result), - random_id, std::move(promise)); + std::move(offset), limit, random_id, std::move(promise)); })); return {}; } -void MessagesManager::on_messages_db_fts_result(Result result, int64 random_id, - Promise &&promise) { +void MessagesManager::on_messages_db_fts_result(Result result, string offset, int32 limit, + int64 random_id, Promise &&promise) { if (G()->close_flag()) { result = Status::Error(500, "Request aborted"); } @@ -19184,6 +19186,9 @@ void MessagesManager::on_messages_db_fts_result(Result resu } it->second.next_offset = fts_result.next_search_id <= 1 ? string() : to_string(fts_result.next_search_id); + it->second.total_count = offset.empty() && fts_result.messages.size() < static_cast(limit) + ? static_cast(fts_result.messages.size()) + : -1; promise.set_value(Unit()); } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 196bd9df0..e2ab36503 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -660,6 +660,7 @@ class MessagesManager : public Actor { struct FoundMessages { vector full_message_ids; string next_offset; + int32 total_count = 0; }; td_api::object_ptr get_found_messages_object(const FoundMessages &found_messages); @@ -2495,7 +2496,8 @@ class MessagesManager : public Actor { int32 offset, int32 limit, Result> r_messages, Promise<> promise); - void on_messages_db_fts_result(Result result, int64 random_id, Promise<> &&promise); + void on_messages_db_fts_result(Result result, string offset, int32 limit, int64 random_id, + Promise<> &&promise); void on_messages_db_calls_result(Result result, int64 random_id, MessageId first_db_message_id, SearchMessagesFilter filter, Promise &&promise); From e848087e24ec8d264d03fc47ac6f0f9017264f32 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 21 Aug 2020 15:38:23 +0300 Subject: [PATCH 19/39] Support sending silent messages in secret chats. GitOrigin-RevId: fe15f9526bd5066b596e7e31d28bd9bab20cf719 --- td/generate/scheme/td_api.tl | 2 +- td/telegram/MessagesManager.cpp | 6 +----- td/telegram/SecretChatActor.cpp | 18 +++++++++++++++--- td/telegram/logevent/SecretChatEvent.h | 3 +++ 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index aeb600c45..879ad9b09 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1693,7 +1693,7 @@ messageSchedulingStateSendWhenOnline = MessageSchedulingState; //@description Options to be used when a message is sent -//@disable_notification Pass true to disable notification for the message. Must be false if the message is sent to a secret chat +//@disable_notification Pass true to disable notification for the message //@from_background Pass true if the message is sent from the background //@scheduling_state Message scheduling state. Messages sent to a secret chat, live location messages and self-destructing messages can't be scheduled messageSendOptions disable_notification:Bool from_background:Bool scheduling_state:MessageSchedulingState = MessageSendOptions; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 0425eda55..057c9715b 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -20953,12 +20953,8 @@ Result MessagesManager::process_message_sen } auto dialog_type = dialog_id.get_type(); - bool is_secret = dialog_type == DialogType::SecretChat; - if (result.disable_notification && is_secret) { - return Status::Error(400, "Can't send messages with silent notifications to secret chats"); - } if (result.schedule_date != 0) { - if (is_secret) { + if (dialog_type == DialogType::SecretChat) { return Status::Error(400, "Can't schedule messages in secret chats"); } if (td_->auth_manager_->is_bot()) { diff --git a/td/telegram/SecretChatActor.cpp b/td/telegram/SecretChatActor.cpp index a46f7bd5b..4310a2b2f 100644 --- a/td/telegram/SecretChatActor.cpp +++ b/td/telegram/SecretChatActor.cpp @@ -324,7 +324,7 @@ void SecretChatActor::send_message_impl(tl_object_ptrneed_notify_user = (flags & SendFlag::Push) == 0; binlog_event->is_external = (flags & SendFlag::External) != 0; + binlog_event->is_silent = (message->get_id() == secret_api::decryptedMessage::ID && + (static_cast(message.get())->flags_ & + secret_api::decryptedMessage::SILENT_MASK) != 0); if (message->get_id() == secret_api::decryptedMessageService::ID) { binlog_event->is_rewritable = false; auto service_message = move_tl_object_as(message); @@ -1467,13 +1470,21 @@ NetQueryPtr SecretChatActor::create_net_query(const logevent::OutboundSecretMess telegram_api::messages_sendEncryptedService(get_input_chat(), message.random_id, message.encrypted_message.clone())); } else if (message.file.empty()) { + int32 flags = 0; + if (message.is_silent) { + flags |= telegram_api::messages_sendEncrypted::SILENT_MASK; + } query = create_net_query( - QueryType::Message, telegram_api::messages_sendEncrypted(0, false /*ignored*/, get_input_chat(), + QueryType::Message, telegram_api::messages_sendEncrypted(flags, false /*ignored*/, get_input_chat(), message.random_id, message.encrypted_message.clone())); } else { + int32 flags = 0; + if (message.is_silent) { + flags |= telegram_api::messages_sendEncryptedFile::SILENT_MASK; + } query = create_net_query(QueryType::Message, telegram_api::messages_sendEncryptedFile( - 0, false /*ignored*/, get_input_chat(), message.random_id, + flags, false /*ignored*/, get_input_chat(), message.random_id, message.encrypted_message.clone(), message.file.as_input_encrypted_file())); } if (!message.is_rewritable) { @@ -1562,6 +1573,7 @@ Status SecretChatActor::outbound_rewrite_with_empty(uint64 state_id) { state->message->is_rewritable = false; state->message->is_external = false; state->message->need_notify_user = false; + state->message->is_silent = true; state->message->file = logevent::EncryptedInputFile::from_input_encrypted_file(nullptr); binlog_rewrite(context_->binlog(), state->message->logevent_id(), LogEvent::HandlerType::SecretChats, create_storer(*state->message)); diff --git a/td/telegram/logevent/SecretChatEvent.h b/td/telegram/logevent/SecretChatEvent.h index c01e86993..361574cf8 100644 --- a/td/telegram/logevent/SecretChatEvent.h +++ b/td/telegram/logevent/SecretChatEvent.h @@ -330,6 +330,7 @@ class OutboundSecretMessage : public SecretChatLogEventBase action; uint64 crc = 0; // DEBUG; @@ -360,6 +361,7 @@ class OutboundSecretMessage : public SecretChatLogEventBase Date: Fri, 21 Aug 2020 17:40:05 +0300 Subject: [PATCH 20/39] Add filter support to searchMessages. GitOrigin-RevId: 571b0ee894296c1e8c947939f7098a1566731461 --- td/generate/scheme/td_api.tl | 5 ++-- td/generate/scheme/td_api.tlo | Bin 179716 -> 179748 bytes td/telegram/MessagesManager.cpp | 46 +++++++++++++++++++------------- td/telegram/MessagesManager.h | 7 +++-- td/telegram/Td.cpp | 9 ++++--- td/telegram/cli.cpp | 15 ++++++----- 6 files changed, 51 insertions(+), 31 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 879ad9b09..636194144 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3591,14 +3591,15 @@ searchChatMessages chat_id:int53 query:string sender_user_id:int32 from_message_ //@offset_chat_id The chat identifier of the last found message, or 0 for the first request //@offset_message_id The message identifier of the last found message, or 0 for the first request //@limit The maximum number of messages to be returned; up to 100. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached -searchMessages chat_list:ChatList query:string offset_date:int32 offset_chat_id:int53 offset_message_id:int53 limit:int32 = Messages; +//@filter Filter for message content in the search results; searchMessagesFilterCall, searchMessagesFilterMissedCall, searchMessagesFilterMention, searchMessagesFilterUnreadMention and searchMessagesFilterFailedToSend are unsupported in this function +searchMessages chat_list:ChatList query:string offset_date:int32 offset_chat_id:int53 offset_message_id:int53 limit:int32 filter:SearchMessagesFilter = Messages; //@description Searches for messages in secret chats. Returns the results in reverse chronological order. For optimal performance the number of returned messages is chosen by the library //@chat_id Identifier of the chat in which to search. Specify 0 to search in all secret chats //@query Query to search for. If empty, searchChatMessages should be used instead //@offset Offset of the first entry to return as received from the previous request; use empty string to get first chunk of results //@limit The maximum number of messages to be returned; up to 100. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached -//@filter A filter for the content of messages in the search results +//@filter A filter for message content in the search results searchSecretMessages chat_id:int53 query:string offset:string limit:int32 filter:SearchMessagesFilter = FoundMessages; //@description Searches for call messages. Returns the results in reverse chronological order (i. e., in order of decreasing message_id). For optimal performance the number of returned messages is chosen by the library diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index d9239b42266c9f9399070678801cc6506cae2966..0af42c6b0e0a07a871d47786c1ab2e60d44f3801 100644 GIT binary patch delta 51 zcmV-30L=e{{0gM}3V?(Gv;x?M1gHkUJ(t{u0vG`YmjT!TE0-XL0<@P&^-bW Jx9o=k7&aZg6LJ6m delta 47 zcmV+~0MP%W{0fBp3V?(Gv;x?M1O;H!net_query_creator().create(telegram_api::messages_searchGlobal( - flags, folder_id.get(), query, make_tl_object(), offset_date_, + flags, folder_id.get(), query, MessagesManager::get_input_messages_filter(filter), offset_date_, std::move(input_peer), offset_message_id.get_server_message_id().get(), limit))); } @@ -1683,7 +1686,7 @@ class SearchMessagesGlobalQuery : public Td::ResultHandler { auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "SearchMessagesGlobalQuery"); td->messages_manager_->on_get_messages_search_result(query_, offset_date_, offset_dialog_id_, offset_message_id_, - limit_, random_id_, info.total_count, + limit_, filter_, random_id_, info.total_count, std::move(info.messages)); promise_.set_value(Unit()); @@ -8745,8 +8748,8 @@ void MessagesManager::on_failed_dialog_messages_search(DialogId dialog_id, int64 } void MessagesManager::on_get_messages_search_result(const string &query, int32 offset_date, DialogId offset_dialog_id, - MessageId offset_message_id, int32 limit, int64 random_id, - int32 total_count, + MessageId offset_message_id, int32 limit, + SearchMessagesFilter filter, int64 random_id, int32 total_count, vector> &&messages) { LOG(INFO) << "Receive " << messages.size() << " found messages"; auto it = found_messages_.find(random_id); @@ -19229,11 +19232,10 @@ void MessagesManager::on_messages_db_calls_result(Result promise.set_value(Unit()); } -std::pair> MessagesManager::search_messages(FolderId folder_id, bool ignore_folder_id, - const string &query, int32 offset_date, - DialogId offset_dialog_id, - MessageId offset_message_id, int32 limit, - int64 &random_id, Promise &&promise) { +std::pair> MessagesManager::search_messages( + FolderId folder_id, bool ignore_folder_id, const string &query, int32 offset_date, DialogId offset_dialog_id, + MessageId offset_message_id, int32 limit, const tl_object_ptr &filter, + int64 &random_id, Promise &&promise) { if (random_id != 0) { // request has already been sent before auto it = found_messages_.find(random_id); @@ -19244,10 +19246,9 @@ std::pair> MessagesManager::search_messages(FolderI return result; } - std::pair> result; if (limit <= 0) { promise.set_error(Status::Error(3, "Parameter limit must be positive")); - return result; + return {}; } if (limit > MAX_SEARCH_MESSAGES) { limit = MAX_SEARCH_MESSAGES; @@ -19259,19 +19260,27 @@ std::pair> MessagesManager::search_messages(FolderI if (!offset_message_id.is_valid()) { if (offset_message_id.is_valid_scheduled()) { promise.set_error(Status::Error(3, "Parameter offset_message_id can't be a scheduled message identifier")); - return result; + return {}; } offset_message_id = MessageId(); } if (offset_message_id != MessageId() && !offset_message_id.is_server()) { promise.set_error( Status::Error(3, "Parameter offset_message_id must be identifier of the last found message or 0")); - return result; + return {}; } if (query.empty()) { promise.set_value(Unit()); - return result; + return {}; + } + + auto filter_type = get_search_messages_filter(filter); + if (filter_type == SearchMessagesFilter::Call || filter_type == SearchMessagesFilter::MissedCall || + filter_type == SearchMessagesFilter::Mention || filter_type == SearchMessagesFilter::UnreadMention || + filter_type == SearchMessagesFilter::FailedToSend) { + promise.set_error(Status::Error(400, "The filter is not supported")); + return {}; } do { @@ -19280,11 +19289,12 @@ std::pair> MessagesManager::search_messages(FolderI found_messages_[random_id]; // reserve place for result LOG(DEBUG) << "Search messages globally with query = \"" << query << "\" from date " << offset_date << ", " - << offset_dialog_id << ", " << offset_message_id << " and with limit " << limit; + << offset_dialog_id << ", " << offset_message_id << " and limit " << limit; td_->create_handler(std::move(promise)) - ->send(folder_id, ignore_folder_id, query, offset_date, offset_dialog_id, offset_message_id, limit, random_id); - return result; + ->send(folder_id, ignore_folder_id, query, offset_date, offset_dialog_id, offset_message_id, limit, filter_type, + random_id); + return {}; } int64 MessagesManager::get_dialog_message_by_date(DialogId dialog_id, int32 date, Promise &&promise) { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index e2ab36503..c7500bc98 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -235,7 +235,8 @@ class MessagesManager : public Actor { void on_failed_dialog_messages_search(DialogId dialog_id, int64 random_id); void on_get_messages_search_result(const string &query, int32 offset_date, DialogId offset_dialog_id, - MessageId offset_message_id, int32 limit, int64 random_id, int32 total_count, + MessageId offset_message_id, int32 limit, SearchMessagesFilter filter, + int64 random_id, int32 total_count, vector> &&messages); void on_failed_messages_search(int64 random_id); @@ -672,7 +673,9 @@ class MessagesManager : public Actor { std::pair> search_messages(FolderId folder_id, bool ignore_folder_id, const string &query, int32 offset_date, DialogId offset_dialog_id, MessageId offset_message_id, - int32 limit, int64 &random_id, Promise &&promise); + int32 limit, + const tl_object_ptr &filter, + int64 &random_id, Promise &&promise); std::pair> search_call_messages(MessageId from_message_id, int32 limit, bool only_missed, int64 &random_id, bool use_db, Promise &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index f0887f540..fd01ed4bf 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1505,6 +1505,7 @@ class SearchMessagesRequest : public RequestActor<> { DialogId offset_dialog_id_; MessageId offset_message_id_; int32 limit_; + tl_object_ptr filter_; int64 random_id_; std::pair> messages_; @@ -1512,7 +1513,7 @@ class SearchMessagesRequest : public RequestActor<> { void do_run(Promise &&promise) override { messages_ = td->messages_manager_->search_messages(folder_id_, ignore_folder_id_, query_, offset_date_, offset_dialog_id_, - offset_message_id_, limit_, random_id_, std::move(promise)); + offset_message_id_, limit_, filter_, random_id_, std::move(promise)); } void do_send_result() override { @@ -1530,7 +1531,8 @@ class SearchMessagesRequest : public RequestActor<> { public: SearchMessagesRequest(ActorShared td, uint64 request_id, FolderId folder_id, bool ignore_folder_id, string query, - int32 offset_date, int64 offset_dialog_id, int64 offset_message_id, int32 limit) + int32 offset_date, int64 offset_dialog_id, int64 offset_message_id, int32 limit, + tl_object_ptr &&filter) : RequestActor(std::move(td), request_id) , folder_id_(folder_id) , ignore_folder_id_(ignore_folder_id) @@ -1539,6 +1541,7 @@ class SearchMessagesRequest : public RequestActor<> { , offset_dialog_id_(offset_dialog_id) , offset_message_id_(offset_message_id) , limit_(limit) + , filter_(std::move(filter)) , random_id_(0) { } }; @@ -5495,7 +5498,7 @@ void Td::on_request(uint64 id, td_api::searchMessages &request) { } CREATE_REQUEST(SearchMessagesRequest, dialog_list_id.get_folder_id(), request.chat_list_ == nullptr, std::move(request.query_), request.offset_date_, request.offset_chat_id_, request.offset_message_id_, - request.limit_); + request.limit_, std::move(request.filter_)); } void Td::on_request(uint64 id, td_api::searchCallMessages &request) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index fc32b541f..03fea0214 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1008,7 +1008,7 @@ class CliClient final : public Actor { return nullptr; } - static td_api::object_ptr get_search_messages_filter(MutableSlice filter) { + static td_api::object_ptr as_search_messages_filter(MutableSlice filter) { filter = trim(filter); to_lower_inplace(filter); if (filter == "an" || filter == "animation") { @@ -1869,9 +1869,11 @@ class CliClient final : public Actor { string from_date; string limit; string query; + string filter; std::tie(query, args) = split(args); - std::tie(limit, from_date) = split(args); + std::tie(limit, args) = split(args); + std::tie(filter, from_date) = split(args); if (from_date.empty()) { from_date = "0"; } @@ -1883,7 +1885,8 @@ class CliClient final : public Actor { chat_list = td_api::make_object(); } send_request(td_api::make_object( - std::move(chat_list), query, to_integer(from_date), 2147482647, 0, to_integer(limit))); + std::move(chat_list), query, to_integer(from_date), 2147482647, 0, to_integer(limit), + as_search_messages_filter(filter))); } else if (op == "SCM") { string chat_id; string limit; @@ -1944,7 +1947,7 @@ class CliClient final : public Actor { send_request(td_api::make_object( as_chat_id(chat_id), "", 0, as_message_id(offset_message_id), to_integer(offset), - to_integer(limit), get_search_messages_filter(filter))); + to_integer(limit), as_search_messages_filter(filter))); } else if (op == "SC") { string limit; string offset_message_id; @@ -2053,7 +2056,7 @@ class CliClient final : public Actor { std::tie(filter, return_local) = split(args); send_request(td_api::make_object( - as_chat_id(chat_id), get_search_messages_filter(filter), as_bool(return_local))); + as_chat_id(chat_id), as_search_messages_filter(filter), as_bool(return_local))); } else if (op == "gup" || op == "gupp") { string user_id; string offset; @@ -2936,7 +2939,7 @@ class CliClient final : public Actor { std::tie(filter, query) = split(args); send_request(td_api::make_object( - as_chat_id(chat_id), query, offset, to_integer(limit), get_search_messages_filter(filter))); + as_chat_id(chat_id), query, offset, to_integer(limit), as_search_messages_filter(filter))); } else if (op == "ssd") { schedule_date_ = args; } else if (op == "sm" || op == "sms" || op == "smr" || op == "smf") { From 552a0550c2af6b988a53614ca6406ddd7500fbd0 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 21 Aug 2020 20:53:39 +0300 Subject: [PATCH 21/39] Add two new call problems. GitOrigin-RevId: 036e7b52be8daa114fa919f560410b5edb09b461 --- td/generate/scheme/td_api.tl | 6 ++++++ td/generate/scheme/td_api.tlo | Bin 179748 -> 179884 bytes td/telegram/CallActor.cpp | 4 ++++ td/telegram/cli.cpp | 2 ++ 4 files changed, 12 insertions(+) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 636194144..2e30bac18 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1989,6 +1989,12 @@ callProblemSilentRemote = CallProblem; //@description The call ended unexpectedly callProblemDropped = CallProblem; +//@description The video was distorted +callProblemDistortedVideo = CallProblem; + +//@description The video was pixelated +callProblemPixelatedVideo = CallProblem; + //@description Describes a call @id Call identifier, not persistent @user_id Peer user identifier @is_outgoing True, if the call is outgoing @is_video True, if the call is a video call @state Call state call id:int32 user_id:int32 is_outgoing:Bool is_video:Bool state:CallState = Call; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 0af42c6b0e0a07a871d47786c1ab2e60d44f3801..876600ebc272616aeab4207820b61974c199ab67 100644 GIT binary patch delta 408 zcmZ4ThilDWt_@RI1ZObZ-@)yin3EGwl%JH7n#(zPB9r*$JuETWjMkea4Von-Kq_t? z6Y^mIf+A-&9S+;JgCMcVTRc^8OMdXw!7XXxg-5c&O9Qvg9rz@Fc&XImaxKX9AaGTV zD~2oSo0w!W!p|<5#U=SgC8;T4nJKCH3=G7Waam2Y4%v)=%!<^U#1ch*Ea7&ta;gPKH(!i~A2R_LkUbr39yvMtJk2mA? ZJ>E<$j;tW}GfZE|#3a8xrI*RW5CDY8S|k7f diff --git a/td/telegram/CallActor.cpp b/td/telegram/CallActor.cpp index e622d922e..838aba9a4 100644 --- a/td/telegram/CallActor.cpp +++ b/td/telegram/CallActor.cpp @@ -277,6 +277,10 @@ void CallActor::rate_call(int32 rating, string comment, vector> problems; problems.emplace_back(td_api::make_object()); problems.emplace_back(td_api::make_object()); + problems.emplace_back(td_api::make_object()); problems.emplace_back(nullptr); problems.emplace_back(td_api::make_object()); problems.emplace_back(td_api::make_object()); + problems.emplace_back(td_api::make_object()); problems.emplace_back(td_api::make_object()); send_request(td_api::make_object( as_call_id(call_id), to_integer(rating), "Wow, such good call! (TDLib test)", std::move(problems))); From f28373a71f770def1e262c92e8b0345ef2896c84 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 21 Aug 2020 21:21:52 +0300 Subject: [PATCH 22/39] Allow to search messages with empty query and non-empty filter. GitOrigin-RevId: bf8e2a0ab5dc2c48b3760ec595e6d22e9da965a5 --- td/telegram/MessagesManager.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 3f14ec7d7..9e406517a 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -19270,11 +19270,6 @@ std::pair> MessagesManager::search_messages( return {}; } - if (query.empty()) { - promise.set_value(Unit()); - return {}; - } - auto filter_type = get_search_messages_filter(filter); if (filter_type == SearchMessagesFilter::Call || filter_type == SearchMessagesFilter::MissedCall || filter_type == SearchMessagesFilter::Mention || filter_type == SearchMessagesFilter::UnreadMention || @@ -19283,6 +19278,11 @@ std::pair> MessagesManager::search_messages( return {}; } + if (query.empty() && filter_type == SearchMessagesFilter::Empty) { + promise.set_value(Unit()); + return {}; + } + do { random_id = Random::secure_int64(); } while (random_id == 0 || found_messages_.find(random_id) != found_messages_.end()); From 7d6546b27af962f25e5d19e5952dede2ca30f401 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 22 Aug 2020 10:05:51 +0300 Subject: [PATCH 23/39] Rename SearchMessagesFilter to MessageSearchFilter. GitOrigin-RevId: ac477d22eae9382c6e9d63e184f10490c1bf4292 --- td/telegram/MessageContent.cpp | 36 +++---- td/telegram/MessagesDb.cpp | 12 +-- td/telegram/MessagesDb.h | 22 ++-- td/telegram/MessagesManager.cpp | 186 ++++++++++++++++---------------- td/telegram/MessagesManager.h | 21 ++-- 5 files changed, 138 insertions(+), 139 deletions(-) diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 4d156a3da..1146a9ee3 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -2447,7 +2447,7 @@ static int32 get_message_content_text_index_mask(const MessageContent *content) for (auto &entity : text->entities) { if (entity.type == MessageEntity::Type::Url || entity.type == MessageEntity::Type::EmailAddress || entity.type == MessageEntity::Type::TextUrl) { - return search_messages_filter_index_mask(SearchMessagesFilter::Url); + return message_search_filter_index_mask(MessageSearchFilter::Url); } } return 0; @@ -2457,43 +2457,43 @@ static int32 get_message_content_media_index_mask(const MessageContent *content, bool is_outgoing) { switch (content->get_type()) { case MessageContentType::Animation: - return search_messages_filter_index_mask(SearchMessagesFilter::Animation); + return message_search_filter_index_mask(MessageSearchFilter::Animation); case MessageContentType::Audio: { auto message_audio = static_cast(content); auto duration = td->audios_manager_->get_audio_duration(message_audio->file_id); - return is_secret || duration > 0 ? search_messages_filter_index_mask(SearchMessagesFilter::Audio) - : search_messages_filter_index_mask(SearchMessagesFilter::Document); + return is_secret || duration > 0 ? message_search_filter_index_mask(MessageSearchFilter::Audio) + : message_search_filter_index_mask(MessageSearchFilter::Document); } case MessageContentType::Document: - return search_messages_filter_index_mask(SearchMessagesFilter::Document); + return message_search_filter_index_mask(MessageSearchFilter::Document); case MessageContentType::Photo: - return search_messages_filter_index_mask(SearchMessagesFilter::Photo) | - search_messages_filter_index_mask(SearchMessagesFilter::PhotoAndVideo); + return message_search_filter_index_mask(MessageSearchFilter::Photo) | + message_search_filter_index_mask(MessageSearchFilter::PhotoAndVideo); case MessageContentType::Video: { auto message_video = static_cast(content); auto duration = td->videos_manager_->get_video_duration(message_video->file_id); - return is_secret || duration > 0 ? search_messages_filter_index_mask(SearchMessagesFilter::Video) | - search_messages_filter_index_mask(SearchMessagesFilter::PhotoAndVideo) - : search_messages_filter_index_mask(SearchMessagesFilter::Document); + return is_secret || duration > 0 ? message_search_filter_index_mask(MessageSearchFilter::Video) | + message_search_filter_index_mask(MessageSearchFilter::PhotoAndVideo) + : message_search_filter_index_mask(MessageSearchFilter::Document); } case MessageContentType::VideoNote: { auto message_video_note = static_cast(content); auto duration = td->video_notes_manager_->get_video_note_duration(message_video_note->file_id); - return is_secret || duration > 0 ? search_messages_filter_index_mask(SearchMessagesFilter::VideoNote) | - search_messages_filter_index_mask(SearchMessagesFilter::VoiceAndVideoNote) - : search_messages_filter_index_mask(SearchMessagesFilter::Document); + return is_secret || duration > 0 ? message_search_filter_index_mask(MessageSearchFilter::VideoNote) | + message_search_filter_index_mask(MessageSearchFilter::VoiceAndVideoNote) + : message_search_filter_index_mask(MessageSearchFilter::Document); } case MessageContentType::VoiceNote: - return search_messages_filter_index_mask(SearchMessagesFilter::VoiceNote) | - search_messages_filter_index_mask(SearchMessagesFilter::VoiceAndVideoNote); + return message_search_filter_index_mask(MessageSearchFilter::VoiceNote) | + message_search_filter_index_mask(MessageSearchFilter::VoiceAndVideoNote); case MessageContentType::ChatChangePhoto: - return search_messages_filter_index_mask(SearchMessagesFilter::ChatPhoto); + return message_search_filter_index_mask(MessageSearchFilter::ChatPhoto); case MessageContentType::Call: { - int32 index_mask = search_messages_filter_index_mask(SearchMessagesFilter::Call); + int32 index_mask = message_search_filter_index_mask(MessageSearchFilter::Call); auto message_call = static_cast(content); if (!is_outgoing && (message_call->discard_reason == CallDiscardReason::Declined || message_call->discard_reason == CallDiscardReason::Missed)) { - index_mask |= search_messages_filter_index_mask(SearchMessagesFilter::MissedCall); + index_mask |= message_search_filter_index_mask(MessageSearchFilter::MissedCall); } return index_mask; } diff --git a/td/telegram/MessagesDb.cpp b/td/telegram/MessagesDb.cpp index 024db5a23..f93816ea7 100644 --- a/td/telegram/MessagesDb.cpp +++ b/td/telegram/MessagesDb.cpp @@ -86,8 +86,8 @@ Status init_messages_db(SqliteDb &db, int32 version) { return Status::OK(); }; auto add_call_index = [&db] { - for (int i = static_cast(SearchMessagesFilter::Call) - 1; - i < static_cast(SearchMessagesFilter::MissedCall); i++) { + for (int i = static_cast(MessageSearchFilter::Call) - 1; i < static_cast(MessageSearchFilter::MissedCall); + i++) { TRY_STATUS(db.exec(PSLICE() << "CREATE INDEX IF NOT EXISTS full_message_index_" << i << " ON messages (unique_message_id) WHERE (index_mask & " << (1 << i) << ") != 0")); } @@ -237,8 +237,8 @@ class MessagesDbImpl : public MessagesDbSyncInterface { // LOG(ERROR) << get_messages_from_index_stmts_[i].asc_stmt_.explain().ok(); } - for (int i = static_cast(SearchMessagesFilter::Call) - 1, pos = 0; - i < static_cast(SearchMessagesFilter::MissedCall); i++, pos++) { + for (int i = static_cast(MessageSearchFilter::Call) - 1, pos = 0; + i < static_cast(MessageSearchFilter::MissedCall); i++, pos++) { TRY_RESULT_ASSIGN( get_calls_stmts_[pos], db_.get_statement( @@ -750,9 +750,9 @@ class MessagesDbImpl : public MessagesDbSyncInterface { return Status::Error("Union is not supported"); } int32 pos; - if (index_i + 1 == static_cast(SearchMessagesFilter::Call)) { + if (index_i + 1 == static_cast(MessageSearchFilter::Call)) { pos = 0; - } else if (index_i + 1 == static_cast(SearchMessagesFilter::MissedCall)) { + } else if (index_i + 1 == static_cast(MessageSearchFilter::MissedCall)) { pos = 1; } else { return Status::Error(PSLICE() << "Index_mask is not Call or MissedCall " << query.index_mask); diff --git a/td/telegram/MessagesDb.h b/td/telegram/MessagesDb.h index 565225ae1..96ce5ea94 100644 --- a/td/telegram/MessagesDb.h +++ b/td/telegram/MessagesDb.h @@ -27,7 +27,7 @@ class SqliteConnectionSafe; class SqliteDb; // append only before Size -enum class SearchMessagesFilter : int32 { +enum class MessageSearchFilter : int32 { Empty, Animation, Audio, @@ -178,25 +178,25 @@ std::shared_ptr create_messages_db_sync( std::shared_ptr create_messages_db_async(std::shared_ptr sync_db, int32 scheduler_id); -inline constexpr size_t search_messages_filter_size() { - return static_cast(SearchMessagesFilter::Size) - 1; +inline constexpr size_t message_search_filter_count() { + return static_cast(MessageSearchFilter::Size) - 1; } -inline int32 search_messages_filter_index(SearchMessagesFilter filter) { - CHECK(filter != SearchMessagesFilter::Empty); +inline int32 message_search_filter_index(MessageSearchFilter filter) { + CHECK(filter != MessageSearchFilter::Empty); return static_cast(filter) - 1; } -inline int32 search_messages_filter_index_mask(SearchMessagesFilter filter) { - if (filter == SearchMessagesFilter::Empty) { +inline int32 message_search_filter_index_mask(MessageSearchFilter filter) { + if (filter == MessageSearchFilter::Empty) { return 0; } - return 1 << search_messages_filter_index(filter); + return 1 << message_search_filter_index(filter); } -inline int32 search_calls_filter_index(SearchMessagesFilter filter) { - CHECK(filter == SearchMessagesFilter::Call || filter == SearchMessagesFilter::MissedCall); - return static_cast(filter) - static_cast(SearchMessagesFilter::Call); +inline int32 search_calls_filter_index(MessageSearchFilter filter) { + CHECK(filter == MessageSearchFilter::Call || filter == MessageSearchFilter::MissedCall); + return static_cast(filter) - static_cast(MessageSearchFilter::Call); } } // namespace td diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 9e406517a..e77f7616d 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -1574,7 +1574,7 @@ class SearchMessagesQuery : public Td::ResultHandler { MessageId from_message_id_; int32 offset_; int32 limit_; - SearchMessagesFilter filter_; + MessageSearchFilter filter_; int64 random_id_; public: @@ -1583,7 +1583,7 @@ class SearchMessagesQuery : public Td::ResultHandler { void send(DialogId dialog_id, const string &query, UserId sender_user_id, telegram_api::object_ptr &&sender_input_user, MessageId from_message_id, - int32 offset, int32 limit, SearchMessagesFilter filter, int64 random_id) { + int32 offset, int32 limit, MessageSearchFilter filter, int64 random_id) { auto input_peer = dialog_id.is_valid() ? td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read) : make_tl_object(); if (input_peer == nullptr) { @@ -1600,7 +1600,7 @@ class SearchMessagesQuery : public Td::ResultHandler { filter_ = filter; random_id_ = random_id; - if (filter == SearchMessagesFilter::UnreadMention) { + if (filter == MessageSearchFilter::UnreadMention) { send_query(G()->net_query_creator().create( telegram_api::messages_getUnreadMentions(std::move(input_peer), from_message_id.get_server_message_id().get(), offset, limit, std::numeric_limits::max(), 0))); @@ -1648,7 +1648,7 @@ class SearchMessagesGlobalQuery : public Td::ResultHandler { DialogId offset_dialog_id_; MessageId offset_message_id_; int32 limit_; - SearchMessagesFilter filter_; + MessageSearchFilter filter_; int64 random_id_; public: @@ -1656,7 +1656,7 @@ class SearchMessagesGlobalQuery : public Td::ResultHandler { } void send(FolderId folder_id, bool ignore_folder_id, const string &query, int32 offset_date, - DialogId offset_dialog_id, MessageId offset_message_id, int32 limit, SearchMessagesFilter filter, + DialogId offset_dialog_id, MessageId offset_message_id, int32 limit, MessageSearchFilter filter, int64 random_id) { query_ = query; offset_date_ = offset_date; @@ -4844,7 +4844,7 @@ void MessagesManager::Dialog::parse(ParserT &parser) { parse(message_count_by_index[i], parser); } } - unread_mention_count = message_count_by_index[search_messages_filter_index(SearchMessagesFilter::UnreadMention)]; + unread_mention_count = message_count_by_index[message_search_filter_index(MessageSearchFilter::UnreadMention)]; LOG(INFO) << "Set unread mention message count in " << dialog_id << " to " << unread_mention_count; if (unread_mention_count < 0) { unread_mention_count = 0; @@ -5211,7 +5211,7 @@ void MessagesManager::invalidate_message_indexes(Dialog *d) { CHECK(d != nullptr); bool is_secret = d->dialog_id.get_type() == DialogType::SecretChat; for (size_t i = 0; i < d->message_count_by_index.size(); i++) { - if (is_secret || i == static_cast(search_messages_filter_index(SearchMessagesFilter::FailedToSend))) { + if (is_secret || i == static_cast(message_search_filter_index(MessageSearchFilter::FailedToSend))) { // always know all messages d->first_database_message_id_by_index[i] = MessageId::min(); // keep the count @@ -5225,8 +5225,8 @@ void MessagesManager::invalidate_message_indexes(Dialog *d) { void MessagesManager::update_message_count_by_index(Dialog *d, int diff, const Message *m) { auto index_mask = get_message_index_mask(d->dialog_id, m); - index_mask &= ~search_messages_filter_index_mask( - SearchMessagesFilter::UnreadMention); // unread mention count has been already manually updated + index_mask &= ~message_search_filter_index_mask( + MessageSearchFilter::UnreadMention); // unread mention count has been already manually updated update_message_count_by_index(d, diff, index_mask); } @@ -5243,7 +5243,7 @@ void MessagesManager::update_message_count_by_index(Dialog *d, int diff, int32 i message_count += diff; if (message_count < 0) { if (d->dialog_id.get_type() == DialogType::SecretChat || - i == search_messages_filter_index(SearchMessagesFilter::FailedToSend)) { + i == message_search_filter_index(MessageSearchFilter::FailedToSend)) { message_count = 0; } else { message_count = -1; @@ -5254,7 +5254,7 @@ void MessagesManager::update_message_count_by_index(Dialog *d, int diff, int32 i i++; } - i = static_cast(SearchMessagesFilter::Call) - 1; + i = static_cast(MessageSearchFilter::Call) - 1; for (auto &message_count : calls_db_state_.message_count_by_index) { if (((index_mask >> i) & 1) != 0 && message_count != -1) { message_count += diff; @@ -5277,7 +5277,7 @@ int32 MessagesManager::get_message_index_mask(DialogId dialog_id, const Message return 0; } if (m->is_failed_to_send) { - return search_messages_filter_index_mask(SearchMessagesFilter::FailedToSend); + return message_search_filter_index_mask(MessageSearchFilter::FailedToSend); } bool is_secret = dialog_id.get_type() == DialogType::SecretChat; if (!m->message_id.is_server() && !is_secret) { @@ -5289,9 +5289,9 @@ int32 MessagesManager::get_message_index_mask(DialogId dialog_id, const Message } int32 index_mask = get_message_content_index_mask(m->content.get(), td_, is_secret, m->is_outgoing); if (m->contains_mention) { - index_mask |= search_messages_filter_index_mask(SearchMessagesFilter::Mention); + index_mask |= message_search_filter_index_mask(MessageSearchFilter::Mention); if (m->contains_unread_mention) { - index_mask |= search_messages_filter_index_mask(SearchMessagesFilter::UnreadMention); + index_mask |= message_search_filter_index_mask(MessageSearchFilter::UnreadMention); } } LOG(INFO) << "Have index mask " << index_mask << " for " << m->message_id << " in " << dialog_id; @@ -8592,7 +8592,7 @@ void MessagesManager::on_failed_public_dialogs_search(const string &query, Statu void MessagesManager::on_get_dialog_messages_search_result(DialogId dialog_id, const string &query, UserId sender_user_id, MessageId from_message_id, - int32 offset, int32 limit, SearchMessagesFilter filter, + int32 offset, int32 limit, MessageSearchFilter filter, int64 random_id, int32 total_count, vector> &&messages) { LOG(INFO) << "Receive " << messages.size() << " found messages in " << dialog_id; @@ -8687,7 +8687,7 @@ void MessagesManager::on_get_dialog_messages_search_result(DialogId dialog_id, c } auto message_id = new_full_message_id.get_message_id(); - if (filter == SearchMessagesFilter::UnreadMention && message_id <= d->last_read_all_mentions_message_id) { + if (filter == MessageSearchFilter::UnreadMention && message_id <= d->last_read_all_mentions_message_id) { total_count--; continue; } @@ -8703,14 +8703,14 @@ void MessagesManager::on_get_dialog_messages_search_result(DialogId dialog_id, c << " messages"; total_count = static_cast(result.size()); } - if (query.empty() && !sender_user_id.is_valid() && filter != SearchMessagesFilter::Empty && + if (query.empty() && !sender_user_id.is_valid() && filter != MessageSearchFilter::Empty && G()->parameters().use_message_db) { bool update_dialog = false; - auto &old_message_count = d->message_count_by_index[search_messages_filter_index(filter)]; + auto &old_message_count = d->message_count_by_index[message_search_filter_index(filter)]; if (old_message_count != total_count) { old_message_count = total_count; - if (filter == SearchMessagesFilter::UnreadMention) { + if (filter == MessageSearchFilter::UnreadMention) { d->unread_mention_count = old_message_count; update_dialog_mention_notification_count(d); send_update_chat_unread_mention_count(d); @@ -8718,7 +8718,7 @@ void MessagesManager::on_get_dialog_messages_search_result(DialogId dialog_id, c update_dialog = true; } - auto &old_first_db_message_id = d->first_database_message_id_by_index[search_messages_filter_index(filter)]; + auto &old_first_db_message_id = d->first_database_message_id_by_index[message_search_filter_index(filter)]; bool from_the_end = !from_message_id.is_valid() || (d->last_message_id != MessageId() && from_message_id > d->last_message_id) || from_message_id >= MessageId::max(); @@ -8749,7 +8749,7 @@ void MessagesManager::on_failed_dialog_messages_search(DialogId dialog_id, int64 void MessagesManager::on_get_messages_search_result(const string &query, int32 offset_date, DialogId offset_dialog_id, MessageId offset_message_id, int32 limit, - SearchMessagesFilter filter, int64 random_id, int32 total_count, + MessageSearchFilter filter, int64 random_id, int32 total_count, vector> &&messages) { LOG(INFO) << "Receive " << messages.size() << " found messages"; auto it = found_messages_.find(random_id); @@ -12552,7 +12552,7 @@ void MessagesManager::set_dialog_unread_mention_count(Dialog *d, int32 unread_me CHECK(unread_mention_count >= 0); d->unread_mention_count = unread_mention_count; - d->message_count_by_index[search_messages_filter_index(SearchMessagesFilter::UnreadMention)] = unread_mention_count; + d->message_count_by_index[message_search_filter_index(MessageSearchFilter::UnreadMention)] = unread_mention_count; } void MessagesManager::set_dialog_is_empty(Dialog *d, const char *source) { @@ -18464,8 +18464,8 @@ std::pair> MessagesManager::search_dialog_messages( return result; } - auto filter_type = get_search_messages_filter(filter); - if (filter_type == SearchMessagesFilter::FailedToSend && sender_user_id.is_valid()) { + auto filter_type = get_message_search_filter(filter); + if (filter_type == MessageSearchFilter::FailedToSend && sender_user_id.is_valid()) { if (sender_user_id != td_->contacts_manager_->get_my_id()) { promise.set_value(Unit()); return result; @@ -18484,7 +18484,7 @@ std::pair> MessagesManager::search_dialog_messages( } while (random_id == 0 || found_dialog_messages_.find(random_id) != found_dialog_messages_.end()); found_dialog_messages_[random_id]; // reserve place for result - if (filter_type == SearchMessagesFilter::UnreadMention) { + if (filter_type == MessageSearchFilter::UnreadMention) { if (!query.empty()) { promise.set_error(Status::Error(6, "Non-empty query is unsupported with the specified filter")); return result; @@ -18496,10 +18496,10 @@ std::pair> MessagesManager::search_dialog_messages( } // Trying to use database - if (use_db && query.empty() && G()->parameters().use_message_db && filter_type != SearchMessagesFilter::Empty && + if (use_db && query.empty() && G()->parameters().use_message_db && filter_type != MessageSearchFilter::Empty && input_user == nullptr) { // TODO support filter by users in the database MessageId first_db_message_id = get_first_database_message_id_by_index(d, filter_type); - int32 message_count = d->message_count_by_index[search_messages_filter_index(filter_type)]; + int32 message_count = d->message_count_by_index[message_search_filter_index(filter_type)]; auto fixed_from_message_id = from_message_id; if (fixed_from_message_id == MessageId()) { fixed_from_message_id = MessageId::max(); @@ -18519,7 +18519,7 @@ std::pair> MessagesManager::search_dialog_messages( }); MessagesDbMessagesQuery db_query; db_query.dialog_id = dialog_id; - db_query.index_mask = search_messages_filter_index_mask(filter_type); + db_query.index_mask = message_search_filter_index_mask(filter_type); db_query.from_message_id = fixed_from_message_id; db_query.offset = offset; db_query.limit = limit; @@ -18527,7 +18527,7 @@ std::pair> MessagesManager::search_dialog_messages( return result; } } - if (filter_type == SearchMessagesFilter::FailedToSend) { + if (filter_type == MessageSearchFilter::FailedToSend) { promise.set_value(Unit()); return result; } @@ -18545,7 +18545,7 @@ std::pair> MessagesManager::search_dialog_messages( random_id); break; case DialogType::SecretChat: - if (filter_type == SearchMessagesFilter::UnreadMention) { + if (filter_type == MessageSearchFilter::UnreadMention) { promise.set_value(Unit()); } else { promise.set_error(Status::Error(500, "Search messages in secret chats is not supported")); @@ -18598,7 +18598,7 @@ std::pair> MessagesManager::search_call_messages(Me } while (random_id == 0 || found_call_messages_.find(random_id) != found_call_messages_.end()); found_call_messages_[random_id]; // reserve place for result - auto filter_type = only_missed ? SearchMessagesFilter::MissedCall : SearchMessagesFilter::Call; + auto filter_type = only_missed ? MessageSearchFilter::MissedCall : MessageSearchFilter::Call; if (use_db && G()->parameters().use_message_db) { // try to use database @@ -18616,7 +18616,7 @@ std::pair> MessagesManager::search_call_messages(Me LOG(INFO) << "Search messages in database from " << fixed_from_message_id << " and with limit " << limit; MessagesDbCallsQuery db_query; - db_query.index_mask = search_messages_filter_index_mask(filter_type); + db_query.index_mask = message_search_filter_index_mask(filter_type); db_query.from_unique_message_id = fixed_from_message_id.get_server_message_id().get(); db_query.limit = limit; G()->td_db()->get_messages_db_async()->get_calls( @@ -19002,11 +19002,11 @@ void MessagesManager::change_message_files(DialogId dialog_id, const Message *m, } } -MessageId MessagesManager::get_first_database_message_id_by_index(const Dialog *d, SearchMessagesFilter filter) { +MessageId MessagesManager::get_first_database_message_id_by_index(const Dialog *d, MessageSearchFilter filter) { CHECK(d != nullptr); - auto message_id = filter == SearchMessagesFilter::Empty + auto message_id = filter == MessageSearchFilter::Empty ? d->first_database_message_id - : d->first_database_message_id_by_index[search_messages_filter_index(filter)]; + : d->first_database_message_id_by_index[message_search_filter_index(filter)]; CHECK(!message_id.is_scheduled()); if (!message_id.is_valid()) { if (d->dialog_id.get_type() == DialogType::SecretChat) { @@ -19020,7 +19020,7 @@ MessageId MessagesManager::get_first_database_message_id_by_index(const Dialog * void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, DialogId dialog_id, MessageId from_message_id, MessageId first_db_message_id, - SearchMessagesFilter filter_type, int32 offset, int32 limit, + MessageSearchFilter filter_type, int32 offset, int32 limit, Result> r_messages, Promise<> promise) { if (G()->close_flag()) { @@ -19029,7 +19029,7 @@ void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, Dialo if (r_messages.is_error()) { LOG(ERROR) << r_messages.error(); if (first_db_message_id != MessageId::min() && dialog_id.get_type() != DialogType::SecretChat && - filter_type != SearchMessagesFilter::FailedToSend) { + filter_type != MessageSearchFilter::FailedToSend) { found_dialog_messages_.erase(random_id); } return promise.set_value(Unit()); @@ -19050,7 +19050,7 @@ void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, Dialo for (auto &message : messages) { auto m = on_get_message_from_database(dialog_id, d, message, false, "on_search_dialog_messages_db_result"); if (m != nullptr && first_db_message_id <= m->message_id) { - if (filter_type == SearchMessagesFilter::UnreadMention && !m->contains_unread_mention) { + if (filter_type == MessageSearchFilter::UnreadMention && !m->contains_unread_mention) { // skip already read by d->last_read_all_mentions_message_id mentions } else { CHECK(!m->message_id.is_scheduled()); @@ -19059,7 +19059,7 @@ void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, Dialo } } - auto &message_count = d->message_count_by_index[search_messages_filter_index(filter_type)]; + auto &message_count = d->message_count_by_index[message_search_filter_index(filter_type)]; int32 result_size = narrow_cast(res.size()); bool from_the_end = from_message_id == MessageId::max() || (offset < 0 && (result_size == 0 || res[0] < from_message_id)); @@ -19068,7 +19068,7 @@ void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, Dialo result_size < limit + offset)) { LOG(INFO) << "Fix found message count in " << dialog_id << " from " << message_count << " to " << result_size; message_count = result_size; - if (filter_type == SearchMessagesFilter::UnreadMention) { + if (filter_type == MessageSearchFilter::UnreadMention) { d->unread_mention_count = message_count; update_dialog_mention_notification_count(d); send_update_chat_unread_mention_count(d); @@ -19137,7 +19137,7 @@ MessagesManager::FoundMessages MessagesManager::offline_search_messages( MessagesDbFtsQuery fts_query; fts_query.query = query; fts_query.dialog_id = dialog_id; - fts_query.index_mask = search_messages_filter_index_mask(get_search_messages_filter(filter)); + fts_query.index_mask = message_search_filter_index_mask(get_message_search_filter(filter)); if (!offset.empty()) { auto r_from_search_id = to_integer_safe(offset); if (r_from_search_id.is_error()) { @@ -19197,7 +19197,7 @@ void MessagesManager::on_messages_db_fts_result(Result resu } void MessagesManager::on_messages_db_calls_result(Result result, int64 random_id, - MessageId first_db_message_id, SearchMessagesFilter filter, + MessageId first_db_message_id, MessageSearchFilter filter, Promise<> &&promise) { CHECK(!first_db_message_id.is_scheduled()); if (G()->close_flag()) { @@ -19270,15 +19270,15 @@ std::pair> MessagesManager::search_messages( return {}; } - auto filter_type = get_search_messages_filter(filter); - if (filter_type == SearchMessagesFilter::Call || filter_type == SearchMessagesFilter::MissedCall || - filter_type == SearchMessagesFilter::Mention || filter_type == SearchMessagesFilter::UnreadMention || - filter_type == SearchMessagesFilter::FailedToSend) { + auto filter_type = get_message_search_filter(filter); + if (filter_type == MessageSearchFilter::Call || filter_type == MessageSearchFilter::MissedCall || + filter_type == MessageSearchFilter::Mention || filter_type == MessageSearchFilter::UnreadMention || + filter_type == MessageSearchFilter::FailedToSend) { promise.set_error(Status::Error(400, "The filter is not supported")); return {}; } - if (query.empty() && filter_type == SearchMessagesFilter::Empty) { + if (query.empty() && filter_type == MessageSearchFilter::Empty) { promise.set_value(Unit()); return {}; } @@ -19477,21 +19477,21 @@ int32 MessagesManager::get_dialog_message_count(DialogId dialog_id, return -1; } - auto filter_type = get_search_messages_filter(filter); - if (filter_type == SearchMessagesFilter::Empty) { + auto filter_type = get_message_search_filter(filter); + if (filter_type == MessageSearchFilter::Empty) { promise.set_error(Status::Error(6, "SearchMessagesFilterEmpty is not supported")); return -1; } auto dialog_type = dialog_id.get_type(); - int32 message_count = d->message_count_by_index[search_messages_filter_index(filter_type)]; + int32 message_count = d->message_count_by_index[message_search_filter_index(filter_type)]; if (message_count == -1) { - if (filter_type == SearchMessagesFilter::UnreadMention) { + if (filter_type == MessageSearchFilter::UnreadMention) { message_count = d->unread_mention_count; } } if (message_count != -1 || return_local || dialog_type == DialogType::SecretChat || - filter_type == SearchMessagesFilter::FailedToSend) { + filter_type == MessageSearchFilter::FailedToSend) { promise.set_value(Unit()); return message_count; } @@ -24385,7 +24385,7 @@ Result> MessagesManager::do_get_message_notifications_from_d // ignore first_db_message_id, notifications can be nonconsecutive MessagesDbMessagesQuery db_query; db_query.dialog_id = d->dialog_id; - db_query.index_mask = search_messages_filter_index_mask(SearchMessagesFilter::UnreadMention); + db_query.index_mask = message_search_filter_index_mask(MessageSearchFilter::UnreadMention); db_query.from_message_id = from_message_id; db_query.offset = 0; db_query.limit = limit; @@ -24504,7 +24504,7 @@ void MessagesManager::do_get_message_notifications_from_database(Dialog *d, bool // ignore first_db_message_id, notifications can be nonconsecutive MessagesDbMessagesQuery db_query; db_query.dialog_id = dialog_id; - db_query.index_mask = search_messages_filter_index_mask(SearchMessagesFilter::UnreadMention); + db_query.index_mask = message_search_filter_index_mask(MessageSearchFilter::UnreadMention); db_query.from_message_id = from_message_id; db_query.offset = 0; db_query.limit = limit; @@ -27333,90 +27333,90 @@ void MessagesManager::clear_active_dialog_actions(DialogId dialog_id) { } } -tl_object_ptr MessagesManager::get_input_messages_filter(SearchMessagesFilter filter) { +tl_object_ptr MessagesManager::get_input_messages_filter(MessageSearchFilter filter) { switch (filter) { - case SearchMessagesFilter::Empty: + case MessageSearchFilter::Empty: return make_tl_object(); - case SearchMessagesFilter::Animation: + case MessageSearchFilter::Animation: return make_tl_object(); - case SearchMessagesFilter::Audio: + case MessageSearchFilter::Audio: return make_tl_object(); - case SearchMessagesFilter::Document: + case MessageSearchFilter::Document: return make_tl_object(); - case SearchMessagesFilter::Photo: + case MessageSearchFilter::Photo: return make_tl_object(); - case SearchMessagesFilter::Video: + case MessageSearchFilter::Video: return make_tl_object(); - case SearchMessagesFilter::VoiceNote: + case MessageSearchFilter::VoiceNote: return make_tl_object(); - case SearchMessagesFilter::PhotoAndVideo: + case MessageSearchFilter::PhotoAndVideo: return make_tl_object(); - case SearchMessagesFilter::Url: + case MessageSearchFilter::Url: return make_tl_object(); - case SearchMessagesFilter::ChatPhoto: + case MessageSearchFilter::ChatPhoto: return make_tl_object(); - case SearchMessagesFilter::Call: + case MessageSearchFilter::Call: return make_tl_object(0, false /*ignored*/); - case SearchMessagesFilter::MissedCall: + case MessageSearchFilter::MissedCall: return make_tl_object( telegram_api::inputMessagesFilterPhoneCalls::MISSED_MASK, false /*ignored*/); - case SearchMessagesFilter::VideoNote: + case MessageSearchFilter::VideoNote: return make_tl_object(); - case SearchMessagesFilter::VoiceAndVideoNote: + case MessageSearchFilter::VoiceAndVideoNote: return make_tl_object(); - case SearchMessagesFilter::Mention: + case MessageSearchFilter::Mention: return make_tl_object(); - case SearchMessagesFilter::UnreadMention: - case SearchMessagesFilter::FailedToSend: + case MessageSearchFilter::UnreadMention: + case MessageSearchFilter::FailedToSend: default: UNREACHABLE(); return nullptr; } } -SearchMessagesFilter MessagesManager::get_search_messages_filter( +MessageSearchFilter MessagesManager::get_message_search_filter( const tl_object_ptr &filter) { if (filter == nullptr) { - return SearchMessagesFilter::Empty; + return MessageSearchFilter::Empty; } switch (filter->get_id()) { case td_api::searchMessagesFilterEmpty::ID: - return SearchMessagesFilter::Empty; + return MessageSearchFilter::Empty; case td_api::searchMessagesFilterAnimation::ID: - return SearchMessagesFilter::Animation; + return MessageSearchFilter::Animation; case td_api::searchMessagesFilterAudio::ID: - return SearchMessagesFilter::Audio; + return MessageSearchFilter::Audio; case td_api::searchMessagesFilterDocument::ID: - return SearchMessagesFilter::Document; + return MessageSearchFilter::Document; case td_api::searchMessagesFilterPhoto::ID: - return SearchMessagesFilter::Photo; + return MessageSearchFilter::Photo; case td_api::searchMessagesFilterVideo::ID: - return SearchMessagesFilter::Video; + return MessageSearchFilter::Video; case td_api::searchMessagesFilterVoiceNote::ID: - return SearchMessagesFilter::VoiceNote; + return MessageSearchFilter::VoiceNote; case td_api::searchMessagesFilterPhotoAndVideo::ID: - return SearchMessagesFilter::PhotoAndVideo; + return MessageSearchFilter::PhotoAndVideo; case td_api::searchMessagesFilterUrl::ID: - return SearchMessagesFilter::Url; + return MessageSearchFilter::Url; case td_api::searchMessagesFilterChatPhoto::ID: - return SearchMessagesFilter::ChatPhoto; + return MessageSearchFilter::ChatPhoto; case td_api::searchMessagesFilterCall::ID: - return SearchMessagesFilter::Call; + return MessageSearchFilter::Call; case td_api::searchMessagesFilterMissedCall::ID: - return SearchMessagesFilter::MissedCall; + return MessageSearchFilter::MissedCall; case td_api::searchMessagesFilterVideoNote::ID: - return SearchMessagesFilter::VideoNote; + return MessageSearchFilter::VideoNote; case td_api::searchMessagesFilterVoiceAndVideoNote::ID: - return SearchMessagesFilter::VoiceAndVideoNote; + return MessageSearchFilter::VoiceAndVideoNote; case td_api::searchMessagesFilterMention::ID: - return SearchMessagesFilter::Mention; + return MessageSearchFilter::Mention; case td_api::searchMessagesFilterUnreadMention::ID: - return SearchMessagesFilter::UnreadMention; + return MessageSearchFilter::UnreadMention; case td_api::searchMessagesFilterFailedToSend::ID: - return SearchMessagesFilter::FailedToSend; + return MessageSearchFilter::FailedToSend; default: UNREACHABLE(); - return SearchMessagesFilter::Empty; + return MessageSearchFilter::Empty; } } @@ -28989,7 +28989,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq message->have_next = false; } if (!message->from_database) { - const int32 INDEX_MASK_MASK = ~search_messages_filter_index_mask(SearchMessagesFilter::UnreadMention); + const int32 INDEX_MASK_MASK = ~message_search_filter_index_mask(MessageSearchFilter::UnreadMention); auto old_index_mask = get_message_index_mask(dialog_id, m) & INDEX_MASK_MASK; bool was_deleted = delete_active_live_location(dialog_id, m); auto old_file_ids = get_message_content_file_ids(m->content.get(), td_); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index c7500bc98..92a4a2c20 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -230,12 +230,12 @@ class MessagesManager : public Actor { void on_get_dialog_messages_search_result(DialogId dialog_id, const string &query, UserId sender_user_id, MessageId from_message_id, int32 offset, int32 limit, - SearchMessagesFilter filter, int64 random_id, int32 total_count, + MessageSearchFilter filter, int64 random_id, int32 total_count, vector> &&messages); void on_failed_dialog_messages_search(DialogId dialog_id, int64 random_id); void on_get_messages_search_result(const string &query, int32 offset_date, DialogId offset_dialog_id, - MessageId offset_message_id, int32 limit, SearchMessagesFilter filter, + MessageId offset_message_id, int32 limit, MessageSearchFilter filter, int64 random_id, int32 total_count, vector> &&messages); void on_failed_messages_search(int64 random_id); @@ -734,9 +734,9 @@ class MessagesManager : public Actor { void on_resolved_username(const string &username, DialogId dialog_id); void drop_username(const string &username); - static tl_object_ptr get_input_messages_filter(SearchMessagesFilter filter); + static tl_object_ptr get_input_messages_filter(MessageSearchFilter filter); - static SearchMessagesFilter get_search_messages_filter(const tl_object_ptr &filter); + static MessageSearchFilter get_message_search_filter(const tl_object_ptr &filter); tl_object_ptr get_input_notify_peer(DialogId dialogId) const; @@ -1091,9 +1091,9 @@ class MessagesManager : public Actor { // is known and last_message_id is known, then last_database_message_id <= // last_message_id - std::array first_database_message_id_by_index; + std::array first_database_message_id_by_index; // use struct Count? - std::array message_count_by_index{{0}}; + std::array message_count_by_index{{0}}; int32 server_unread_count = 0; int32 local_unread_count = 0; @@ -2492,18 +2492,17 @@ class MessagesManager : public Actor { void on_get_message_link_dialog(MessageLinkInfo &&info, Promise &&promise); - static MessageId get_first_database_message_id_by_index(const Dialog *d, SearchMessagesFilter filter); + static MessageId get_first_database_message_id_by_index(const Dialog *d, MessageSearchFilter filter); void on_search_dialog_messages_db_result(int64 random_id, DialogId dialog_id, MessageId from_message_id, - MessageId first_db_message_id, SearchMessagesFilter filter_type, - int32 offset, int32 limit, Result> r_messages, - Promise<> promise); + MessageId first_db_message_id, MessageSearchFilter filter_type, int32 offset, + int32 limit, Result> r_messages, Promise<> promise); void on_messages_db_fts_result(Result result, string offset, int32 limit, int64 random_id, Promise<> &&promise); void on_messages_db_calls_result(Result result, int64 random_id, MessageId first_db_message_id, - SearchMessagesFilter filter, Promise &&promise); + MessageSearchFilter filter, Promise &&promise); void on_load_active_live_location_full_message_ids_from_database(string value); From 46f42d80b65d33293e1eaf068075bbfcc716f498 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 22 Aug 2020 10:27:13 +0300 Subject: [PATCH 24/39] Move MessageSearchFilter to separate files. GitOrigin-RevId: 07b7df009b4e74a145b5ebc1966190630545baef --- CMakeLists.txt | 2 + td/telegram/AccessRights.h | 2 + td/telegram/MessageContent.cpp | 2 +- td/telegram/MessageSearchFilter.cpp | 100 ++++++++++++++++++++++++++ td/telegram/MessageSearchFilter.h | 61 ++++++++++++++++ td/telegram/MessagesDb.cpp | 3 +- td/telegram/MessagesDb.h | 43 ----------- td/telegram/MessagesManager.cpp | 107 +++------------------------- td/telegram/MessagesManager.h | 13 ++-- 9 files changed, 183 insertions(+), 150 deletions(-) create mode 100644 td/telegram/MessageSearchFilter.cpp create mode 100644 td/telegram/MessageSearchFilter.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 735bfd7f4..f30a6c95b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -444,6 +444,7 @@ set(TDLIB_SOURCE td/telegram/MessageEntity.cpp td/telegram/MessageId.cpp td/telegram/MessagesDb.cpp + td/telegram/MessageSearchFilter.cpp td/telegram/MessagesManager.cpp td/telegram/misc.cpp td/telegram/net/AuthDataShared.cpp @@ -615,6 +616,7 @@ set(TDLIB_SOURCE td/telegram/MessageEntity.h td/telegram/MessageId.h td/telegram/MessagesDb.h + td/telegram/MessageSearchFilter.h td/telegram/MessagesManager.h td/telegram/misc.h td/telegram/net/AuthDataShared.h diff --git a/td/telegram/AccessRights.h b/td/telegram/AccessRights.h index bc7b49371..029cea6d0 100644 --- a/td/telegram/AccessRights.h +++ b/td/telegram/AccessRights.h @@ -6,6 +6,8 @@ // #pragma once +#include "td/utils/common.h" + namespace td { enum class AccessRights : int32 { Read, Edit, Write }; diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 1146a9ee3..f08d29530 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -33,7 +33,7 @@ #include "td/telegram/MessageEntity.h" #include "td/telegram/MessageEntity.hpp" #include "td/telegram/MessageId.h" -#include "td/telegram/MessagesDb.h" +#include "td/telegram/MessageSearchFilter.h" #include "td/telegram/misc.h" #include "td/telegram/net/DcId.h" #include "td/telegram/Payments.h" diff --git a/td/telegram/MessageSearchFilter.cpp b/td/telegram/MessageSearchFilter.cpp new file mode 100644 index 000000000..60fee6e18 --- /dev/null +++ b/td/telegram/MessageSearchFilter.cpp @@ -0,0 +1,100 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/telegram/MessageSearchFilter.h" + +#include "td/utils/common.h" + +namespace td { + +tl_object_ptr get_input_messages_filter(MessageSearchFilter filter) { + switch (filter) { + case MessageSearchFilter::Empty: + return make_tl_object(); + case MessageSearchFilter::Animation: + return make_tl_object(); + case MessageSearchFilter::Audio: + return make_tl_object(); + case MessageSearchFilter::Document: + return make_tl_object(); + case MessageSearchFilter::Photo: + return make_tl_object(); + case MessageSearchFilter::Video: + return make_tl_object(); + case MessageSearchFilter::VoiceNote: + return make_tl_object(); + case MessageSearchFilter::PhotoAndVideo: + return make_tl_object(); + case MessageSearchFilter::Url: + return make_tl_object(); + case MessageSearchFilter::ChatPhoto: + return make_tl_object(); + case MessageSearchFilter::Call: + return make_tl_object(0, false /*ignored*/); + case MessageSearchFilter::MissedCall: + return make_tl_object( + telegram_api::inputMessagesFilterPhoneCalls::MISSED_MASK, false /*ignored*/); + case MessageSearchFilter::VideoNote: + return make_tl_object(); + case MessageSearchFilter::VoiceAndVideoNote: + return make_tl_object(); + case MessageSearchFilter::Mention: + return make_tl_object(); + case MessageSearchFilter::UnreadMention: + case MessageSearchFilter::FailedToSend: + default: + UNREACHABLE(); + return nullptr; + } +} + +MessageSearchFilter get_message_search_filter( + const tl_object_ptr &filter) { + if (filter == nullptr) { + return MessageSearchFilter::Empty; + } + switch (filter->get_id()) { + case td_api::searchMessagesFilterEmpty::ID: + return MessageSearchFilter::Empty; + case td_api::searchMessagesFilterAnimation::ID: + return MessageSearchFilter::Animation; + case td_api::searchMessagesFilterAudio::ID: + return MessageSearchFilter::Audio; + case td_api::searchMessagesFilterDocument::ID: + return MessageSearchFilter::Document; + case td_api::searchMessagesFilterPhoto::ID: + return MessageSearchFilter::Photo; + case td_api::searchMessagesFilterVideo::ID: + return MessageSearchFilter::Video; + case td_api::searchMessagesFilterVoiceNote::ID: + return MessageSearchFilter::VoiceNote; + case td_api::searchMessagesFilterPhotoAndVideo::ID: + return MessageSearchFilter::PhotoAndVideo; + case td_api::searchMessagesFilterUrl::ID: + return MessageSearchFilter::Url; + case td_api::searchMessagesFilterChatPhoto::ID: + return MessageSearchFilter::ChatPhoto; + case td_api::searchMessagesFilterCall::ID: + return MessageSearchFilter::Call; + case td_api::searchMessagesFilterMissedCall::ID: + return MessageSearchFilter::MissedCall; + case td_api::searchMessagesFilterVideoNote::ID: + return MessageSearchFilter::VideoNote; + case td_api::searchMessagesFilterVoiceAndVideoNote::ID: + return MessageSearchFilter::VoiceAndVideoNote; + case td_api::searchMessagesFilterMention::ID: + return MessageSearchFilter::Mention; + case td_api::searchMessagesFilterUnreadMention::ID: + return MessageSearchFilter::UnreadMention; + case td_api::searchMessagesFilterFailedToSend::ID: + return MessageSearchFilter::FailedToSend; + default: + UNREACHABLE(); + return MessageSearchFilter::Empty; + } +} + +} // namespace td \ No newline at end of file diff --git a/td/telegram/MessageSearchFilter.h b/td/telegram/MessageSearchFilter.h new file mode 100644 index 000000000..f1e0545de --- /dev/null +++ b/td/telegram/MessageSearchFilter.h @@ -0,0 +1,61 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/td_api.h" +#include "td/telegram/telegram_api.h" + +namespace td { + +// append only before Size +enum class MessageSearchFilter : int32 { + Empty, + Animation, + Audio, + Document, + Photo, + Video, + VoiceNote, + PhotoAndVideo, + Url, + ChatPhoto, + Call, + MissedCall, + VideoNote, + VoiceAndVideoNote, + Mention, + UnreadMention, + FailedToSend, + Size +}; + +inline constexpr size_t message_search_filter_count() { + return static_cast(MessageSearchFilter::Size) - 1; +} + +inline int32 message_search_filter_index(MessageSearchFilter filter) { + CHECK(filter != MessageSearchFilter::Empty); + return static_cast(filter) - 1; +} + +inline int32 message_search_filter_index_mask(MessageSearchFilter filter) { + if (filter == MessageSearchFilter::Empty) { + return 0; + } + return 1 << message_search_filter_index(filter); +} + +inline int32 call_message_search_filter_index(MessageSearchFilter filter) { + CHECK(filter == MessageSearchFilter::Call || filter == MessageSearchFilter::MissedCall); + return static_cast(filter) - static_cast(MessageSearchFilter::Call); +} + +tl_object_ptr get_input_messages_filter(MessageSearchFilter filter); + +MessageSearchFilter get_message_search_filter(const tl_object_ptr &filter); + +} // namespace td \ No newline at end of file diff --git a/td/telegram/MessagesDb.cpp b/td/telegram/MessagesDb.cpp index f93816ea7..262156a63 100644 --- a/td/telegram/MessagesDb.cpp +++ b/td/telegram/MessagesDb.cpp @@ -7,6 +7,7 @@ #include "td/telegram/MessagesDb.h" #include "td/telegram/logevent/LogEvent.h" +#include "td/telegram/MessageSearchFilter.h" #include "td/telegram/Version.h" #include "td/db/SqliteConnectionSafe.h" @@ -755,7 +756,7 @@ class MessagesDbImpl : public MessagesDbSyncInterface { } else if (index_i + 1 == static_cast(MessageSearchFilter::MissedCall)) { pos = 1; } else { - return Status::Error(PSLICE() << "Index_mask is not Call or MissedCall " << query.index_mask); + return Status::Error(PSLICE() << "Index mask is not Call or MissedCall " << query.index_mask); } auto &stmt = get_calls_stmts_[pos]; diff --git a/td/telegram/MessagesDb.h b/td/telegram/MessagesDb.h index 96ce5ea94..c8683cafd 100644 --- a/td/telegram/MessagesDb.h +++ b/td/telegram/MessagesDb.h @@ -26,28 +26,6 @@ namespace td { class SqliteConnectionSafe; class SqliteDb; -// append only before Size -enum class MessageSearchFilter : int32 { - Empty, - Animation, - Audio, - Document, - Photo, - Video, - VoiceNote, - PhotoAndVideo, - Url, - ChatPhoto, - Call, - MissedCall, - VideoNote, - VoiceAndVideoNote, - Mention, - UnreadMention, - FailedToSend, - Size -}; - struct MessagesDbMessagesQuery { DialogId dialog_id; int32 index_mask{0}; @@ -178,25 +156,4 @@ std::shared_ptr create_messages_db_sync( std::shared_ptr create_messages_db_async(std::shared_ptr sync_db, int32 scheduler_id); -inline constexpr size_t message_search_filter_count() { - return static_cast(MessageSearchFilter::Size) - 1; -} - -inline int32 message_search_filter_index(MessageSearchFilter filter) { - CHECK(filter != MessageSearchFilter::Empty); - return static_cast(filter) - 1; -} - -inline int32 message_search_filter_index_mask(MessageSearchFilter filter) { - if (filter == MessageSearchFilter::Empty) { - return 0; - } - return 1 << message_search_filter_index(filter); -} - -inline int32 search_calls_filter_index(MessageSearchFilter filter) { - CHECK(filter == MessageSearchFilter::Call || filter == MessageSearchFilter::MissedCall); - return static_cast(filter) - static_cast(MessageSearchFilter::Call); -} - } // namespace td diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index e77f7616d..35181827d 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -1611,9 +1611,9 @@ class SearchMessagesQuery : public Td::ResultHandler { } send_query(G()->net_query_creator().create(telegram_api::messages_search( - flags, std::move(input_peer), query, std::move(sender_input_user), - MessagesManager::get_input_messages_filter(filter), 0, std::numeric_limits::max(), - from_message_id.get_server_message_id().get(), offset, limit, std::numeric_limits::max(), 0, 0))); + flags, std::move(input_peer), query, std::move(sender_input_user), get_input_messages_filter(filter), 0, + std::numeric_limits::max(), from_message_id.get_server_message_id().get(), offset, limit, + std::numeric_limits::max(), 0, 0))); } } @@ -1674,8 +1674,8 @@ class SearchMessagesGlobalQuery : public Td::ResultHandler { flags |= telegram_api::messages_searchGlobal::FOLDER_ID_MASK; } send_query(G()->net_query_creator().create(telegram_api::messages_searchGlobal( - flags, folder_id.get(), query, MessagesManager::get_input_messages_filter(filter), offset_date_, - std::move(input_peer), offset_message_id.get_server_message_id().get(), limit))); + flags, folder_id.get(), query, get_input_messages_filter(filter), offset_date_, std::move(input_peer), + offset_message_id.get_server_message_id().get(), limit))); } void on_result(uint64 id, BufferSlice packet) override { @@ -8633,7 +8633,7 @@ void MessagesManager::on_get_dialog_messages_search_result(DialogId dialog_id, c if (G()->parameters().use_message_db) { bool update_state = false; - auto &old_message_count = calls_db_state_.message_count_by_index[search_calls_filter_index(filter)]; + auto &old_message_count = calls_db_state_.message_count_by_index[call_message_search_filter_index(filter)]; if (old_message_count != total_count) { LOG(INFO) << "Update calls database message count to " << total_count; old_message_count = total_count; @@ -8641,7 +8641,7 @@ void MessagesManager::on_get_dialog_messages_search_result(DialogId dialog_id, c } auto &old_first_db_message_id = - calls_db_state_.first_calls_database_message_id_by_index[search_calls_filter_index(filter)]; + calls_db_state_.first_calls_database_message_id_by_index[call_message_search_filter_index(filter)]; bool from_the_end = !from_message_id.is_valid() || from_message_id >= MessageId::max(); LOG(INFO) << "Have from_the_end = " << from_the_end << ", old_first_db_message_id = " << old_first_db_message_id << ", first_added_message_id = " << first_added_message_id << ", from_message_id = " << from_message_id; @@ -18603,8 +18603,8 @@ std::pair> MessagesManager::search_call_messages(Me if (use_db && G()->parameters().use_message_db) { // try to use database MessageId first_db_message_id = - calls_db_state_.first_calls_database_message_id_by_index[search_calls_filter_index(filter_type)]; - int32 message_count = calls_db_state_.message_count_by_index[search_calls_filter_index(filter_type)]; + calls_db_state_.first_calls_database_message_id_by_index[call_message_search_filter_index(filter_type)]; + int32 message_count = calls_db_state_.message_count_by_index[call_message_search_filter_index(filter_type)]; auto fixed_from_message_id = from_message_id; if (fixed_from_message_id == MessageId()) { fixed_from_message_id = MessageId::max(); @@ -19222,7 +19222,7 @@ void MessagesManager::on_messages_db_calls_result(Result res.push_back(FullMessageId(message.dialog_id, m->message_id)); } } - it->second.first = calls_db_state_.message_count_by_index[search_calls_filter_index(filter)]; + it->second.first = calls_db_state_.message_count_by_index[call_message_search_filter_index(filter)]; if (res.empty() && first_db_message_id != MessageId::min()) { LOG(INFO) << "No messages in database found"; @@ -27333,93 +27333,6 @@ void MessagesManager::clear_active_dialog_actions(DialogId dialog_id) { } } -tl_object_ptr MessagesManager::get_input_messages_filter(MessageSearchFilter filter) { - switch (filter) { - case MessageSearchFilter::Empty: - return make_tl_object(); - case MessageSearchFilter::Animation: - return make_tl_object(); - case MessageSearchFilter::Audio: - return make_tl_object(); - case MessageSearchFilter::Document: - return make_tl_object(); - case MessageSearchFilter::Photo: - return make_tl_object(); - case MessageSearchFilter::Video: - return make_tl_object(); - case MessageSearchFilter::VoiceNote: - return make_tl_object(); - case MessageSearchFilter::PhotoAndVideo: - return make_tl_object(); - case MessageSearchFilter::Url: - return make_tl_object(); - case MessageSearchFilter::ChatPhoto: - return make_tl_object(); - case MessageSearchFilter::Call: - return make_tl_object(0, false /*ignored*/); - case MessageSearchFilter::MissedCall: - return make_tl_object( - telegram_api::inputMessagesFilterPhoneCalls::MISSED_MASK, false /*ignored*/); - case MessageSearchFilter::VideoNote: - return make_tl_object(); - case MessageSearchFilter::VoiceAndVideoNote: - return make_tl_object(); - case MessageSearchFilter::Mention: - return make_tl_object(); - case MessageSearchFilter::UnreadMention: - case MessageSearchFilter::FailedToSend: - default: - UNREACHABLE(); - return nullptr; - } -} - -MessageSearchFilter MessagesManager::get_message_search_filter( - const tl_object_ptr &filter) { - if (filter == nullptr) { - return MessageSearchFilter::Empty; - } - switch (filter->get_id()) { - case td_api::searchMessagesFilterEmpty::ID: - return MessageSearchFilter::Empty; - case td_api::searchMessagesFilterAnimation::ID: - return MessageSearchFilter::Animation; - case td_api::searchMessagesFilterAudio::ID: - return MessageSearchFilter::Audio; - case td_api::searchMessagesFilterDocument::ID: - return MessageSearchFilter::Document; - case td_api::searchMessagesFilterPhoto::ID: - return MessageSearchFilter::Photo; - case td_api::searchMessagesFilterVideo::ID: - return MessageSearchFilter::Video; - case td_api::searchMessagesFilterVoiceNote::ID: - return MessageSearchFilter::VoiceNote; - case td_api::searchMessagesFilterPhotoAndVideo::ID: - return MessageSearchFilter::PhotoAndVideo; - case td_api::searchMessagesFilterUrl::ID: - return MessageSearchFilter::Url; - case td_api::searchMessagesFilterChatPhoto::ID: - return MessageSearchFilter::ChatPhoto; - case td_api::searchMessagesFilterCall::ID: - return MessageSearchFilter::Call; - case td_api::searchMessagesFilterMissedCall::ID: - return MessageSearchFilter::MissedCall; - case td_api::searchMessagesFilterVideoNote::ID: - return MessageSearchFilter::VideoNote; - case td_api::searchMessagesFilterVoiceAndVideoNote::ID: - return MessageSearchFilter::VoiceAndVideoNote; - case td_api::searchMessagesFilterMention::ID: - return MessageSearchFilter::Mention; - case td_api::searchMessagesFilterUnreadMention::ID: - return MessageSearchFilter::UnreadMention; - case td_api::searchMessagesFilterFailedToSend::ID: - return MessageSearchFilter::FailedToSend; - default: - UNREACHABLE(); - return MessageSearchFilter::Empty; - } -} - vector MessagesManager::get_dialog_lists_to_add_dialog(DialogId dialog_id) { vector result; const Dialog *d = get_dialog_force(dialog_id); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 92a4a2c20..af3ee6530 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -6,10 +6,6 @@ // #pragma once -#include "td/telegram/secret_api.h" -#include "td/telegram/td_api.h" -#include "td/telegram/telegram_api.h" - #include "td/telegram/AccessRights.h" #include "td/telegram/ChannelId.h" #include "td/telegram/Dependencies.h" @@ -32,6 +28,7 @@ #include "td/telegram/MessageCopyOptions.h" #include "td/telegram/MessageId.h" #include "td/telegram/MessagesDb.h" +#include "td/telegram/MessageSearchFilter.h" #include "td/telegram/net/NetQuery.h" #include "td/telegram/Notification.h" #include "td/telegram/NotificationGroupId.h" @@ -47,6 +44,10 @@ #include "td/telegram/ServerMessageId.h" #include "td/telegram/UserId.h" +#include "td/telegram/secret_api.h" +#include "td/telegram/td_api.h" +#include "td/telegram/telegram_api.h" + #include "td/actor/actor.h" #include "td/actor/MultiPromise.h" #include "td/actor/PromiseFuture.h" @@ -734,10 +735,6 @@ class MessagesManager : public Actor { void on_resolved_username(const string &username, DialogId dialog_id); void drop_username(const string &username); - static tl_object_ptr get_input_messages_filter(MessageSearchFilter filter); - - static MessageSearchFilter get_message_search_filter(const tl_object_ptr &filter); - tl_object_ptr get_input_notify_peer(DialogId dialogId) const; void on_update_dialog_notify_settings(DialogId dialog_id, From dd722844bd8a6b42acf4bbd59b984aaf4142c7c2 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 22 Aug 2020 10:48:36 +0300 Subject: [PATCH 25/39] Early conversion to MessageSearchFilter. GitOrigin-RevId: c74a75329a873842ee30ce45515a05024da26153 --- td/telegram/MessageSearchFilter.cpp | 47 ++++++++++++- td/telegram/MessageSearchFilter.h | 7 +- td/telegram/MessagesManager.cpp | 101 +++++++++++++--------------- td/telegram/MessagesManager.h | 17 ++--- td/telegram/Td.cpp | 17 ++--- 5 files changed, 114 insertions(+), 75 deletions(-) diff --git a/td/telegram/MessageSearchFilter.cpp b/td/telegram/MessageSearchFilter.cpp index 60fee6e18..baec0b1f2 100644 --- a/td/telegram/MessageSearchFilter.cpp +++ b/td/telegram/MessageSearchFilter.cpp @@ -51,8 +51,7 @@ tl_object_ptr get_input_messages_filter(MessageSea } } -MessageSearchFilter get_message_search_filter( - const tl_object_ptr &filter) { +MessageSearchFilter get_message_search_filter(const tl_object_ptr &filter) { if (filter == nullptr) { return MessageSearchFilter::Empty; } @@ -97,4 +96,46 @@ MessageSearchFilter get_message_search_filter( } } -} // namespace td \ No newline at end of file +StringBuilder &operator<<(StringBuilder &string_builder, MessageSearchFilter filter) { + switch (filter) { + case MessageSearchFilter::Empty: + return string_builder << "Empty"; + case MessageSearchFilter::Animation: + return string_builder << "Animation"; + case MessageSearchFilter::Audio: + return string_builder << "Audio"; + case MessageSearchFilter::Document: + return string_builder << "Document"; + case MessageSearchFilter::Photo: + return string_builder << "Photo"; + case MessageSearchFilter::Video: + return string_builder << "Video"; + case MessageSearchFilter::VoiceNote: + return string_builder << "VoiceNote"; + case MessageSearchFilter::PhotoAndVideo: + return string_builder << "PhotoAndVideo"; + case MessageSearchFilter::Url: + return string_builder << "Url"; + case MessageSearchFilter::ChatPhoto: + return string_builder << "ChatPhoto"; + case MessageSearchFilter::Call: + return string_builder << "Call"; + case MessageSearchFilter::MissedCall: + return string_builder << "MissedCall"; + case MessageSearchFilter::VideoNote: + return string_builder << "VideoNote"; + case MessageSearchFilter::VoiceAndVideoNote: + return string_builder << "VoiceAndVideoNote"; + case MessageSearchFilter::Mention: + return string_builder << "Mention"; + case MessageSearchFilter::UnreadMention: + return string_builder << "UnreadMention"; + case MessageSearchFilter::FailedToSend: + return string_builder << "FailedToSend"; + default: + UNREACHABLE(); + return string_builder; + } +} + +} // namespace td diff --git a/td/telegram/MessageSearchFilter.h b/td/telegram/MessageSearchFilter.h index f1e0545de..b5f25bb26 100644 --- a/td/telegram/MessageSearchFilter.h +++ b/td/telegram/MessageSearchFilter.h @@ -9,6 +9,9 @@ #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" +#include "td/utils/common.h" +#include "td/utils/StringBuilder.h" + namespace td { // append only before Size @@ -58,4 +61,6 @@ tl_object_ptr get_input_messages_filter(MessageSea MessageSearchFilter get_message_search_filter(const tl_object_ptr &filter); -} // namespace td \ No newline at end of file +StringBuilder &operator<<(StringBuilder &string_builder, MessageSearchFilter filter); + +} // namespace td diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 35181827d..c6959095f 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -18414,8 +18414,7 @@ void MessagesManager::on_read_history_finished(DialogId dialog_id, uint64 genera std::pair> MessagesManager::search_dialog_messages( DialogId dialog_id, const string &query, UserId sender_user_id, MessageId from_message_id, int32 offset, - int32 limit, const tl_object_ptr &filter, int64 &random_id, bool use_db, - Promise &&promise) { + int32 limit, MessageSearchFilter filter, int64 &random_id, bool use_db, Promise &&promise) { if (random_id != 0) { // request has already been sent before auto it = found_dialog_messages_.find(random_id); @@ -18428,8 +18427,8 @@ std::pair> MessagesManager::search_dialog_messages( random_id = 0; } LOG(INFO) << "Search messages with query \"" << query << "\" in " << dialog_id << " sent by " << sender_user_id - << " filtered by " << to_string(filter) << " from " << from_message_id << " with offset " << offset - << " and limit " << limit; + << " filtered by " << filter << " from " << from_message_id << " with offset " << offset << " and limit " + << limit; std::pair> result; if (limit <= 0) { @@ -18464,8 +18463,7 @@ std::pair> MessagesManager::search_dialog_messages( return result; } - auto filter_type = get_message_search_filter(filter); - if (filter_type == MessageSearchFilter::FailedToSend && sender_user_id.is_valid()) { + if (filter == MessageSearchFilter::FailedToSend && sender_user_id.is_valid()) { if (sender_user_id != td_->contacts_manager_->get_my_id()) { promise.set_value(Unit()); return result; @@ -18484,7 +18482,7 @@ std::pair> MessagesManager::search_dialog_messages( } while (random_id == 0 || found_dialog_messages_.find(random_id) != found_dialog_messages_.end()); found_dialog_messages_[random_id]; // reserve place for result - if (filter_type == MessageSearchFilter::UnreadMention) { + if (filter == MessageSearchFilter::UnreadMention) { if (!query.empty()) { promise.set_error(Status::Error(6, "Non-empty query is unsupported with the specified filter")); return result; @@ -18496,10 +18494,10 @@ std::pair> MessagesManager::search_dialog_messages( } // Trying to use database - if (use_db && query.empty() && G()->parameters().use_message_db && filter_type != MessageSearchFilter::Empty && + if (use_db && query.empty() && G()->parameters().use_message_db && filter != MessageSearchFilter::Empty && input_user == nullptr) { // TODO support filter by users in the database - MessageId first_db_message_id = get_first_database_message_id_by_index(d, filter_type); - int32 message_count = d->message_count_by_index[message_search_filter_index(filter_type)]; + MessageId first_db_message_id = get_first_database_message_id_by_index(d, filter); + int32 message_count = d->message_count_by_index[message_search_filter_index(filter)]; auto fixed_from_message_id = from_message_id; if (fixed_from_message_id == MessageId()) { fixed_from_message_id = MessageId::max(); @@ -18511,15 +18509,15 @@ std::pair> MessagesManager::search_dialog_messages( LOG(INFO) << "Search messages in database in " << dialog_id << " from " << fixed_from_message_id << " and with limit " << limit; auto new_promise = PromiseCreator::lambda( - [random_id, dialog_id, fixed_from_message_id, first_db_message_id, filter_type, offset, limit, + [random_id, dialog_id, fixed_from_message_id, first_db_message_id, filter, offset, limit, promise = std::move(promise)](Result> r_messages) mutable { send_closure(G()->messages_manager(), &MessagesManager::on_search_dialog_messages_db_result, random_id, - dialog_id, fixed_from_message_id, first_db_message_id, filter_type, offset, limit, + dialog_id, fixed_from_message_id, first_db_message_id, filter, offset, limit, std::move(r_messages), std::move(promise)); }); MessagesDbMessagesQuery db_query; db_query.dialog_id = dialog_id; - db_query.index_mask = message_search_filter_index_mask(filter_type); + db_query.index_mask = message_search_filter_index_mask(filter); db_query.from_message_id = fixed_from_message_id; db_query.offset = offset; db_query.limit = limit; @@ -18527,7 +18525,7 @@ std::pair> MessagesManager::search_dialog_messages( return result; } } - if (filter_type == MessageSearchFilter::FailedToSend) { + if (filter == MessageSearchFilter::FailedToSend) { promise.set_value(Unit()); return result; } @@ -18541,11 +18539,11 @@ std::pair> MessagesManager::search_dialog_messages( case DialogType::Chat: case DialogType::Channel: td_->create_handler(std::move(promise)) - ->send(dialog_id, query, sender_user_id, std::move(input_user), from_message_id, offset, limit, filter_type, + ->send(dialog_id, query, sender_user_id, std::move(input_user), from_message_id, offset, limit, filter, random_id); break; case DialogType::SecretChat: - if (filter_type == MessageSearchFilter::UnreadMention) { + if (filter == MessageSearchFilter::UnreadMention) { promise.set_value(Unit()); } else { promise.set_error(Status::Error(500, "Search messages in secret chats is not supported")); @@ -18598,13 +18596,13 @@ std::pair> MessagesManager::search_call_messages(Me } while (random_id == 0 || found_call_messages_.find(random_id) != found_call_messages_.end()); found_call_messages_[random_id]; // reserve place for result - auto filter_type = only_missed ? MessageSearchFilter::MissedCall : MessageSearchFilter::Call; + auto filter = only_missed ? MessageSearchFilter::MissedCall : MessageSearchFilter::Call; if (use_db && G()->parameters().use_message_db) { // try to use database MessageId first_db_message_id = - calls_db_state_.first_calls_database_message_id_by_index[call_message_search_filter_index(filter_type)]; - int32 message_count = calls_db_state_.message_count_by_index[call_message_search_filter_index(filter_type)]; + calls_db_state_.first_calls_database_message_id_by_index[call_message_search_filter_index(filter)]; + int32 message_count = calls_db_state_.message_count_by_index[call_message_search_filter_index(filter)]; auto fixed_from_message_id = from_message_id; if (fixed_from_message_id == MessageId()) { fixed_from_message_id = MessageId::max(); @@ -18616,14 +18614,14 @@ std::pair> MessagesManager::search_call_messages(Me LOG(INFO) << "Search messages in database from " << fixed_from_message_id << " and with limit " << limit; MessagesDbCallsQuery db_query; - db_query.index_mask = message_search_filter_index_mask(filter_type); + db_query.index_mask = message_search_filter_index_mask(filter); db_query.from_unique_message_id = fixed_from_message_id.get_server_message_id().get(); db_query.limit = limit; G()->td_db()->get_messages_db_async()->get_calls( - db_query, PromiseCreator::lambda([random_id, first_db_message_id, filter_type, promise = std::move(promise)]( + db_query, PromiseCreator::lambda([random_id, first_db_message_id, filter, promise = std::move(promise)]( Result calls_result) mutable { send_closure(G()->messages_manager(), &MessagesManager::on_messages_db_calls_result, - std::move(calls_result), random_id, first_db_message_id, filter_type, std::move(promise)); + std::move(calls_result), random_id, first_db_message_id, filter, std::move(promise)); })); return result; } @@ -18631,7 +18629,7 @@ std::pair> MessagesManager::search_call_messages(Me LOG(DEBUG) << "Search call messages on server from " << from_message_id << " and with limit " << limit; td_->create_handler(std::move(promise)) - ->send(DialogId(), "", UserId(), nullptr, from_message_id, 0, limit, filter_type, random_id); + ->send(DialogId(), "", UserId(), nullptr, from_message_id, 0, limit, filter, random_id); return result; } @@ -19020,7 +19018,7 @@ MessageId MessagesManager::get_first_database_message_id_by_index(const Dialog * void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, DialogId dialog_id, MessageId from_message_id, MessageId first_db_message_id, - MessageSearchFilter filter_type, int32 offset, int32 limit, + MessageSearchFilter filter, int32 offset, int32 limit, Result> r_messages, Promise<> promise) { if (G()->close_flag()) { @@ -19029,7 +19027,7 @@ void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, Dialo if (r_messages.is_error()) { LOG(ERROR) << r_messages.error(); if (first_db_message_id != MessageId::min() && dialog_id.get_type() != DialogType::SecretChat && - filter_type != MessageSearchFilter::FailedToSend) { + filter != MessageSearchFilter::FailedToSend) { found_dialog_messages_.erase(random_id); } return promise.set_value(Unit()); @@ -19050,7 +19048,7 @@ void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, Dialo for (auto &message : messages) { auto m = on_get_message_from_database(dialog_id, d, message, false, "on_search_dialog_messages_db_result"); if (m != nullptr && first_db_message_id <= m->message_id) { - if (filter_type == MessageSearchFilter::UnreadMention && !m->contains_unread_mention) { + if (filter == MessageSearchFilter::UnreadMention && !m->contains_unread_mention) { // skip already read by d->last_read_all_mentions_message_id mentions } else { CHECK(!m->message_id.is_scheduled()); @@ -19059,7 +19057,7 @@ void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, Dialo } } - auto &message_count = d->message_count_by_index[message_search_filter_index(filter_type)]; + auto &message_count = d->message_count_by_index[message_search_filter_index(filter)]; int32 result_size = narrow_cast(res.size()); bool from_the_end = from_message_id == MessageId::max() || (offset < 0 && (result_size == 0 || res[0] < from_message_id)); @@ -19068,7 +19066,7 @@ void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, Dialo result_size < limit + offset)) { LOG(INFO) << "Fix found message count in " << dialog_id << " from " << message_count << " to " << result_size; message_count = result_size; - if (filter_type == MessageSearchFilter::UnreadMention) { + if (filter == MessageSearchFilter::UnreadMention) { d->unread_mention_count = message_count; update_dialog_mention_notification_count(d); send_update_chat_unread_mention_count(d); @@ -19100,9 +19098,10 @@ td_api::object_ptr MessagesManager::get_found_messages_ob found_messages.next_offset); } -MessagesManager::FoundMessages MessagesManager::offline_search_messages( - DialogId dialog_id, const string &query, const string &offset, int32 limit, - const tl_object_ptr &filter, int64 &random_id, Promise<> &&promise) { +MessagesManager::FoundMessages MessagesManager::offline_search_messages(DialogId dialog_id, const string &query, + const string &offset, int32 limit, + MessageSearchFilter filter, int64 &random_id, + Promise<> &&promise) { if (!G()->parameters().use_message_db) { promise.set_error(Status::Error(400, "Message database is required to search messages in secret chats")); return {}; @@ -19137,7 +19136,7 @@ MessagesManager::FoundMessages MessagesManager::offline_search_messages( MessagesDbFtsQuery fts_query; fts_query.query = query; fts_query.dialog_id = dialog_id; - fts_query.index_mask = message_search_filter_index_mask(get_message_search_filter(filter)); + fts_query.index_mask = message_search_filter_index_mask(filter); if (!offset.empty()) { auto r_from_search_id = to_integer_safe(offset); if (r_from_search_id.is_error()) { @@ -19234,8 +19233,7 @@ void MessagesManager::on_messages_db_calls_result(Result std::pair> MessagesManager::search_messages( FolderId folder_id, bool ignore_folder_id, const string &query, int32 offset_date, DialogId offset_dialog_id, - MessageId offset_message_id, int32 limit, const tl_object_ptr &filter, - int64 &random_id, Promise &&promise) { + MessageId offset_message_id, int32 limit, MessageSearchFilter filter, int64 &random_id, Promise &&promise) { if (random_id != 0) { // request has already been sent before auto it = found_messages_.find(random_id); @@ -19270,15 +19268,14 @@ std::pair> MessagesManager::search_messages( return {}; } - auto filter_type = get_message_search_filter(filter); - if (filter_type == MessageSearchFilter::Call || filter_type == MessageSearchFilter::MissedCall || - filter_type == MessageSearchFilter::Mention || filter_type == MessageSearchFilter::UnreadMention || - filter_type == MessageSearchFilter::FailedToSend) { + if (filter == MessageSearchFilter::Call || filter == MessageSearchFilter::MissedCall || + filter == MessageSearchFilter::Mention || filter == MessageSearchFilter::UnreadMention || + filter == MessageSearchFilter::FailedToSend) { promise.set_error(Status::Error(400, "The filter is not supported")); return {}; } - if (query.empty() && filter_type == MessageSearchFilter::Empty) { + if (query.empty() && filter == MessageSearchFilter::Empty) { promise.set_value(Unit()); return {}; } @@ -19288,11 +19285,11 @@ std::pair> MessagesManager::search_messages( } while (random_id == 0 || found_messages_.find(random_id) != found_messages_.end()); found_messages_[random_id]; // reserve place for result - LOG(DEBUG) << "Search messages globally with query = \"" << query << "\" from date " << offset_date << ", " - << offset_dialog_id << ", " << offset_message_id << " and limit " << limit; + LOG(DEBUG) << "Search all messages filtered by " << filter << " with query = \"" << query << "\" from date " + << offset_date << ", " << offset_dialog_id << ", " << offset_message_id << " and limit " << limit; td_->create_handler(std::move(promise)) - ->send(folder_id, ignore_folder_id, query, offset_date, offset_dialog_id, offset_message_id, limit, filter_type, + ->send(folder_id, ignore_folder_id, query, offset_date, offset_dialog_id, offset_message_id, limit, filter, random_id); return {}; } @@ -19455,9 +19452,8 @@ tl_object_ptr MessagesManager::get_dialog_message_by_date_objec return get_message_object(full_message_id); } -int32 MessagesManager::get_dialog_message_count(DialogId dialog_id, - const tl_object_ptr &filter, - bool return_local, int64 &random_id, Promise &&promise) { +int32 MessagesManager::get_dialog_message_count(DialogId dialog_id, MessageSearchFilter filter, bool return_local, + int64 &random_id, Promise &&promise) { if (random_id != 0) { // request has already been sent before auto it = found_dialog_messages_.find(random_id); @@ -19469,7 +19465,7 @@ int32 MessagesManager::get_dialog_message_count(DialogId dialog_id, } LOG(INFO) << "Get " << (return_local ? "local " : "") << "number of messages in " << dialog_id << " filtered by " - << to_string(filter); + << filter; const Dialog *d = get_dialog_force(dialog_id); if (d == nullptr) { @@ -19477,26 +19473,25 @@ int32 MessagesManager::get_dialog_message_count(DialogId dialog_id, return -1; } - auto filter_type = get_message_search_filter(filter); - if (filter_type == MessageSearchFilter::Empty) { + if (filter == MessageSearchFilter::Empty) { promise.set_error(Status::Error(6, "SearchMessagesFilterEmpty is not supported")); return -1; } auto dialog_type = dialog_id.get_type(); - int32 message_count = d->message_count_by_index[message_search_filter_index(filter_type)]; + int32 message_count = d->message_count_by_index[message_search_filter_index(filter)]; if (message_count == -1) { - if (filter_type == MessageSearchFilter::UnreadMention) { + if (filter == MessageSearchFilter::UnreadMention) { message_count = d->unread_mention_count; } } if (message_count != -1 || return_local || dialog_type == DialogType::SecretChat || - filter_type == MessageSearchFilter::FailedToSend) { + filter == MessageSearchFilter::FailedToSend) { promise.set_value(Unit()); return message_count; } - LOG(INFO) << "Get number of messages in " << dialog_id << " filtered by " << to_string(filter) << " from the server"; + LOG(INFO) << "Get number of messages in " << dialog_id << " filtered by " << filter << " from the server"; do { random_id = Random::secure_int64(); @@ -19508,7 +19503,7 @@ int32 MessagesManager::get_dialog_message_count(DialogId dialog_id, case DialogType::Chat: case DialogType::Channel: td_->create_handler(std::move(promise)) - ->send(dialog_id, "", UserId(), nullptr, MessageId(), 0, 1, filter_type, random_id); + ->send(dialog_id, "", UserId(), nullptr, MessageId(), 0, 1, filter, random_id); break; case DialogType::None: case DialogType::SecretChat: diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index af3ee6530..b42b17ae5 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -655,8 +655,7 @@ class MessagesManager : public Actor { std::pair> search_dialog_messages(DialogId dialog_id, const string &query, UserId sender_user_id, MessageId from_message_id, - int32 offset, int32 limit, - const tl_object_ptr &filter, + int32 offset, int32 limit, MessageSearchFilter filter, int64 &random_id, bool use_db, Promise &&promise); struct FoundMessages { @@ -668,15 +667,13 @@ class MessagesManager : public Actor { td_api::object_ptr get_found_messages_object(const FoundMessages &found_messages); FoundMessages offline_search_messages(DialogId dialog_id, const string &query, const string &offset, int32 limit, - const tl_object_ptr &filter, int64 &random_id, - Promise<> &&promise); + MessageSearchFilter filter, int64 &random_id, Promise<> &&promise); std::pair> search_messages(FolderId folder_id, bool ignore_folder_id, const string &query, int32 offset_date, DialogId offset_dialog_id, MessageId offset_message_id, - int32 limit, - const tl_object_ptr &filter, - int64 &random_id, Promise &&promise); + int32 limit, MessageSearchFilter filter, int64 &random_id, + Promise &&promise); std::pair> search_call_messages(MessageId from_message_id, int32 limit, bool only_missed, int64 &random_id, bool use_db, Promise &&promise); @@ -693,8 +690,8 @@ class MessagesManager : public Actor { void on_get_dialog_message_by_date_fail(int64 random_id); - int32 get_dialog_message_count(DialogId dialog_id, const tl_object_ptr &filter, - bool return_local, int64 &random_id, Promise &&promise); + int32 get_dialog_message_count(DialogId dialog_id, MessageSearchFilter filter, bool return_local, int64 &random_id, + Promise &&promise); vector get_dialog_scheduled_messages(DialogId dialog_id, bool force, bool ignore_result, Promise &&promise); @@ -2492,7 +2489,7 @@ class MessagesManager : public Actor { static MessageId get_first_database_message_id_by_index(const Dialog *d, MessageSearchFilter filter); void on_search_dialog_messages_db_result(int64 random_id, DialogId dialog_id, MessageId from_message_id, - MessageId first_db_message_id, MessageSearchFilter filter_type, int32 offset, + MessageId first_db_message_id, MessageSearchFilter filter, int32 offset, int32 limit, Result> r_messages, Promise<> promise); void on_messages_db_fts_result(Result result, string offset, int32 limit, int64 random_id, diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index fd01ed4bf..b09ae39d0 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -50,6 +50,7 @@ #include "td/telegram/MessageCopyOptions.h" #include "td/telegram/MessageEntity.h" #include "td/telegram/MessageId.h" +#include "td/telegram/MessageSearchFilter.h" #include "td/telegram/MessagesManager.h" #include "td/telegram/misc.h" #include "td/telegram/net/ConnectionCreator.h" @@ -1424,7 +1425,7 @@ class SearchChatMessagesRequest : public RequestActor<> { MessageId from_message_id_; int32 offset_; int32 limit_; - tl_object_ptr filter_; + MessageSearchFilter filter_; int64 random_id_; std::pair> messages_; @@ -1459,7 +1460,7 @@ class SearchChatMessagesRequest : public RequestActor<> { , from_message_id_(from_message_id) , offset_(offset) , limit_(limit) - , filter_(std::move(filter)) + , filter_(get_message_search_filter(filter)) , random_id_(0) { set_tries(3); } @@ -1470,7 +1471,7 @@ class SearchSecretMessagesRequest : public RequestActor<> { string query_; string offset_; int32 limit_; - tl_object_ptr filter_; + MessageSearchFilter filter_; int64 random_id_; MessagesManager::FoundMessages found_messages_; @@ -1492,7 +1493,7 @@ class SearchSecretMessagesRequest : public RequestActor<> { , query_(std::move(query)) , offset_(std::move(offset)) , limit_(limit) - , filter_(std::move(filter)) + , filter_(get_message_search_filter(filter)) , random_id_(0) { } }; @@ -1505,7 +1506,7 @@ class SearchMessagesRequest : public RequestActor<> { DialogId offset_dialog_id_; MessageId offset_message_id_; int32 limit_; - tl_object_ptr filter_; + MessageSearchFilter filter_; int64 random_id_; std::pair> messages_; @@ -1541,7 +1542,7 @@ class SearchMessagesRequest : public RequestActor<> { , offset_dialog_id_(offset_dialog_id) , offset_message_id_(offset_message_id) , limit_(limit) - , filter_(std::move(filter)) + , filter_(get_message_search_filter(filter)) , random_id_(0) { } }; @@ -1635,7 +1636,7 @@ class GetChatMessageByDateRequest : public RequestOnceActor { class GetChatMessageCountRequest : public RequestActor<> { DialogId dialog_id_; - tl_object_ptr filter_; + MessageSearchFilter filter_; bool return_local_; int64 random_id_; @@ -1655,7 +1656,7 @@ class GetChatMessageCountRequest : public RequestActor<> { tl_object_ptr filter, bool return_local) : RequestActor(std::move(td), request_id) , dialog_id_(dialog_id) - , filter_(std::move(filter)) + , filter_(get_message_search_filter(filter)) , return_local_(return_local) , random_id_(0) { } From 3305ca56894c2ba94fe338e4678287c81312e0e9 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 23 Aug 2020 20:34:05 +0300 Subject: [PATCH 26/39] Fix misprint. GitOrigin-RevId: cb8c1e3f26771d317ae3c9db1157d8e98d0ad3a8 --- td/telegram/ConfigManager.cpp | 6 +++--- td/telegram/ConfigManager.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/td/telegram/ConfigManager.cpp b/td/telegram/ConfigManager.cpp index 23bd09036..6bf45802f 100644 --- a/td/telegram/ConfigManager.cpp +++ b/td/telegram/ConfigManager.cpp @@ -875,7 +875,7 @@ class ConfigRecoverer : public Actor { }; ConfigManager::ConfigManager(ActorShared<> parent) : parent_(std::move(parent)) { - lazy_request_flood_countrol_.add_limit(20, 1); + lazy_request_flood_control_.add_limit(20, 1); } void ConfigManager::start_up() { @@ -930,7 +930,7 @@ void ConfigManager::request_config() { return; } - lazy_request_flood_countrol_.add_event(static_cast(Timestamp::now().at())); + lazy_request_flood_control_.add_event(static_cast(Timestamp::now().at())); request_config_from_dc_impl(DcId::main()); } @@ -943,7 +943,7 @@ void ConfigManager::lazy_request_config() { return; } - expire_time_.relax(Timestamp::at(lazy_request_flood_countrol_.get_wakeup_at())); + expire_time_.relax(Timestamp::at(lazy_request_flood_control_.get_wakeup_at())); set_timeout_at(expire_time_.at()); } diff --git a/td/telegram/ConfigManager.h b/td/telegram/ConfigManager.h index 3a0190f54..10e76c7f0 100644 --- a/td/telegram/ConfigManager.h +++ b/td/telegram/ConfigManager.h @@ -114,7 +114,7 @@ class ConfigManager : public NetQueryCallback { int ref_cnt_{1}; Timestamp expire_time_; - FloodControlStrict lazy_request_flood_countrol_; + FloodControlStrict lazy_request_flood_control_; vector>> get_app_config_queries_; From b575ed9a98e5908d9c1e01eae5115fc33901863e Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 23 Aug 2020 21:25:06 +0300 Subject: [PATCH 27/39] Add static assert for array size. GitOrigin-RevId: 1f044bd3c05346316d27c7ae0462a2b0d575168a --- td/telegram/MessageEntity.cpp | 1 + td/telegram/MessageEntity.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/td/telegram/MessageEntity.cpp b/td/telegram/MessageEntity.cpp index 53db4f05c..f4938b8c4 100644 --- a/td/telegram/MessageEntity.cpp +++ b/td/telegram/MessageEntity.cpp @@ -26,6 +26,7 @@ namespace td { int MessageEntity::get_type_priority(Type type) { static const int types[] = {50, 50, 50, 50, 50, 90, 91, 20, 11, 10, 49, 49, 50, 50, 92, 93, 0, 50}; + static_assert(sizeof(types) / sizeof(types[0]) == static_cast(MessageEntity::Type::Size), ""); return types[static_cast(type)]; } diff --git a/td/telegram/MessageEntity.h b/td/telegram/MessageEntity.h index 7a1d5e9cf..48c33d8fc 100644 --- a/td/telegram/MessageEntity.h +++ b/td/telegram/MessageEntity.h @@ -47,7 +47,8 @@ class MessageEntity { Underline, Strikethrough, BlockQuote, - BankCardNumber + BankCardNumber, + Size }; Type type; int32 offset; From 7bf004c8c3124436399a56b7f0af17c684f1e136 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 23 Aug 2020 23:02:20 +0300 Subject: [PATCH 28/39] Improve function name. GitOrigin-RevId: 93a8577f8cbe4e7d12f5365b0ea3eff8d5b82a94 --- td/telegram/SecureManager.cpp | 3 ++- td/telegram/SecureManager.h | 2 +- td/telegram/Td.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/td/telegram/SecureManager.cpp b/td/telegram/SecureManager.cpp index 32dfd4d51..accd573a0 100644 --- a/td/telegram/SecureManager.cpp +++ b/td/telegram/SecureManager.cpp @@ -1280,7 +1280,8 @@ void SecureManager::send_passport_authorization_form(int32 authorization_form_id send_with_promise(std::move(query), std::move(new_promise)); } -void SecureManager::get_preferred_country_code(string country_code, Promise> promise) { +void SecureManager::get_preferred_country_language(string country_code, + Promise> promise) { refcnt_++; for (auto &c : country_code) { c = to_upper(c); diff --git a/td/telegram/SecureManager.h b/td/telegram/SecureManager.h index f83000123..20802ea6a 100644 --- a/td/telegram/SecureManager.h +++ b/td/telegram/SecureManager.h @@ -54,7 +54,7 @@ class SecureManager : public NetQueryCallback { void send_passport_authorization_form(int32 authorization_form_id, std::vector types, Promise<> promise); - void get_preferred_country_code(string country_code, Promise> promise); + void get_preferred_country_language(string country_code, Promise> promise); private: ActorShared<> parent_; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index b09ae39d0..97e6962ec 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -7453,7 +7453,7 @@ void Td::on_request(uint64 id, td_api::getPreferredCountryLanguage &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.country_code_); CREATE_REQUEST_PROMISE(); - send_closure(secure_manager_, &SecureManager::get_preferred_country_code, std::move(request.country_code_), + send_closure(secure_manager_, &SecureManager::get_preferred_country_language, std::move(request.country_code_), std::move(promise)); } From 59265a41f5954636960767aa48ed054467931090 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 24 Aug 2020 00:43:31 +0300 Subject: [PATCH 29/39] Add CountryInfoManager. GitOrigin-RevId: cdd8cab21bac58e6162cae7b806aef8dfe400b81 --- CMakeLists.txt | 2 ++ td/telegram/CountryInfoManager.cpp | 54 ++++++++++++++++++++++++++++++ td/telegram/CountryInfoManager.h | 27 +++++++++++++++ td/telegram/Td.cpp | 43 +++++------------------- td/telegram/Td.h | 4 +-- 5 files changed, 93 insertions(+), 37 deletions(-) create mode 100644 td/telegram/CountryInfoManager.cpp create mode 100644 td/telegram/CountryInfoManager.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f30a6c95b..ff647a9f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -395,6 +395,7 @@ set(TDLIB_SOURCE td/telegram/ConfigShared.cpp td/telegram/Contact.cpp td/telegram/ContactsManager.cpp + td/telegram/CountryInfoManager.cpp td/telegram/DelayDispatcher.cpp td/telegram/Dependencies.cpp td/telegram/DeviceTokenManager.cpp @@ -550,6 +551,7 @@ set(TDLIB_SOURCE td/telegram/ConfigShared.h td/telegram/Contact.h td/telegram/ContactsManager.h + td/telegram/CountryInfoManager.h td/telegram/DelayDispatcher.h td/telegram/Dependencies.h td/telegram/DeviceTokenManager.h diff --git a/td/telegram/CountryInfoManager.cpp b/td/telegram/CountryInfoManager.cpp new file mode 100644 index 000000000..8eaa5724b --- /dev/null +++ b/td/telegram/CountryInfoManager.cpp @@ -0,0 +1,54 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/telegram/CountryInfoManager.h" + +#include "td/telegram/Global.h" +#include "td/telegram/Td.h" +#include "td/telegram/telegram_api.h" + +#include "td/utils/buffer.h" +#include "td/utils/Status.h" + +namespace td { + +class GetNearestDcQuery : public Td::ResultHandler { + Promise promise_; + + public: + explicit GetNearestDcQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send() { + send_query(G()->net_query_creator().create_unauth(telegram_api::help_getNearestDc())); + } + + void on_result(uint64 id, BufferSlice packet) override { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(id, result_ptr.move_as_error()); + } + + auto result = result_ptr.move_as_ok(); + promise_.set_value(std::move(result->country_)); + } + + void on_error(uint64 id, Status status) override { + if (!G()->is_expected_error(status) && status.message() != "BOT_METHOD_INVALID") { + LOG(ERROR) << "GetNearestDc returned " << status; + } + promise_.set_error(std::move(status)); + } +}; + +CountryInfoManager::CountryInfoManager(Td *td) : td_(td) { +} + +void CountryInfoManager::get_current_country_code(Promise &&promise) { + td_->create_handler(std::move(promise))->send(); +} + +} // namespace td diff --git a/td/telegram/CountryInfoManager.h b/td/telegram/CountryInfoManager.h new file mode 100644 index 000000000..5b9b4c560 --- /dev/null +++ b/td/telegram/CountryInfoManager.h @@ -0,0 +1,27 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/actor/PromiseFuture.h" + +#include "td/utils/common.h" + +namespace td { + +class Td; + +class CountryInfoManager { + public: + explicit CountryInfoManager(Td *td); + + void get_current_country_code(Promise &&promise); + + private: + Td *td_; +}; + +} // namespace td diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 97e6962ec..d583f696d 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -22,6 +22,7 @@ #include "td/telegram/ConfigManager.h" #include "td/telegram/ConfigShared.h" #include "td/telegram/ContactsManager.h" +#include "td/telegram/CountryInfoManager.h" #include "td/telegram/DeviceTokenManager.h" #include "td/telegram/DialogAdministrator.h" #include "td/telegram/DialogFilter.h" @@ -156,35 +157,6 @@ void Td::ResultHandler::send_query(NetQueryPtr query) { td->send(std::move(query)); } -class GetNearestDcQuery : public Td::ResultHandler { - Promise promise_; - - public: - explicit GetNearestDcQuery(Promise &&promise) : promise_(std::move(promise)) { - } - - void send() { - send_query(G()->net_query_creator().create_unauth(telegram_api::help_getNearestDc())); - } - - void on_result(uint64 id, BufferSlice packet) override { - auto result_ptr = fetch_result(packet); - if (result_ptr.is_error()) { - return on_error(id, result_ptr.move_as_error()); - } - - auto result = result_ptr.move_as_ok(); - promise_.set_value(std::move(result->country_)); - } - - void on_error(uint64 id, Status status) override { - if (!G()->is_expected_error(status) && status.message() != "BOT_METHOD_INVALID") { - LOG(ERROR) << "GetNearestDc returned " << status; - } - promise_.set_error(std::move(status)); - } -}; - class GetPromoDataQuery : public Td::ResultHandler { Promise> promise_; @@ -3813,8 +3785,12 @@ void Td::dec_actor_refcnt() { LOG(DEBUG) << "AuthManager was cleared" << timer; background_manager_.reset(); LOG(DEBUG) << "BackgroundManager was cleared" << timer; + callback_queries_manager_.reset(); + LOG(DEBUG) << "CallbackQueriesManager was cleared" << timer; contacts_manager_.reset(); LOG(DEBUG) << "ContactsManager was cleared" << timer; + country_info_manager_.reset(); + LOG(DEBUG) << "CountryInfoManager was cleared" << timer; documents_manager_.reset(); LOG(DEBUG) << "DocumentsManager was cleared" << timer; file_manager_.reset(); @@ -4230,7 +4206,7 @@ Status Td::init(DbKey key) { VLOG(td_init) << "Ping datacenter"; if (!auth_manager_->is_authorized()) { - send_get_nearest_dc_query(Promise()); + country_info_manager_->get_current_country_code(Promise()); } else { updates_manager_->get_difference("init"); schedule_get_terms_of_service(0); @@ -4419,6 +4395,7 @@ void Td::init_managers() { VLOG(td_init) << "Create Managers"; audios_manager_ = make_unique(this); callback_queries_manager_ = make_unique(this); + country_info_manager_ = make_unique(this); documents_manager_ = make_unique(this); video_notes_manager_ = make_unique(this); videos_manager_ = make_unique(this); @@ -4475,10 +4452,6 @@ void Td::init_managers() { "VerifyPhoneNumberManager", PhoneNumberManager::Type::VerifyPhone, create_reference()); } -void Td::send_get_nearest_dc_query(Promise promise) { - create_handler(std::move(promise))->send(); -} - void Td::send_update(tl_object_ptr &&object) { CHECK(object != nullptr); auto object_id = object->get_id(); @@ -7684,7 +7657,7 @@ void Td::on_request(uint64 id, const td_api::getCountryCode &request) { promise.set_value(make_tl_object(result.move_as_ok())); } }); - create_handler(std::move(query_promise))->send(); + country_info_manager_->get_current_country_code(std::move(query_promise)); } void Td::on_request(uint64 id, const td_api::getInviteText &request) { diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 208c02933..ba0db30ab 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -46,6 +46,7 @@ class CallManager; class CallbackQueriesManager; class ConfigManager; class ContactsManager; +class CountryInfoManager; class DeviceTokenManager; class DocumentsManager; class FileManager; @@ -136,6 +137,7 @@ class Td final : public NetQueryCallback { unique_ptr audios_manager_; unique_ptr callback_queries_manager_; + unique_ptr country_info_manager_; unique_ptr documents_manager_; unique_ptr video_notes_manager_; unique_ptr videos_manager_; @@ -1169,8 +1171,6 @@ class Td final : public NetQueryCallback { static Status fix_parameters(TdParameters ¶meters) TD_WARN_UNUSED_RESULT; Status set_parameters(td_api::object_ptr parameters) TD_WARN_UNUSED_RESULT; - void send_get_nearest_dc_query(Promise promise); - static td_api::object_ptr make_error(int32 code, CSlice error) { return td_api::make_object(code, error.str()); } From 1c6f778e8d68fbd20ae2c02ecdc1bc07ac240c20 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 24 Aug 2020 13:43:54 +0300 Subject: [PATCH 30/39] Fix message handling during logging out. GitOrigin-RevId: 6542058eb0fcec8e2693db5f5f8abf725c4d4ed7 --- td/telegram/MessageContent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index f08d29530..5ca47b190 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -3764,7 +3764,7 @@ unique_ptr get_message_content(Td *td, FormattedText message, tl_object_ptr &&media, DialogId owner_dialog_id, bool is_content_read, UserId via_bot_user_id, int32 *ttl) { - if (!td->auth_manager_->is_authorized() && !G()->close_flag() && media != nullptr) { + if (!td->auth_manager_->was_authorized() && !G()->close_flag() && media != nullptr) { LOG(ERROR) << "Receive without authorization " << to_string(media); media = nullptr; } From eff3dd9f36a524b2853101a6fe92a52e1b6ff17d Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 24 Aug 2020 14:39:03 +0300 Subject: [PATCH 31/39] Make CountryInfoManager actor. GitOrigin-RevId: 4e03cee13e38b682c6e063f16cd078345c0c00ff --- td/telegram/CountryInfoManager.cpp | 6 +++++- td/telegram/CountryInfoManager.h | 8 ++++++-- td/telegram/Td.cpp | 7 ++++++- td/telegram/Td.h | 3 ++- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/td/telegram/CountryInfoManager.cpp b/td/telegram/CountryInfoManager.cpp index 8eaa5724b..af5295f24 100644 --- a/td/telegram/CountryInfoManager.cpp +++ b/td/telegram/CountryInfoManager.cpp @@ -44,7 +44,11 @@ class GetNearestDcQuery : public Td::ResultHandler { } }; -CountryInfoManager::CountryInfoManager(Td *td) : td_(td) { +CountryInfoManager::CountryInfoManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { +} + +void CountryInfoManager::tear_down() { + parent_.reset(); } void CountryInfoManager::get_current_country_code(Promise &&promise) { diff --git a/td/telegram/CountryInfoManager.h b/td/telegram/CountryInfoManager.h index 5b9b4c560..cb6811e9f 100644 --- a/td/telegram/CountryInfoManager.h +++ b/td/telegram/CountryInfoManager.h @@ -6,6 +6,7 @@ // #pragma once +#include "td/actor/actor.h" #include "td/actor/PromiseFuture.h" #include "td/utils/common.h" @@ -14,14 +15,17 @@ namespace td { class Td; -class CountryInfoManager { +class CountryInfoManager : public Actor { public: - explicit CountryInfoManager(Td *td); + explicit CountryInfoManager(Td *td, ActorShared<> parent); void get_current_country_code(Promise &&promise); private: + void tear_down() override; + Td *td_; + ActorShared<> parent_; }; } // namespace td diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index d583f696d..f45618a90 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -3770,6 +3770,7 @@ void Td::inc_actor_refcnt() { void Td::dec_actor_refcnt() { actor_refcnt_--; + LOG(DEBUG) << "Decrease reference count to " << actor_refcnt_; if (actor_refcnt_ == 0) { if (close_flag_ == 2) { create_reference(); @@ -3858,6 +3859,7 @@ void Td::inc_request_actor_refcnt() { void Td::dec_request_actor_refcnt() { request_actor_refcnt_--; + LOG(DEBUG) << "Decrease request actor count to " << request_actor_refcnt_; if (request_actor_refcnt_ == 0) { LOG(WARNING) << "Have no request actors"; clear(); @@ -3974,6 +3976,8 @@ void Td::clear() { LOG(DEBUG) << "BackgroundManager actor was cleared" << timer; contacts_manager_actor_.reset(); LOG(DEBUG) << "ContactsManager actor was cleared" << timer; + country_info_manager_actor_.reset(); + LOG(DEBUG) << "CountryInfoManager actor was cleared" << timer; file_manager_actor_.reset(); LOG(DEBUG) << "FileManager actor was cleared" << timer; file_reference_manager_actor_.reset(); @@ -4395,7 +4399,6 @@ void Td::init_managers() { VLOG(td_init) << "Create Managers"; audios_manager_ = make_unique(this); callback_queries_manager_ = make_unique(this); - country_info_manager_ = make_unique(this); documents_manager_ = make_unique(this); video_notes_manager_ = make_unique(this); videos_manager_ = make_unique(this); @@ -4410,6 +4413,8 @@ void Td::init_managers() { contacts_manager_ = make_unique(this, create_reference()); contacts_manager_actor_ = register_actor("ContactsManager", contacts_manager_.get()); G()->set_contacts_manager(contacts_manager_actor_.get()); + country_info_manager_ = make_unique(this, create_reference()); + country_info_manager_actor_ = register_actor("CountryInfoManager", country_info_manager_.get()); inline_queries_manager_ = make_unique(this, create_reference()); inline_queries_manager_actor_ = register_actor("InlineQueriesManager", inline_queries_manager_.get()); messages_manager_ = make_unique(this, create_reference()); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index ba0db30ab..8ed81b801 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -137,7 +137,6 @@ class Td final : public NetQueryCallback { unique_ptr audios_manager_; unique_ptr callback_queries_manager_; - unique_ptr country_info_manager_; unique_ptr documents_manager_; unique_ptr video_notes_manager_; unique_ptr videos_manager_; @@ -151,6 +150,8 @@ class Td final : public NetQueryCallback { ActorOwn background_manager_actor_; unique_ptr contacts_manager_; ActorOwn contacts_manager_actor_; + unique_ptr country_info_manager_; + ActorOwn country_info_manager_actor_; unique_ptr file_manager_; ActorOwn file_manager_actor_; unique_ptr file_reference_manager_; From 3860953251889652bb0e414678c5ebc2eb75c18e Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 24 Aug 2020 23:38:45 +0300 Subject: [PATCH 32/39] Add td_api::getCountries. GitOrigin-RevId: 1c70e6e267b9582afe50014ffc9d1ef81a33f123 --- td/generate/scheme/td_api.tl | 15 +++ td/generate/scheme/td_api.tlo | Bin 179884 -> 180388 bytes td/telegram/CountryInfoManager.cpp | 197 ++++++++++++++++++++++++++++ td/telegram/CountryInfoManager.h | 27 ++++ td/telegram/LanguagePackManager.cpp | 44 +++++++ td/telegram/LanguagePackManager.h | 2 + td/telegram/Td.cpp | 6 + td/telegram/Td.h | 2 + td/telegram/cli.cpp | 4 +- 9 files changed, 296 insertions(+), 1 deletion(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 2e30bac18..a7a9b273a 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1177,6 +1177,18 @@ webPageInstantView page_blocks:vector view_count:int32 version:int32 webPage url:string display_url:string type:string site_name:string title:string description:formattedText photo:photo embed_url:string embed_type:string embed_width:int32 embed_height:int32 duration:int32 author:string animation:animation audio:audio document:document sticker:sticker video:video video_note:videoNote voice_note:voiceNote instant_view_version:int32 = WebPage; +//@description Contains information about a country +//@country_code A two-letter ISO 3166-1 alpha-2 country code +//@name Native name of the country +//@english_name English name of the country +//@is_hidden True, if the country should be hidden from the list of all countries +//@calling_codes List of country calling codes +countryInfo country_code:string name:string english_name:string is_hidden:Bool calling_codes:vector = CountryInfo; + +//@description Contains information about countries @countries The list of countries +countries countries:vector = Countries; + + //@description Describes an action associated with a bank card number @text Action text @url The URL to be opened bankCardActionOpenUrl text:string url:string = BankCardActionOpenUrl; @@ -4654,6 +4666,9 @@ answerCustomQuery custom_query_id:int64 data:string = Ok; setAlarm seconds:double = Ok; +//@description Returns information about existing countries. Can be called before authorization +getCountries = Countries; + //@description Uses current user IP address to find their country. Returns two-letter ISO 3166-1 alpha-2 country code. Can be called before authorization getCountryCode = Text; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 876600ebc272616aeab4207820b61974c199ab67..89087622f23a8d21af13c487ee84109e0fb04ee4 100644 GIT binary patch delta 313 zcmZ4UmupEQH}9j_`c@23AhwaWnV07&TWcPtbAD-FNm1q`UKxQ?MJWl~5Pqd+URwUd z0}`7j@OCIM+HRIK2+z<2t51fgPc3F(0P$}g6Y^mMnkxP5z9uJ3Zt}t~d0UWaAQ=!S za%R)vux&dC(g6`+V7MyB6$7>rq6=&zhz~N6b^6?RM*YbXekpMBq~@jPWEN+{PiM?! zRA$Y{Oi4+de9%vP`UEv5HtxinoXouR_~d+`Akfn34i6YbSU{#Ur_9)%GK29>CS&7v jM<%A*jym%=U;N=oPc4CXFcahfxDU|XxLv@7X-*XYi(G5+ delta 59 zcmZ3|$i3z-7w@Cl`c@23AhMCSnRoL8-VP;3>&=-4;Tg>av$h+|V!V*a*sz_Eh3U5A Kb`dwG2~_|w> promise_; + + public: + explicit GetCountriesListQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(const string &language_code, int32 hash) { + send_query(G()->net_query_creator().create_unauth(telegram_api::help_getCountriesList(language_code, hash))); + } + + void on_result(uint64 id, BufferSlice packet) override { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(id, result_ptr.move_as_error()); + } + + promise_.set_value(result_ptr.move_as_ok()); + } + + void on_error(uint64 id, Status status) override { + if (!G()->is_expected_error(status)) { + LOG(ERROR) << "GetCountriesList returned " << status; + } + promise_.set_error(std::move(status)); + } +}; + +struct CountryInfoManager::CallingCodeInfo { + int32 calling_code = 0; + vector prefixes; + vector patterns; +}; + +struct CountryInfoManager::CountryInfo { + string country_code; + string default_name; + string name; + vector calling_codes; + bool is_hidden = false; + + td_api::object_ptr get_country_info_object() const { + return td_api::make_object( + country_code, name.empty() ? default_name : name, default_name, is_hidden, + transform(calling_codes, [](const CallingCodeInfo &info) { return to_string(info.calling_code); })); + } +}; + +struct CountryInfoManager::CountryList { + vector countries_; + int32 hash = 0; + double next_reload_time = 0.0; + + td_api::object_ptr get_countries_object() const { + return td_api::make_object( + transform(countries_, [](const CountryInfo &info) { return info.get_country_info_object(); })); + } +}; + CountryInfoManager::CountryInfoManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { } @@ -51,8 +114,142 @@ void CountryInfoManager::tear_down() { parent_.reset(); } +string CountryInfoManager::get_main_language_code() { + return to_lower(td_->language_pack_manager_->get_actor_unsafe()->get_main_language_code()); +} + +void CountryInfoManager::get_countries(Promise> &&promise) { + do_get_countries(get_main_language_code(), false, std::move(promise)); +} + +void CountryInfoManager::do_get_countries(string language_code, bool is_recursive, + Promise> &&promise) { + auto list = get_country_list(language_code); + if (list == nullptr) { + if (is_recursive) { + return promise.set_error(Status::Error(500, "Requested data is inaccessible")); + } + return load_country_list(language_code, 0, + PromiseCreator::lambda([actor_id = actor_id(this), language_code, + promise = std::move(promise)](Result &&result) mutable { + if (result.is_error()) { + return promise.set_error(result.move_as_error()); + } + send_closure(actor_id, &CountryInfoManager::do_get_countries, std::move(language_code), + true, std::move(promise)); + })); + } + + promise.set_value(list->get_countries_object()); +} + void CountryInfoManager::get_current_country_code(Promise &&promise) { td_->create_handler(std::move(promise))->send(); } +void CountryInfoManager::load_country_list(string language_code, int32 hash, Promise &&promise) { + auto &queries = pending_load_country_queries_[language_code]; + if (!promise && !queries.empty()) { + return; + } + queries.push_back(std::move(promise)); + if (queries.size() == 1) { + auto query_promise = PromiseCreator::lambda( + [actor_id = actor_id(this), language_code](Result> &&result) { + send_closure(actor_id, &CountryInfoManager::on_get_country_list, language_code, std::move(result)); + }); + td_->create_handler(std::move(query_promise))->send(language_code, hash); + } +} + +void CountryInfoManager::on_get_country_list(const string &language_code, + Result> r_country_list) { + auto query_it = pending_load_country_queries_.find(language_code); + CHECK(query_it != pending_load_country_queries_.end()); + auto promises = std::move(query_it->second); + CHECK(!promises.empty()); + pending_load_country_queries_.erase(query_it); + + auto &countries = countries_[language_code]; + if (r_country_list.is_error()) { + if (countries != nullptr) { + countries->next_reload_time = Time::now() + Random::fast(60, 120); + } + for (auto &promise : promises) { + promise.set_error(r_country_list.error().clone()); + } + return; + } + + auto country_list = r_country_list.move_as_ok(); + CHECK(country_list != nullptr); + switch (country_list->get_id()) { + case telegram_api::help_countriesListNotModified::ID: + if (countries == nullptr) { + LOG(ERROR) << "Receive countriesListNotModified for unknown list with language code " << language_code; + countries_.erase(language_code); + } else { + LOG(INFO) << "List of countries with language code " << language_code << " is not modified"; + countries->next_reload_time = Time::now() + Random::fast(86400, 2 * 86400); + } + break; + case telegram_api::help_countriesList::ID: { + auto list = move_tl_object_as(country_list); + if (countries == nullptr) { + countries = make_unique(); + } + for (auto &c : list->countries_) { + CountryInfo info; + info.country_code = std::move(c->iso2_); + info.default_name = std::move(c->default_name_); + info.name = std::move(c->name_); + info.is_hidden = std::move(c->hidden_); + for (auto &code : c->country_codes_) { + auto r_calling_code = to_integer_safe(code->country_code_); + if (r_calling_code.is_error() || r_calling_code.ok() <= 0) { + LOG(ERROR) << "Receive invalid calling code " << code->country_code_ << " for country " + << info.country_code; + } else { + CallingCodeInfo calling_code_info; + calling_code_info.calling_code = r_calling_code.ok(); + calling_code_info.prefixes = std::move(code->prefixes_); + calling_code_info.patterns = std::move(code->patterns_); + info.calling_codes.push_back(std::move(calling_code_info)); + } + } + if (info.calling_codes.empty()) { + LOG(ERROR) << "Receive empty list of calling codes for " << info.country_code; + continue; + } + + countries->countries_.push_back(std::move(info)); + } + countries->hash = list->hash_; + countries->next_reload_time = Time::now() + Random::fast(86400, 2 * 86400); + break; + } + default: + UNREACHABLE(); + } + + for (auto &promise : promises) { + promise.set_value(Unit()); + } +} + +const CountryInfoManager::CountryList *CountryInfoManager::get_country_list(const string &language_code) { + auto it = countries_.find(language_code); + if (it == countries_.end()) { + return nullptr; + } + + auto *country = it->second.get(); + CHECK(country != nullptr); + if (country->next_reload_time < Time::now()) { + load_country_list(language_code, country->hash, Auto()); + } + + return country; +} + } // namespace td diff --git a/td/telegram/CountryInfoManager.h b/td/telegram/CountryInfoManager.h index cb6811e9f..3bb444490 100644 --- a/td/telegram/CountryInfoManager.h +++ b/td/telegram/CountryInfoManager.h @@ -6,10 +6,16 @@ // #pragma once +#include "td/telegram/td_api.h" +#include "td/telegram/telegram_api.h" + #include "td/actor/actor.h" #include "td/actor/PromiseFuture.h" #include "td/utils/common.h" +#include "td/utils/Status.h" + +#include namespace td { @@ -19,11 +25,32 @@ class CountryInfoManager : public Actor { public: explicit CountryInfoManager(Td *td, ActorShared<> parent); + void get_countries(Promise> &&promise); + void get_current_country_code(Promise &&promise); private: void tear_down() override; + struct CallingCodeInfo; + struct CountryInfo; + struct CountryList; + + string get_main_language_code(); + + void do_get_countries(string language_code, bool is_recursive, + Promise> &&promise); + + void load_country_list(string language_code, int32 hash, Promise &&promise); + + void on_get_country_list(const string &language_code, + Result> r_country_list); + + const CountryList *get_country_list(const string &language_code); + + std::unordered_map>> pending_load_country_queries_; + std::unordered_map> countries_; + Td *td_; ActorShared<> parent_; }; diff --git a/td/telegram/LanguagePackManager.cpp b/td/telegram/LanguagePackManager.cpp index fcb4011c5..e7847ff2e 100644 --- a/td/telegram/LanguagePackManager.cpp +++ b/td/telegram/LanguagePackManager.cpp @@ -238,6 +238,50 @@ void LanguagePackManager::tear_down() { } } +string LanguagePackManager::get_main_language_code() { + if (language_pack_.empty() || language_code_.empty()) { + return "en"; + } + if (language_code_.size() <= 2) { + return language_code_; + } + + std::lock_guard packs_lock(database_->mutex_); + auto pack_it = database_->language_packs_.find(language_pack_); + CHECK(pack_it != database_->language_packs_.end()); + + LanguageInfo *info = nullptr; + LanguagePack *pack = pack_it->second.get(); + std::lock_guard languages_lock(pack->mutex_); + if (is_custom_language_code(language_code_)) { + auto custom_it = pack->custom_language_pack_infos_.find(language_code_); + if (custom_it != pack->custom_language_pack_infos_.end()) { + info = &custom_it->second; + } + } else { + for (auto &server_info : pack->server_language_pack_infos_) { + if (server_info.first == language_code_) { + info = &server_info.second; + } + } + } + + if (info == nullptr) { + LOG(ERROR) << "Failed to find information about chosen language " << language_code_; + if (!is_custom_language_code(language_code_)) { + search_language_info(language_code_, Auto()); + } + } else { + if (!info->base_language_code_.empty()) { + return info->base_language_code_; + } + if (!info->plural_code_.empty()) { + return info->plural_code_; + } + } + return "en"; +} + vector LanguagePackManager::get_used_language_codes() { if (language_pack_.empty() || language_code_.empty()) { return {}; diff --git a/td/telegram/LanguagePackManager.h b/td/telegram/LanguagePackManager.h index 311f79403..bc3af5cc0 100644 --- a/td/telegram/LanguagePackManager.h +++ b/td/telegram/LanguagePackManager.h @@ -43,6 +43,8 @@ class LanguagePackManager : public NetQueryCallback { static bool is_custom_language_code(Slice language_code); + string get_main_language_code(); + vector get_used_language_codes(); void on_language_pack_changed(); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index f45618a90..e4fb8daf4 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -3298,6 +3298,7 @@ bool Td::is_preauthentication_request(int32 id) { case td_api::getNetworkStatistics::ID: case td_api::addNetworkStatistics::ID: case td_api::resetNetworkStatistics::ID: + case td_api::getCountries::ID: case td_api::getCountryCode::ID: case td_api::getDeepLinkInfo::ID: case td_api::getApplicationConfig::ID: @@ -7653,6 +7654,11 @@ void Td::on_request(uint64 id, td_api::acceptTermsOfService &request) { accept_terms_of_service(this, std::move(request.terms_of_service_id_), std::move(promise)); } +void Td::on_request(uint64 id, const td_api::getCountries &request) { + CREATE_REQUEST_PROMISE(); + country_info_manager_->get_countries(std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::getCountryCode &request) { CREATE_REQUEST_PROMISE(); auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result result) mutable { diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 8ed81b801..38f4e81a1 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1054,6 +1054,8 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, td_api::acceptTermsOfService &request); + void on_request(uint64 id, const td_api::getCountries &request); + void on_request(uint64 id, const td_api::getCountryCode &request); void on_request(uint64 id, const td_api::getInviteText &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 65326864a..a9b869872 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2268,8 +2268,10 @@ class CliClient final : public Actor { send_request(td_api::make_object(to_integer(args))); } else if (op == "rbgs") { send_request(td_api::make_object()); - } else if (op == "gccode") { + } else if (op == "gcoc") { send_request(td_api::make_object()); + } else if (op == "gcos") { + send_request(td_api::make_object()); } else if (op == "git") { send_request(td_api::make_object()); } else if (op == "atos") { From 1843e92961600be7b7b03f8b85d82e95d6d26dff Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 25 Aug 2020 13:42:14 +0300 Subject: [PATCH 33/39] Add td_api::getPhoneNumberInfo. GitOrigin-RevId: bba065e87cf5d68026d7408c2a34770f6e4f931d --- td/generate/scheme/td_api.tl | 9 +++ td/generate/scheme/td_api.tlo | Bin 180388 -> 180720 bytes td/telegram/CountryInfoManager.cpp | 123 ++++++++++++++++++++++++++++- td/telegram/CountryInfoManager.h | 6 ++ td/telegram/Td.cpp | 6 ++ td/telegram/Td.h | 2 + td/telegram/cli.cpp | 6 +- 7 files changed, 147 insertions(+), 5 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index a7a9b273a..36180d639 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1188,6 +1188,12 @@ countryInfo country_code:string name:string english_name:string is_hidden:Bool c //@description Contains information about countries @countries The list of countries countries countries:vector = Countries; +//@description Contains information about a phone number +//@country Information about the country to which the phone number belongs; may be null +//@country_calling_code The part of the phone number denoting country calling code or its part +//@formatted_phone_number The phone number without country calling code formatted accordingly to local rules +phoneNumberInfo country:countryInfo country_calling_code:string formatted_phone_number:string = PhoneNumberInfo; + //@description Describes an action associated with a bank card number @text Action text @url The URL to be opened bankCardActionOpenUrl text:string url:string = BankCardActionOpenUrl; @@ -4672,6 +4678,9 @@ getCountries = Countries; //@description Uses current user IP address to find their country. Returns two-letter ISO 3166-1 alpha-2 country code. Can be called before authorization getCountryCode = Text; +//@description Returns information about a phone number by its prefix. Can be called before authorization @phone_number_prefix The phone number prefix +getPhoneNumberInfo phone_number_prefix:string = PhoneNumberInfo; + //@description Returns the default text for invitation messages to be used as a placeholder when the current user invites friends to Telegram getInviteText = Text; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 89087622f23a8d21af13c487ee84109e0fb04ee4..0b46896a4b9a38fa8c520cdd327caf2bc98f6c9c 100644 GIT binary patch delta 272 zcmZ3|$o-+2oA=RdeJchi5Z}lfp~Sx~S&=^=BR?1JSODB3^Yvo*?mp+QkRb8<5C(&ML36lap2tYFN-C6<<7l$%&mlA1F89vhR`q@z5O6GAvxKsIc5 zNoL%$fU#*iBMXyrgw4;{N(+S2Q%jKC3vvqs%rPJfL6!-F9UGqq_ECI6QEFOd#pDl> MG7vK@VwiGL0OyBZc>n+a delta 60 zcmey+%)O+MoA=RdeJchi5ZlNbp|p9T5;Gs8ZSz!v?NbdHUl?sSO<`QWfU$A=Qx+!Y Li0u<%nG#X}CpZ&L diff --git a/td/telegram/CountryInfoManager.cpp b/td/telegram/CountryInfoManager.cpp index 6da346f6d..f303160d0 100644 --- a/td/telegram/CountryInfoManager.cpp +++ b/td/telegram/CountryInfoManager.cpp @@ -77,7 +77,7 @@ class GetCountriesListQuery : public Td::ResultHandler { }; struct CountryInfoManager::CallingCodeInfo { - int32 calling_code = 0; + string calling_code; vector prefixes; vector patterns; }; @@ -92,7 +92,7 @@ struct CountryInfoManager::CountryInfo { td_api::object_ptr get_country_info_object() const { return td_api::make_object( country_code, name.empty() ? default_name : name, default_name, is_hidden, - transform(calling_codes, [](const CallingCodeInfo &info) { return to_string(info.calling_code); })); + transform(calling_codes, [](const CallingCodeInfo &info) { return info.calling_code; })); } }; @@ -124,6 +124,13 @@ void CountryInfoManager::get_countries(Promise> &&promise) { + if (is_recursive) { + auto main_language_code = get_main_language_code(); + if (language_code != main_language_code) { + language_code = std::move(main_language_code); + is_recursive = false; + } + } auto list = get_country_list(language_code); if (list == nullptr) { if (is_recursive) { @@ -143,6 +150,113 @@ void CountryInfoManager::do_get_countries(string language_code, bool is_recursiv promise.set_value(list->get_countries_object()); } +void CountryInfoManager::get_phone_number_info(string phone_number_prefix, + Promise> &&promise) { + td::remove_if(phone_number_prefix, [](char c) { return c < '0' || c > '9'; }); + if (phone_number_prefix.empty()) { + return promise.set_value(td_api::make_object(nullptr, string(), string())); + } + do_get_phone_number_info(std::move(phone_number_prefix), get_main_language_code(), false, std::move(promise)); +} + +void CountryInfoManager::do_get_phone_number_info(string phone_number_prefix, string language_code, bool is_recursive, + Promise> &&promise) { + if (is_recursive) { + auto main_language_code = get_main_language_code(); + if (language_code != main_language_code) { + language_code = std::move(main_language_code); + is_recursive = false; + } + } + auto list = get_country_list(language_code); + if (list == nullptr) { + if (is_recursive) { + return promise.set_error(Status::Error(500, "Requested data is inaccessible")); + } + return load_country_list(language_code, 0, + PromiseCreator::lambda([actor_id = actor_id(this), phone_number_prefix, language_code, + promise = std::move(promise)](Result &&result) mutable { + if (result.is_error()) { + return promise.set_error(result.move_as_error()); + } + send_closure(actor_id, &CountryInfoManager::do_get_phone_number_info, + std::move(phone_number_prefix), std::move(language_code), true, + std::move(promise)); + })); + } + + Slice phone_number = phone_number_prefix; + const CountryInfo *best_country = nullptr; + const CallingCodeInfo *best_calling_code = nullptr; + size_t best_length = 0; + bool is_prefix = false; + for (auto &country : list->countries_) { + for (auto &calling_code : country.calling_codes) { + if (begins_with(phone_number, calling_code.calling_code)) { + auto calling_code_size = calling_code.calling_code.size(); + for (auto &prefix : calling_code.prefixes) { + if (begins_with(prefix, phone_number.substr(calling_code_size))) { + is_prefix = true; + } + if (calling_code_size + prefix.size() > best_length && + begins_with(phone_number.substr(calling_code_size), prefix)) { + best_country = &country; + best_calling_code = &calling_code; + best_length = calling_code_size + prefix.size(); + } + } + } + if (begins_with(calling_code.calling_code, phone_number)) { + is_prefix = true; + } + } + } + if (best_country == nullptr) { + return promise.set_value(td_api::make_object( + nullptr, is_prefix ? phone_number_prefix : string(), is_prefix ? string() : phone_number_prefix)); + } + + string formatted_part = phone_number_prefix.substr(best_calling_code->calling_code.size()); + string formatted_phone_number = formatted_part; + size_t max_matched_digits = 0; + for (auto &pattern : best_calling_code->patterns) { + string result; + size_t current_pattern_pos = 0; + bool is_failed_match = false; + size_t matched_digits = 0; + for (auto &c : formatted_part) { + while (current_pattern_pos < pattern.size() && pattern[current_pattern_pos] != 'X' && + !is_digit(pattern[current_pattern_pos])) { + result += pattern[current_pattern_pos++]; + } + if (current_pattern_pos == pattern.size()) { + result += c; + } else if (pattern[current_pattern_pos] == 'X') { + result += c; + current_pattern_pos++; + } else { + CHECK(is_digit(pattern[current_pattern_pos])); + if (c == pattern[current_pattern_pos]) { + matched_digits++; + result += c; + current_pattern_pos++; + } else { + is_failed_match = true; + break; + } + } + } + if (!is_failed_match && matched_digits >= max_matched_digits) { + max_matched_digits = matched_digits; + formatted_phone_number = std::move(result); + } + } + + promise.set_value(td_api::make_object( + best_country->get_country_info_object(), best_calling_code->calling_code, + formatted_phone_number.empty() ? formatted_part : formatted_phone_number)); +} + void CountryInfoManager::get_current_country_code(Promise &&promise) { td_->create_handler(std::move(promise))->send(); } @@ -211,8 +325,11 @@ void CountryInfoManager::on_get_country_list(const string &language_code, << info.country_code; } else { CallingCodeInfo calling_code_info; - calling_code_info.calling_code = r_calling_code.ok(); + calling_code_info.calling_code = std::move(code->country_code_); calling_code_info.prefixes = std::move(code->prefixes_); + if (calling_code_info.prefixes.empty()) { + calling_code_info.prefixes.resize(1); + } calling_code_info.patterns = std::move(code->patterns_); info.calling_codes.push_back(std::move(calling_code_info)); } diff --git a/td/telegram/CountryInfoManager.h b/td/telegram/CountryInfoManager.h index 3bb444490..5602a40e0 100644 --- a/td/telegram/CountryInfoManager.h +++ b/td/telegram/CountryInfoManager.h @@ -29,6 +29,9 @@ class CountryInfoManager : public Actor { void get_current_country_code(Promise &&promise); + void get_phone_number_info(string phone_number_prefix, + Promise> &&promise); + private: void tear_down() override; @@ -41,6 +44,9 @@ class CountryInfoManager : public Actor { void do_get_countries(string language_code, bool is_recursive, Promise> &&promise); + void do_get_phone_number_info(string phone_number_prefix, string language_code, bool is_recursive, + Promise> &&promise); + void load_country_list(string language_code, int32 hash, Promise &&promise); void on_get_country_list(const string &language_code, diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index e4fb8daf4..a6a63a9e7 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -3300,6 +3300,7 @@ bool Td::is_preauthentication_request(int32 id) { case td_api::resetNetworkStatistics::ID: case td_api::getCountries::ID: case td_api::getCountryCode::ID: + case td_api::getPhoneNumberInfo::ID: case td_api::getDeepLinkInfo::ID: case td_api::getApplicationConfig::ID: case td_api::saveApplicationLogEvent::ID: @@ -7671,6 +7672,11 @@ void Td::on_request(uint64 id, const td_api::getCountryCode &request) { country_info_manager_->get_current_country_code(std::move(query_promise)); } +void Td::on_request(uint64 id, const td_api::getPhoneNumberInfo &request) { + CREATE_REQUEST_PROMISE(); + country_info_manager_->get_phone_number_info(request.phone_number_prefix_, std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::getInviteText &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 38f4e81a1..cf08b4660 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1058,6 +1058,8 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, const td_api::getCountryCode &request); + void on_request(uint64 id, const td_api::getPhoneNumberInfo &request); + void on_request(uint64 id, const td_api::getInviteText &request); void on_request(uint64 id, td_api::getDeepLinkInfo &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index a9b869872..1693fa3cc 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2268,10 +2268,12 @@ class CliClient final : public Actor { send_request(td_api::make_object(to_integer(args))); } else if (op == "rbgs") { send_request(td_api::make_object()); - } else if (op == "gcoc") { - send_request(td_api::make_object()); } else if (op == "gcos") { send_request(td_api::make_object()); + } else if (op == "gcoc") { + send_request(td_api::make_object()); + } else if (op == "gpni") { + send_request(td_api::make_object(args)); } else if (op == "git") { send_request(td_api::make_object()); } else if (op == "atos") { From 1a4a834b2d362f10dc6afc84f35903aaca7834b7 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 25 Aug 2020 15:09:24 +0300 Subject: [PATCH 34/39] Add progressive JPEG support. GitOrigin-RevId: 48c56c3c2575da76df5e9237f6fb043e374bf30d --- td/generate/scheme/td_api.tl | 6 +++-- td/generate/scheme/td_api.tlo | Bin 180720 -> 180784 bytes td/telegram/InlineQueriesManager.cpp | 3 ++- td/telegram/MessageContent.cpp | 32 +++++++++++++-------------- td/telegram/Photo.cpp | 20 ++++++++++++++--- td/telegram/Photo.h | 1 + td/telegram/Photo.hpp | 6 +++++ td/telegram/Version.h | 1 + 8 files changed, 47 insertions(+), 22 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 36180d639..5c300e5a5 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -178,8 +178,10 @@ inputFileLocal path:string = InputFile; inputFileGenerated original_path:string conversion:string expected_size:int32 = InputFile; -//@description Photo description @type Thumbnail type (see https://core.telegram.org/constructor/photoSize) @photo Information about the photo file @width Photo width @height Photo height -photoSize type:string photo:file width:int32 height:int32 = PhotoSize; +//@description Describes an image in JPEG format @type Image type (see https://core.telegram.org/constructor/photoSize) +//@photo Information about the image file @width Image width @height Image height +//@progressive_sizes Sizes of progressive JPEG file prefixes, which can be used to preliminarily show the image +photoSize type:string photo:file width:int32 height:int32 progressive_sizes:vector = PhotoSize; //@description Thumbnail image of a very poor quality and low resolution @width Thumbnail width, usually doesn't exceed 40 @height Thumbnail height, usually doesn't exceed 40 @data The thumbnail in JPEG format minithumbnail width:int32 height:int32 data:bytes = Minithumbnail; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 0b46896a4b9a38fa8c520cdd327caf2bc98f6c9c..5864e0a4d50a49e819face70f17cf217a285acce 100644 GIT binary patch delta 118 zcmey+%)Oz7d&3qbmI*qq;y3S53Wx`@rf*X;@>RL1QWQkfEB0GL)HVE_OC diff --git a/td/telegram/InlineQueriesManager.cpp b/td/telegram/InlineQueriesManager.cpp index 16fd37374..6e4038bd5 100644 --- a/td/telegram/InlineQueriesManager.cpp +++ b/td/telegram/InlineQueriesManager.cpp @@ -864,7 +864,8 @@ tl_object_ptr copy(const td_api::minithumbnail &obj) { template <> tl_object_ptr copy(const td_api::photoSize &obj) { - return make_tl_object(obj.type_, copy(obj.photo_), obj.width_, obj.height_); + return make_tl_object(obj.type_, copy(obj.photo_), obj.width_, obj.height_, + vector(obj.progressive_sizes_)); } template <> diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 5ca47b190..ed3774ede 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -3355,17 +3355,17 @@ void unregister_message_content(Td *td, const MessageContent *content, FullMessa template static tl_object_ptr secret_to_telegram(FromT &from); -// fileLocationUnavailable#7c596b46 volume_id:long local_id:int secret:long = FileLocation; +// fileLocationUnavailable volume_id:long local_id:int secret:long = FileLocation; static auto secret_to_telegram(secret_api::fileLocationUnavailable &file_location) { return make_tl_object(file_location.volume_id_, file_location.local_id_); } -// fileLocation#53d69076 dc_id:int volume_id:long local_id:int secret:long = FileLocation; +// fileLocation dc_id:int volume_id:long local_id:int secret:long = FileLocation; static auto secret_to_telegram(secret_api::fileLocation &file_location) { return make_tl_object(file_location.volume_id_, file_location.local_id_); } -// photoSizeEmpty#e17e23c type:string = PhotoSize; +// photoSizeEmpty type:string = PhotoSize; static auto secret_to_telegram(secret_api::photoSizeEmpty &empty) { if (!clean_input_string(empty.type_)) { empty.type_.clear(); @@ -3373,7 +3373,7 @@ static auto secret_to_telegram(secret_api::photoSizeEmpty &empty) { return make_tl_object(empty.type_); } -// photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize; +// photoSize type:string location:FileLocation w:int h:int size:int = PhotoSize; static auto secret_to_telegram(secret_api::photoSize &photo_size) { if (!clean_input_string(photo_size.type_)) { photo_size.type_.clear(); @@ -3383,7 +3383,7 @@ static auto secret_to_telegram(secret_api::photoSize &photo_size) { photo_size.w_, photo_size.h_, photo_size.size_); } -// photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize; +// photoCachedSize type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize; static auto secret_to_telegram(secret_api::photoCachedSize &photo_size) { if (!clean_input_string(photo_size.type_)) { photo_size.type_.clear(); @@ -3393,17 +3393,17 @@ static auto secret_to_telegram(secret_api::photoCachedSize &photo_size) { photo_size.w_, photo_size.h_, photo_size.bytes_.clone()); } -// documentAttributeImageSize #6c37c15c w:int h:int = DocumentAttribute; +// documentAttributeImageSize w:int h:int = DocumentAttribute; static auto secret_to_telegram(secret_api::documentAttributeImageSize &image_size) { return make_tl_object(image_size.w_, image_size.h_); } -// documentAttributeAnimated #11b58939 = DocumentAttribute; +// documentAttributeAnimated = DocumentAttribute; static auto secret_to_telegram(secret_api::documentAttributeAnimated &animated) { return make_tl_object(); } -// documentAttributeSticker23 #fb0a5727 = DocumentAttribute; +// documentAttributeSticker23 = DocumentAttribute; static auto secret_to_telegram(secret_api::documentAttributeSticker23 &sticker) { return make_tl_object( 0, false /*ignored*/, "", make_tl_object(), nullptr); @@ -3420,7 +3420,7 @@ static auto secret_to_telegram(secret_api::inputStickerSetShortName &sticker_set return make_tl_object(sticker_set.short_name_); } -// documentAttributeSticker #3a556302 alt:string stickerset:InputStickerSet = DocumentAttribute; +// documentAttributeSticker alt:string stickerset:InputStickerSet = DocumentAttribute; static auto secret_to_telegram(secret_api::documentAttributeSticker &sticker) { if (!clean_input_string(sticker.alt_)) { sticker.alt_.clear(); @@ -3430,13 +3430,13 @@ static auto secret_to_telegram(secret_api::documentAttributeSticker &sticker) { nullptr); } -// documentAttributeVideo #5910cccb duration:int w:int h:int = DocumentAttribute; +// documentAttributeVideo duration:int w:int h:int = DocumentAttribute; static auto secret_to_telegram(secret_api::documentAttributeVideo &video) { return make_tl_object(0, false /*ignored*/, false /*ignored*/, video.duration_, video.w_, video.h_); } -// documentAttributeFilename #15590068 file_name:string = DocumentAttribute; +// documentAttributeFilename file_name:string = DocumentAttribute; static auto secret_to_telegram(secret_api::documentAttributeFilename &filename) { if (!clean_input_string(filename.file_name_)) { filename.file_name_.clear(); @@ -3444,7 +3444,7 @@ static auto secret_to_telegram(secret_api::documentAttributeFilename &filename) return make_tl_object(filename.file_name_); } -// documentAttributeVideo66#ef02ce6 flags:# round_message:flags.0?true duration:int w:int h:int = DocumentAttribute; +// documentAttributeVideo66 flags:# round_message:flags.0?true duration:int w:int h:int = DocumentAttribute; static auto secret_to_telegram(secret_api::documentAttributeVideo66 &video) { return make_tl_object( (video.flags_ & secret_api::documentAttributeVideo66::ROUND_MESSAGE_MASK) != 0 @@ -3479,16 +3479,16 @@ static auto telegram_documentAttributeAudio(bool is_voice_note, int duration, st std::move(performer), std::move(waveform)); } -// documentAttributeAudio23 #51448e5 duration:int = DocumentAttribute; +// documentAttributeAudio23 duration:int = DocumentAttribute; static auto secret_to_telegram(secret_api::documentAttributeAudio23 &audio) { return telegram_documentAttributeAudio(false, audio.duration_, "", "", Auto()); } -// documentAttributeAudio45 #ded218e0 duration:int title:string performer:string = DocumentAttribute; +// documentAttributeAudio45 duration:int title:string performer:string = DocumentAttribute; static auto secret_to_telegram(secret_api::documentAttributeAudio45 &audio) { return telegram_documentAttributeAudio(false, audio.duration_, audio.title_, audio.performer_, Auto()); } -// documentAttributeAudio#9852f9c6 flags:# voice:flags.10?true duration:int title:flags.0?string +// documentAttributeAudio flags:# voice:flags.10?true duration:int title:flags.0?string // performer:flags.1?string waveform:flags.2?bytes = DocumentAttribute; static auto secret_to_telegram(secret_api::documentAttributeAudio &audio) { return telegram_documentAttributeAudio((audio.flags_ & secret_api::documentAttributeAudio::VOICE_MASK) != 0, @@ -3506,7 +3506,7 @@ static auto secret_to_telegram(std::vector = DecryptedMessageMedia; static auto secret_to_telegram_document(secret_api::decryptedMessageMediaExternalDocument &from) { if (!clean_input_string(from.mime_type_)) { diff --git a/td/telegram/Photo.cpp b/td/telegram/Photo.cpp index b14b6023f..0a3c6cee8 100644 --- a/td/telegram/Photo.cpp +++ b/td/telegram/Photo.cpp @@ -408,6 +408,8 @@ Variant get_photo_size(FileManager *file_manager, PhotoSizeSo location = std::move(size->location_); res.dimensions = get_dimensions(size->w_, size->h_); res.size = size->sizes_.back(); + size->sizes_.pop_back(); + res.progressive_sizes = std::move(size->sizes_); break; } @@ -567,7 +569,8 @@ static tl_object_ptr get_photo_size_object(FileManager *file_ return td_api::make_object( photo_size->type ? std::string(1, static_cast(photo_size->type)) : std::string(), // TODO replace string type with integer type - file_manager->get_file_object(photo_size->file_id), photo_size->dimensions.width, photo_size->dimensions.height); + file_manager->get_file_object(photo_size->file_id), photo_size->dimensions.width, photo_size->dimensions.height, + vector(photo_size->progressive_sizes)); } static vector> get_photo_sizes_object(FileManager *file_manager, @@ -586,7 +589,8 @@ static vector> get_photo_sizes_object(File } bool operator==(const PhotoSize &lhs, const PhotoSize &rhs) { - return lhs.type == rhs.type && lhs.dimensions == rhs.dimensions && lhs.size == rhs.size && lhs.file_id == rhs.file_id; + return lhs.type == rhs.type && lhs.dimensions == rhs.dimensions && lhs.size == rhs.size && + lhs.file_id == rhs.file_id && lhs.progressive_sizes == rhs.progressive_sizes; } bool operator!=(const PhotoSize &lhs, const PhotoSize &rhs) { @@ -615,7 +619,8 @@ bool operator<(const PhotoSize &lhs, const PhotoSize &rhs) { StringBuilder &operator<<(StringBuilder &string_builder, const PhotoSize &photo_size) { return string_builder << "{type = " << photo_size.type << ", dimensions = " << photo_size.dimensions - << ", size = " << photo_size.size << ", file_id = " << photo_size.file_id << "}"; + << ", size = " << photo_size.size << ", file_id = " << photo_size.file_id + << ", progressive_sizes = " << photo_size.progressive_sizes << "}"; } static tl_object_ptr get_animated_chat_photo_object(FileManager *file_manager, @@ -949,6 +954,15 @@ tl_object_ptr convert_photo_to_profile_photo( } case telegram_api::photoStrippedSize::ID: break; + case telegram_api::photoSizeProgressive::ID: { + auto size = static_cast(size_ptr.get()); + if (size->type_ == "a") { + photo_small = copy_location(size->location_); + } else if (size->type_ == "c") { + photo_big = copy_location(size->location_); + } + break; + } default: UNREACHABLE(); break; diff --git a/td/telegram/Photo.h b/td/telegram/Photo.h index 46a18ce4b..43db9372a 100644 --- a/td/telegram/Photo.h +++ b/td/telegram/Photo.h @@ -48,6 +48,7 @@ struct PhotoSize { Dimensions dimensions; int32 size = 0; FileId file_id; + vector progressive_sizes; }; struct AnimationSize : public PhotoSize { diff --git a/td/telegram/Photo.hpp b/td/telegram/Photo.hpp index 0ffd0a086..911316040 100644 --- a/td/telegram/Photo.hpp +++ b/td/telegram/Photo.hpp @@ -75,6 +75,7 @@ void store(const PhotoSize &photo_size, StorerT &storer) { store(photo_size.dimensions, storer); store(photo_size.size, storer); store(photo_size.file_id, storer); + store(photo_size.progressive_sizes, storer); } template @@ -83,6 +84,11 @@ void parse(PhotoSize &photo_size, ParserT &parser) { parse(photo_size.dimensions, parser); parse(photo_size.size, parser); parse(photo_size.file_id, parser); + if (parser.version() >= static_cast(Version::AddPhotoProgressiveSizes)) { + parse(photo_size.progressive_sizes, parser); + } else { + photo_size.progressive_sizes.clear(); + } LOG(DEBUG) << "Parsed photo size " << photo_size; } diff --git a/td/telegram/Version.h b/td/telegram/Version.h index 9891f0e48..fd62e28a7 100644 --- a/td/telegram/Version.h +++ b/td/telegram/Version.h @@ -39,6 +39,7 @@ enum class Version : int32 { AddDiceEmoji, // 25 AddAnimationStickers, AddDialogPhotoHasAnimation, + AddPhotoProgressiveSizes, Next }; From b90e1bbeaff8699feeb57dee473df1208fb73a67 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 30 Aug 2020 22:12:43 +0300 Subject: [PATCH 35/39] Update layer to 119. GitOrigin-RevId: fdec9a689414746baf67cc15ec279e2516c2765a --- td/generate/scheme/telegram_api.tl | 26 ++++++++++++++------- td/generate/scheme/telegram_api.tlo | Bin 213116 -> 215056 bytes td/telegram/MessagesManager.cpp | 16 +++++++++---- td/telegram/MessagesManager.h | 2 ++ td/telegram/UpdatesManager.cpp | 35 ++++++++++++++++++---------- td/telegram/UpdatesManager.h | 2 ++ td/telegram/Version.h | 2 +- 7 files changed, 57 insertions(+), 26 deletions(-) diff --git a/td/generate/scheme/telegram_api.tl b/td/generate/scheme/telegram_api.tl index af17ed2c4..4e57dd8fc 100644 --- a/td/generate/scheme/telegram_api.tl +++ b/td/generate/scheme/telegram_api.tl @@ -128,7 +128,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto; chatPhoto#d20b9f3c flags:# has_video:flags.0?true photo_small:FileLocation photo_big:FileLocation dc_id:int = ChatPhoto; messageEmpty#83e5de54 id:int = Message; -message#f52e6b7f flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector views:flags.10?int forwards:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector = Message; +message#8a7e027d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int reply_to_top_id:flags.24?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector = Message; messageService#9e19a1f6 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?int to_id:Peer reply_to_msg_id:flags.3?int date:int action:MessageAction = Message; messageMediaEmpty#3ded6320 = MessageMedia; @@ -347,6 +347,7 @@ updateDialogFilters#3504914f = Update; updatePhoneCallSignalingData#2661bf09 phone_call_id:long data:bytes = Update; updateChannelParticipant#65d2b464 flags:# channel_id:int date:int user_id:int prev_participant:flags.0?ChannelParticipant new_participant:flags.1?ChannelParticipant qts:int = Update; updateChannelMessageForwards#6e8a84df channel_id:int id:int forwards:int = Update; +updateReadDiscussion#119fb587 peer:Peer msg_id:int read_max_id:int = Update; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; @@ -1139,10 +1140,6 @@ stats.megagroupStats#ef7ff916 period:StatsDateRangeDays members:StatsAbsValueAnd globalPrivacySettings#bea2f424 flags:# archive_and_mute_new_noncontact_peers:flags.0?Bool = GlobalPrivacySettings; -messageViews#6d24f493 views:int forwards:int = MessageViews; - -stats.messageStats#8999f295 views_graph:StatsGraph = stats.MessageStats; - help.countryCode#4203c5ef flags:# country_code:string prefixes:flags.0?Vector patterns:flags.1?Vector = help.CountryCode; help.country#c3878e23 flags:# hidden:flags.0?true iso2:string default_name:string name:flags.1?string country_codes:Vector = help.Country; @@ -1150,6 +1147,16 @@ help.country#c3878e23 flags:# hidden:flags.0?true iso2:string default_name:strin help.countriesListNotModified#93cc1f32 = help.CountriesList; help.countriesList#87d0759e countries:Vector hash:int = help.CountriesList; +messageReplies#82e3c815 flags:# comments:flags.0?true replies:int replies_pts:int recent_repliers:flags.1?Vector channel_id:flags.0?int = MessageReplies; + +messageViews#455b853d flags:# views:flags.0?int forwards:flags.1?int replies:flags.2?MessageReplies = MessageViews; + +messages.messageViews#2c3f2ae2 views:Vector users:Vector = messages.MessageViews; + +stats.messageStats#8999f295 views_graph:StatsGraph = stats.MessageStats; + +messages.discussionMessage#d25fad90 message:Message read_max_id:int chats:Vector users:Vector = messages.DiscussionMessage; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -1274,7 +1281,7 @@ contacts.getLocated#d348bc44 flags:# background:flags.1?true geo_point:InputGeoP messages.getMessages#63c66506 id:Vector = messages.Messages; messages.getDialogs#a0ee3b73 flags:# exclude_pinned:flags.0?true folder_id:flags.1?int offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:int = messages.Dialogs; messages.getHistory#dcbb8260 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages; -messages.search#8614ef68 flags:# peer:InputPeer q:string from_id:flags.0?InputUser filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages; +messages.search#4e17810b flags:# peer:InputPeer q:string from_id:flags.0?InputUser top_msg_id:flags.1?int filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages; messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages; messages.deleteHistory#1c015b09 flags:# just_clear:flags.0?true revoke:flags.1?true peer:InputPeer max_id:int = messages.AffectedHistory; messages.deleteMessages#e58e95d2 flags:# revoke:flags.0?true id:Vector = messages.AffectedMessages; @@ -1315,10 +1322,10 @@ messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet messages.installStickerSet#c78fe460 stickerset:InputStickerSet archived:Bool = messages.StickerSetInstallResult; messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool; messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_param:string = Updates; -messages.getMessagesViews#fdac5dba peer:InputPeer id:Vector increment:Bool = Vector; +messages.getMessagesViews#5784d3e1 peer:InputPeer id:Vector increment:Bool = messages.MessageViews; messages.editChatAdmin#a9e69f2e chat_id:int user_id:InputUser is_admin:Bool = Bool; messages.migrateChat#15a3b8e3 chat_id:int = Updates; -messages.searchGlobal#734dd16d flags:# folder_id:flags.0?int q:string filter:MessagesFilter offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages; +messages.searchGlobal#4bc6589a flags:# folder_id:flags.0?int q:string filter:MessagesFilter min_date:int max_date:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages; messages.reorderStickerSets#78337739 flags:# masks:flags.0?true order:Vector = Bool; messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document; messages.getSavedGifs#83bf3d52 hash:int = messages.SavedGifs; @@ -1394,6 +1401,9 @@ messages.getSuggestedDialogFilters#a29cd42c = Vector; messages.updateDialogFilter#1ad4a04a flags:# id:int filter:flags.0?DialogFilter = Bool; messages.updateDialogFiltersOrder#c563c1e4 order:Vector = Bool; messages.getOldFeaturedStickers#5fe7025b offset:int limit:int hash:int = messages.FeaturedStickers; +messages.getReplies#fda52fdc peer:InputPeer msg_id:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages; +messages.getDiscussionMessage#446972fd peer:InputPeer msg_id:int = messages.DiscussionMessage; +messages.readDiscussion#f731a9f4 peer:InputPeer msg_id:int read_max_id:int = Bool; updates.getState#edd4882a = updates.State; updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference; diff --git a/td/generate/scheme/telegram_api.tlo b/td/generate/scheme/telegram_api.tlo index d8d4c7c1bd133aab24077c0d8bb0d3b48e00bc4a..5fd375dff2dc75a97527c6e71b7d3afe1ce45125 100644 GIT binary patch delta 3677 zcmaJ^eNa@_73bW2nB_|z4ThzxW!tWC8#m!GG8s&;!MK?+>6%$>G-hPN5_Str7hTwO zBpK47)+S8HPO+EakcLz`lg?;s4RO^+%8H9pLk-bY@Dr5PForhRp`El%XRy=z_P)C; z8HIm%?|lBw@0@$z*}2xN_V%o-+wT-Tm7@QZe2}#(SDJidH-_4BOX1;V!=LV6y1^R= zRM&bpdHue6Z(!g4d>UD1m)8Dl+jF7WWx>p>f4?c`F4^q&R0q8&FNPYwm6ui6{>Q3| zUvJ=kfhQdGftsCxK>d#GdMFkn)K*ju`L`c?#=b0Jr)#&=dw0>_rWb^Um7Y}iL8$)8 zz$0-?H0BKQhpihdsT#@@y7Bo!+P%R!{}#%8p-W179o`gHxl`*k`--@eUhJiBq*uN{ ze*E)?bO4&}+L^C8%{1p(JHDL_=hd+c@B_-9LV9*^hrg=cLv&vgHXeggJkbX$JFgHU zc4WcC@`su@MZzeL85`HWIjFIig5ISt9tVPsY_RaB=qsS8UD*(Y_`B-Mfw@9coOK

zHJTIwK~$~%PgJeb)wF(zU6W}6)dQjdzRM(Ia3;xHdK1BVp_Ip%>P?D4{cU;( z_Xl7}(~xLWA<@QdHhjF7e2=z!S^4h}Gk3NgSzvYHt@YS`1e{zMI|6q8B!`5|9TKwk z5GY(b6w(pkOh^z>epJ}`k3x{!O*2^nQYsEkfsNj+D5Slwm1Fd>s4RL+_hhyExnuCS z&MI~thYBv6I-XQETFgYIZ5wmB&aH}I<-Z3r9#El7N1*Dlsk>Ieiawa-^0E&_0{4gD z=CUCnqgrofM~Q@c_XxAHKj|4*pkjJ&|0;|;Ml2ZZ2TNxJ9G!r|<8_{)2^rrh1SQ8e2jZYd1aOxE3-I+U; zT+-Ilg7ENZu$sigYG+Rzy!dJR@-$c;tW}0YJ=!&czZil)@B+&IEQpFeWhmCh4WmQg zpkarZ`X-HNJ|pywGosY{5jM@ViINCzjKO;9uQT!_zK=w9%LNGPqc9HUU#*eQIShNa z)!48|b-x7uzv#y)KANrz45M#SM%!8F;O>#LBFW5Ic#+E-AB&J|(Cyfjc#V7v_6M^i zjezaJTF1y@Ot*|I)}=lcnL}eUq+nebJp8rg6M@w7P1c8lTe7j+2PT~RMBEszbGil9 zCcXV6yXNI{%p!b`eWE7LiR;dE9&Cw501m!QR`CqY=aV{Qz`>7T6-LtxGP=)0CiP#I zaO4qU?2NKYJ3dgBsDSE>LJybCM)es`StHAV3q2Q;PZ;KGCMz=+jArDbh%|E%O1P7C zR2=V$Q6Xy`U5vUgvr804@YV^2zc&IU^JC^2Tg<;_43w|<)65|IR$dYnmtN9w#u*-2 z%Xsa+1P%^(N+?mjoVe`8rA%Y5+p&ER%+&R+c^=T*WzjOrGsU?13jB!28oDAr4ayd< zQ`@U1s%*+d*Hyt&%T+NA?_Gtx+^OW6ki}>D&_BVlkmjQagVq_MVCHpkp;)i$U851F z*_6B`Eof8Qb%BZ}c$U~u9v4Au?7SxE1N_G>l82szwq-mC+~aunF8MY`{UuX8_$ZZ3 zh>G14;u@Hq5TWE7(9EOky&>%SZs-l^yt!E5vYVn7|4rD+gN)o1G-w|;`y@Dd#W0$ zo9VvE!gvyOC+q%_quQS`fe4<~!-%Rc(=5QWMy3;O;=-lNgiQnBGPvRZAMB^7CwFAf&} zCokcp^=cmJ?%NqFX!)cwZN7(WywJU!$ZGVzL`gSg{3P#%?1Xo~TisMs_sinH9;Av} zLI2;`0_I!7maLXX*=M6$GRVes?T1f8pqBP*v#N(Ag9D^rZ$0yU{36w0fpmId|4W)j U8IDMX3iRJ1Mzwc|VPwt!0g@m}wEzGB delta 2874 zcmai0e@v8R9OwJoU4h=|Wv8-yjkmletwWEbB8T%DWK^g)&9TG05@pa4QHQge|7I5Hu;t8i6Bno&SC@AQut+3d)uI`4zJ!2C6gkn#W-=s zn!L%K_xPH_dhXJ(epKf8z=-XID2*1^(6ciNKP_AG`;*&C%FBzlmZ-Xst~q(n$UA02 z8AG!Vo|DsN!A!uS*$|47V1^mQBtn`{LH>`kDp3Y(ys%f_3)%2(!Q$mgpq&4hC|gNw`bUXt0pkjZ6E zZ=7wKl(c^lmydh37|?zUY?9ECBjslsFv-Ifb3j820YWWM%VnjlV2kC()ZDP873>!(uAMq!YX>(c4z$M+>k!hEAu@Ilb3q3sI@y0qfLI&> z*sHMwD1xE_s;Y1nQez=Me)RkbM5kmW9X*_m;u)p$ji*KQ^nxgb_8IWN8OWBxza{C^ zF&#b^*KIw1b_G7b#&e+bv7KV{eHRB&Jhr_g1v~;4z6e5$rZ7n8njj65wUavJ`iqI^ z>;wx>tE!VyZS16i<#d5HnL42!{+-!R*b-OlI~zSrm0ciCt@U*gpX+5v$IU&EjqVF< z2Cg~}%kjwf6h=^4QC%eSCNT#3oX6F3{?SAqbE;k4l&7bgX5xOg=3W*rK&CcXg%`p4 zKW%z&kxq~@k#@|#06FOCf#W=w++Ipb@nlE$A8fMPJ-u2=hfdf~?4$g0`@lAJm1_DR zb!u%--*gq$Uz)Bvj!P7(^Aa^*AJU?dLT}imzyUKlLr}_78zx;{KOEsAPrpVX+kbYvhN!+TTRB{|u?xt)nb!<;XAK%jYkl@CsIq87o+Q zY&#+QS2CvoLvJz-V;0zMtbCi9v0)XP;J`_lHJ61aWnU{eh;HkaunKg4#H_OLE^{v6 z5J#!v&a#zQ!rK^spva1%fZL&1#`xcj7;3m}OfGxMn9Ts2`;3L9_bmHnYcIO;CFLc>J3lNv zn11&g^|fY_){WZm%R!ccS@ldn=VC}k|4f}3_pa2Lcontacts_manager_->on_get_users(std::move(result->users_), "GetMessagesViewsQuery"); + auto interaction_infos = std::move(result->views_); if (message_ids_.size() != interaction_infos.size()) { return on_error(id, Status::Error(500, "Wrong number of message views returned")); } for (size_t i = 0; i < message_ids_.size(); i++) { - td->messages_manager_->on_update_message_interaction_info( - {dialog_id_, message_ids_[i]}, interaction_infos[i]->views_, interaction_infos[i]->forwards_); + const auto *info = interaction_infos[i].get(); + auto flags = info->flags_; + auto view_count = (flags & telegram_api::messageViews::VIEWS_MASK) != 0 ? info->views_ : 0; + auto forward_count = (flags & telegram_api::messageViews::FORWARDS_MASK) != 0 ? info->forwards_ : 0; + td->messages_manager_->on_update_message_interaction_info({dialog_id_, message_ids_[i]}, view_count, + forward_count); } } @@ -1611,7 +1617,7 @@ class SearchMessagesQuery : public Td::ResultHandler { } send_query(G()->net_query_creator().create(telegram_api::messages_search( - flags, std::move(input_peer), query, std::move(sender_input_user), get_input_messages_filter(filter), 0, + flags, std::move(input_peer), query, std::move(sender_input_user), 0, get_input_messages_filter(filter), 0, std::numeric_limits::max(), from_message_id.get_server_message_id().get(), offset, limit, std::numeric_limits::max(), 0, 0))); } @@ -1674,7 +1680,7 @@ class SearchMessagesGlobalQuery : public Td::ResultHandler { flags |= telegram_api::messages_searchGlobal::FOLDER_ID_MASK; } send_query(G()->net_query_creator().create(telegram_api::messages_searchGlobal( - flags, folder_id.get(), query, get_input_messages_filter(filter), offset_date_, std::move(input_peer), + flags, folder_id.get(), query, get_input_messages_filter(filter), 0, 0, offset_date_, std::move(input_peer), offset_message_id.get_server_message_id().get(), limit))); } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index b42b17ae5..553333eed 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -163,6 +163,8 @@ class MessagesManager : public Actor { static constexpr int32 MESSAGE_FLAG_IS_LEGACY = 1 << 19; static constexpr int32 MESSAGE_FLAG_HIDE_EDIT_DATE = 1 << 21; static constexpr int32 MESSAGE_FLAG_IS_RESTRICTED = 1 << 22; + static constexpr int32 MESSAGE_FLAG_HAS_REPLY_INFO = 1 << 23; + static constexpr int32 MESSAGE_FLAG_HAS_RECENT_REPLIERS = 1 << 24; static constexpr int32 SEND_MESSAGE_FLAG_IS_REPLY = 1 << 0; static constexpr int32 SEND_MESSAGE_FLAG_DISABLE_WEB_PAGE_PREVIEW = 1 << 1; diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 954a229c8..a3f7f5c00 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -506,6 +506,14 @@ bool UpdatesManager::is_acceptable_message(const telegram_api::Message *message_ CHECK(message->media_ == nullptr); } + if (message->replies_ != nullptr) { + for (auto &user_id : message->replies_->recent_repliers_) { + if (!is_acceptable_user(UserId(user_id))) { + return false; + } + } + } + break; } case telegram_api::messageService::ID: { @@ -695,8 +703,8 @@ void UpdatesManager::on_get_updates(tl_object_ptr &&updat update->flags_, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, update->id_, from_id, make_tl_object(update->user_id_), std::move(update->fwd_from_), - update->via_bot_id_, update->reply_to_msg_id_, update->date_, update->message_, nullptr, nullptr, - std::move(update->entities_), 0, 0, 0, "", 0, Auto()), + update->via_bot_id_, update->reply_to_msg_id_, 0, update->date_, update->message_, nullptr, nullptr, + std::move(update->entities_), 0, 0, nullptr, 0, string(), 0, Auto()), update->pts_, update->pts_count_), 0, "telegram_api::updatesShortMessage"); break; @@ -713,16 +721,16 @@ void UpdatesManager::on_get_updates(tl_object_ptr &&updat } update->flags_ |= MessagesManager::MESSAGE_FLAG_HAS_FROM_ID; - on_pending_update( - make_tl_object( - make_tl_object( - update->flags_, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, - false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, update->id_, - update->from_id_, make_tl_object(update->chat_id_), - std::move(update->fwd_from_), update->via_bot_id_, update->reply_to_msg_id_, update->date_, - update->message_, nullptr, nullptr, std::move(update->entities_), 0, 0, 0, "", 0, Auto()), - update->pts_, update->pts_count_), - 0, "telegram_api::updatesShortChatMessage"); + on_pending_update(make_tl_object( + make_tl_object( + update->flags_, false /*ignored*/, false /*ignored*/, false /*ignored*/, + false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, + false /*ignored*/, update->id_, update->from_id_, + make_tl_object(update->chat_id_), std::move(update->fwd_from_), + update->via_bot_id_, update->reply_to_msg_id_, 0, update->date_, update->message_, + nullptr, nullptr, std::move(update->entities_), 0, 0, nullptr, 0, string(), 0, Auto()), + update->pts_, update->pts_count_), + 0, "telegram_api::updatesShortChatMessage"); break; } case telegram_api::updateShort::ID: { @@ -2186,4 +2194,7 @@ void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { } +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +} + } // namespace td diff --git a/td/telegram/UpdatesManager.h b/td/telegram/UpdatesManager.h index a0c931705..45c4978e3 100644 --- a/td/telegram/UpdatesManager.h +++ b/td/telegram/UpdatesManager.h @@ -315,6 +315,8 @@ class UpdatesManager : public Actor { // unsupported updates void on_update(tl_object_ptr update, bool /*force_apply*/); + + void on_update(tl_object_ptr update, bool /*force_apply*/); }; } // namespace td diff --git a/td/telegram/Version.h b/td/telegram/Version.h index fd62e28a7..25fa03756 100644 --- a/td/telegram/Version.h +++ b/td/telegram/Version.h @@ -8,7 +8,7 @@ namespace td { -constexpr int32 MTPROTO_LAYER = 118; +constexpr int32 MTPROTO_LAYER = 119; enum class Version : int32 { Initial, // 0 From ed782145bf20393a309265092868bb24b0073592 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 31 Aug 2020 13:42:27 +0300 Subject: [PATCH 36/39] Add reply_count and recent_replier_user_ids to MessageIntercationInfo. GitOrigin-RevId: 48bae463c091d3d29e3096ebb4c2fbbbeda38dfd --- td/generate/scheme/td_api.tl | 15 +++-- td/generate/scheme/td_api.tlo | Bin 180784 -> 180928 bytes td/telegram/ContactsManager.cpp | 15 ++++- td/telegram/ContactsManager.h | 2 + td/telegram/MessagesManager.cpp | 108 ++++++++++++++++++++++++------- td/telegram/MessagesManager.h | 110 +++++++++++++++++++++++++++++++- td/telegram/UpdatesManager.cpp | 3 + 7 files changed, 221 insertions(+), 32 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 5c300e5a5..bf56ef850 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -578,7 +578,7 @@ supergroup id:int32 username:string date:int32 status:ChatMemberStatus member_co //@can_set_username True, if the chat username can be changed //@can_set_sticker_set True, if the supergroup sticker set can be changed //@can_set_location True, if the supergroup location can be changed -//@can_get_statistics True, if the supergroup or channel statistics is available +//@can_get_statistics True, if the supergroup or channel statistics are available //@is_all_history_available True, if new chat members will have access to old messages. In public or discussion groups and both public and private channels, old messages are always available, so this option affects only private supergroups without a linked chat. The value of this field is only available for chat administrators //@sticker_set_id Identifier of the supergroup sticker set; 0 if none //@location Location to which the supergroup is connected; may be null @@ -638,7 +638,9 @@ messageForwardInfo origin:MessageForwardOrigin date:int32 public_service_announc //@description Contains information about interactions with a message //@view_count Number of times the message was viewed //@forward_count Number of times the message was forwarded -messageInteractionInfo view_count:int32 forward_count:int32 = MessageInteractionInfo; +//@reply_count Number of times the message was directly or indirectly replied; supergroups and linked channels only +//@recent_replier_user_ids User identifiers of the recent repliers to the message +messageInteractionInfo view_count:int32 forward_count:int32 reply_count:int32 recent_replier_user_ids:vector = MessageInteractionInfo; //@class MessageSendingState @description Contains information about the sending state of the message @@ -662,7 +664,8 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool r //@can_be_forwarded True, if the message can be forwarded //@can_be_deleted_only_for_self True, if the message can be deleted only for the current user while other users will continue to see it //@can_be_deleted_for_all_users True, if the message can be deleted for all users -//@can_get_statistics True, if the message statistics is available +//@can_get_statistics True, if the message statistics are available +//@can_get_replies True, if the message replies are available //@is_channel_post True, if the message is a channel post. All messages to channels are channel posts, all other messages are not channel posts //@contains_unread_mention True, if the message contains an unread mention for the current user //@date Point in time (Unix timestamp) when the message was sent @@ -678,7 +681,7 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool r //@restriction_reason If non-empty, contains a human-readable description of the reason why access to this message must be restricted //@content Content of the message //@reply_markup Reply markup for the message; may be null -message id:int53 sender_user_id:int32 chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_get_statistics:Bool is_channel_post:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo interaction_info:messageInteractionInfo reply_to_message_id:int53 ttl:int32 ttl_expires_in:double via_bot_user_id:int32 author_signature:string media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message; +message id:int53 sender_user_id:int32 chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_get_statistics:Bool can_get_replies:Bool is_channel_post:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo interaction_info:messageInteractionInfo reply_to_message_id:int53 ttl:int32 ttl_expires_in:double via_bot_user_id:int32 author_signature:string media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message; //@description Contains a list of messages @total_count Approximate total count of messages found @messages List of messages; messages may be null messages total_count:int32 messages:vector = Messages; @@ -2829,7 +2832,7 @@ networkStatisticsEntryFile file_type:FileType network_type:NetworkType sent_byte //@sent_bytes Total number of bytes sent @received_bytes Total number of bytes received @duration Total call duration, in seconds networkStatisticsEntryCall network_type:NetworkType sent_bytes:int53 received_bytes:int53 duration:double = NetworkStatisticsEntry; -//@description A full list of available network statistic entries @since_date Point in time (Unix timestamp) from which the statistics is collected @entries Network statistics entries +//@description A full list of available network statistic entries @since_date Point in time (Unix timestamp) from which the statistics are collected @entries Network statistics entries networkStatistics since_date:int32 entries:vector = NetworkStatistics; @@ -4500,7 +4503,7 @@ removeChatActionBar chat_id:int53 = Ok; reportChat chat_id:int53 reason:ChatReportReason message_ids:vector = Ok; -//@description Returns an HTTP URL with the chat statistics. Currently this method of getting the statistics is disabled and can be deleted in the future @chat_id Chat identifier @parameters Parameters from "tg://statsrefresh?params=******" link @is_dark Pass true if a URL with the dark theme must be returned +//@description Returns an HTTP URL with the chat statistics. Currently this method of getting the statistics are disabled and can be deleted in the future @chat_id Chat identifier @parameters Parameters from "tg://statsrefresh?params=******" link @is_dark Pass true if a URL with the dark theme must be returned getChatStatisticsUrl chat_id:int53 parameters:string is_dark:Bool = HttpUrl; //@description Returns detailed statistics about a chat. Currently this method can be used only for supergroups and channels. Can be used only if SupergroupFullInfo.can_get_statistics == true @chat_id Chat identifier @is_dark Pass true if a dark theme is used by the application diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 5864e0a4d50a49e819face70f17cf217a285acce..dbfff2331cd4380dac95e940aec93834f3d0c2a9 100644 GIT binary patch delta 760 zcmdnc!hN8XdqajK%g6H(mnY{)K4AHARViw7fYcTnu+V0Xa1U;XWJr<%D@YaN9I=~IoOL*3vx13izjbrketrT#dsg=yzL*j7z-G|W^Pa6VRVrI zi%wso!YIKBaz4l;mdOwM{3m~S%*qNfqH^-OzjD0dMXAZDc_r~+L#M}zGg?D5YN#@{ zKup`9%D9Ia!Yt5a)Zl=4ak`^1qx|+ghKvr~V7X~~8Q*{z(?9Hm>IAV2raP!GvTk3y zk1?GIY%oxr!gh;;jDMg;S{!A3;tbKKz{&IkVh;xw(-BpO;01lAIS^KX0h0z?tYWgx zd4=h7mNRicgd7Z+RFEVaPMSb?5=Jmh2Ai2`AYw<1n66+^yWPix=?gDdVzNN3&h!E& zsFB-eI5DL_f_9nfv^<9n0}y%Z7&IDYJsGd>2QVHLz0u0I}Gq%_CGreH~Gr`se6fj9lc5s0BZ~LA}Oezp3OkZHfq%&P$3ey1XLA>)=B4-|QqXi@sOn5tn98&QV#}GSOdI&Y%;^nFneIRY6P7VukOlzS CY*g|9 delta 728 zcmX@m%Dth5dqajKOYslGx07=uAFxOsI3m0`Kx&H(SZFgxxCb{xG9*cX6{L!Ba$~Ce z9Jq%+wdievMGwJuSjAhXzWQ;Ule(^En0o5zHF zq$VeB6W;E_!FZ5yx+xdqeXwh`OK>w5FoKQP-owM_BB2U$qZm}HXI@EaQDSmQW`3S$ zURpi_NDgEa)8vPJ;b8sKcc?P9K(srkG45doGq-6mYH&b&F#V!2qx^OsBSwdAh&w0j zWqbo+HSB}xoDO6eOxwrEy4`j^V>%PWT%bCI?I#X0{(%^|{lrnmC(aO!8#tMsfLYsT za4{WGg$O1XFwFt8rWrD6z=bL%>zr4ZuCs!P10r<6kVyqevf-o>x*7rs=?DrW%M? zh%wU@ENZvkF=6_`3znEHP^&Y|8EWEo4QHklNJvhf;KF18R2L62o-3!tGCznO0~+R8Ht;ssOXL^GslR!vto6?4KUM%_uS1!2#mI z?LL#4RG^M9uxHYlzF-Q|0ToaRV1R_##rsbYQ6JOy4k-X$8cV Ym}yKK_`%HS0?U~0Km0F{+8YXATM diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index d4c9a013c..1e3f0b054 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -2876,7 +2876,8 @@ class GetBroadcastStatsQuery : public Td::ResultHandler { auto result = ContactsManager::convert_broadcast_stats(result_ptr.move_as_ok()); for (auto &info : result->recent_message_interactions_) { td->messages_manager_->on_update_message_interaction_info({DialogId(channel_id_), MessageId(info->message_id_)}, - info->view_count_, info->forward_count_); + info->view_count_, info->forward_count_, false, + nullptr); } promise_.set_value(std::move(result)); } @@ -13008,6 +13009,18 @@ bool ContactsManager::get_channel_sign_messages(const Channel *c) { return c->sign_messages; } +bool ContactsManager::get_channel_has_linked_channel(ChannelId channel_id) const { + auto c = get_channel(channel_id); + if (c == nullptr) { + return false; + } + return get_channel_has_linked_channel(c); +} + +bool ContactsManager::get_channel_has_linked_channel(const Channel *c) { + return c->has_linked_channel; +} + int32 ContactsManager::get_channel_slow_mode_delay(ChannelId channel_id) { auto channel_full = get_channel_full_force(channel_id, "get_channel_slow_mode_delay"); if (channel_full == nullptr) { diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index e93fe36d7..3c649d881 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -492,6 +492,7 @@ class ContactsManager : public Actor { DialogParticipantStatus get_channel_permissions(ChannelId channel_id) const; int32 get_channel_participant_count(ChannelId channel_id) const; bool get_channel_sign_messages(ChannelId channel_id) const; + bool get_channel_has_linked_channel(ChannelId channel_id) const; int32 get_channel_slow_mode_delay(ChannelId channel_id); std::pair> search_among_users(const vector &user_ids, const string &query, int32 limit); @@ -1124,6 +1125,7 @@ class ContactsManager : public Actor { static DialogParticipantStatus get_channel_status(const Channel *c); DialogParticipantStatus get_channel_permissions(const Channel *c) const; static bool get_channel_sign_messages(const Channel *c); + static bool get_channel_has_linked_channel(const Channel *c); void set_my_id(UserId my_id); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 8b778753d..46b1c6d4b 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -1281,18 +1281,22 @@ class GetMessagesViewsQuery : public Td::ResultHandler { } auto result = result_ptr.move_as_ok(); - td->contacts_manager_->on_get_users(std::move(result->users_), "GetMessagesViewsQuery"); + if (!td->auth_manager_->is_bot()) { + td->contacts_manager_->on_get_users(std::move(result->users_), "GetMessagesViewsQuery"); + } auto interaction_infos = std::move(result->views_); if (message_ids_.size() != interaction_infos.size()) { return on_error(id, Status::Error(500, "Wrong number of message views returned")); } for (size_t i = 0; i < message_ids_.size(); i++) { - const auto *info = interaction_infos[i].get(); + FullMessageId full_message_id{dialog_id_, message_ids_[i]}; + + auto *info = interaction_infos[i].get(); auto flags = info->flags_; auto view_count = (flags & telegram_api::messageViews::VIEWS_MASK) != 0 ? info->views_ : 0; auto forward_count = (flags & telegram_api::messageViews::FORWARDS_MASK) != 0 ? info->forwards_ : 0; - td->messages_manager_->on_update_message_interaction_info({dialog_id_, message_ids_[i]}, view_count, - forward_count); + td->messages_manager_->on_update_message_interaction_info(full_message_id, view_count, forward_count, true, + std::move(info->replies_)); } } @@ -4179,6 +4183,7 @@ void MessagesManager::Message::store(StorerT &storer) const { bool has_restriction_reasons = !restriction_reasons.empty(); bool has_forward_psa_type = is_forwarded && !forward_info->psa_type.empty(); bool has_forward_count = forward_count > 0; + bool has_reply_info = !reply_info.is_empty(); BEGIN_STORE_FLAGS(); STORE_FLAG(is_channel_post); STORE_FLAG(is_outgoing); @@ -4228,6 +4233,7 @@ void MessagesManager::Message::store(StorerT &storer) const { STORE_FLAG(is_copy); STORE_FLAG(has_forward_psa_type); STORE_FLAG(has_forward_count); + STORE_FLAG(has_reply_info); END_STORE_FLAGS(); } @@ -4283,6 +4289,9 @@ void MessagesManager::Message::store(StorerT &storer) const { if (has_forward_count) { store(forward_count, storer); } + if (has_reply_info) { + store(reply_info, storer); + } if (has_ttl) { store(ttl, storer); store_time(ttl_expires_at, storer); @@ -4343,6 +4352,7 @@ void MessagesManager::Message::parse(ParserT &parser) { bool has_restriction_reasons = false; bool has_forward_psa_type = false; bool has_forward_count = false; + bool has_reply_info = false; BEGIN_PARSE_FLAGS(); PARSE_FLAG(is_channel_post); PARSE_FLAG(is_outgoing); @@ -4392,6 +4402,7 @@ void MessagesManager::Message::parse(ParserT &parser) { PARSE_FLAG(is_copy); PARSE_FLAG(has_forward_psa_type); PARSE_FLAG(has_forward_count); + PARSE_FLAG(has_reply_info); END_PARSE_FLAGS(); } @@ -4453,6 +4464,9 @@ void MessagesManager::Message::parse(ParserT &parser) { if (has_forward_count) { parse(forward_count, parser); } + if (has_reply_info) { + parse(reply_info, parser); + } if (has_ttl) { parse(ttl, parser); parse_time(ttl_expires_at, parser); @@ -6005,7 +6019,7 @@ void MessagesManager::on_update_message_view_count(FullMessageId full_message_id LOG(ERROR) << "Receive " << view_count << " views in updateChannelMessageViews for " << full_message_id; return; } - update_message_interaction_info(full_message_id, view_count, -1); + update_message_interaction_info(full_message_id, view_count, -1, false, nullptr); } void MessagesManager::on_update_message_forward_count(FullMessageId full_message_id, int32 forward_count) { @@ -6013,16 +6027,17 @@ void MessagesManager::on_update_message_forward_count(FullMessageId full_message LOG(ERROR) << "Receive " << forward_count << " forwards in updateChannelMessageForwards for " << full_message_id; return; } - update_message_interaction_info(full_message_id, -1, forward_count); + update_message_interaction_info(full_message_id, -1, forward_count, false, nullptr); } void MessagesManager::on_update_message_interaction_info(FullMessageId full_message_id, int32 view_count, - int32 forward_count) { + int32 forward_count, bool has_reply_info, + tl_object_ptr &&reply_info) { if (view_count < 0 || forward_count < 0) { LOG(ERROR) << "Receive " << view_count << "/" << forward_count << " interaction counters for " << full_message_id; return; } - update_message_interaction_info(full_message_id, view_count, forward_count); + update_message_interaction_info(full_message_id, view_count, forward_count, has_reply_info, std::move(reply_info)); } void MessagesManager::on_pending_message_views_timeout(DialogId dialog_id) { @@ -6051,7 +6066,8 @@ void MessagesManager::on_pending_message_views_timeout(DialogId dialog_id) { } void MessagesManager::update_message_interaction_info(FullMessageId full_message_id, int32 view_count, - int32 forward_count) { + int32 forward_count, bool has_reply_info, + tl_object_ptr &&reply_info) { auto dialog_id = full_message_id.get_dialog_id(); Dialog *d = get_dialog_force(dialog_id); if (d == nullptr) { @@ -6068,15 +6084,27 @@ void MessagesManager::update_message_interaction_info(FullMessageId full_message return; } - if (update_message_interaction_info(dialog_id, m, view_count >= 0 ? view_count : m->view_count, - forward_count >= 0 ? forward_count : m->forward_count)) { - on_message_changed(d, m, true, "on_update_message_view_count"); + if (view_count < 0) { + view_count = m->view_count; + } + if (forward_count < 0) { + forward_count = m->forward_count; + } + bool is_empty_reply_info = reply_info == nullptr; + MessageReplyInfo new_reply_info(std::move(reply_info), td_->auth_manager_->is_bot()); + if (new_reply_info.is_empty() && !is_empty_reply_info) { + has_reply_info = false; + } + + if (update_message_interaction_info(dialog_id, m, view_count, forward_count, has_reply_info, + std::move(new_reply_info))) { + on_message_changed(d, m, true, "update_message_interaction_info"); } } td_api::object_ptr MessagesManager::get_message_interaction_info_object( DialogId dialog_id, const Message *m) const { - if (m->view_count == 0 && m->forward_count == 0) { + if (m->view_count == 0 && m->forward_count == 0 && m->reply_info.is_empty()) { return nullptr; } if (m->message_id.is_scheduled() && (m->forward_info == nullptr || is_broadcast_channel(dialog_id))) { @@ -6086,21 +6114,30 @@ td_api::object_ptr MessagesManager::get_message_ return nullptr; } - return td_api::make_object(m->view_count, m->forward_count); + return td_api::make_object( + m->view_count, m->forward_count, m->reply_info.reply_count, + td_->contacts_manager_->get_user_ids_object(m->reply_info.recent_replier_user_ids, + "get_message_interaction_info_object")); } bool MessagesManager::update_message_interaction_info(DialogId dialog_id, Message *m, int32 view_count, - int32 forward_count) { + int32 forward_count, bool has_reply_info, + MessageReplyInfo &&reply_info) { CHECK(m != nullptr); - if (view_count > m->view_count || forward_count > m->forward_count) { + bool need_update_reply_info = has_reply_info && m->reply_info.need_update_to(reply_info); + if (view_count > m->view_count || forward_count > m->forward_count || need_update_reply_info) { LOG(DEBUG) << "Update interaction info of " << FullMessageId{dialog_id, m->message_id} << " from " << m->view_count - << '/' << m->forward_count << " to " << view_count << '/' << forward_count; + << '/' << m->forward_count << "/" << m->reply_info << " to " << view_count << '/' << forward_count << "/" + << reply_info; if (view_count > m->view_count) { m->view_count = view_count; } if (forward_count > m->forward_count) { m->forward_count = forward_count; } + if (need_update_reply_info) { + m->reply_info = std::move(reply_info); + } send_closure(G()->td(), &Td::send_update, make_tl_object( dialog_id.get(), m->message_id.get(), get_message_interaction_info_object(dialog_id, m))); @@ -11979,6 +12016,9 @@ MessagesManager::MessageInfo MessagesManager::parse_telegram_api_message( message_info.view_count = message->views_; message_info.forward_count = message->forwards_; } + if (message->flags_ & MESSAGE_FLAG_HAS_REPLY_INFO) { + message_info.reply_info = std::move(message->replies_); + } if (message->flags_ & MESSAGE_FLAG_HAS_EDIT_DATE) { message_info.edit_date = message->edit_date_; } @@ -12155,6 +12195,7 @@ std::pair> MessagesManager::creat LOG(ERROR) << "Wrong forward_count = " << forward_count << " received in " << message_id << " in " << dialog_id; forward_count = 0; } + MessageReplyInfo reply_info(std::move(message_info.reply_info), td_->auth_manager_->is_bot()); bool has_forward_info = message_info.forward_header != nullptr; @@ -12187,6 +12228,7 @@ std::pair> MessagesManager::creat message->is_from_scheduled = is_from_scheduled; message->view_count = view_count; message->forward_count = forward_count; + message->reply_info = std::move(reply_info); message->legacy_layer = (is_legacy ? MTPROTO_LAYER : 0); message->content = std::move(message_info.content); message->reply_markup = get_reply_markup(std::move(message_info.reply_markup), td_->auth_manager_->is_bot(), false, @@ -20246,6 +20288,7 @@ tl_object_ptr MessagesManager::get_message_object(DialogId dial bool can_be_edited = for_event_log ? false : can_edit_message(dialog_id, m, false, td_->auth_manager_->is_bot()); bool can_be_forwarded = for_event_log ? false : can_forward_message(dialog_id, m); bool can_get_statistics = for_event_log ? false : can_get_message_statistics(dialog_id, m); + bool can_get_replies = for_event_log || is_scheduled ? false : !m->reply_info.is_empty() && m->message_id.is_server(); auto via_bot_user_id = td_->contacts_manager_->get_user_id_object(m->via_bot_user_id, "via_bot_user_id"); auto media_album_id = for_event_log ? static_cast(0) : m->media_album_id; auto reply_to_message_id = for_event_log ? static_cast(0) : m->reply_to_message_id.get(); @@ -20256,8 +20299,8 @@ tl_object_ptr MessagesManager::get_message_object(DialogId dial return make_tl_object( m->message_id.get(), td_->contacts_manager_->get_user_id_object(m->sender_user_id, "sender_user_id"), dialog_id.get(), std::move(sending_state), std::move(scheduling_state), is_outgoing, can_be_edited, - can_be_forwarded, can_delete_for_self, can_delete_for_all_users, can_get_statistics, m->is_channel_post, - contains_unread_mention, date, edit_date, get_message_forward_info_object(m->forward_info), + can_be_forwarded, can_delete_for_self, can_delete_for_all_users, can_get_statistics, can_get_replies, + m->is_channel_post, contains_unread_mention, date, edit_date, get_message_forward_info_object(m->forward_info), get_message_interaction_info_object(dialog_id, m), reply_to_message_id, ttl, ttl_expires_in, via_bot_user_id, m->author_signature, media_album_id, get_restriction_reason_description(m->restriction_reasons), get_message_content_object(m->content.get(), td_, live_location_date, m->is_content_secret), @@ -20324,6 +20367,23 @@ MessagesManager::Message *MessagesManager::get_message_to_send( m->from_background = options.from_background; m->view_count = is_channel_post && !is_scheduled ? 1 : 0; m->forward_count = 0; + if ([&] { + if (is_scheduled) { + return false; + } + if (dialog_type != DialogType::Channel) { + return false; + } + if (td_->auth_manager_->is_bot()) { + return false; + } + if (is_channel_post) { + return td_->contacts_manager_->get_channel_has_linked_channel(dialog_id.get_channel_id()); + } + return !m->reply_to_message_id.is_valid(); + }()) { + m->reply_info.reply_count = 0; + } m->content = std::move(content); m->forward_info = std::move(forward_info); m->is_copy = is_copy || forward_info != nullptr; @@ -20770,6 +20830,9 @@ void MessagesManager::add_message_dependencies(Dependencies &dependencies, Dialo add_dialog_dependencies(dependencies, m->forward_info->from_dialog_id); } } + for (auto recent_replier_user_id : m->reply_info.recent_replier_user_ids) { + dependencies.user_ids.insert(recent_replier_user_id); + } add_message_content_dependencies(dependencies, m->content.get()); } @@ -23383,7 +23446,7 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i m->in_game_share = in_game_share; if (forwarded_message->view_count > 0 && is_broadcast_channel(from_dialog_id)) { if (update_message_interaction_info(from_dialog_id, forwarded_message, forwarded_message->view_count, - forwarded_message->forward_count + 1)) { + forwarded_message->forward_count + 1, false, {})) { on_message_changed(from_dialog, forwarded_message, true, "forward_messages"); } } @@ -30061,7 +30124,8 @@ bool MessagesManager::update_message(Dialog *d, Message *old_message, unique_ptr update_message_contains_unread_mention(d, old_message, new_message->contains_unread_mention, "update_message")) { need_send_update = true; } - if (update_message_interaction_info(dialog_id, old_message, new_message->view_count, new_message->forward_count)) { + if (update_message_interaction_info(dialog_id, old_message, new_message->view_count, new_message->forward_count, true, + std::move(new_message->reply_info))) { need_send_update = true; } if (old_message->restriction_reasons != new_message->restriction_reasons) { @@ -32588,7 +32652,7 @@ void MessagesManager::update_forward_count(DialogId dialog_id, MessageId message CHECK(d != nullptr); Message *m = get_message_force(d, message_id, "update_forward_count"); if (m != nullptr && !m->message_id.is_scheduled() && m->message_id.is_server() && m->view_count > 0) { - if (m->forward_count == 0 && update_message_interaction_info(dialog_id, m, m->view_count, 1)) { + if (m->forward_count == 0 && update_message_interaction_info(dialog_id, m, m->view_count, 1, false, {})) { on_message_changed(d, m, true, "update_forward_count"); } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 553333eed..113631980 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -63,6 +63,7 @@ #include "td/utils/Slice.h" #include "td/utils/Status.h" #include "td/utils/StringBuilder.h" +#include "td/utils/tl_helpers.h" #include "td/utils/tl_storers.h" #include @@ -140,6 +141,102 @@ class updateSentMessage : public telegram_api::Update { } }; +struct MessageReplyInfo { + int32 reply_count = -1; + int32 pts = -1; + vector recent_replier_user_ids; + ChannelId channel_id; + bool is_comment = false; + + MessageReplyInfo() = default; + MessageReplyInfo(tl_object_ptr &&reply_info, bool is_bot) { + if (reply_info == nullptr) { + return; + } + if (reply_info->replies_ < 0) { + LOG(ERROR) << "Receive wrong " << to_string(reply_info); + return; + } + reply_count = reply_info->replies_; + pts = reply_info->replies_pts_; + + if (!is_bot) { + for (auto &user_id_int : reply_info->recent_repliers_) { + UserId user_id(user_id_int); + if (user_id.is_valid()) { + recent_replier_user_ids.push_back(user_id); + } else { + LOG(ERROR) << "Receive " << user_id << " as a recent replier"; + } + } + } + + is_comment = reply_info->comments_; + if (is_comment) { + channel_id = ChannelId(reply_info->channel_id_); + if (!channel_id.is_valid()) { + LOG(ERROR) << "Receive invalid " << channel_id; + channel_id = ChannelId(); + } + } + } + + bool is_empty() const { + return reply_count < 0; + } + + bool need_update_to(const MessageReplyInfo &other) const { + if (other.pts < pts) { + return false; + } + return true; + } + + template + void store(StorerT &storer) const { + CHECK(!is_empty()); + bool has_recent_replier_user_ids = !recent_replier_user_ids.empty(); + bool has_channel_id = channel_id.is_valid(); + BEGIN_STORE_FLAGS(); + STORE_FLAG(is_comment); + STORE_FLAG(has_recent_replier_user_ids); + STORE_FLAG(has_channel_id); + END_STORE_FLAGS(); + td::store(reply_count, storer); + td::store(pts, storer); + if (has_recent_replier_user_ids) { + td::store(recent_replier_user_ids, storer); + } + if (has_channel_id) { + td::store(channel_id, storer); + } + } + + template + void parse(ParserT &parser) { + CHECK(!is_empty()); + bool has_recent_replier_user_ids = !recent_replier_user_ids.empty(); + bool has_channel_id = channel_id.is_valid(); + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(is_comment); + PARSE_FLAG(has_recent_replier_user_ids); + PARSE_FLAG(has_channel_id); + END_PARSE_FLAGS(); + td::parse(reply_count, parser); + td::parse(pts, parser); + if (has_recent_replier_user_ids) { + td::parse(recent_replier_user_ids, parser); + } + if (has_channel_id) { + td::parse(channel_id, parser); + } + } +}; + +inline StringBuilder &operator<<(StringBuilder &string_builder, const MessageReplyInfo &reply_info) { + return string_builder << reply_info.reply_count << " replies by " << reply_info.recent_replier_user_ids; +} + class MessagesManager : public Actor { public: // static constexpr int32 MESSAGE_FLAG_IS_UNREAD = 1 << 0; @@ -335,7 +432,9 @@ class MessagesManager : public Actor { void on_update_message_forward_count(FullMessageId full_message_id, int32 forward_count); - void on_update_message_interaction_info(FullMessageId full_message_id, int32 view_count, int32 forward_count); + void on_update_message_interaction_info(FullMessageId full_message_id, int32 view_count, int32 forward_count, + bool has_reply_info, + tl_object_ptr &&reply_info); void on_update_live_location_viewed(FullMessageId full_message_id); @@ -909,6 +1008,7 @@ class MessagesManager : public Actor { UserId via_bot_user_id; int32 view_count = 0; int32 forward_count = 0; + tl_object_ptr reply_info; int32 flags = 0; int32 edit_date = 0; vector restriction_reasons; @@ -1022,6 +1122,8 @@ class MessagesManager : public Actor { int32 view_count = 0; int32 forward_count = 0; + MessageReplyInfo reply_info; + int32 legacy_layer = 0; int32 send_error_code = 0; @@ -1844,12 +1946,14 @@ class MessagesManager : public Actor { void on_pending_message_views_timeout(DialogId dialog_id); - void update_message_interaction_info(FullMessageId full_message_id, int32 view_count, int32 forward_count); + void update_message_interaction_info(FullMessageId full_message_id, int32 view_count, int32 forward_count, + bool has_reply_info, tl_object_ptr &&reply_info); td_api::object_ptr get_message_interaction_info_object(DialogId dialog_id, const Message *m) const; - bool update_message_interaction_info(DialogId dialog_id, Message *m, int32 view_count, int32 forward_count); + bool update_message_interaction_info(DialogId dialog_id, Message *m, int32 view_count, int32 forward_count, + bool has_reply_info, MessageReplyInfo &&reply_info); bool update_message_contains_unread_mention(Dialog *d, Message *m, bool contains_unread_mention, const char *source); diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index a3f7f5c00..42dfc7c21 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -506,6 +506,8 @@ bool UpdatesManager::is_acceptable_message(const telegram_api::Message *message_ CHECK(message->media_ == nullptr); } + /* + // the users are always min, so no need to check if (message->replies_ != nullptr) { for (auto &user_id : message->replies_->recent_repliers_) { if (!is_acceptable_user(UserId(user_id))) { @@ -513,6 +515,7 @@ bool UpdatesManager::is_acceptable_message(const telegram_api::Message *message_ } } } + */ break; } From 0a5ff51c22ed8904b0132e6838067055e7eb3345 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 2 Sep 2020 14:47:38 +0300 Subject: [PATCH 37/39] Add release dates to the Change Log. GitOrigin-RevId: 26e7a652a883febf23500beba647b5cd5d604590 --- CHANGELOG.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8dfc4772..6a0210500 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -Changes in 1.6.0: +Changes in 1.6.0 (31 Jan 2020): * Added support for multiple chat lists. Currently, only two chat lists Main and Archive are supported: - Added the class `ChatList`, which represents a chat list and could be `chatListMain` or `chatListArchive`. @@ -61,7 +61,7 @@ Changes in 1.6.0: - Added the field `type` to the classes `poll` and `inputMessagePoll`. - Added support for non-anonymous polls with visible votes by adding the field `is_anonymous` to the classes `poll` and `inputMessagePoll`. - - Added the method `getPollVoters`, returning users that voted for the specified option in a non-anonymous poll. + - Added the method `getPollVoters` returning users that voted for the specified option in a non-anonymous poll. - Added the new reply markup keyboard button `keyboardButtonTypeRequestPoll`. - Added the field `is_regular` to the class `pushMessageContentPoll`. - Added the update `updatePollAnswer` for bots only. @@ -172,7 +172,7 @@ Changes in 1.6.0: ----------------------------------------------------------------------------------------------------------------------- -Changes in 1.5.0: +Changes in 1.5.0 (9 Sep 2019): * Changed authorization workflow: - Added the state `authorizationStateWaitRegistration`, which will be received after `authorizationStateWaitCode` for @@ -250,7 +250,7 @@ Changes in 1.5.0: - Added the field `audio_cover_minithumbnail` to the class `audio`. * Added support for resending messages which failed to send: - Added the fields `error_code`, `error_message`, `can_retry` and `retry_after` to - the `messageSendingStateFailed` object. + the class `messageSendingStateFailed`. - Added the method `resendMessages`. * Added the field `is_animated` to the `sticker`, `stickerSet` and `stickerSetInfo` classes. Animated stickers can be received anywhere where non-animated stickers can appear. @@ -278,7 +278,7 @@ Changes in 1.5.0: ----------------------------------------------------------------------------------------------------------------------- -Changes in 1.4.0: +Changes in 1.4.0 (1 May 2019): * Added a [TDLib build instructions generator](https://tdlib.github.io/td/build.html), covering in details TDLib building on the most popular operating systems. @@ -532,7 +532,7 @@ Changes in 1.4.0: ----------------------------------------------------------------------------------------------------------------------- -Changes in 1.3.0: +Changes in 1.3.0 (5 Sep 2018): * Added a review of existing TDLib based [frameworks](https://github.com/tdlib/td/blob/master/example/README.md) in different programming languages. @@ -678,7 +678,7 @@ Changes in 1.3.0: ----------------------------------------------------------------------------------------------------------------------- -Changes in 1.2.0: +Changes in 1.2.0 (20 Mar 2018): * Added support for native .NET bindings through `C++/CLI` and `C++/CX`. See [using in .NET projects](README.md#using-dotnet) for more details. @@ -725,13 +725,13 @@ Changes in 1.2.0: ----------------------------------------------------------------------------------------------------------------------- -Changes in 1.1.1: +Changes in 1.1.1 (4 Feb 2018): * Fixed C JSON bindings compilation error. * Fixed locale-dependent JSON generation. ----------------------------------------------------------------------------------------------------------------------- -Changes in 1.1.0: +Changes in 1.1.0 (31 Jan 2018): * Methods `td::Log::set_file_path` and `td_set_log_file_path` now return whether they succeeded. * Added methods `td::Log::set_max_file_size` and `td_set_log_max_file_size` for restricting maximum TDLib log size. From 4655be30526f9714e0bdf93ee29f37f6ee3cc4f4 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 2 Sep 2020 14:47:55 +0300 Subject: [PATCH 38/39] Improve documentation. GitOrigin-RevId: eae53b31c03f9d9f97f7c511b2eed5ea2f79d7f9 --- td/generate/scheme/td_api.tl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index bf56ef850..54d3a9167 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -354,7 +354,7 @@ chatLocation location:location address:string = ChatLocation; //@description Animated variant of a chat photo in MPEG4 format //@length Animation width and height //@file Information about the animation file -//@main_frame_timestamp Timestamp of the frame, used as static chat photo +//@main_frame_timestamp Timestamp of the frame, used as a static chat photo animatedChatPhoto length:int32 file:file main_frame_timestamp:double = AnimatedChatPhoto; @@ -430,7 +430,7 @@ chatAdministrators administrators:vector = ChatAdministrators //@can_send_messages True, if the user can send text messages, contacts, locations, and venues //@can_send_media_messages True, if the user can send audio files, documents, photos, videos, video notes, and voice notes. Implies can_send_messages permissions //@can_send_polls True, if the user can send polls. Implies can_send_messages permissions -//@can_send_other_messages True, if the user can send animations, games, stickers and dice and use inline bots. Implies can_send_messages permissions +//@can_send_other_messages True, if the user can send animations, games, stickers, and dice and use inline bots. Implies can_send_messages permissions //@can_add_web_page_previews True, if the user may add a web page preview to their messages. Implies can_send_messages permissions //@can_change_info True, if the user can change the chat title, photo, and other settings //@can_invite_users True, if the user can invite new users to the chat @@ -477,9 +477,9 @@ chatMemberStatusBanned banned_until_date:int32 = ChatMemberStatus; //@description A user with information about joining/leaving a chat @user_id User identifier of the chat member //@inviter_user_id Identifier of a user that invited/promoted/banned this member in the chat; 0 if unknown -//@joined_chat_date Point in time (Unix timestamp) when the user joined a chat +//@joined_chat_date Point in time (Unix timestamp) when the user joined the chat //@status Status of the member in the chat -//@bot_info If the user is a bot, information about the bot; may be null. Can be null even for a bot if the bot is not a chat member +//@bot_info If the user is a bot, information about the bot; may be null. Can be null even for a bot if the bot is not the chat member chatMember user_id:int32 inviter_user_id:int32 joined_chat_date:int32 status:ChatMemberStatus bot_info:botInfo = ChatMember; //@description Contains a list of chat members @total_count Approximate total count of chat members found @members A list of chat members @@ -844,7 +844,7 @@ chatsNearby users_nearby:vector supergroups_nearby:vector = LocalizationTargetInfo; -//@class DeviceToken @description Represents a data needed to subscribe for push notifications through registerDevice method. To use specific push notification service, you must specify the correct application platform and upload valid server authentication data at https://my.telegram.org +//@class DeviceToken @description Represents a data needed to subscribe for push notifications through registerDevice method. To use specific push notification service, the correct application platform must be specified and a valid server authentication data must be uploaded at https://my.telegram.org //@description A token for Firebase Cloud Messaging @token Device registration token; may be empty to de-register a device @encrypt True, if push notifications should be additionally encrypted deviceTokenFirebaseCloudMessaging token:string encrypt:Bool = DeviceToken; @@ -3964,7 +3964,7 @@ getChatFilterDefaultIconName filter:chatFilter = Text; setChatTitle chat_id:int53 title:string = Ok; //@description Changes the photo of a chat. Supported only for basic groups, supergroups and channels. Requires can_change_info rights -//@chat_id Chat identifier @photo New chat photo. You can pass null to delete the chat photo +//@chat_id Chat identifier @photo New chat photo. Pass null to delete the chat photo setChatPhoto chat_id:int53 photo:InputChatPhoto = Ok; //@description Changes the chat members permissions. Supported only for basic groups and supergroups. Requires can_restrict_members administrator right @@ -4059,7 +4059,7 @@ setScopeNotificationSettings scope:NotificationSettingsScope notification_settin resetAllNotificationSettings = Ok; -//@description Changes the pinned state of a chat. You can pin up to GetOption("pinned_chat_count_max")/GetOption("pinned_archived_chat_count_max") non-secret chats and the same number of secret chats in the main/arhive chat list +//@description Changes the pinned state of a chat. There can be up to GetOption("pinned_chat_count_max")/GetOption("pinned_archived_chat_count_max") pinned non-secret chats and the same number of secret chats in the main/arhive chat list //@chat_list Chat list in which to change the pinned state of the chat @chat_id Chat identifier @is_pinned True, if the chat is pinned toggleChatIsPinned chat_list:ChatList chat_id:int53 is_pinned:Bool = Ok; @@ -4647,7 +4647,7 @@ addStickerToSet user_id:int32 name:string sticker:InputSticker = StickerSet; //@description Sets a sticker set thumbnail; for bots only. Returns the sticker set //@user_id Sticker set owner @name Sticker set name -//@thumbnail Thumbnail to set in PNG or TGS format. Animated thumbnail must be set for animated sticker sets and only for them. You can use a zero InputFileId to delete the thumbnail +//@thumbnail Thumbnail to set in PNG or TGS format. Animated thumbnail must be set for animated sticker sets and only for them. Pass a zero InputFileId to delete the thumbnail setStickerSetThumbnail user_id:int32 name:string thumbnail:InputFile = StickerSet; //@description Changes the position of a sticker in the set to which it belongs; for bots only. The sticker set must have been created by the bot From 3aee3527511ce43ae670081f3f65a71e7c92ee2c Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 7 Sep 2020 14:07:40 +0300 Subject: [PATCH 39/39] Add MessageReplyInfo.{cpp,h}. GitOrigin-RevId: 0f5b18fdbaac549d4c5a963b067056824d373c4e --- CMakeLists.txt | 2 + td/telegram/MessageReplyInfo.cpp | 56 ++++++++++++++++++ td/telegram/MessageReplyInfo.h | 79 +++++++++++++++++++++++++ td/telegram/MessagesManager.cpp | 4 +- td/telegram/MessagesManager.h | 98 +------------------------------- 5 files changed, 139 insertions(+), 100 deletions(-) create mode 100644 td/telegram/MessageReplyInfo.cpp create mode 100644 td/telegram/MessageReplyInfo.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ff647a9f5..10cd30ab8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -444,6 +444,7 @@ set(TDLIB_SOURCE td/telegram/MessageContentType.cpp td/telegram/MessageEntity.cpp td/telegram/MessageId.cpp + td/telegram/MessageReplyInfo.cpp td/telegram/MessagesDb.cpp td/telegram/MessageSearchFilter.cpp td/telegram/MessagesManager.cpp @@ -617,6 +618,7 @@ set(TDLIB_SOURCE td/telegram/MessageCopyOptions.h td/telegram/MessageEntity.h td/telegram/MessageId.h + td/telegram/MessageReplyInfo.h td/telegram/MessagesDb.h td/telegram/MessageSearchFilter.h td/telegram/MessagesManager.h diff --git a/td/telegram/MessageReplyInfo.cpp b/td/telegram/MessageReplyInfo.cpp new file mode 100644 index 000000000..faa84002b --- /dev/null +++ b/td/telegram/MessageReplyInfo.cpp @@ -0,0 +1,56 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/telegram/MessageReplyInfo.h" + +#include "td/utils/logging.h" + +namespace td { + +MessageReplyInfo::MessageReplyInfo(tl_object_ptr &&reply_info, bool is_bot) { + if (reply_info == nullptr) { + return; + } + if (reply_info->replies_ < 0) { + LOG(ERROR) << "Receive wrong " << to_string(reply_info); + return; + } + reply_count = reply_info->replies_; + pts = reply_info->replies_pts_; + + if (!is_bot) { + for (auto &user_id_int : reply_info->recent_repliers_) { + UserId user_id(user_id_int); + if (user_id.is_valid()) { + recent_replier_user_ids.push_back(user_id); + } else { + LOG(ERROR) << "Receive " << user_id << " as a recent replier"; + } + } + } + + is_comment = reply_info->comments_; + if (is_comment) { + channel_id = ChannelId(reply_info->channel_id_); + if (!channel_id.is_valid()) { + LOG(ERROR) << "Receive invalid " << channel_id; + channel_id = ChannelId(); + } + } +} + +bool MessageReplyInfo::need_update_to(const MessageReplyInfo &other) const { + if (other.pts < pts) { + return false; + } + return true; +} + +StringBuilder &operator<<(StringBuilder &string_builder, const MessageReplyInfo &reply_info) { + return string_builder << reply_info.reply_count << " replies by " << reply_info.recent_replier_user_ids; +} + +} // namespace td \ No newline at end of file diff --git a/td/telegram/MessageReplyInfo.h b/td/telegram/MessageReplyInfo.h new file mode 100644 index 000000000..07e4c65c0 --- /dev/null +++ b/td/telegram/MessageReplyInfo.h @@ -0,0 +1,79 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/ChannelId.h" +#include "td/telegram/telegram_api.h" +#include "td/telegram/UserId.h" + +#include "td/utils/common.h" +#include "td/utils/StringBuilder.h" +#include "td/utils/tl_helpers.h" + +namespace td { + +struct MessageReplyInfo { + int32 reply_count = -1; + int32 pts = -1; + vector recent_replier_user_ids; + ChannelId channel_id; + bool is_comment = false; + + MessageReplyInfo() = default; + + MessageReplyInfo(tl_object_ptr &&reply_info, bool is_bot); + + bool is_empty() const { + return reply_count < 0; + } + + bool need_update_to(const MessageReplyInfo &other) const; + + template + void store(StorerT &storer) const { + CHECK(!is_empty()); + bool has_recent_replier_user_ids = !recent_replier_user_ids.empty(); + bool has_channel_id = channel_id.is_valid(); + BEGIN_STORE_FLAGS(); + STORE_FLAG(is_comment); + STORE_FLAG(has_recent_replier_user_ids); + STORE_FLAG(has_channel_id); + END_STORE_FLAGS(); + td::store(reply_count, storer); + td::store(pts, storer); + if (has_recent_replier_user_ids) { + td::store(recent_replier_user_ids, storer); + } + if (has_channel_id) { + td::store(channel_id, storer); + } + } + + template + void parse(ParserT &parser) { + CHECK(!is_empty()); + bool has_recent_replier_user_ids = !recent_replier_user_ids.empty(); + bool has_channel_id = channel_id.is_valid(); + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(is_comment); + PARSE_FLAG(has_recent_replier_user_ids); + PARSE_FLAG(has_channel_id); + END_PARSE_FLAGS(); + td::parse(reply_count, parser); + td::parse(pts, parser); + if (has_recent_replier_user_ids) { + td::parse(recent_replier_user_ids, parser); + } + if (has_channel_id) { + td::parse(channel_id, parser); + } + } +}; + +StringBuilder &operator<<(StringBuilder &string_builder, const MessageReplyInfo &reply_info); + +} // namespace td \ No newline at end of file diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 46b1c6d4b..19f78f1d1 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -1281,13 +1281,11 @@ class GetMessagesViewsQuery : public Td::ResultHandler { } auto result = result_ptr.move_as_ok(); - if (!td->auth_manager_->is_bot()) { - td->contacts_manager_->on_get_users(std::move(result->users_), "GetMessagesViewsQuery"); - } auto interaction_infos = std::move(result->views_); if (message_ids_.size() != interaction_infos.size()) { return on_error(id, Status::Error(500, "Wrong number of message views returned")); } + td->contacts_manager_->on_get_users(std::move(result->users_), "GetMessagesViewsQuery"); for (size_t i = 0; i < message_ids_.size(); i++) { FullMessageId full_message_id{dialog_id_, message_ids_[i]}; diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 113631980..d2ef8a319 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -27,6 +27,7 @@ #include "td/telegram/MessageContentType.h" #include "td/telegram/MessageCopyOptions.h" #include "td/telegram/MessageId.h" +#include "td/telegram/MessageReplyInfo.h" #include "td/telegram/MessagesDb.h" #include "td/telegram/MessageSearchFilter.h" #include "td/telegram/net/NetQuery.h" @@ -63,7 +64,6 @@ #include "td/utils/Slice.h" #include "td/utils/Status.h" #include "td/utils/StringBuilder.h" -#include "td/utils/tl_helpers.h" #include "td/utils/tl_storers.h" #include @@ -141,102 +141,6 @@ class updateSentMessage : public telegram_api::Update { } }; -struct MessageReplyInfo { - int32 reply_count = -1; - int32 pts = -1; - vector recent_replier_user_ids; - ChannelId channel_id; - bool is_comment = false; - - MessageReplyInfo() = default; - MessageReplyInfo(tl_object_ptr &&reply_info, bool is_bot) { - if (reply_info == nullptr) { - return; - } - if (reply_info->replies_ < 0) { - LOG(ERROR) << "Receive wrong " << to_string(reply_info); - return; - } - reply_count = reply_info->replies_; - pts = reply_info->replies_pts_; - - if (!is_bot) { - for (auto &user_id_int : reply_info->recent_repliers_) { - UserId user_id(user_id_int); - if (user_id.is_valid()) { - recent_replier_user_ids.push_back(user_id); - } else { - LOG(ERROR) << "Receive " << user_id << " as a recent replier"; - } - } - } - - is_comment = reply_info->comments_; - if (is_comment) { - channel_id = ChannelId(reply_info->channel_id_); - if (!channel_id.is_valid()) { - LOG(ERROR) << "Receive invalid " << channel_id; - channel_id = ChannelId(); - } - } - } - - bool is_empty() const { - return reply_count < 0; - } - - bool need_update_to(const MessageReplyInfo &other) const { - if (other.pts < pts) { - return false; - } - return true; - } - - template - void store(StorerT &storer) const { - CHECK(!is_empty()); - bool has_recent_replier_user_ids = !recent_replier_user_ids.empty(); - bool has_channel_id = channel_id.is_valid(); - BEGIN_STORE_FLAGS(); - STORE_FLAG(is_comment); - STORE_FLAG(has_recent_replier_user_ids); - STORE_FLAG(has_channel_id); - END_STORE_FLAGS(); - td::store(reply_count, storer); - td::store(pts, storer); - if (has_recent_replier_user_ids) { - td::store(recent_replier_user_ids, storer); - } - if (has_channel_id) { - td::store(channel_id, storer); - } - } - - template - void parse(ParserT &parser) { - CHECK(!is_empty()); - bool has_recent_replier_user_ids = !recent_replier_user_ids.empty(); - bool has_channel_id = channel_id.is_valid(); - BEGIN_PARSE_FLAGS(); - PARSE_FLAG(is_comment); - PARSE_FLAG(has_recent_replier_user_ids); - PARSE_FLAG(has_channel_id); - END_PARSE_FLAGS(); - td::parse(reply_count, parser); - td::parse(pts, parser); - if (has_recent_replier_user_ids) { - td::parse(recent_replier_user_ids, parser); - } - if (has_channel_id) { - td::parse(channel_id, parser); - } - } -}; - -inline StringBuilder &operator<<(StringBuilder &string_builder, const MessageReplyInfo &reply_info) { - return string_builder << reply_info.reply_count << " replies by " << reply_info.recent_replier_user_ids; -} - class MessagesManager : public Actor { public: // static constexpr int32 MESSAGE_FLAG_IS_UNREAD = 1 << 0;