Merge commit '711b0cfd4f2aa163858b94e97db25d6be4adcfcb'

Conflicts:
	td/telegram/MessagesManager.cpp
This commit is contained in:
Andrea Cavalli 2020-10-01 23:45:02 +02:00
commit 96cf4f15a4
13 changed files with 604 additions and 470 deletions

View File

@ -404,6 +404,7 @@ set(TDLIB_SOURCE
td/telegram/Dependencies.cpp
td/telegram/DeviceTokenManager.cpp
td/telegram/DhCache.cpp
td/telegram/DialogAction.cpp
td/telegram/DialogAdministrator.cpp
td/telegram/DialogDb.cpp
td/telegram/DialogFilter.cpp
@ -563,6 +564,7 @@ set(TDLIB_SOURCE
td/telegram/DeviceTokenManager.h
td/telegram/DhCache.h
td/telegram/DhConfig.h
td/telegram/DialogAction.h
td/telegram/DialogAdministrator.h
td/telegram/DialogDate.h
td/telegram/DialogDb.h
@ -836,7 +838,6 @@ if (TD_ENABLE_DOTNET)
td/telegram/LogDotNet.cpp
${TL_DOTNET_SCHEME_SOURCE}
)
set(VCPKG_APPLOCAL_LIBRARY_DEPS ON)
set_target_properties(tddotnet PROPERTIES OUTPUT_NAME Telegram.Td)
target_link_libraries(tddotnet PRIVATE tdclient tdutils)
target_include_directories(tddotnet PUBLIC

View File

@ -639,15 +639,19 @@ messageForwardOriginChannel chat_id:int53 message_id:int53 author_signature:stri
//@from_message_id For messages forwarded to the chat with the current user (Saved Messages), to the Replies bot chat, or to the channel's discussion group, the identifier of the original message from which the new message was forwarded last time; 0 if unknown
messageForwardInfo origin:MessageForwardOrigin date:int32 public_service_announcement_type:string from_chat_id:int53 from_message_id:int53 = MessageForwardInfo;
//@description Contains information about message replies
//@reply_count Number of times the message was directly or indirectly replied
//@recent_replier_user_ids User identifiers of the recent repliers to the message; available in channels with a discussion supergroup
//@last_read_inbox_message_id Identifier of the last read incoming reply to the message
//@last_read_outbox_message_id Identifier of the last read outgoing reply to the message
//@last_message_id Identifier of the last reply to the message
messageReplyInfo reply_count:int32 recent_replier_user_ids:vector<int32> last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 last_message_id:int53 = MessageReplyInfo;
//@description Contains information about interactions with a message
//@view_count Number of times the message was viewed
//@forward_count Number of times the message was forwarded
//@reply_count Number of times the message was directly or indirectly replied; available in discussion supergroups and channels with a discussion supergroup
//@recent_replier_user_ids User identifiers of the recent repliers to the message; available in channels with a discussion supergroup
//@last_read_inbox_comment_message_id Identifier of the last read incoming comment to the message
//@last_read_outbox_comment_message_id Identifier of the last read outgoing comment to the message
//@last_comment_message_id Identifier of the last comment to the message
messageInteractionInfo view_count:int32 forward_count:int32 reply_count:int32 recent_replier_user_ids:vector<int32> last_read_inbox_comment_message_id:int53 last_read_outbox_comment_message_id:int53 last_comment_message_id:int53 = MessageInteractionInfo;
//@reply_info Contains information about direct or indirect replies to the message; may be null. Currently, available only in channels with a discussion supergroup and discussion supergroups for messages, which are not replies itself
messageInteractionInfo view_count:int32 forward_count:int32 reply_info:messageReplyInfo = MessageInteractionInfo;
//@class MessageSendingState @description Contains information about the sending state of the message

Binary file not shown.

View File

@ -0,0 +1,376 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "td/telegram/DialogAction.h"
namespace td {
void DialogAction::init(Type type) {
type_ = type;
progress_ = 0;
}
void DialogAction::init(Type type, int32 progress) {
if (progress < 0 || progress > 100) {
progress = 0;
}
type_ = type;
progress_ = progress;
}
DialogAction::DialogAction(Type type, int32 progress) {
init(type, progress);
}
DialogAction::DialogAction(tl_object_ptr<td_api::ChatAction> &&action) {
if (action == nullptr) {
return;
}
switch (action->get_id()) {
case td_api::chatActionCancel::ID:
init(Type::Cancel);
break;
case td_api::chatActionTyping::ID:
init(Type::Typing);
break;
case td_api::chatActionRecordingVideo::ID:
init(Type::RecordingVideo);
break;
case td_api::chatActionUploadingVideo::ID: {
auto uploading_action = move_tl_object_as<td_api::chatActionUploadingVideo>(action);
init(Type::UploadingVideo, uploading_action->progress_);
break;
}
case td_api::chatActionRecordingVoiceNote::ID:
init(Type::RecordingVoiceNote);
break;
case td_api::chatActionUploadingVoiceNote::ID: {
auto uploading_action = move_tl_object_as<td_api::chatActionUploadingVoiceNote>(action);
init(Type::UploadingVoiceNote, uploading_action->progress_);
break;
}
case td_api::chatActionUploadingPhoto::ID: {
auto uploading_action = move_tl_object_as<td_api::chatActionUploadingPhoto>(action);
init(Type::UploadingPhoto, uploading_action->progress_);
break;
}
case td_api::chatActionUploadingDocument::ID: {
auto uploading_action = move_tl_object_as<td_api::chatActionUploadingDocument>(action);
init(Type::UploadingDocument, uploading_action->progress_);
break;
}
case td_api::chatActionChoosingLocation::ID:
init(Type::ChoosingLocation);
break;
case td_api::chatActionChoosingContact::ID:
init(Type::ChoosingContact);
break;
case td_api::chatActionStartPlayingGame::ID:
init(Type::StartPlayingGame);
break;
case td_api::chatActionRecordingVideoNote::ID:
init(Type::RecordingVideoNote);
break;
case td_api::chatActionUploadingVideoNote::ID: {
auto uploading_action = move_tl_object_as<td_api::chatActionUploadingVideoNote>(action);
init(Type::UploadingVideoNote, uploading_action->progress_);
break;
}
default:
UNREACHABLE();
break;
}
}
DialogAction::DialogAction(tl_object_ptr<telegram_api::SendMessageAction> &&action) {
switch (action->get_id()) {
case telegram_api::sendMessageCancelAction::ID:
init(Type::Cancel);
break;
case telegram_api::sendMessageTypingAction::ID:
init(Type::Typing);
break;
case telegram_api::sendMessageRecordVideoAction::ID:
init(Type::RecordingVideo);
break;
case telegram_api::sendMessageUploadVideoAction::ID: {
auto upload_video_action = move_tl_object_as<telegram_api::sendMessageUploadVideoAction>(action);
init(Type::UploadingVideo, upload_video_action->progress_);
break;
}
case telegram_api::sendMessageRecordAudioAction::ID:
init(Type::RecordingVoiceNote);
break;
case telegram_api::sendMessageUploadAudioAction::ID: {
auto upload_audio_action = move_tl_object_as<telegram_api::sendMessageUploadAudioAction>(action);
init(Type::UploadingVoiceNote, upload_audio_action->progress_);
break;
}
case telegram_api::sendMessageUploadPhotoAction::ID: {
auto upload_photo_action = move_tl_object_as<telegram_api::sendMessageUploadPhotoAction>(action);
init(Type::UploadingPhoto, upload_photo_action->progress_);
break;
}
case telegram_api::sendMessageUploadDocumentAction::ID: {
auto upload_document_action = move_tl_object_as<telegram_api::sendMessageUploadDocumentAction>(action);
init(Type::UploadingDocument, upload_document_action->progress_);
break;
}
case telegram_api::sendMessageGeoLocationAction::ID:
init(Type::ChoosingLocation);
break;
case telegram_api::sendMessageChooseContactAction::ID:
init(Type::ChoosingContact);
break;
case telegram_api::sendMessageGamePlayAction::ID:
init(Type::StartPlayingGame);
break;
case telegram_api::sendMessageRecordRoundAction::ID:
init(Type::RecordingVideoNote);
break;
case telegram_api::sendMessageUploadRoundAction::ID: {
auto upload_round_action = move_tl_object_as<telegram_api::sendMessageUploadRoundAction>(action);
init(Type::UploadingVideoNote, upload_round_action->progress_);
break;
}
default:
UNREACHABLE();
break;
}
}
tl_object_ptr<telegram_api::SendMessageAction> DialogAction::get_input_send_message_action() const {
switch (type_) {
case Type::Cancel:
return make_tl_object<telegram_api::sendMessageCancelAction>();
case Type::Typing:
return make_tl_object<telegram_api::sendMessageTypingAction>();
case Type::RecordingVideo:
return make_tl_object<telegram_api::sendMessageRecordVideoAction>();
case Type::UploadingVideo:
return make_tl_object<telegram_api::sendMessageUploadVideoAction>(progress_);
case Type::RecordingVoiceNote:
return make_tl_object<telegram_api::sendMessageRecordAudioAction>();
case Type::UploadingVoiceNote:
return make_tl_object<telegram_api::sendMessageUploadAudioAction>(progress_);
case Type::UploadingPhoto:
return make_tl_object<telegram_api::sendMessageUploadPhotoAction>(progress_);
case Type::UploadingDocument:
return make_tl_object<telegram_api::sendMessageUploadDocumentAction>(progress_);
case Type::ChoosingLocation:
return make_tl_object<telegram_api::sendMessageGeoLocationAction>();
case Type::ChoosingContact:
return make_tl_object<telegram_api::sendMessageChooseContactAction>();
case Type::RecordingVideoNote:
return make_tl_object<telegram_api::sendMessageRecordRoundAction>();
case Type::UploadingVideoNote:
return make_tl_object<telegram_api::sendMessageUploadRoundAction>(progress_);
case Type::StartPlayingGame:
return make_tl_object<telegram_api::sendMessageTypingAction>();
default:
UNREACHABLE();
return nullptr;
}
}
tl_object_ptr<secret_api::SendMessageAction> DialogAction::get_secret_input_send_message_action() const {
switch (type_) {
case Type::Cancel:
return make_tl_object<secret_api::sendMessageCancelAction>();
case Type::Typing:
return make_tl_object<secret_api::sendMessageTypingAction>();
case Type::RecordingVideo:
return make_tl_object<secret_api::sendMessageRecordVideoAction>();
case Type::UploadingVideo:
return make_tl_object<secret_api::sendMessageUploadVideoAction>();
case Type::RecordingVoiceNote:
return make_tl_object<secret_api::sendMessageRecordAudioAction>();
case Type::UploadingVoiceNote:
return make_tl_object<secret_api::sendMessageUploadAudioAction>();
case Type::UploadingPhoto:
return make_tl_object<secret_api::sendMessageUploadPhotoAction>();
case Type::UploadingDocument:
return make_tl_object<secret_api::sendMessageUploadDocumentAction>();
case Type::ChoosingLocation:
return make_tl_object<secret_api::sendMessageGeoLocationAction>();
case Type::ChoosingContact:
return make_tl_object<secret_api::sendMessageChooseContactAction>();
case Type::RecordingVideoNote:
return make_tl_object<secret_api::sendMessageRecordRoundAction>();
case Type::UploadingVideoNote:
return make_tl_object<secret_api::sendMessageUploadRoundAction>();
case Type::StartPlayingGame:
return make_tl_object<secret_api::sendMessageTypingAction>();
default:
UNREACHABLE();
return nullptr;
}
}
tl_object_ptr<td_api::ChatAction> DialogAction::get_chat_action_object() const {
switch (type_) {
case Type::Cancel:
return td_api::make_object<td_api::chatActionCancel>();
case Type::Typing:
return td_api::make_object<td_api::chatActionTyping>();
case Type::RecordingVideo:
return td_api::make_object<td_api::chatActionRecordingVideo>();
case Type::UploadingVideo:
return td_api::make_object<td_api::chatActionUploadingVideo>(progress_);
case Type::RecordingVoiceNote:
return td_api::make_object<td_api::chatActionRecordingVoiceNote>();
case Type::UploadingVoiceNote:
return td_api::make_object<td_api::chatActionUploadingVoiceNote>(progress_);
case Type::UploadingPhoto:
return td_api::make_object<td_api::chatActionUploadingPhoto>(progress_);
case Type::UploadingDocument:
return td_api::make_object<td_api::chatActionUploadingDocument>(progress_);
case Type::ChoosingLocation:
return td_api::make_object<td_api::chatActionChoosingLocation>();
case Type::ChoosingContact:
return td_api::make_object<td_api::chatActionChoosingContact>();
case Type::StartPlayingGame:
return td_api::make_object<td_api::chatActionStartPlayingGame>();
case Type::RecordingVideoNote:
return td_api::make_object<td_api::chatActionRecordingVideoNote>();
case Type::UploadingVideoNote:
return td_api::make_object<td_api::chatActionUploadingVideoNote>(progress_);
default:
UNREACHABLE();
return td_api::make_object<td_api::chatActionCancel>();
}
}
bool DialogAction::is_cancelled_by_message_of_type(MessageContentType message_content_type) const {
if (message_content_type == MessageContentType::None) {
return true;
}
if (type_ == Type::Typing) {
return message_content_type == MessageContentType::Text || message_content_type == MessageContentType::Game ||
can_have_message_content_caption(message_content_type);
}
switch (message_content_type) {
case MessageContentType::Animation:
case MessageContentType::Audio:
case MessageContentType::Document:
return type_ == Type::UploadingDocument;
case MessageContentType::ExpiredPhoto:
case MessageContentType::Photo:
return type_ == Type::UploadingPhoto;
case MessageContentType::ExpiredVideo:
case MessageContentType::Video:
return type_ == Type::RecordingVideo || type_ == Type::UploadingVideo;
case MessageContentType::VideoNote:
return type_ == Type::RecordingVideoNote || type_ == Type::UploadingVideoNote;
case MessageContentType::VoiceNote:
return type_ == Type::RecordingVoiceNote || type_ == Type::UploadingVoiceNote;
case MessageContentType::Contact:
return type_ == Type::ChoosingContact;
case MessageContentType::LiveLocation:
case MessageContentType::Location:
case MessageContentType::Venue:
return type_ == Type::ChoosingLocation;
case MessageContentType::Game:
case MessageContentType::Invoice:
case MessageContentType::Sticker:
case MessageContentType::Text:
case MessageContentType::Unsupported:
case MessageContentType::ChatCreate:
case MessageContentType::ChatChangeTitle:
case MessageContentType::ChatChangePhoto:
case MessageContentType::ChatDeletePhoto:
case MessageContentType::ChatDeleteHistory:
case MessageContentType::ChatAddUsers:
case MessageContentType::ChatJoinedByLink:
case MessageContentType::ChatDeleteUser:
case MessageContentType::ChatMigrateTo:
case MessageContentType::ChannelCreate:
case MessageContentType::ChannelMigrateFrom:
case MessageContentType::PinMessage:
case MessageContentType::GameScore:
case MessageContentType::ScreenshotTaken:
case MessageContentType::ChatSetTtl:
case MessageContentType::Call:
case MessageContentType::PaymentSuccessful:
case MessageContentType::ContactRegistered:
case MessageContentType::CustomServiceAction:
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
case MessageContentType::Dice:
return false;
default:
UNREACHABLE();
return false;
}
}
DialogAction DialogAction::get_uploading_action(MessageContentType message_content_type, int32 progress) {
switch (message_content_type) {
case MessageContentType::Animation:
case MessageContentType::Audio:
case MessageContentType::Document:
return DialogAction(Type::UploadingDocument, progress);
case MessageContentType::Photo:
return DialogAction(Type::UploadingPhoto, progress);
case MessageContentType::Video:
return DialogAction(Type::UploadingVideo, progress);
case MessageContentType::VideoNote:
return DialogAction(Type::UploadingVideoNote, progress);
case MessageContentType::VoiceNote:
return DialogAction(Type::UploadingVoiceNote, progress);
default:
return DialogAction();
}
}
StringBuilder &operator<<(StringBuilder &string_builder, const DialogAction &action) {
string_builder << "ChatAction";
const char *type = [action_type = action.type_] {
switch (action_type) {
case DialogAction::Type::Cancel:
return "Cancel";
case DialogAction::Type::Typing:
return "Typing";
case DialogAction::Type::RecordingVideo:
return "RecordingVideo";
case DialogAction::Type::UploadingVideo:
return "UploadingVideo";
case DialogAction::Type::RecordingVoiceNote:
return "RecordingVoiceNote";
case DialogAction::Type::UploadingVoiceNote:
return "UploadingVoiceNote";
case DialogAction::Type::UploadingPhoto:
return "UploadingPhoto";
case DialogAction::Type::UploadingDocument:
return "UploadingDocument";
case DialogAction::Type::ChoosingLocation:
return "ChoosingLocation";
case DialogAction::Type::ChoosingContact:
return "ChoosingContact";
case DialogAction::Type::StartPlayingGame:
return "StartPlayingGame";
case DialogAction::Type::RecordingVideoNote:
return "RecordingVideoNote";
case DialogAction::Type::UploadingVideoNote:
return "UploadingVideoNote";
default:
UNREACHABLE();
return "Cancel";
}
}();
string_builder << type << "Action";
if (action.progress_ != 0) {
string_builder << '(' << action.progress_ << "%)";
}
return string_builder;
}
} // namespace td

View File

@ -0,0 +1,73 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/MessageContentType.h"
#include "td/telegram/secret_api.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/tl_helpers.h"
namespace td {
class DialogAction {
public:
enum class Type : int32 {
Cancel,
Typing,
RecordingVideo,
UploadingVideo,
RecordingVoiceNote,
UploadingVoiceNote,
UploadingPhoto,
UploadingDocument,
ChoosingLocation,
ChoosingContact,
StartPlayingGame,
RecordingVideoNote,
UploadingVideoNote
};
Type type_ = Type::Cancel;
int32 progress_ = 0;
DialogAction() = default;
DialogAction(Type type, int32 progress);
explicit DialogAction(tl_object_ptr<td_api::ChatAction> &&action);
explicit DialogAction(tl_object_ptr<telegram_api::SendMessageAction> &&action);
tl_object_ptr<telegram_api::SendMessageAction> get_input_send_message_action() const;
tl_object_ptr<secret_api::SendMessageAction> get_secret_input_send_message_action() const;
td_api::object_ptr<td_api::ChatAction> get_chat_action_object() const;
bool is_cancelled_by_message_of_type(MessageContentType message_content_type) const;
static DialogAction get_uploading_action(MessageContentType message_content_type, int32 progress);
private:
void init(Type type);
void init(Type type, int32 progress);
};
inline bool operator==(const DialogAction &lhs, const DialogAction &rhs) {
return lhs.type_ == rhs.type_ && lhs.progress_ == rhs.progress_;
}
inline bool operator!=(const DialogAction &lhs, const DialogAction &rhs) {
return !(lhs == rhs);
}
StringBuilder &operator<<(StringBuilder &string_builder, const DialogAction &action);
} // namespace td

View File

@ -19,7 +19,7 @@ td_api::object_ptr<td_api::chatAdministrator> DialogAdministrator::get_chat_admi
}
StringBuilder &operator<<(StringBuilder &string_builder, const DialogAdministrator &administrator) {
return string_builder << "DialogAdministrator[" << administrator.user_id_ << ", title = " << administrator.rank_
return string_builder << "ChatAdministrator[" << administrator.user_id_ << ", title = " << administrator.rank_
<< ", is_owner = " << administrator.is_creator_ << "]";
}

View File

@ -242,7 +242,7 @@ string LanguagePackManager::get_main_language_code() {
if (language_pack_.empty() || language_code_.empty()) {
return "en";
}
if (language_code_.size() <= 2) {
if (language_code_.size() == 2) {
return language_code_;
}
@ -267,7 +267,8 @@ string LanguagePackManager::get_main_language_code() {
}
if (info == nullptr) {
LOG(ERROR) << "Failed to find information about chosen language " << language_code_;
LOG(WARNING) << "Failed to find information about chosen language " << language_code_
<< ", ensure that valid language pack ID is used";
if (!is_custom_language_code(language_code_)) {
search_language_info(language_code_, Auto());
}
@ -308,11 +309,12 @@ vector<string> LanguagePackManager::get_used_language_codes() {
}
vector<string> result;
if (language_code_.size() <= 2) {
if (language_code_.size() == 2) {
result.push_back(language_code_);
}
if (info == nullptr) {
LOG(ERROR) << "Failed to find information about chosen language " << language_code_;
LOG(WARNING) << "Failed to find information about chosen language " << language_code_
<< ", ensure that valid language pack ID is used";
if (!is_custom_language_code(language_code_)) {
search_language_info(language_code_, Auto());
}

View File

@ -399,21 +399,19 @@ class GetDiscussionMessageQuery : public Td::ResultHandler {
Promise<vector<FullMessageId>> promise_;
DialogId dialog_id_;
MessageId message_id_;
ChannelId expected_channel_id_;
DialogId expected_dialog_id_;
MessageId expected_message_id_;
public:
explicit GetDiscussionMessageQuery(Promise<vector<FullMessageId>> &&promise) : promise_(std::move(promise)) {
}
void send(DialogId dialog_id, MessageId message_id, ChannelId expected_channel_id, MessageId expected_message_id) {
void send(DialogId dialog_id, MessageId message_id, DialogId expected_dialog_id, MessageId expected_message_id) {
dialog_id_ = dialog_id;
message_id_ = message_id;
expected_channel_id_ = expected_channel_id;
expected_dialog_id_ = expected_dialog_id;
expected_message_id_ = expected_message_id;
if (!expected_channel_id_.is_valid()) {
return promise_.set_error(Status::Error(500, "Wrong message specified"));
}
CHECK(expected_dialog_id_.is_valid());
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read);
CHECK(input_peer != nullptr);
send_query(G()->net_query_creator().create(
@ -443,7 +441,7 @@ class GetDiscussionMessageQuery : public Td::ResultHandler {
if ((ptr->flags_ & telegram_api::messages_discussionMessage::READ_OUTBOX_MAX_ID_MASK) != 0) {
last_read_outbox_message_id = MessageId(ServerMessageId(ptr->read_outbox_max_id_));
}
if (DialogId(expected_channel_id_) != dialog_id_) {
if (expected_dialog_id_ != dialog_id_) {
td->messages_manager_->on_update_read_message_comments(dialog_id_, message_id_, max_message_id,
last_read_inbox_message_id, last_read_outbox_message_id);
}
@ -455,7 +453,7 @@ class GetDiscussionMessageQuery : public Td::ResultHandler {
"GetDiscussionMessageQuery");
if (full_message_id.get_message_id().is_valid()) {
full_message_ids.push_back(full_message_id);
if (full_message_id.get_dialog_id() != DialogId(expected_channel_id_)) {
if (full_message_id.get_dialog_id() != expected_dialog_id_) {
return on_error(id, Status::Error(500, "Expected messages in a different chat"));
}
if (full_message_id.get_message_id() == expected_message_id_) {
@ -467,16 +465,16 @@ class GetDiscussionMessageQuery : public Td::ResultHandler {
top_message_id = full_message_ids.back().get_message_id();
}
if (top_message_id.is_valid()) {
td->messages_manager_->on_update_read_message_comments(DialogId(expected_channel_id_), top_message_id,
max_message_id, last_read_inbox_message_id,
last_read_outbox_message_id);
td->messages_manager_->on_update_read_message_comments(expected_dialog_id_, top_message_id, max_message_id,
last_read_inbox_message_id, last_read_outbox_message_id);
}
promise_.set_value(std::move(full_message_ids));
}
void on_error(uint64 id, Status status) override {
// because the error can be caused by the linked channel
// td->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetDiscussionMessageQuery");
if (expected_dialog_id_ == dialog_id_) {
td->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetDiscussionMessageQuery");
}
promise_.set_error(std::move(status));
}
};
@ -6513,6 +6511,12 @@ bool MessagesManager::is_active_message_reply_info(DialogId dialog_id, const Mes
if (dialog_id.get_type() != DialogType::Channel) {
return false;
}
auto channel_id = dialog_id.get_channel_id();
if (!td_->contacts_manager_->get_channel_has_linked_channel(channel_id)) {
return false;
}
if (!info.is_comment) {
return true;
}
@ -6520,10 +6524,6 @@ bool MessagesManager::is_active_message_reply_info(DialogId dialog_id, const Mes
return true;
}
auto channel_id = dialog_id.get_channel_id();
if (!td_->contacts_manager_->get_channel_has_linked_channel(channel_id)) {
return false;
}
auto linked_channel_id = td_->contacts_manager_->get_channel_linked_channel_id(channel_id);
if (!linked_channel_id.is_valid()) {
// keep the comment button while linked channel is unknown
@ -6559,27 +6559,23 @@ td_api::object_ptr<td_api::messageInteractionInfo> MessagesManager::get_message_
return nullptr;
}
int32 reply_count = -1;
vector<UserId> recent_replier_user_ids;
MessageId last_read_inbox_message_id;
MessageId last_read_outbox_message_id;
MessageId max_message_id;
td_api::object_ptr<td_api::messageReplyInfo> reply_info;
if (is_visible_reply_info) {
reply_count = m->reply_info.reply_count;
vector<UserId> recent_replier_user_ids;
for (auto recent_replier_dialog_id : m->reply_info.recent_replier_dialog_ids) {
if (recent_replier_dialog_id.get_type() == DialogType::User) {
recent_replier_user_ids.push_back(recent_replier_dialog_id.get_user_id());
}
}
last_read_inbox_message_id = m->reply_info.last_read_inbox_message_id;
last_read_outbox_message_id = m->reply_info.last_read_outbox_message_id;
max_message_id = m->reply_info.max_message_id;
reply_info = td_api::make_object<td_api::messageReplyInfo>(
m->reply_info.reply_count,
td_->contacts_manager_->get_user_ids_object(recent_replier_user_ids, "get_message_interaction_info_object"),
m->reply_info.last_read_inbox_message_id.get(), m->reply_info.last_read_outbox_message_id.get(),
m->reply_info.max_message_id.get());
CHECK(reply_info->reply_count_ >= 0);
}
return td_api::make_object<td_api::messageInteractionInfo>(
m->view_count, m->forward_count, reply_count,
td_->contacts_manager_->get_user_ids_object(recent_replier_user_ids, "get_message_interaction_info_object"),
last_read_inbox_message_id.get(), last_read_outbox_message_id.get(), max_message_id.get());
return td_api::make_object<td_api::messageInteractionInfo>(m->view_count, m->forward_count, std::move(reply_info));
}
bool MessagesManager::update_message_interaction_info(DialogId dialog_id, Message *m, int32 view_count,
@ -6845,87 +6841,17 @@ void MessagesManager::on_update_delete_scheduled_messages(DialogId dialog_id,
send_update_chat_has_scheduled_messages(d, true);
}
bool MessagesManager::need_cancel_user_dialog_action(int32 action_id, MessageContentType message_content_type) {
if (message_content_type == MessageContentType::None) {
return true;
}
if (action_id == td_api::chatActionTyping::ID) {
return message_content_type == MessageContentType::Text || message_content_type == MessageContentType::Game ||
can_have_message_content_caption(message_content_type);
}
switch (message_content_type) {
case MessageContentType::Animation:
case MessageContentType::Audio:
case MessageContentType::Document:
return action_id == td_api::chatActionUploadingDocument::ID;
case MessageContentType::ExpiredPhoto:
case MessageContentType::Photo:
return action_id == td_api::chatActionUploadingPhoto::ID;
case MessageContentType::ExpiredVideo:
case MessageContentType::Video:
return action_id == td_api::chatActionRecordingVideo::ID || action_id == td_api::chatActionUploadingVideo::ID;
case MessageContentType::VideoNote:
return action_id == td_api::chatActionRecordingVideoNote::ID ||
action_id == td_api::chatActionUploadingVideoNote::ID;
case MessageContentType::VoiceNote:
return action_id == td_api::chatActionRecordingVoiceNote::ID ||
action_id == td_api::chatActionUploadingVoiceNote::ID;
case MessageContentType::Contact:
return action_id == td_api::chatActionChoosingContact::ID;
case MessageContentType::LiveLocation:
case MessageContentType::Location:
case MessageContentType::Venue:
return action_id == td_api::chatActionChoosingLocation::ID;
case MessageContentType::Game:
case MessageContentType::Invoice:
case MessageContentType::Sticker:
case MessageContentType::Text:
case MessageContentType::Unsupported:
case MessageContentType::ChatCreate:
case MessageContentType::ChatChangeTitle:
case MessageContentType::ChatChangePhoto:
case MessageContentType::ChatDeletePhoto:
case MessageContentType::ChatDeleteHistory:
case MessageContentType::ChatAddUsers:
case MessageContentType::ChatJoinedByLink:
case MessageContentType::ChatDeleteUser:
case MessageContentType::ChatMigrateTo:
case MessageContentType::ChannelCreate:
case MessageContentType::ChannelMigrateFrom:
case MessageContentType::PinMessage:
case MessageContentType::GameScore:
case MessageContentType::ScreenshotTaken:
case MessageContentType::ChatSetTtl:
case MessageContentType::Call:
case MessageContentType::PaymentSuccessful:
case MessageContentType::ContactRegistered:
case MessageContentType::CustomServiceAction:
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
case MessageContentType::Dice:
return false;
default:
UNREACHABLE();
return false;
}
}
void MessagesManager::on_user_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, UserId user_id,
tl_object_ptr<td_api::ChatAction> &&action, int32 date,
MessageContentType message_content_type) {
DialogAction action, int32 date, MessageContentType message_content_type) {
if (td_->auth_manager_->is_bot() || !user_id.is_valid() || is_broadcast_channel(dialog_id)) {
return;
}
if (action != nullptr || message_content_type != MessageContentType::None) {
bool is_canceled = action == DialogAction();
if (!is_canceled || message_content_type != MessageContentType::None) {
td_->contacts_manager_->on_update_user_local_was_online(user_id, date);
}
bool is_canceled = action == nullptr || action->get_id() == td_api::chatActionCancel::ID;
if (is_canceled) {
auto actions_it = active_dialog_actions_.find(dialog_id);
if (actions_it == active_dialog_actions_.end()) {
@ -6940,7 +6866,7 @@ void MessagesManager::on_user_dialog_action(DialogId dialog_id, MessageId top_th
}
if (!td_->contacts_manager_->is_user_bot(user_id) &&
!need_cancel_user_dialog_action(it->action_id, message_content_type)) {
!it->action.is_cancelled_by_message_of_type(message_content_type)) {
return;
}
@ -6952,9 +6878,6 @@ void MessagesManager::on_user_dialog_action(DialogId dialog_id, MessageId top_th
LOG(DEBUG) << "Cancel action timeout in " << dialog_id;
active_dialog_action_timeout_.cancel_timeout(dialog_id.get());
}
if (action == nullptr) {
action = make_tl_object<td_api::chatActionCancel>();
}
} else {
if (date < G()->unix_time_cached() - DIALOG_ACTION_TIMEOUT - 60) {
LOG(DEBUG) << "Ignore too old action of " << user_id << " in " << dialog_id << " sent at " << date;
@ -6964,43 +6887,22 @@ void MessagesManager::on_user_dialog_action(DialogId dialog_id, MessageId top_th
auto it = std::find_if(active_actions.begin(), active_actions.end(),
[user_id](const ActiveDialogAction &action) { return action.user_id == user_id; });
MessageId prev_top_thread_message_id;
int32 prev_action_id = 0;
int32 prev_progress = 0;
DialogAction prev_action;
if (it != active_actions.end()) {
LOG(DEBUG) << "Re-add action of " << user_id << " in " << dialog_id;
prev_top_thread_message_id = it->top_thread_message_id;
prev_action_id = it->action_id;
prev_progress = it->progress;
prev_action = it->action;
active_actions.erase(it);
} else {
LOG(DEBUG) << "Add action of " << user_id << " in " << dialog_id;
}
auto action_id = action->get_id();
auto progress = [&] {
switch (action_id) {
case td_api::chatActionUploadingVideo::ID:
return static_cast<td_api::chatActionUploadingVideo &>(*action).progress_;
case td_api::chatActionUploadingVoiceNote::ID:
return static_cast<td_api::chatActionUploadingVoiceNote &>(*action).progress_;
case td_api::chatActionUploadingPhoto::ID:
return static_cast<td_api::chatActionUploadingPhoto &>(*action).progress_;
case td_api::chatActionUploadingDocument::ID:
return static_cast<td_api::chatActionUploadingDocument &>(*action).progress_;
case td_api::chatActionUploadingVideoNote::ID:
return static_cast<td_api::chatActionUploadingVideoNote &>(*action).progress_;
default:
return 0;
}
}();
active_actions.emplace_back(top_thread_message_id, user_id, action_id, Time::now());
if (top_thread_message_id == prev_top_thread_message_id && action_id == prev_action_id &&
progress <= prev_progress) {
active_actions.emplace_back(top_thread_message_id, user_id, action, Time::now());
if (top_thread_message_id == prev_top_thread_message_id && action == prev_action) {
return;
}
if (top_thread_message_id != prev_top_thread_message_id && prev_top_thread_message_id.is_valid()) {
send_update_user_chat_action(dialog_id, prev_top_thread_message_id, user_id,
td_api::make_object<td_api::chatActionCancel>());
send_update_user_chat_action(dialog_id, prev_top_thread_message_id, user_id, DialogAction());
}
if (active_actions.size() == 1u) {
LOG(DEBUG) << "Set action timeout in " << dialog_id;
@ -7010,9 +6912,9 @@ 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 (top_thread_message_id.is_valid()) {
send_update_user_chat_action(dialog_id, MessageId(), user_id, copy_chat_action_object(action));
send_update_user_chat_action(dialog_id, MessageId(), user_id, action);
}
send_update_user_chat_action(dialog_id, top_thread_message_id, user_id, std::move(action));
send_update_user_chat_action(dialog_id, top_thread_message_id, user_id, action);
}
}
@ -7023,7 +6925,7 @@ void MessagesManager::cancel_user_dialog_action(DialogId dialog_id, const Messag
return;
}
on_user_dialog_action(dialog_id, MessageId(), m->sender_user_id, nullptr, m->date, m->content->get_type());
on_user_dialog_action(dialog_id, MessageId(), m->sender_user_id, DialogAction(), m->date, m->content->get_type());
}
void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_ptr<telegram_api::Update> &&update,
@ -7768,7 +7670,7 @@ void MessagesManager::repair_dialog_action_bar(Dialog *d, const char *source) {
d->know_action_bar = false;
if (have_input_peer(dialog_id, AccessRights::Read)) {
create_actor<SleepActor>(
"RepairDialogActionBarActor", 1.0,
"RepairChatActionBarActor", 1.0,
PromiseCreator::lambda([actor_id = actor_id(this), dialog_id, source](Result<Unit> result) {
send_closure(actor_id, &MessagesManager::reget_dialog_action_bar, dialog_id, source);
}))
@ -16064,6 +15966,24 @@ FullMessageId MessagesManager::get_replied_message(DialogId dialog_id, MessageId
return replied_message_id;
}
Result<FullMessageId> MessagesManager::get_top_thread_full_message_id(DialogId dialog_id, const Message *m) const {
CHECK(m != nullptr);
if (m->message_id.is_scheduled()) {
return Status::Error(400, "Message is scheduled");
}
if (m->reply_info.is_comment) {
if (!is_visible_message_reply_info(dialog_id, m)) {
return Status::Error(400, "Message has no comments");
}
return FullMessageId{DialogId(m->reply_info.channel_id), m->linked_top_thread_message_id};
} else {
if (!m->top_thread_message_id.is_valid() || !is_visible_message_reply_info(dialog_id, m)) {
return Status::Error(400, "Message has no thread");
}
return FullMessageId{dialog_id, m->top_thread_message_id};
}
}
void MessagesManager::get_message_thread(DialogId dialog_id, MessageId message_id,
Promise<MessageThreadInfo> &&promise) {
LOG(INFO) << "Get message thread from " << message_id << " in " << dialog_id;
@ -16086,21 +16006,7 @@ void MessagesManager::get_message_thread(DialogId dialog_id, MessageId message_i
return promise.set_error(Status::Error(400, "Message not found"));
}
ChannelId message_thread_channel_id;
MessageId top_thread_message_id;
if (m->reply_info.is_comment) {
if (!is_visible_message_reply_info(dialog_id, m)) {
return promise.set_error(Status::Error(400, "Message has no comments"));
}
message_thread_channel_id = m->reply_info.channel_id;
} else {
if (!m->top_thread_message_id.is_valid()) {
return promise.set_error(Status::Error(400, "Message has no thread"));
}
message_thread_channel_id = dialog_id.get_channel_id();
top_thread_message_id = m->top_thread_message_id;
}
CHECK(message_thread_channel_id.is_valid());
TRY_RESULT_PROMISE(promise, top_thread_full_message_id, get_top_thread_full_message_id(dialog_id, m));
auto query_promise =
PromiseCreator::lambda([actor_id = actor_id(this), dialog_id, message_id,
@ -16113,7 +16019,8 @@ void MessagesManager::get_message_thread(DialogId dialog_id, MessageId message_i
});
td_->create_handler<GetDiscussionMessageQuery>(std::move(query_promise))
->send(dialog_id, message_id, message_thread_channel_id, top_thread_message_id);
->send(dialog_id, message_id, top_thread_full_message_id.get_dialog_id(),
top_thread_full_message_id.get_message_id());
}
void MessagesManager::on_get_discussion_message(DialogId dialog_id, MessageId message_id,
@ -16193,11 +16100,13 @@ td_api::object_ptr<td_api::messageThreadInfo> MessagesManager::get_message_threa
MessageId top_thread_message_id;
td_api::object_ptr<td_api::draftMessage> draft_message;
if (!info.message_ids.empty() && can_send_message(d->dialog_id).is_ok()) {
if (!info.message_ids.empty()) {
top_thread_message_id = info.message_ids.back();
const Message *m = get_message_force(d, top_thread_message_id, "get_message_thread_info_object 2");
if (m != nullptr && !m->reply_info.is_comment && is_active_message_reply_info(d->dialog_id, m->reply_info)) {
draft_message = get_draft_message_object(m->thread_draft_message);
if (can_send_message(d->dialog_id).is_ok()) {
const Message *m = get_message_force(d, top_thread_message_id, "get_message_thread_info_object 2");
if (m != nullptr && !m->reply_info.is_comment && is_active_message_reply_info(d->dialog_id, m->reply_info)) {
draft_message = get_draft_message_object(m->thread_draft_message);
}
}
}
return td_api::make_object<td_api::messageThreadInfo>(d->dialog_id.get(), top_thread_message_id.get(),
@ -16789,7 +16698,7 @@ void MessagesManager::on_get_message_link_message(MessageLinkInfo &&info, Dialog
});
td_->create_handler<GetDiscussionMessageQuery>(std::move(query_promise))
->send(dialog_id, info.message_id, m->reply_info.channel_id, MessageId());
->send(dialog_id, info.message_id, DialogId(m->reply_info.channel_id), MessageId());
}
void MessagesManager::on_get_message_link_discussion_message(MessageLinkInfo &&info, DialogId comment_dialog_id,
@ -19826,8 +19735,7 @@ std::pair<DialogId, vector<MessageId>> MessagesManager::get_message_thread_histo
return {};
}
DialogId message_thread_dialog_id;
MessageId top_thread_message_id;
FullMessageId top_thread_full_message_id;
{
Message *m = get_message_force(d, message_id, "get_message_thread_history 1");
if (m == nullptr) {
@ -19835,35 +19743,27 @@ std::pair<DialogId, vector<MessageId>> MessagesManager::get_message_thread_histo
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;
auto r_top_thread_full_message_id = get_top_thread_full_message_id(dialog_id, m);
if (r_top_thread_full_message_id.is_error()) {
promise.set_error(r_top_thread_full_message_id.move_as_error());
return {};
}
top_thread_full_message_id = r_top_thread_full_message_id.move_as_ok();
if (!top_thread_full_message_id.get_message_id().is_valid()) {
CHECK(m->reply_info.is_comment);
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 {};
}
}
CHECK(top_thread_message_id.is_valid());
if (random_id != 0) {
// request has already been sent before
@ -19880,12 +19780,12 @@ std::pair<DialogId, vector<MessageId>> MessagesManager::get_message_thread_histo
d = get_dialog(dialog_id);
CHECK(d != nullptr);
}
if (dialog_id != message_thread_dialog_id) {
if (dialog_id != top_thread_full_message_id.get_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);
auto yet_unsent_it = d->yet_unsent_thread_message_ids.find(top_thread_full_message_id.get_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),
@ -19896,7 +19796,7 @@ std::pair<DialogId, vector<MessageId>> MessagesManager::get_message_thread_histo
result = std::move(new_result);
}
Message *top_m = get_message_force(d, top_thread_message_id, "get_message_thread_history 2");
Message *top_m = get_message_force(d, top_thread_full_message_id.get_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;
@ -21798,9 +21698,7 @@ 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_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_message_thread = for_event_log || is_scheduled ? false
: is_visible_message_reply_info(dialog_id, m) ||
m->top_thread_message_id.is_valid();
bool can_get_message_thread = for_event_log ? false : get_top_thread_full_message_id(dialog_id, m).is_ok();
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 reply_to_message_id = for_event_log ? static_cast<int64>(0) : m->reply_to_message_id.get();
@ -27314,18 +27212,18 @@ void MessagesManager::send_update_chat_has_scheduled_messages(Dialog *d, bool fr
}
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) {
DialogAction 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)));
LOG(DEBUG) << "Send " << action << " of " << user_id << " in thread of " << top_thread_message_id << " in "
<< dialog_id;
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"),
action.get_chat_action_object()));
}
void MessagesManager::on_send_message_get_quick_ack(int64 random_id) {
@ -28959,58 +28857,8 @@ bool MessagesManager::is_dialog_action_unneeded(DialogId dialog_id) const {
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,
const tl_object_ptr<td_api::ChatAction> &action, Promise<Unit> &&promise) {
if (action == nullptr) {
return promise.set_error(Status::Error(5, "Action must be non-empty"));
}
void MessagesManager::send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogAction action,
Promise<Unit> &&promise) {
if (!have_dialog_force(dialog_id)) {
return promise.set_error(Status::Error(5, "Chat not found"));
}
@ -29032,117 +28880,19 @@ void MessagesManager::send_dialog_action(DialogId dialog_id, MessageId top_threa
}
if (dialog_id.get_type() == DialogType::SecretChat) {
tl_object_ptr<secret_api::SendMessageAction> send_action;
switch (action->get_id()) {
case td_api::chatActionCancel::ID:
send_action = make_tl_object<secret_api::sendMessageCancelAction>();
break;
case td_api::chatActionTyping::ID:
send_action = make_tl_object<secret_api::sendMessageTypingAction>();
break;
case td_api::chatActionRecordingVideo::ID:
send_action = make_tl_object<secret_api::sendMessageRecordVideoAction>();
break;
case td_api::chatActionUploadingVideo::ID:
send_action = make_tl_object<secret_api::sendMessageUploadVideoAction>();
break;
case td_api::chatActionRecordingVoiceNote::ID:
send_action = make_tl_object<secret_api::sendMessageRecordAudioAction>();
break;
case td_api::chatActionUploadingVoiceNote::ID:
send_action = make_tl_object<secret_api::sendMessageUploadAudioAction>();
break;
case td_api::chatActionUploadingPhoto::ID:
send_action = make_tl_object<secret_api::sendMessageUploadPhotoAction>();
break;
case td_api::chatActionUploadingDocument::ID:
send_action = make_tl_object<secret_api::sendMessageUploadDocumentAction>();
break;
case td_api::chatActionChoosingLocation::ID:
send_action = make_tl_object<secret_api::sendMessageGeoLocationAction>();
break;
case td_api::chatActionChoosingContact::ID:
send_action = make_tl_object<secret_api::sendMessageChooseContactAction>();
break;
case td_api::chatActionRecordingVideoNote::ID:
send_action = make_tl_object<secret_api::sendMessageRecordRoundAction>();
break;
case td_api::chatActionUploadingVideoNote::ID:
send_action = make_tl_object<secret_api::sendMessageUploadRoundAction>();
break;
case td_api::chatActionStartPlayingGame::ID:
return promise.set_error(Status::Error(5, "Games are unsupported in secret chats"));
default:
UNREACHABLE();
}
send_closure(G()->secret_chats_manager(), &SecretChatsManager::send_message_action, dialog_id.get_secret_chat_id(),
std::move(send_action));
action.get_secret_input_send_message_action());
promise.set_value(Unit());
return;
}
tl_object_ptr<telegram_api::SendMessageAction> send_action;
switch (action->get_id()) {
case td_api::chatActionCancel::ID:
send_action = make_tl_object<telegram_api::sendMessageCancelAction>();
break;
case td_api::chatActionTyping::ID:
send_action = make_tl_object<telegram_api::sendMessageTypingAction>();
break;
case td_api::chatActionRecordingVideo::ID:
send_action = make_tl_object<telegram_api::sendMessageRecordVideoAction>();
break;
case td_api::chatActionUploadingVideo::ID: {
auto progress = static_cast<const td_api::chatActionUploadingVideo &>(*action).progress_;
send_action = make_tl_object<telegram_api::sendMessageUploadVideoAction>(progress);
break;
}
case td_api::chatActionRecordingVoiceNote::ID:
send_action = make_tl_object<telegram_api::sendMessageRecordAudioAction>();
break;
case td_api::chatActionUploadingVoiceNote::ID: {
auto progress = static_cast<const td_api::chatActionUploadingVoiceNote &>(*action).progress_;
send_action = make_tl_object<telegram_api::sendMessageUploadAudioAction>(progress);
break;
}
case td_api::chatActionUploadingPhoto::ID: {
auto progress = static_cast<const td_api::chatActionUploadingPhoto &>(*action).progress_;
send_action = make_tl_object<telegram_api::sendMessageUploadPhotoAction>(progress);
break;
}
case td_api::chatActionUploadingDocument::ID: {
auto progress = static_cast<const td_api::chatActionUploadingDocument &>(*action).progress_;
send_action = make_tl_object<telegram_api::sendMessageUploadDocumentAction>(progress);
break;
}
case td_api::chatActionChoosingLocation::ID:
send_action = make_tl_object<telegram_api::sendMessageGeoLocationAction>();
break;
case td_api::chatActionChoosingContact::ID:
send_action = make_tl_object<telegram_api::sendMessageChooseContactAction>();
break;
case td_api::chatActionStartPlayingGame::ID:
send_action = make_tl_object<telegram_api::sendMessageGamePlayAction>();
break;
case td_api::chatActionRecordingVideoNote::ID:
send_action = make_tl_object<telegram_api::sendMessageRecordRoundAction>();
break;
case td_api::chatActionUploadingVideoNote::ID: {
auto progress = static_cast<const td_api::chatActionUploadingVideoNote &>(*action).progress_;
send_action = make_tl_object<telegram_api::sendMessageUploadRoundAction>(progress);
break;
}
default:
UNREACHABLE();
}
auto &query_ref = set_typing_query_[dialog_id];
if (!query_ref.empty() && !td_->auth_manager_->is_bot()) {
LOG(INFO) << "Cancel previous set typing query";
cancel_query(query_ref);
}
query_ref = td_->create_handler<SetTypingQuery>(std::move(promise))
->send(dialog_id, top_thread_message_id, std::move(send_action));
->send(dialog_id, top_thread_message_id, action.get_input_send_message_action());
}
void MessagesManager::on_send_dialog_action_timeout(DialogId dialog_id) {
@ -29194,31 +28944,12 @@ void MessagesManager::on_send_dialog_action_timeout(DialogId dialog_id) {
progress = static_cast<int32>(100 * uploaded_size / total_size);
}
td_api::object_ptr<td_api::ChatAction> action;
switch (m->content->get_type()) {
case MessageContentType::Animation:
case MessageContentType::Audio:
case MessageContentType::Document:
action = td_api::make_object<td_api::chatActionUploadingDocument>(progress);
break;
case MessageContentType::Photo:
action = td_api::make_object<td_api::chatActionUploadingPhoto>(progress);
break;
case MessageContentType::Video:
action = td_api::make_object<td_api::chatActionUploadingVideo>(progress);
break;
case MessageContentType::VideoNote:
action = td_api::make_object<td_api::chatActionUploadingVideoNote>(progress);
break;
case MessageContentType::VoiceNote:
action = td_api::make_object<td_api::chatActionUploadingVoiceNote>(progress);
break;
default:
return;
DialogAction action = DialogAction::get_uploading_action(m->content->get_type(), progress);
if (action == DialogAction()) {
return;
}
CHECK(action != nullptr);
LOG(INFO) << "Send action in " << dialog_id << ": " << to_string(action);
send_dialog_action(dialog_id, m->top_thread_message_id, std::move(action), Auto());
LOG(INFO) << "Send " << action << " in " << dialog_id;
send_dialog_action(dialog_id, m->top_thread_message_id, std::move(action), Promise<Unit>());
}
void MessagesManager::on_active_dialog_action_timeout(DialogId dialog_id) {
@ -29232,7 +28963,7 @@ void MessagesManager::on_active_dialog_action_timeout(DialogId dialog_id) {
auto now = Time::now();
while (actions_it->second[0].start_time + DIALOG_ACTION_TIMEOUT < now + 0.1) {
on_user_dialog_action(dialog_id, actions_it->second[0].top_thread_message_id, actions_it->second[0].user_id,
nullptr, 0);
DialogAction(), 0);
actions_it = active_dialog_actions_.find(dialog_id);
if (actions_it == active_dialog_actions_.end()) {
@ -29252,7 +28983,7 @@ void MessagesManager::clear_active_dialog_actions(DialogId dialog_id) {
while (actions_it != active_dialog_actions_.end()) {
CHECK(!actions_it->second.empty());
on_user_dialog_action(dialog_id, actions_it->second[0].top_thread_message_id, actions_it->second[0].user_id,
nullptr, 0);
DialogAction(), 0);
actions_it = active_dialog_actions_.find(dialog_id);
}
}

View File

@ -9,6 +9,7 @@
#include "td/telegram/AccessRights.h"
#include "td/telegram/ChannelId.h"
#include "td/telegram/Dependencies.h"
#include "td/telegram/DialogAction.h"
#include "td/telegram/DialogAdministrator.h"
#include "td/telegram/DialogDate.h"
#include "td/telegram/DialogDb.h"
@ -367,9 +368,8 @@ class MessagesManager : public Actor {
void on_update_delete_scheduled_messages(DialogId dialog_id, vector<ScheduledServerMessageId> &&server_message_ids);
void on_user_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, UserId user_id,
tl_object_ptr<td_api::ChatAction> &&action, int32 date,
MessageContentType message_content_type = MessageContentType::None);
void on_user_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, UserId user_id, DialogAction action,
int32 date, MessageContentType message_content_type = MessageContentType::None);
void read_history_inbox(DialogId dialog_id, MessageId max_message_id, int32 unread_count, const char *source);
@ -478,8 +478,8 @@ class MessagesManager : public Actor {
tl_object_ptr<td_api::gameHighScores> get_game_high_scores_object(int64 random_id);
void send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id,
const tl_object_ptr<td_api::ChatAction> &action, Promise<Unit> &&promise);
void send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogAction action,
Promise<Unit> &&promise);
vector<DialogListId> get_dialog_lists_to_add_dialog(DialogId dialog_id);
@ -1937,6 +1937,8 @@ class MessagesManager : public Actor {
bool is_visible_message_reply_info(DialogId dialog_id, const Message *m) const;
Result<FullMessageId> get_top_thread_full_message_id(DialogId dialog_id, const Message *m) const;
td_api::object_ptr<td_api::messageInteractionInfo> get_message_interaction_info_object(DialogId dialog_id,
const Message *m) const;
@ -2216,7 +2218,7 @@ class MessagesManager : public Actor {
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);
DialogAction action);
void repair_dialog_action_bar(Dialog *d, const char *source);
@ -2353,8 +2355,6 @@ class MessagesManager : public Actor {
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;
void on_send_dialog_action_timeout(DialogId dialog_id);
@ -2363,8 +2363,6 @@ class MessagesManager : public Actor {
void clear_active_dialog_actions(DialogId dialog_id);
static bool need_cancel_user_dialog_action(int32 action_id, MessageContentType message_content_type);
void cancel_user_dialog_action(DialogId dialog_id, const Message *m);
Dialog *get_dialog_by_message_id(MessageId message_id);
@ -3102,12 +3100,11 @@ class MessagesManager : public Actor {
struct ActiveDialogAction {
MessageId top_thread_message_id;
UserId user_id;
int32 action_id;
int32 progress;
DialogAction action;
double start_time;
ActiveDialogAction(MessageId top_thread_message_id, UserId user_id, int32 action_id, double start_time)
: top_thread_message_id(top_thread_message_id), user_id(user_id), action_id(action_id), start_time(start_time) {
ActiveDialogAction(MessageId top_thread_message_id, UserId user_id, DialogAction action, double start_time)
: top_thread_message_id(top_thread_message_id), user_id(user_id), action(action), start_time(start_time) {
}
};

View File

@ -5904,12 +5904,14 @@ vector<string> StickersManager::get_emoji_language_codes(const vector<string> &i
Promise<Unit> &promise) {
vector<string> language_codes = td_->language_pack_manager_->get_actor_unsafe()->get_used_language_codes();
auto system_language_code = G()->mtproto_header().get_system_language_code();
if (!system_language_code.empty() && system_language_code.find('$') == string::npos) {
language_codes.push_back(system_language_code);
if (system_language_code.size() >= 2 && system_language_code.find('$') == string::npos &&
(system_language_code.size() == 2 || system_language_code[2] == '-')) {
language_codes.push_back(system_language_code.substr(0, 2));
}
for (auto &input_language_code : input_language_codes) {
if (!input_language_code.empty() && input_language_code.find('$') == string::npos) {
language_codes.push_back(input_language_code);
if (input_language_code.size() >= 2 && input_language_code.find('$') == string::npos &&
(input_language_code.size() == 2 || input_language_code[2] == '-')) {
language_codes.push_back(input_language_code.substr(0, 2));
}
}
if (!text.empty()) {
@ -5929,7 +5931,7 @@ vector<string> StickersManager::get_emoji_language_codes(const vector<string> &i
}
if (language_codes.empty()) {
LOG(ERROR) << "List of language codes is empty";
LOG(INFO) << "List of language codes is empty";
language_codes.push_back("en");
}
std::sort(language_codes.begin(), language_codes.end());
@ -5944,6 +5946,7 @@ vector<string> StickersManager::get_emoji_language_codes(const vector<string> &i
if (it->second.empty()) {
load_language_codes(std::move(language_codes), std::move(key), std::move(promise));
} else {
LOG(DEBUG) << "Have emoji language codes " << it->second;
double now = Time::now_cached();
for (auto &language_code : it->second) {
double last_difference_time = get_emoji_language_code_last_difference_time(language_code);

View File

@ -24,6 +24,7 @@
#include "td/telegram/ContactsManager.h"
#include "td/telegram/CountryInfoManager.h"
#include "td/telegram/DeviceTokenManager.h"
#include "td/telegram/DialogAction.h"
#include "td/telegram/DialogAdministrator.h"
#include "td/telegram/DialogFilter.h"
#include "td/telegram/DialogFilterId.h"
@ -5843,7 +5844,7 @@ void Td::on_request(uint64 id, const td_api::deleteChatReplyMarkup &request) {
void Td::on_request(uint64 id, td_api::sendChatAction &request) {
CREATE_OK_REQUEST_PROMISE();
messages_manager_->send_dialog_action(DialogId(request.chat_id_), MessageId(request.message_thread_id_),
std::move(request.action_), std::move(promise));
DialogAction(std::move(request.action_)), std::move(promise));
}
void Td::on_request(uint64 id, td_api::sendChatScreenshotTakenNotification &request) {

View File

@ -16,6 +16,7 @@
#include "td/telegram/ChatId.h"
#include "td/telegram/ConfigManager.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/DialogAction.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/FolderId.h"
#include "td/telegram/Global.h"
@ -1829,55 +1830,6 @@ int32 UpdatesManager::get_short_update_date() const {
return now;
}
tl_object_ptr<td_api::ChatAction> UpdatesManager::convert_send_message_action(
tl_object_ptr<telegram_api::SendMessageAction> action) {
auto fix_progress = [](int32 progress) {
return progress <= 0 || progress > 100 ? 0 : progress;
};
switch (action->get_id()) {
case telegram_api::sendMessageCancelAction::ID:
return make_tl_object<td_api::chatActionCancel>();
case telegram_api::sendMessageTypingAction::ID:
return make_tl_object<td_api::chatActionTyping>();
case telegram_api::sendMessageRecordVideoAction::ID:
return make_tl_object<td_api::chatActionRecordingVideo>();
case telegram_api::sendMessageUploadVideoAction::ID: {
auto upload_video_action = move_tl_object_as<telegram_api::sendMessageUploadVideoAction>(action);
return make_tl_object<td_api::chatActionUploadingVideo>(fix_progress(upload_video_action->progress_));
}
case telegram_api::sendMessageRecordAudioAction::ID:
return make_tl_object<td_api::chatActionRecordingVoiceNote>();
case telegram_api::sendMessageUploadAudioAction::ID: {
auto upload_audio_action = move_tl_object_as<telegram_api::sendMessageUploadAudioAction>(action);
return make_tl_object<td_api::chatActionUploadingVoiceNote>(fix_progress(upload_audio_action->progress_));
}
case telegram_api::sendMessageUploadPhotoAction::ID: {
auto upload_photo_action = move_tl_object_as<telegram_api::sendMessageUploadPhotoAction>(action);
return make_tl_object<td_api::chatActionUploadingPhoto>(fix_progress(upload_photo_action->progress_));
}
case telegram_api::sendMessageUploadDocumentAction::ID: {
auto upload_document_action = move_tl_object_as<telegram_api::sendMessageUploadDocumentAction>(action);
return make_tl_object<td_api::chatActionUploadingDocument>(fix_progress(upload_document_action->progress_));
}
case telegram_api::sendMessageGeoLocationAction::ID:
return make_tl_object<td_api::chatActionChoosingLocation>();
case telegram_api::sendMessageChooseContactAction::ID:
return make_tl_object<td_api::chatActionChoosingContact>();
case telegram_api::sendMessageGamePlayAction::ID:
return make_tl_object<td_api::chatActionStartPlayingGame>();
case telegram_api::sendMessageRecordRoundAction::ID:
return make_tl_object<td_api::chatActionRecordingVideoNote>();
case telegram_api::sendMessageUploadRoundAction::ID: {
auto upload_round_action = move_tl_object_as<telegram_api::sendMessageUploadRoundAction>(action);
return make_tl_object<td_api::chatActionUploadingVideoNote>(fix_progress(upload_round_action->progress_));
}
default:
UNREACHABLE();
return make_tl_object<td_api::chatActionTyping>();
}
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateUserTyping> update, bool /*force_apply*/) {
UserId user_id(update->user_id_);
if (!td_->contacts_manager_->have_min_user(user_id)) {
@ -1890,8 +1842,7 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateUserTyping> upd
return;
}
td_->messages_manager_->on_user_dialog_action(dialog_id, MessageId(), user_id,
convert_send_message_action(std::move(update->action_)),
get_short_update_date());
DialogAction(std::move(update->action_)), get_short_update_date());
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChatUserTyping> update, bool /*force_apply*/) {
@ -1906,8 +1857,7 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChatUserTyping>
return;
}
td_->messages_manager_->on_user_dialog_action(dialog_id, MessageId(), user_id,
convert_send_message_action(std::move(update->action_)),
get_short_update_date());
DialogAction(std::move(update->action_)), get_short_update_date());
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChannelUserTyping> update, bool /*force_apply*/) {
@ -1930,8 +1880,7 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChannelUserTypi
}
}
td_->messages_manager_->on_user_dialog_action(dialog_id, top_thread_message_id, user_id,
convert_send_message_action(std::move(update->action_)),
get_short_update_date());
DialogAction(std::move(update->action_)), get_short_update_date());
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateEncryptedChatTyping> update, bool /*force_apply*/) {
@ -1950,7 +1899,7 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateEncryptedChatTy
}
td_->messages_manager_->on_user_dialog_action(dialog_id, MessageId(), user_id,
make_tl_object<td_api::chatActionTyping>(), get_short_update_date());
DialogAction(DialogAction::Type::Typing, 0), get_short_update_date());
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateUserStatus> update, bool /*force_apply*/) {

View File

@ -136,9 +136,6 @@ class UpdatesManager : public Actor {
int32 get_short_update_date() const;
static tl_object_ptr<td_api::ChatAction> convert_send_message_action(
tl_object_ptr<telegram_api::SendMessageAction> action);
void process_get_difference_updates(vector<tl_object_ptr<telegram_api::Message>> &&new_messages,
vector<tl_object_ptr<telegram_api::EncryptedMessage>> &&new_encrypted_messages,
vector<tl_object_ptr<telegram_api::Update>> &&other_updates);