2024-02-21 18:43:55 +01:00
|
|
|
//
|
|
|
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
|
|
|
|
//
|
|
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
//
|
|
|
|
#include "td/telegram/QuickReplyManager.h"
|
|
|
|
|
2024-03-07 11:56:57 +01:00
|
|
|
#include "td/telegram/AccessRights.h"
|
2024-02-21 20:06:07 +01:00
|
|
|
#include "td/telegram/AuthManager.h"
|
2024-04-02 12:06:22 +02:00
|
|
|
#include "td/telegram/ChatManager.h"
|
2024-02-21 20:06:07 +01:00
|
|
|
#include "td/telegram/Dependencies.h"
|
|
|
|
#include "td/telegram/DialogManager.h"
|
2024-02-29 15:41:05 +01:00
|
|
|
#include "td/telegram/FileReferenceManager.h"
|
2024-02-29 17:01:40 +01:00
|
|
|
#include "td/telegram/files/FileManager.h"
|
2024-02-22 15:32:12 +01:00
|
|
|
#include "td/telegram/Global.h"
|
2024-02-23 14:17:37 +01:00
|
|
|
#include "td/telegram/logevent/LogEvent.h"
|
|
|
|
#include "td/telegram/logevent/LogEventHelper.h"
|
2024-02-21 20:06:07 +01:00
|
|
|
#include "td/telegram/MessageContent.h"
|
2024-02-23 18:22:33 +01:00
|
|
|
#include "td/telegram/MessageContentType.h"
|
2024-03-07 11:56:57 +01:00
|
|
|
#include "td/telegram/MessageCopyOptions.h"
|
2024-02-21 20:06:07 +01:00
|
|
|
#include "td/telegram/MessageReplyHeader.h"
|
2024-02-21 22:48:05 +01:00
|
|
|
#include "td/telegram/MessageSelfDestructType.h"
|
2024-02-23 12:49:29 +01:00
|
|
|
#include "td/telegram/misc.h"
|
2024-04-15 21:41:36 +02:00
|
|
|
#include "td/telegram/OptionManager.h"
|
2024-03-06 13:56:50 +01:00
|
|
|
#include "td/telegram/ReplyMarkup.h"
|
|
|
|
#include "td/telegram/ReplyMarkup.hpp"
|
2024-03-07 11:56:57 +01:00
|
|
|
#include "td/telegram/ServerMessageId.h"
|
|
|
|
#include "td/telegram/StoryFullId.h"
|
2024-02-21 20:06:07 +01:00
|
|
|
#include "td/telegram/Td.h"
|
2024-03-07 11:56:57 +01:00
|
|
|
#include "td/telegram/TdDb.h"
|
|
|
|
#include "td/telegram/telegram_api.h"
|
2024-04-02 02:52:34 +02:00
|
|
|
#include "td/telegram/UserManager.h"
|
2024-03-05 13:49:42 +01:00
|
|
|
#include "td/telegram/Version.h"
|
2024-02-21 20:06:07 +01:00
|
|
|
|
2024-02-22 15:32:12 +01:00
|
|
|
#include "td/utils/algorithm.h"
|
|
|
|
#include "td/utils/buffer.h"
|
2024-02-29 19:59:53 +01:00
|
|
|
#include "td/utils/format.h"
|
2024-02-22 15:32:12 +01:00
|
|
|
#include "td/utils/logging.h"
|
2024-03-07 11:56:57 +01:00
|
|
|
#include "td/utils/misc.h"
|
2024-04-15 23:53:48 +02:00
|
|
|
#include "td/utils/Random.h"
|
2024-03-07 11:56:57 +01:00
|
|
|
#include "td/utils/Time.h"
|
|
|
|
#include "td/utils/tl_helpers.h"
|
2024-03-04 12:34:47 +01:00
|
|
|
#include "td/utils/unicode.h"
|
|
|
|
#include "td/utils/utf8.h"
|
2024-02-22 15:32:12 +01:00
|
|
|
|
2024-03-07 11:56:57 +01:00
|
|
|
#include <algorithm>
|
|
|
|
|
2024-02-21 18:43:55 +01:00
|
|
|
namespace td {
|
|
|
|
|
2024-02-22 15:32:12 +01:00
|
|
|
class GetQuickRepliesQuery final : public Td::ResultHandler {
|
|
|
|
Promise<telegram_api::object_ptr<telegram_api::messages_QuickReplies>> promise_;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit GetQuickRepliesQuery(Promise<telegram_api::object_ptr<telegram_api::messages_QuickReplies>> &&promise)
|
|
|
|
: promise_(std::move(promise)) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void send(int64 hash) {
|
2024-03-04 13:00:00 +01:00
|
|
|
send_query(G()->net_query_creator().create(telegram_api::messages_getQuickReplies(hash), {{"quick_reply"}}));
|
2024-02-22 15:32:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void on_result(BufferSlice packet) final {
|
|
|
|
auto result_ptr = fetch_result<telegram_api::messages_getQuickReplies>(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 GetQuickRepliesQuery: " << to_string(ptr);
|
|
|
|
promise_.set_value(std::move(ptr));
|
|
|
|
}
|
|
|
|
|
|
|
|
void on_error(Status status) final {
|
|
|
|
promise_.set_error(std::move(status));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-03-04 13:00:00 +01:00
|
|
|
class EditQuickReplyShortcutQuery final : public Td::ResultHandler {
|
|
|
|
Promise<Unit> promise_;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit EditQuickReplyShortcutQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void send(QuickReplyShortcutId shortcut_id, const string &name) {
|
|
|
|
send_query(G()->net_query_creator().create(telegram_api::messages_editQuickReplyShortcut(shortcut_id.get(), name),
|
|
|
|
{{"quick_reply"}}));
|
|
|
|
}
|
|
|
|
|
|
|
|
void on_result(BufferSlice packet) final {
|
|
|
|
auto result_ptr = fetch_result<telegram_api::messages_editQuickReplyShortcut>(packet);
|
|
|
|
if (result_ptr.is_error()) {
|
|
|
|
return on_error(result_ptr.move_as_error());
|
|
|
|
}
|
|
|
|
|
|
|
|
promise_.set_value(Unit());
|
|
|
|
}
|
|
|
|
|
|
|
|
void on_error(Status status) final {
|
|
|
|
promise_.set_error(std::move(status));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-02-24 01:02:42 +01:00
|
|
|
class DeleteQuickReplyShortcutQuery final : public Td::ResultHandler {
|
|
|
|
Promise<Unit> promise_;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit DeleteQuickReplyShortcutQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
|
|
|
}
|
|
|
|
|
2024-02-24 01:16:56 +01:00
|
|
|
void send(QuickReplyShortcutId shortcut_id) {
|
2024-03-04 13:00:00 +01:00
|
|
|
send_query(G()->net_query_creator().create(telegram_api::messages_deleteQuickReplyShortcut(shortcut_id.get()),
|
|
|
|
{{"quick_reply"}}));
|
2024-02-24 01:02:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void on_result(BufferSlice packet) final {
|
|
|
|
auto result_ptr = fetch_result<telegram_api::messages_deleteQuickReplyShortcut>(packet);
|
|
|
|
if (result_ptr.is_error()) {
|
|
|
|
return on_error(result_ptr.move_as_error());
|
|
|
|
}
|
|
|
|
|
|
|
|
promise_.set_value(Unit());
|
|
|
|
}
|
|
|
|
|
|
|
|
void on_error(Status status) final {
|
2024-02-24 12:40:25 +01:00
|
|
|
td_->quick_reply_manager_->reload_quick_reply_shortcuts();
|
|
|
|
promise_.set_error(std::move(status));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class ReorderQuickRepliesQuery final : public Td::ResultHandler {
|
|
|
|
Promise<Unit> promise_;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit ReorderQuickRepliesQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void send(vector<QuickReplyShortcutId> shortcut_ids) {
|
|
|
|
send_query(
|
|
|
|
G()->net_query_creator().create(telegram_api::messages_reorderQuickReplies(
|
|
|
|
QuickReplyShortcutId::get_input_quick_reply_shortcut_ids(shortcut_ids)),
|
2024-03-04 13:00:00 +01:00
|
|
|
{{"quick_reply"}}));
|
2024-02-24 12:40:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void on_result(BufferSlice packet) final {
|
|
|
|
auto result_ptr = fetch_result<telegram_api::messages_reorderQuickReplies>(packet);
|
|
|
|
if (result_ptr.is_error()) {
|
|
|
|
return on_error(result_ptr.move_as_error());
|
|
|
|
}
|
|
|
|
|
|
|
|
promise_.set_value(Unit());
|
|
|
|
}
|
|
|
|
|
|
|
|
void on_error(Status status) final {
|
|
|
|
td_->quick_reply_manager_->reload_quick_reply_shortcuts();
|
2024-02-24 01:02:42 +01:00
|
|
|
promise_.set_error(std::move(status));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-02-28 15:19:28 +01:00
|
|
|
class GetQuickReplyMessagesQuery final : public Td::ResultHandler {
|
|
|
|
Promise<telegram_api::object_ptr<telegram_api::messages_Messages>> promise_;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit GetQuickReplyMessagesQuery(Promise<telegram_api::object_ptr<telegram_api::messages_Messages>> &&promise)
|
|
|
|
: promise_(std::move(promise)) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void send(QuickReplyShortcutId shortcut_id, const vector<MessageId> &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),
|
2024-03-04 13:00:00 +01:00
|
|
|
{{"quick_reply"}}));
|
2024-02-28 15:19:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void on_result(BufferSlice packet) final {
|
|
|
|
auto result_ptr = fetch_result<telegram_api::messages_getQuickReplyMessages>(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));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-02-29 19:34:45 +01:00
|
|
|
class DeleteQuickReplyMessagesQuery final : public Td::ResultHandler {
|
|
|
|
Promise<Unit> promise_;
|
|
|
|
QuickReplyShortcutId shortcut_id_;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit DeleteQuickReplyMessagesQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void send(QuickReplyShortcutId shortcut_id, const vector<MessageId> &message_ids) {
|
|
|
|
shortcut_id_ = shortcut_id;
|
|
|
|
send_query(G()->net_query_creator().create(telegram_api::messages_deleteQuickReplyMessages(
|
|
|
|
shortcut_id.get(), MessageId::get_server_message_ids(message_ids)),
|
2024-03-04 13:00:00 +01:00
|
|
|
{{"quick_reply"}}));
|
2024-02-29 19:34:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void on_result(BufferSlice packet) final {
|
|
|
|
auto result_ptr = fetch_result<telegram_api::messages_deleteQuickReplyMessages>(packet);
|
|
|
|
if (result_ptr.is_error()) {
|
|
|
|
return on_error(result_ptr.move_as_error());
|
|
|
|
}
|
|
|
|
|
|
|
|
promise_.set_value(Unit());
|
|
|
|
}
|
|
|
|
|
|
|
|
void on_error(Status status) final {
|
|
|
|
td_->quick_reply_manager_->reload_quick_reply_messages(shortcut_id_, Promise<Unit>());
|
|
|
|
promise_.set_error(std::move(status));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-04-17 17:39:25 +02:00
|
|
|
class QuickReplyManager::SendQuickReplyMessageQuery final : public Td::ResultHandler {
|
|
|
|
int64 random_id_;
|
|
|
|
QuickReplyShortcutId shortcut_id_;
|
|
|
|
|
|
|
|
public:
|
|
|
|
void send(const QuickReplyMessage *m) {
|
|
|
|
random_id_ = m->random_id;
|
|
|
|
shortcut_id_ = m->shortcut_id;
|
|
|
|
|
|
|
|
int32 flags = telegram_api::messages_sendMessage::QUICK_REPLY_SHORTCUT_MASK;
|
|
|
|
if (m->disable_web_page_preview) {
|
|
|
|
flags |= telegram_api::messages_sendMessage::NO_WEBPAGE_MASK;
|
|
|
|
}
|
|
|
|
if (m->invert_media) {
|
|
|
|
flags |= telegram_api::messages_sendMessage::INVERT_MEDIA_MASK;
|
|
|
|
}
|
|
|
|
auto reply_to =
|
|
|
|
MessageInputReplyTo(m->reply_to_message_id, DialogId(), Auto(), 0).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(m->content.get());
|
|
|
|
CHECK(message_text != nullptr);
|
|
|
|
auto entities = get_input_message_entities(td_->user_manager_.get(), message_text, "SendQuickReplyMessageQuery");
|
|
|
|
if (!entities.empty()) {
|
|
|
|
flags |= telegram_api::messages_sendMessage::ENTITIES_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
send_query(G()->net_query_creator().create(
|
|
|
|
telegram_api::messages_sendMessage(
|
|
|
|
flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
|
|
|
|
false /*ignored*/, false /*ignored*/, telegram_api::make_object<telegram_api::inputPeerSelf>(),
|
|
|
|
std::move(reply_to), message_text->text, m->random_id, nullptr, std::move(entities), 0, nullptr,
|
|
|
|
td_->quick_reply_manager_->get_input_quick_reply_shortcut(m->shortcut_id)),
|
|
|
|
{{"me"}}));
|
|
|
|
}
|
|
|
|
|
|
|
|
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 SendQuickReplyMessageQuery for " << random_id_ << ": " << to_string(ptr);
|
|
|
|
td_->quick_reply_manager_->process_send_quick_reply_updates(shortcut_id_, std::move(ptr), {random_id_});
|
|
|
|
}
|
|
|
|
|
|
|
|
void on_error(Status status) final {
|
|
|
|
LOG(INFO) << "Receive error for SendQuickReplyMessageQuery: " << status;
|
|
|
|
if (G()->close_flag()) {
|
|
|
|
// do not send error, message will be re-sent after restart
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
td_->quick_reply_manager_->on_failed_send_quick_reply_messages(shortcut_id_, {random_id_}, std::move(status));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class QuickReplyManager::SendQuickReplyMediaQuery final : public Td::ResultHandler {
|
|
|
|
int64 random_id_;
|
|
|
|
QuickReplyShortcutId shortcut_id_;
|
|
|
|
FileId file_id_;
|
|
|
|
FileId thumbnail_file_id_;
|
|
|
|
string file_reference_;
|
|
|
|
bool was_uploaded_ = false;
|
|
|
|
bool was_thumbnail_uploaded_ = false;
|
|
|
|
|
|
|
|
public:
|
|
|
|
void send(FileId file_id, FileId thumbnail_file_id, const QuickReplyMessage *m,
|
|
|
|
telegram_api::object_ptr<telegram_api::InputMedia> &&input_media) {
|
|
|
|
random_id_ = m->random_id;
|
|
|
|
shortcut_id_ = m->shortcut_id;
|
|
|
|
file_id_ = file_id;
|
|
|
|
thumbnail_file_id_ = thumbnail_file_id;
|
|
|
|
file_reference_ = FileManager::extract_file_reference(input_media);
|
|
|
|
was_uploaded_ = FileManager::extract_was_uploaded(input_media);
|
|
|
|
was_thumbnail_uploaded_ = FileManager::extract_was_thumbnail_uploaded(input_media);
|
|
|
|
|
|
|
|
int32 flags = telegram_api::messages_sendMedia::QUICK_REPLY_SHORTCUT_MASK;
|
|
|
|
if (m->invert_media) {
|
|
|
|
flags |= telegram_api::messages_sendMedia::INVERT_MEDIA_MASK;
|
|
|
|
}
|
|
|
|
auto reply_to =
|
|
|
|
MessageInputReplyTo(m->reply_to_message_id, DialogId(), Auto(), 0).get_input_reply_to(td_, MessageId());
|
|
|
|
if (reply_to != nullptr) {
|
|
|
|
flags |= telegram_api::messages_sendMedia::REPLY_TO_MASK;
|
|
|
|
}
|
|
|
|
vector<telegram_api::object_ptr<telegram_api::MessageEntity>> entities;
|
|
|
|
const FormattedText *message_text = get_message_content_text(m->content.get());
|
|
|
|
if (message_text != nullptr) {
|
|
|
|
entities = get_input_message_entities(td_->user_manager_.get(), message_text, "SendQuickReplyMessageQuery");
|
|
|
|
if (!entities.empty()) {
|
|
|
|
flags |= telegram_api::messages_sendMedia::ENTITIES_MASK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
send_query(G()->net_query_creator().create(
|
|
|
|
telegram_api::messages_sendMedia(
|
|
|
|
flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
|
|
|
|
false /*ignored*/, telegram_api::make_object<telegram_api::inputPeerSelf>(), std::move(reply_to),
|
|
|
|
std::move(input_media), message_text == nullptr ? string() : message_text->text, m->random_id, nullptr,
|
|
|
|
std::move(entities), 0, nullptr, td_->quick_reply_manager_->get_input_quick_reply_shortcut(m->shortcut_id)),
|
|
|
|
{{"me"}}));
|
|
|
|
}
|
|
|
|
|
|
|
|
void on_result(BufferSlice packet) final {
|
|
|
|
auto result_ptr = fetch_result<telegram_api::messages_sendMedia>(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 SendQuickReplyMediaQuery for " << random_id_ << ": " << to_string(ptr);
|
|
|
|
td_->quick_reply_manager_->process_send_quick_reply_updates(shortcut_id_, std::move(ptr), {random_id_});
|
|
|
|
}
|
|
|
|
|
|
|
|
void on_error(Status status) final {
|
|
|
|
LOG(INFO) << "Receive error for SendQuickReplyMediaQuery: " << status;
|
|
|
|
if (G()->close_flag()) {
|
|
|
|
// do not send error, message will be re-sent after restart
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
td_->quick_reply_manager_->on_failed_send_quick_reply_messages(shortcut_id_, {random_id_}, std::move(status));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-02-22 15:32:12 +01:00
|
|
|
QuickReplyManager::QuickReplyMessage::~QuickReplyMessage() = default;
|
|
|
|
|
2024-02-23 14:17:37 +01:00
|
|
|
template <class StorerT>
|
|
|
|
void QuickReplyManager::QuickReplyMessage::store(StorerT &storer) const {
|
|
|
|
bool is_server = message_id.is_server();
|
|
|
|
bool has_edit_date = edit_date != 0;
|
|
|
|
bool has_random_id = !is_server && random_id != 0;
|
|
|
|
bool has_reply_to_message_id = reply_to_message_id != MessageId();
|
|
|
|
bool has_send_emoji = !is_server && !send_emoji.empty();
|
|
|
|
bool has_via_bot_user_id = via_bot_user_id != UserId();
|
|
|
|
bool has_legacy_layer = legacy_layer != 0;
|
|
|
|
bool has_send_error_code = !is_server && send_error_code != 0;
|
|
|
|
bool has_send_error_message = !is_server && !send_error_message.empty();
|
|
|
|
bool has_try_resend_at = !is_server && try_resend_at != 0;
|
|
|
|
bool has_media_album_id = media_album_id != 0;
|
2024-03-06 13:56:50 +01:00
|
|
|
bool has_reply_markup = reply_markup != nullptr;
|
2024-02-23 14:17:37 +01:00
|
|
|
BEGIN_STORE_FLAGS();
|
|
|
|
STORE_FLAG(has_edit_date);
|
|
|
|
STORE_FLAG(has_random_id);
|
|
|
|
STORE_FLAG(has_reply_to_message_id);
|
|
|
|
STORE_FLAG(has_send_emoji);
|
|
|
|
STORE_FLAG(has_via_bot_user_id);
|
|
|
|
STORE_FLAG(is_failed_to_send);
|
|
|
|
STORE_FLAG(disable_notification);
|
|
|
|
STORE_FLAG(invert_media);
|
|
|
|
STORE_FLAG(from_background);
|
|
|
|
STORE_FLAG(disable_web_page_preview);
|
|
|
|
STORE_FLAG(hide_via_bot);
|
|
|
|
STORE_FLAG(has_legacy_layer);
|
|
|
|
STORE_FLAG(has_send_error_code);
|
|
|
|
STORE_FLAG(has_send_error_message);
|
|
|
|
STORE_FLAG(has_try_resend_at);
|
|
|
|
STORE_FLAG(has_media_album_id);
|
2024-03-06 13:56:50 +01:00
|
|
|
STORE_FLAG(has_reply_markup);
|
2024-02-23 14:17:37 +01:00
|
|
|
END_STORE_FLAGS();
|
|
|
|
td::store(message_id, storer);
|
|
|
|
td::store(shortcut_id, storer);
|
|
|
|
if (has_edit_date) {
|
|
|
|
td::store(edit_date, storer);
|
|
|
|
}
|
|
|
|
if (has_random_id) {
|
|
|
|
td::store(random_id, storer);
|
|
|
|
}
|
|
|
|
if (has_reply_to_message_id) {
|
|
|
|
td::store(reply_to_message_id, storer);
|
|
|
|
}
|
|
|
|
if (has_send_emoji) {
|
|
|
|
td::store(send_emoji, storer);
|
|
|
|
}
|
|
|
|
if (has_via_bot_user_id) {
|
|
|
|
td::store(via_bot_user_id, storer);
|
|
|
|
}
|
|
|
|
if (has_legacy_layer) {
|
|
|
|
td::store(legacy_layer, storer);
|
|
|
|
}
|
|
|
|
if (has_send_error_code) {
|
|
|
|
td::store(send_error_code, storer);
|
|
|
|
}
|
|
|
|
if (has_send_error_message) {
|
|
|
|
td::store(send_error_message, storer);
|
|
|
|
}
|
|
|
|
if (has_try_resend_at) {
|
|
|
|
td::store_time(try_resend_at, storer);
|
|
|
|
}
|
|
|
|
if (has_media_album_id) {
|
|
|
|
td::store(media_album_id, storer);
|
|
|
|
}
|
|
|
|
store_message_content(content.get(), storer);
|
2024-03-06 13:56:50 +01:00
|
|
|
if (has_reply_markup) {
|
|
|
|
td::store(reply_markup, storer);
|
|
|
|
}
|
2024-02-23 14:17:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class ParserT>
|
|
|
|
void QuickReplyManager::QuickReplyMessage::parse(ParserT &parser) {
|
|
|
|
bool has_edit_date;
|
|
|
|
bool has_random_id;
|
|
|
|
bool has_reply_to_message_id;
|
|
|
|
bool has_send_emoji;
|
|
|
|
bool has_via_bot_user_id;
|
|
|
|
bool has_legacy_layer;
|
|
|
|
bool has_send_error_code;
|
|
|
|
bool has_send_error_message;
|
|
|
|
bool has_try_resend_at;
|
|
|
|
bool has_media_album_id;
|
2024-03-06 13:56:50 +01:00
|
|
|
bool has_reply_markup;
|
2024-02-23 14:17:37 +01:00
|
|
|
BEGIN_PARSE_FLAGS();
|
|
|
|
PARSE_FLAG(has_edit_date);
|
|
|
|
PARSE_FLAG(has_random_id);
|
|
|
|
PARSE_FLAG(has_reply_to_message_id);
|
|
|
|
PARSE_FLAG(has_send_emoji);
|
|
|
|
PARSE_FLAG(has_via_bot_user_id);
|
|
|
|
PARSE_FLAG(is_failed_to_send);
|
|
|
|
PARSE_FLAG(disable_notification);
|
|
|
|
PARSE_FLAG(invert_media);
|
|
|
|
PARSE_FLAG(from_background);
|
|
|
|
PARSE_FLAG(disable_web_page_preview);
|
|
|
|
PARSE_FLAG(hide_via_bot);
|
|
|
|
PARSE_FLAG(has_legacy_layer);
|
|
|
|
PARSE_FLAG(has_send_error_code);
|
|
|
|
PARSE_FLAG(has_send_error_message);
|
|
|
|
PARSE_FLAG(has_try_resend_at);
|
|
|
|
PARSE_FLAG(has_media_album_id);
|
2024-03-06 13:56:50 +01:00
|
|
|
PARSE_FLAG(has_reply_markup);
|
2024-02-23 14:17:37 +01:00
|
|
|
END_PARSE_FLAGS();
|
|
|
|
td::parse(message_id, parser);
|
|
|
|
td::parse(shortcut_id, parser);
|
|
|
|
if (has_edit_date) {
|
|
|
|
td::parse(edit_date, parser);
|
|
|
|
}
|
|
|
|
if (has_random_id) {
|
|
|
|
td::parse(random_id, parser);
|
|
|
|
}
|
|
|
|
if (has_reply_to_message_id) {
|
|
|
|
td::parse(reply_to_message_id, parser);
|
|
|
|
}
|
|
|
|
if (has_send_emoji) {
|
|
|
|
td::parse(send_emoji, parser);
|
|
|
|
}
|
|
|
|
if (has_via_bot_user_id) {
|
|
|
|
td::parse(via_bot_user_id, parser);
|
|
|
|
}
|
|
|
|
if (has_legacy_layer) {
|
|
|
|
td::parse(legacy_layer, parser);
|
|
|
|
}
|
|
|
|
if (has_send_error_code) {
|
|
|
|
td::parse(send_error_code, parser);
|
|
|
|
}
|
|
|
|
if (has_send_error_message) {
|
|
|
|
td::parse(send_error_message, parser);
|
|
|
|
}
|
|
|
|
if (has_try_resend_at) {
|
|
|
|
td::parse_time(try_resend_at, parser);
|
|
|
|
}
|
|
|
|
if (has_media_album_id) {
|
|
|
|
td::parse(media_album_id, parser);
|
|
|
|
}
|
|
|
|
parse_message_content(content, parser);
|
2024-03-06 13:56:50 +01:00
|
|
|
if (has_reply_markup) {
|
|
|
|
td::parse(reply_markup, parser);
|
|
|
|
}
|
2024-02-23 14:17:37 +01:00
|
|
|
}
|
|
|
|
|
2024-02-22 15:32:12 +01:00
|
|
|
QuickReplyManager::Shortcut::~Shortcut() = default;
|
|
|
|
|
2024-02-23 14:17:37 +01:00
|
|
|
template <class StorerT>
|
|
|
|
void QuickReplyManager::Shortcut::store(StorerT &storer) const {
|
2024-03-05 11:42:21 +01:00
|
|
|
int32 server_total_count = 0;
|
|
|
|
int32 local_total_count = 0;
|
|
|
|
for (const auto &message : messages_) {
|
|
|
|
if (message->message_id.is_server()) {
|
|
|
|
server_total_count++;
|
2024-04-17 17:39:25 +02:00
|
|
|
} else {
|
2024-03-05 11:42:21 +01:00
|
|
|
local_total_count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CHECK(server_total_count <= server_total_count_);
|
|
|
|
CHECK(local_total_count <= local_total_count_);
|
|
|
|
|
|
|
|
bool has_server_total_count = server_total_count != 0;
|
|
|
|
bool has_local_total_count = local_total_count != 0;
|
2024-02-23 14:17:37 +01:00
|
|
|
BEGIN_STORE_FLAGS();
|
|
|
|
STORE_FLAG(has_server_total_count);
|
|
|
|
STORE_FLAG(has_local_total_count);
|
|
|
|
END_STORE_FLAGS();
|
|
|
|
td::store(name_, storer);
|
|
|
|
td::store(shortcut_id_, storer);
|
|
|
|
if (has_server_total_count) {
|
2024-03-05 11:42:21 +01:00
|
|
|
td::store(server_total_count, storer);
|
2024-02-23 14:17:37 +01:00
|
|
|
}
|
|
|
|
if (has_local_total_count) {
|
2024-03-05 11:42:21 +01:00
|
|
|
td::store(local_total_count, storer);
|
|
|
|
}
|
|
|
|
for (const auto &message : messages_) {
|
2024-04-17 17:39:25 +02:00
|
|
|
td::store(message, storer);
|
2024-02-23 14:17:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class ParserT>
|
|
|
|
void QuickReplyManager::Shortcut::parse(ParserT &parser) {
|
|
|
|
bool has_server_total_count;
|
|
|
|
bool has_local_total_count;
|
|
|
|
BEGIN_PARSE_FLAGS();
|
|
|
|
PARSE_FLAG(has_server_total_count);
|
|
|
|
PARSE_FLAG(has_local_total_count);
|
|
|
|
END_PARSE_FLAGS();
|
|
|
|
td::parse(name_, parser);
|
|
|
|
td::parse(shortcut_id_, parser);
|
|
|
|
if (has_server_total_count) {
|
|
|
|
td::parse(server_total_count_, parser);
|
|
|
|
}
|
|
|
|
if (has_local_total_count) {
|
|
|
|
td::parse(local_total_count_, parser);
|
|
|
|
}
|
2024-03-05 11:42:21 +01:00
|
|
|
if (server_total_count_ < 0 || local_total_count_ < 0) {
|
|
|
|
return parser.set_error("Wrong message count");
|
|
|
|
}
|
|
|
|
auto size = static_cast<size_t>(server_total_count_) + static_cast<size_t>(local_total_count_);
|
|
|
|
if (parser.get_left_len() < size) {
|
|
|
|
return parser.set_error("Wrong message count");
|
|
|
|
}
|
|
|
|
messages_ = vector<unique_ptr<QuickReplyMessage>>(size);
|
|
|
|
for (auto &message : messages_) {
|
|
|
|
td::parse(message, parser);
|
|
|
|
}
|
2024-02-23 14:17:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class StorerT>
|
|
|
|
void QuickReplyManager::Shortcuts::store(StorerT &storer) const {
|
|
|
|
BEGIN_STORE_FLAGS();
|
|
|
|
END_STORE_FLAGS();
|
|
|
|
td::store(shortcuts_, storer);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class ParserT>
|
|
|
|
void QuickReplyManager::Shortcuts::parse(ParserT &parser) {
|
|
|
|
BEGIN_PARSE_FLAGS();
|
|
|
|
END_PARSE_FLAGS();
|
|
|
|
td::parse(shortcuts_, parser);
|
|
|
|
}
|
|
|
|
|
2024-02-21 18:43:55 +01:00
|
|
|
QuickReplyManager::QuickReplyManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::tear_down() {
|
|
|
|
parent_.reset();
|
|
|
|
}
|
|
|
|
|
2024-03-04 12:34:47 +01:00
|
|
|
bool QuickReplyManager::is_shortcut_name_letter(uint32 code) {
|
|
|
|
auto category = get_unicode_simple_category(code);
|
|
|
|
if (code == '_' || code == 0x200c || code == 0xb7 || (0xd80 <= code && code <= 0xdff)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
switch (category) {
|
|
|
|
case UnicodeSimpleCategory::DecimalNumber:
|
|
|
|
case UnicodeSimpleCategory::Letter:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Status QuickReplyManager::check_shortcut_name(CSlice name) {
|
|
|
|
if (!check_utf8(name)) {
|
|
|
|
return Status::Error("Strings must be encoded in UTF-8");
|
|
|
|
}
|
|
|
|
int32 length = 0;
|
|
|
|
auto *ptr = name.ubegin();
|
|
|
|
while (ptr != name.uend()) {
|
|
|
|
uint32 code;
|
|
|
|
ptr = next_utf8_unsafe(ptr, &code);
|
|
|
|
if (!is_shortcut_name_letter(code)) {
|
|
|
|
return Status::Error("A letter is not allowed");
|
|
|
|
}
|
|
|
|
length++;
|
|
|
|
}
|
|
|
|
if (length == 0) {
|
2024-03-07 12:09:31 +01:00
|
|
|
return Status::Error("Name must be non-empty");
|
2024-03-04 12:34:47 +01:00
|
|
|
}
|
|
|
|
if (length > 32) {
|
|
|
|
return Status::Error("Name is too long");
|
|
|
|
}
|
|
|
|
return Status::OK();
|
|
|
|
}
|
|
|
|
|
2024-02-21 20:06:07 +01:00
|
|
|
unique_ptr<QuickReplyManager::QuickReplyMessage> QuickReplyManager::create_message(
|
|
|
|
telegram_api::object_ptr<telegram_api::Message> message_ptr, const char *source) const {
|
|
|
|
LOG(DEBUG) << "Receive from " << source << " " << to_string(message_ptr);
|
|
|
|
CHECK(message_ptr != nullptr);
|
|
|
|
|
|
|
|
switch (message_ptr->get_id()) {
|
|
|
|
case telegram_api::messageEmpty::ID:
|
|
|
|
break;
|
|
|
|
case telegram_api::message::ID: {
|
2024-02-22 15:32:12 +01:00
|
|
|
auto message_id = MessageId::get_message_id(message_ptr, false);
|
2024-02-21 20:06:07 +01:00
|
|
|
auto message = move_tl_object_as<telegram_api::message>(message_ptr);
|
2024-02-29 14:39:38 +01:00
|
|
|
auto shortcut_id = QuickReplyShortcutId(message->quick_reply_shortcut_id_);
|
|
|
|
if (!shortcut_id.is_server()) {
|
|
|
|
LOG(ERROR) << "Receive invalid quick reply " << shortcut_id << " from " << source;
|
2024-02-21 20:06:07 +01:00
|
|
|
break;
|
|
|
|
}
|
2024-02-29 15:27:12 +01:00
|
|
|
if (deleted_message_full_ids_.count({shortcut_id, message_id})) {
|
|
|
|
// a previously deleted message
|
|
|
|
break;
|
|
|
|
}
|
2024-02-21 20:06:07 +01:00
|
|
|
|
|
|
|
auto my_dialog_id = td_->dialog_manager_->get_my_dialog_id();
|
2024-02-22 15:32:12 +01:00
|
|
|
if (DialogId(message->peer_id_) != my_dialog_id || message->from_id_ != nullptr ||
|
2024-03-04 20:30:24 +01:00
|
|
|
message->fwd_from_ != nullptr || message->views_ != 0 || message->forwards_ != 0 ||
|
|
|
|
message->replies_ != nullptr || message->reactions_ != nullptr || message->ttl_period_ != 0 ||
|
2024-03-05 12:25:09 +01:00
|
|
|
!message->out_ || message->post_ || message->from_scheduled_ || message->pinned_ || message->noforwards_ ||
|
2024-03-06 13:56:50 +01:00
|
|
|
message->mentioned_ || message->media_unread_ || !message->restriction_reason_.empty() ||
|
|
|
|
!message->post_author_.empty() || message->from_boosts_applied_ != 0) {
|
2024-02-21 20:06:07 +01:00
|
|
|
LOG(ERROR) << "Receive an invalid quick reply from " << source << ": " << to_string(message);
|
|
|
|
}
|
2024-03-04 20:30:24 +01:00
|
|
|
if (message->saved_peer_id_ != nullptr) {
|
|
|
|
LOG(DEBUG) << "Receive unneeded Saved Messages topic in quick reply " << message_id << " from " << source;
|
|
|
|
}
|
2024-02-21 20:06:07 +01:00
|
|
|
|
|
|
|
UserId via_bot_user_id;
|
|
|
|
if (message->flags_ & telegram_api::message::VIA_BOT_ID_MASK) {
|
|
|
|
via_bot_user_id = UserId(message->via_bot_id_);
|
|
|
|
if (!via_bot_user_id.is_valid()) {
|
|
|
|
LOG(ERROR) << "Receive invalid " << via_bot_user_id << " from " << source;
|
|
|
|
via_bot_user_id = UserId();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
auto media_album_id = message->grouped_id_;
|
|
|
|
|
|
|
|
MessageSelfDestructType ttl;
|
|
|
|
bool disable_web_page_preview = false;
|
|
|
|
auto content = get_message_content(
|
|
|
|
td_,
|
2024-04-02 02:52:34 +02:00
|
|
|
get_message_text(td_->user_manager_.get(), std::move(message->message_), std::move(message->entities_), true,
|
|
|
|
td_->auth_manager_->is_bot(), 0, media_album_id != 0, source),
|
2024-02-21 20:06:07 +01:00
|
|
|
std::move(message->media_), my_dialog_id, message->date_, true, via_bot_user_id, &ttl,
|
|
|
|
&disable_web_page_preview, source);
|
|
|
|
|
|
|
|
auto reply_header = MessageReplyHeader(td_, std::move(message->reply_to_), my_dialog_id, message_id, -1, false);
|
|
|
|
if (reply_header.story_full_id_ != StoryFullId()) {
|
|
|
|
LOG(ERROR) << "Receive reply to " << reply_header.story_full_id_;
|
|
|
|
reply_header.story_full_id_ = {};
|
|
|
|
}
|
2024-02-21 20:27:46 +01:00
|
|
|
if (reply_header.replied_message_info_.is_external() ||
|
|
|
|
reply_header.replied_message_info_.get_reply_message_full_id(DialogId(), true).get_dialog_id() !=
|
|
|
|
DialogId()) {
|
|
|
|
LOG(ERROR) << "Receive reply to " << reply_header.replied_message_info_;
|
|
|
|
reply_header.replied_message_info_ = {};
|
|
|
|
}
|
|
|
|
auto reply_to_message_id = reply_header.replied_message_info_.get_same_chat_reply_to_message_id(true);
|
2024-02-21 20:06:07 +01:00
|
|
|
|
|
|
|
if (!ttl.is_empty()) {
|
2024-02-21 22:48:05 +01:00
|
|
|
LOG(ERROR) << "Wrong " << ttl << " received in " << message_id << " from " << source;
|
2024-02-22 19:40:07 +01:00
|
|
|
break;
|
2024-02-21 20:06:07 +01:00
|
|
|
}
|
|
|
|
|
2024-02-21 22:48:05 +01:00
|
|
|
auto content_type = content->get_type();
|
2024-03-05 14:41:10 +01:00
|
|
|
if (is_service_message_content(content_type) || content_type == MessageContentType::LiveLocation ||
|
|
|
|
is_expired_message_content(content_type)) {
|
2024-02-21 20:06:07 +01:00
|
|
|
LOG(ERROR) << "Receive " << content_type << " from " << source;
|
2024-02-22 19:40:07 +01:00
|
|
|
break;
|
2024-02-21 20:06:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
auto result = make_unique<QuickReplyMessage>();
|
2024-02-29 14:39:38 +01:00
|
|
|
result->shortcut_id = shortcut_id;
|
2024-02-21 20:06:07 +01:00
|
|
|
result->message_id = message_id;
|
2024-02-22 19:40:07 +01:00
|
|
|
result->edit_date = max(message->edit_date_, 0);
|
2024-02-21 20:06:07 +01:00
|
|
|
result->disable_web_page_preview = disable_web_page_preview;
|
2024-02-21 20:27:46 +01:00
|
|
|
result->reply_to_message_id = reply_to_message_id;
|
2024-02-21 20:06:07 +01:00
|
|
|
result->via_bot_user_id = via_bot_user_id;
|
|
|
|
result->disable_notification = message->silent_;
|
|
|
|
result->legacy_layer = (message->legacy_ ? MTPROTO_LAYER : 0);
|
|
|
|
result->invert_media = message->invert_media_;
|
|
|
|
result->content = std::move(content);
|
2024-03-06 13:56:50 +01:00
|
|
|
result->reply_markup =
|
|
|
|
get_reply_markup(std::move(message->reply_markup_), td_->auth_manager_->is_bot(), true, false);
|
2024-02-21 20:06:07 +01:00
|
|
|
|
|
|
|
if (media_album_id != 0) {
|
|
|
|
if (!is_allowed_media_group_content(content_type)) {
|
|
|
|
if (content_type != MessageContentType::Unsupported) {
|
|
|
|
LOG(ERROR) << "Receive media group identifier " << media_album_id << " in " << message_id
|
|
|
|
<< " with content "
|
|
|
|
<< oneline(to_string(get_quick_reply_message_message_content_object(result.get())));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
result->media_album_id = media_album_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Dependencies dependencies;
|
|
|
|
add_quick_reply_message_dependencies(dependencies, result.get());
|
|
|
|
for (auto dependent_dialog_id : dependencies.get_dialog_ids()) {
|
|
|
|
td_->dialog_manager_->force_create_dialog(dependent_dialog_id, source, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
case telegram_api::messageService::ID:
|
|
|
|
LOG(ERROR) << "Receive " << to_string(message_ptr);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2024-02-21 20:27:46 +01:00
|
|
|
void QuickReplyManager::add_quick_reply_message_dependencies(Dependencies &dependencies,
|
|
|
|
const QuickReplyMessage *m) const {
|
2024-02-21 20:06:07 +01:00
|
|
|
auto is_bot = td_->auth_manager_->is_bot();
|
|
|
|
dependencies.add(m->via_bot_user_id);
|
|
|
|
add_message_content_dependencies(dependencies, m->content.get(), is_bot);
|
2024-03-06 13:56:50 +01:00
|
|
|
add_reply_markup_dependencies(dependencies, m->reply_markup.get());
|
2024-02-21 20:06:07 +01:00
|
|
|
}
|
|
|
|
|
2024-02-23 18:22:33 +01:00
|
|
|
bool QuickReplyManager::can_edit_quick_reply_message(const QuickReplyMessage *m) const {
|
2024-02-27 18:52:59 +01:00
|
|
|
return m->message_id.is_server() && !m->via_bot_user_id.is_valid() &&
|
2024-02-23 18:22:33 +01:00
|
|
|
is_editable_message_content(m->content->get_type());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QuickReplyManager::can_resend_quick_reply_message(const QuickReplyMessage *m) const {
|
2024-02-21 20:43:29 +01:00
|
|
|
if (m->send_error_code != 429) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (m->via_bot_user_id.is_valid() || m->hide_via_bot) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
td_api::object_ptr<td_api::MessageSendingState> QuickReplyManager::get_message_sending_state_object(
|
|
|
|
const QuickReplyMessage *m) const {
|
|
|
|
CHECK(m != nullptr);
|
|
|
|
if (m->message_id.is_yet_unsent()) {
|
2024-04-15 23:53:48 +02:00
|
|
|
return td_api::make_object<td_api::messageSendingStatePending>(0);
|
2024-02-21 20:43:29 +01:00
|
|
|
}
|
|
|
|
if (m->is_failed_to_send) {
|
2024-02-23 18:22:33 +01:00
|
|
|
auto can_retry = can_resend_quick_reply_message(m);
|
2024-02-21 20:43:29 +01:00
|
|
|
auto error_code = m->send_error_code > 0 ? m->send_error_code : 400;
|
|
|
|
auto need_another_reply_quote =
|
|
|
|
can_retry && error_code == 400 && m->send_error_message == CSlice("QUOTE_TEXT_INVALID");
|
|
|
|
return td_api::make_object<td_api::messageSendingStateFailed>(
|
|
|
|
td_api::make_object<td_api::error>(error_code, m->send_error_message), can_retry, false,
|
|
|
|
need_another_reply_quote, false, max(m->try_resend_at - Time::now(), 0.0));
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
td_api::object_ptr<td_api::MessageContent> QuickReplyManager::get_quick_reply_message_message_content_object(
|
|
|
|
const QuickReplyMessage *m) const {
|
2024-02-21 22:48:05 +01:00
|
|
|
return get_message_content_object(m->content.get(), td_, DialogId(), 0, false, true, -1, m->invert_media,
|
|
|
|
m->disable_web_page_preview);
|
2024-02-21 20:43:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
td_api::object_ptr<td_api::quickReplyMessage> QuickReplyManager::get_quick_reply_message_object(
|
|
|
|
const QuickReplyMessage *m, const char *source) const {
|
|
|
|
CHECK(m != nullptr);
|
2024-02-23 18:22:33 +01:00
|
|
|
auto can_be_edited = can_edit_quick_reply_message(m);
|
2024-02-21 20:43:29 +01:00
|
|
|
return td_api::make_object<td_api::quickReplyMessage>(
|
2024-02-27 18:52:59 +01:00
|
|
|
m->message_id.get(), get_message_sending_state_object(m), can_be_edited, m->reply_to_message_id.get(),
|
2024-04-02 02:52:34 +02:00
|
|
|
td_->user_manager_->get_user_id_object(m->via_bot_user_id, "via_bot_user_id"), m->media_album_id,
|
2024-03-06 13:56:50 +01:00
|
|
|
get_quick_reply_message_message_content_object(m),
|
2024-04-02 02:52:34 +02:00
|
|
|
get_reply_markup_object(td_->user_manager_.get(), m->reply_markup));
|
2024-02-21 20:43:29 +01:00
|
|
|
}
|
|
|
|
|
2024-02-22 17:45:49 +01:00
|
|
|
int32 QuickReplyManager::get_shortcut_message_count(const Shortcut *s) {
|
2024-02-29 13:55:38 +01:00
|
|
|
return s->server_total_count_ + s->local_total_count_;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QuickReplyManager::have_all_shortcut_messages(const Shortcut *s) {
|
|
|
|
return static_cast<int32>(s->messages_.size()) == get_shortcut_message_count(s);
|
2024-02-22 17:45:49 +01:00
|
|
|
}
|
|
|
|
|
2024-02-22 15:32:12 +01:00
|
|
|
td_api::object_ptr<td_api::quickReplyShortcut> QuickReplyManager::get_quick_reply_shortcut_object(
|
|
|
|
const Shortcut *s, const char *source) const {
|
|
|
|
CHECK(s != nullptr);
|
|
|
|
CHECK(!s->messages_.empty());
|
2024-02-26 16:18:53 +01:00
|
|
|
return td_api::make_object<td_api::quickReplyShortcut>(s->shortcut_id_.get(), s->name_,
|
|
|
|
get_quick_reply_message_object(s->messages_[0].get(), source),
|
|
|
|
get_shortcut_message_count(s));
|
2024-02-22 15:32:12 +01:00
|
|
|
}
|
|
|
|
|
2024-02-22 21:04:36 +01:00
|
|
|
void QuickReplyManager::get_quick_reply_shortcuts(Promise<Unit> &&promise) {
|
2024-03-05 13:30:57 +01:00
|
|
|
load_quick_reply_shortcuts();
|
2024-02-22 15:32:12 +01:00
|
|
|
if (shortcuts_.are_inited_) {
|
2024-02-22 21:04:36 +01:00
|
|
|
return promise.set_value(Unit());
|
2024-02-22 15:32:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
shortcuts_.load_queries_.push_back(std::move(promise));
|
|
|
|
if (shortcuts_.load_queries_.size() != 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
reload_quick_reply_shortcuts();
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::reload_quick_reply_shortcuts() {
|
2024-03-05 15:58:40 +01:00
|
|
|
if (td_->auth_manager_->is_bot()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-05 14:25:39 +01:00
|
|
|
load_quick_reply_shortcuts();
|
2024-02-22 15:32:12 +01:00
|
|
|
auto promise = PromiseCreator::lambda(
|
|
|
|
[actor_id = actor_id(this)](Result<telegram_api::object_ptr<telegram_api::messages_QuickReplies>> r_shortcuts) {
|
|
|
|
send_closure(actor_id, &QuickReplyManager::on_reload_quick_reply_shortcuts, std::move(r_shortcuts));
|
|
|
|
});
|
2024-02-23 12:49:29 +01:00
|
|
|
td_->create_handler<GetQuickRepliesQuery>(std::move(promise))->send(get_shortcuts_hash());
|
2024-02-22 15:32:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::on_reload_quick_reply_shortcuts(
|
|
|
|
Result<telegram_api::object_ptr<telegram_api::messages_QuickReplies>> r_shortcuts) {
|
|
|
|
G()->ignore_result_if_closing(r_shortcuts);
|
|
|
|
if (r_shortcuts.is_error()) {
|
|
|
|
return on_load_quick_reply_fail(r_shortcuts.move_as_error());
|
|
|
|
}
|
|
|
|
auto shortcuts_ptr = r_shortcuts.move_as_ok();
|
|
|
|
switch (shortcuts_ptr->get_id()) {
|
|
|
|
case telegram_api::messages_quickRepliesNotModified::ID:
|
|
|
|
if (!shortcuts_.are_inited_) {
|
|
|
|
shortcuts_.are_inited_ = true;
|
2024-02-27 21:47:29 +01:00
|
|
|
save_quick_reply_shortcuts();
|
2024-02-22 20:55:09 +01:00
|
|
|
send_update_quick_reply_shortcuts();
|
2024-02-22 15:32:12 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case telegram_api::messages_quickReplies::ID: {
|
|
|
|
auto shortcuts = telegram_api::move_object_as<telegram_api::messages_quickReplies>(shortcuts_ptr);
|
2024-04-02 02:52:34 +02:00
|
|
|
td_->user_manager_->on_get_users(std::move(shortcuts->users_), "messages.quickReplies");
|
2024-04-02 12:06:22 +02:00
|
|
|
td_->chat_manager_->on_get_chats(std::move(shortcuts->chats_), "messages.quickReplies");
|
2024-02-22 15:32:12 +01:00
|
|
|
|
|
|
|
FlatHashMap<MessageId, telegram_api::object_ptr<telegram_api::Message>, MessageIdHash> message_id_to_message;
|
|
|
|
for (auto &message : shortcuts->messages_) {
|
|
|
|
auto message_id = MessageId::get_message_id(message, false);
|
|
|
|
if (!message_id.is_valid()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
message_id_to_message[message_id] = std::move(message);
|
|
|
|
}
|
|
|
|
|
2024-02-24 01:16:56 +01:00
|
|
|
FlatHashSet<QuickReplyShortcutId, QuickReplyShortcutIdHash> old_shortcut_ids;
|
2024-02-22 19:23:19 +01:00
|
|
|
for (auto &shortcut : shortcuts_.shortcuts_) {
|
|
|
|
old_shortcut_ids.insert(shortcut->shortcut_id_);
|
|
|
|
}
|
2024-02-24 01:16:56 +01:00
|
|
|
FlatHashSet<QuickReplyShortcutId, QuickReplyShortcutIdHash> added_shortcut_ids;
|
2024-02-22 15:32:12 +01:00
|
|
|
FlatHashSet<string> added_shortcut_names;
|
|
|
|
vector<unique_ptr<Shortcut>> new_shortcuts;
|
2024-02-24 01:16:56 +01:00
|
|
|
vector<QuickReplyShortcutId> changed_shortcut_ids;
|
2024-02-29 13:55:38 +01:00
|
|
|
vector<QuickReplyShortcutId> changed_message_shortcut_ids;
|
2024-02-24 01:16:56 +01:00
|
|
|
vector<QuickReplyShortcutId> deleted_shortcut_ids;
|
2024-02-22 15:32:12 +01:00
|
|
|
for (auto &quick_reply : shortcuts->quick_replies_) {
|
2024-02-24 01:16:56 +01:00
|
|
|
auto shortcut_id = QuickReplyShortcutId(quick_reply->shortcut_id_);
|
2024-02-24 01:28:55 +01:00
|
|
|
if (!shortcut_id.is_server() || quick_reply->shortcut_.empty() || quick_reply->count_ <= 0 ||
|
2024-02-22 15:32:12 +01:00
|
|
|
quick_reply->top_message_ <= 0) {
|
|
|
|
LOG(ERROR) << "Receive " << to_string(quick_reply);
|
|
|
|
continue;
|
|
|
|
}
|
2024-02-24 01:16:56 +01:00
|
|
|
if (added_shortcut_ids.count(shortcut_id) || added_shortcut_names.count(quick_reply->shortcut_)) {
|
2024-02-22 15:32:12 +01:00
|
|
|
LOG(ERROR) << "Receive duplicate " << to_string(quick_reply);
|
|
|
|
continue;
|
|
|
|
}
|
2024-02-24 01:16:56 +01:00
|
|
|
if (deleted_shortcut_ids_.count(shortcut_id)) {
|
2024-02-24 01:06:20 +01:00
|
|
|
continue;
|
|
|
|
}
|
2024-02-24 01:16:56 +01:00
|
|
|
added_shortcut_ids.insert(shortcut_id);
|
2024-02-22 15:32:12 +01:00
|
|
|
added_shortcut_names.insert(quick_reply->shortcut_);
|
|
|
|
|
|
|
|
MessageId first_message_id(ServerMessageId(quick_reply->top_message_));
|
|
|
|
auto it = message_id_to_message.find(first_message_id);
|
|
|
|
if (it == message_id_to_message.end()) {
|
2024-02-24 01:16:56 +01:00
|
|
|
LOG(ERROR) << "Can't find last " << first_message_id << " in " << shortcut_id;
|
2024-02-22 15:32:12 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
auto message = create_message(std::move(it->second), "on_reload_quick_reply_shortcuts");
|
|
|
|
message_id_to_message.erase(it);
|
|
|
|
if (message == nullptr) {
|
|
|
|
continue;
|
|
|
|
}
|
2024-02-24 01:16:56 +01:00
|
|
|
if (message->shortcut_id != shortcut_id) {
|
|
|
|
LOG(ERROR) << "Receive message from " << message->shortcut_id << " instead of " << shortcut_id;
|
2024-02-24 01:06:20 +01:00
|
|
|
continue;
|
2024-02-22 15:32:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
auto shortcut = td::make_unique<Shortcut>();
|
|
|
|
shortcut->name_ = std::move(quick_reply->shortcut_);
|
2024-02-24 01:16:56 +01:00
|
|
|
shortcut->shortcut_id_ = shortcut_id;
|
2024-02-22 21:08:38 +01:00
|
|
|
shortcut->server_total_count_ = quick_reply->count_;
|
2024-02-22 15:32:12 +01:00
|
|
|
shortcut->messages_.push_back(std::move(message));
|
2024-02-22 17:45:49 +01:00
|
|
|
|
2024-02-24 01:16:56 +01:00
|
|
|
auto old_shortcut = get_shortcut(shortcut_id);
|
2024-02-29 19:05:56 +01:00
|
|
|
if (old_shortcut == nullptr) {
|
|
|
|
changed_shortcut_ids.push_back(shortcut_id);
|
2024-02-29 13:55:38 +01:00
|
|
|
changed_message_shortcut_ids.push_back(shortcut_id);
|
2024-02-29 19:05:56 +01:00
|
|
|
change_message_files({shortcut_id, first_message_id}, shortcut->messages_[0].get(), {});
|
|
|
|
} else {
|
2024-03-05 16:12:05 +01:00
|
|
|
bool is_shortcut_changed = false;
|
|
|
|
bool are_messages_changed = false;
|
|
|
|
update_shortcut_from(shortcut.get(), old_shortcut, true, &is_shortcut_changed, &are_messages_changed);
|
|
|
|
if (are_messages_changed) {
|
2024-02-29 19:05:56 +01:00
|
|
|
changed_message_shortcut_ids.push_back(shortcut_id);
|
|
|
|
}
|
2024-03-05 16:12:05 +01:00
|
|
|
if (is_shortcut_changed) {
|
2024-03-05 12:41:35 +01:00
|
|
|
changed_shortcut_ids.push_back(shortcut_id);
|
|
|
|
}
|
2024-02-29 19:05:56 +01:00
|
|
|
old_shortcut_ids.erase(shortcut_id);
|
2024-02-22 17:45:49 +01:00
|
|
|
}
|
|
|
|
|
2024-02-22 15:32:12 +01:00
|
|
|
new_shortcuts.push_back(std::move(shortcut));
|
|
|
|
}
|
2024-02-22 19:23:19 +01:00
|
|
|
for (auto shortcut_id : old_shortcut_ids) {
|
|
|
|
auto old_shortcut = get_shortcut(shortcut_id);
|
|
|
|
CHECK(old_shortcut != nullptr);
|
2024-02-29 17:01:40 +01:00
|
|
|
auto is_changed = td::remove_if(old_shortcut->messages_, [&](const unique_ptr<QuickReplyMessage> &message) {
|
|
|
|
if (message->message_id.is_server()) {
|
|
|
|
delete_message_files(shortcut_id, message.get());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2024-02-22 19:23:19 +01:00
|
|
|
});
|
|
|
|
if (old_shortcut->messages_.empty()) {
|
|
|
|
CHECK(is_changed);
|
|
|
|
send_update_quick_reply_shortcut_deleted(old_shortcut);
|
|
|
|
} else {
|
2024-03-07 13:24:28 +01:00
|
|
|
// some local messages left
|
2024-02-26 11:48:19 +01:00
|
|
|
if (added_shortcut_names.count(old_shortcut->name_)) {
|
2024-02-29 19:05:56 +01:00
|
|
|
LOG(INFO) << "Local shortcut " << old_shortcut->name_ << " has been created server-side";
|
2024-02-26 11:48:19 +01:00
|
|
|
for (auto &shortcut : new_shortcuts) {
|
|
|
|
if (shortcut->name_ == old_shortcut->name_) {
|
2024-02-29 19:05:56 +01:00
|
|
|
LOG(INFO) << "Move local messages from " << old_shortcut->shortcut_id_ << " to "
|
|
|
|
<< shortcut->shortcut_id_;
|
2024-02-26 11:48:19 +01:00
|
|
|
CHECK(shortcut->local_total_count_ == 0);
|
|
|
|
shortcut->local_total_count_ = static_cast<int32>(old_shortcut->messages_.size());
|
|
|
|
append(shortcut->messages_, std::move(old_shortcut->messages_));
|
|
|
|
sort_quick_reply_messages(shortcut->messages_);
|
|
|
|
send_update_quick_reply_shortcut_deleted(old_shortcut);
|
2024-02-29 13:55:38 +01:00
|
|
|
changed_shortcut_ids.push_back(shortcut->shortcut_id_);
|
|
|
|
changed_message_shortcut_ids.push_back(shortcut->shortcut_id_);
|
2024-03-05 12:17:18 +01:00
|
|
|
break;
|
2024-02-26 11:48:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2024-02-29 19:05:56 +01:00
|
|
|
LOG(INFO) << "Keep local shortcut " << old_shortcut->name_;
|
2024-02-22 19:23:19 +01:00
|
|
|
auto shortcut = td::make_unique<Shortcut>();
|
|
|
|
shortcut->name_ = std::move(old_shortcut->name_);
|
|
|
|
shortcut->shortcut_id_ = old_shortcut->shortcut_id_;
|
2024-02-22 21:08:38 +01:00
|
|
|
shortcut->server_total_count_ = 0;
|
|
|
|
shortcut->local_total_count_ = static_cast<int32>(old_shortcut->messages_.size());
|
2024-02-22 19:23:19 +01:00
|
|
|
shortcut->messages_ = std::move(old_shortcut->messages_);
|
|
|
|
if (is_changed) {
|
2024-02-29 13:55:38 +01:00
|
|
|
changed_shortcut_ids.push_back(shortcut->shortcut_id_);
|
|
|
|
changed_message_shortcut_ids.push_back(shortcut->shortcut_id_);
|
2024-02-22 19:23:19 +01:00
|
|
|
}
|
|
|
|
new_shortcuts.push_back(std::move(shortcut));
|
|
|
|
}
|
|
|
|
}
|
2024-02-24 12:22:01 +01:00
|
|
|
bool is_list_changed = is_shortcut_list_changed(new_shortcuts);
|
2024-02-22 15:32:12 +01:00
|
|
|
shortcuts_.shortcuts_ = std::move(new_shortcuts);
|
|
|
|
shortcuts_.are_inited_ = true;
|
2024-02-22 19:23:19 +01:00
|
|
|
|
2024-02-27 21:47:29 +01:00
|
|
|
save_quick_reply_shortcuts();
|
2024-02-22 19:23:19 +01:00
|
|
|
for (auto shortcut_id : changed_shortcut_ids) {
|
2024-02-29 13:55:38 +01:00
|
|
|
send_update_quick_reply_shortcut(get_shortcut(shortcut_id), "on_reload_quick_reply_shortcuts");
|
|
|
|
}
|
|
|
|
for (auto shortcut_id : changed_message_shortcut_ids) {
|
|
|
|
const auto *s = get_shortcut(shortcut_id);
|
2024-02-29 14:10:15 +01:00
|
|
|
send_update_quick_reply_shortcut_messages(s, "on_reload_quick_reply_shortcuts");
|
2024-02-22 19:23:19 +01:00
|
|
|
}
|
2024-02-22 20:55:09 +01:00
|
|
|
if (is_list_changed) {
|
|
|
|
send_update_quick_reply_shortcuts();
|
|
|
|
}
|
2024-02-22 15:32:12 +01:00
|
|
|
break;
|
|
|
|
}
|
2024-02-28 15:19:28 +01:00
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
2024-02-22 15:32:12 +01:00
|
|
|
}
|
|
|
|
on_load_quick_reply_success();
|
|
|
|
}
|
|
|
|
|
2024-02-24 12:22:01 +01:00
|
|
|
bool QuickReplyManager::is_shortcut_list_changed(const vector<unique_ptr<Shortcut>> &new_shortcuts) const {
|
|
|
|
if (!shortcuts_.are_inited_ || shortcuts_.shortcuts_.size() != new_shortcuts.size()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i < new_shortcuts.size(); i++) {
|
2024-02-27 16:10:11 +01:00
|
|
|
if (shortcuts_.shortcuts_[i]->shortcut_id_ != new_shortcuts[i]->shortcut_id_) {
|
2024-02-24 12:22:01 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-02-22 15:32:12 +01:00
|
|
|
void QuickReplyManager::on_load_quick_reply_success() {
|
2024-02-28 15:42:41 +01:00
|
|
|
for (auto &shortcut : shortcuts_.shortcuts_) {
|
|
|
|
reload_quick_reply_messages(shortcut->shortcut_id_, Auto());
|
|
|
|
}
|
2024-02-22 21:04:36 +01:00
|
|
|
set_promises(shortcuts_.load_queries_);
|
2024-02-22 15:32:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::on_load_quick_reply_fail(Status error) {
|
|
|
|
fail_promises(shortcuts_.load_queries_, std::move(error));
|
|
|
|
}
|
|
|
|
|
2024-02-23 12:49:29 +01:00
|
|
|
int64 QuickReplyManager::get_shortcuts_hash() const {
|
|
|
|
vector<uint64> numbers;
|
|
|
|
for (auto &shortcut : shortcuts_.shortcuts_) {
|
|
|
|
for (auto &message : shortcut->messages_) {
|
|
|
|
if (message->message_id.is_server()) {
|
2024-02-24 01:16:56 +01:00
|
|
|
numbers.push_back(shortcut->shortcut_id_.get());
|
2024-02-23 12:49:29 +01:00
|
|
|
numbers.push_back(get_md5_string_hash(shortcut->name_));
|
|
|
|
numbers.push_back(message->message_id.get_server_message_id().get());
|
|
|
|
numbers.push_back(message->edit_date);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return get_vector_hash(numbers);
|
|
|
|
}
|
|
|
|
|
2024-03-04 13:00:00 +01:00
|
|
|
void QuickReplyManager::set_quick_reply_shortcut_name(QuickReplyShortcutId shortcut_id, const string &name,
|
|
|
|
Promise<Unit> &&promise) {
|
2024-03-05 14:25:39 +01:00
|
|
|
load_quick_reply_shortcuts();
|
2024-03-04 13:00:00 +01:00
|
|
|
const auto *shortcut = get_shortcut(shortcut_id);
|
|
|
|
if (shortcut == nullptr) {
|
|
|
|
return promise.set_error(Status::Error(400, "Shortcut not found"));
|
|
|
|
}
|
|
|
|
if (check_shortcut_name(name).is_error()) {
|
|
|
|
return promise.set_error(Status::Error(400, "Shortcut name is invalid"));
|
|
|
|
}
|
|
|
|
if (!shortcut_id.is_server()) {
|
|
|
|
return promise.set_error(Status::Error(400, "Shortcut isn't created yet"));
|
|
|
|
}
|
|
|
|
auto query_promise = PromiseCreator::lambda(
|
|
|
|
[actor_id = actor_id(this), shortcut_id, name, promise = std::move(promise)](Result<Unit> &&result) mutable {
|
|
|
|
if (result.is_ok()) {
|
|
|
|
send_closure(actor_id, &QuickReplyManager::on_set_quick_reply_shortcut_name, shortcut_id, name,
|
|
|
|
std::move(promise));
|
2024-03-06 14:52:54 +01:00
|
|
|
} else {
|
|
|
|
promise.set_error(result.move_as_error());
|
2024-03-04 13:00:00 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
set_quick_reply_shortcut_name_on_server(shortcut_id, name, std::move(query_promise));
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::set_quick_reply_shortcut_name_on_server(QuickReplyShortcutId shortcut_id, const string &name,
|
|
|
|
Promise<Unit> &&promise) {
|
|
|
|
CHECK(shortcut_id.is_server());
|
|
|
|
td_->create_handler<EditQuickReplyShortcutQuery>(std::move(promise))->send(shortcut_id, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::on_set_quick_reply_shortcut_name(QuickReplyShortcutId shortcut_id, const string &name,
|
|
|
|
Promise<Unit> &&promise) {
|
|
|
|
auto *shortcut = get_shortcut(shortcut_id);
|
|
|
|
if (shortcut == nullptr || shortcut->name_ == name) {
|
|
|
|
return promise.set_value(Unit());
|
|
|
|
}
|
|
|
|
shortcut->name_ = name;
|
|
|
|
send_update_quick_reply_shortcut(shortcut, "on_set_quick_reply_shortcut_name");
|
|
|
|
save_quick_reply_shortcuts();
|
|
|
|
promise.set_value(Unit());
|
|
|
|
}
|
|
|
|
|
2024-02-27 16:10:11 +01:00
|
|
|
void QuickReplyManager::delete_quick_reply_shortcut(QuickReplyShortcutId shortcut_id, Promise<Unit> &&promise) {
|
2024-03-05 14:25:39 +01:00
|
|
|
load_quick_reply_shortcuts();
|
2024-02-27 16:10:11 +01:00
|
|
|
auto it = get_shortcut_it(shortcut_id);
|
2024-02-24 11:37:02 +01:00
|
|
|
if (it == shortcuts_.shortcuts_.end()) {
|
2024-02-24 01:02:42 +01:00
|
|
|
return promise.set_error(Status::Error(400, "Shortcut not found"));
|
|
|
|
}
|
2024-02-28 15:19:28 +01:00
|
|
|
send_update_quick_reply_shortcut_deleted(it->get());
|
2024-02-24 11:37:02 +01:00
|
|
|
shortcuts_.shortcuts_.erase(it);
|
2024-02-27 21:47:29 +01:00
|
|
|
save_quick_reply_shortcuts();
|
2024-02-28 15:19:28 +01:00
|
|
|
send_update_quick_reply_shortcuts();
|
2024-02-24 01:02:42 +01:00
|
|
|
|
2024-02-24 01:28:55 +01:00
|
|
|
if (!shortcut_id.is_server()) {
|
|
|
|
return promise.set_value(Unit());
|
|
|
|
}
|
|
|
|
|
|
|
|
delete_quick_reply_shortcut_from_server(shortcut_id, std::move(promise));
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::delete_quick_reply_shortcut_from_server(QuickReplyShortcutId shortcut_id,
|
|
|
|
Promise<Unit> &&promise) {
|
|
|
|
CHECK(shortcut_id.is_server());
|
|
|
|
|
|
|
|
deleted_shortcut_ids_.insert(shortcut_id);
|
2024-02-24 01:02:42 +01:00
|
|
|
td_->create_handler<DeleteQuickReplyShortcutQuery>(std::move(promise))->send(shortcut_id);
|
|
|
|
}
|
|
|
|
|
2024-02-27 16:10:11 +01:00
|
|
|
void QuickReplyManager::reorder_quick_reply_shortcuts(const vector<QuickReplyShortcutId> &shortcut_ids,
|
|
|
|
Promise<Unit> &&promise) {
|
2024-03-05 14:25:39 +01:00
|
|
|
load_quick_reply_shortcuts();
|
2024-02-27 16:10:11 +01:00
|
|
|
FlatHashSet<QuickReplyShortcutId, QuickReplyShortcutIdHash> unique_shortcut_ids;
|
|
|
|
for (const auto &shortcut_id : shortcut_ids) {
|
|
|
|
if (get_shortcut(shortcut_id) == nullptr) {
|
2024-02-24 12:40:25 +01:00
|
|
|
return promise.set_error(Status::Error(400, "Shortcut not found"));
|
|
|
|
}
|
2024-02-27 16:10:11 +01:00
|
|
|
unique_shortcut_ids.insert(shortcut_id);
|
2024-02-24 12:40:25 +01:00
|
|
|
}
|
2024-02-27 16:10:11 +01:00
|
|
|
if (unique_shortcut_ids.size() != shortcut_ids.size()) {
|
|
|
|
return promise.set_error(Status::Error(400, "Duplicate shortcut identifiers specified"));
|
2024-02-24 12:40:25 +01:00
|
|
|
}
|
|
|
|
if (!shortcuts_.are_inited_) {
|
|
|
|
return promise.set_value(Unit());
|
|
|
|
}
|
2024-02-27 16:10:11 +01:00
|
|
|
auto old_shortcut_ids = get_shortcut_ids();
|
|
|
|
auto old_server_shortcut_ids = get_server_shortcut_ids();
|
2024-02-24 12:40:25 +01:00
|
|
|
vector<unique_ptr<Shortcut>> shortcuts;
|
2024-02-27 16:10:11 +01:00
|
|
|
for (const auto &shortcut_id : shortcut_ids) {
|
|
|
|
auto it = get_shortcut_it(shortcut_id);
|
2024-02-24 12:40:25 +01:00
|
|
|
CHECK(it != shortcuts_.shortcuts_.end() && *it != nullptr);
|
|
|
|
shortcuts.push_back(std::move(*it));
|
|
|
|
}
|
|
|
|
for (auto &shortcut : shortcuts_.shortcuts_) {
|
|
|
|
if (shortcut != nullptr) {
|
2024-02-27 16:10:11 +01:00
|
|
|
CHECK(unique_shortcut_ids.count(shortcut->shortcut_id_) == 0);
|
2024-02-24 12:40:25 +01:00
|
|
|
shortcuts.push_back(std::move(shortcut));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
shortcuts_.shortcuts_ = std::move(shortcuts);
|
2024-02-27 21:47:29 +01:00
|
|
|
if (old_shortcut_ids == get_shortcut_ids()) {
|
2024-02-24 12:40:25 +01:00
|
|
|
return promise.set_value(Unit());
|
|
|
|
}
|
2024-02-27 21:47:29 +01:00
|
|
|
save_quick_reply_shortcuts();
|
2024-02-24 12:40:25 +01:00
|
|
|
send_update_quick_reply_shortcuts();
|
|
|
|
|
|
|
|
auto new_server_shortcut_ids = get_server_shortcut_ids();
|
2024-02-27 16:10:11 +01:00
|
|
|
if (new_server_shortcut_ids == old_server_shortcut_ids) {
|
2024-02-24 12:40:25 +01:00
|
|
|
return promise.set_value(Unit());
|
|
|
|
}
|
|
|
|
|
|
|
|
reorder_quick_reply_shortcuts_on_server(new_server_shortcut_ids, std::move(promise));
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::reorder_quick_reply_shortcuts_on_server(vector<QuickReplyShortcutId> shortcut_ids,
|
|
|
|
Promise<Unit> &&promise) {
|
|
|
|
td_->create_handler<ReorderQuickRepliesQuery>(std::move(promise))->send(std::move(shortcut_ids));
|
|
|
|
}
|
|
|
|
|
2024-02-29 14:39:38 +01:00
|
|
|
void QuickReplyManager::update_quick_reply_message(telegram_api::object_ptr<telegram_api::Message> &&message_ptr) {
|
2024-03-05 15:58:40 +01:00
|
|
|
if (td_->auth_manager_->is_bot()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-05 14:25:39 +01:00
|
|
|
load_quick_reply_shortcuts();
|
2024-02-29 14:39:38 +01:00
|
|
|
auto message = create_message(std::move(message_ptr), "update_quick_reply_message");
|
|
|
|
if (message == nullptr) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
auto shortcut_id = message->shortcut_id;
|
|
|
|
auto *s = get_shortcut(shortcut_id);
|
|
|
|
if (s == nullptr) {
|
|
|
|
return reload_quick_reply_messages(shortcut_id, Promise<Unit>());
|
|
|
|
}
|
2024-02-29 15:05:00 +01:00
|
|
|
on_get_quick_reply_message(s, std::move(message));
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::on_get_quick_reply_message(Shortcut *s, unique_ptr<QuickReplyMessage> message) {
|
2024-02-29 14:39:38 +01:00
|
|
|
auto it = get_message_it(s, message->message_id);
|
|
|
|
if (it == s->messages_.end()) {
|
2024-02-29 19:05:56 +01:00
|
|
|
change_message_files({s->shortcut_id_, message->message_id}, message.get(), {});
|
2024-02-29 14:39:38 +01:00
|
|
|
s->messages_.push_back(std::move(message));
|
2024-03-05 12:17:18 +01:00
|
|
|
s->server_total_count_++;
|
2024-02-29 14:39:38 +01:00
|
|
|
sort_quick_reply_messages(s->messages_);
|
2024-02-29 18:58:30 +01:00
|
|
|
send_update_quick_reply_shortcut(s, "on_get_quick_reply_message 1");
|
2024-02-29 14:39:38 +01:00
|
|
|
} else {
|
|
|
|
if (get_quick_reply_unique_id(it->get()) == get_quick_reply_unique_id(message.get())) {
|
|
|
|
return;
|
|
|
|
}
|
2024-02-29 18:58:30 +01:00
|
|
|
update_quick_reply_message(s->shortcut_id_, *it, std::move(message));
|
2024-02-29 14:39:38 +01:00
|
|
|
if (it == s->messages_.begin()) {
|
2024-02-29 18:58:30 +01:00
|
|
|
send_update_quick_reply_shortcut(s, "on_get_quick_reply_message 2");
|
2024-02-29 14:39:38 +01:00
|
|
|
}
|
|
|
|
}
|
2024-02-29 18:58:30 +01:00
|
|
|
send_update_quick_reply_shortcut_messages(s, "on_get_quick_reply_message 2");
|
2024-02-29 15:05:00 +01:00
|
|
|
save_quick_reply_shortcuts();
|
2024-02-29 14:39:38 +01:00
|
|
|
}
|
|
|
|
|
2024-02-29 18:58:30 +01:00
|
|
|
void QuickReplyManager::update_quick_reply_message(QuickReplyShortcutId shortcut_id,
|
|
|
|
unique_ptr<QuickReplyMessage> &old_message,
|
|
|
|
unique_ptr<QuickReplyMessage> &&new_message) {
|
|
|
|
CHECK(old_message != nullptr);
|
|
|
|
CHECK(new_message != nullptr);
|
|
|
|
CHECK(old_message->message_id == new_message->message_id);
|
|
|
|
CHECK(old_message->message_id.is_server());
|
|
|
|
if (old_message->edit_date > new_message->edit_date) {
|
|
|
|
LOG(INFO) << "Ignore update of " << old_message->message_id << " from " << shortcut_id << " to its old version";
|
|
|
|
return;
|
|
|
|
}
|
2024-02-29 19:05:56 +01:00
|
|
|
auto old_file_ids = get_message_file_ids(old_message.get());
|
2024-02-29 18:58:30 +01:00
|
|
|
old_message = std::move(new_message);
|
2024-02-29 19:05:56 +01:00
|
|
|
change_message_files({shortcut_id, old_message->message_id}, old_message.get(), old_file_ids);
|
2024-02-29 18:58:30 +01:00
|
|
|
}
|
|
|
|
|
2024-02-29 19:59:53 +01:00
|
|
|
void QuickReplyManager::delete_quick_reply_messages_from_updates(QuickReplyShortcutId shortcut_id,
|
|
|
|
const vector<MessageId> &message_ids) {
|
2024-03-05 15:58:40 +01:00
|
|
|
if (td_->auth_manager_->is_bot()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-05 14:25:39 +01:00
|
|
|
load_quick_reply_shortcuts();
|
2024-04-15 23:53:48 +02:00
|
|
|
auto *s = get_shortcut(shortcut_id);
|
2024-02-29 12:43:32 +01:00
|
|
|
if (s == nullptr) {
|
|
|
|
return;
|
|
|
|
}
|
2024-02-29 15:27:12 +01:00
|
|
|
for (auto message_id : message_ids) {
|
|
|
|
if (!message_id.is_server()) {
|
|
|
|
LOG(ERROR) << "Receive delete of " << message_ids;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2024-02-29 19:59:53 +01:00
|
|
|
delete_quick_reply_messages(s, message_ids, "delete_quick_reply_messages_from_updates");
|
2024-02-29 15:21:55 +01:00
|
|
|
}
|
|
|
|
|
2024-02-29 19:59:53 +01:00
|
|
|
void QuickReplyManager::delete_quick_reply_messages(Shortcut *s, const vector<MessageId> &message_ids,
|
|
|
|
const char *source) {
|
|
|
|
LOG(INFO) << "Delete " << message_ids << " from " << s->shortcut_id_ << " from " << source;
|
2024-02-29 12:43:32 +01:00
|
|
|
bool is_changed = false;
|
|
|
|
for (auto &message_id : message_ids) {
|
|
|
|
auto it = get_message_it(s, message_id);
|
2024-02-29 15:27:12 +01:00
|
|
|
if (it != s->messages_.end()) {
|
2024-02-29 17:01:40 +01:00
|
|
|
delete_message_files(s->shortcut_id_, it->get());
|
2024-03-05 12:17:18 +01:00
|
|
|
if (message_id.is_server()) {
|
|
|
|
s->server_total_count_--;
|
|
|
|
} else {
|
|
|
|
s->local_total_count_--;
|
2024-02-29 12:43:32 +01:00
|
|
|
}
|
|
|
|
is_changed = true;
|
|
|
|
s->messages_.erase(it);
|
|
|
|
}
|
2024-02-29 15:27:12 +01:00
|
|
|
if (message_id.is_server()) {
|
|
|
|
deleted_message_full_ids_.insert({s->shortcut_id_, message_id});
|
|
|
|
}
|
2024-02-29 12:43:32 +01:00
|
|
|
}
|
|
|
|
if (s->messages_.empty()) {
|
|
|
|
send_update_quick_reply_shortcut_deleted(s);
|
2024-02-29 15:21:55 +01:00
|
|
|
shortcuts_.shortcuts_.erase(get_shortcut_it(s->shortcut_id_));
|
2024-03-05 12:17:18 +01:00
|
|
|
CHECK(is_changed);
|
2024-03-04 13:11:36 +01:00
|
|
|
send_update_quick_reply_shortcuts();
|
2024-03-05 12:17:18 +01:00
|
|
|
save_quick_reply_shortcuts();
|
2024-02-29 13:55:38 +01:00
|
|
|
} else if (is_changed) {
|
2024-03-05 12:17:18 +01:00
|
|
|
send_update_quick_reply_shortcut(s, source);
|
2024-03-05 16:04:40 +01:00
|
|
|
send_update_quick_reply_shortcut_messages(s, source);
|
2024-02-29 12:43:32 +01:00
|
|
|
save_quick_reply_shortcuts();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-29 19:34:45 +01:00
|
|
|
void QuickReplyManager::delete_quick_reply_shortcut_messages(QuickReplyShortcutId shortcut_id,
|
|
|
|
const vector<MessageId> &message_ids,
|
|
|
|
Promise<Unit> &&promise) {
|
2024-03-05 14:25:39 +01:00
|
|
|
load_quick_reply_shortcuts();
|
2024-04-15 23:53:48 +02:00
|
|
|
auto *s = get_shortcut(shortcut_id);
|
2024-02-29 19:34:45 +01:00
|
|
|
if (s == nullptr) {
|
|
|
|
return promise.set_error(Status::Error(400, "Shortcut not found"));
|
|
|
|
}
|
|
|
|
if (message_ids.empty()) {
|
|
|
|
return promise.set_value(Unit());
|
|
|
|
}
|
|
|
|
|
|
|
|
vector<MessageId> deleted_server_message_ids;
|
|
|
|
for (auto &message_id : message_ids) {
|
|
|
|
if (!message_id.is_valid()) {
|
|
|
|
return promise.set_error(Status::Error(400, "Invalid message identifier"));
|
|
|
|
}
|
|
|
|
|
|
|
|
// message_id = get_persistent_message_id(s, message_id);
|
|
|
|
if (message_id.is_server()) {
|
|
|
|
deleted_server_message_ids.push_back(message_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delete_quick_reply_messages_on_server(shortcut_id, std::move(deleted_server_message_ids), std::move(promise));
|
|
|
|
|
2024-02-29 19:59:53 +01:00
|
|
|
delete_quick_reply_messages(s, message_ids, "delete_quick_reply_shortcut_messages");
|
2024-02-29 19:34:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::delete_quick_reply_messages_on_server(QuickReplyShortcutId shortcut_id,
|
|
|
|
const vector<MessageId> &message_ids,
|
|
|
|
Promise<Unit> &&promise) {
|
2024-04-17 13:31:36 +02:00
|
|
|
if (message_ids.empty()) {
|
|
|
|
return promise.set_value(Unit());
|
|
|
|
}
|
2024-02-29 19:34:45 +01:00
|
|
|
td_->create_handler<DeleteQuickReplyMessagesQuery>(std::move(promise))->send(shortcut_id, message_ids);
|
|
|
|
}
|
|
|
|
|
2024-04-17 17:39:25 +02:00
|
|
|
telegram_api::object_ptr<telegram_api::InputQuickReplyShortcut> QuickReplyManager::get_input_quick_reply_shortcut(
|
|
|
|
QuickReplyShortcutId shortcut_id) const {
|
|
|
|
if (shortcut_id.is_server()) {
|
|
|
|
return telegram_api::make_object<telegram_api::inputQuickReplyShortcutId>(shortcut_id.get());
|
|
|
|
}
|
|
|
|
const auto *s = get_shortcut(shortcut_id);
|
|
|
|
CHECK(s != nullptr);
|
|
|
|
return telegram_api::make_object<telegram_api::inputQuickReplyShortcut>(s->name_);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QuickReplyManager::check_send_quick_reply_messages_response(
|
|
|
|
QuickReplyShortcutId shortcut_id, const telegram_api::object_ptr<telegram_api::Updates> &updates_ptr,
|
|
|
|
const vector<int64> &random_ids) {
|
|
|
|
if (updates_ptr->get_id() != telegram_api::updates::ID) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const auto &updates = static_cast<const telegram_api::updates *>(updates_ptr.get())->updates_;
|
|
|
|
FlatHashSet<int64> sent_random_ids;
|
|
|
|
for (auto &update : updates) {
|
|
|
|
if (update->get_id() == telegram_api::updateMessageID::ID) {
|
|
|
|
auto update_message_id = static_cast<const telegram_api::updateMessageID *>(update.get());
|
|
|
|
int64 random_id = update_message_id->random_id_;
|
|
|
|
if (random_id == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!sent_random_ids.insert(random_id).second) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (sent_random_ids.size() != random_ids.size()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for (auto random_id : random_ids) {
|
|
|
|
if (sent_random_ids.count(random_id) != 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int32 new_shortcut_count = 0;
|
|
|
|
for (auto &update : updates) {
|
|
|
|
if (update->get_id() == telegram_api::updateNewQuickReply::ID) {
|
|
|
|
if (!QuickReplyShortcutId(
|
|
|
|
static_cast<const telegram_api::updateNewQuickReply *>(update.get())->quick_reply_->shortcut_id_)
|
|
|
|
.is_server()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
new_shortcut_count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (new_shortcut_count != (shortcut_id.is_server() ? 0 : 1)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::process_send_quick_reply_updates(QuickReplyShortcutId shortcut_id,
|
|
|
|
telegram_api::object_ptr<telegram_api::Updates> updates_ptr,
|
|
|
|
vector<int64> random_ids) {
|
|
|
|
if (!check_send_quick_reply_messages_response(shortcut_id, updates_ptr, random_ids)) {
|
|
|
|
LOG(ERROR) << "Receive " << to_string(updates_ptr);
|
|
|
|
on_failed_send_quick_reply_messages(shortcut_id, std::move(random_ids),
|
|
|
|
Status::Error(500, "Receive wrong response"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto updates = telegram_api::move_object_as<telegram_api::updates>(updates_ptr);
|
|
|
|
td_->user_manager_->on_get_users(std::move(updates->users_), "process_send_quick_reply_updates");
|
|
|
|
td_->chat_manager_->on_get_chats(std::move(updates->chats_), "process_send_quick_reply_updates");
|
|
|
|
|
|
|
|
bool is_shortcut_new = !shortcut_id.is_server();
|
|
|
|
{
|
|
|
|
auto it = get_shortcut_it(shortcut_id);
|
|
|
|
if (it == shortcuts_.shortcuts_.end()) {
|
|
|
|
// the shortcut was deleted
|
|
|
|
reload_quick_reply_shortcuts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_shortcut_new) {
|
|
|
|
QuickReplyShortcutId new_shortcut_id;
|
|
|
|
for (auto &update : updates->updates_) {
|
|
|
|
if (update->get_id() == telegram_api::updateNewQuickReply::ID) {
|
|
|
|
new_shortcut_id = QuickReplyShortcutId(
|
|
|
|
static_cast<const telegram_api::updateNewQuickReply *>(update.get())->quick_reply_->shortcut_id_);
|
|
|
|
update = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CHECK(new_shortcut_id.is_server());
|
|
|
|
send_update_quick_reply_shortcut_deleted(it->get());
|
|
|
|
(*it)->shortcut_id_ = new_shortcut_id;
|
|
|
|
for (auto &message : (*it)->messages_) {
|
|
|
|
CHECK(message->shortcut_id == shortcut_id);
|
|
|
|
message->shortcut_id = new_shortcut_id;
|
|
|
|
}
|
|
|
|
shortcut_id = new_shortcut_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
auto *s = get_shortcut(shortcut_id);
|
|
|
|
CHECK(s != nullptr);
|
|
|
|
|
|
|
|
for (auto &random_id : random_ids) {
|
|
|
|
for (auto it = s->messages_.begin(); it != s->messages_.end(); ++it) {
|
|
|
|
if ((*it)->random_id == random_id) {
|
|
|
|
MessageId new_message_id;
|
|
|
|
for (auto &update : updates->updates_) {
|
|
|
|
if (update != nullptr && update->get_id() == telegram_api::updateMessageID::ID &&
|
|
|
|
static_cast<const telegram_api::updateMessageID *>(update.get())->random_id_ == random_id) {
|
|
|
|
new_message_id =
|
|
|
|
MessageId(ServerMessageId(static_cast<const telegram_api::updateMessageID *>(update.get())->id_));
|
|
|
|
update = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (new_message_id.is_valid()) {
|
|
|
|
for (auto &update : updates->updates_) {
|
|
|
|
if (update != nullptr && update->get_id() == telegram_api::updateQuickReplyMessage::ID &&
|
|
|
|
MessageId::get_message_id(
|
|
|
|
static_cast<const telegram_api::updateQuickReplyMessage *>(update.get())->message_, false) ==
|
|
|
|
new_message_id) {
|
|
|
|
auto message = create_message(
|
|
|
|
std::move(static_cast<telegram_api::updateQuickReplyMessage *>(update.get())->message_),
|
|
|
|
"process_send_quick_reply_updates");
|
|
|
|
if (message != nullptr && message->shortcut_id == shortcut_id) {
|
|
|
|
change_message_files({shortcut_id, message->message_id}, message.get(), {});
|
|
|
|
*it = std::move(message);
|
|
|
|
s->server_total_count_++;
|
|
|
|
s->local_total_count_--;
|
|
|
|
}
|
|
|
|
update = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sort_quick_reply_messages(s->messages_);
|
|
|
|
send_update_quick_reply_shortcut(s, "process_send_quick_reply_updates");
|
|
|
|
send_update_quick_reply_shortcut_messages(s, "process_send_quick_reply_updates");
|
|
|
|
if (is_shortcut_new) {
|
|
|
|
send_update_quick_reply_shortcuts();
|
|
|
|
}
|
|
|
|
save_quick_reply_shortcuts();
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::on_failed_send_quick_reply_messages(QuickReplyShortcutId shortcut_id, vector<int64> random_ids,
|
|
|
|
Status error) {
|
|
|
|
// TODO
|
|
|
|
}
|
|
|
|
|
|
|
|
Result<td_api::object_ptr<td_api::quickReplyMessage>> QuickReplyManager::send_message(
|
|
|
|
const string &shortcut_name, MessageId reply_to_message_id,
|
|
|
|
td_api::object_ptr<td_api::InputMessageContent> &&input_message_content) {
|
|
|
|
TRY_RESULT(message_content, process_input_message_content(std::move(input_message_content)));
|
|
|
|
TRY_RESULT(s, create_new_local_shortcut(shortcut_name, 1));
|
|
|
|
bool is_new = s->messages_.empty();
|
|
|
|
reply_to_message_id = get_input_reply_to_message_id(s, reply_to_message_id);
|
|
|
|
|
|
|
|
auto content = dup_message_content(td_, td_->dialog_manager_->get_my_dialog_id(), message_content.content.get(),
|
|
|
|
MessageContentDupType::Send, MessageCopyOptions());
|
|
|
|
auto *m = add_local_message(s, reply_to_message_id, std::move(content), message_content.invert_media,
|
|
|
|
message_content.via_bot_user_id, false, message_content.disable_web_page_preview,
|
|
|
|
std::move(message_content.emoji));
|
|
|
|
|
|
|
|
send_update_quick_reply_shortcut(s, "send_message");
|
|
|
|
send_update_quick_reply_shortcut_messages(s, "send_message");
|
|
|
|
if (is_new) {
|
|
|
|
send_update_quick_reply_shortcuts();
|
|
|
|
}
|
|
|
|
save_quick_reply_shortcuts();
|
|
|
|
|
|
|
|
do_send_message(m);
|
|
|
|
|
|
|
|
return get_quick_reply_message_object(m, "send_message");
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::do_send_message(const QuickReplyMessage *m, vector<int> bad_parts) {
|
|
|
|
bool is_edit = m->message_id.is_server();
|
|
|
|
LOG(INFO) << "Do " << (is_edit ? "edit" : "send") << ' ' << QuickReplyMessageFullId(m->shortcut_id, m->message_id);
|
|
|
|
|
|
|
|
auto content = m->content.get();
|
|
|
|
CHECK(content != nullptr);
|
|
|
|
auto content_type = content->get_type();
|
|
|
|
if (content_type == MessageContentType::Text) {
|
|
|
|
CHECK(!is_edit);
|
|
|
|
const FormattedText *message_text = get_message_content_text(content);
|
|
|
|
CHECK(message_text != nullptr);
|
|
|
|
auto input_media = get_message_content_input_media_web_page(td_, content);
|
|
|
|
if (input_media == nullptr) {
|
|
|
|
td_->create_handler<SendQuickReplyMessageQuery>()->send(m);
|
|
|
|
} else {
|
|
|
|
td_->create_handler<SendQuickReplyMediaQuery>()->send(FileId(), FileId(), m, std::move(input_media));
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-29 14:05:16 +01:00
|
|
|
void QuickReplyManager::get_quick_reply_shortcut_messages(QuickReplyShortcutId shortcut_id, Promise<Unit> &&promise) {
|
2024-03-05 14:25:39 +01:00
|
|
|
load_quick_reply_shortcuts();
|
2024-04-15 23:53:48 +02:00
|
|
|
auto *s = get_shortcut(shortcut_id);
|
2024-02-28 15:19:28 +01:00
|
|
|
if (s == nullptr) {
|
|
|
|
return promise.set_error(Status::Error(400, "Shortcut not found"));
|
|
|
|
}
|
2024-02-29 13:55:38 +01:00
|
|
|
if (have_all_shortcut_messages(s)) {
|
2024-02-29 14:05:16 +01:00
|
|
|
return promise.set_value(Unit());
|
2024-02-28 15:19:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
CHECK(shortcut_id.is_server());
|
|
|
|
reload_quick_reply_messages(shortcut_id, std::move(promise));
|
|
|
|
}
|
|
|
|
|
2024-02-29 14:05:16 +01:00
|
|
|
void QuickReplyManager::reload_quick_reply_messages(QuickReplyShortcutId shortcut_id, Promise<Unit> &&promise) {
|
2024-03-05 15:58:40 +01:00
|
|
|
if (td_->auth_manager_->is_bot()) {
|
|
|
|
return promise.set_error(Status::Error(400, "Not supported by bots"));
|
|
|
|
}
|
|
|
|
|
2024-03-05 14:25:39 +01:00
|
|
|
load_quick_reply_shortcuts();
|
2024-03-01 11:39:26 +01:00
|
|
|
CHECK(shortcut_id.is_valid());
|
|
|
|
if (!shortcut_id.is_server()) {
|
|
|
|
return promise.set_value(Unit());
|
|
|
|
}
|
2024-02-28 15:19:28 +01:00
|
|
|
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<telegram_api::object_ptr<telegram_api::messages_Messages>> r_messages) {
|
|
|
|
send_closure(actor_id, &QuickReplyManager::on_reload_quick_reply_messages, shortcut_id, std::move(r_messages));
|
|
|
|
});
|
2024-02-28 15:38:17 +01:00
|
|
|
td_->create_handler<GetQuickReplyMessagesQuery>(std::move(query_promise))
|
|
|
|
->send(shortcut_id, vector<MessageId>(), get_quick_reply_messages_hash(get_shortcut(shortcut_id)));
|
2024-02-28 15:19:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::on_reload_quick_reply_messages(
|
|
|
|
QuickReplyShortcutId shortcut_id, Result<telegram_api::object_ptr<telegram_api::messages_Messages>> 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<telegram_api::messages_messages>(messages_ptr);
|
2024-04-02 02:52:34 +02:00
|
|
|
td_->user_manager_->on_get_users(std::move(messages->users_), "on_reload_quick_reply_messages");
|
2024-04-02 12:06:22 +02:00
|
|
|
td_->chat_manager_->on_get_chats(std::move(messages->chats_), "on_reload_quick_reply_messages");
|
2024-02-28 15:19:28 +01:00
|
|
|
|
|
|
|
vector<unique_ptr<QuickReplyMessage>> 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;
|
|
|
|
}
|
|
|
|
|
2024-02-29 14:39:38 +01:00
|
|
|
auto *old_shortcut = it != shortcuts_.shortcuts_.end() ? it->get() : nullptr;
|
2024-02-28 15:19:28 +01:00
|
|
|
auto shortcut = td::make_unique<Shortcut>();
|
|
|
|
shortcut->name_ = old_shortcut->name_;
|
|
|
|
shortcut->shortcut_id_ = shortcut_id;
|
2024-03-07 10:03:22 +01:00
|
|
|
shortcut->server_total_count_ = static_cast<int32>(quick_reply_messages.size());
|
2024-02-28 15:19:28 +01:00
|
|
|
shortcut->messages_ = std::move(quick_reply_messages);
|
|
|
|
|
2024-02-29 19:05:56 +01:00
|
|
|
if (old_shortcut == nullptr) {
|
2024-02-29 13:55:38 +01:00
|
|
|
CHECK(have_all_shortcut_messages(shortcut.get()));
|
2024-02-29 19:05:56 +01:00
|
|
|
send_update_quick_reply_shortcut(shortcut.get(), "on_reload_quick_reply_messages 1");
|
|
|
|
send_update_quick_reply_shortcut_messages(shortcut.get(), "on_reload_quick_reply_messages 2");
|
|
|
|
for (auto &message : shortcut->messages_) {
|
|
|
|
change_message_files({shortcut_id, message->message_id}, message.get(), {});
|
2024-02-29 14:39:38 +01:00
|
|
|
}
|
|
|
|
shortcuts_.shortcuts_.push_back(std::move(shortcut));
|
|
|
|
} else {
|
2024-03-05 16:12:05 +01:00
|
|
|
bool is_shortcut_changed = false;
|
|
|
|
bool are_messages_changed = false;
|
|
|
|
update_shortcut_from(shortcut.get(), old_shortcut, false, &is_shortcut_changed, &are_messages_changed);
|
|
|
|
CHECK(have_all_shortcut_messages(shortcut.get()));
|
|
|
|
if (is_shortcut_changed) {
|
|
|
|
send_update_quick_reply_shortcut(shortcut.get(), "on_reload_quick_reply_messages 3");
|
|
|
|
}
|
|
|
|
if (are_messages_changed) {
|
2024-03-05 16:04:40 +01:00
|
|
|
send_update_quick_reply_shortcut_messages(shortcut.get(), "on_reload_quick_reply_messages 4");
|
2024-02-29 19:05:56 +01:00
|
|
|
}
|
2024-02-29 14:39:38 +01:00
|
|
|
*it = std::move(shortcut);
|
|
|
|
}
|
2024-02-29 19:05:56 +01:00
|
|
|
|
2024-02-28 15:19:28 +01:00
|
|
|
save_quick_reply_shortcuts();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
2024-04-15 23:53:48 +02:00
|
|
|
auto *s = get_shortcut(shortcut_id);
|
2024-02-28 15:19:28 +01:00
|
|
|
if (s == nullptr) {
|
|
|
|
return fail_promises(promises, Status::Error(400, "Shortcut not found"));
|
|
|
|
}
|
2024-03-07 12:09:31 +01:00
|
|
|
set_promises(promises);
|
2024-02-28 15:19:28 +01:00
|
|
|
}
|
|
|
|
|
2024-02-28 15:38:17 +01:00
|
|
|
int64 QuickReplyManager::get_quick_reply_messages_hash(const Shortcut *s) {
|
2024-03-01 11:39:26 +01:00
|
|
|
if (s == nullptr) {
|
|
|
|
return 0;
|
|
|
|
}
|
2024-02-28 15:38:17 +01:00
|
|
|
vector<uint64> numbers;
|
2024-02-29 13:55:38 +01:00
|
|
|
for (const auto &message : s->messages_) {
|
2024-02-28 15:38:17 +01:00
|
|
|
if (message->message_id.is_server()) {
|
|
|
|
numbers.push_back(message->message_id.get_server_message_id().get());
|
|
|
|
numbers.push_back(message->edit_date);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return get_vector_hash(numbers);
|
|
|
|
}
|
|
|
|
|
2024-02-29 15:05:00 +01:00
|
|
|
void QuickReplyManager::reload_quick_reply_message(QuickReplyShortcutId shortcut_id, MessageId message_id,
|
|
|
|
Promise<Unit> &&promise) {
|
2024-03-05 15:58:40 +01:00
|
|
|
if (td_->auth_manager_->is_bot()) {
|
|
|
|
return promise.set_error(Status::Error(400, "Not supported by bots"));
|
|
|
|
}
|
|
|
|
|
2024-03-05 14:25:39 +01:00
|
|
|
load_quick_reply_shortcuts();
|
2024-04-15 23:53:48 +02:00
|
|
|
auto *s = get_shortcut(shortcut_id);
|
2024-02-29 15:05:00 +01:00
|
|
|
if (s == nullptr) {
|
|
|
|
return promise.set_error(Status::Error(400, "Shortcut not found"));
|
|
|
|
}
|
|
|
|
if (!message_id.is_server()) {
|
|
|
|
return promise.set_error(Status::Error(400, "Message can't be reloaded"));
|
|
|
|
}
|
|
|
|
auto query_promise =
|
|
|
|
PromiseCreator::lambda([actor_id = actor_id(this), shortcut_id, message_id, promise = std::move(promise)](
|
|
|
|
Result<telegram_api::object_ptr<telegram_api::messages_Messages>> r_messages) mutable {
|
|
|
|
send_closure(actor_id, &QuickReplyManager::on_reload_quick_reply_message, shortcut_id, message_id,
|
|
|
|
std::move(r_messages), std::move(promise));
|
|
|
|
});
|
|
|
|
td_->create_handler<GetQuickReplyMessagesQuery>(std::move(query_promise))
|
|
|
|
->send(shortcut_id, vector<MessageId>{message_id}, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::on_reload_quick_reply_message(
|
|
|
|
QuickReplyShortcutId shortcut_id, MessageId message_id,
|
|
|
|
Result<telegram_api::object_ptr<telegram_api::messages_Messages>> r_messages, Promise<Unit> &&promise) {
|
|
|
|
G()->ignore_result_if_closing(r_messages);
|
|
|
|
if (r_messages.is_error()) {
|
|
|
|
return promise.set_error(r_messages.move_as_error());
|
|
|
|
}
|
2024-04-15 23:53:48 +02:00
|
|
|
auto *s = get_shortcut(shortcut_id);
|
2024-02-29 15:05:00 +01:00
|
|
|
if (s == nullptr) {
|
|
|
|
return promise.set_error(Status::Error(400, "Shortcut not found"));
|
|
|
|
}
|
|
|
|
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:
|
|
|
|
case telegram_api::messages_messagesNotModified::ID:
|
|
|
|
LOG(ERROR) << "Receive " << to_string(messages_ptr);
|
|
|
|
return promise.set_error(Status::Error(400, "Receive wrong response"));
|
|
|
|
case telegram_api::messages_messages::ID: {
|
|
|
|
auto messages = telegram_api::move_object_as<telegram_api::messages_messages>(messages_ptr);
|
2024-04-02 02:52:34 +02:00
|
|
|
td_->user_manager_->on_get_users(std::move(messages->users_), "on_reload_quick_reply_message");
|
2024-04-02 12:06:22 +02:00
|
|
|
td_->chat_manager_->on_get_chats(std::move(messages->chats_), "on_reload_quick_reply_message");
|
2024-02-29 15:05:00 +01:00
|
|
|
|
|
|
|
if (messages->messages_.size() > 1u) {
|
|
|
|
LOG(ERROR) << "Receive " << to_string(messages_ptr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
unique_ptr<QuickReplyMessage> message;
|
|
|
|
if (messages->messages_.size() == 1u) {
|
|
|
|
message = create_message(std::move(messages->messages_[0]), "on_reload_quick_reply_message");
|
|
|
|
}
|
|
|
|
if (message == nullptr) {
|
2024-02-29 19:59:53 +01:00
|
|
|
delete_quick_reply_messages(s, {message_id}, "on_reload_quick_reply_message");
|
2024-02-29 15:05:00 +01:00
|
|
|
return promise.set_error(Status::Error(400, "Message not found"));
|
|
|
|
}
|
|
|
|
if (message->shortcut_id != shortcut_id) {
|
|
|
|
LOG(ERROR) << "Receive message from " << message->shortcut_id << " instead of " << shortcut_id;
|
|
|
|
return promise.set_error(Status::Error(400, "Message not found"));
|
|
|
|
}
|
|
|
|
on_get_quick_reply_message(s, std::move(message));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
promise.set_value(Unit());
|
|
|
|
}
|
|
|
|
|
2024-03-04 18:06:32 +01:00
|
|
|
Result<vector<QuickReplyManager::QuickReplyMessageContent>> QuickReplyManager::get_quick_reply_message_contents(
|
|
|
|
DialogId dialog_id, QuickReplyShortcutId shortcut_id) const {
|
|
|
|
const auto *shortcut = get_shortcut(shortcut_id);
|
|
|
|
if (shortcut == nullptr) {
|
|
|
|
return Status::Error(400, "Shortcut not found");
|
|
|
|
}
|
|
|
|
if (!shortcut_id.is_server()) {
|
|
|
|
return Status::Error(400, "Shortcut isn't created yet");
|
|
|
|
}
|
|
|
|
if (!have_all_shortcut_messages(shortcut)) {
|
|
|
|
return Status::Error(400, "Shortcut messages aren't loaded yet");
|
|
|
|
}
|
|
|
|
|
2024-04-15 01:32:04 +02:00
|
|
|
TRY_STATUS(td_->dialog_manager_->check_dialog_access(dialog_id, false, AccessRights::Write,
|
|
|
|
"get_quick_reply_message_contents"));
|
2024-04-02 02:52:34 +02:00
|
|
|
if (dialog_id.get_type() != DialogType::User || td_->user_manager_->is_user_bot(dialog_id.get_user_id())) {
|
2024-03-04 20:33:25 +01:00
|
|
|
return Status::Error(400, "Can't use quick replies in the chat");
|
2024-03-04 18:06:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
vector<QuickReplyMessageContent> result;
|
|
|
|
for (auto &message : shortcut->messages_) {
|
|
|
|
if (!message->message_id.is_server()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
auto content = dup_message_content(td_, dialog_id, message->content.get(), MessageContentDupType::ServerCopy,
|
|
|
|
MessageCopyOptions(true, false));
|
|
|
|
|
|
|
|
auto can_send_status = can_send_message_content(dialog_id, content.get(), false, true, td_);
|
|
|
|
if (can_send_status.is_error()) {
|
|
|
|
LOG(INFO) << "Can't send " << message->message_id << ": " << can_send_status.message();
|
2024-04-15 19:36:23 +02:00
|
|
|
// if we skip the message, the sending will fail anyway with MESSAGE_IDS_MISMATCH
|
|
|
|
// continue;
|
2024-03-04 18:06:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
auto disable_web_page_preview = message->disable_web_page_preview &&
|
|
|
|
content->get_type() == MessageContentType::Text &&
|
|
|
|
!has_message_content_web_page(content.get());
|
2024-03-06 13:56:50 +01:00
|
|
|
result.push_back({std::move(content), message->message_id, message->reply_to_message_id,
|
2024-03-18 20:38:30 +01:00
|
|
|
dup_reply_markup(message->reply_markup),
|
|
|
|
message->hide_via_bot ? UserId() : message->via_bot_user_id, message->media_album_id,
|
|
|
|
message->invert_media, disable_web_page_preview});
|
2024-03-04 18:06:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return std::move(result);
|
|
|
|
}
|
|
|
|
|
2024-02-24 01:16:56 +01:00
|
|
|
QuickReplyManager::Shortcut *QuickReplyManager::get_shortcut(QuickReplyShortcutId shortcut_id) {
|
2024-02-22 17:45:49 +01:00
|
|
|
if (!shortcuts_.are_inited_) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
for (auto &shortcut : shortcuts_.shortcuts_) {
|
|
|
|
if (shortcut->shortcut_id_ == shortcut_id) {
|
|
|
|
return shortcut.get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2024-03-04 18:06:32 +01:00
|
|
|
const QuickReplyManager::Shortcut *QuickReplyManager::get_shortcut(QuickReplyShortcutId shortcut_id) const {
|
|
|
|
if (!shortcuts_.are_inited_) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
for (auto &shortcut : shortcuts_.shortcuts_) {
|
|
|
|
if (shortcut->shortcut_id_ == shortcut_id) {
|
|
|
|
return shortcut.get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2024-02-24 01:02:42 +01:00
|
|
|
QuickReplyManager::Shortcut *QuickReplyManager::get_shortcut(const string &name) {
|
|
|
|
if (!shortcuts_.are_inited_) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
for (auto &shortcut : shortcuts_.shortcuts_) {
|
|
|
|
if (shortcut->name_ == name) {
|
|
|
|
return shortcut.get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2024-02-27 16:10:11 +01:00
|
|
|
vector<unique_ptr<QuickReplyManager::Shortcut>>::iterator QuickReplyManager::get_shortcut_it(
|
|
|
|
QuickReplyShortcutId shortcut_id) {
|
|
|
|
for (auto it = shortcuts_.shortcuts_.begin(); it != shortcuts_.shortcuts_.end(); ++it) {
|
2024-03-06 15:05:30 +01:00
|
|
|
if (*it != nullptr && (*it)->shortcut_id_ == shortcut_id) {
|
2024-02-27 16:10:11 +01:00
|
|
|
return it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return shortcuts_.shortcuts_.end();
|
|
|
|
}
|
|
|
|
|
2024-02-29 12:43:32 +01:00
|
|
|
vector<unique_ptr<QuickReplyManager::QuickReplyMessage>>::iterator QuickReplyManager::get_message_it(
|
|
|
|
Shortcut *s, MessageId message_id) {
|
|
|
|
CHECK(s != nullptr);
|
|
|
|
for (auto it = s->messages_.begin(); it != s->messages_.end(); ++it) {
|
|
|
|
if ((*it)->message_id == message_id) {
|
|
|
|
return it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return s->messages_.end();
|
|
|
|
}
|
|
|
|
|
2024-04-15 22:36:27 +02:00
|
|
|
Result<QuickReplyManager::Shortcut *> QuickReplyManager::create_new_local_shortcut(const string &name,
|
|
|
|
int32 new_message_count) {
|
2024-04-15 21:41:36 +02:00
|
|
|
TRY_STATUS(check_shortcut_name(name));
|
|
|
|
|
|
|
|
load_quick_reply_shortcuts();
|
2024-04-15 22:36:27 +02:00
|
|
|
if (!shortcuts_.are_inited_) {
|
|
|
|
return Status::Error(400, "Quick reply shortcuts must be loaded first");
|
|
|
|
}
|
|
|
|
|
|
|
|
auto *s = get_shortcut(name);
|
2024-04-15 21:41:36 +02:00
|
|
|
auto max_message_count = td_->option_manager_->get_option_integer("quick_reply_shortcut_message_count_max");
|
|
|
|
if (s != nullptr) {
|
|
|
|
max_message_count -= s->server_total_count_ + s->local_total_count_;
|
|
|
|
} else {
|
|
|
|
auto max_shortcut_count = td_->option_manager_->get_option_integer("quick_reply_shortcut_count_max");
|
2024-04-15 22:36:27 +02:00
|
|
|
if (static_cast<int64>(shortcuts_.shortcuts_.size()) >= max_shortcut_count) {
|
2024-04-15 21:41:36 +02:00
|
|
|
return Status::Error(400, "Quick reply shortcut count exceeded");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (new_message_count > max_message_count) {
|
|
|
|
return Status::Error(400, "Quick reply message count exceeded");
|
|
|
|
}
|
2024-04-15 22:36:27 +02:00
|
|
|
if (s != nullptr) {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
if (next_local_shortcut_id_ >= std::numeric_limits<int32>::max() - 10) {
|
|
|
|
return Status::Error(400, "Too many local shortcuts created");
|
|
|
|
}
|
2024-04-15 21:41:36 +02:00
|
|
|
|
2024-04-15 22:36:27 +02:00
|
|
|
auto shortcut = td::make_unique<Shortcut>();
|
|
|
|
shortcut->name_ = name;
|
|
|
|
shortcut->shortcut_id_ = QuickReplyShortcutId(next_local_shortcut_id_++);
|
|
|
|
s = shortcut.get();
|
|
|
|
|
|
|
|
shortcuts_.shortcuts_.push_back(std::move(shortcut));
|
|
|
|
|
|
|
|
return s;
|
2024-04-15 21:41:36 +02:00
|
|
|
}
|
|
|
|
|
2024-04-15 21:55:26 +02:00
|
|
|
MessageId QuickReplyManager::get_input_reply_to_message_id(const Shortcut *s, MessageId reply_to_message_id) {
|
|
|
|
if (s == nullptr || !reply_to_message_id.is_valid() || !reply_to_message_id.is_server()) {
|
|
|
|
return MessageId();
|
|
|
|
}
|
|
|
|
for (auto &message : s->messages_) {
|
|
|
|
CHECK(message != nullptr);
|
|
|
|
if (message->message_id == reply_to_message_id) {
|
|
|
|
return reply_to_message_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return MessageId();
|
|
|
|
}
|
|
|
|
|
2024-04-15 22:12:22 +02:00
|
|
|
Result<InputMessageContent> QuickReplyManager::process_input_message_content(
|
|
|
|
td_api::object_ptr<td_api::InputMessageContent> &&input_message_content) {
|
|
|
|
if (input_message_content == nullptr) {
|
|
|
|
return Status::Error(400, "Can't add quick reply without content");
|
|
|
|
}
|
|
|
|
if (input_message_content->get_id() == td_api::inputMessageForwarded::ID) {
|
|
|
|
return Status::Error(400, "Can't forward messages to quick replies");
|
|
|
|
}
|
|
|
|
if (input_message_content->get_id() == td_api::inputMessagePoll::ID) {
|
|
|
|
return Status::Error(400, "Can't add quick reply poll");
|
|
|
|
}
|
|
|
|
return get_input_message_content(DialogId(), std::move(input_message_content), td_, true);
|
|
|
|
}
|
|
|
|
|
2024-04-15 23:53:48 +02:00
|
|
|
MessageId QuickReplyManager::get_next_message_id(Shortcut *s, MessageType type) const {
|
|
|
|
CHECK(s != nullptr);
|
|
|
|
MessageId last_message_id = s->last_assigned_message_id_;
|
|
|
|
if (!s->messages_.empty() && s->messages_.back() != nullptr && s->messages_.back()->message_id > last_message_id) {
|
|
|
|
last_message_id = s->messages_.back()->message_id;
|
|
|
|
}
|
|
|
|
s->last_assigned_message_id_ = last_message_id.get_next_message_id(type);
|
|
|
|
CHECK(s->last_assigned_message_id_.is_valid());
|
|
|
|
return s->last_assigned_message_id_;
|
|
|
|
}
|
|
|
|
|
|
|
|
MessageId QuickReplyManager::get_next_yet_unsent_message_id(Shortcut *s) const {
|
|
|
|
return get_next_message_id(s, MessageType::YetUnsent);
|
|
|
|
}
|
|
|
|
|
|
|
|
MessageId QuickReplyManager::get_next_local_message_id(Shortcut *s) const {
|
|
|
|
return get_next_message_id(s, MessageType::Local);
|
|
|
|
}
|
|
|
|
|
|
|
|
QuickReplyManager::QuickReplyMessage *QuickReplyManager::add_local_message(
|
|
|
|
Shortcut *s, MessageId reply_to_message_id, unique_ptr<MessageContent> &&content, bool invert_media,
|
|
|
|
UserId via_bot_user_id, bool hide_via_bot, bool disable_web_page_preview, string &&send_emoji) {
|
|
|
|
CHECK(s != nullptr);
|
|
|
|
auto message = make_unique<QuickReplyMessage>();
|
|
|
|
auto *m = message.get();
|
|
|
|
m->shortcut_id = s->shortcut_id_;
|
|
|
|
m->message_id = get_next_yet_unsent_message_id(s);
|
|
|
|
m->reply_to_message_id = reply_to_message_id;
|
|
|
|
m->send_emoji = std::move(send_emoji);
|
|
|
|
m->via_bot_user_id = via_bot_user_id;
|
|
|
|
m->hide_via_bot = hide_via_bot;
|
|
|
|
m->invert_media = invert_media;
|
|
|
|
m->disable_web_page_preview = disable_web_page_preview;
|
|
|
|
m->content = std::move(content);
|
|
|
|
do {
|
|
|
|
m->random_id = Random::secure_int64();
|
|
|
|
} while (m->random_id == 0);
|
|
|
|
|
|
|
|
s->messages_.push_back(std::move(message));
|
|
|
|
s->local_total_count_++;
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2024-02-27 16:10:11 +01:00
|
|
|
vector<QuickReplyShortcutId> QuickReplyManager::get_shortcut_ids() const {
|
|
|
|
return transform(shortcuts_.shortcuts_, [](const unique_ptr<Shortcut> &shortcut) { return shortcut->shortcut_id_; });
|
|
|
|
}
|
|
|
|
|
2024-02-24 12:40:25 +01:00
|
|
|
vector<QuickReplyShortcutId> QuickReplyManager::get_server_shortcut_ids() const {
|
|
|
|
vector<QuickReplyShortcutId> shortcut_ids;
|
|
|
|
for (auto &shortcut : shortcuts_.shortcuts_) {
|
|
|
|
if (shortcut->shortcut_id_.is_server()) {
|
|
|
|
shortcut_ids.push_back(shortcut->shortcut_id_);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return shortcut_ids;
|
|
|
|
}
|
|
|
|
|
2024-02-22 17:45:49 +01:00
|
|
|
void QuickReplyManager::sort_quick_reply_messages(vector<unique_ptr<QuickReplyMessage>> &messages) {
|
|
|
|
std::sort(messages.begin(), messages.end(),
|
|
|
|
[](const unique_ptr<QuickReplyMessage> &lhs, const unique_ptr<QuickReplyMessage> &rhs) {
|
|
|
|
return lhs->message_id < rhs->message_id;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-02-22 19:47:34 +01:00
|
|
|
QuickReplyManager::QuickReplyMessageUniqueId QuickReplyManager::get_quick_reply_unique_id(const QuickReplyMessage *m) {
|
|
|
|
return QuickReplyMessageUniqueId(m->message_id, m->edit_date);
|
|
|
|
}
|
|
|
|
|
2024-02-22 19:44:13 +01:00
|
|
|
vector<QuickReplyManager::QuickReplyMessageUniqueId> QuickReplyManager::get_quick_reply_unique_ids(
|
2024-02-22 17:45:49 +01:00
|
|
|
const vector<unique_ptr<QuickReplyMessage>> &messages) {
|
2024-02-22 19:47:34 +01:00
|
|
|
return transform(
|
|
|
|
messages, [](const unique_ptr<QuickReplyMessage> &message) { return get_quick_reply_unique_id(message.get()); });
|
2024-02-22 17:45:49 +01:00
|
|
|
}
|
|
|
|
|
2024-02-22 19:44:13 +01:00
|
|
|
vector<QuickReplyManager::QuickReplyMessageUniqueId> QuickReplyManager::get_server_quick_reply_unique_ids(
|
2024-02-22 17:45:49 +01:00
|
|
|
const vector<unique_ptr<QuickReplyMessage>> &messages) {
|
2024-02-22 19:44:13 +01:00
|
|
|
auto message_ids = get_quick_reply_unique_ids(messages);
|
|
|
|
td::remove_if(message_ids, [](const QuickReplyMessageUniqueId &message_id) { return !message_id.first.is_server(); });
|
2024-02-22 17:45:49 +01:00
|
|
|
return message_ids;
|
|
|
|
}
|
|
|
|
|
2024-03-05 16:12:05 +01:00
|
|
|
void QuickReplyManager::update_shortcut_from(Shortcut *new_shortcut, Shortcut *old_shortcut, bool is_partial,
|
|
|
|
bool *is_shortcut_changed, bool *are_messages_changed) {
|
2024-02-22 17:45:49 +01:00
|
|
|
CHECK(old_shortcut != nullptr);
|
|
|
|
CHECK(new_shortcut != nullptr);
|
|
|
|
CHECK(old_shortcut->shortcut_id_ == new_shortcut->shortcut_id_);
|
|
|
|
CHECK(!old_shortcut->messages_.empty());
|
|
|
|
CHECK(!new_shortcut->messages_.empty());
|
2024-02-22 19:57:43 +01:00
|
|
|
auto old_unique_id = get_quick_reply_unique_id(old_shortcut->messages_[0].get());
|
2024-02-22 17:45:49 +01:00
|
|
|
auto old_message_count = get_shortcut_message_count(old_shortcut);
|
|
|
|
if (is_partial) {
|
|
|
|
// only the first server message is known
|
|
|
|
// delete all definitely deleted server messages and insert the new message in the correct place
|
2024-02-22 19:44:13 +01:00
|
|
|
auto old_message_ids = get_quick_reply_unique_ids(old_shortcut->messages_);
|
2024-02-22 17:45:49 +01:00
|
|
|
auto new_first_message_id = new_shortcut->messages_[0]->message_id;
|
|
|
|
auto it = old_shortcut->messages_.begin();
|
|
|
|
while (it != old_shortcut->messages_.end() && (*it)->message_id < new_first_message_id) {
|
|
|
|
if ((*it)->message_id.is_server()) {
|
2024-02-29 17:01:40 +01:00
|
|
|
delete_message_files(old_shortcut->shortcut_id_, it->get());
|
2024-02-22 17:45:49 +01:00
|
|
|
it = old_shortcut->messages_.erase(it);
|
|
|
|
} else {
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (it == old_shortcut->messages_.end() || (*it)->message_id != new_first_message_id) {
|
2024-02-29 19:05:56 +01:00
|
|
|
change_message_files({old_shortcut->shortcut_id_, new_first_message_id}, new_shortcut->messages_[0].get(), {});
|
2024-02-22 17:45:49 +01:00
|
|
|
old_shortcut->messages_.insert(it, std::move(new_shortcut->messages_[0]));
|
2024-02-22 19:40:07 +01:00
|
|
|
} else {
|
2024-02-29 18:58:30 +01:00
|
|
|
update_quick_reply_message(old_shortcut->shortcut_id_, *it, std::move(new_shortcut->messages_[0]));
|
2024-02-22 17:45:49 +01:00
|
|
|
}
|
|
|
|
new_shortcut->messages_ = std::move(old_shortcut->messages_);
|
2024-03-05 16:12:05 +01:00
|
|
|
*are_messages_changed = (old_message_ids != get_quick_reply_unique_ids(new_shortcut->messages_));
|
2024-03-05 12:17:18 +01:00
|
|
|
|
|
|
|
int32 server_total_count = 0;
|
|
|
|
for (const auto &message : new_shortcut->messages_) {
|
|
|
|
if (message->message_id.is_server()) {
|
|
|
|
server_total_count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (server_total_count > new_shortcut->server_total_count_) {
|
|
|
|
new_shortcut->server_total_count_ = server_total_count;
|
|
|
|
}
|
2024-02-22 17:45:49 +01:00
|
|
|
} else {
|
2024-02-22 19:44:13 +01:00
|
|
|
auto old_server_message_ids = get_server_quick_reply_unique_ids(old_shortcut->messages_);
|
|
|
|
auto new_server_message_ids = get_server_quick_reply_unique_ids(new_shortcut->messages_);
|
2024-03-05 12:17:18 +01:00
|
|
|
CHECK(static_cast<size_t>(new_shortcut->server_total_count_) == new_server_message_ids.size());
|
2024-02-22 17:45:49 +01:00
|
|
|
if (old_server_message_ids == new_server_message_ids) {
|
2024-03-05 16:12:05 +01:00
|
|
|
*are_messages_changed = false;
|
2024-02-22 17:45:49 +01:00
|
|
|
new_shortcut->messages_ = std::move(old_shortcut->messages_);
|
|
|
|
} else {
|
2024-03-05 16:12:05 +01:00
|
|
|
*are_messages_changed = true;
|
2024-02-29 17:01:40 +01:00
|
|
|
for (auto &old_message : old_shortcut->messages_) {
|
2024-02-29 18:58:30 +01:00
|
|
|
CHECK(old_message != nullptr);
|
2024-02-29 17:01:40 +01:00
|
|
|
if (!old_message->message_id.is_server()) {
|
|
|
|
new_shortcut->messages_.push_back(std::move(old_message));
|
|
|
|
} else {
|
|
|
|
bool is_deleted = true;
|
|
|
|
for (auto &new_message : new_shortcut->messages_) {
|
|
|
|
if (new_message->message_id == old_message->message_id) {
|
2024-02-29 18:58:30 +01:00
|
|
|
update_quick_reply_message(old_shortcut->shortcut_id_, old_message, std::move(new_message));
|
|
|
|
new_message = std::move(old_message);
|
2024-02-29 17:01:40 +01:00
|
|
|
is_deleted = false;
|
2024-02-29 18:58:30 +01:00
|
|
|
break;
|
2024-02-29 17:01:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (is_deleted) {
|
|
|
|
delete_message_files(old_shortcut->shortcut_id_, old_message.get());
|
|
|
|
}
|
2024-02-22 17:45:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
sort_quick_reply_messages(new_shortcut->messages_);
|
|
|
|
}
|
|
|
|
}
|
2024-03-05 12:17:18 +01:00
|
|
|
new_shortcut->local_total_count_ = old_shortcut->local_total_count_;
|
2024-03-05 16:12:05 +01:00
|
|
|
*is_shortcut_changed = old_unique_id != get_quick_reply_unique_id(new_shortcut->messages_[0].get()) ||
|
|
|
|
new_shortcut->name_ != old_shortcut->name_ ||
|
|
|
|
old_message_count != get_shortcut_message_count(new_shortcut);
|
2024-02-22 17:45:49 +01:00
|
|
|
}
|
|
|
|
|
2024-02-27 21:47:29 +01:00
|
|
|
string QuickReplyManager::get_quick_reply_shortcuts_database_key() {
|
|
|
|
return "quick_reply_shortcuts";
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::save_quick_reply_shortcuts() {
|
2024-03-05 14:25:39 +01:00
|
|
|
CHECK(shortcuts_.are_inited_);
|
2024-02-27 21:47:29 +01:00
|
|
|
G()->td_db()->get_binlog_pmc()->set(get_quick_reply_shortcuts_database_key(),
|
|
|
|
log_event_store(shortcuts_).as_slice().str());
|
|
|
|
}
|
|
|
|
|
2024-03-05 13:30:57 +01:00
|
|
|
void QuickReplyManager::load_quick_reply_shortcuts() {
|
2024-03-05 15:58:40 +01:00
|
|
|
CHECK(!td_->auth_manager_->is_bot());
|
2024-03-05 13:30:57 +01:00
|
|
|
if (shortcuts_.are_loaded_from_database_) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
shortcuts_.are_loaded_from_database_ = true;
|
2024-03-05 14:25:39 +01:00
|
|
|
CHECK(shortcuts_.load_queries_.empty());
|
2024-03-05 13:30:57 +01:00
|
|
|
|
|
|
|
auto shortcuts_str = G()->td_db()->get_binlog_pmc()->get(get_quick_reply_shortcuts_database_key());
|
|
|
|
auto status = log_event_parse(shortcuts_, shortcuts_str);
|
|
|
|
if (status.is_error()) {
|
|
|
|
LOG(ERROR) << "Can't load quick replies: " << status;
|
|
|
|
G()->td_db()->get_binlog_pmc()->erase(get_quick_reply_shortcuts_database_key());
|
|
|
|
shortcuts_.shortcuts_.clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Dependencies dependencies;
|
|
|
|
for (const auto &shortcut : shortcuts_.shortcuts_) {
|
|
|
|
for (const auto &message : shortcut->messages_) {
|
|
|
|
add_quick_reply_message_dependencies(dependencies, message.get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!dependencies.resolve_force(td_, "load_quick_reply_shortcuts")) {
|
|
|
|
shortcuts_.shortcuts_.clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
shortcuts_.are_inited_ = true;
|
2024-04-17 17:39:25 +02:00
|
|
|
for (auto &shortcut : shortcuts_.shortcuts_) {
|
2024-04-15 22:36:27 +02:00
|
|
|
if (shortcut->shortcut_id_.get() >= next_local_shortcut_id_) {
|
|
|
|
next_local_shortcut_id_ = shortcut->shortcut_id_.get() + 1;
|
|
|
|
}
|
2024-04-17 17:39:25 +02:00
|
|
|
for (auto &message : shortcut->messages_) {
|
|
|
|
if (message->shortcut_id != shortcut->shortcut_id_) {
|
|
|
|
LOG(ERROR) << "Receive quick reply " << message->message_id << " in " << message->shortcut_id << " instead of "
|
|
|
|
<< shortcut->shortcut_id_;
|
|
|
|
message->shortcut_id = shortcut->shortcut_id_;
|
|
|
|
}
|
2024-03-05 13:30:57 +01:00
|
|
|
change_message_files({shortcut->shortcut_id_, message->message_id}, message.get(), {});
|
2024-03-05 13:49:42 +01:00
|
|
|
|
|
|
|
if (message->message_id.is_server()) {
|
|
|
|
if (need_reget_message_content(message->content.get()) ||
|
|
|
|
(message->legacy_layer != 0 && message->legacy_layer < MTPROTO_LAYER)) {
|
|
|
|
reload_quick_reply_message(shortcut->shortcut_id_, message->message_id, Promise<Unit>());
|
|
|
|
}
|
2024-04-17 17:39:25 +02:00
|
|
|
} else if (message->message_id.is_yet_unsent()) {
|
|
|
|
do_send_message(message.get());
|
2024-03-05 13:49:42 +01:00
|
|
|
}
|
2024-03-05 13:30:57 +01:00
|
|
|
}
|
|
|
|
send_update_quick_reply_shortcut(shortcut.get(), "load_quick_reply_shortcuts");
|
|
|
|
send_update_quick_reply_shortcut_messages(shortcut.get(), "load_quick_reply_shortcuts");
|
|
|
|
}
|
|
|
|
|
|
|
|
send_update_quick_reply_shortcuts();
|
|
|
|
|
|
|
|
reload_quick_reply_shortcuts();
|
|
|
|
}
|
|
|
|
|
2024-02-22 19:23:19 +01:00
|
|
|
td_api::object_ptr<td_api::updateQuickReplyShortcut> QuickReplyManager::get_update_quick_reply_shortcut_object(
|
|
|
|
const Shortcut *s, const char *source) const {
|
|
|
|
return td_api::make_object<td_api::updateQuickReplyShortcut>(get_quick_reply_shortcut_object(s, source));
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::send_update_quick_reply_shortcut(const Shortcut *s, const char *source) {
|
|
|
|
send_closure(G()->td(), &Td::send_update, get_update_quick_reply_shortcut_object(s, source));
|
|
|
|
}
|
|
|
|
|
|
|
|
td_api::object_ptr<td_api::updateQuickReplyShortcutDeleted>
|
|
|
|
QuickReplyManager::get_update_quick_reply_shortcut_deleted_object(const Shortcut *s) const {
|
|
|
|
CHECK(s != nullptr);
|
2024-02-27 16:10:11 +01:00
|
|
|
return td_api::make_object<td_api::updateQuickReplyShortcutDeleted>(s->shortcut_id_.get());
|
2024-02-22 19:23:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::send_update_quick_reply_shortcut_deleted(const Shortcut *s) {
|
|
|
|
send_closure(G()->td(), &Td::send_update, get_update_quick_reply_shortcut_deleted_object(s));
|
|
|
|
}
|
|
|
|
|
2024-02-22 20:55:09 +01:00
|
|
|
td_api::object_ptr<td_api::updateQuickReplyShortcuts> QuickReplyManager::get_update_quick_reply_shortcuts_object()
|
|
|
|
const {
|
|
|
|
CHECK(shortcuts_.are_inited_);
|
2024-02-27 16:10:11 +01:00
|
|
|
return td_api::make_object<td_api::updateQuickReplyShortcuts>(transform(
|
|
|
|
shortcuts_.shortcuts_, [](const unique_ptr<Shortcut> &shortcut) { return shortcut->shortcut_id_.get(); }));
|
2024-02-22 20:55:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::send_update_quick_reply_shortcuts() {
|
|
|
|
send_closure(G()->td(), &Td::send_update, get_update_quick_reply_shortcuts_object());
|
|
|
|
}
|
|
|
|
|
2024-02-29 13:55:38 +01:00
|
|
|
td_api::object_ptr<td_api::updateQuickReplyShortcutMessages>
|
2024-02-29 14:10:15 +01:00
|
|
|
QuickReplyManager::get_update_quick_reply_shortcut_messages_object(const Shortcut *s, const char *source) const {
|
2024-02-29 13:55:38 +01:00
|
|
|
CHECK(s != nullptr);
|
2024-02-29 14:10:15 +01:00
|
|
|
auto messages = transform(s->messages_, [this, source](const unique_ptr<QuickReplyMessage> &message) {
|
|
|
|
return get_quick_reply_message_object(message.get(), source);
|
2024-02-29 13:55:38 +01:00
|
|
|
});
|
|
|
|
return td_api::make_object<td_api::updateQuickReplyShortcutMessages>(s->shortcut_id_.get(), std::move(messages));
|
|
|
|
}
|
|
|
|
|
2024-02-29 14:10:15 +01:00
|
|
|
void QuickReplyManager::send_update_quick_reply_shortcut_messages(const Shortcut *s, const char *source) {
|
2024-02-29 13:55:38 +01:00
|
|
|
if (have_all_shortcut_messages(s)) {
|
2024-02-29 14:10:15 +01:00
|
|
|
send_closure(G()->td(), &Td::send_update, get_update_quick_reply_shortcut_messages_object(s, source));
|
2024-02-29 13:55:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-29 17:01:40 +01:00
|
|
|
vector<FileId> QuickReplyManager::get_message_file_ids(const QuickReplyMessage *m) const {
|
|
|
|
if (m == nullptr) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
return get_message_content_file_ids(m->content.get(), td_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::delete_message_files(QuickReplyShortcutId shortcut_id, const QuickReplyMessage *m) const {
|
2024-02-29 19:05:56 +01:00
|
|
|
CHECK(m != nullptr);
|
|
|
|
auto file_ids = get_message_file_ids(m);
|
|
|
|
if (file_ids.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (auto file_id : file_ids) {
|
2024-02-29 17:01:40 +01:00
|
|
|
send_closure(G()->file_manager(), &FileManager::delete_file, file_id, Promise<Unit>(), "delete_message_files");
|
|
|
|
}
|
2024-02-29 19:05:56 +01:00
|
|
|
auto it = message_full_id_to_file_source_id_.find({shortcut_id, m->message_id});
|
|
|
|
if (it != message_full_id_to_file_source_id_.end()) {
|
|
|
|
td_->file_manager_->change_files_source(it->second, file_ids, {});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickReplyManager::change_message_files(QuickReplyMessageFullId message_full_id, const QuickReplyMessage *m,
|
|
|
|
const vector<FileId> &old_file_ids) {
|
|
|
|
CHECK(m != nullptr);
|
|
|
|
auto new_file_ids = get_message_file_ids(m);
|
|
|
|
if (new_file_ids == old_file_ids) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto file_id : old_file_ids) {
|
|
|
|
if (!td::contains(new_file_ids, file_id)) {
|
|
|
|
send_closure(G()->file_manager(), &FileManager::delete_file, file_id, Promise<Unit>(), "change_message_files");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
auto file_source_id = get_quick_reply_message_file_source_id(message_full_id);
|
|
|
|
if (file_source_id.is_valid()) {
|
|
|
|
td_->file_manager_->change_files_source(file_source_id, old_file_ids, new_file_ids);
|
|
|
|
}
|
2024-02-29 17:01:40 +01:00
|
|
|
}
|
|
|
|
|
2024-02-29 15:41:05 +01:00
|
|
|
FileSourceId QuickReplyManager::get_quick_reply_message_file_source_id(QuickReplyMessageFullId message_full_id) {
|
|
|
|
if (td_->auth_manager_->is_bot()) {
|
|
|
|
return FileSourceId();
|
|
|
|
}
|
|
|
|
if (!message_full_id.is_server()) {
|
|
|
|
return FileSourceId();
|
|
|
|
}
|
|
|
|
|
|
|
|
auto &file_source_id = message_full_id_to_file_source_id_[message_full_id];
|
|
|
|
if (!file_source_id.is_valid()) {
|
|
|
|
file_source_id = td_->file_reference_manager_->create_quick_reply_message_file_source(message_full_id);
|
|
|
|
}
|
|
|
|
return file_source_id;
|
|
|
|
}
|
|
|
|
|
2024-02-22 19:26:17 +01:00
|
|
|
void QuickReplyManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const {
|
|
|
|
if (td_->auth_manager_->is_bot()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-02-22 20:55:09 +01:00
|
|
|
if (shortcuts_.are_inited_) {
|
2024-03-05 16:02:11 +01:00
|
|
|
for (auto &shortcut : shortcuts_.shortcuts_) {
|
|
|
|
updates.push_back(get_update_quick_reply_shortcut_object(shortcut.get(), "get_current_state"));
|
|
|
|
if (have_all_shortcut_messages(shortcut.get())) {
|
|
|
|
updates.push_back(get_update_quick_reply_shortcut_messages_object(shortcut.get(), "get_current_state"));
|
|
|
|
}
|
2024-02-29 13:55:38 +01:00
|
|
|
}
|
2024-03-05 16:02:11 +01:00
|
|
|
|
|
|
|
updates.push_back(get_update_quick_reply_shortcuts_object());
|
2024-02-29 13:55:38 +01:00
|
|
|
}
|
2024-02-22 19:26:17 +01:00
|
|
|
}
|
|
|
|
|
2024-02-21 18:43:55 +01:00
|
|
|
} // namespace td
|