diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 8b971bfb4..fa00d7e75 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1154,6 +1154,9 @@ chatMessageSender sender:MessageSender needs_premium:Bool = ChatMessageSender; chatMessageSenders senders:vector = ChatMessageSenders; +//@description Contains read date of a recent outgoing message in a private chat @read_date Point in time (Unix timestamp) when the message was read by the other user +messageReadDate read_date:int32 = MessageReadDate; + //@description Represents a viewer of a message @user_id User identifier of the viewer @view_date Approximate point in time (Unix timestamp) when the message was viewed messageViewer user_id:int53 view_date:int32 = MessageViewer; @@ -7088,6 +7091,11 @@ getMessages chat_id:int53 message_ids:vector = Messages; //@description Returns information about a message thread. Can be used only if message.can_get_message_thread == true @chat_id Chat identifier @message_id Identifier of the message getMessageThread chat_id:int53 message_id:int53 = MessageThreadInfo; +//@description Returns read date of a recent outgoing message in a private chat. The method can be called if message.can_get_read_date == true +//@chat_id Chat identifier +//@message_id Identifier of the message +getMessageReadDate chat_id:int53 message_id:int53 = MessageReadDate; + //@description Returns viewers of a recent outgoing message in a basic group or a supergroup chat. For video notes and voice notes only users, opened content of the message, are returned. The method can be called if message.can_get_viewers == true //@chat_id Chat identifier //@message_id Identifier of the message diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index b02c7607d..babf7862a 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -717,6 +717,41 @@ class UnpinAllMessagesQuery final : public Td::ResultHandler { } }; +class GetOutboxReadDateQuery final : public Td::ResultHandler { + Promise> promise_; + DialogId dialog_id_; + MessageId message_id_; + + public: + explicit GetOutboxReadDateQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(DialogId dialog_id, MessageId message_id) { + dialog_id_ = dialog_id; + message_id_ = message_id; + auto input_peer = td_->dialog_manager_->get_input_peer(dialog_id, AccessRights::Read); + CHECK(input_peer != nullptr); + send_query(G()->net_query_creator().create( + telegram_api::messages_getOutboxReadDate(std::move(input_peer), message_id.get_server_message_id().get()))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + auto ptr = result_ptr.move_as_ok(); + promise_.set_value(td_api::make_object(ptr->date_)); + } + + void on_error(Status status) final { + td_->messages_manager_->on_get_message_error(dialog_id_, message_id_, status, "GetOutboxReadDateQuery"); + promise_.set_error(std::move(status)); + } +}; + class GetMessageReadParticipantsQuery final : public Td::ResultHandler { Promise promise_; DialogId dialog_id_; @@ -17107,14 +17142,74 @@ td_api::object_ptr MessagesManager::get_message_threa info.unread_message_count, std::move(messages), std::move(draft_message)); } -Status MessagesManager::can_get_message_viewers(MessageFullId message_full_id) { +Status MessagesManager::can_get_message_read_date(MessageFullId message_full_id) { auto dialog_id = message_full_id.get_dialog_id(); - Dialog *d = get_dialog_force(dialog_id, "get_message_viewers"); + Dialog *d = get_dialog_force(dialog_id, "can_get_message_read_date"); if (d == nullptr) { return Status::Error(400, "Chat not found"); } - auto m = get_message_force(d, message_full_id.get_message_id(), "get_message_viewers"); + auto m = get_message_force(d, message_full_id.get_message_id(), "can_get_message_read_date"); + if (m == nullptr) { + return Status::Error(400, "Message not found"); + } + + return can_get_message_read_date(dialog_id, m); +} + +Status MessagesManager::can_get_message_read_date(DialogId dialog_id, const Message *m) const { + if (td_->auth_manager_->is_bot()) { + return Status::Error(400, "User is bot"); + } + CHECK(m != nullptr); + if (!m->is_outgoing) { + return Status::Error(400, "Can't get read date of incoming messages"); + } + + if (dialog_id.get_type() != DialogType::User) { + return Status::Error(400, "Read date can be received only in private chats"); + } + if (!td_->dialog_manager_->have_input_peer(dialog_id, AccessRights::Read)) { + return Status::Error(400, "Can't access the chat"); + } + auto user_id = dialog_id.get_user_id(); + if (td_->contacts_manager_->is_user_bot(user_id)) { + return Status::Error(400, "The user is a bot"); + } + if (td_->contacts_manager_->is_user_support(user_id)) { + return Status::Error(400, "The user is a Telegram support account"); + } + + if (m->message_id.is_scheduled()) { + return Status::Error(400, "Scheduled messages can't be read"); + } + if (m->message_id.is_yet_unsent()) { + return Status::Error(400, "Yet unsent messages can't be read"); + } + if (m->message_id.is_local()) { + return Status::Error(400, "Local messages can't be read"); + } + CHECK(m->message_id.is_server()); + + return Status::OK(); +} + +void MessagesManager::get_message_read_date(MessageFullId message_full_id, + Promise> &&promise) { + TRY_STATUS_PROMISE(promise, can_get_message_read_date(message_full_id)); + + td_->create_handler(std::move(promise)) + ->send(message_full_id.get_dialog_id(), message_full_id.get_message_id()); +} + +Status MessagesManager::can_get_message_viewers(MessageFullId message_full_id) { + auto dialog_id = message_full_id.get_dialog_id(); + Dialog *d = get_dialog_force(dialog_id, "can_get_message_viewers"); + if (d == nullptr) { + return Status::Error(400, "Chat not found"); + } + + auto m = get_message_force(d, message_full_id.get_message_id(), "can_get_message_viewers"); if (m == nullptr) { return Status::Error(400, "Message not found"); } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 5a876926a..c5d828018 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -606,6 +606,9 @@ class MessagesManager final : public Actor { DialogId dialog_id, MessageId message_id, DialogId expected_dialog_id, MessageId expected_message_id, Promise promise); + void get_message_read_date(MessageFullId message_full_id, + Promise> &&promise); + void get_message_viewers(MessageFullId message_full_id, Promise> &&promise); @@ -1705,6 +1708,10 @@ class MessagesManager final : public Actor { bool can_report_message_reactions(DialogId dialog_id, const Message *m) const; + Status can_get_message_read_date(MessageFullId message_full_id) TD_WARN_UNUSED_RESULT; + + Status can_get_message_read_date(DialogId dialog_id, const Message *m) const TD_WARN_UNUSED_RESULT; + Status can_get_message_viewers(MessageFullId message_full_id) TD_WARN_UNUSED_RESULT; Status can_get_message_viewers(DialogId dialog_id, const Message *m) const TD_WARN_UNUSED_RESULT; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 699a929f1..b1e493e70 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -4704,6 +4704,13 @@ void Td::on_request(uint64 id, const td_api::getMessageThread &request) { CREATE_REQUEST(GetMessageThreadRequest, request.chat_id_, request.message_id_); } +void Td::on_request(uint64 id, const td_api::getMessageReadDate &request) { + CHECK_IS_USER(); + CREATE_REQUEST_PROMISE(); + messages_manager_->get_message_read_date({DialogId(request.chat_id_), MessageId(request.message_id_)}, + std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::getMessageViewers &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index b5919cdf2..5f7a098ce 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -605,6 +605,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::getMessageThread &request); + void on_request(uint64 id, const td_api::getMessageReadDate &request); + void on_request(uint64 id, const td_api::getMessageViewers &request); void on_request(uint64 id, const td_api::getMessages &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 5d13a3f96..6ad363e0c 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3652,6 +3652,11 @@ class CliClient final : public Actor { MessageId message_id; get_args(args, chat_id, message_id); send_request(td_api::make_object(chat_id, message_id)); + } else if (op == "gmrd") { + ChatId chat_id; + MessageId message_id; + get_args(args, chat_id, message_id); + send_request(td_api::make_object(chat_id, message_id)); } else if (op == "gmv") { ChatId chat_id; MessageId message_id;