Merge remote-tracking branch 'td/master'
This commit is contained in:
commit
3440f2c07e
29
build.html
29
build.html
@ -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);
|
||||
|
@ -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_);
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
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,9 +32961,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33328,19 +33333,15 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -33958,8 +33959,8 @@ 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;
|
||||
}
|
||||
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);
|
||||
@ -33984,8 +33985,8 @@ bool MessagesManager::need_delete_message_files(DialogId dialog_id, const Messag
|
||||
return false;
|
||||
}
|
||||
if (being_readded_message_id_ == FullMessageId{dialog_id, m->message_id}) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m->forward_info != nullptr && m->forward_info->from_dialog_id.is_valid() &&
|
||||
m->forward_info->from_message_id.is_valid()) {
|
||||
@ -36525,7 +36526,7 @@ void MessagesManager::run_after_channel_difference(DialogId dialog_id, Promise<U
|
||||
|
||||
const Dialog *d = get_dialog(dialog_id);
|
||||
get_channel_difference(dialog_id, d == nullptr ? load_channel_pts(dialog_id) : d->pts, true,
|
||||
"run_after_channel_difference");
|
||||
"run_after_channel_difference");
|
||||
}
|
||||
|
||||
bool MessagesManager::running_get_channel_difference(DialogId dialog_id) const {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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") {
|
||||
|
Loading…
Reference in New Issue
Block a user