Merge remote-tracking branch 'td/master'

This commit is contained in:
Andrea Cavalli 2021-12-20 16:51:07 +01:00
commit 3440f2c07e
17 changed files with 176 additions and 131 deletions

View File

@ -282,6 +282,13 @@
<p></p>
</div>
<div id="buildMacOsHostDiv" class="hide">
<span>Choose host architecture:</span><br>
<label><input type="radio" id="buildMacOsHostRadioAppleSilicon" name="buildMacOsHostRadio" onchange="onOptionsChanged()" checked/>Apple silicon</label>
<label><input type="radio" id="buildMacOsHostRadioIntel" name="buildMacOsHostRadio" onchange="onOptionsChanged()"/>Intel</label>
<p></p>
</div>
<div id="buildBitnessDiv" class="hide">
<span>Choose for which bitness you want to build TDLight:</span><br>
<label><input type="radio" id="buildBitnessRadio32" name="buildBitnessRadio" onchange="onOptionsChanged()" checked/>32</label>
@ -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 TDLight only for the current architecture (x64 or Apple silicon).');
pre_text.push('Note that the following instruction will build TDLight only for ' + os_mac_host_name + '.');
pre_text.push('If you want to create a universal XCFramework, take a look at our <a href="https://github.com/tdlight-team/tdlight/tree/master/example/ios">example</a> 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);

View File

@ -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_);

View File

@ -36,7 +36,7 @@ cd <path to TDLib sources>/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/tdlight-team/tdlight/blob/master/CMake/iOS.cmake) toolchain, other toolchains may work too.
Built libraries and XCFramework will be stored in `tdjson` directory.

View File

@ -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://tdlight-team.github.io/tdlight/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 <path to TDLib sources>
@ -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=<VCPKG_DIR>/scripts/buildsystems/vcpkg.cmake
In Windows, use vcpkg toolchain file by adding parameter -DCMAKE_TOOLCHAIN_FILE=<VCPKG_DIR>/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.

View File

@ -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:

View File

