From 059fe9911e79c2460c402546d80cf2eecb07cbb4 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 17 Dec 2021 16:28:14 +0300 Subject: [PATCH 01/13] Documentation improvements. --- example/java/org/drinkless/tdlib/example/Example.java | 4 ++-- example/uwp/README.md | 2 +- td/generate/scheme/td_api.tl | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/example/java/org/drinkless/tdlib/example/Example.java b/example/java/org/drinkless/tdlib/example/Example.java index ee5e2f1ca..993c834a2 100644 --- a/example/java/org/drinkless/tdlib/example/Example.java +++ b/example/java/org/drinkless/tdlib/example/Example.java @@ -248,7 +248,7 @@ public final class Example { private static void getMainChatList(final int limit) { synchronized (mainChatList) { if (!haveFullMainChatList && limit > mainChatList.size()) { - // send GetChats request if there are some unknown chats and have not enough known chats + // send LoadChats request if there are some unknown chats and have not enough known chats client.send(new TdApi.LoadChats(new TdApi.ChatListMain(), limit - mainChatList.size()), new Client.ResultHandler() { @Override public void onResult(TdApi.Object object) { @@ -259,7 +259,7 @@ public final class Example { haveFullMainChatList = true; } } else { - System.err.println("Receive an error for GetChats:" + newLine + object); + System.err.println("Receive an error for LoadChats:" + newLine + object); } break; case TdApi.Ok.CONSTRUCTOR: diff --git a/example/uwp/README.md b/example/uwp/README.md index f6cf3aa54..c0b4de723 100644 --- a/example/uwp/README.md +++ b/example/uwp/README.md @@ -19,7 +19,7 @@ cd ``` powershell -ExecutionPolicy ByPass .\build.ps1 -vcpkg_root C:\vcpkg ``` -If you need to restart the build from scratch, call `.\build.ps1 -vcpkg_root ../../vcpkg -mode clean` first. +If you need to restart the build from scratch, call `.\build.ps1 -vcpkg_root C:\vcpkg -mode clean` first. * Install Visual Studio Extension "TDLib for Universal Windows Platform" located at `build-uwp\vsix\tdlib.vsix`, which was created on the previous step by `build.ps1` script. Now `TDLib` can be used from any UWP project, built in Visual Studio. diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index f56fe08a7..67f0d3a48 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -573,7 +573,7 @@ supergroupMembersFilterBots = SupergroupMembersFilter; //@member_count Number of chat members, which joined the chat using the link //@pending_join_request_count Number of pending join requests created using this link //@creates_join_request True, if the link only creates join request. If true, total number of joining members will be unlimited -//@is_primary True, if the link is primary. Primary invite link can't have name, expire date or usage limit. There is exactly one primary invite link for each administrator with can_invite_users right at a given time +//@is_primary True, if the link is primary. Primary invite link can't have name, expiration date, or usage limit. There is exactly one primary invite link for each administrator with can_invite_users right at a given time //@is_revoked True, if the link was revoked chatInviteLink invite_link:string name:string creator_user_id:int53 date:int32 edit_date:int32 expire_date:int32 member_limit:int32 member_count:int32 pending_join_request_count:int32 creates_join_request:Bool is_primary:Bool is_revoked:Bool = ChatInviteLink; From 28d65e42e6f979734aaf8c260d5f5e50eec46fdb Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 17 Dec 2021 19:15:16 +0300 Subject: [PATCH 02/13] tg_cli: add user_ids to "log" command. --- td/telegram/cli.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index d39457e79..a2994354c 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4055,9 +4055,10 @@ class CliClient final : public Actor { } else if (op == "log") { string chat_id; string limit; - get_args(args, chat_id, limit); + string user_ids; + get_args(args, chat_id, limit, user_ids); send_request(td_api::make_object(as_chat_id(chat_id), "", 0, as_limit(limit), nullptr, - vector())); + as_user_ids(user_ids))); } else if (op == "join") { send_request(td_api::make_object(as_chat_id(args))); } else if (op == "leave") { From 93464ccd2778274405f3c763ad109be57abe8707 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 18 Dec 2021 22:44:25 +0300 Subject: [PATCH 03/13] Use request promise in getChatAdministrators. --- td/telegram/ContactsManager.cpp | 128 ++++++++++++++++++-------------- td/telegram/ContactsManager.h | 19 +++-- td/telegram/Td.cpp | 27 +------ 3 files changed, 89 insertions(+), 85 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 00f03f5b1..34105cfd5 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -13399,7 +13399,7 @@ void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id c->is_creator_changed = true; send_get_channel_full_query(nullptr, channel_id, Auto(), "update channel owner"); - reload_dialog_administrators(DialogId(channel_id), 0, Auto()); + reload_dialog_administrators(DialogId(channel_id), {}, Auto()); remove_dialog_suggested_action(SuggestedAction{SuggestedAction::Type::ConvertToGigagroup, DialogId(channel_id)}); } @@ -15234,60 +15234,39 @@ void ContactsManager::get_channel_participants(ChannelId channel_id, ->send(channel_id, participants_filter, offset, limit); } -vector ContactsManager::get_dialog_administrators(DialogId dialog_id, int left_tries, - Promise &&promise) { - LOG(INFO) << "Receive GetChatAdministrators request in " << dialog_id << " with " << left_tries << " left tries"; +td_api::object_ptr ContactsManager::get_chat_administrators_object( + const vector &dialog_administrators) { + auto administrator_objects = transform(dialog_administrators, [this](const DialogAdministrator &administrator) { + return administrator.get_chat_administrator_object(this); + }); + return td_api::make_object(std::move(administrator_objects)); +} + +void ContactsManager::get_dialog_administrators(DialogId dialog_id, + Promise> &&promise) { if (!td_->messages_manager_->have_dialog_force(dialog_id, "get_dialog_administrators")) { - promise.set_error(Status::Error(400, "Chat not found")); - return {}; + return promise.set_error(Status::Error(400, "Chat not found")); } switch (dialog_id.get_type()) { case DialogType::User: case DialogType::SecretChat: - promise.set_value(Unit()); - return {}; + return promise.set_value(td_api::make_object()); case DialogType::Chat: case DialogType::Channel: break; case DialogType::None: default: UNREACHABLE(); - return {}; + return; } auto it = dialog_administrators_.find(dialog_id); if (it != dialog_administrators_.end()) { - promise.set_value(Unit()); - if (left_tries >= 2) { - auto hash = get_vector_hash(transform(it->second, [](const DialogAdministrator &administrator) { - return static_cast(administrator.get_user_id().get()); - })); - reload_dialog_administrators(dialog_id, hash, Auto()); // update administrators cache - } - return it->second; + reload_dialog_administrators(dialog_id, it->second, Auto()); // update administrators cache + return promise.set_value(get_chat_administrators_object(it->second)); } - if (left_tries >= 3) { - load_dialog_administrators(dialog_id, std::move(promise)); - return {}; - } - - if (left_tries >= 2) { - reload_dialog_administrators(dialog_id, 0, std::move(promise)); - return {}; - } - - LOG(ERROR) << "Have no known administrators in " << dialog_id; - promise.set_value(Unit()); - return {}; -} - -string ContactsManager::get_dialog_administrators_database_key(DialogId dialog_id) { - return PSTRING() << "adm" << (-dialog_id.get()); -} - -void ContactsManager::load_dialog_administrators(DialogId dialog_id, Promise &&promise) { if (G()->parameters().use_chat_info_db) { LOG(INFO) << "Load administrators of " << dialog_id << " from database"; G()->td_db()->get_sqlite_pmc()->get(get_dialog_administrators_database_key(dialog_id), @@ -15297,16 +15276,22 @@ void ContactsManager::load_dialog_administrators(DialogId dialog_id, Promise &&promise) { - if (value.empty() || G()->close_flag()) { - promise.set_value(Unit()); - return; +string ContactsManager::get_dialog_administrators_database_key(DialogId dialog_id) { + return PSTRING() << "adm" << (-dialog_id.get()); +} + +void ContactsManager::on_load_dialog_administrators_from_database( + DialogId dialog_id, string value, Promise> &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + + if (value.empty()) { + return reload_dialog_administrators(dialog_id, {}, std::move(promise)); } vector administrators; @@ -15332,13 +15317,18 @@ void ContactsManager::on_load_dialog_administrators_from_database(DialogId dialo lock_promise.set_value(Unit()); } -void ContactsManager::on_load_administrator_users_finished(DialogId dialog_id, - vector administrators, Result<> result, - Promise promise) { - if (!G()->close_flag() && result.is_ok()) { - dialog_administrators_.emplace(dialog_id, std::move(administrators)); +void ContactsManager::on_load_administrator_users_finished( + DialogId dialog_id, vector administrators, Result<> result, + Promise> &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + + if (result.is_error()) { + return reload_dialog_administrators(dialog_id, {}, std::move(promise)); } - promise.set_value(Unit()); + + auto it = dialog_administrators_.emplace(dialog_id, std::move(administrators)).first; + reload_dialog_administrators(dialog_id, it->second, Auto()); // update administrators cache + promise.set_value(get_chat_administrators_object(it->second)); } void ContactsManager::on_update_channel_administrator_count(ChannelId channel_id, int32 administrator_count) { @@ -15394,19 +15384,49 @@ void ContactsManager::on_update_dialog_administrators(DialogId dialog_id, vector } } -void ContactsManager::reload_dialog_administrators(DialogId dialog_id, int64 hash, Promise &&promise) { +void ContactsManager::reload_dialog_administrators(DialogId dialog_id, + const vector &dialog_administrators, + Promise> &&promise) { + auto query_promise = PromiseCreator::lambda( + [actor_id = actor_id(this), dialog_id, promise = std::move(promise)](Result &&result) mutable { + if (promise) { + if (result.is_ok()) { + send_closure(actor_id, &ContactsManager::on_reload_dialog_administrators, dialog_id, std::move(promise)); + } else { + promise.set_error(result.move_as_error()); + } + } + }); switch (dialog_id.get_type()) { case DialogType::Chat: - load_chat_full(dialog_id.get_chat_id(), false, std::move(promise), "reload_dialog_administrators"); + load_chat_full(dialog_id.get_chat_id(), false, std::move(query_promise), "reload_dialog_administrators"); break; - case DialogType::Channel: - td_->create_handler(std::move(promise))->send(dialog_id.get_channel_id(), hash); + case DialogType::Channel: { + auto hash = get_vector_hash(transform(dialog_administrators, [](const DialogAdministrator &administrator) { + return static_cast(administrator.get_user_id().get()); + })); + td_->create_handler(std::move(query_promise)) + ->send(dialog_id.get_channel_id(), hash); break; + } default: UNREACHABLE(); } } +void ContactsManager::on_reload_dialog_administrators( + DialogId dialog_id, Promise> &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + + auto it = dialog_administrators_.find(dialog_id); + if (it != dialog_administrators_.end()) { + return promise.set_value(get_chat_administrators_object(it->second)); + } + + LOG(ERROR) << "Failed to load administrators in " << dialog_id; + promise.set_error(Status::Error(500, "Failed to find chat administrators")); +} + void ContactsManager::on_chat_update(telegram_api::chatEmpty &chat, const char *source) { ChatId chat_id(chat.id_); if (!chat_id.is_valid()) { diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index fc54082f5..8a30d9efc 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -534,7 +534,7 @@ class ContactsManager final : public Actor { void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter, Promise &&promise); - vector get_dialog_administrators(DialogId dialog_id, int left_tries, Promise &&promise); + void get_dialog_administrators(DialogId dialog_id, Promise> &&promise); void get_channel_participants(ChannelId channel_id, tl_object_ptr &&filter, string additional_query, int32 offset, int32 limit, int32 additional_limit, @@ -1476,16 +1476,23 @@ class ContactsManager final : public Actor { void finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant, Promise &&promise); + td_api::object_ptr ContactsManager::get_chat_administrators_object( + const vector &dialog_administrators); + static string get_dialog_administrators_database_key(DialogId dialog_id); - void load_dialog_administrators(DialogId dialog_id, Promise &&promise); - - void on_load_dialog_administrators_from_database(DialogId dialog_id, string value, Promise &&promise); + void on_load_dialog_administrators_from_database(DialogId dialog_id, string value, + Promise> &&promise); void on_load_administrator_users_finished(DialogId dialog_id, vector administrators, - Result<> result, Promise promise); + Result<> result, + Promise> &&promise); - void reload_dialog_administrators(DialogId dialog_id, int64 hash, Promise &&promise); + void reload_dialog_administrators(DialogId dialog_id, const vector &dialog_administrators, + Promise> &&promise); + + void on_reload_dialog_administrators(DialogId dialog_id, + Promise> &&promise); void remove_dialog_suggested_action(SuggestedAction action); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 7bc1d69e6..df59dbedd 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1764,30 +1764,6 @@ class UpgradeGroupChatToSupergroupChatRequest final : public RequestActor<> { } }; -class GetChatAdministratorsRequest final : public RequestActor<> { - DialogId dialog_id_; - - vector administrators_; - - void do_run(Promise &&promise) final { - administrators_ = td_->contacts_manager_->get_dialog_administrators(dialog_id_, get_tries(), std::move(promise)); - } - - void do_send_result() final { - auto administrator_objects = transform( - administrators_, [contacts_manager = td_->contacts_manager_.get()](const DialogAdministrator &administrator) { - return administrator.get_chat_administrator_object(contacts_manager); - }); - send_result(td_api::make_object(std::move(administrator_objects))); - } - - public: - GetChatAdministratorsRequest(ActorShared td, uint64 request_id, int64 dialog_id) - : RequestActor(std::move(td), request_id), dialog_id_(dialog_id) { - set_tries(3); - } -}; - class CheckChatInviteLinkRequest final : public RequestActor<> { string invite_link_; @@ -6194,7 +6170,8 @@ void Td::on_request(uint64 id, td_api::searchChatMembers &request) { } void Td::on_request(uint64 id, const td_api::getChatAdministrators &request) { - CREATE_REQUEST(GetChatAdministratorsRequest, request.chat_id_); + CREATE_REQUEST_PROMISE(); + contacts_manager_->get_dialog_administrators(DialogId(request.chat_id_), std::move(promise)); } void Td::on_request(uint64 id, const td_api::replacePrimaryChatInviteLink &request) { From 0ab05735c08763f1650305d6d8a572bafbd533a7 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 18 Dec 2021 23:15:06 +0300 Subject: [PATCH 04/13] Silence expected warnings. --- td/telegram/MessagesManager.cpp | 18 ++++++++++-------- td/telegram/MessagesManager.h | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index ffb47bd5c..76a947efc 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -13930,7 +13930,7 @@ FullMessageId MessagesManager::on_get_message(MessageInfo &&message_info, bool f need_update = false; if (old_message_id.is_valid() && message_id.is_valid() && message_id < old_message_id && - !can_overflow_message_id(dialog_id)) { + !has_qts_messages(dialog_id)) { LOG(ERROR) << "Sent " << old_message_id << " to " << dialog_id << " as " << message_id; } @@ -23957,7 +23957,7 @@ void MessagesManager::fix_server_reply_to_message_id(DialogId dialog_id, Message } if (!message_id.is_scheduled() && !reply_in_dialog_id.is_valid() && reply_to_message_id >= message_id) { - if (!can_overflow_message_id(dialog_id)) { + if (!has_qts_messages(dialog_id)) { LOG(ERROR) << "Receive reply to wrong " << reply_to_message_id << " in " << message_id << " in " << dialog_id; } reply_to_message_id = MessageId(); @@ -25428,7 +25428,7 @@ void MessagesManager::do_send_inline_query_result_message(DialogId dialog_id, co random_id, query_id, result_id); } -bool MessagesManager::can_overflow_message_id(DialogId dialog_id) { +bool MessagesManager::has_qts_messages(DialogId dialog_id) { switch (dialog_id.get_type()) { case DialogType::User: case DialogType::Chat: @@ -29760,7 +29760,7 @@ FullMessageId MessagesManager::on_send_message_success(int64 random_id, MessageI send_update_message_content(d, sent_message.get(), false, source); } - if (old_message_id.is_valid() && new_message_id < old_message_id && !can_overflow_message_id(dialog_id)) { + if (old_message_id.is_valid() && new_message_id < old_message_id && !has_qts_messages(dialog_id)) { LOG(ERROR) << "Sent " << old_message_id << " to " << dialog_id << " as " << new_message_id; } @@ -32856,9 +32856,11 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq LOG(FATAL) << "Force restart because of message_id overflow in " << dialog_id << " from " << d->last_new_message_id << " to " << message_id; } - LOG(ERROR) << "New " << message_id << " in " << dialog_id << " from " << source - << " has identifier less than last_new_message_id = " << d->last_new_message_id; - dump_debug_message_op(d); + if (!has_qts_messages(dialog_id)) { + LOG(ERROR) << "New " << message_id << " in " << dialog_id << " from " << source + << " has identifier less than last_new_message_id = " << d->last_new_message_id; + dump_debug_message_op(d); + } } } } @@ -33226,7 +33228,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq ++it; auto next_message = *it; if (next_message != nullptr) { - if (next_message->message_id.is_server()) { + if (next_message->message_id.is_server() && !has_qts_messages(dialog_id)) { LOG(ERROR) << "Attach " << message_id << " from " << source << " before " << next_message->message_id << " and after " << previous_message_id << " in " << dialog_id; dump_debug_message_op(d); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 66c3f23b9..9705c4e67 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1836,7 +1836,7 @@ class MessagesManager final : public Actor { bool can_edit_message(DialogId dialog_id, const Message *m, bool is_editing, bool only_reply_markup = false) const; - static bool can_overflow_message_id(DialogId dialog_id); + static bool has_qts_messages(DialogId dialog_id); bool can_report_dialog(DialogId dialog_id) const; From 5587f10eba5bc1ea44732970fbac5bd908680dc5 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 19 Dec 2021 01:17:39 +0300 Subject: [PATCH 05/13] Expect different Homebrew install paths on Apple silicon/Intel. --- build.html | 29 +++++++++++++++++++++++++---- example/ios/README.md | 2 +- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/build.html b/build.html index 3cf8802d6..68922727b 100644 --- a/build.html +++ b/build.html @@ -282,6 +282,13 @@

+
+ Choose host architecture:
+ + +

+
+
Choose for which bitness you want to build TDLib:
@@ -586,6 +593,8 @@ function onOptionsChanged() { var use_powershell = false; var use_cmd = false; var use_csh = false; + var homebrew_install_dir = ''; + var os_mac_host_name = ''; if (os_windows) { document.getElementById('buildShellDiv').style.display = 'block'; use_powershell = document.getElementById('buildShellRadioPowerShell').checked; @@ -598,6 +607,18 @@ function onOptionsChanged() { } else { document.getElementById('buildShellBsdDiv').style.display = 'none'; } + if (os_mac) { + document.getElementById('buildMacOsHostDiv').style.display = 'block'; + if (document.getElementById('buildMacOsHostRadioAppleSilicon').checked) { + homebrew_install_dir = '/opt/homebrew'; + os_mac_host_name = 'Apple silicon'; + } else { + homebrew_install_dir = '/usr/local'; + os_mac_host_name = 'Intel'; + } + } else { + document.getElementById('buildMacOsHostDiv').style.display = 'none'; + } var use_msvc = os_windows; var use_vcpkg = os_windows; @@ -713,7 +734,7 @@ function onOptionsChanged() { pre_text.push('Note that the following instruction is for NetBSD 8.0 and default SH shell.'); } if (os_mac) { - pre_text.push('Note that the following instruction will build TDLib only for the current architecture (x64 or Apple silicon).'); + pre_text.push('Note that the following instruction will build TDLib only for ' + os_mac_host_name + '.'); pre_text.push('If you want to create a universal XCFramework, take a look at our example instead.'); } @@ -773,7 +794,7 @@ function onOptionsChanged() { var cmake = 'cmake'; if (os_mac) { commands.push('xcode-select --install'); - commands.push('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"'); + commands.push('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"'); commands.push('brew install gperf cmake openssl' + (target === 'JNI' ? ' coreutils' : '')); if (target === 'JNI') { commands.push('brew install openjdk'); @@ -926,7 +947,7 @@ function onOptionsChanged() { options.push('-DJAVA_HOME=/usr/local/openjdk7/'); } if (os_mac) { - options.push('-DJAVA_HOME=/usr/local/opt/openjdk/libexec/openjdk.jdk/Contents/Home/'); + options.push('-DJAVA_HOME=' + homebrew_install_dir + '/opt/openjdk/libexec/openjdk.jdk/Contents/Home/'); } } return options; @@ -957,7 +978,7 @@ function onOptionsChanged() { cmake_init_options = getBacicCmakeInitOptions(); if (os_mac) { - cmake_init_options.push('-DOPENSSL_ROOT_DIR=/usr/local/opt/openssl/'); + cmake_init_options.push('-DOPENSSL_ROOT_DIR=' + homebrew_install_dir + '/opt/openssl/'); } if (install_dir) { cmake_init_options.push('-DCMAKE_INSTALL_PREFIX:PATH=' + install_dir); diff --git a/example/ios/README.md b/example/ios/README.md index 32266528d..00d4312be 100644 --- a/example/ios/README.md +++ b/example/ios/README.md @@ -36,7 +36,7 @@ cd /example/ios ./build.sh ``` This may take a while, because TDLib will be built about 16 times. -Resulting XCFramework will work on any architecture and even on a simulator (x64, Apple silicon). +Resulting XCFramework will work on any architecture and even on a simulator. We use [CMake/iOS.cmake](https://github.com/tdlib/td/blob/master/CMake/iOS.cmake) toolchain, other toolchains may work too. Built libraries and XCFramework will be stored in `tdjson` directory. From 1f68217399c69180516b6bdea709f7d240450885 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 19 Dec 2021 13:16:00 +0300 Subject: [PATCH 06/13] Update C++ example to 1.7.10. --- example/cpp/td_example.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/cpp/td_example.cpp b/example/cpp/td_example.cpp index e185702da..928f5c787 100644 --- a/example/cpp/td_example.cpp +++ b/example/cpp/td_example.cpp @@ -210,7 +210,7 @@ class TdExample { [this](td_api::updateNewMessage &update_new_message) { auto chat_id = update_new_message.message_->chat_id_; std::string sender_name; - td_api::downcast_call(*update_new_message.message_->sender_, + td_api::downcast_call(*update_new_message.message_->sender_id_, overloaded( [this, &sender_name](td_api::messageSenderUser &user) { sender_name = get_user_name(user.user_id_); From 3b2e7cf5d0afeac3c1f855dadf8f7c62db5f8144 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 19 Dec 2021 18:02:46 +0300 Subject: [PATCH 07/13] Fix compilation error. --- td/telegram/ContactsManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 8a30d9efc..02674d418 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -1476,7 +1476,7 @@ class ContactsManager final : public Actor { void finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant, Promise &&promise); - td_api::object_ptr ContactsManager::get_chat_administrators_object( + td_api::object_ptr get_chat_administrators_object( const vector &dialog_administrators); static string get_dialog_administrators_database_key(DialogId dialog_id); From e8c0b8780fef894686e8b787a4b1bc2dc4e804ed Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 19 Dec 2021 18:10:38 +0300 Subject: [PATCH 08/13] Add CHECK debug. --- td/telegram/WebPagesManager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/td/telegram/WebPagesManager.cpp b/td/telegram/WebPagesManager.cpp index ff7ec2173..cf2db4855 100644 --- a/td/telegram/WebPagesManager.cpp +++ b/td/telegram/WebPagesManager.cpp @@ -1307,7 +1307,9 @@ void WebPagesManager::on_web_page_changed(WebPageId web_page_id, bool have_web_p } } if (have_web_page) { - CHECK(web_page_messages_[web_page_id].size() == full_message_ids.size()); + LOG_CHECK(web_page_messages_[web_page_id].size() == full_message_ids.size()) + << full_message_ids << ' ' + << std::vector(web_page_messages_[web_page_id].begin(), web_page_messages_[web_page_id].end()); } else { CHECK(web_page_messages_.count(web_page_id) == 0); } From 4eaae3306829be9aa66f9dd2a7e3d3895e01841e Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 19 Dec 2021 18:10:59 +0300 Subject: [PATCH 09/13] Improve Java example README. --- example/java/README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/example/java/README.md b/example/java/README.md index 49455299f..4c7df1916 100644 --- a/example/java/README.md +++ b/example/java/README.md @@ -3,6 +3,10 @@ To run this example, you will need installed JDK >= 1.6. For Javadoc documentation generation PHP is needed. +You can find complete build instructions for your operating system at https://tdlib.github.io/td/build.html?language=Java. + +In general, the build process looks as follows. + TDLib should be prebuilt with JNI bindings and installed to local subdirectory `td/` as follows: ``` cd @@ -13,7 +17,7 @@ cmake --build . --target install ``` If you want to compile TDLib for 32-bit/64-bit Java on Windows using MSVC, you will also need to add `-A Win32`/`-A x64` option to CMake. -In Windows, use Vcpkg toolchain file by adding parameter -DCMAKE_TOOLCHAIN_FILE=/scripts/buildsystems/vcpkg.cmake +In Windows, use vcpkg toolchain file by adding parameter -DCMAKE_TOOLCHAIN_FILE=/scripts/buildsystems/vcpkg.cmake Then you can build this example: ``` @@ -36,4 +40,4 @@ If you receive "Could NOT find JNI ..." error from CMake, you need to specify to If you receive java.lang.UnsatisfiedLinkError with "Can't find dependent libraries", you may also need to copy some dependent shared OpenSSL and zlib libraries to `bin/`. -In case you compiled the example as 32-bit version, you may need to give -d32 parameter to Java. +Make sure that you compiled the example for the same architecture as your JVM. From d3780284fcf48a9c630a8352a479c1f0678d49e1 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 20 Dec 2021 15:15:34 +0300 Subject: [PATCH 10/13] Remove wrong check. --- td/telegram/StickersManager.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 5fd9e4d7a..f6fd262c7 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -1368,7 +1368,9 @@ void StickersManager::load_special_sticker_set_by_type(SpecialStickerSetType typ } auto &sticker_set = add_special_sticker_set(type); - CHECK(sticker_set.is_being_loaded_); + if (!sticker_set.is_being_loaded_) { + return; + } sticker_set.is_being_loaded_ = false; load_special_sticker_set(sticker_set); } @@ -1446,6 +1448,8 @@ void StickersManager::on_load_special_sticker_set(const SpecialStickerSetType &t } if (result.is_error()) { + LOG(INFO) << "Failed to load special sticker set " << type.type_ << ": " << result.error(); + // failed to load the special sticker set; repeat after some time create_actor("RetryLoadSpecialStickerSetActor", Random::fast(300, 600), PromiseCreator::lambda([actor_id = actor_id(this), type](Result result) mutable { From 2b9a5741b26898a9b621d10cd31e5dce6696362c Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 20 Dec 2021 15:42:28 +0300 Subject: [PATCH 11/13] Ensure that there are at most 3 recent pending join requests. --- td/telegram/MessagesManager.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 76a947efc..80adb01ba 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -30626,13 +30626,13 @@ void MessagesManager::on_update_dialog_pending_join_requests(DialogId dialog_id, return; } - auto pending_join_request_user_ids = UserId::get_user_ids(pending_requesters); - td::remove_if(pending_join_request_user_ids, [](UserId user_id) { return !user_id.is_valid(); }); - set_dialog_pending_join_requests(d, pending_join_request_count, std::move(pending_join_request_user_ids)); + set_dialog_pending_join_requests(d, pending_join_request_count, UserId::get_user_ids(pending_requesters)); } void MessagesManager::fix_pending_join_requests(DialogId dialog_id, int32 &pending_join_request_count, vector &pending_join_request_user_ids) const { + td::remove_if(pending_join_request_user_ids, [](UserId user_id) { return !user_id.is_valid(); }); + bool need_drop_pending_join_requests = [&] { if (pending_join_request_count < 0) { return true; @@ -30671,6 +30671,11 @@ void MessagesManager::fix_pending_join_requests(DialogId dialog_id, int32 &pendi << pending_join_request_user_ids.size(); pending_join_request_count = narrow_cast(pending_join_request_user_ids.size()); } + + static constexpr size_t MAX_PENDING_JOIN_REQUESTS = 3; + if (pending_join_request_user_ids.size() > MAX_PENDING_JOIN_REQUESTS) { + pending_join_request_user_ids.resize(MAX_PENDING_JOIN_REQUESTS); + } } void MessagesManager::set_dialog_pending_join_requests(Dialog *d, int32 pending_join_request_count, From f53ae6b85e79740f7b249122972ef8030d25d858 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 20 Dec 2021 15:47:03 +0300 Subject: [PATCH 12/13] Ensure that there are at most 3 recent repliers. --- td/telegram/MessageReplyInfo.cpp | 5 ++++- td/telegram/MessageReplyInfo.h | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/td/telegram/MessageReplyInfo.cpp b/td/telegram/MessageReplyInfo.cpp index a8d9ea955..b92e77092 100644 --- a/td/telegram/MessageReplyInfo.cpp +++ b/td/telegram/MessageReplyInfo.cpp @@ -48,6 +48,9 @@ MessageReplyInfo::MessageReplyInfo(tl_object_ptr & LOG(ERROR) << "Receive " << dialog_id << " as a recent replier"; } } + if (recent_replier_dialog_ids.size() > MAX_RECENT_REPLIERS) { + recent_replier_dialog_ids.resize(MAX_RECENT_REPLIERS); + } } if ((reply_info->flags_ & telegram_api::messageReplies::MAX_ID_MASK) != 0 && ServerMessageId(reply_info->max_id_).is_valid()) { @@ -120,7 +123,7 @@ bool MessageReplyInfo::add_reply(DialogId replier_dialog_id, MessageId reply_mes td::remove(recent_replier_dialog_ids, replier_dialog_id); if (diff > 0) { recent_replier_dialog_ids.insert(recent_replier_dialog_ids.begin(), replier_dialog_id); - if (recent_replier_dialog_ids.size() > 3) { + if (recent_replier_dialog_ids.size() > MAX_RECENT_REPLIERS) { recent_replier_dialog_ids.pop_back(); } } else { diff --git a/td/telegram/MessageReplyInfo.h b/td/telegram/MessageReplyInfo.h index fb682966d..781badd2e 100644 --- a/td/telegram/MessageReplyInfo.h +++ b/td/telegram/MessageReplyInfo.h @@ -31,6 +31,8 @@ struct MessageReplyInfo { MessageId last_read_outbox_message_id; bool is_comment = false; + static constexpr size_t MAX_RECENT_REPLIERS = 3; + MessageReplyInfo() = default; MessageReplyInfo(tl_object_ptr &&reply_info, bool is_bot); @@ -121,6 +123,9 @@ struct MessageReplyInfo { if (channel_id.get() == 777) { *this = MessageReplyInfo(); } + if (recent_replier_dialog_ids.size() > MAX_RECENT_REPLIERS) { + recent_replier_dialog_ids.resize(MAX_RECENT_REPLIERS); + } } }; From f32a1b9af45ee5736d48ace63dd35e568118d962 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 20 Dec 2021 15:54:19 +0300 Subject: [PATCH 13/13] Document that there can be at most 3 recent repliers/speakers/pending join requests. --- td/generate/scheme/td_api.tl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 67f0d3a48..004730735 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -614,7 +614,7 @@ chatJoinRequest user_id:int53 date:int32 bio:string = ChatJoinRequest; //@description Contains a list of chat join requests @total_count Approximate total count of requests found @requests List of the requests chatJoinRequests total_count:int32 requests:vector = ChatJoinRequests; -//@description Contains information about pending chat join requests @total_count Total number of pending join requests @user_ids Identifiers of users sent the newest pending join requests +//@description Contains information about pending chat join requests @total_count Total number of pending join requests @user_ids Identifiers of at most 3 users sent the newest pending join requests chatJoinRequestsInfo total_count:int32 user_ids:vector = ChatJoinRequestsInfo; @@ -748,7 +748,7 @@ messageForwardInfo origin:MessageForwardOrigin date:int32 public_service_announc //@description Contains information about replies to a message //@reply_count Number of times the message was directly or indirectly replied -//@recent_replier_ids Identifiers of recent repliers to the message; available in channels with a discussion supergroup +//@recent_replier_ids Identifiers of at most 3 recent repliers to the message; available in channels with a discussion supergroup //@last_read_inbox_message_id Identifier of the last read incoming reply to the message //@last_read_outbox_message_id Identifier of the last read outgoing reply to the message //@last_message_id Identifier of the last reply to the message @@ -2275,7 +2275,7 @@ groupCallRecentSpeaker participant_id:MessageSender is_speaking:Bool = GroupCall //@can_be_managed True, if the current user can manage the group call //@participant_count Number of participants in the group call //@loaded_all_participants True, if all group call participants are loaded -//@recent_speakers Recently speaking users in the group call +//@recent_speakers At most 3 recently speaking users in the group call //@is_my_video_enabled True, if the current user's video is enabled //@is_my_video_paused True, if the current user's video is paused //@can_enable_video True, if the current user can broadcast video or share screen