Merge commit '3a626f6df2003e4cd834477de65dc900f074adda'
This commit is contained in:
commit
8c0ce47f61
@ -180,7 +180,7 @@ To build `TDLib` in Release mode using MSVC, you will need to additionally speci
|
|||||||
|
|
||||||
<a name="using-cxx"></a>
|
<a name="using-cxx"></a>
|
||||||
## Using in CMake C++ projects
|
## Using in CMake C++ projects
|
||||||
For C++ projects that use CMake, the best approach is to build `TDLib` as part of your project or to use a prebuilt installation.
|
For C++ projects that use CMake, the best approach is to build `TDLib` as part of your project or to install it system-wide.
|
||||||
|
|
||||||
There are several libraries that you could use in your CMake project:
|
There are several libraries that you could use in your CMake project:
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ This is an example of building TDLib with `C++/CLI` support and an example of TD
|
|||||||
* Download and install Microsoft Visual Studio 2015 or later.
|
* Download and install Microsoft Visual Studio 2015 or later.
|
||||||
* Download and install [CMake](https://cmake.org/download/); choose "Add CMake to the system PATH" option while installing.
|
* Download and install [CMake](https://cmake.org/download/); choose "Add CMake to the system PATH" option while installing.
|
||||||
* Install [vcpkg](https://github.com/Microsoft/vcpkg#quick-start) or update it to the latest version using `vcpkg update` and following received instructions.
|
* Install [vcpkg](https://github.com/Microsoft/vcpkg#quick-start) or update it to the latest version using `vcpkg update` and following received instructions.
|
||||||
* Install `zlib` and `openssl` for using `vcpkg`:
|
* Install `zlib` and `openssl` using `vcpkg`:
|
||||||
```
|
```
|
||||||
cd <path to vcpkg>
|
cd <path to vcpkg>
|
||||||
.\vcpkg.exe install openssl:x64-windows openssl:x86-windows zlib:x64-windows zlib:x86-windows
|
.\vcpkg.exe install openssl:x64-windows openssl:x86-windows zlib:x64-windows zlib:x86-windows
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
To run this example, you will need installed JDK >= 1.6.
|
To run this example, you will need installed JDK >= 1.6.
|
||||||
For Javadoc documentation generation PHP is needed.
|
For Javadoc documentation generation PHP is needed.
|
||||||
|
|
||||||
TDLib should be prebuilt for using with Java and installed to local subdirectory `td/` as follows:
|
TDLib should be prebuilt with JNI bindings and installed to local subdirectory `td/` as follows:
|
||||||
```
|
```
|
||||||
cd <path to TDLib sources>
|
cd <path to TDLib sources>
|
||||||
mkdir jnibuild
|
mkdir jnibuild
|
||||||
|
@ -109,7 +109,7 @@ documentAttributeVideo66#ef02ce6 flags:# round_message:flags.0?true duration:int
|
|||||||
|
|
||||||
// layer 73
|
// layer 73
|
||||||
|
|
||||||
decryptedMessage#91cc4674 flags:# random_id:long ttl:int message:string media:flags.9?DecryptedMessageMedia entities:flags.7?Vector<MessageEntity> via_bot_name:flags.11?string reply_to_random_id:flags.3?long grouped_id:flags.17?long = DecryptedMessage;
|
decryptedMessage#91cc4674 flags:# silent:flags.5?true random_id:long ttl:int message:string media:flags.9?DecryptedMessageMedia entities:flags.7?Vector<MessageEntity> via_bot_name:flags.11?string reply_to_random_id:flags.3?long grouped_id:flags.17?long = DecryptedMessage;
|
||||||
|
|
||||||
// layer 101
|
// layer 101
|
||||||
|
|
||||||
|
Binary file not shown.
@ -71,7 +71,7 @@ AuthManager::AuthManager(int32 api_id, const string &api_hash, ActorShared<> par
|
|||||||
|
|
||||||
void AuthManager::start_up() {
|
void AuthManager::start_up() {
|
||||||
if (state_ == State::LoggingOut) {
|
if (state_ == State::LoggingOut) {
|
||||||
start_net_query(NetQueryType::LogOut, G()->net_query_creator().create(telegram_api::auth_logOut()));
|
send_log_out_query();
|
||||||
} else if (state_ == State::DestroyingKeys) {
|
} else if (state_ == State::DestroyingKeys) {
|
||||||
destroy_auth_keys();
|
destroy_auth_keys();
|
||||||
}
|
}
|
||||||
@ -364,10 +364,16 @@ void AuthManager::log_out(uint64 query_id) {
|
|||||||
LOG(INFO) << "Logging out";
|
LOG(INFO) << "Logging out";
|
||||||
G()->td_db()->get_binlog_pmc()->set("auth", "logout");
|
G()->td_db()->get_binlog_pmc()->set("auth", "logout");
|
||||||
update_state(State::LoggingOut);
|
update_state(State::LoggingOut);
|
||||||
start_net_query(NetQueryType::LogOut, G()->net_query_creator().create(telegram_api::auth_logOut()));
|
send_log_out_query();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AuthManager::send_log_out_query() {
|
||||||
|
auto query = G()->net_query_creator().create(telegram_api::auth_logOut());
|
||||||
|
query->set_priority(1);
|
||||||
|
start_net_query(NetQueryType::LogOut, std::move(query));
|
||||||
|
}
|
||||||
|
|
||||||
void AuthManager::delete_account(uint64 query_id, const string &reason) {
|
void AuthManager::delete_account(uint64 query_id, const string &reason) {
|
||||||
if (state_ != State::Ok && state_ != State::WaitPassword) {
|
if (state_ != State::Ok && state_ != State::WaitPassword) {
|
||||||
return on_query_error(query_id, Status::Error(8, "Need to log in first"));
|
return on_query_error(query_id, Status::Error(8, "Need to log in first"));
|
||||||
@ -833,6 +839,8 @@ void AuthManager::update_state(State new_state, bool force, bool should_save_sta
|
|||||||
if (state_ == new_state && !force) {
|
if (state_ == new_state && !force) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bool skip_update = (state_ == State::LoggingOut || state_ == State::DestroyingKeys) &&
|
||||||
|
(new_state == State::LoggingOut || new_state == State::DestroyingKeys);
|
||||||
state_ = new_state;
|
state_ = new_state;
|
||||||
if (should_save_state) {
|
if (should_save_state) {
|
||||||
save_state();
|
save_state();
|
||||||
@ -840,8 +848,10 @@ void AuthManager::update_state(State new_state, bool force, bool should_save_sta
|
|||||||
if (new_state == State::LoggingOut || new_state == State::DestroyingKeys) {
|
if (new_state == State::LoggingOut || new_state == State::DestroyingKeys) {
|
||||||
send_closure(G()->state_manager(), &StateManager::on_logging_out, true);
|
send_closure(G()->state_manager(), &StateManager::on_logging_out, true);
|
||||||
}
|
}
|
||||||
|
if (!skip_update) {
|
||||||
send_closure(G()->td(), &Td::send_update,
|
send_closure(G()->td(), &Td::send_update,
|
||||||
make_tl_object<td_api::updateAuthorizationState>(get_authorization_state_object(state_)));
|
make_tl_object<td_api::updateAuthorizationState>(get_authorization_state_object(state_)));
|
||||||
|
}
|
||||||
|
|
||||||
if (!pending_get_authorization_state_requests_.empty()) {
|
if (!pending_get_authorization_state_requests_.empty()) {
|
||||||
auto query_ids = std::move(pending_get_authorization_state_requests_);
|
auto query_ids = std::move(pending_get_authorization_state_requests_);
|
||||||
|
@ -217,6 +217,8 @@ class AuthManager : public NetActor {
|
|||||||
static void on_update_login_token_static(void *td);
|
static void on_update_login_token_static(void *td);
|
||||||
void send_export_login_token_query();
|
void send_export_login_token_query();
|
||||||
void set_login_token_expires_at(double login_token_expires_at);
|
void set_login_token_expires_at(double login_token_expires_at);
|
||||||
|
|
||||||
|
void send_log_out_query();
|
||||||
void destroy_auth_keys();
|
void destroy_auth_keys();
|
||||||
|
|
||||||
void on_send_code_result(NetQueryPtr &result);
|
void on_send_code_result(NetQueryPtr &result);
|
||||||
|
@ -37,18 +37,9 @@ class MultiTd : public Actor {
|
|||||||
CHECK(td.empty());
|
CHECK(td.empty());
|
||||||
|
|
||||||
string name = "Td";
|
string name = "Td";
|
||||||
class TdActorContext : public ActorContext {
|
auto context = std::make_shared<td::ActorContext>();
|
||||||
public:
|
|
||||||
explicit TdActorContext(string tag) : tag_(std::move(tag)) {
|
|
||||||
}
|
|
||||||
int32 get_id() const override {
|
|
||||||
return 0x172ae58d;
|
|
||||||
}
|
|
||||||
string tag_;
|
|
||||||
};
|
|
||||||
auto context = std::make_shared<TdActorContext>(to_string(td_id));
|
|
||||||
auto old_context = set_context(context);
|
auto old_context = set_context(context);
|
||||||
auto old_tag = set_tag(context->tag_);
|
auto old_tag = set_tag(to_string(td_id));
|
||||||
td = create_actor<Td>("Td", std::move(callback), options_);
|
td = create_actor<Td>("Td", std::move(callback), options_);
|
||||||
set_context(old_context);
|
set_context(old_context);
|
||||||
set_tag(old_tag);
|
set_tag(old_tag);
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
int MessageEntity::get_type_priority(Type type) {
|
int MessageEntity::get_type_priority(Type type) {
|
||||||
static const int types[] = {50, 50, 50, 50, 50, 90, 91, 20, 11, 10, 49, 49, 50, 50, 92, 93, 0};
|
static const int types[] = {50, 50, 50, 50, 50, 90, 91, 20, 11, 10, 49, 49, 50, 50, 92, 93, 0, 50};
|
||||||
return types[static_cast<int32>(type)];
|
return types[static_cast<int32>(type)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ class ContactsManager;
|
|||||||
|
|
||||||
class MessageEntity {
|
class MessageEntity {
|
||||||
public:
|
public:
|
||||||
|
// don't forget to update get_type_priority()
|
||||||
enum class Type : int32 {
|
enum class Type : int32 {
|
||||||
Mention,
|
Mention,
|
||||||
Hashtag,
|
Hashtag,
|
||||||
|
@ -2056,7 +2056,7 @@ class SendSecretMessageActor : public NetActor {
|
|||||||
public:
|
public:
|
||||||
void send(DialogId dialog_id, int64 reply_to_random_id, int32 ttl, const string &text, SecretInputMedia media,
|
void send(DialogId dialog_id, int64 reply_to_random_id, int32 ttl, const string &text, SecretInputMedia media,
|
||||||
vector<tl_object_ptr<secret_api::MessageEntity>> &&entities, UserId via_bot_user_id, int64 media_album_id,
|
vector<tl_object_ptr<secret_api::MessageEntity>> &&entities, UserId via_bot_user_id, int64 media_album_id,
|
||||||
int64 random_id) {
|
bool disable_notification, int64 random_id) {
|
||||||
if (false && !media.empty()) {
|
if (false && !media.empty()) {
|
||||||
td->messages_manager_->on_send_secret_message_error(random_id, Status::Error(400, "FILE_PART_1_MISSING"), Auto());
|
td->messages_manager_->on_send_secret_message_error(random_id, Status::Error(400, "FILE_PART_1_MISSING"), Auto());
|
||||||
stop();
|
stop();
|
||||||
@ -2083,13 +2083,16 @@ class SendSecretMessageActor : public NetActor {
|
|||||||
CHECK(media_album_id < 0);
|
CHECK(media_album_id < 0);
|
||||||
flags |= secret_api::decryptedMessage::GROUPED_ID_MASK;
|
flags |= secret_api::decryptedMessage::GROUPED_ID_MASK;
|
||||||
}
|
}
|
||||||
|
if (disable_notification) {
|
||||||
|
flags |= secret_api::decryptedMessage::SILENT_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
send_closure(G()->secret_chats_manager(), &SecretChatsManager::send_message, dialog_id.get_secret_chat_id(),
|
send_closure(
|
||||||
|
G()->secret_chats_manager(), &SecretChatsManager::send_message, dialog_id.get_secret_chat_id(),
|
||||||
make_tl_object<secret_api::decryptedMessage>(
|
make_tl_object<secret_api::decryptedMessage>(
|
||||||
flags, random_id, ttl, text, std::move(media.decrypted_media_), std::move(entities),
|
flags, false /*ignored*/, random_id, ttl, text, std::move(media.decrypted_media_), std::move(entities),
|
||||||
td->contacts_manager_->get_user_username(via_bot_user_id), reply_to_random_id, -media_album_id),
|
td->contacts_manager_->get_user_username(via_bot_user_id), reply_to_random_id, -media_album_id),
|
||||||
std::move(media.input_file_),
|
std::move(media.input_file_), PromiseCreator::event(self_closure(this, &SendSecretMessageActor::done)));
|
||||||
PromiseCreator::event(self_closure(this, &SendSecretMessageActor::done)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void done() {
|
void done() {
|
||||||
@ -3183,10 +3186,14 @@ class DeleteMessagesQuery : public Td::ResultHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void on_error(uint64 id, Status status) override {
|
void on_error(uint64 id, Status status) override {
|
||||||
if (!G()->is_expected_error(status) &&
|
if (!G()->is_expected_error(status)) {
|
||||||
(dialog_id_.get_type() == DialogType::User || status.message() != "MESSAGE_DELETE_FORBIDDEN")) {
|
// MESSAGE_DELETE_FORBIDDEN can be returned in group chats when administrator rights was removed
|
||||||
|
// MESSAGE_DELETE_FORBIDDEN can be returned in private chats for bots when revoke time limit exceeded
|
||||||
|
if (status.message() != "MESSAGE_DELETE_FORBIDDEN" ||
|
||||||
|
(dialog_id_.get_type() == DialogType::User && !td->auth_manager_->is_bot())) {
|
||||||
LOG(ERROR) << "Receive error for delete messages: " << status;
|
LOG(ERROR) << "Receive error for delete messages: " << status;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
promise_.set_error(std::move(status));
|
promise_.set_error(std::move(status));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -6411,7 +6418,7 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p
|
|||||||
auto channel_id = dialog_id.get_channel_id();
|
auto channel_id = dialog_id.get_channel_id();
|
||||||
if (!td_->contacts_manager_->have_channel(channel_id)) {
|
if (!td_->contacts_manager_->have_channel(channel_id)) {
|
||||||
// do not create dialog if there is no info about the channel
|
// do not create dialog if there is no info about the channel
|
||||||
LOG(WARNING) << "There is no info about " << channel_id << ", so ignore " << oneline(to_string(update));
|
LOG(INFO) << "There is no info about " << channel_id << ", so ignore " << oneline(to_string(update));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8030,7 +8037,9 @@ void MessagesManager::after_get_difference() {
|
|||||||
|
|
||||||
vector<FullMessageId> update_message_ids_to_delete;
|
vector<FullMessageId> update_message_ids_to_delete;
|
||||||
for (auto &it : update_message_ids_) {
|
for (auto &it : update_message_ids_) {
|
||||||
// this is impossible for ordinary chats because updates coming during getDifference have already been applied
|
// there can be unhandled updateMessageId updates after getDifference even for ordinary chats,
|
||||||
|
// because despite updates coming during getDifference have already been applied,
|
||||||
|
// some of them could be postponed because of pts gap
|
||||||
auto full_message_id = it.first;
|
auto full_message_id = it.first;
|
||||||
auto dialog_id = full_message_id.get_dialog_id();
|
auto dialog_id = full_message_id.get_dialog_id();
|
||||||
auto message_id = full_message_id.get_message_id();
|
auto message_id = full_message_id.get_message_id();
|
||||||
@ -8059,9 +8068,13 @@ void MessagesManager::after_get_difference() {
|
|||||||
|
|
||||||
const Dialog *d = get_dialog(dialog_id);
|
const Dialog *d = get_dialog(dialog_id);
|
||||||
CHECK(d != nullptr);
|
CHECK(d != nullptr);
|
||||||
|
if (dialog_id.get_type() == DialogType::Channel || pending_updates_.empty() || message_id.is_scheduled() ||
|
||||||
|
message_id <= d->last_new_message_id) {
|
||||||
LOG(ERROR) << "Receive updateMessageId from " << it.second << " to " << full_message_id
|
LOG(ERROR) << "Receive updateMessageId from " << it.second << " to " << full_message_id
|
||||||
<< " but not receive corresponding message, last_new_message_id = " << d->last_new_message_id;
|
<< " but not receive corresponding message, last_new_message_id = " << d->last_new_message_id;
|
||||||
if (dialog_id.get_type() != DialogType::Channel) {
|
}
|
||||||
|
if (dialog_id.get_type() != DialogType::Channel &&
|
||||||
|
(pending_updates_.empty() || message_id.is_scheduled() || message_id <= d->last_new_message_id)) {
|
||||||
dump_debug_message_op(get_dialog(dialog_id));
|
dump_debug_message_op(get_dialog(dialog_id));
|
||||||
}
|
}
|
||||||
if (message_id.is_scheduled() || message_id <= d->last_new_message_id) {
|
if (message_id.is_scheduled() || message_id <= d->last_new_message_id) {
|
||||||
@ -8849,7 +8862,7 @@ void MessagesManager::delete_dialog_messages_from_updates(DialogId dialog_id, co
|
|||||||
send_update_delete_messages(dialog_id, std::move(deleted_message_ids), true, false);
|
send_update_delete_messages(dialog_id, std::move(deleted_message_ids), true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
string MessagesManager::get_search_text(const Message *m) const {
|
string MessagesManager::get_message_search_text(const Message *m) const {
|
||||||
if (m->is_content_secret) {
|
if (m->is_content_secret) {
|
||||||
return string();
|
return string();
|
||||||
}
|
}
|
||||||
@ -11615,6 +11628,9 @@ void MessagesManager::on_get_secret_message(SecretChatId secret_chat_id, UserId
|
|||||||
if ((message->flags_ & secret_api::decryptedMessage::MEDIA_MASK) != 0) {
|
if ((message->flags_ & secret_api::decryptedMessage::MEDIA_MASK) != 0) {
|
||||||
flags |= MESSAGE_FLAG_HAS_MEDIA;
|
flags |= MESSAGE_FLAG_HAS_MEDIA;
|
||||||
}
|
}
|
||||||
|
if ((message->flags_ & secret_api::decryptedMessage::SILENT_MASK) != 0) {
|
||||||
|
flags |= MESSAGE_FLAG_IS_SILENT;
|
||||||
|
}
|
||||||
|
|
||||||
if (!clean_input_string(message->via_bot_name_)) {
|
if (!clean_input_string(message->via_bot_name_)) {
|
||||||
LOG(WARNING) << "Receive invalid bot username " << message->via_bot_name_;
|
LOG(WARNING) << "Receive invalid bot username " << message->via_bot_name_;
|
||||||
@ -11893,16 +11909,6 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32 flags = message_info.flags;
|
int32 flags = message_info.flags;
|
||||||
if (flags &
|
|
||||||
~(MESSAGE_FLAG_IS_OUT | MESSAGE_FLAG_IS_FORWARDED | MESSAGE_FLAG_IS_REPLY | MESSAGE_FLAG_HAS_MENTION |
|
|
||||||
MESSAGE_FLAG_HAS_UNREAD_CONTENT | MESSAGE_FLAG_HAS_REPLY_MARKUP | MESSAGE_FLAG_HAS_ENTITIES |
|
|
||||||
MESSAGE_FLAG_HAS_FROM_ID | MESSAGE_FLAG_HAS_MEDIA | MESSAGE_FLAG_HAS_VIEWS | MESSAGE_FLAG_IS_SENT_VIA_BOT |
|
|
||||||
MESSAGE_FLAG_IS_SILENT | MESSAGE_FLAG_IS_POST | MESSAGE_FLAG_HAS_EDIT_DATE | MESSAGE_FLAG_HAS_AUTHOR_SIGNATURE |
|
|
||||||
MESSAGE_FLAG_HAS_MEDIA_ALBUM_ID | MESSAGE_FLAG_IS_FROM_SCHEDULED | MESSAGE_FLAG_IS_LEGACY |
|
|
||||||
MESSAGE_FLAG_HIDE_EDIT_DATE | MESSAGE_FLAG_IS_RESTRICTED)) {
|
|
||||||
LOG(ERROR) << "Unsupported message flags = " << flags << " received";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_outgoing = (flags & MESSAGE_FLAG_IS_OUT) != 0;
|
bool is_outgoing = (flags & MESSAGE_FLAG_IS_OUT) != 0;
|
||||||
bool is_silent = (flags & MESSAGE_FLAG_IS_SILENT) != 0;
|
bool is_silent = (flags & MESSAGE_FLAG_IS_SILENT) != 0;
|
||||||
bool is_channel_post = (flags & MESSAGE_FLAG_IS_POST) != 0;
|
bool is_channel_post = (flags & MESSAGE_FLAG_IS_POST) != 0;
|
||||||
@ -19979,7 +19985,14 @@ tl_object_ptr<td_api::message> MessagesManager::get_message_object(DialogId dial
|
|||||||
auto live_location_date = m->is_failed_to_send ? 0 : m->date;
|
auto live_location_date = m->is_failed_to_send ? 0 : m->date;
|
||||||
auto date = is_scheduled ? 0 : m->date;
|
auto date = is_scheduled ? 0 : m->date;
|
||||||
auto edit_date = m->hide_edit_date ? 0 : m->edit_date;
|
auto edit_date = m->hide_edit_date ? 0 : m->edit_date;
|
||||||
auto views = m->message_id.is_scheduled() || (m->message_id.is_local() && m->forward_info == nullptr) ? 0 : m->views;
|
auto views = m->views;
|
||||||
|
if (m->message_id.is_scheduled()) {
|
||||||
|
if (m->forward_info == nullptr || is_broadcast_channel(dialog_id)) {
|
||||||
|
views = 0;
|
||||||
|
}
|
||||||
|
} else if (m->message_id.is_local() && m->forward_info == nullptr) {
|
||||||
|
views = 0;
|
||||||
|
}
|
||||||
return make_tl_object<td_api::message>(
|
return make_tl_object<td_api::message>(
|
||||||
m->message_id.get(), td_->contacts_manager_->get_user_id_object(m->sender_user_id, "sender_user_id"),
|
m->message_id.get(), td_->contacts_manager_->get_user_id_object(m->sender_user_id, "sender_user_id"),
|
||||||
dialog_id.get(), std::move(sending_state), std::move(scheduling_state), is_outgoing, can_be_edited,
|
dialog_id.get(), std::move(sending_state), std::move(scheduling_state), is_outgoing, can_be_edited,
|
||||||
@ -20850,7 +20863,7 @@ void MessagesManager::do_send_message(DialogId dialog_id, const Message *m, vect
|
|||||||
m->reply_to_random_id, m->ttl, message_text->text,
|
m->reply_to_random_id, m->ttl, message_text->text,
|
||||||
get_secret_input_media(content, td_, nullptr, BufferSlice(), layer),
|
get_secret_input_media(content, td_, nullptr, BufferSlice(), layer),
|
||||||
get_input_secret_message_entities(message_text->entities, layer), m->via_bot_user_id,
|
get_input_secret_message_entities(message_text->entities, layer), m->via_bot_user_id,
|
||||||
m->media_album_id, random_id);
|
m->media_album_id, m->disable_notification, random_id);
|
||||||
} else {
|
} else {
|
||||||
send_closure(td_->create_net_actor<SendMessageActor>(), &SendMessageActor::send, get_message_flags(m), dialog_id,
|
send_closure(td_->create_net_actor<SendMessageActor>(), &SendMessageActor::send, get_message_flags(m), dialog_id,
|
||||||
m->reply_to_message_id, get_message_schedule_date(m), get_input_reply_markup(m->reply_markup),
|
m->reply_to_message_id, get_message_schedule_date(m), get_input_reply_markup(m->reply_markup),
|
||||||
@ -21030,7 +21043,7 @@ void MessagesManager::on_secret_message_media_uploaded(DialogId dialog_id, const
|
|||||||
}
|
}
|
||||||
send_closure(td_->create_net_actor<SendSecretMessageActor>(), &SendSecretMessageActor::send, dialog_id,
|
send_closure(td_->create_net_actor<SendSecretMessageActor>(), &SendSecretMessageActor::send, dialog_id,
|
||||||
m->reply_to_random_id, m->ttl, "", std::move(secret_input_media), std::move(entities),
|
m->reply_to_random_id, m->ttl, "", std::move(secret_input_media), std::move(entities),
|
||||||
m->via_bot_user_id, m->media_album_id, random_id);
|
m->via_bot_user_id, m->media_album_id, m->disable_notification, random_id);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23111,8 +23124,9 @@ Result<vector<MessageId>> MessagesManager::forward_messages(DialogId to_dialog_i
|
|||||||
m->real_forward_from_message_id = message_id;
|
m->real_forward_from_message_id = message_id;
|
||||||
m->via_bot_user_id = forwarded_message->via_bot_user_id;
|
m->via_bot_user_id = forwarded_message->via_bot_user_id;
|
||||||
m->in_game_share = in_game_share;
|
m->in_game_share = in_game_share;
|
||||||
if (forwarded_message->views > 0 && m->forward_info != nullptr) {
|
if (forwarded_message->views > 0 && m->forward_info != nullptr && m->views == 0 &&
|
||||||
m->views = 1;
|
!(m->message_id.is_scheduled() && is_broadcast_channel(to_dialog_id))) {
|
||||||
|
m->views = forwarded_message->views;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_game) {
|
if (is_game) {
|
||||||
@ -27385,6 +27399,11 @@ void MessagesManager::set_dialog_photo(DialogId dialog_id, const tl_object_ptr<t
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (input_file == nullptr) {
|
||||||
|
send_edit_dialog_photo_query(dialog_id, FileId(), make_tl_object<telegram_api::inputChatPhotoEmpty>(),
|
||||||
|
std::move(promise));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const double MAX_ANIMATION_DURATION = 10.0;
|
const double MAX_ANIMATION_DURATION = 10.0;
|
||||||
if (main_frame_timestamp < 0.0 || main_frame_timestamp > MAX_ANIMATION_DURATION) {
|
if (main_frame_timestamp < 0.0 || main_frame_timestamp > MAX_ANIMATION_DURATION) {
|
||||||
@ -29352,7 +29371,7 @@ void MessagesManager::add_message_to_database(const Dialog *d, const Message *m,
|
|||||||
unique_message_id = message_id.get_server_message_id();
|
unique_message_id = message_id.get_server_message_id();
|
||||||
}
|
}
|
||||||
// FOR DEBUG
|
// FOR DEBUG
|
||||||
// text = get_search_text(m);
|
// text = get_message_search_text(m);
|
||||||
// if (!text.empty()) {
|
// if (!text.empty()) {
|
||||||
// search_id = (static_cast<int64>(m->date) << 32) | static_cast<uint32>(Random::secure_int32());
|
// search_id = (static_cast<int64>(m->date) << 32) | static_cast<uint32>(Random::secure_int32());
|
||||||
// }
|
// }
|
||||||
@ -29361,7 +29380,7 @@ void MessagesManager::add_message_to_database(const Dialog *d, const Message *m,
|
|||||||
break;
|
break;
|
||||||
case DialogType::SecretChat:
|
case DialogType::SecretChat:
|
||||||
random_id = m->random_id;
|
random_id = m->random_id;
|
||||||
text = get_search_text(m);
|
text = get_message_search_text(m);
|
||||||
if (!text.empty()) {
|
if (!text.empty()) {
|
||||||
search_id = (static_cast<int64>(m->date) << 32) | static_cast<uint32>(m->random_id);
|
search_id = (static_cast<int64>(m->date) << 32) | static_cast<uint32>(m->random_id);
|
||||||
}
|
}
|
||||||
|
@ -2692,7 +2692,7 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
void try_hide_distance(DialogId dialog_id, const Message *m);
|
void try_hide_distance(DialogId dialog_id, const Message *m);
|
||||||
|
|
||||||
string get_search_text(const Message *m) const;
|
string get_message_search_text(const Message *m) const;
|
||||||
|
|
||||||
unique_ptr<Message> parse_message(DialogId dialog_id, const BufferSlice &value, bool is_scheduled);
|
unique_ptr<Message> parse_message(DialogId dialog_id, const BufferSlice &value, bool is_scheduled);
|
||||||
|
|
||||||
|
@ -1289,7 +1289,7 @@ Status SecretChatActor::do_inbound_message_decrypted(unique_ptr<logevent::Inboun
|
|||||||
auto old = move_tl_object_as<secret_api::decryptedMessage46>(message->decrypted_message_layer->message_);
|
auto old = move_tl_object_as<secret_api::decryptedMessage46>(message->decrypted_message_layer->message_);
|
||||||
old->flags_ &= ~secret_api::decryptedMessage::GROUPED_ID_MASK; // just in case
|
old->flags_ &= ~secret_api::decryptedMessage::GROUPED_ID_MASK; // just in case
|
||||||
message->decrypted_message_layer->message_ = secret_api::make_object<secret_api::decryptedMessage>(
|
message->decrypted_message_layer->message_ = secret_api::make_object<secret_api::decryptedMessage>(
|
||||||
old->flags_, old->random_id_, old->ttl_, std::move(old->message_), std::move(old->media_),
|
old->flags_, false /*ignored*/, old->random_id_, old->ttl_, std::move(old->message_), std::move(old->media_),
|
||||||
std::move(old->entities_), std::move(old->via_bot_name_), old->reply_to_random_id_, 0);
|
std::move(old->entities_), std::move(old->via_bot_name_), old->reply_to_random_id_, 0);
|
||||||
}
|
}
|
||||||
if (message->decrypted_message_layer->message_->get_id() == secret_api::decryptedMessageService8::ID) {
|
if (message->decrypted_message_layer->message_->get_id() == secret_api::decryptedMessageService8::ID) {
|
||||||
@ -1786,7 +1786,7 @@ void SecretChatActor::on_outbound_outer_send_message_promise(uint64 state_id, Pr
|
|||||||
promise.set_value(Unit()); // Seems like this message is at least stored to binlog already
|
promise.set_value(Unit()); // Seems like this message is at least stored to binlog already
|
||||||
if (state->send_result_) {
|
if (state->send_result_) {
|
||||||
state->send_result_({});
|
state->send_result_({});
|
||||||
} else {
|
} else if (state->message->is_sent) {
|
||||||
context_->on_send_message_error(state->message->random_id, Status::Error(400, "Message has already been sent"),
|
context_->on_send_message_error(state->message->random_id, Status::Error(400, "Message has already been sent"),
|
||||||
Auto());
|
Auto());
|
||||||
}
|
}
|
||||||
|
@ -3576,6 +3576,10 @@ class CliClient final : public Actor {
|
|||||||
|
|
||||||
std::tie(chat_id, title) = split(args);
|
std::tie(chat_id, title) = split(args);
|
||||||
send_request(td_api::make_object<td_api::setChatTitle>(as_chat_id(chat_id), title));
|
send_request(td_api::make_object<td_api::setChatTitle>(as_chat_id(chat_id), title));
|
||||||
|
} else if (op == "scpe") {
|
||||||
|
string chat_id = args;
|
||||||
|
|
||||||
|
send_request(td_api::make_object<td_api::setChatPhoto>(as_chat_id(chat_id), nullptr));
|
||||||
} else if (op == "scpp") {
|
} else if (op == "scpp") {
|
||||||
string chat_id;
|
string chat_id;
|
||||||
string photo_id;
|
string photo_id;
|
||||||
|
@ -266,6 +266,13 @@ class NetQuery : public TsListNode<NetQueryDebug> {
|
|||||||
finish_migrate(cancel_slot_);
|
finish_migrate(cancel_slot_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8 priority() const {
|
||||||
|
return priority_;
|
||||||
|
}
|
||||||
|
void set_priority(int8 priority) {
|
||||||
|
priority_ = priority;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
State state_ = State::Empty;
|
State state_ = State::Empty;
|
||||||
Type type_ = Type::Common;
|
Type type_ = Type::Common;
|
||||||
@ -284,6 +291,7 @@ class NetQuery : public TsListNode<NetQueryDebug> {
|
|||||||
uint32 session_rand_ = 0;
|
uint32 session_rand_ = 0;
|
||||||
|
|
||||||
bool may_be_lost_ = false;
|
bool may_be_lost_ = false;
|
||||||
|
int8 priority_{0};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct movable_atomic : public std::atomic<T> {
|
struct movable_atomic : public std::atomic<T> {
|
||||||
|
@ -117,6 +117,25 @@ class GenAuthKeyActor : public Actor {
|
|||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
void Session::PriorityQueue::push(NetQueryPtr query) {
|
||||||
|
auto priority = query->priority();
|
||||||
|
queries_[priority].push(std::move(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
NetQueryPtr Session::PriorityQueue::pop() {
|
||||||
|
CHECK(!empty());
|
||||||
|
auto it = queries_.begin();
|
||||||
|
auto res = it->second.pop();
|
||||||
|
if (it->second.empty()) {
|
||||||
|
queries_.erase(it);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Session::PriorityQueue::empty() const {
|
||||||
|
return queries_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
Session::Session(unique_ptr<Callback> callback, std::shared_ptr<AuthDataShared> shared_auth_data, int32 raw_dc_id,
|
Session::Session(unique_ptr<Callback> callback, std::shared_ptr<AuthDataShared> shared_auth_data, int32 raw_dc_id,
|
||||||
int32 dc_id, bool is_main, bool use_pfs, bool is_cdn, bool need_destroy,
|
int32 dc_id, bool is_main, bool use_pfs, bool is_cdn, bool need_destroy,
|
||||||
const mtproto::AuthKey &tmp_auth_key, std::vector<mtproto::ServerSalt> server_salts)
|
const mtproto::AuthKey &tmp_auth_key, std::vector<mtproto::ServerSalt> server_salts)
|
||||||
@ -344,7 +363,7 @@ void Session::return_query(NetQueryPtr &&query) {
|
|||||||
void Session::flush_pending_invoke_after_queries() {
|
void Session::flush_pending_invoke_after_queries() {
|
||||||
while (!pending_invoke_after_queries_.empty()) {
|
while (!pending_invoke_after_queries_.empty()) {
|
||||||
auto &query = pending_invoke_after_queries_.front();
|
auto &query = pending_invoke_after_queries_.front();
|
||||||
pending_queries_.push_back(std::move(query));
|
pending_queries_.push(std::move(query));
|
||||||
pending_invoke_after_queries_.pop_front();
|
pending_invoke_after_queries_.pop_front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -359,7 +378,7 @@ void Session::close() {
|
|||||||
auto &query = it.second.query;
|
auto &query = it.second.query;
|
||||||
query->set_message_id(0);
|
query->set_message_id(0);
|
||||||
query->cancel_slot_.clear_event();
|
query->cancel_slot_.clear_event();
|
||||||
pending_queries_.push_back(std::move(query));
|
pending_queries_.push(std::move(query));
|
||||||
}
|
}
|
||||||
sent_queries_.clear();
|
sent_queries_.clear();
|
||||||
sent_containers_.clear();
|
sent_containers_.clear();
|
||||||
@ -367,10 +386,9 @@ void Session::close() {
|
|||||||
flush_pending_invoke_after_queries();
|
flush_pending_invoke_after_queries();
|
||||||
CHECK(sent_queries_.empty());
|
CHECK(sent_queries_.empty());
|
||||||
while (!pending_queries_.empty()) {
|
while (!pending_queries_.empty()) {
|
||||||
auto &query = pending_queries_.front();
|
auto query = pending_queries_.pop();
|
||||||
query->set_error_resend();
|
query->set_error_resend();
|
||||||
return_query(std::move(query));
|
return_query(std::move(query));
|
||||||
pending_queries_.pop_front();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
callback_->on_closed();
|
callback_->on_closed();
|
||||||
@ -905,7 +923,7 @@ void Session::add_query(NetQueryPtr &&net_query) {
|
|||||||
net_query->debug("Session: pending");
|
net_query->debug("Session: pending");
|
||||||
LOG_IF(FATAL, UniqueId::extract_type(net_query->id()) == UniqueId::BindKey)
|
LOG_IF(FATAL, UniqueId::extract_type(net_query->id()) == UniqueId::BindKey)
|
||||||
<< "Add BindKey query inpo pending_queries_";
|
<< "Add BindKey query inpo pending_queries_";
|
||||||
pending_queries_.emplace_back(std::move(net_query));
|
pending_queries_.push(std::move(net_query));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::connection_send_query(ConnectionInfo *info, NetQueryPtr &&net_query, uint64 message_id) {
|
void Session::connection_send_query(ConnectionInfo *info, NetQueryPtr &&net_query, uint64 message_id) {
|
||||||
@ -1323,9 +1341,8 @@ void Session::loop() {
|
|||||||
if (auth_data_.is_ready(Time::now_cached())) {
|
if (auth_data_.is_ready(Time::now_cached())) {
|
||||||
if (need_send_query()) {
|
if (need_send_query()) {
|
||||||
while (!pending_queries_.empty() && sent_queries_.size() < MAX_INFLIGHT_QUERIES) {
|
while (!pending_queries_.empty() && sent_queries_.size() < MAX_INFLIGHT_QUERIES) {
|
||||||
auto &query = pending_queries_.front();
|
auto query = pending_queries_.pop();
|
||||||
connection_send_query(&main_connection_, std::move(query));
|
connection_send_query(&main_connection_, std::move(query));
|
||||||
pending_queries_.pop_front();
|
|
||||||
need_flush = true;
|
need_flush = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,11 @@
|
|||||||
#include "td/utils/List.h"
|
#include "td/utils/List.h"
|
||||||
#include "td/utils/Status.h"
|
#include "td/utils/Status.h"
|
||||||
#include "td/utils/StringBuilder.h"
|
#include "td/utils/StringBuilder.h"
|
||||||
|
#include "td/utils/VectorQueue.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@ -124,7 +126,16 @@ class Session final
|
|||||||
|
|
||||||
// Do not invalidate iterators of these two containers!
|
// Do not invalidate iterators of these two containers!
|
||||||
// TODO: better data structures
|
// TODO: better data structures
|
||||||
std::deque<NetQueryPtr> pending_queries_;
|
struct PriorityQueue {
|
||||||
|
public:
|
||||||
|
void push(NetQueryPtr query);
|
||||||
|
NetQueryPtr pop();
|
||||||
|
bool empty() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<int8, VectorQueue<NetQueryPtr>, std::greater<>> queries_;
|
||||||
|
};
|
||||||
|
PriorityQueue pending_queries_;
|
||||||
std::map<uint64, Query> sent_queries_;
|
std::map<uint64, Query> sent_queries_;
|
||||||
std::deque<NetQueryPtr> pending_invoke_after_queries_;
|
std::deque<NetQueryPtr> pending_invoke_after_queries_;
|
||||||
ListNode sent_queries_list_;
|
ListNode sent_queries_list_;
|
||||||
|
@ -75,7 +75,7 @@ class Actor : public ObserverBase {
|
|||||||
|
|
||||||
uint64 get_link_token();
|
uint64 get_link_token();
|
||||||
std::shared_ptr<ActorContext> set_context(std::shared_ptr<ActorContext> context);
|
std::shared_ptr<ActorContext> set_context(std::shared_ptr<ActorContext> context);
|
||||||
CSlice set_tag(CSlice tag);
|
string set_tag(string tag);
|
||||||
|
|
||||||
void always_wait_for_mailbox();
|
void always_wait_for_mailbox();
|
||||||
|
|
||||||
|
@ -88,13 +88,13 @@ inline uint64 Actor::get_link_token() {
|
|||||||
inline std::shared_ptr<ActorContext> Actor::set_context(std::shared_ptr<ActorContext> context) {
|
inline std::shared_ptr<ActorContext> Actor::set_context(std::shared_ptr<ActorContext> context) {
|
||||||
return info_->set_context(std::move(context));
|
return info_->set_context(std::move(context));
|
||||||
}
|
}
|
||||||
inline CSlice Actor::set_tag(CSlice tag) {
|
inline string Actor::set_tag(string tag) {
|
||||||
auto &tag_ref = info_->get_context()->tag_;
|
auto *ctx = info_->get_context();
|
||||||
CSlice old_tag;
|
string old_tag;
|
||||||
if (tag_ref) {
|
if (ctx->tag_) {
|
||||||
old_tag = CSlice(tag_ref);
|
old_tag = ctx->tag_;
|
||||||
}
|
}
|
||||||
tag_ref = tag.c_str();
|
ctx->set_tag(std::move(tag));
|
||||||
Scheduler::on_context_updated();
|
Scheduler::on_context_updated();
|
||||||
return old_tag;
|
return old_tag;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,13 @@ class ActorContext {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_tag(string tag) {
|
||||||
|
tag_storage_ = std::move(tag);
|
||||||
|
tag_ = tag_storage_.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
const char *tag_ = nullptr;
|
const char *tag_ = nullptr;
|
||||||
|
string tag_storage_; // sometimes tag_ == tag_storage_.c_str()
|
||||||
std::weak_ptr<ActorContext> this_ptr_;
|
std::weak_ptr<ActorContext> this_ptr_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -146,7 +146,9 @@ inline const Actor *ActorInfo::get_actor_unsafe() const {
|
|||||||
inline std::shared_ptr<ActorContext> ActorInfo::set_context(std::shared_ptr<ActorContext> context) {
|
inline std::shared_ptr<ActorContext> ActorInfo::set_context(std::shared_ptr<ActorContext> context) {
|
||||||
CHECK(is_running());
|
CHECK(is_running());
|
||||||
context->this_ptr_ = context;
|
context->this_ptr_ = context;
|
||||||
context->tag_ = Scheduler::context()->tag_;
|
if (Scheduler::context()->tag_) {
|
||||||
|
context->set_tag(Scheduler::context()->tag_);
|
||||||
|
}
|
||||||
std::swap(context_, context);
|
std::swap(context_, context);
|
||||||
Scheduler::context() = context_.get();
|
Scheduler::context() = context_.get();
|
||||||
Scheduler::on_context_updated();
|
Scheduler::on_context_updated();
|
||||||
|
@ -20,15 +20,17 @@ class BinlogActor : public Actor {
|
|||||||
}
|
}
|
||||||
void close(Promise<> promise) {
|
void close(Promise<> promise) {
|
||||||
binlog_->close().ensure();
|
binlog_->close().ensure();
|
||||||
promise.set_value(Unit());
|
|
||||||
LOG(INFO) << "Finished to close binlog";
|
LOG(INFO) << "Finished to close binlog";
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
|
promise.set_value(Unit()); // setting promise can complete closing and destroy the current actor context
|
||||||
}
|
}
|
||||||
void close_and_destroy(Promise<> promise) {
|
void close_and_destroy(Promise<> promise) {
|
||||||
binlog_->close_and_destroy().ensure();
|
binlog_->close_and_destroy().ensure();
|
||||||
promise.set_value(Unit());
|
|
||||||
LOG(INFO) << "Finished to destroy binlog";
|
LOG(INFO) << "Finished to destroy binlog";
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
|
promise.set_value(Unit()); // setting promise can complete closing and destroy the current actor context
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Event {
|
struct Event {
|
||||||
|
@ -136,8 +136,17 @@ TEST(Http, reader) {
|
|||||||
{
|
{
|
||||||
BufferSlice a("test test");
|
BufferSlice a("test test");
|
||||||
BufferSlice b = std::move(a);
|
BufferSlice b = std::move(a);
|
||||||
|
#if TD_CLANG
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunknown-pragmas"
|
||||||
|
#pragma clang diagnostic ignored "-Wunknown-warning-option"
|
||||||
|
#pragma clang diagnostic ignored "-Wself-move"
|
||||||
|
#endif
|
||||||
a = std::move(a);
|
a = std::move(a);
|
||||||
b = std::move(b);
|
b = std::move(b);
|
||||||
|
#if TD_CLANG
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
a = std::move(b);
|
a = std::move(b);
|
||||||
BufferSlice c = a.from_slice(a);
|
BufferSlice c = a.from_slice(a);
|
||||||
CHECK(c.size() == a.size());
|
CHECK(c.size() == a.size());
|
||||||
|
@ -881,8 +881,8 @@ class Master : public Actor {
|
|||||||
LOG(INFO) << "Send message: " << tag("id", id) << tag("text", text) << tag("random_id", random_id);
|
LOG(INFO) << "Send message: " << tag("id", id) << tag("text", text) << tag("random_id", random_id);
|
||||||
sent_messages_[random_id] = Message{id, text};
|
sent_messages_[random_id] = Message{id, text};
|
||||||
send_closure(get_by_id(id), &SecretChatProxy::send_message,
|
send_closure(get_by_id(id), &SecretChatProxy::send_message,
|
||||||
secret_api::make_object<secret_api::decryptedMessage>(0, random_id, 0, text, Auto(), Auto(), Auto(),
|
secret_api::make_object<secret_api::decryptedMessage>(0, false /*ignored*/, random_id, 0, text, Auto(),
|
||||||
Auto(), 0));
|
Auto(), Auto(), Auto(), 0));
|
||||||
}
|
}
|
||||||
void process_net_query(my_api::messages_sendEncryptedService &&message, NetQueryPtr net_query,
|
void process_net_query(my_api::messages_sendEncryptedService &&message, NetQueryPtr net_query,
|
||||||
ActorShared<NetQueryCallback> callback) {
|
ActorShared<NetQueryCallback> callback) {
|
||||||
|
Loading…
Reference in New Issue
Block a user