@ -19,7 +19,7 @@ cd <path to vcpkg>
```
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.

View File

@ -587,7 +587,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;
@ -628,7 +628,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<chatJoinRequest> = 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<int53> = ChatJoinRequestsInfo;
@ -762,7 +762,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
@ -2289,7 +2289,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

View File

@ -13416,7 +13416,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)});
}
@ -15251,60 +15251,39 @@ void ContactsManager::get_channel_participants(ChannelId channel_id,
->send(channel_id, participants_filter, offset, limit);
}
vector<DialogAdministrator> ContactsManager::get_dialog_administrators(DialogId dialog_id, int left_tries,
Promise<Unit> &&promise) {
LOG(INFO) << "Receive GetChatAdministrators request in " << dialog_id << " with " << left_tries << " left tries";
td_api::object_ptr<td_api::chatAdministrators> ContactsManager::get_chat_administrators_object(
const vector<DialogAdministrator> &dialog_administrators) {
auto administrator_objects = transform(dialog_administrators, [this](const DialogAdministrator &administrator) {
return administrator.get_chat_administrator_object(this);
});
return td_api::make_object<td_api::chatAdministrators>(std::move(administrator_objects));
}
void ContactsManager::get_dialog_administrators(DialogId dialog_id,
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&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<td_api::chatAdministrators>());
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<uint64>(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<Unit> &&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),
@ -15314,16 +15293,22 @@ void ContactsManager::load_dialog_administrators(DialogId dialog_id, Promise<Uni
&ContactsManager::on_load_dialog_administrators_from_database,
dialog_id, std::move(value), std::move(promise));
}));
} else {
promise.set_value(Unit());
return;
}
reload_dialog_administrators(dialog_id, {}, std::move(promise));
}
void ContactsManager::on_load_dialog_administrators_from_database(DialogId dialog_id, string value,
Promise<Unit> &&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<td_api::object_ptr<td_api::chatAdministrators>> &&promise) {
TRY_STATUS_PROMISE(promise, G()->close_status());
if (value.empty()) {
return reload_dialog_administrators(dialog_id, {}, std::move(promise));
}
vector<DialogAdministrator> administrators;
@ -15349,13 +15334,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<DialogAdministrator> administrators, Result<> result,
Promise<Unit> 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<DialogAdministrator> administrators, Result<> result,
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&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) {
@ -15411,19 +15401,49 @@ void ContactsManager::on_update_dialog_administrators(DialogId dialog_id, vector
}
}
void ContactsManager::reload_dialog_administrators(DialogId dialog_id, int64 hash, Promise<Unit> &&promise) {
void ContactsManager::reload_dialog_administrators(DialogId dialog_id,
const vector<DialogAdministrator> &dialog_administrators,
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise) {
auto query_promise = PromiseCreator::lambda(
[actor_id = actor_id(this), dialog_id, promise = std::move(promise)](Result<Unit> &&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<GetChannelAdministratorsQuery>(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<uint64>(administrator.get_user_id().get());
}));
td_->create_handler<GetChannelAdministratorsQuery>(std::move(query_promise))
->send(dialog_id.get_channel_id(), hash);
break;
}
default:
UNREACHABLE();
}
}
void ContactsManager::on_reload_dialog_administrators(
DialogId dialog_id, Promise<td_api::object_ptr<td_api::chatAdministrators>> &&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()) {

View File

@ -536,7 +536,7 @@ class ContactsManager final : public Actor {
void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter,
Promise<DialogParticipants> &&promise);
vector<DialogAdministrator> get_dialog_administrators(DialogId dialog_id, int left_tries, Promise<Unit> &&promise);
void get_dialog_administrators(DialogId dialog_id, Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise);
void get_channel_participants(ChannelId channel_id, tl_object_ptr<td_api::SupergroupMembersFilter> &&filter,
string additional_query, int32 offset, int32 limit, int32 additional_limit,
@ -1478,16 +1478,23 @@ class ContactsManager final : public Actor {
void finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant,
Promise<DialogParticipant> &&promise);
td_api::object_ptr<td_api::chatAdministrators> get_chat_administrators_object(
const vector<DialogAdministrator> &dialog_administrators);
static string get_dialog_administrators_database_key(DialogId dialog_id);
void load_dialog_administrators(DialogId dialog_id, Promise<Unit> &&promise);
void on_load_dialog_administrators_from_database(DialogId dialog_id, string value, Promise<Unit> &&promise);
void on_load_dialog_administrators_from_database(DialogId dialog_id, string value,
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise);
void on_load_administrator_users_finished(DialogId dialog_id, vector<DialogAdministrator> administrators,
Result<> result, Promise<Unit> promise);
Result<> result,
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise);
void reload_dialog_administrators(DialogId dialog_id, int64 hash, Promise<Unit> &&promise);
void reload_dialog_administrators(DialogId dialog_id, const vector<DialogAdministrator> &dialog_administrators,
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise);
void on_reload_dialog_administrators(DialogId dialog_id,
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise);
void remove_dialog_suggested_action(SuggestedAction action);

View File

@ -48,6 +48,9 @@ MessageReplyInfo::MessageReplyInfo(tl_object_ptr<telegram_api::messageReplies> &
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 {

View File

@ -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<telegram_api::messageReplies> &&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);
}
}
};

View File

@ -7385,12 +7385,10 @@ void MessagesManager::on_dialog_action(DialogId dialog_id, MessageId top_thread_
}
}
if (!G()->shared_config().get_option_boolean("ignore_update_user_chat_action")) {
if (top_thread_message_id.is_valid()) {
send_update_chat_action(dialog_id, MessageId(), typing_dialog_id, action);
}
send_update_chat_action(dialog_id, top_thread_message_id, typing_dialog_id, action);
}
}
void MessagesManager::cancel_dialog_action(DialogId dialog_id, const Message *m) {
@ -14022,7 +14020,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;
}
@ -24052,7 +24050,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();
@ -25523,7 +25521,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:
@ -29862,7 +29860,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;
}
@ -30728,13 +30726,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<UserId> &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;
@ -30773,6 +30771,11 @@ void MessagesManager::fix_pending_join_requests(DialogId dialog_id, int32 &pendi
<< pending_join_request_user_ids.size();
pending_join_request_count = narrow_cast<int32>(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,
@ -32958,12 +32961,14 @@ 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;
}
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);
}
}
}
}
if (!from_update && !message->is_failed_to_send) {
MessageId max_message_id;
@ -33328,21 +33333,17 @@ 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 (G()->shared_config().get_option_boolean("enable_reactive_channel_difference", false) == false) {
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);
}
}
} else {
if (G()->shared_config().get_option_boolean("enable_reactive_channel_difference", false) == false) {
LOG(ERROR) << "Have_next is true, but there is no next message after " << previous_message_id << " from "
<< source << " in " << dialog_id;
dump_debug_message_op(d);
}
}
}
LOG(INFO) << "Attach " << message_id << " to the previous " << previous_message_id << " in " << dialog_id;
message->have_previous = true;
@ -33959,7 +33960,7 @@ void MessagesManager::delete_message_files(DialogId dialog_id, const Message *m)
bool MessagesManager::need_delete_file(FullMessageId full_message_id, FileId file_id) const {
if (being_readded_message_id_ == full_message_id) {
return false;
}
}
auto main_file_id = td_->file_manager_->get_file_view(file_id).file_id();
auto full_message_ids = td_->file_reference_manager_->get_some_message_file_sources(main_file_id);
@ -33985,7 +33986,7 @@ bool MessagesManager::need_delete_message_files(DialogId dialog_id, const Messag
}
if (being_readded_message_id_ == FullMessageId{dialog_id, m->message_id}) {
return false;
}
}
if (m->forward_info != nullptr && m->forward_info->from_dialog_id.is_valid() &&
m->forward_info->from_message_id.is_valid()) {

View File

@ -1838,7 +1838,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;

View File

@ -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<SleepActor>("RetryLoadSpecialStickerSetActor", Random::fast(300, 600),
PromiseCreator::lambda([actor_id = actor_id(this), type](Result<Unit> result) mutable {

View File

@ -1765,30 +1765,6 @@ class UpgradeGroupChatToSupergroupChatRequest final : public RequestActor<> {
}
};
class GetChatAdministratorsRequest final : public RequestActor<> {
DialogId dialog_id_;
vector<DialogAdministrator> administrators_;
void do_run(Promise<Unit> &&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<td_api::chatAdministrators>(std::move(administrator_objects)));
}
public:
GetChatAdministratorsRequest(ActorShared<Td> 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_;
@ -6235,7 +6211,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) {

View File

@ -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<FullMessageId>(web_page_messages_[web_page_id].begin(), web_page_messages_[web_page_id].end());
} else {
CHECK(web_page_messages_.count(web_page_id) == 0);
}

View File

@ -4058,9 +4058,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<td_api::getChatEventLog>(as_chat_id(chat_id), "", 0, as_limit(limit), nullptr,
vector<int64>()));
as_user_ids(user_ids)));
} else if (op == "join") {
send_request(td_api::make_object<td_api::joinChat>(as_chat_id(args)));
} else if (op == "leave") {