Add td_api::sendBusinessMessage.
This commit is contained in:
parent
e717e25a1d
commit
0f98e748a8
@ -7818,6 +7818,17 @@ editInlineMessageReplyMarkup inline_message_id:string reply_markup:ReplyMarkup =
|
||||
editMessageSchedulingState chat_id:int53 message_id:int53 scheduling_state:MessageSchedulingState = Ok;
|
||||
|
||||
|
||||
//@description Sends a business message; for bots only. Returns the message after it was sent
|
||||
//@business_connection_id Unique identifier of business connection on behalf of which to send the request
|
||||
//@chat_id Target chat
|
||||
//@reply_to Information about the message; pass null if none
|
||||
//@disable_notification Pass true to disable notification for the message
|
||||
//@protect_content Pass true if the content of the message must be protected from forwarding and saving; for bots only
|
||||
//@reply_markup Markup for replying to the message; pass null if none; for bots only
|
||||
//@input_message_content The content of the message to be sent
|
||||
sendBusinessMessage business_connection_id:string chat_id:int53 reply_to:InputMessageReplyTo disable_notification:Bool protect_content:Bool reply_markup:ReplyMarkup input_message_content:InputMessageContent = Message;
|
||||
|
||||
|
||||
//@description Checks validness of a name for a quick reply shortcut. Can be called synchronously @name The name of the shortcut; 1-32 characters
|
||||
checkQuickReplyShortcutName name:string = Ok;
|
||||
|
||||
|
@ -10,7 +10,14 @@
|
||||
#include "td/telegram/ContactsManager.h"
|
||||
#include "td/telegram/DialogManager.h"
|
||||
#include "td/telegram/Global.h"
|
||||
#include "td/telegram/MessageContent.h"
|
||||
#include "td/telegram/MessageCopyOptions.h"
|
||||
#include "td/telegram/MessageEntity.h"
|
||||
#include "td/telegram/MessageId.h"
|
||||
#include "td/telegram/MessageSelfDestructType.h"
|
||||
#include "td/telegram/MessagesManager.h"
|
||||
#include "td/telegram/ReplyMarkup.h"
|
||||
#include "td/telegram/ServerMessageId.h"
|
||||
#include "td/telegram/Td.h"
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
@ -18,6 +25,7 @@
|
||||
|
||||
#include "td/utils/format.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/Random.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
@ -83,6 +91,95 @@ struct BusinessConnectionManager::BusinessConnection {
|
||||
}
|
||||
};
|
||||
|
||||
struct BusinessConnectionManager::PendingMessage {
|
||||
BusinessConnectionId business_connection_id_;
|
||||
DialogId dialog_id_;
|
||||
MessageInputReplyTo input_reply_to_;
|
||||
string send_emoji_;
|
||||
MessageSelfDestructType ttl_;
|
||||
unique_ptr<MessageContent> content_;
|
||||
unique_ptr<ReplyMarkup> reply_markup_;
|
||||
int64 media_album_id_ = 0;
|
||||
int64 random_id_ = 0;
|
||||
bool noforwards_ = false;
|
||||
bool disable_notification_ = false;
|
||||
bool invert_media_ = false;
|
||||
bool disable_web_page_preview_ = false;
|
||||
};
|
||||
|
||||
class BusinessConnectionManager::SendBusinessMessageQuery final : public Td::ResultHandler {
|
||||
Promise<td_api::object_ptr<td_api::message>> promise_;
|
||||
unique_ptr<PendingMessage> message_;
|
||||
|
||||
public:
|
||||
explicit SendBusinessMessageQuery(Promise<td_api::object_ptr<td_api::message>> &&promise)
|
||||
: promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(unique_ptr<PendingMessage> message) {
|
||||
message_ = std::move(message);
|
||||
|
||||
int32 flags = 0;
|
||||
if (message_->disable_web_page_preview_) {
|
||||
flags |= telegram_api::messages_sendMessage::NO_WEBPAGE_MASK;
|
||||
}
|
||||
if (message_->disable_notification_) {
|
||||
flags |= telegram_api::messages_sendMessage::SILENT_MASK;
|
||||
}
|
||||
if (message_->noforwards_) {
|
||||
flags |= telegram_api::messages_sendMessage::NOFORWARDS_MASK;
|
||||
}
|
||||
if (message_->invert_media_) {
|
||||
flags |= telegram_api::messages_sendMessage::INVERT_MEDIA_MASK;
|
||||
}
|
||||
|
||||
auto input_peer = td_->dialog_manager_->get_input_peer_force(message_->dialog_id_);
|
||||
CHECK(input_peer != nullptr);
|
||||
|
||||
auto reply_to = message_->input_reply_to_.get_input_reply_to(td_, MessageId());
|
||||
if (reply_to != nullptr) {
|
||||
flags |= telegram_api::messages_sendMessage::REPLY_TO_MASK;
|
||||
}
|
||||
|
||||
const FormattedText *message_text = get_message_content_text(message_->content_.get());
|
||||
CHECK(message_text != nullptr);
|
||||
auto entities = get_input_message_entities(td_->contacts_manager_.get(), message_text, "SendBusinessMessageQuery");
|
||||
if (!entities.empty()) {
|
||||
flags |= telegram_api::messages_sendMessage::ENTITIES_MASK;
|
||||
}
|
||||
|
||||
if (message_->reply_markup_ != nullptr) {
|
||||
flags |= telegram_api::messages_sendMessage::REPLY_MARKUP_MASK;
|
||||
}
|
||||
|
||||
send_query(G()->net_query_creator().create_with_prefix(
|
||||
message_->business_connection_id_.get_invoke_prefix(),
|
||||
telegram_api::messages_sendMessage(
|
||||
flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
|
||||
false /*ignored*/, false /*ignored*/, std::move(input_peer), std::move(reply_to), message_text->text,
|
||||
message_->random_id_, get_input_reply_markup(td_->contacts_manager_.get(), message_->reply_markup_),
|
||||
std::move(entities), 0, nullptr, nullptr),
|
||||
td_->business_connection_manager_->get_business_connection_dc_id(message_->business_connection_id_),
|
||||
{{message_->dialog_id_}}));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_sendMessage>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
auto ptr = result_ptr.move_as_ok();
|
||||
LOG(INFO) << "Receive result for SendBusinessMessageQuery: " << to_string(ptr);
|
||||
promise_.set_value(nullptr); // TODO
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
LOG(INFO) << "Receive error for SendBusinessMessageQuery: " << status;
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
BusinessConnectionManager::BusinessConnectionManager(Td *td, ActorShared<> parent)
|
||||
: td_(td), parent_(std::move(parent)) {
|
||||
}
|
||||
@ -259,4 +356,119 @@ void BusinessConnectionManager::on_get_business_connection(
|
||||
}
|
||||
}
|
||||
|
||||
MessageInputReplyTo BusinessConnectionManager::create_business_message_input_reply_to(
|
||||
td_api::object_ptr<td_api::InputMessageReplyTo> &&reply_to) {
|
||||
if (reply_to == nullptr) {
|
||||
return {};
|
||||
}
|
||||
switch (reply_to->get_id()) {
|
||||
case td_api::inputMessageReplyToStory::ID:
|
||||
return {};
|
||||
case td_api::inputMessageReplyToMessage::ID: {
|
||||
auto reply_to_message = td_api::move_object_as<td_api::inputMessageReplyToMessage>(reply_to);
|
||||
auto message_id = MessageId(reply_to_message->message_id_);
|
||||
if (!message_id.is_valid() || !message_id.is_server()) {
|
||||
return {};
|
||||
}
|
||||
if (reply_to_message->chat_id_ != 0) {
|
||||
return {};
|
||||
}
|
||||
FormattedText quote;
|
||||
int32 quote_position = 0;
|
||||
if (reply_to_message->quote_ != nullptr) {
|
||||
int32 ltrim_count = 0;
|
||||
auto r_quote = get_formatted_text(td_, td_->dialog_manager_->get_my_dialog_id(),
|
||||
std::move(reply_to_message->quote_->text_), td_->auth_manager_->is_bot(),
|
||||
true, true, false, <rim_count);
|
||||
if (r_quote.is_ok() && !r_quote.ok().text.empty()) {
|
||||
quote = r_quote.move_as_ok();
|
||||
quote_position = reply_to_message->quote_->position_;
|
||||
if (0 <= quote_position && quote_position <= 1000000) { // some unreasonably big bound
|
||||
quote_position += ltrim_count;
|
||||
} else {
|
||||
quote_position = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return MessageInputReplyTo{message_id, DialogId(), std::move(quote), quote_position};
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
Result<InputMessageContent> BusinessConnectionManager::process_input_message_content(
|
||||
DialogId dialog_id, td_api::object_ptr<td_api::InputMessageContent> &&input_message_content) {
|
||||
if (input_message_content == nullptr) {
|
||||
return Status::Error(400, "Can't send message without content");
|
||||
}
|
||||
if (input_message_content->get_id() == td_api::inputMessageForwarded::ID) {
|
||||
return Status::Error(400, "Can't forward messages as business");
|
||||
}
|
||||
return get_input_message_content(dialog_id, std::move(input_message_content), td_, true);
|
||||
}
|
||||
|
||||
unique_ptr<BusinessConnectionManager::PendingMessage> BusinessConnectionManager::create_business_message_to_send(
|
||||
BusinessConnectionId business_connection_id, DialogId dialog_id, MessageInputReplyTo &&input_reply_to,
|
||||
bool disable_notification, bool protect_content, unique_ptr<ReplyMarkup> &&reply_markup,
|
||||
InputMessageContent &&input_content) const {
|
||||
auto content = dup_message_content(td_, td_->dialog_manager_->get_my_dialog_id(), input_content.content.get(),
|
||||
MessageContentDupType::Send, MessageCopyOptions());
|
||||
auto message = make_unique<PendingMessage>();
|
||||
message->business_connection_id_ = business_connection_id;
|
||||
message->dialog_id_ = dialog_id;
|
||||
message->input_reply_to_ = std::move(input_reply_to);
|
||||
message->noforwards_ = protect_content;
|
||||
message->content_ = std::move(content);
|
||||
message->reply_markup_ = std::move(reply_markup);
|
||||
message->disable_notification_ = disable_notification;
|
||||
message->invert_media_ = input_content.invert_media;
|
||||
message->disable_web_page_preview_ = input_content.disable_web_page_preview;
|
||||
message->ttl_ = input_content.ttl;
|
||||
message->send_emoji_ = std::move(input_content.emoji);
|
||||
message->random_id_ = Random::secure_int64();
|
||||
return message;
|
||||
}
|
||||
|
||||
void BusinessConnectionManager::send_message(BusinessConnectionId business_connection_id, DialogId dialog_id,
|
||||
td_api::object_ptr<td_api::InputMessageReplyTo> &&reply_to,
|
||||
bool disable_notification, bool protect_content,
|
||||
td_api::object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
||||
td_api::object_ptr<td_api::InputMessageContent> &&input_message_content,
|
||||
Promise<td_api::object_ptr<td_api::message>> &&promise) {
|
||||
TRY_STATUS_PROMISE(promise, check_business_connection(business_connection_id, dialog_id));
|
||||
TRY_RESULT_PROMISE(promise, input_content,
|
||||
process_input_message_content(dialog_id, std::move(input_message_content)));
|
||||
auto input_reply_to = create_business_message_input_reply_to(std::move(reply_to));
|
||||
TRY_RESULT_PROMISE(promise, message_reply_markup,
|
||||
get_reply_markup(std::move(reply_markup), DialogType::User, td_->auth_manager_->is_bot(), false));
|
||||
|
||||
auto message = create_business_message_to_send(std::move(business_connection_id), dialog_id,
|
||||
std::move(input_reply_to), disable_notification, protect_content,
|
||||
std::move(message_reply_markup), std::move(input_content));
|
||||
|
||||
do_send_message(std::move(message), std::move(promise));
|
||||
}
|
||||
|
||||
void BusinessConnectionManager::do_send_message(unique_ptr<PendingMessage> &&message,
|
||||
Promise<td_api::object_ptr<td_api::message>> &&promise) {
|
||||
LOG(INFO) << "Send business message to " << message->dialog_id_;
|
||||
|
||||
auto content = message->content_.get();
|
||||
CHECK(content != nullptr);
|
||||
auto content_type = content->get_type();
|
||||
if (content_type == MessageContentType::Text) {
|
||||
auto input_media = get_message_content_input_media_web_page(td_, content);
|
||||
if (input_media == nullptr) {
|
||||
td_->create_handler<SendBusinessMessageQuery>(std::move(promise))->send(std::move(message));
|
||||
} else {
|
||||
promise.set_error(Status::Error(400, "Unsupported"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
promise.set_error(Status::Error(400, "Unsupported"));
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "td/telegram/BusinessConnectionId.h"
|
||||
#include "td/telegram/DialogId.h"
|
||||
#include "td/telegram/MessageInputReplyTo.h"
|
||||
#include "td/telegram/net/DcId.h"
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
@ -21,6 +22,8 @@
|
||||
|
||||
namespace td {
|
||||
|
||||
struct InputMessageContent;
|
||||
struct ReplyMarkup;
|
||||
class Td;
|
||||
|
||||
class BusinessConnectionManager final : public Actor {
|
||||
@ -50,14 +53,36 @@ class BusinessConnectionManager final : public Actor {
|
||||
void get_business_connection(const BusinessConnectionId &connection_id,
|
||||
Promise<td_api::object_ptr<td_api::businessConnection>> &&promise);
|
||||
|
||||
void send_message(BusinessConnectionId business_connection_id, DialogId dialog_id,
|
||||
td_api::object_ptr<td_api::InputMessageReplyTo> &&reply_to, bool disable_notification,
|
||||
bool protect_content, td_api::object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
||||
td_api::object_ptr<td_api::InputMessageContent> &&input_message_content,
|
||||
Promise<td_api::object_ptr<td_api::message>> &&promise);
|
||||
|
||||
private:
|
||||
struct BusinessConnection;
|
||||
struct PendingMessage;
|
||||
class SendBusinessMessageQuery;
|
||||
|
||||
void tear_down() final;
|
||||
|
||||
void on_get_business_connection(const BusinessConnectionId &connection_id,
|
||||
Result<telegram_api::object_ptr<telegram_api::Updates>> r_updates);
|
||||
|
||||
MessageInputReplyTo create_business_message_input_reply_to(
|
||||
td_api::object_ptr<td_api::InputMessageReplyTo> &&reply_to);
|
||||
|
||||
Result<InputMessageContent> process_input_message_content(
|
||||
DialogId dialog_id, td_api::object_ptr<td_api::InputMessageContent> &&input_message_content);
|
||||
|
||||
unique_ptr<PendingMessage> create_business_message_to_send(BusinessConnectionId business_connection_id,
|
||||
DialogId dialog_id, MessageInputReplyTo &&input_reply_to,
|
||||
bool disable_notification, bool protect_content,
|
||||
unique_ptr<ReplyMarkup> &&reply_markup,
|
||||
InputMessageContent &&input_content) const;
|
||||
|
||||
void do_send_message(unique_ptr<PendingMessage> &&message, Promise<td_api::object_ptr<td_api::message>> &&promise);
|
||||
|
||||
WaitFreeHashMap<BusinessConnectionId, unique_ptr<BusinessConnection>, BusinessConnectionIdHash> business_connections_;
|
||||
|
||||
FlatHashMap<BusinessConnectionId, vector<Promise<td_api::object_ptr<td_api::businessConnection>>>,
|
||||
|
@ -24486,15 +24486,16 @@ void MessagesManager::on_text_message_ready_to_send(DialogId dialog_id, MessageI
|
||||
get_message_flags(m), dialog_id, get_send_message_as_input_peer(m), *get_message_input_reply_to(m),
|
||||
m->initial_top_thread_message_id, get_message_schedule_date(m),
|
||||
get_input_reply_markup(td_->contacts_manager_.get(), m->reply_markup),
|
||||
get_input_message_entities(td_->contacts_manager_.get(), message_text, "do_send_message"), message_text->text,
|
||||
m->is_copy, random_id, &m->send_query_ref);
|
||||
get_input_message_entities(td_->contacts_manager_.get(), message_text, "on_text_message_ready_to_send"),
|
||||
message_text->text, m->is_copy, random_id, &m->send_query_ref);
|
||||
} else {
|
||||
td_->create_handler<SendMediaQuery>()->send(
|
||||
FileId(), FileId(), get_message_flags(m), dialog_id, get_send_message_as_input_peer(m),
|
||||
*get_message_input_reply_to(m), m->initial_top_thread_message_id, get_message_schedule_date(m),
|
||||
get_input_reply_markup(td_->contacts_manager_.get(), m->reply_markup),
|
||||
get_input_message_entities(td_->contacts_manager_.get(), message_text, "do_send_message"), message_text->text,
|
||||
std::move(input_media), MessageContentType::Text, m->is_copy, random_id, &m->send_query_ref);
|
||||
get_input_message_entities(td_->contacts_manager_.get(), message_text, "on_text_message_ready_to_send"),
|
||||
message_text->text, std::move(input_media), MessageContentType::Text, m->is_copy, random_id,
|
||||
&m->send_query_ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5789,6 +5789,15 @@ void Td::on_request(uint64 id, td_api::editMessageSchedulingState &request) {
|
||||
std::move(request.scheduling_state_), std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::sendBusinessMessage &request) {
|
||||
CHECK_IS_BOT();
|
||||
CREATE_REQUEST_PROMISE();
|
||||
business_connection_manager_->send_message(
|
||||
BusinessConnectionId(std::move(request.business_connection_id_)), DialogId(request.chat_id_),
|
||||
std::move(request.reply_to_), request.disable_notification_, request.protect_content_,
|
||||
std::move(request.reply_markup_), std::move(request.input_message_content_), std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::loadQuickReplyShortcuts &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
|
@ -876,6 +876,8 @@ class Td final : public Actor {
|
||||
|
||||
void on_request(uint64 id, td_api::editMessageSchedulingState &request);
|
||||
|
||||
void on_request(uint64 id, td_api::sendBusinessMessage &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::loadQuickReplyShortcuts &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::setQuickReplyShortcutName &request);
|
||||
|
@ -2343,6 +2343,12 @@ class CliClient final : public Actor {
|
||||
|
||||
void send_message(int64 chat_id, td_api::object_ptr<td_api::InputMessageContent> &&input_message_content,
|
||||
bool disable_notification = false, bool from_background = false) {
|
||||
if (!business_connection_id_.empty()) {
|
||||
send_request(td_api::make_object<td_api::sendBusinessMessage>(
|
||||
business_connection_id_, chat_id, get_input_message_reply_to(), disable_notification, rand_bool(), nullptr,
|
||||
std::move(input_message_content)));
|
||||
return;
|
||||
}
|
||||
auto id = send_request(td_api::make_object<td_api::sendMessage>(
|
||||
chat_id, message_thread_id_, get_input_message_reply_to(),
|
||||
td_api::make_object<td_api::messageSendOptions>(disable_notification, from_background, true, true,
|
||||
|
Loading…
Reference in New Issue
Block a user