diff --git a/td/telegram/BotCommand.cpp b/td/telegram/BotCommand.cpp index 41b1f5762..859c69db2 100644 --- a/td/telegram/BotCommand.cpp +++ b/td/telegram/BotCommand.cpp @@ -6,13 +6,103 @@ // #include "td/telegram/BotCommand.h" +#include "td/telegram/BotCommandScope.h" #include "td/telegram/ContactsManager.h" +#include "td/telegram/misc.h" #include "td/telegram/Td.h" #include "td/utils/algorithm.h" +#include "td/utils/buffer.h" +#include "td/utils/logging.h" +#include "td/utils/Status.h" namespace td { +class SetBotCommandsQuery : public Td::ResultHandler { + Promise promise_; + + public: + explicit SetBotCommandsQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(BotCommandScope scope, const string &language_code, vector> &&commands) { + send_query(G()->net_query_creator().create(telegram_api::bots_setBotCommands( + scope.get_input_bot_command_scope(td), language_code, transform(commands, [](const auto &command) { + return make_tl_object(command.first, command.second); + })))); + } + + void on_result(uint64 id, BufferSlice packet) override { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(id, result_ptr.move_as_error()); + } + + if (!result_ptr.ok()) { + LOG(ERROR) << "Set bot commands request failed"; + } + promise_.set_value(Unit()); + } + + void on_error(uint64 id, Status status) override { + promise_.set_error(std::move(status)); + } +}; + +class ResetBotCommandsQuery : public Td::ResultHandler { + Promise promise_; + + public: + explicit ResetBotCommandsQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(BotCommandScope scope, const string &language_code) { + send_query(G()->net_query_creator().create( + telegram_api::bots_resetBotCommands(scope.get_input_bot_command_scope(td), language_code))); + } + + void on_result(uint64 id, BufferSlice packet) override { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(id, result_ptr.move_as_error()); + } + + promise_.set_value(Unit()); + } + + void on_error(uint64 id, Status status) override { + promise_.set_error(std::move(status)); + } +}; + +class GetBotCommandsQuery : public Td::ResultHandler { + Promise> promise_; + + public: + explicit GetBotCommandsQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(BotCommandScope scope, const string &language_code) { + send_query(G()->net_query_creator().create( + telegram_api::bots_getBotCommands(scope.get_input_bot_command_scope(td), language_code))); + } + + void on_result(uint64 id, BufferSlice packet) override { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(id, result_ptr.move_as_error()); + } + + BotCommands commands(td->contacts_manager_->get_my_id(), result_ptr.move_as_ok()); + promise_.set_value(commands.get_bot_commands_object(td)); + } + + void on_error(uint64 id, Status status) override { + promise_.set_error(std::move(status)); + } +}; + BotCommand::BotCommand(telegram_api::object_ptr &&bot_command) { CHECK(bot_command != nullptr); command_ = std::move(bot_command->command_); @@ -44,4 +134,90 @@ bool operator==(const BotCommands &lhs, const BotCommands &rhs) { return lhs.bot_user_id_ == rhs.bot_user_id_ && lhs.commands_ == rhs.commands_; } +void set_commands(Td *td, td_api::object_ptr &&scope_ptr, string &&language_code, + vector> &&commands, Promise &&promise) { + TRY_RESULT_PROMISE(promise, scope, BotCommandScope::get_bot_command_scope(td, std::move(scope_ptr))); + + if (!language_code.empty() && (language_code.size() != 2 || language_code[0] < 'a' || language_code[0] > 'z' || + language_code[1] < 'a' || language_code[1] > 'z')) { + return promise.set_error(Status::Error(400, "Invalid language code specified")); + } + if (!scope.have_input_bot_command_scope(td)) { + return promise.set_error(Status::Error(400, "Invalid scope specified")); + } + + vector> new_commands; + for (auto &command : commands) { + if (command == nullptr) { + return promise.set_error(Status::Error(400, "Command must be non-empty")); + } + if (!clean_input_string(command->command_)) { + return promise.set_error(Status::Error(400, "Command must be encoded in UTF-8")); + } + if (!clean_input_string(command->description_)) { + return promise.set_error(Status::Error(400, "Command description must be encoded in UTF-8")); + } + + const size_t MAX_COMMAND_TEXT_LENGTH = 32; + command->command_ = trim(command->command_); + if (command->command_[0] == '/') { + command->command_ = command->command_.substr(1); + } + if (command->command_.empty()) { + return promise.set_error(Status::Error(400, "Command must be non-empty")); + } + if (utf8_length(command->command_) > MAX_COMMAND_TEXT_LENGTH) { + return promise.set_error( + Status::Error(400, PSLICE() << "Command length must not exceed " << MAX_COMMAND_TEXT_LENGTH)); + } + + const size_t MIN_COMMAND_DESCRIPTION_LENGTH = 3; + const size_t MAX_COMMAND_DESCRIPTION_LENGTH = 256; + command->description_ = trim(command->description_); + auto description_length = utf8_length(command->description_); + if (description_length < MIN_COMMAND_DESCRIPTION_LENGTH) { + return promise.set_error(Status::Error( + 400, PSLICE() << "Command description length must be at least " << MIN_COMMAND_DESCRIPTION_LENGTH)); + } + if (description_length > MAX_COMMAND_DESCRIPTION_LENGTH) { + return promise.set_error(Status::Error( + 400, PSLICE() << "Command description length must not exceed " << MAX_COMMAND_DESCRIPTION_LENGTH)); + } + + new_commands.emplace_back(std::move(command->command_), std::move(command->description_)); + } + + td->create_handler(std::move(promise))->send(scope, language_code, std::move(new_commands)); +} + +void delete_commands(Td *td, td_api::object_ptr &&scope_ptr, string &&language_code, + Promise &&promise) { + TRY_RESULT_PROMISE(promise, scope, BotCommandScope::get_bot_command_scope(td, std::move(scope_ptr))); + + if (!language_code.empty() && (language_code.size() != 2 || language_code[0] < 'a' || language_code[0] > 'z' || + language_code[1] < 'a' || language_code[1] > 'z')) { + return promise.set_error(Status::Error(400, "Invalid language code specified")); + } + if (!scope.have_input_bot_command_scope(td)) { + return promise.set_error(Status::Error(400, "Invalid scope specified")); + } + + td->create_handler(std::move(promise))->send(scope, language_code); +} + +void get_commands(Td *td, td_api::object_ptr &&scope_ptr, string &&language_code, + Promise> &&promise) { + TRY_RESULT_PROMISE(promise, scope, BotCommandScope::get_bot_command_scope(td, std::move(scope_ptr))); + + if (!language_code.empty() && (language_code.size() != 2 || language_code[0] < 'a' || language_code[0] > 'z' || + language_code[1] < 'a' || language_code[1] > 'z')) { + return promise.set_error(Status::Error(400, "Invalid language code specified")); + } + if (!scope.have_input_bot_command_scope(td)) { + return promise.set_error(Status::Error(400, "Invalid scope specified")); + } + + td->create_handler(std::move(promise))->send(scope, language_code); +} + } // namespace td diff --git a/td/telegram/BotCommand.h b/td/telegram/BotCommand.h index 33444f3b5..4a54a32a4 100644 --- a/td/telegram/BotCommand.h +++ b/td/telegram/BotCommand.h @@ -10,6 +10,8 @@ #include "td/telegram/telegram_api.h" #include "td/telegram/UserId.h" +#include "td/actor/PromiseFuture.h" + #include "td/utils/common.h" #include "td/utils/tl_helpers.h" @@ -85,4 +87,13 @@ inline bool operator!=(const BotCommands &lhs, const BotCommands &rhs) { return !(lhs == rhs); } +void set_commands(Td *td, td_api::object_ptr &&scope_ptr, string &&language_code, + vector> &&commands, Promise &&promise); + +void delete_commands(Td *td, td_api::object_ptr &&scope_ptr, string &&language_code, + Promise &&promise); + +void get_commands(Td *td, td_api::object_ptr &&scope_ptr, string &&language_code, + Promise> &&promise); + } // namespace td diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 929523321..511929df1 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -11,7 +11,6 @@ #include "td/telegram/telegram_api.hpp" #include "td/telegram/AuthManager.h" -#include "td/telegram/BotCommandScope.h" #include "td/telegram/ConfigManager.h" #include "td/telegram/ConfigShared.h" #include "td/telegram/Dependencies.h" @@ -980,91 +979,6 @@ class UpdateUsernameQuery : public Td::ResultHandler { } }; -class SetBotCommandsQuery : public Td::ResultHandler { - Promise promise_; - - public: - explicit SetBotCommandsQuery(Promise &&promise) : promise_(std::move(promise)) { - } - - void send(BotCommandScope scope, const string &language_code, vector> &&commands) { - send_query(G()->net_query_creator().create(telegram_api::bots_setBotCommands( - scope.get_input_bot_command_scope(td), language_code, transform(commands, [](const auto &command) { - return make_tl_object(command.first, command.second); - })))); - } - - void on_result(uint64 id, BufferSlice packet) override { - auto result_ptr = fetch_result(packet); - if (result_ptr.is_error()) { - return on_error(id, result_ptr.move_as_error()); - } - - if (!result_ptr.ok()) { - LOG(ERROR) << "Set bot commands request failed"; - } - promise_.set_value(Unit()); - } - - void on_error(uint64 id, Status status) override { - promise_.set_error(std::move(status)); - } -}; - -class ResetBotCommandsQuery : public Td::ResultHandler { - Promise promise_; - - public: - explicit ResetBotCommandsQuery(Promise &&promise) : promise_(std::move(promise)) { - } - - void send(BotCommandScope scope, const string &language_code) { - send_query(G()->net_query_creator().create( - telegram_api::bots_resetBotCommands(scope.get_input_bot_command_scope(td), language_code))); - } - - void on_result(uint64 id, BufferSlice packet) override { - auto result_ptr = fetch_result(packet); - if (result_ptr.is_error()) { - return on_error(id, result_ptr.move_as_error()); - } - - promise_.set_value(Unit()); - } - - void on_error(uint64 id, Status status) override { - promise_.set_error(std::move(status)); - } -}; - -class GetBotCommandsQuery : public Td::ResultHandler { - Promise> promise_; - - public: - explicit GetBotCommandsQuery(Promise> &&promise) - : promise_(std::move(promise)) { - } - - void send(BotCommandScope scope, const string &language_code) { - send_query(G()->net_query_creator().create( - telegram_api::bots_getBotCommands(scope.get_input_bot_command_scope(td), language_code))); - } - - void on_result(uint64 id, BufferSlice packet) override { - auto result_ptr = fetch_result(packet); - if (result_ptr.is_error()) { - return on_error(id, result_ptr.move_as_error()); - } - - BotCommands commands(td->contacts_manager_->get_my_id(), result_ptr.move_as_ok()); - promise_.set_value(commands.get_bot_commands_object(td)); - } - - void on_error(uint64 id, Status status) override { - promise_.set_error(std::move(status)); - } -}; - class CheckChannelUsernameQuery : public Td::ResultHandler { Promise promise_; ChannelId channel_id_; @@ -6310,92 +6224,6 @@ void ContactsManager::set_username(const string &username, Promise &&promi td_->create_handler(std::move(promise))->send(username); } -void ContactsManager::set_commands(td_api::object_ptr &&scope_ptr, string &&language_code, - vector> &&commands, Promise &&promise) { - TRY_RESULT_PROMISE(promise, scope, BotCommandScope::get_bot_command_scope(td_, std::move(scope_ptr))); - - if (!language_code.empty() && (language_code.size() != 2 || language_code[0] < 'a' || language_code[0] > 'z' || - language_code[1] < 'a' || language_code[1] > 'z')) { - return promise.set_error(Status::Error(400, "Invalid language code specified")); - } - if (!scope.have_input_bot_command_scope(td_)) { - return promise.set_error(Status::Error(400, "Invalid scope specified")); - } - - vector> new_commands; - for (auto &command : commands) { - if (command == nullptr) { - return promise.set_error(Status::Error(400, "Command must be non-empty")); - } - if (!clean_input_string(command->command_)) { - return promise.set_error(Status::Error(400, "Command must be encoded in UTF-8")); - } - if (!clean_input_string(command->description_)) { - return promise.set_error(Status::Error(400, "Command description must be encoded in UTF-8")); - } - - const size_t MAX_COMMAND_TEXT_LENGTH = 32; - command->command_ = trim(command->command_); - if (command->command_[0] == '/') { - command->command_ = command->command_.substr(1); - } - if (command->command_.empty()) { - return promise.set_error(Status::Error(400, "Command must be non-empty")); - } - if (utf8_length(command->command_) > MAX_COMMAND_TEXT_LENGTH) { - return promise.set_error( - Status::Error(400, PSLICE() << "Command length must not exceed " << MAX_COMMAND_TEXT_LENGTH)); - } - - const size_t MIN_COMMAND_DESCRIPTION_LENGTH = 3; - const size_t MAX_COMMAND_DESCRIPTION_LENGTH = 256; - command->description_ = trim(command->description_); - auto description_length = utf8_length(command->description_); - if (description_length < MIN_COMMAND_DESCRIPTION_LENGTH) { - return promise.set_error(Status::Error( - 400, PSLICE() << "Command description length must be at least " << MIN_COMMAND_DESCRIPTION_LENGTH)); - } - if (description_length > MAX_COMMAND_DESCRIPTION_LENGTH) { - return promise.set_error(Status::Error( - 400, PSLICE() << "Command description length must not exceed " << MAX_COMMAND_DESCRIPTION_LENGTH)); - } - - new_commands.emplace_back(std::move(command->command_), std::move(command->description_)); - } - - td_->create_handler(std::move(promise))->send(scope, language_code, std::move(new_commands)); -} - -void ContactsManager::delete_commands(td_api::object_ptr &&scope_ptr, string &&language_code, - Promise &&promise) { - TRY_RESULT_PROMISE(promise, scope, BotCommandScope::get_bot_command_scope(td_, std::move(scope_ptr))); - - if (!language_code.empty() && (language_code.size() != 2 || language_code[0] < 'a' || language_code[0] > 'z' || - language_code[1] < 'a' || language_code[1] > 'z')) { - return promise.set_error(Status::Error(400, "Invalid language code specified")); - } - if (!scope.have_input_bot_command_scope(td_)) { - return promise.set_error(Status::Error(400, "Invalid scope specified")); - } - - td_->create_handler(std::move(promise))->send(scope, language_code); -} - -void ContactsManager::get_commands(td_api::object_ptr &&scope_ptr, string &&language_code, - Promise> &&promise) { - TRY_RESULT_PROMISE(promise, scope, BotCommandScope::get_bot_command_scope(td_, std::move(scope_ptr))); - - if (!language_code.empty() && (language_code.size() != 2 || language_code[0] < 'a' || language_code[0] > 'z' || - language_code[1] < 'a' || language_code[1] > 'z')) { - return promise.set_error(Status::Error(400, "Invalid language code specified")); - } - if (!scope.have_input_bot_command_scope(td_)) { - return promise.set_error(Status::Error(400, "Invalid scope specified")); - } - - td_->create_handler(std::move(promise))->send(scope, language_code); -} - void ContactsManager::set_chat_description(ChatId chat_id, const string &description, Promise &&promise) { auto new_description = strip_empty_characters(description, MAX_DESCRIPTION_LENGTH); auto c = get_chat(chat_id); diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 9093d5688..24bedbb56 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -329,15 +329,6 @@ class ContactsManager : public Actor { void set_username(const string &username, Promise &&promise); - void set_commands(td_api::object_ptr &&scope_ptr, string &&language_code, - vector> &&commands, Promise &&promise); - - void delete_commands(td_api::object_ptr &&scope_ptr, string &&language_code, - Promise &&promise); - - void get_commands(td_api::object_ptr &&scope_ptr, string &&language_code, - Promise> &&promise); - void set_chat_description(ChatId chat_id, const string &description, Promise &&promise); void set_channel_username(ChannelId channel_id, const string &username, Promise &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index bf89b2b2d..c4e6d487e 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -14,6 +14,7 @@ #include "td/telegram/BackgroundId.h" #include "td/telegram/BackgroundManager.h" #include "td/telegram/BackgroundType.h" +#include "td/telegram/BotCommand.h" #include "td/telegram/CallbackQueriesManager.h" #include "td/telegram/CallId.h" #include "td/telegram/CallManager.h" @@ -6874,20 +6875,20 @@ void Td::on_request(uint64 id, td_api::setUsername &request) { void Td::on_request(uint64 id, td_api::setCommands &request) { CHECK_IS_BOT(); CREATE_OK_REQUEST_PROMISE(); - contacts_manager_->set_commands(std::move(request.scope_), std::move(request.language_code_), - std::move(request.commands_), std::move(promise)); + set_commands(this, std::move(request.scope_), std::move(request.language_code_), std::move(request.commands_), + std::move(promise)); } void Td::on_request(uint64 id, td_api::deleteCommands &request) { CHECK_IS_BOT(); CREATE_OK_REQUEST_PROMISE(); - contacts_manager_->delete_commands(std::move(request.scope_), std::move(request.language_code_), std::move(promise)); + delete_commands(this, std::move(request.scope_), std::move(request.language_code_), std::move(promise)); } void Td::on_request(uint64 id, td_api::getCommands &request) { CHECK_IS_BOT(); CREATE_REQUEST_PROMISE(); - contacts_manager_->get_commands(std::move(request.scope_), std::move(request.language_code_), std::move(promise)); + get_commands(this, std::move(request.scope_), std::move(request.language_code_), std::move(promise)); } void Td::on_request(uint64 id, const td_api::setLocation &request) {