diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index d8757812a..6a7949e67 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3777,6 +3777,9 @@ storyInteractions total_count:int32 total_forward_count:int32 total_reaction_cou //@content Content of the message quickReplyMessage id:int53 sending_state:MessageSendingState can_be_edited:Bool reply_to_message_id:int53 via_bot_user_id:int53 media_album_id:int64 content:MessageContent = QuickReplyMessage; +//@description Contains a list of quick reply messages @messages List of messages +quickReplyMessages messages:vector = QuickReplyMessages; + //@description Describes a shortcut that can be used for a quick reply //@id Unique shortcut identifier //@name The name of the shortcut that can be used to use the shortcut @@ -7778,6 +7781,9 @@ deleteQuickReplyShortcut shortcut_id:int32 = Ok; //@description Changes the order of quick reply shortcuts @shortcut_ids The new order of quick reply shortcuts reorderQuickReplyShortcuts shortcut_ids:vector = Ok; +//@description Returns all messages that can be sent by a quick reply shortcut. The messages are returned in order from the first to the last sent @shortcut_id Unique identifier of the quick reply shortcut +getQuickReplyShortcutMessages shortcut_id:int32 = QuickReplyMessages; + //@description Returns list of custom emojis, which can be used as forum topic icon by all users getForumTopicDefaultIcons = Stickers; diff --git a/td/telegram/QuickReplyManager.cpp b/td/telegram/QuickReplyManager.cpp index 05cf3a369..18312ed73 100644 --- a/td/telegram/QuickReplyManager.cpp +++ b/td/telegram/QuickReplyManager.cpp @@ -111,6 +111,41 @@ class ReorderQuickRepliesQuery final : public Td::ResultHandler { } }; +class GetQuickReplyMessagesQuery final : public Td::ResultHandler { + Promise> promise_; + + public: + explicit GetQuickReplyMessagesQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(QuickReplyShortcutId shortcut_id, const vector &message_ids, int64 hash) { + int32 flags = 0; + if (!message_ids.empty()) { + flags |= telegram_api::messages_getQuickReplyMessages::ID_MASK; + } + send_query(G()->net_query_creator().create( + telegram_api::messages_getQuickReplyMessages(flags, shortcut_id.get(), + MessageId::get_server_message_ids(message_ids), hash), + {{"me"}})); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + auto ptr = result_ptr.move_as_ok(); + LOG(DEBUG) << "Receive result for GetQuickReplyMessagesQuery: " << to_string(ptr); + promise_.set_value(std::move(ptr)); + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + QuickReplyManager::QuickReplyMessage::~QuickReplyMessage() = default; template @@ -653,6 +688,8 @@ void QuickReplyManager::on_reload_quick_reply_shortcuts( } break; } + default: + UNREACHABLE(); } on_load_quick_reply_success(); } @@ -698,8 +735,10 @@ void QuickReplyManager::delete_quick_reply_shortcut(QuickReplyShortcutId shortcu if (it == shortcuts_.shortcuts_.end()) { return promise.set_error(Status::Error(400, "Shortcut not found")); } + send_update_quick_reply_shortcut_deleted(it->get()); shortcuts_.shortcuts_.erase(it); save_quick_reply_shortcuts(); + send_update_quick_reply_shortcuts(); if (!shortcut_id.is_server()) { return promise.set_value(Unit()); @@ -765,6 +804,111 @@ void QuickReplyManager::reorder_quick_reply_shortcuts_on_server(vectorcreate_handler(std::move(promise))->send(std::move(shortcut_ids)); } +void QuickReplyManager::get_quick_reply_shortcut_messages( + QuickReplyShortcutId shortcut_id, Promise> &&promise) { + auto s = get_shortcut(shortcut_id); + if (s == nullptr) { + return promise.set_error(Status::Error(400, "Shortcut not found")); + } + if (static_cast(s->messages_.size()) == s->server_total_count_ + s->local_total_count_) { + return promise.set_value(get_quick_reply_messages_object(s)); + } + + CHECK(shortcut_id.is_server()); + reload_quick_reply_messages(shortcut_id, std::move(promise)); +} + +void QuickReplyManager::reload_quick_reply_messages(QuickReplyShortcutId shortcut_id, + Promise> &&promise) { + auto &queries = get_shortcut_messages_queries_[shortcut_id]; + queries.push_back(std::move(promise)); + if (queries.size() != 1) { + return; + } + auto query_promise = + PromiseCreator::lambda([actor_id = actor_id(this), shortcut_id]( + Result> r_messages) { + send_closure(actor_id, &QuickReplyManager::on_reload_quick_reply_messages, shortcut_id, std::move(r_messages)); + }); + td_->create_handler(std::move(query_promise))->send(shortcut_id, vector(), 0); +} + +void QuickReplyManager::on_reload_quick_reply_messages( + QuickReplyShortcutId shortcut_id, Result> r_messages) { + G()->ignore_result_if_closing(r_messages); + auto queries_it = get_shortcut_messages_queries_.find(shortcut_id); + CHECK(queries_it != get_shortcut_messages_queries_.end()); + CHECK(!queries_it->second.empty()); + auto promises = std::move(queries_it->second); + get_shortcut_messages_queries_.erase(queries_it); + if (r_messages.is_error()) { + return fail_promises(promises, r_messages.move_as_error()); + } + auto messages_ptr = r_messages.move_as_ok(); + switch (messages_ptr->get_id()) { + case telegram_api::messages_messagesSlice::ID: + case telegram_api::messages_channelMessages::ID: + LOG(ERROR) << "Receive " << to_string(messages_ptr); + break; + case telegram_api::messages_messagesNotModified::ID: + break; + case telegram_api::messages_messages::ID: { + auto messages = telegram_api::move_object_as(messages_ptr); + td_->contacts_manager_->on_get_users(std::move(messages->users_), "on_reload_quick_reply_messages"); + td_->contacts_manager_->on_get_chats(std::move(messages->chats_), "on_reload_quick_reply_messages"); + + vector> quick_reply_messages; + for (auto &server_message : messages->messages_) { + auto message = create_message(std::move(server_message), "on_reload_quick_reply_messages"); + if (message == nullptr) { + continue; + } + if (message->shortcut_id != shortcut_id) { + LOG(ERROR) << "Receive message from " << message->shortcut_id << " instead of " << shortcut_id; + continue; + } + + quick_reply_messages.push_back(std::move(message)); + } + auto it = get_shortcut_it(shortcut_id); + if (quick_reply_messages.empty()) { + if (it != shortcuts_.shortcuts_.end()) { + send_update_quick_reply_shortcut_deleted(it->get()); + shortcuts_.shortcuts_.erase(it); + save_quick_reply_shortcuts(); + send_update_quick_reply_shortcuts(); + } + break; + } + + auto *old_shortcut = it->get(); + auto shortcut = td::make_unique(); + shortcut->name_ = old_shortcut->name_; + shortcut->shortcut_id_ = shortcut_id; + shortcut->server_total_count_ = quick_reply_messages.size(); + shortcut->messages_ = std::move(quick_reply_messages); + + auto is_object_changed = false; + update_shortcut_from(shortcut.get(), old_shortcut, false, &is_object_changed); + *it = std::move(shortcut); + if (is_object_changed) { + send_update_quick_reply_shortcut(it->get(), "on_reload_quick_reply_messages"); + } + save_quick_reply_shortcuts(); + break; + } + default: + UNREACHABLE(); + } + auto s = get_shortcut(shortcut_id); + if (s == nullptr) { + return fail_promises(promises, Status::Error(400, "Shortcut not found")); + } + for (auto &promise : promises) { + return promise.set_value(get_quick_reply_messages_object(s)); + } +} + QuickReplyManager::Shortcut *QuickReplyManager::get_shortcut(QuickReplyShortcutId shortcut_id) { if (!shortcuts_.are_inited_) { return nullptr; @@ -936,6 +1080,14 @@ void QuickReplyManager::send_update_quick_reply_shortcuts() { send_closure(G()->td(), &Td::send_update, get_update_quick_reply_shortcuts_object()); } +td_api::object_ptr QuickReplyManager::get_quick_reply_messages_object( + const Shortcut *s) const { + auto messages = transform(s->messages_, [this](const unique_ptr &message) { + return get_quick_reply_message_object(message.get(), "get_quick_reply_messages_object"); + }); + return td_api::make_object(std::move(messages)); +} + void QuickReplyManager::get_current_state(vector> &updates) const { if (td_->auth_manager_->is_bot()) { return; diff --git a/td/telegram/QuickReplyManager.h b/td/telegram/QuickReplyManager.h index e4b79eb92..68caafc30 100644 --- a/td/telegram/QuickReplyManager.h +++ b/td/telegram/QuickReplyManager.h @@ -15,6 +15,7 @@ #include "td/actor/actor.h" #include "td/utils/common.h" +#include "td/utils/FlatHashMap.h" #include "td/utils/FlatHashSet.h" #include "td/utils/Promise.h" @@ -36,6 +37,9 @@ class QuickReplyManager final : public Actor { void reorder_quick_reply_shortcuts(const vector &shortcut_ids, Promise &&promise); + void get_quick_reply_shortcut_messages(QuickReplyShortcutId shortcut_id, + Promise> &&promise); + void reload_quick_reply_shortcuts(); void get_current_state(vector> &updates) const; @@ -159,6 +163,12 @@ class QuickReplyManager final : public Actor { int64 get_shortcuts_hash() const; + void reload_quick_reply_messages(QuickReplyShortcutId shortcut_id, + Promise> &&promise); + + void on_reload_quick_reply_messages(QuickReplyShortcutId shortcut_id, + Result> r_messages); + Shortcut *get_shortcut(QuickReplyShortcutId shortcut_id); Shortcut *get_shortcut(const string &name); @@ -202,6 +212,8 @@ class QuickReplyManager final : public Actor { void send_update_quick_reply_shortcuts(); + td_api::object_ptr get_quick_reply_messages_object(const Shortcut *s) const; + void delete_quick_reply_shortcut_from_server(QuickReplyShortcutId shortcut_id, Promise &&promise); void reorder_quick_reply_shortcuts_on_server(vector shortcut_ids, Promise &&promise); @@ -214,6 +226,10 @@ class QuickReplyManager final : public Actor { FlatHashSet deleted_shortcut_ids_; + FlatHashMap>>, + QuickReplyShortcutIdHash> + get_shortcut_messages_queries_; + Td *td_; ActorShared<> parent_; }; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 9560d195f..72bf38f62 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5780,6 +5780,13 @@ void Td::on_request(uint64 id, const td_api::reorderQuickReplyShortcuts &request QuickReplyShortcutId::get_quick_reply_shortcut_ids(request.shortcut_ids_), std::move(promise)); } +void Td::on_request(uint64 id, const td_api::getQuickReplyShortcutMessages &request) { + CHECK_IS_USER(); + CREATE_REQUEST_PROMISE(); + quick_reply_manager_->get_quick_reply_shortcut_messages(QuickReplyShortcutId(request.shortcut_id_), + std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::getStory &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index b16213f4b..2eb704fa5 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -870,6 +870,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::reorderQuickReplyShortcuts &request); + void on_request(uint64 id, const td_api::getQuickReplyShortcutMessages &request); + void on_request(uint64 id, const td_api::getStory &request); void on_request(uint64 id, const td_api::getChatsToSendStories &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index a6074dfa3..6560f9383 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4855,6 +4855,10 @@ class CliClient final : public Actor { string shortcut_ids; get_args(args, shortcut_ids); send_request(td_api::make_object(as_shortcut_ids(shortcut_ids))); + } else if (op == "gqrsm") { + ShortcutId shortcut_id; + get_args(args, shortcut_id); + send_request(td_api::make_object(shortcut_id)); } else if (op == "gftdi") { send_request(td_api::make_object()); } else if (op == "cft") {