Merge commit '3d2067475e0764d4765b41aa372e5c3c10a5af5d'
Conflicts: td/telegram/MessagesManager.cpp
This commit is contained in:
commit
41e5ce21ac
@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
|
||||||
|
|
||||||
project(TDLib VERSION 1.6.8 LANGUAGES CXX C)
|
project(TDLib VERSION 1.6.9 LANGUAGES CXX C)
|
||||||
|
|
||||||
if (NOT DEFINED CMAKE_INSTALL_LIBDIR)
|
if (NOT DEFINED CMAKE_INSTALL_LIBDIR)
|
||||||
set(CMAKE_INSTALL_LIBDIR "lib")
|
set(CMAKE_INSTALL_LIBDIR "lib")
|
||||||
|
@ -201,7 +201,7 @@ target_link_libraries(YourTarget PRIVATE Td::TdStatic)
|
|||||||
|
|
||||||
Or you could install `TDLib` and then reference it in your CMakeLists.txt like this:
|
Or you could install `TDLib` and then reference it in your CMakeLists.txt like this:
|
||||||
```
|
```
|
||||||
find_package(Td 1.6.8 REQUIRED)
|
find_package(Td 1.6.9 REQUIRED)
|
||||||
target_link_libraries(YourTarget PRIVATE Td::TdStatic)
|
target_link_libraries(YourTarget PRIVATE Td::TdStatic)
|
||||||
```
|
```
|
||||||
See [example/cpp/CMakeLists.txt](https://github.com/tdlib/td/tree/master/example/cpp/CMakeLists.txt).
|
See [example/cpp/CMakeLists.txt](https://github.com/tdlib/td/tree/master/example/cpp/CMakeLists.txt).
|
||||||
|
@ -156,6 +156,7 @@ function split_file($file, $chunks, $undo) {
|
|||||||
'(?<name>[A-Z][A-Za-z]*) : public (Td::ResultHandler|NetActor|Request)|'.
|
'(?<name>[A-Z][A-Za-z]*) : public (Td::ResultHandler|NetActor|Request)|'.
|
||||||
'(CREATE_REQUEST|CREATE_NO_ARGS_REQUEST)[(](?<name>[A-Z][A-Za-z]*)|'.
|
'(CREATE_REQUEST|CREATE_NO_ARGS_REQUEST)[(](?<name>[A-Z][A-Za-z]*)|'.
|
||||||
'(?<name>complete_pending_preauthentication_requests)|'.
|
'(?<name>complete_pending_preauthentication_requests)|'.
|
||||||
|
'(?<name>get_message_history_slice)|'.
|
||||||
'(Up|Down)load[a-zA-Z]*C(?<name>allback)|(up|down)load_[a-z_]*_c(?<name>allback)_|'.
|
'(Up|Down)load[a-zA-Z]*C(?<name>allback)|(up|down)load_[a-z_]*_c(?<name>allback)_|'.
|
||||||
'(?<name>lazy_to_json)|'.
|
'(?<name>lazy_to_json)|'.
|
||||||
'(?<name>LogEvent)[^sA]|'.
|
'(?<name>LogEvent)[^sA]|'.
|
||||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
|
|||||||
|
|
||||||
project(TdExample VERSION 1.0 LANGUAGES CXX)
|
project(TdExample VERSION 1.0 LANGUAGES CXX)
|
||||||
|
|
||||||
find_package(Td 1.6.8 REQUIRED)
|
find_package(Td 1.6.9 REQUIRED)
|
||||||
|
|
||||||
add_executable(tdjson_example tdjson_example.cpp)
|
add_executable(tdjson_example tdjson_example.cpp)
|
||||||
target_link_libraries(tdjson_example PRIVATE Td::TdJson)
|
target_link_libraries(tdjson_example PRIVATE Td::TdJson)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
|
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
|
||||||
<Metadata>
|
<Metadata>
|
||||||
<Identity Id="Telegram.Td.UWP" Version="1.6.8" Language="en-US" Publisher="Telegram LLC" />
|
<Identity Id="Telegram.Td.UWP" Version="1.6.9" Language="en-US" Publisher="Telegram LLC" />
|
||||||
<DisplayName>TDLib for Universal Windows Platform</DisplayName>
|
<DisplayName>TDLib for Universal Windows Platform</DisplayName>
|
||||||
<Description>TDLib is a library for building Telegram clients</Description>
|
<Description>TDLib is a library for building Telegram clients</Description>
|
||||||
<MoreInfo>https://core.telegram.org/tdlib</MoreInfo>
|
<MoreInfo>https://core.telegram.org/tdlib</MoreInfo>
|
||||||
|
@ -618,7 +618,7 @@ secretChat id:int32 user_id:int32 state:SecretChatState is_outbound:Bool ttl:int
|
|||||||
//@description The message was originally written by a known user @sender_user_id Identifier of the user that originally sent the message
|
//@description The message was originally written by a known user @sender_user_id Identifier of the user that originally sent the message
|
||||||
messageForwardOriginUser sender_user_id:int32 = MessageForwardOrigin;
|
messageForwardOriginUser sender_user_id:int32 = MessageForwardOrigin;
|
||||||
|
|
||||||
//@description The message was originally written by an anonimous chat administrator on behalf of the chat @sender_chat_id Identifier of the chat that originally sent the message
|
//@description The message was originally written by an anonymous chat administrator on behalf of the chat @sender_chat_id Identifier of the chat that originally sent the message
|
||||||
messageForwardOriginChat sender_chat_id:int53 = MessageForwardOrigin;
|
messageForwardOriginChat sender_chat_id:int53 = MessageForwardOrigin;
|
||||||
|
|
||||||
//@description The message was originally written by a user, which is hidden by their privacy settings @sender_name Name of the sender
|
//@description The message was originally written by a user, which is hidden by their privacy settings @sender_name Name of the sender
|
||||||
@ -662,7 +662,7 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool r
|
|||||||
|
|
||||||
//@description Describes a message
|
//@description Describes a message
|
||||||
//@id Message identifier; unique for the chat to which the message belongs
|
//@id Message identifier; unique for the chat to which the message belongs
|
||||||
//@sender_user_id Identifier of the user who sent the message; 0 if unknown. Currently, it is unknown for channel posts, for channel posts automatically forwarded to discussion group and for anonimously sent supergroup messages
|
//@sender_user_id Identifier of the user who sent the message; 0 if unknown. Currently, it is unknown for channel posts, for channel posts automatically forwarded to discussion group and for anonymously sent supergroup messages
|
||||||
//@sender_chat_id Identifier of the chat on behalf of which the message was sent; 0 if none
|
//@sender_chat_id Identifier of the chat on behalf of which the message was sent; 0 if none
|
||||||
//@chat_id Chat identifier
|
//@chat_id Chat identifier
|
||||||
//@sending_state Information about the sending state of the message; may be null
|
//@sending_state Information about the sending state of the message; may be null
|
||||||
@ -3624,10 +3624,19 @@ getGroupsInCommon user_id:int32 offset_chat_id:int53 limit:int32 = Chats;
|
|||||||
//@chat_id Chat identifier
|
//@chat_id Chat identifier
|
||||||
//@from_message_id Identifier of the message starting from which history must be fetched; use 0 to get results from the last message
|
//@from_message_id Identifier of the message starting from which history must be fetched; use 0 to get results from the last message
|
||||||
//@offset Specify 0 to get results from exactly the from_message_id or a negative offset up to 99 to get additionally some newer messages
|
//@offset Specify 0 to get results from exactly the from_message_id or a negative offset up to 99 to get additionally some newer messages
|
||||||
//@limit The maximum number of messages to be returned; must be positive and can't be greater than 100. If the offset is negative, the limit must be greater or equal to -offset. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached
|
//@limit The maximum number of messages to be returned; must be positive and can't be greater than 100. If the offset is negative, the limit must be greater than or equal to -offset. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached
|
||||||
//@only_local If true, returns only messages that are available locally without sending network requests
|
//@only_local If true, returns only messages that are available locally without sending network requests
|
||||||
getChatHistory chat_id:int53 from_message_id:int53 offset:int32 limit:int32 only_local:Bool = Messages;
|
getChatHistory chat_id:int53 from_message_id:int53 offset:int32 limit:int32 only_local:Bool = Messages;
|
||||||
|
|
||||||
|
//@description Returns messages in a message thread of a message. Can be used only if message.can_get_message_thread == true. Message thread of a channel message is in the channel's linked supergroup.
|
||||||
|
//-The messages are returned in a reverse chronological order (i.e., in order of decreasing message_id). For optimal performance the number of returned messages is chosen by the library
|
||||||
|
//@chat_id Chat identifier
|
||||||
|
//@message_id Message identifier, which thread history needs to be returned
|
||||||
|
//@from_message_id Identifier of the message starting from which history must be fetched; use 0 to get results from the last message
|
||||||
|
//@offset Specify 0 to get results from exactly the from_message_id or a negative offset up to 99 to get additionally some newer messages
|
||||||
|
//@limit The maximum number of messages to be returned; must be positive and can't be greater than 100. If the offset is negative, the limit must be greater than or equal to -offset. Fewer messages may be returned than specified by the limit, even if the end of the message thread history has not been reached
|
||||||
|
getMessageThreadHistory chat_id:int53 message_id:int53 from_message_id:int53 offset:int32 limit:int32 = Messages;
|
||||||
|
|
||||||
//@description Deletes all messages in the chat. Use Chat.can_be_deleted_only_for_self and Chat.can_be_deleted_for_all_users fields to find whether and how the method can be applied to the chat
|
//@description Deletes all messages in the chat. Use Chat.can_be_deleted_only_for_self and Chat.can_be_deleted_for_all_users fields to find whether and how the method can be applied to the chat
|
||||||
//@chat_id Chat identifier @remove_from_chat_list Pass true if the chat should be removed from the chat list @revoke Pass true to try to delete chat history for all users
|
//@chat_id Chat identifier @remove_from_chat_list Pass true if the chat should be removed from the chat list @revoke Pass true to try to delete chat history for all users
|
||||||
deleteChatHistory chat_id:int53 remove_from_chat_list:Bool revoke:Bool = Ok;
|
deleteChatHistory chat_id:int53 remove_from_chat_list:Bool revoke:Bool = Ok;
|
||||||
|
Binary file not shown.
@ -371,7 +371,7 @@ Status CallActor::do_update_call(telegram_api::phoneCallWaiting &call) {
|
|||||||
call_state_.is_received = true;
|
call_state_.is_received = true;
|
||||||
call_state_need_flush_ = true;
|
call_state_need_flush_ = true;
|
||||||
int64 call_ring_timeout_ms = G()->shared_config().get_option_integer("call_ring_timeout_ms", 90000);
|
int64 call_ring_timeout_ms = G()->shared_config().get_option_integer("call_ring_timeout_ms", 90000);
|
||||||
set_timeout_in(call_ring_timeout_ms * 0.001);
|
set_timeout_in(static_cast<double>(call_ring_timeout_ms) * 0.001);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,7 +454,7 @@ void CallActor::on_begin_exchanging_key() {
|
|||||||
call_state_.type = CallState::Type::ExchangingKey;
|
call_state_.type = CallState::Type::ExchangingKey;
|
||||||
call_state_need_flush_ = true;
|
call_state_need_flush_ = true;
|
||||||
int64 call_receive_timeout_ms = G()->shared_config().get_option_integer("call_receive_timeout_ms", 20000);
|
int64 call_receive_timeout_ms = G()->shared_config().get_option_integer("call_receive_timeout_ms", 20000);
|
||||||
double timeout = call_receive_timeout_ms * 0.001;
|
double timeout = static_cast<double>(call_receive_timeout_ms) * 0.001;
|
||||||
LOG(INFO) << "Set call timeout to " << timeout;
|
LOG(INFO) << "Set call timeout to " << timeout;
|
||||||
set_timeout_in(timeout);
|
set_timeout_in(timeout);
|
||||||
}
|
}
|
||||||
@ -632,7 +632,7 @@ void CallActor::try_send_request_query() {
|
|||||||
auto query = G()->net_query_creator().create(tl_query);
|
auto query = G()->net_query_creator().create(tl_query);
|
||||||
state_ = State::WaitRequestResult;
|
state_ = State::WaitRequestResult;
|
||||||
int64 call_receive_timeout_ms = G()->shared_config().get_option_integer("call_receive_timeout_ms", 20000);
|
int64 call_receive_timeout_ms = G()->shared_config().get_option_integer("call_receive_timeout_ms", 20000);
|
||||||
double timeout = call_receive_timeout_ms * 0.001;
|
double timeout = static_cast<double>(call_receive_timeout_ms) * 0.001;
|
||||||
LOG(INFO) << "Set call timeout to " << timeout;
|
LOG(INFO) << "Set call timeout to " << timeout;
|
||||||
set_timeout_in(timeout);
|
set_timeout_in(timeout);
|
||||||
query->total_timeout_limit_ = max(timeout, 10.0);
|
query->total_timeout_limit_ = max(timeout, 10.0);
|
||||||
|
@ -3358,6 +3358,10 @@ void ContactsManager::UserFull::parse(ParserT &parser) {
|
|||||||
if (has_photo) {
|
if (has_photo) {
|
||||||
parse(photo, parser);
|
parse(photo, parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (legacy_is_blocked) {
|
||||||
|
LOG(DEBUG) << "Ignore legacy is_blocked flag";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
@ -4059,14 +4063,19 @@ bool ContactsManager::have_input_peer_channel(const Channel *c, ChannelId channe
|
|||||||
if (access_rights == AccessRights::Know) {
|
if (access_rights == AccessRights::Know) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (c->status.is_creator()) {
|
if (c->status.is_administrator()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (c->status.is_banned()) {
|
if (c->status.is_banned()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (c->status.is_member()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_public = is_channel_public(c);
|
||||||
if (access_rights == AccessRights::Read) {
|
if (access_rights == AccessRights::Read) {
|
||||||
if (!c->username.empty() || c->has_location) {
|
if (is_public) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!from_linked) {
|
if (!from_linked) {
|
||||||
@ -4076,22 +4085,19 @@ bool ContactsManager::have_input_peer_channel(const Channel *c, ChannelId channe
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dialog_access_by_invite_link_.count(DialogId(channel_id))) {
|
if (!from_linked && dialog_access_by_invite_link_.count(DialogId(channel_id))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!from_linked && c->is_megagroup) {
|
if (!from_linked && c->is_megagroup && !td_->auth_manager_->is_bot()) {
|
||||||
auto linked_channel_id = get_linked_channel_id(channel_id);
|
auto linked_channel_id = get_linked_channel_id(channel_id);
|
||||||
if (linked_channel_id.is_valid()) {
|
if (linked_channel_id.is_valid()) {
|
||||||
return !c->username.empty() || c->has_location ||
|
return is_public ||
|
||||||
have_input_peer_channel(get_channel(linked_channel_id), linked_channel_id, AccessRights::Read, true);
|
have_input_peer_channel(get_channel(linked_channel_id), linked_channel_id, AccessRights::Read, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!c->status.is_member()) {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ContactsManager::have_input_encrypted_peer(SecretChatId secret_chat_id, AccessRights access_rights) const {
|
bool ContactsManager::have_input_encrypted_peer(SecretChatId secret_chat_id, AccessRights access_rights) const {
|
||||||
@ -7173,7 +7179,7 @@ void ContactsManager::on_get_user(tl_object_ptr<telegram_api::User> &&user_ptr,
|
|||||||
if (is_received || !user->phone_.empty()) {
|
if (is_received || !user->phone_.empty()) {
|
||||||
on_update_user_phone_number(u, user_id, std::move(user->phone_));
|
on_update_user_phone_number(u, user_id, std::move(user->phone_));
|
||||||
}
|
}
|
||||||
if (is_received || u->need_apply_min_photo) {
|
if (is_received || u->need_apply_min_photo || !u->is_received) {
|
||||||
on_update_user_photo(u, user_id, std::move(user->photo_), source);
|
on_update_user_photo(u, user_id, std::move(user->photo_), source);
|
||||||
}
|
}
|
||||||
if (is_received) {
|
if (is_received) {
|
||||||
|
@ -3949,8 +3949,10 @@ bool need_skip_bot_commands(const ContactsManager *contacts_manager, DialogId di
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (dialog_id.get_type()) {
|
switch (dialog_id.get_type()) {
|
||||||
case DialogType::User:
|
case DialogType::User: {
|
||||||
return !contacts_manager->is_user_bot(dialog_id.get_user_id());
|
auto user_id = dialog_id.get_user_id();
|
||||||
|
return user_id == ContactsManager::get_replies_bot_user_id() || !contacts_manager->is_user_bot(user_id);
|
||||||
|
}
|
||||||
case DialogType::SecretChat: {
|
case DialogType::SecretChat: {
|
||||||
auto user_id = contacts_manager->get_secret_chat_user_id(dialog_id.get_secret_chat_id());
|
auto user_id = contacts_manager->get_secret_chat_user_id(dialog_id.get_secret_chat_id());
|
||||||
return !user_id.is_valid() || !contacts_manager->is_user_bot(user_id);
|
return !user_id.is_valid() || !contacts_manager->is_user_bot(user_id);
|
||||||
|
@ -61,6 +61,10 @@ MessageReplyInfo::MessageReplyInfo(tl_object_ptr<telegram_api::messageReplies> &
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MessageReplyInfo::need_update_to(const MessageReplyInfo &other) const {
|
bool MessageReplyInfo::need_update_to(const MessageReplyInfo &other) const {
|
||||||
|
if (other.is_empty() && !is_empty()) {
|
||||||
|
// ignore updates to empty reply info, because we will hide the info ourselves
|
||||||
|
// return true;
|
||||||
|
}
|
||||||
if (other.pts < pts) {
|
if (other.pts < pts) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -4512,6 +4512,7 @@ void MessagesManager::Message::store(StorerT &storer) const {
|
|||||||
bool has_top_thread_message_id = top_thread_message_id.is_valid();
|
bool has_top_thread_message_id = top_thread_message_id.is_valid();
|
||||||
bool has_thread_draft_message = thread_draft_message != nullptr;
|
bool has_thread_draft_message = thread_draft_message != nullptr;
|
||||||
bool has_local_thread_message_ids = !local_thread_message_ids.empty();
|
bool has_local_thread_message_ids = !local_thread_message_ids.empty();
|
||||||
|
bool has_linked_top_thread_message_id = linked_top_thread_message_id.is_valid();
|
||||||
BEGIN_STORE_FLAGS();
|
BEGIN_STORE_FLAGS();
|
||||||
STORE_FLAG(is_channel_post);
|
STORE_FLAG(is_channel_post);
|
||||||
STORE_FLAG(is_outgoing);
|
STORE_FLAG(is_outgoing);
|
||||||
@ -4567,6 +4568,7 @@ void MessagesManager::Message::store(StorerT &storer) const {
|
|||||||
STORE_FLAG(has_top_thread_message_id);
|
STORE_FLAG(has_top_thread_message_id);
|
||||||
STORE_FLAG(has_thread_draft_message);
|
STORE_FLAG(has_thread_draft_message);
|
||||||
STORE_FLAG(has_local_thread_message_ids);
|
STORE_FLAG(has_local_thread_message_ids);
|
||||||
|
STORE_FLAG(has_linked_top_thread_message_id);
|
||||||
END_STORE_FLAGS();
|
END_STORE_FLAGS();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4666,6 +4668,9 @@ void MessagesManager::Message::store(StorerT &storer) const {
|
|||||||
if (has_local_thread_message_ids) {
|
if (has_local_thread_message_ids) {
|
||||||
store(local_thread_message_ids, storer);
|
store(local_thread_message_ids, storer);
|
||||||
}
|
}
|
||||||
|
if (has_linked_top_thread_message_id) {
|
||||||
|
store(linked_top_thread_message_id, storer);
|
||||||
|
}
|
||||||
store_message_content(content.get(), storer);
|
store_message_content(content.get(), storer);
|
||||||
if (has_reply_markup) {
|
if (has_reply_markup) {
|
||||||
store(reply_markup, storer);
|
store(reply_markup, storer);
|
||||||
@ -4706,6 +4711,7 @@ void MessagesManager::Message::parse(ParserT &parser) {
|
|||||||
bool has_top_thread_message_id = false;
|
bool has_top_thread_message_id = false;
|
||||||
bool has_thread_draft_message = false;
|
bool has_thread_draft_message = false;
|
||||||
bool has_local_thread_message_ids = false;
|
bool has_local_thread_message_ids = false;
|
||||||
|
bool has_linked_top_thread_message_id = false;
|
||||||
BEGIN_PARSE_FLAGS();
|
BEGIN_PARSE_FLAGS();
|
||||||
PARSE_FLAG(is_channel_post);
|
PARSE_FLAG(is_channel_post);
|
||||||
PARSE_FLAG(is_outgoing);
|
PARSE_FLAG(is_outgoing);
|
||||||
@ -4761,6 +4767,7 @@ void MessagesManager::Message::parse(ParserT &parser) {
|
|||||||
PARSE_FLAG(has_top_thread_message_id);
|
PARSE_FLAG(has_top_thread_message_id);
|
||||||
PARSE_FLAG(has_thread_draft_message);
|
PARSE_FLAG(has_thread_draft_message);
|
||||||
PARSE_FLAG(has_local_thread_message_ids);
|
PARSE_FLAG(has_local_thread_message_ids);
|
||||||
|
PARSE_FLAG(has_linked_top_thread_message_id);
|
||||||
END_PARSE_FLAGS();
|
END_PARSE_FLAGS();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4866,6 +4873,9 @@ void MessagesManager::Message::parse(ParserT &parser) {
|
|||||||
if (has_local_thread_message_ids) {
|
if (has_local_thread_message_ids) {
|
||||||
parse(local_thread_message_ids, parser);
|
parse(local_thread_message_ids, parser);
|
||||||
}
|
}
|
||||||
|
if (has_linked_top_thread_message_id) {
|
||||||
|
parse(linked_top_thread_message_id, parser);
|
||||||
|
}
|
||||||
parse_message_content(content, parser);
|
parse_message_content(content, parser);
|
||||||
if (has_reply_markup) {
|
if (has_reply_markup) {
|
||||||
parse(reply_markup, parser);
|
parse(reply_markup, parser);
|
||||||
@ -6363,7 +6373,8 @@ void MessagesManager::on_update_read_message_comments(DialogId dialog_id, Messag
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto m = get_message_force(d, message_id, "on_update_read_message_comments");
|
auto m = get_message_force(d, message_id, "on_update_read_message_comments");
|
||||||
if (m == nullptr || !m->message_id.is_server()) {
|
if (m == nullptr || !m->message_id.is_server() || m->top_thread_message_id != m->message_id ||
|
||||||
|
!is_active_message_reply_info(dialog_id, m->reply_info)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m->reply_info.update_max_message_ids(max_message_id, last_read_inbox_message_id, last_read_outbox_message_id)) {
|
if (m->reply_info.update_max_message_ids(max_message_id, last_read_inbox_message_id, last_read_outbox_message_id)) {
|
||||||
@ -6526,8 +6537,13 @@ bool MessagesManager::is_active_message_reply_info(DialogId dialog_id, const Mes
|
|||||||
|
|
||||||
bool MessagesManager::is_visible_message_reply_info(DialogId dialog_id, const Message *m) const {
|
bool MessagesManager::is_visible_message_reply_info(DialogId dialog_id, const Message *m) const {
|
||||||
CHECK(m != nullptr);
|
CHECK(m != nullptr);
|
||||||
return m->message_id.is_valid() && m->message_id.is_server() && !m->had_reply_markup && m->reply_markup == nullptr &&
|
if (!m->message_id.is_valid() || !m->message_id.is_server()) {
|
||||||
is_active_message_reply_info(dialog_id, m->reply_info);
|
return false;
|
||||||
|
}
|
||||||
|
if (is_broadcast_channel(dialog_id) && (m->had_reply_markup || m->reply_markup != nullptr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return is_active_message_reply_info(dialog_id, m->reply_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
td_api::object_ptr<td_api::messageInteractionInfo> MessagesManager::get_message_interaction_info_object(
|
td_api::object_ptr<td_api::messageInteractionInfo> MessagesManager::get_message_interaction_info_object(
|
||||||
@ -6607,6 +6623,10 @@ bool MessagesManager::update_message_interaction_info(DialogId dialog_id, Messag
|
|||||||
m->reply_info = std::move(reply_info);
|
m->reply_info = std::move(reply_info);
|
||||||
need_update |=
|
need_update |=
|
||||||
m->message_id.is_valid() && m->message_id.is_server() && !m->had_reply_markup && m->reply_markup == nullptr;
|
m->message_id.is_valid() && m->message_id.is_server() && !m->had_reply_markup && m->reply_markup == nullptr;
|
||||||
|
if (!m->top_thread_message_id.is_valid() && !is_broadcast_channel(dialog_id) &&
|
||||||
|
is_visible_message_reply_info(dialog_id, m)) {
|
||||||
|
m->top_thread_message_id = m->message_id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (need_update) {
|
if (need_update) {
|
||||||
send_update_message_interaction_info(dialog_id, m);
|
send_update_message_interaction_info(dialog_id, m);
|
||||||
@ -6978,12 +6998,9 @@ void MessagesManager::on_user_dialog_action(DialogId dialog_id, MessageId top_th
|
|||||||
progress <= prev_progress) {
|
progress <= prev_progress) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (top_thread_message_id != prev_top_thread_message_id) {
|
if (top_thread_message_id != prev_top_thread_message_id && prev_top_thread_message_id.is_valid()) {
|
||||||
send_closure(G()->td(), &Td::send_update,
|
send_update_user_chat_action(dialog_id, prev_top_thread_message_id, user_id,
|
||||||
make_tl_object<td_api::updateUserChatAction>(
|
td_api::make_object<td_api::chatActionCancel>());
|
||||||
dialog_id.get(), prev_top_thread_message_id.get(),
|
|
||||||
td_->contacts_manager_->get_user_id_object(user_id, "on_user_dialog_action"),
|
|
||||||
make_tl_object<td_api::chatActionCancel>()));
|
|
||||||
}
|
}
|
||||||
if (active_actions.size() == 1u) {
|
if (active_actions.size() == 1u) {
|
||||||
LOG(DEBUG) << "Set action timeout in " << dialog_id;
|
LOG(DEBUG) << "Set action timeout in " << dialog_id;
|
||||||
@ -6992,11 +7009,10 @@ void MessagesManager::on_user_dialog_action(DialogId dialog_id, MessageId top_th
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!G()->shared_config().get_option_boolean("ignore_update_user_chat_action")) {
|
if (!G()->shared_config().get_option_boolean("ignore_update_user_chat_action")) {
|
||||||
LOG(DEBUG) << "Send action of " << user_id << " in " << dialog_id << ": " << to_string(action);
|
if (top_thread_message_id.is_valid()) {
|
||||||
send_closure(G()->td(), &Td::send_update,
|
send_update_user_chat_action(dialog_id, MessageId(), user_id, copy_chat_action_object(action));
|
||||||
make_tl_object<td_api::updateUserChatAction>(
|
}
|
||||||
dialog_id.get(), top_thread_message_id.get(),
|
send_update_user_chat_action(dialog_id, top_thread_message_id, user_id, std::move(action));
|
||||||
td_->contacts_manager_->get_user_id_object(user_id, "on_user_dialog_action"), std::move(action)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9205,6 +9221,8 @@ void MessagesManager::on_get_dialog_messages_search_result(DialogId dialog_id, c
|
|||||||
// anyway pretend that there is no more messages
|
// anyway pretend that there is no more messages
|
||||||
first_added_message_id = MessageId::min();
|
first_added_message_id = MessageId::min();
|
||||||
}
|
}
|
||||||
|
bool can_be_in_different_dialog = top_thread_message_id.is_valid() && is_broadcast_channel(dialog_id);
|
||||||
|
DialogId real_dialog_id;
|
||||||
Dialog *d = get_dialog(dialog_id);
|
Dialog *d = get_dialog(dialog_id);
|
||||||
CHECK(d != nullptr);
|
CHECK(d != nullptr);
|
||||||
for (auto &message : messages) {
|
for (auto &message : messages) {
|
||||||
@ -9216,13 +9234,26 @@ void MessagesManager::on_get_dialog_messages_search_result(DialogId dialog_id, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (new_full_message_id.get_dialog_id() != dialog_id) {
|
if (new_full_message_id.get_dialog_id() != dialog_id) {
|
||||||
LOG(ERROR) << "Receive " << new_full_message_id << " instead of a message in " << dialog_id;
|
if (!can_be_in_different_dialog) {
|
||||||
total_count--;
|
LOG(ERROR) << "Receive " << new_full_message_id << " instead of a message in " << dialog_id;
|
||||||
continue;
|
total_count--;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (!real_dialog_id.is_valid()) {
|
||||||
|
real_dialog_id = new_full_message_id.get_dialog_id();
|
||||||
|
found_dialog_messages_dialog_id_[random_id] = real_dialog_id;
|
||||||
|
} else if (new_full_message_id.get_dialog_id() != real_dialog_id) {
|
||||||
|
LOG(ERROR) << "Receive " << new_full_message_id << " instead of a message in " << real_dialog_id << " or "
|
||||||
|
<< dialog_id;
|
||||||
|
total_count--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto message_id = new_full_message_id.get_message_id();
|
auto message_id = new_full_message_id.get_message_id();
|
||||||
if (filter == MessageSearchFilter::UnreadMention && message_id <= d->last_read_all_mentions_message_id) {
|
if (filter == MessageSearchFilter::UnreadMention && message_id <= d->last_read_all_mentions_message_id &&
|
||||||
|
!real_dialog_id.is_valid()) {
|
||||||
total_count--;
|
total_count--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -11527,6 +11558,7 @@ void MessagesManager::on_message_ttl_expired_impl(Dialog *d, Message *m) {
|
|||||||
m->reply_to_message_id = MessageId();
|
m->reply_to_message_id = MessageId();
|
||||||
m->reply_in_dialog_id = DialogId();
|
m->reply_in_dialog_id = DialogId();
|
||||||
m->top_thread_message_id = MessageId();
|
m->top_thread_message_id = MessageId();
|
||||||
|
m->linked_top_thread_message_id = MessageId();
|
||||||
m->is_content_secret = false;
|
m->is_content_secret = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12790,6 +12822,7 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
|
|||||||
message->reply_to_message_id = MessageId();
|
message->reply_to_message_id = MessageId();
|
||||||
message->reply_in_dialog_id = DialogId();
|
message->reply_in_dialog_id = DialogId();
|
||||||
message->top_thread_message_id = MessageId();
|
message->top_thread_message_id = MessageId();
|
||||||
|
message->linked_top_thread_message_id = MessageId();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message_info.media_album_id != 0) {
|
if (message_info.media_album_id != 0) {
|
||||||
@ -16059,7 +16092,7 @@ void MessagesManager::get_message_thread(DialogId dialog_id, MessageId message_i
|
|||||||
ChannelId message_thread_channel_id;
|
ChannelId message_thread_channel_id;
|
||||||
MessageId top_thread_message_id;
|
MessageId top_thread_message_id;
|
||||||
if (m->reply_info.is_comment) {
|
if (m->reply_info.is_comment) {
|
||||||
if (!is_active_message_reply_info(dialog_id, m->reply_info)) {
|
if (!is_visible_message_reply_info(dialog_id, m)) {
|
||||||
return promise.set_error(Status::Error(400, "Message has no comments"));
|
return promise.set_error(Status::Error(400, "Message has no comments"));
|
||||||
}
|
}
|
||||||
message_thread_channel_id = m->reply_info.channel_id;
|
message_thread_channel_id = m->reply_info.channel_id;
|
||||||
@ -16123,6 +16156,23 @@ void MessagesManager::on_get_discussion_message(DialogId dialog_id, MessageId me
|
|||||||
}
|
}
|
||||||
result.message_ids.push_back(full_message_id.get_message_id());
|
result.message_ids.push_back(full_message_id.get_message_id());
|
||||||
}
|
}
|
||||||
|
if (expected_dialog_id != dialog_id && m->reply_info.is_comment && !result.message_ids.empty() &&
|
||||||
|
m->linked_top_thread_message_id != result.message_ids.back()) {
|
||||||
|
auto linked_d = get_dialog_force(expected_dialog_id);
|
||||||
|
CHECK(linked_d != nullptr);
|
||||||
|
auto linked_message_id = result.message_ids.back();
|
||||||
|
Message *linked_m = get_message_force(linked_d, linked_message_id, "on_get_discussion_message");
|
||||||
|
CHECK(linked_m != nullptr && linked_m->message_id.is_server());
|
||||||
|
if (linked_m->top_thread_message_id == linked_m->message_id &&
|
||||||
|
is_active_message_reply_info(expected_dialog_id, linked_m->reply_info)) {
|
||||||
|
if (m->linked_top_thread_message_id.is_valid()) {
|
||||||
|
LOG(ERROR) << "Comment message identifier for " << message_id << " in " << dialog_id << " changed from "
|
||||||
|
<< m->linked_top_thread_message_id << " to " << linked_message_id;
|
||||||
|
}
|
||||||
|
m->linked_top_thread_message_id = linked_message_id;
|
||||||
|
on_dialog_updated(dialog_id, "on_get_discussion_message");
|
||||||
|
}
|
||||||
|
}
|
||||||
result.dialog_id = expected_dialog_id;
|
result.dialog_id = expected_dialog_id;
|
||||||
promise.set_value(std::move(result));
|
promise.set_value(std::move(result));
|
||||||
}
|
}
|
||||||
@ -19309,7 +19359,7 @@ tl_object_ptr<td_api::messages> MessagesManager::get_dialog_history(DialogId dia
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (offset < -limit) {
|
if (offset < -limit) {
|
||||||
promise.set_error(Status::Error(5, "Parameter offset must not be less than -limit"));
|
promise.set_error(Status::Error(5, "Parameter offset must be greater than or equal to -limit"));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
bool is_limit_increased = false;
|
bool is_limit_increased = false;
|
||||||
@ -19707,6 +19757,202 @@ void MessagesManager::on_read_history_finished(DialogId dialog_id, MessageId top
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T, class It>
|
||||||
|
vector<MessageId> MessagesManager::get_message_history_slice(const T &begin, It it, const T &end,
|
||||||
|
MessageId from_message_id, int32 offset, int32 limit) {
|
||||||
|
int32 left_offset = -offset;
|
||||||
|
int32 left_limit = limit + offset;
|
||||||
|
while (left_offset > 0 && it != end) {
|
||||||
|
++it;
|
||||||
|
left_offset--;
|
||||||
|
left_limit++;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<MessageId> message_ids;
|
||||||
|
while (left_limit > 0 && it != begin) {
|
||||||
|
--it;
|
||||||
|
left_limit--;
|
||||||
|
message_ids.push_back(*it);
|
||||||
|
}
|
||||||
|
return message_ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<DialogId, vector<MessageId>> MessagesManager::get_message_thread_history(
|
||||||
|
DialogId dialog_id, MessageId message_id, MessageId from_message_id, int32 offset, int32 limit, int64 &random_id,
|
||||||
|
Promise<Unit> &&promise) {
|
||||||
|
if (limit <= 0) {
|
||||||
|
promise.set_error(Status::Error(3, "Parameter limit must be positive"));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (limit > MAX_GET_HISTORY) {
|
||||||
|
limit = MAX_GET_HISTORY;
|
||||||
|
}
|
||||||
|
if (offset > 0) {
|
||||||
|
promise.set_error(Status::Error(5, "Parameter offset must be non-positive"));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (offset <= -MAX_GET_HISTORY) {
|
||||||
|
promise.set_error(Status::Error(5, "Parameter offset must be greater than -100"));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (offset < -limit) {
|
||||||
|
promise.set_error(Status::Error(5, "Parameter offset must be greater than or equal to -limit"));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
bool is_limit_increased = false;
|
||||||
|
if (limit == -offset) {
|
||||||
|
limit++;
|
||||||
|
is_limit_increased = true;
|
||||||
|
}
|
||||||
|
CHECK(0 < limit && limit <= MAX_GET_HISTORY);
|
||||||
|
CHECK(-limit < offset && offset <= 0);
|
||||||
|
|
||||||
|
Dialog *d = get_dialog_force(dialog_id);
|
||||||
|
if (d == nullptr) {
|
||||||
|
promise.set_error(Status::Error(6, "Chat not found"));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (!have_input_peer(dialog_id, AccessRights::Read)) {
|
||||||
|
promise.set_error(Status::Error(5, "Can't access the chat"));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (dialog_id.get_type() != DialogType::Channel) {
|
||||||
|
promise.set_error(Status::Error(400, "Can't get message thread history in the chat"));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from_message_id == MessageId() || from_message_id.get() > MessageId::max().get()) {
|
||||||
|
from_message_id = MessageId::max();
|
||||||
|
}
|
||||||
|
if (!from_message_id.is_valid()) {
|
||||||
|
promise.set_error(Status::Error(3, "Parameter from_message_id must be identifier of the chat message or 0"));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
DialogId message_thread_dialog_id;
|
||||||
|
MessageId top_thread_message_id;
|
||||||
|
{
|
||||||
|
Message *m = get_message_force(d, message_id, "get_message_thread_history 1");
|
||||||
|
if (m == nullptr) {
|
||||||
|
promise.set_error(Status::Error(400, "Message not found"));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m->reply_info.is_comment) {
|
||||||
|
if (!is_visible_message_reply_info(dialog_id, m)) {
|
||||||
|
promise.set_error(Status::Error(400, "Message has no comments"));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (!m->linked_top_thread_message_id.is_valid()) {
|
||||||
|
get_message_thread(
|
||||||
|
dialog_id, message_id,
|
||||||
|
PromiseCreator::lambda([promise = std::move(promise)](Result<MessageThreadInfo> &&result) mutable {
|
||||||
|
if (result.is_error()) {
|
||||||
|
promise.set_error(result.move_as_error());
|
||||||
|
} else {
|
||||||
|
promise.set_value(Unit());
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
message_thread_dialog_id = DialogId(m->reply_info.channel_id);
|
||||||
|
top_thread_message_id = m->linked_top_thread_message_id;
|
||||||
|
} else {
|
||||||
|
if (!m->top_thread_message_id.is_valid()) {
|
||||||
|
promise.set_error(Status::Error(400, "Message has no thread"));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
message_thread_dialog_id = dialog_id;
|
||||||
|
top_thread_message_id = m->top_thread_message_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHECK(top_thread_message_id.is_valid());
|
||||||
|
|
||||||
|
if (random_id != 0) {
|
||||||
|
// request has already been sent before
|
||||||
|
auto it = found_dialog_messages_.find(random_id);
|
||||||
|
CHECK(it != found_dialog_messages_.end());
|
||||||
|
auto result = std::move(it->second.second);
|
||||||
|
found_dialog_messages_.erase(it);
|
||||||
|
|
||||||
|
auto dialog_id_it = found_dialog_messages_dialog_id_.find(random_id);
|
||||||
|
if (dialog_id_it != found_dialog_messages_dialog_id_.end()) {
|
||||||
|
dialog_id = dialog_id_it->second;
|
||||||
|
found_dialog_messages_dialog_id_.erase(dialog_id_it);
|
||||||
|
|
||||||
|
d = get_dialog(dialog_id);
|
||||||
|
CHECK(d != nullptr);
|
||||||
|
}
|
||||||
|
if (dialog_id != message_thread_dialog_id) {
|
||||||
|
promise.set_error(Status::Error(500, "Receive messages in an unexpected chat"));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto yet_unsent_it = d->yet_unsent_thread_message_ids.find(top_thread_message_id);
|
||||||
|
if (yet_unsent_it != d->yet_unsent_thread_message_ids.end()) {
|
||||||
|
const std::set<MessageId> &message_ids = yet_unsent_it->second;
|
||||||
|
auto merge_message_ids = get_message_history_slice(message_ids.begin(), message_ids.lower_bound(from_message_id),
|
||||||
|
message_ids.end(), from_message_id, offset, limit);
|
||||||
|
vector<MessageId> new_result(result.size() + merge_message_ids.size());
|
||||||
|
std::merge(result.begin(), result.end(), merge_message_ids.begin(), merge_message_ids.end(), new_result.begin(),
|
||||||
|
std::greater<>());
|
||||||
|
result = std::move(new_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
Message *top_m = get_message_force(d, top_thread_message_id, "get_message_thread_history 2");
|
||||||
|
if (top_m != nullptr && !top_m->local_thread_message_ids.empty()) {
|
||||||
|
vector<MessageId> &message_ids = top_m->local_thread_message_ids;
|
||||||
|
vector<MessageId> merge_message_ids;
|
||||||
|
while (true) {
|
||||||
|
merge_message_ids = get_message_history_slice(
|
||||||
|
message_ids.begin(), std::lower_bound(message_ids.begin(), message_ids.end(), from_message_id),
|
||||||
|
message_ids.end(), from_message_id, offset, limit);
|
||||||
|
bool found_deleted = false;
|
||||||
|
for (auto local_message_id : merge_message_ids) {
|
||||||
|
Message *local_m = get_message_force(d, local_message_id, "get_message_thread_history 3");
|
||||||
|
if (local_m == nullptr) {
|
||||||
|
auto local_it = std::lower_bound(message_ids.begin(), message_ids.end(), local_message_id);
|
||||||
|
CHECK(local_it != message_ids.end() && *local_it == local_message_id);
|
||||||
|
message_ids.erase(local_it);
|
||||||
|
found_deleted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found_deleted) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
on_message_changed(d, top_m, false, "get_message_thread_history");
|
||||||
|
}
|
||||||
|
vector<MessageId> new_result(result.size() + merge_message_ids.size());
|
||||||
|
std::merge(result.begin(), result.end(), merge_message_ids.begin(), merge_message_ids.end(), new_result.begin(),
|
||||||
|
std::greater<>());
|
||||||
|
result = std::move(new_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_limit_increased) {
|
||||||
|
limit--;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::reverse(result.begin(), result.end());
|
||||||
|
result = get_message_history_slice(result.begin(), std::lower_bound(result.begin(), result.end(), from_message_id),
|
||||||
|
result.end(), from_message_id, offset, limit);
|
||||||
|
|
||||||
|
LOG(INFO) << "Return " << result.size() << " messages in result to getMessageThreadHistory";
|
||||||
|
|
||||||
|
promise.set_value(Unit());
|
||||||
|
return {dialog_id, std::move(result)};
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
random_id = Random::secure_int64();
|
||||||
|
} while (random_id == 0 || found_dialog_messages_.find(random_id) != found_dialog_messages_.end());
|
||||||
|
found_dialog_messages_[random_id]; // reserve place for result
|
||||||
|
|
||||||
|
td_->create_handler<SearchMessagesQuery>(std::move(promise))
|
||||||
|
->send(dialog_id, string(), UserId(), nullptr, from_message_id.get_next_server_message_id(), offset, limit,
|
||||||
|
MessageSearchFilter::Empty, message_id, random_id);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<int32, vector<MessageId>> MessagesManager::search_dialog_messages(
|
std::pair<int32, vector<MessageId>> MessagesManager::search_dialog_messages(
|
||||||
DialogId dialog_id, const string &query, UserId sender_user_id, MessageId from_message_id, int32 offset,
|
DialogId dialog_id, const string &query, UserId sender_user_id, MessageId from_message_id, int32 offset,
|
||||||
int32 limit, MessageSearchFilter filter, MessageId top_thread_message_id, int64 &random_id, bool use_db,
|
int32 limit, MessageSearchFilter filter, MessageId top_thread_message_id, int64 &random_id, bool use_db,
|
||||||
@ -19715,6 +19961,7 @@ std::pair<int32, vector<MessageId>> MessagesManager::search_dialog_messages(
|
|||||||
// request has already been sent before
|
// request has already been sent before
|
||||||
auto it = found_dialog_messages_.find(random_id);
|
auto it = found_dialog_messages_.find(random_id);
|
||||||
if (it != found_dialog_messages_.end()) {
|
if (it != found_dialog_messages_.end()) {
|
||||||
|
CHECK(found_dialog_messages_dialog_id_.count(random_id) == 0);
|
||||||
auto result = std::move(it->second);
|
auto result = std::move(it->second);
|
||||||
found_dialog_messages_.erase(it);
|
found_dialog_messages_.erase(it);
|
||||||
promise.set_value(Unit());
|
promise.set_value(Unit());
|
||||||
@ -20337,7 +20584,7 @@ void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, Dialo
|
|||||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||||
}
|
}
|
||||||
if (r_messages.is_error()) {
|
if (r_messages.is_error()) {
|
||||||
LOG(ERROR) << r_messages.error();
|
LOG(ERROR) << "Failed to get messages from the database: " << r_messages.error();
|
||||||
if (first_db_message_id != MessageId::min() && dialog_id.get_type() != DialogType::SecretChat &&
|
if (first_db_message_id != MessageId::min() && dialog_id.get_type() != DialogType::SecretChat &&
|
||||||
filter != MessageSearchFilter::FailedToSend) {
|
filter != MessageSearchFilter::FailedToSend) {
|
||||||
found_dialog_messages_.erase(random_id);
|
found_dialog_messages_.erase(random_id);
|
||||||
@ -20773,6 +21020,7 @@ int32 MessagesManager::get_dialog_message_count(DialogId dialog_id, MessageSearc
|
|||||||
CHECK(it != found_dialog_messages_.end());
|
CHECK(it != found_dialog_messages_.end());
|
||||||
auto result = std::move(it->second);
|
auto result = std::move(it->second);
|
||||||
found_dialog_messages_.erase(it);
|
found_dialog_messages_.erase(it);
|
||||||
|
CHECK(found_dialog_messages_dialog_id_.count(random_id) == 0);
|
||||||
promise.set_value(Unit());
|
promise.set_value(Unit());
|
||||||
return result.first;
|
return result.first;
|
||||||
}
|
}
|
||||||
@ -21553,8 +21801,9 @@ tl_object_ptr<td_api::message> MessagesManager::get_message_object(DialogId dial
|
|||||||
bool can_be_edited = for_event_log ? false : can_edit_message(dialog_id, m, false, td_->auth_manager_->is_bot());
|
bool can_be_edited = for_event_log ? false : can_edit_message(dialog_id, m, false, td_->auth_manager_->is_bot());
|
||||||
bool can_be_forwarded = for_event_log ? false : can_forward_message(dialog_id, m);
|
bool can_be_forwarded = for_event_log ? false : can_forward_message(dialog_id, m);
|
||||||
bool can_get_statistics = for_event_log ? false : can_get_message_statistics(dialog_id, m);
|
bool can_get_statistics = for_event_log ? false : can_get_message_statistics(dialog_id, m);
|
||||||
bool can_get_message_thread =
|
bool can_get_message_thread = for_event_log || is_scheduled ? false
|
||||||
for_event_log || is_scheduled ? false : !m->reply_info.is_empty() || m->top_thread_message_id.is_valid();
|
: is_visible_message_reply_info(dialog_id, m) ||
|
||||||
|
m->top_thread_message_id.is_valid();
|
||||||
auto via_bot_user_id = td_->contacts_manager_->get_user_id_object(m->via_bot_user_id, "via_bot_user_id");
|
auto via_bot_user_id = td_->contacts_manager_->get_user_id_object(m->via_bot_user_id, "via_bot_user_id");
|
||||||
auto media_album_id = for_event_log ? static_cast<int64>(0) : m->media_album_id;
|
auto media_album_id = for_event_log ? static_cast<int64>(0) : m->media_album_id;
|
||||||
auto reply_to_message_id = for_event_log ? static_cast<int64>(0) : m->reply_to_message_id.get();
|
auto reply_to_message_id = for_event_log ? static_cast<int64>(0) : m->reply_to_message_id.get();
|
||||||
@ -27067,6 +27316,21 @@ void MessagesManager::send_update_chat_has_scheduled_messages(Dialog *d, bool fr
|
|||||||
td_api::make_object<td_api::updateChatHasScheduledMessages>(d->dialog_id.get(), has_scheduled_messages));
|
td_api::make_object<td_api::updateChatHasScheduledMessages>(d->dialog_id.get(), has_scheduled_messages));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MessagesManager::send_update_user_chat_action(DialogId dialog_id, MessageId top_thread_message_id, UserId user_id,
|
||||||
|
td_api::object_ptr<td_api::ChatAction> action) {
|
||||||
|
if (td_->auth_manager_->is_bot()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(DEBUG) << "Send action of " << user_id << " in thread of " << top_thread_message_id << " in " << dialog_id << ": "
|
||||||
|
<< to_string(action);
|
||||||
|
send_closure(
|
||||||
|
G()->td(), &Td::send_update,
|
||||||
|
make_tl_object<td_api::updateUserChatAction>(
|
||||||
|
dialog_id.get(), top_thread_message_id.get(),
|
||||||
|
td_->contacts_manager_->get_user_id_object(user_id, "send_update_user_chat_action"), std::move(action)));
|
||||||
|
}
|
||||||
|
|
||||||
void MessagesManager::on_send_message_get_quick_ack(int64 random_id) {
|
void MessagesManager::on_send_message_get_quick_ack(int64 random_id) {
|
||||||
auto it = being_sent_messages_.find(random_id);
|
auto it = being_sent_messages_.find(random_id);
|
||||||
if (it == being_sent_messages_.end()) {
|
if (it == being_sent_messages_.end()) {
|
||||||
@ -28698,6 +28962,52 @@ bool MessagesManager::is_dialog_action_unneeded(DialogId dialog_id) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tl_object_ptr<td_api::ChatAction> MessagesManager::copy_chat_action_object(
|
||||||
|
const tl_object_ptr<td_api::ChatAction> &action) {
|
||||||
|
CHECK(action != nullptr);
|
||||||
|
switch (action->get_id()) {
|
||||||
|
case td_api::chatActionCancel::ID:
|
||||||
|
return make_tl_object<td_api::chatActionCancel>();
|
||||||
|
case td_api::chatActionTyping::ID:
|
||||||
|
return make_tl_object<td_api::chatActionTyping>();
|
||||||
|
case td_api::chatActionRecordingVideo::ID:
|
||||||
|
return make_tl_object<td_api::chatActionRecordingVideo>();
|
||||||
|
case td_api::chatActionUploadingVideo::ID: {
|
||||||
|
auto progress = static_cast<const td_api::chatActionUploadingVideo &>(*action).progress_;
|
||||||
|
return make_tl_object<td_api::chatActionUploadingVideo>(progress);
|
||||||
|
}
|
||||||
|
case td_api::chatActionRecordingVoiceNote::ID:
|
||||||
|
return make_tl_object<td_api::chatActionRecordingVoiceNote>();
|
||||||
|
case td_api::chatActionUploadingVoiceNote::ID: {
|
||||||
|
auto progress = static_cast<const td_api::chatActionUploadingVoiceNote &>(*action).progress_;
|
||||||
|
return make_tl_object<td_api::chatActionUploadingVoiceNote>(progress);
|
||||||
|
}
|
||||||
|
case td_api::chatActionUploadingPhoto::ID: {
|
||||||
|
auto progress = static_cast<const td_api::chatActionUploadingPhoto &>(*action).progress_;
|
||||||
|
return make_tl_object<td_api::chatActionUploadingPhoto>(progress);
|
||||||
|
}
|
||||||
|
case td_api::chatActionUploadingDocument::ID: {
|
||||||
|
auto progress = static_cast<const td_api::chatActionUploadingDocument &>(*action).progress_;
|
||||||
|
return make_tl_object<td_api::chatActionUploadingDocument>(progress);
|
||||||
|
}
|
||||||
|
case td_api::chatActionChoosingLocation::ID:
|
||||||
|
return make_tl_object<td_api::chatActionChoosingLocation>();
|
||||||
|
case td_api::chatActionChoosingContact::ID:
|
||||||
|
return make_tl_object<td_api::chatActionChoosingContact>();
|
||||||
|
case td_api::chatActionStartPlayingGame::ID:
|
||||||
|
return make_tl_object<td_api::chatActionStartPlayingGame>();
|
||||||
|
case td_api::chatActionRecordingVideoNote::ID:
|
||||||
|
return make_tl_object<td_api::chatActionRecordingVideoNote>();
|
||||||
|
case td_api::chatActionUploadingVideoNote::ID: {
|
||||||
|
auto progress = static_cast<const td_api::chatActionUploadingVideoNote &>(*action).progress_;
|
||||||
|
return make_tl_object<td_api::chatActionUploadingVideoNote>(progress);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MessagesManager::send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id,
|
void MessagesManager::send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id,
|
||||||
const tl_object_ptr<td_api::ChatAction> &action, Promise<Unit> &&promise) {
|
const tl_object_ptr<td_api::ChatAction> &action, Promise<Unit> &&promise) {
|
||||||
if (action == nullptr) {
|
if (action == nullptr) {
|
||||||
@ -30332,6 +30642,10 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!message->top_thread_message_id.is_valid() && !is_broadcast_channel(dialog_id) &&
|
||||||
|
is_visible_message_reply_info(dialog_id, message.get())) {
|
||||||
|
message->top_thread_message_id = message_id;
|
||||||
|
}
|
||||||
|
|
||||||
if (!message_id.is_scheduled() && message_id <= d->last_clear_history_message_id) {
|
if (!message_id.is_scheduled() && message_id <= d->last_clear_history_message_id) {
|
||||||
LOG(INFO) << "Skip adding cleared " << message_id << " to " << dialog_id << " from " << source;
|
LOG(INFO) << "Skip adding cleared " << message_id << " to " << dialog_id << " from " << source;
|
||||||
|
@ -701,6 +701,11 @@ class MessagesManager : public Actor {
|
|||||||
int32 limit, int left_tries, bool only_local,
|
int32 limit, int left_tries, bool only_local,
|
||||||
Promise<Unit> &&promise);
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
std::pair<DialogId, vector<MessageId>> get_message_thread_history(DialogId dialog_id, MessageId message_id,
|
||||||
|
MessageId from_message_id, int32 offset,
|
||||||
|
int32 limit, int64 &random_id,
|
||||||
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
std::pair<int32, vector<MessageId>> search_dialog_messages(DialogId dialog_id, const string &query,
|
std::pair<int32, vector<MessageId>> search_dialog_messages(DialogId dialog_id, const string &query,
|
||||||
UserId sender_user_id, MessageId from_message_id,
|
UserId sender_user_id, MessageId from_message_id,
|
||||||
int32 offset, int32 limit, MessageSearchFilter filter,
|
int32 offset, int32 limit, MessageSearchFilter filter,
|
||||||
@ -1035,6 +1040,7 @@ class MessagesManager : public Actor {
|
|||||||
int64 reply_to_random_id = 0; // for send_message
|
int64 reply_to_random_id = 0; // for send_message
|
||||||
DialogId reply_in_dialog_id;
|
DialogId reply_in_dialog_id;
|
||||||
MessageId top_thread_message_id;
|
MessageId top_thread_message_id;
|
||||||
|
MessageId linked_top_thread_message_id;
|
||||||
vector<MessageId> local_thread_message_ids;
|
vector<MessageId> local_thread_message_ids;
|
||||||
|
|
||||||
UserId via_bot_user_id;
|
UserId via_bot_user_id;
|
||||||
@ -1986,6 +1992,10 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
void on_update_dialog_online_member_count_timeout(DialogId dialog_id);
|
void on_update_dialog_online_member_count_timeout(DialogId dialog_id);
|
||||||
|
|
||||||
|
template <class T, class It>
|
||||||
|
vector<MessageId> get_message_history_slice(const T &begin, It it, const T &end, MessageId from_message_id,
|
||||||
|
int32 offset, int32 limit);
|
||||||
|
|
||||||
void preload_newer_messages(const Dialog *d, MessageId max_message_id);
|
void preload_newer_messages(const Dialog *d, MessageId max_message_id);
|
||||||
|
|
||||||
void preload_older_messages(const Dialog *d, MessageId min_message_id);
|
void preload_older_messages(const Dialog *d, MessageId min_message_id);
|
||||||
@ -2205,6 +2215,9 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
void send_update_chat_has_scheduled_messages(Dialog *d, bool from_deletion);
|
void send_update_chat_has_scheduled_messages(Dialog *d, bool from_deletion);
|
||||||
|
|
||||||
|
void send_update_user_chat_action(DialogId dialog_id, MessageId top_thread_message_id, UserId user_id,
|
||||||
|
td_api::object_ptr<td_api::ChatAction> action);
|
||||||
|
|
||||||
void repair_dialog_action_bar(Dialog *d, const char *source);
|
void repair_dialog_action_bar(Dialog *d, const char *source);
|
||||||
|
|
||||||
void hide_dialog_action_bar(Dialog *d);
|
void hide_dialog_action_bar(Dialog *d);
|
||||||
@ -2340,6 +2353,8 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
bool update_dialog_silent_send_message(Dialog *d, bool silent_send_message);
|
bool update_dialog_silent_send_message(Dialog *d, bool silent_send_message);
|
||||||
|
|
||||||
|
static tl_object_ptr<td_api::ChatAction> copy_chat_action_object(const tl_object_ptr<td_api::ChatAction> &action);
|
||||||
|
|
||||||
bool is_dialog_action_unneeded(DialogId dialog_id) const;
|
bool is_dialog_action_unneeded(DialogId dialog_id) const;
|
||||||
|
|
||||||
void on_send_dialog_action_timeout(DialogId dialog_id);
|
void on_send_dialog_action_timeout(DialogId dialog_id);
|
||||||
@ -3056,7 +3071,8 @@ class MessagesManager : public Actor {
|
|||||||
std::unordered_map<int64, FullMessageId> get_dialog_message_by_date_results_;
|
std::unordered_map<int64, FullMessageId> get_dialog_message_by_date_results_;
|
||||||
|
|
||||||
std::unordered_map<int64, std::pair<int32, vector<MessageId>>>
|
std::unordered_map<int64, std::pair<int32, vector<MessageId>>>
|
||||||
found_dialog_messages_; // random_id -> [total_count, [message_id]...]
|
found_dialog_messages_; // random_id -> [total_count, [message_id]...]
|
||||||
|
std::unordered_map<int64, DialogId> found_dialog_messages_dialog_id_; // random_id -> dialog_id
|
||||||
std::unordered_map<int64, std::pair<int32, vector<FullMessageId>>>
|
std::unordered_map<int64, std::pair<int32, vector<FullMessageId>>>
|
||||||
found_messages_; // random_id -> [total_count, [full_message_id]...]
|
found_messages_; // random_id -> [total_count, [full_message_id]...]
|
||||||
std::unordered_map<int64, std::pair<int32, vector<FullMessageId>>>
|
std::unordered_map<int64, std::pair<int32, vector<FullMessageId>>>
|
||||||
|
@ -1398,6 +1398,39 @@ class GetChatHistoryRequest : public RequestActor<> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GetMessageThreadHistoryRequest : public RequestActor<> {
|
||||||
|
DialogId dialog_id_;
|
||||||
|
MessageId message_id_;
|
||||||
|
MessageId from_message_id_;
|
||||||
|
int32 offset_;
|
||||||
|
int32 limit_;
|
||||||
|
int64 random_id_;
|
||||||
|
|
||||||
|
std::pair<DialogId, vector<MessageId>> messages_;
|
||||||
|
|
||||||
|
void do_run(Promise<Unit> &&promise) override {
|
||||||
|
messages_ = td->messages_manager_->get_message_thread_history(dialog_id_, message_id_, from_message_id_, offset_,
|
||||||
|
limit_, random_id_, std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_send_result() override {
|
||||||
|
send_result(td->messages_manager_->get_messages_object(-1, messages_.first, messages_.second));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
GetMessageThreadHistoryRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, int64 message_id,
|
||||||
|
int64 from_message_id, int32 offset, int32 limit)
|
||||||
|
: RequestActor(std::move(td), request_id)
|
||||||
|
, dialog_id_(dialog_id)
|
||||||
|
, message_id_(message_id)
|
||||||
|
, from_message_id_(from_message_id)
|
||||||
|
, offset_(offset)
|
||||||
|
, limit_(limit)
|
||||||
|
, random_id_(0) {
|
||||||
|
set_tries(3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class SearchChatMessagesRequest : public RequestActor<> {
|
class SearchChatMessagesRequest : public RequestActor<> {
|
||||||
DialogId dialog_id_;
|
DialogId dialog_id_;
|
||||||
string query_;
|
string query_;
|
||||||
@ -3096,8 +3129,9 @@ void Td::on_online_updated(bool force, bool send_update) {
|
|||||||
update_status_query_ = create_handler<UpdateStatusQuery>()->send(!is_online_);
|
update_status_query_ = create_handler<UpdateStatusQuery>()->send(!is_online_);
|
||||||
}
|
}
|
||||||
if (is_online_) {
|
if (is_online_) {
|
||||||
alarm_timeout_.set_timeout_in(ONLINE_ALARM_ID,
|
alarm_timeout_.set_timeout_in(
|
||||||
G()->shared_config().get_option_integer("online_update_period_ms", 210000) * 1e-3);
|
ONLINE_ALARM_ID,
|
||||||
|
static_cast<double>(G()->shared_config().get_option_integer("online_update_period_ms", 210000)) * 1e-3);
|
||||||
} else {
|
} else {
|
||||||
alarm_timeout_.cancel_timeout(ONLINE_ALARM_ID);
|
alarm_timeout_.cancel_timeout(ONLINE_ALARM_ID);
|
||||||
}
|
}
|
||||||
@ -5506,6 +5540,12 @@ void Td::on_request(uint64 id, const td_api::deleteChatHistory &request) {
|
|||||||
std::move(promise));
|
std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Td::on_request(uint64 id, const td_api::getMessageThreadHistory &request) {
|
||||||
|
CHECK_IS_USER();
|
||||||
|
CREATE_REQUEST(GetMessageThreadHistoryRequest, request.chat_id_, request.message_id_, request.from_message_id_,
|
||||||
|
request.offset_, request.limit_);
|
||||||
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::searchChatMessages &request) {
|
void Td::on_request(uint64 id, td_api::searchChatMessages &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CLEAN_INPUT_STRING(request.query_);
|
CLEAN_INPUT_STRING(request.query_);
|
||||||
|
@ -237,7 +237,7 @@ class Td final : public NetQueryCallback {
|
|||||||
static td_api::object_ptr<td_api::Object> static_request(td_api::object_ptr<td_api::Function> function);
|
static td_api::object_ptr<td_api::Object> static_request(td_api::object_ptr<td_api::Function> function);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr const char *TDLIB_VERSION = "1.6.8";
|
static constexpr const char *TDLIB_VERSION = "1.6.9";
|
||||||
static constexpr int64 ONLINE_ALARM_ID = 0;
|
static constexpr int64 ONLINE_ALARM_ID = 0;
|
||||||
static constexpr int64 PING_SERVER_ALARM_ID = -1;
|
static constexpr int64 PING_SERVER_ALARM_ID = -1;
|
||||||
static constexpr int32 PING_SERVER_TIMEOUT = 300;
|
static constexpr int32 PING_SERVER_TIMEOUT = 300;
|
||||||
@ -578,6 +578,8 @@ class Td final : public NetQueryCallback {
|
|||||||
|
|
||||||
void on_request(uint64 id, const td_api::deleteChatHistory &request);
|
void on_request(uint64 id, const td_api::deleteChatHistory &request);
|
||||||
|
|
||||||
|
void on_request(uint64 id, const td_api::getMessageThreadHistory &request);
|
||||||
|
|
||||||
void on_request(uint64 id, td_api::searchChatMessages &request);
|
void on_request(uint64 id, td_api::searchChatMessages &request);
|
||||||
|
|
||||||
void on_request(uint64 id, td_api::searchSecretMessages &request);
|
void on_request(uint64 id, td_api::searchSecretMessages &request);
|
||||||
|
@ -1058,6 +1058,12 @@ void UpdatesManager::on_get_difference(tl_object_ptr<telegram_api::updates_Diffe
|
|||||||
auto difference = move_tl_object_as<telegram_api::updates_differenceEmpty>(difference_ptr);
|
auto difference = move_tl_object_as<telegram_api::updates_differenceEmpty>(difference_ptr);
|
||||||
set_date(difference->date_, false, "on_get_difference_empty");
|
set_date(difference->date_, false, "on_get_difference_empty");
|
||||||
seq_ = difference->seq_;
|
seq_ = difference->seq_;
|
||||||
|
if (!pending_seq_updates_.empty()) {
|
||||||
|
LOG(ERROR) << "Drop " << pending_seq_updates_.size() << " pending seq updates after receive empty difference";
|
||||||
|
}
|
||||||
|
if (!pending_qts_updates_.empty()) {
|
||||||
|
LOG(ERROR) << "Drop " << pending_qts_updates_.size() << " pending qts updates after receive empty difference";
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case telegram_api::updates_difference::ID: {
|
case telegram_api::updates_difference::ID: {
|
||||||
|
@ -1821,13 +1821,17 @@ class CliClient final : public Actor {
|
|||||||
}
|
}
|
||||||
send_request(td_api::make_object<td_api::getGroupsInCommon>(as_user_id(user_id), as_chat_id(offset_chat_id),
|
send_request(td_api::make_object<td_api::getGroupsInCommon>(as_user_id(user_id), as_chat_id(offset_chat_id),
|
||||||
to_integer<int32>(limit)));
|
to_integer<int32>(limit)));
|
||||||
} else if (op == "gh" || op == "GetHistory" || op == "ghl") {
|
} else if (op == "gh" || op == "GetHistory" || op == "ghl" || op == "gmth") {
|
||||||
string chat_id;
|
string chat_id;
|
||||||
|
string thread_message_id;
|
||||||
string from_message_id;
|
string from_message_id;
|
||||||
string offset;
|
string offset;
|
||||||
string limit;
|
string limit;
|
||||||
|
|
||||||
std::tie(chat_id, args) = split(args);
|
std::tie(chat_id, args) = split(args);
|
||||||
|
if (op == "gmth") {
|
||||||
|
std::tie(thread_message_id, args) = split(args);
|
||||||
|
}
|
||||||
std::tie(from_message_id, args) = split(args);
|
std::tie(from_message_id, args) = split(args);
|
||||||
if (from_message_id.empty()) {
|
if (from_message_id.empty()) {
|
||||||
from_message_id = "0";
|
from_message_id = "0";
|
||||||
@ -1842,6 +1846,10 @@ class CliClient final : public Actor {
|
|||||||
}
|
}
|
||||||
if (!args.empty()) {
|
if (!args.empty()) {
|
||||||
LOG(ERROR) << "Wrong parameters to function getChatHistory specified";
|
LOG(ERROR) << "Wrong parameters to function getChatHistory specified";
|
||||||
|
} else if (op == "gmth") {
|
||||||
|
send_request(td_api::make_object<td_api::getMessageThreadHistory>(
|
||||||
|
as_chat_id(chat_id), as_message_id(thread_message_id), as_message_id(from_message_id),
|
||||||
|
to_integer<int32>(offset), to_integer<int32>(limit)));
|
||||||
} else {
|
} else {
|
||||||
send_request(td_api::make_object<td_api::getChatHistory>(as_chat_id(chat_id), as_message_id(from_message_id),
|
send_request(td_api::make_object<td_api::getChatHistory>(as_chat_id(chat_id), as_message_id(from_message_id),
|
||||||
to_integer<int32>(offset), to_integer<int32>(limit),
|
to_integer<int32>(offset), to_integer<int32>(limit),
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "td/telegram/Global.h"
|
||||||
|
|
||||||
#include "td/actor/PromiseFuture.h"
|
#include "td/actor/PromiseFuture.h"
|
||||||
|
|
||||||
#include "td/utils/common.h"
|
#include "td/utils/common.h"
|
||||||
|
@ -9,15 +9,19 @@
|
|||||||
#include "td/utils/logging.h"
|
#include "td/utils/logging.h"
|
||||||
#include "td/utils/PathView.h"
|
#include "td/utils/PathView.h"
|
||||||
|
|
||||||
#if TD_PORT_WINDOWS && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#if TD_PORT_WINDOWS
|
||||||
|
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
#include "td/utils/port/wstring_convert.h"
|
#include "td/utils/port/wstring_convert.h"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#if TD_PORT_WINDOWS && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#if TD_PORT_WINDOWS
|
||||||
|
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
@ -70,7 +74,8 @@ void OptionParser::add_check(std::function<Status()> check) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result<vector<char *>> OptionParser::run(int argc, char *argv[], int expected_non_option_count) {
|
Result<vector<char *>> OptionParser::run(int argc, char *argv[], int expected_non_option_count) {
|
||||||
#if TD_PORT_WINDOWS && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#if TD_PORT_WINDOWS
|
||||||
|
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
LPWSTR *utf16_argv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
LPWSTR *utf16_argv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||||
if (utf16_argv == nullptr) {
|
if (utf16_argv == nullptr) {
|
||||||
return Status::Error("Failed to parse command line");
|
return Status::Error("Failed to parse command line");
|
||||||
@ -83,6 +88,7 @@ Result<vector<char *>> OptionParser::run(int argc, char *argv[], int expected_no
|
|||||||
}
|
}
|
||||||
LocalFree(utf16_argv);
|
LocalFree(utf16_argv);
|
||||||
argv = &args[0];
|
argv = &args[0];
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::unordered_map<char, const Option *> short_options;
|
std::unordered_map<char, const Option *> short_options;
|
||||||
|
@ -548,7 +548,7 @@ void aes_cbc_encrypt(Slice aes_key, MutableSlice aes_iv, Slice from, MutableSlic
|
|||||||
Evp evp;
|
Evp evp;
|
||||||
evp.init_encrypt_cbc(aes_key);
|
evp.init_encrypt_cbc(aes_key);
|
||||||
evp.init_iv(aes_iv);
|
evp.init_iv(aes_iv);
|
||||||
evp.encrypt(from.ubegin(), to.ubegin(), from.size());
|
evp.encrypt(from.ubegin(), to.ubegin(), narrow_cast<int>(from.size()));
|
||||||
aes_iv.copy_from(to.substr(from.size() - 16));
|
aes_iv.copy_from(to.substr(from.size() - 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,7 +560,7 @@ void aes_cbc_decrypt(Slice aes_key, MutableSlice aes_iv, Slice from, MutableSlic
|
|||||||
evp.init_decrypt_cbc(aes_key);
|
evp.init_decrypt_cbc(aes_key);
|
||||||
evp.init_iv(aes_iv);
|
evp.init_iv(aes_iv);
|
||||||
aes_iv.copy_from(from.substr(from.size() - 16));
|
aes_iv.copy_from(from.substr(from.size() - 16));
|
||||||
evp.decrypt(from.ubegin(), to.ubegin(), from.size());
|
evp.decrypt(from.ubegin(), to.ubegin(), narrow_cast<int>(from.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AesCbcState::Impl {
|
struct AesCbcState::Impl {
|
||||||
@ -591,7 +591,7 @@ void AesCbcState::encrypt(Slice from, MutableSlice to) {
|
|||||||
} else {
|
} else {
|
||||||
CHECK(is_encrypt_);
|
CHECK(is_encrypt_);
|
||||||
}
|
}
|
||||||
ctx_->evp_.encrypt(from.ubegin(), to.ubegin(), from.size());
|
ctx_->evp_.encrypt(from.ubegin(), to.ubegin(), narrow_cast<int>(from.size()));
|
||||||
raw_.iv.as_mutable_slice().copy_from(to.substr(from.size() - 16));
|
raw_.iv.as_mutable_slice().copy_from(to.substr(from.size() - 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,7 +611,7 @@ void AesCbcState::decrypt(Slice from, MutableSlice to) {
|
|||||||
CHECK(!is_encrypt_);
|
CHECK(!is_encrypt_);
|
||||||
}
|
}
|
||||||
raw_.iv.as_mutable_slice().copy_from(from.substr(from.size() - 16));
|
raw_.iv.as_mutable_slice().copy_from(from.substr(from.size() - 16));
|
||||||
ctx_->evp_.decrypt(from.ubegin(), to.ubegin(), from.size());
|
ctx_->evp_.decrypt(from.ubegin(), to.ubegin(), narrow_cast<int>(from.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AesCtrState::Impl {
|
struct AesCtrState::Impl {
|
||||||
@ -633,7 +633,7 @@ void AesCtrState::init(Slice key, Slice iv) {
|
|||||||
|
|
||||||
void AesCtrState::encrypt(Slice from, MutableSlice to) {
|
void AesCtrState::encrypt(Slice from, MutableSlice to) {
|
||||||
CHECK(from.size() <= to.size());
|
CHECK(from.size() <= to.size());
|
||||||
ctx_->evp_.encrypt(from.ubegin(), to.ubegin(), from.size());
|
ctx_->evp_.encrypt(from.ubegin(), to.ubegin(), narrow_cast<int>(from.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AesCtrState::decrypt(Slice from, MutableSlice to) {
|
void AesCtrState::decrypt(Slice from, MutableSlice to) {
|
||||||
|
@ -183,7 +183,7 @@ class messages_sendEncrypted final {
|
|||||||
BufferSlice data_;
|
BufferSlice data_;
|
||||||
|
|
||||||
messages_sendEncrypted() = default;
|
messages_sendEncrypted() = default;
|
||||||
static const int32 ID = -1451792525;
|
static const int32 ID = 1157265941;
|
||||||
|
|
||||||
explicit messages_sendEncrypted(TlBufferParser &p)
|
explicit messages_sendEncrypted(TlBufferParser &p)
|
||||||
: flags_(TlFetchInt::parse(p))
|
: flags_(TlFetchInt::parse(p))
|
||||||
|
Loading…
Reference in New Issue
Block a user