Support sendChatAction for business connections.

This commit is contained in:
levlam 2024-03-07 23:05:58 +03:00
parent c2130b3d3b
commit e6b9f2eb07
12 changed files with 76 additions and 27 deletions

View File

@ -8178,8 +8178,12 @@ getInlineGameHighScores inline_message_id:string user_id:int53 = GameHighScores;
deleteChatReplyMarkup chat_id:int53 message_id:int53 = Ok; 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 //@description Sends a notification about user activity in a chat
sendChatAction chat_id:int53 message_thread_id:int53 action:ChatAction = Ok; //@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 //@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

View File

@ -6,6 +6,8 @@
// //
#pragma once #pragma once
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/HashTableUtils.h" #include "td/utils/HashTableUtils.h"
#include "td/utils/StringBuilder.h" #include "td/utils/StringBuilder.h"
@ -18,10 +20,12 @@ class BusinessConnectionId {
public: public:
BusinessConnectionId() = default; 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 { bool is_empty() const {
@ -44,6 +48,13 @@ class BusinessConnectionId {
return business_connection_id_ != other.business_connection_id_; return business_connection_id_ != other.business_connection_id_;
} }
telegram_api::object_ptr<telegram_api::Function> get_invoke_prefix() const {
if (is_empty()) {
return nullptr;
}
return telegram_api::make_object<telegram_api::invokeWithBusinessConnectionPrefix>(business_connection_id_);
}
template <class StorerT> template <class StorerT>
void store(StorerT &storer) const { void store(StorerT &storer) const {
storer.store_string(business_connection_id_); storer.store_string(business_connection_id_);

View File

@ -9,7 +9,6 @@
#include "td/telegram/AuthManager.h" #include "td/telegram/AuthManager.h"
#include "td/telegram/ContactsManager.h" #include "td/telegram/ContactsManager.h"
#include "td/telegram/Global.h" #include "td/telegram/Global.h"
#include "td/telegram/net/DcId.h"
#include "td/telegram/Td.h" #include "td/telegram/Td.h"
#include "td/telegram/td_api.h" #include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h" #include "td/telegram/telegram_api.h"
@ -110,6 +109,15 @@ Status BusinessConnectionManager::check_business_connection(const BusinessConnec
return Status::OK(); 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( void BusinessConnectionManager::on_update_bot_business_connect(
telegram_api::object_ptr<telegram_api::botBusinessConnection> &&connection) { telegram_api::object_ptr<telegram_api::botBusinessConnection> &&connection) {
CHECK(connection != nullptr); CHECK(connection != nullptr);

View File

@ -8,6 +8,7 @@
#include "td/telegram/BusinessConnectionId.h" #include "td/telegram/BusinessConnectionId.h"
#include "td/telegram/DialogId.h" #include "td/telegram/DialogId.h"
#include "td/telegram/net/DcId.h"
#include "td/telegram/td_api.h" #include "td/telegram/td_api.h"
#include "td/telegram/telegram_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; 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<telegram_api::botBusinessConnection> &&connection); void on_update_bot_business_connect(telegram_api::object_ptr<telegram_api::botBusinessConnection> &&connection);
void get_business_connection(const BusinessConnectionId &connection_id, void get_business_connection(const BusinessConnectionId &connection_id,

View File

@ -8,6 +8,7 @@
#include "td/telegram/AccessRights.h" #include "td/telegram/AccessRights.h"
#include "td/telegram/AuthManager.h" #include "td/telegram/AuthManager.h"
#include "td/telegram/BusinessConnectionManager.h"
#include "td/telegram/ContactsManager.h" #include "td/telegram/ContactsManager.h"
#include "td/telegram/DialogManager.h" #include "td/telegram/DialogManager.h"
#include "td/telegram/Global.h" #include "td/telegram/Global.h"
@ -34,6 +35,7 @@ namespace td {
class SetTypingQuery final : public Td::ResultHandler { class SetTypingQuery final : public Td::ResultHandler {
Promise<Unit> promise_; Promise<Unit> promise_;
DialogId dialog_id_; DialogId dialog_id_;
BusinessConnectionId business_connection_id_;
int32 generation_ = 0; int32 generation_ = 0;
public: public:
@ -41,16 +43,22 @@ class SetTypingQuery final : public Td::ResultHandler {
} }
NetQueryRef send(DialogId dialog_id, tl_object_ptr<telegram_api::InputPeer> &&input_peer, NetQueryRef send(DialogId dialog_id, tl_object_ptr<telegram_api::InputPeer> &&input_peer,
MessageId top_thread_message_id, tl_object_ptr<telegram_api::SendMessageAction> &&action) { MessageId top_thread_message_id, BusinessConnectionId business_connection_id,
tl_object_ptr<telegram_api::SendMessageAction> &&action) {
dialog_id_ = dialog_id; dialog_id_ = dialog_id;
business_connection_id_ = business_connection_id;
CHECK(input_peer != nullptr); CHECK(input_peer != nullptr);
int32 flags = 0; int32 flags = 0;
if (top_thread_message_id.is_valid()) { if (top_thread_message_id.is_valid()) {
flags |= telegram_api::messages_setTyping::TOP_MSG_ID_MASK; 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; query->total_timeout_limit_ = 2;
auto result = query.get_weak(); auto result = query.get_weak();
generation_ = result.generation(); generation_ = result.generation();
@ -76,7 +84,8 @@ class SetTypingQuery final : public Td::ResultHandler {
return promise_.set_value(Unit()); 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; LOG(INFO) << "Receive error for set typing: " << status;
} }
promise_.set_error(std::move(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())); 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<Unit> &&promise) { Promise<Unit> &&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")); return promise.set_error(Status::Error(400, "Chat not found"));
} }
if (top_thread_message_id != MessageId() && 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")); 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)); top_thread_message_id = MessageId(ServerMessageId(1));
} }
tl_object_ptr<telegram_api::InputPeer> input_peer; tl_object_ptr<telegram_api::InputPeer> input_peer;
if (action == DialogAction::get_speaking_action()) { 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); input_peer = td_->dialog_manager_->get_input_peer(dialog_id, AccessRights::Read);
if (input_peer == nullptr) { if (input_peer == nullptr) {
return promise.set_error(Status::Error(400, "Have no access to the chat")); 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 { } else {
if (!td_->dialog_manager_->have_input_peer(dialog_id, AccessRights::Write)) { if (!td_->dialog_manager_->have_input_peer(dialog_id, AccessRights::Write)) {
if (td_->auth_manager_->is_bot()) { 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) { 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(), send_closure(G()->secret_chats_manager(), &SecretChatsManager::send_message_action, dialog_id.get_secret_chat_id(),
action.get_secret_input_send_message_action()); action.get_secret_input_send_message_action());
promise.set_value(Unit()); promise.set_value(Unit());
@ -329,9 +348,9 @@ void DialogActionManager::send_dialog_action(DialogId dialog_id, MessageId top_t
CHECK(input_peer != nullptr); CHECK(input_peer != nullptr);
auto new_query_ref = auto new_query_ref = td_->create_handler<SetTypingQuery>(std::move(promise))
td_->create_handler<SetTypingQuery>(std::move(promise)) ->send(dialog_id, std::move(input_peer), top_thread_message_id, business_connection_id,
->send(dialog_id, std::move(input_peer), top_thread_message_id, action.get_input_send_message_action()); action.get_input_send_message_action());
if (td_->auth_manager_->is_bot()) { if (td_->auth_manager_->is_bot()) {
return; return;
} }

View File

@ -6,6 +6,7 @@
// //
#pragma once #pragma once
#include "td/telegram/BusinessConnectionId.h"
#include "td/telegram/DialogAction.h" #include "td/telegram/DialogAction.h"
#include "td/telegram/DialogId.h" #include "td/telegram/DialogId.h"
#include "td/telegram/MessageContentType.h" #include "td/telegram/MessageContentType.h"
@ -31,8 +32,8 @@ class DialogActionManager final : public Actor {
DialogAction action, int32 date, DialogAction action, int32 date,
MessageContentType message_content_type = MessageContentType::None); MessageContentType message_content_type = MessageContentType::None);
void send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogAction action, void send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id,
Promise<Unit> &&promise); BusinessConnectionId business_connection_id, DialogAction action, Promise<Unit> &&promise);
void cancel_send_dialog_action_queries(DialogId dialog_id); void cancel_send_dialog_action_queries(DialogId dialog_id);

View File

@ -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); 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<Unit>()); DialogAction::get_speaking_action(), Promise<Unit>());
} }

View File

@ -31163,7 +31163,7 @@ void MessagesManager::on_send_dialog_action_timeout(DialogId dialog_id) {
return; return;
} }
LOG(INFO) << "Send " << action << " in " << dialog_id; 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<Unit>()); Promise<Unit>());
} }

View File

@ -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) { void Td::on_request(uint64 id, td_api::sendChatAction &request) {
CLEAN_INPUT_STRING(request.business_connection_id_);
CREATE_OK_REQUEST_PROMISE(); CREATE_OK_REQUEST_PROMISE();
dialog_action_manager_->send_dialog_action(DialogId(request.chat_id_), MessageId(request.message_thread_id_), 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)); DialogAction(std::move(request.action_)), std::move(promise));
} }

View File

@ -4651,7 +4651,8 @@ class CliClient final : public Actor {
ChatId chat_id; ChatId chat_id;
string action; string action;
get_args(args, chat_id, action); get_args(args, chat_id, action);
send_request(td_api::make_object<td_api::sendChatAction>(chat_id, message_thread_id_, as_chat_action(action))); send_request(
td_api::make_object<td_api::sendChatAction>(chat_id, message_thread_id_, string(), as_chat_action(action)));
} else if (op == "smt" || op == "smtp" || op == "smtf" || op == "smtpf") { } else if (op == "smt" || op == "smtp" || op == "smtf" || op == "smtpf") {
ChatId chat_id; ChatId chat_id;
get_args(args, chat_id); get_args(args, chat_id);

View File

@ -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); return create(UniqueId::next(), nullptr, function, std::move(chain_ids), dc_id, type, NetQuery::AuthFlag::On);
} }
NetQueryPtr NetQueryCreator::create_with_prefix(const unique_ptr<telegram_api::Function> &prefix, NetQueryPtr NetQueryCreator::create_with_prefix(const telegram_api::object_ptr<telegram_api::Function> &prefix,
const telegram_api::Function &function, DcId dc_id, const telegram_api::Function &function, DcId dc_id,
NetQuery::Type type) { vector<ChainId> chain_ids, NetQuery::Type type) {
return create(UniqueId::next(), prefix, function, {}, dc_id, type, NetQuery::AuthFlag::On); return create(UniqueId::next(), prefix, function, std::move(chain_ids), dc_id, type, NetQuery::AuthFlag::On);
} }
NetQueryPtr NetQueryCreator::create(uint64 id, const unique_ptr<telegram_api::Function> &prefix, NetQueryPtr NetQueryCreator::create(uint64 id, const telegram_api::object_ptr<telegram_api::Function> &prefix,
const telegram_api::Function &function, vector<ChainId> &&chain_ids, DcId dc_id, const telegram_api::Function &function, vector<ChainId> &&chain_ids, DcId dc_id,
NetQuery::Type type, NetQuery::AuthFlag auth_flag) { NetQuery::Type type, NetQuery::AuthFlag auth_flag) {
LOG(INFO) << "Create query " << to_string(function); LOG(INFO) << "Create query " << to_string(function);

View File

@ -38,11 +38,11 @@ class NetQueryCreator {
return create(UniqueId::next(), nullptr, function, {}, dc_id, NetQuery::Type::Common, NetQuery::AuthFlag::Off); return create(UniqueId::next(), nullptr, function, {}, dc_id, NetQuery::Type::Common, NetQuery::AuthFlag::Off);
} }
NetQueryPtr create_with_prefix(const unique_ptr<telegram_api::Function> &prefix, NetQueryPtr create_with_prefix(const telegram_api::object_ptr<telegram_api::Function> &prefix,
const telegram_api::Function &function, DcId dc_id, const telegram_api::Function &function, DcId dc_id, vector<ChainId> chain_ids = {},
NetQuery::Type type = NetQuery::Type::Common); NetQuery::Type type = NetQuery::Type::Common);
NetQueryPtr create(uint64 id, const unique_ptr<telegram_api::Function> &prefix, NetQueryPtr create(uint64 id, const telegram_api::object_ptr<telegram_api::Function> &prefix,
const telegram_api::Function &function, vector<ChainId> &&chain_ids, DcId dc_id, const telegram_api::Function &function, vector<ChainId> &&chain_ids, DcId dc_id,
NetQuery::Type type, NetQuery::AuthFlag auth_flag); NetQuery::Type type, NetQuery::AuthFlag auth_flag);