diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 889e698b9..ca7f129b6 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -8178,8 +8178,12 @@ getInlineGameHighScores inline_message_id:string user_id:int53 = GameHighScores; deleteChatReplyMarkup chat_id:int53 message_id:int53 = Ok; -//@description Sends a notification about user activity in a chat @chat_id Chat identifier @message_thread_id If not 0, the message thread identifier in which the action was performed @action The action description; pass null to cancel the currently active action -sendChatAction chat_id:int53 message_thread_id:int53 action:ChatAction = Ok; +//@description Sends a notification about user activity in a chat +//@chat_id Chat identifier +//@message_thread_id If not 0, the message thread identifier in which the action was performed +//@business_connection_id Unique identifier of business connection on behalf of which to send the request; for bots only +//@action The action description; pass null to cancel the currently active action +sendChatAction chat_id:int53 message_thread_id:int53 business_connection_id:string action:ChatAction = Ok; //@description Informs TDLib that the chat is opened by the user. Many useful activities depend on the chat being opened or closed (e.g., in supergroups and channels all updates are received only for opened chats) @chat_id Chat identifier diff --git a/td/telegram/BusinessConnectionId.h b/td/telegram/BusinessConnectionId.h index a0ee0095b..fea7b94e4 100644 --- a/td/telegram/BusinessConnectionId.h +++ b/td/telegram/BusinessConnectionId.h @@ -6,6 +6,8 @@ // #pragma once +#include "td/telegram/telegram_api.h" + #include "td/utils/common.h" #include "td/utils/HashTableUtils.h" #include "td/utils/StringBuilder.h" @@ -18,10 +20,12 @@ class BusinessConnectionId { public: BusinessConnectionId() = default; - explicit BusinessConnectionId(string &&business_connection_id) : business_connection_id_(std::move(business_connection_id)) { + explicit BusinessConnectionId(string &&business_connection_id) + : business_connection_id_(std::move(business_connection_id)) { } - explicit BusinessConnectionId(const string &business_connection_id) : business_connection_id_(business_connection_id) { + explicit BusinessConnectionId(const string &business_connection_id) + : business_connection_id_(business_connection_id) { } bool is_empty() const { @@ -44,6 +48,13 @@ class BusinessConnectionId { return business_connection_id_ != other.business_connection_id_; } + telegram_api::object_ptr get_invoke_prefix() const { + if (is_empty()) { + return nullptr; + } + return telegram_api::make_object(business_connection_id_); + } + template void store(StorerT &storer) const { storer.store_string(business_connection_id_); diff --git a/td/telegram/BusinessConnectionManager.cpp b/td/telegram/BusinessConnectionManager.cpp index 8d7711934..119cd6aa8 100644 --- a/td/telegram/BusinessConnectionManager.cpp +++ b/td/telegram/BusinessConnectionManager.cpp @@ -9,7 +9,6 @@ #include "td/telegram/AuthManager.h" #include "td/telegram/ContactsManager.h" #include "td/telegram/Global.h" -#include "td/telegram/net/DcId.h" #include "td/telegram/Td.h" #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" @@ -110,6 +109,15 @@ Status BusinessConnectionManager::check_business_connection(const BusinessConnec return Status::OK(); } +DcId BusinessConnectionManager::get_business_connection_dc_id(const BusinessConnectionId &connection_id) const { + if (connection_id.is_empty()) { + return DcId::main(); + } + auto connection = business_connections_.get_pointer(connection_id); + CHECK(connection != nullptr); + return connection->dc_id_; +} + void BusinessConnectionManager::on_update_bot_business_connect( telegram_api::object_ptr &&connection) { CHECK(connection != nullptr); diff --git a/td/telegram/BusinessConnectionManager.h b/td/telegram/BusinessConnectionManager.h index 4ddf26b32..7468516ee 100644 --- a/td/telegram/BusinessConnectionManager.h +++ b/td/telegram/BusinessConnectionManager.h @@ -8,6 +8,7 @@ #include "td/telegram/BusinessConnectionId.h" #include "td/telegram/DialogId.h" +#include "td/telegram/net/DcId.h" #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" @@ -33,6 +34,8 @@ class BusinessConnectionManager final : public Actor { Status check_business_connection(const BusinessConnectionId &connection_id, DialogId dialog_id) const; + DcId get_business_connection_dc_id(const BusinessConnectionId &connection_id) const; + void on_update_bot_business_connect(telegram_api::object_ptr &&connection); void get_business_connection(const BusinessConnectionId &connection_id, diff --git a/td/telegram/DialogActionManager.cpp b/td/telegram/DialogActionManager.cpp index fa07adc94..052def159 100644 --- a/td/telegram/DialogActionManager.cpp +++ b/td/telegram/DialogActionManager.cpp @@ -8,6 +8,7 @@ #include "td/telegram/AccessRights.h" #include "td/telegram/AuthManager.h" +#include "td/telegram/BusinessConnectionManager.h" #include "td/telegram/ContactsManager.h" #include "td/telegram/DialogManager.h" #include "td/telegram/Global.h" @@ -34,6 +35,7 @@ namespace td { class SetTypingQuery final : public Td::ResultHandler { Promise promise_; DialogId dialog_id_; + BusinessConnectionId business_connection_id_; int32 generation_ = 0; public: @@ -41,16 +43,22 @@ class SetTypingQuery final : public Td::ResultHandler { } NetQueryRef send(DialogId dialog_id, tl_object_ptr &&input_peer, - MessageId top_thread_message_id, tl_object_ptr &&action) { + MessageId top_thread_message_id, BusinessConnectionId business_connection_id, + tl_object_ptr &&action) { dialog_id_ = dialog_id; + business_connection_id_ = business_connection_id; CHECK(input_peer != nullptr); int32 flags = 0; if (top_thread_message_id.is_valid()) { flags |= telegram_api::messages_setTyping::TOP_MSG_ID_MASK; } - auto query = G()->net_query_creator().create(telegram_api::messages_setTyping( - flags, std::move(input_peer), top_thread_message_id.get_server_message_id().get(), std::move(action))); + + auto query = G()->net_query_creator().create_with_prefix( + business_connection_id.get_invoke_prefix(), + telegram_api::messages_setTyping(flags, std::move(input_peer), + top_thread_message_id.get_server_message_id().get(), std::move(action)), + td_->business_connection_manager_->get_business_connection_dc_id(business_connection_id)); query->total_timeout_limit_ = 2; auto result = query.get_weak(); generation_ = result.generation(); @@ -76,7 +84,8 @@ class SetTypingQuery final : public Td::ResultHandler { return promise_.set_value(Unit()); } - if (!td_->dialog_manager_->on_get_dialog_error(dialog_id_, status, "SetTypingQuery")) { + if (!business_connection_id_.is_valid() && + !td_->dialog_manager_->on_get_dialog_error(dialog_id_, status, "SetTypingQuery")) { LOG(INFO) << "Receive error for set typing: " << status; } promise_.set_error(std::move(status)); @@ -284,9 +293,13 @@ void DialogActionManager::send_update_chat_action(DialogId dialog_id, MessageId action.get_chat_action_object())); } -void DialogActionManager::send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogAction action, +void DialogActionManager::send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, + BusinessConnectionId business_connection_id, DialogAction action, Promise &&promise) { - if (!td_->dialog_manager_->have_dialog_force(dialog_id, "send_dialog_action")) { + TRY_STATUS_PROMISE(promise, + td_->business_connection_manager_->check_business_connection(business_connection_id, dialog_id)); + bool as_business = business_connection_id.is_valid(); + if (!as_business && !td_->dialog_manager_->have_dialog_force(dialog_id, "send_dialog_action")) { return promise.set_error(Status::Error(400, "Chat not found")); } if (top_thread_message_id != MessageId() && @@ -294,16 +307,21 @@ void DialogActionManager::send_dialog_action(DialogId dialog_id, MessageId top_t return promise.set_error(Status::Error(400, "Invalid message thread specified")); } - if (td_->dialog_manager_->is_forum_channel(dialog_id) && !top_thread_message_id.is_valid()) { + if (!as_business && td_->dialog_manager_->is_forum_channel(dialog_id) && !top_thread_message_id.is_valid()) { top_thread_message_id = MessageId(ServerMessageId(1)); } tl_object_ptr input_peer; if (action == DialogAction::get_speaking_action()) { + if (as_business) { + return promise.set_error(Status::Error(400, "Can't use the action")); + } input_peer = td_->dialog_manager_->get_input_peer(dialog_id, AccessRights::Read); if (input_peer == nullptr) { return promise.set_error(Status::Error(400, "Have no access to the chat")); } + } else if (as_business) { + input_peer = td_->dialog_manager_->get_input_peer_force(dialog_id); } else { if (!td_->dialog_manager_->have_input_peer(dialog_id, AccessRights::Write)) { if (td_->auth_manager_->is_bot()) { @@ -321,6 +339,7 @@ void DialogActionManager::send_dialog_action(DialogId dialog_id, MessageId top_t } if (dialog_id.get_type() == DialogType::SecretChat) { + CHECK(!as_business); send_closure(G()->secret_chats_manager(), &SecretChatsManager::send_message_action, dialog_id.get_secret_chat_id(), action.get_secret_input_send_message_action()); promise.set_value(Unit()); @@ -329,9 +348,9 @@ void DialogActionManager::send_dialog_action(DialogId dialog_id, MessageId top_t CHECK(input_peer != nullptr); - auto new_query_ref = - td_->create_handler(std::move(promise)) - ->send(dialog_id, std::move(input_peer), top_thread_message_id, action.get_input_send_message_action()); + auto new_query_ref = td_->create_handler(std::move(promise)) + ->send(dialog_id, std::move(input_peer), top_thread_message_id, business_connection_id, + action.get_input_send_message_action()); if (td_->auth_manager_->is_bot()) { return; } diff --git a/td/telegram/DialogActionManager.h b/td/telegram/DialogActionManager.h index 3cd87a6cf..ecebf59b8 100644 --- a/td/telegram/DialogActionManager.h +++ b/td/telegram/DialogActionManager.h @@ -6,6 +6,7 @@ // #pragma once +#include "td/telegram/BusinessConnectionId.h" #include "td/telegram/DialogAction.h" #include "td/telegram/DialogId.h" #include "td/telegram/MessageContentType.h" @@ -31,8 +32,8 @@ class DialogActionManager final : public Actor { DialogAction action, int32 date, MessageContentType message_content_type = MessageContentType::None); - void send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogAction action, - Promise &&promise); + void send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, + BusinessConnectionId business_connection_id, DialogAction action, Promise &&promise); void cancel_send_dialog_action_queries(DialogId dialog_id); diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index b60236ae5..cf5b93dc8 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -1101,7 +1101,7 @@ void GroupCallManager::on_send_speaking_action_timeout(GroupCallId group_call_id pending_send_speaking_action_timeout_.add_timeout_in(group_call_id.get(), 4.0); - td_->dialog_action_manager_->send_dialog_action(group_call->dialog_id, MessageId(), + td_->dialog_action_manager_->send_dialog_action(group_call->dialog_id, MessageId(), {}, DialogAction::get_speaking_action(), Promise()); } diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index a45f231c4..8f2ca473b 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -31163,7 +31163,7 @@ void MessagesManager::on_send_dialog_action_timeout(DialogId dialog_id) { return; } LOG(INFO) << "Send " << action << " in " << dialog_id; - td_->dialog_action_manager_->send_dialog_action(dialog_id, m->top_thread_message_id, std::move(action), + td_->dialog_action_manager_->send_dialog_action(dialog_id, m->top_thread_message_id, {}, std::move(action), Promise()); } diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 9b19141de..9abcd152e 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6008,8 +6008,10 @@ void Td::on_request(uint64 id, const td_api::deleteChatReplyMarkup &request) { } void Td::on_request(uint64 id, td_api::sendChatAction &request) { + CLEAN_INPUT_STRING(request.business_connection_id_); CREATE_OK_REQUEST_PROMISE(); dialog_action_manager_->send_dialog_action(DialogId(request.chat_id_), MessageId(request.message_thread_id_), + BusinessConnectionId(std::move(request.business_connection_id_)), DialogAction(std::move(request.action_)), std::move(promise)); } diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 075b79d2b..803ad8d8d 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4651,7 +4651,8 @@ class CliClient final : public Actor { ChatId chat_id; string action; get_args(args, chat_id, action); - send_request(td_api::make_object(chat_id, message_thread_id_, as_chat_action(action))); + send_request( + td_api::make_object(chat_id, message_thread_id_, string(), as_chat_action(action))); } else if (op == "smt" || op == "smtp" || op == "smtf" || op == "smtpf") { ChatId chat_id; get_args(args, chat_id); diff --git a/td/telegram/net/NetQueryCreator.cpp b/td/telegram/net/NetQueryCreator.cpp index 2b78d699a..b0340cf82 100644 --- a/td/telegram/net/NetQueryCreator.cpp +++ b/td/telegram/net/NetQueryCreator.cpp @@ -32,13 +32,13 @@ NetQueryPtr NetQueryCreator::create(const telegram_api::Function &function, vect return create(UniqueId::next(), nullptr, function, std::move(chain_ids), dc_id, type, NetQuery::AuthFlag::On); } -NetQueryPtr NetQueryCreator::create_with_prefix(const unique_ptr &prefix, +NetQueryPtr NetQueryCreator::create_with_prefix(const telegram_api::object_ptr &prefix, const telegram_api::Function &function, DcId dc_id, - NetQuery::Type type) { - return create(UniqueId::next(), prefix, function, {}, dc_id, type, NetQuery::AuthFlag::On); + vector chain_ids, NetQuery::Type type) { + return create(UniqueId::next(), prefix, function, std::move(chain_ids), dc_id, type, NetQuery::AuthFlag::On); } -NetQueryPtr NetQueryCreator::create(uint64 id, const unique_ptr &prefix, +NetQueryPtr NetQueryCreator::create(uint64 id, const telegram_api::object_ptr &prefix, const telegram_api::Function &function, vector &&chain_ids, DcId dc_id, NetQuery::Type type, NetQuery::AuthFlag auth_flag) { LOG(INFO) << "Create query " << to_string(function); diff --git a/td/telegram/net/NetQueryCreator.h b/td/telegram/net/NetQueryCreator.h index da2a9a912..d2e774be6 100644 --- a/td/telegram/net/NetQueryCreator.h +++ b/td/telegram/net/NetQueryCreator.h @@ -38,11 +38,11 @@ class NetQueryCreator { return create(UniqueId::next(), nullptr, function, {}, dc_id, NetQuery::Type::Common, NetQuery::AuthFlag::Off); } - NetQueryPtr create_with_prefix(const unique_ptr &prefix, - const telegram_api::Function &function, DcId dc_id, + NetQueryPtr create_with_prefix(const telegram_api::object_ptr &prefix, + const telegram_api::Function &function, DcId dc_id, vector chain_ids = {}, NetQuery::Type type = NetQuery::Type::Common); - NetQueryPtr create(uint64 id, const unique_ptr &prefix, + NetQueryPtr create(uint64 id, const telegram_api::object_ptr &prefix, const telegram_api::Function &function, vector &&chain_ids, DcId dc_id, NetQuery::Type type, NetQuery::AuthFlag auth_flag);