diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index b7f90fc76..d011665b6 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -4213,7 +4213,8 @@ string ContactsManager::get_chat_invite_link(ChatId chat_id) const { return chat_full->invite_link; } -string ContactsManager::get_channel_invite_link(ChannelId channel_id) const { +string ContactsManager::get_channel_invite_link( + ChannelId channel_id) { // should be non-const to update ChannelFull cache auto channel_full = get_channel_full(channel_id); if (channel_full == nullptr) { auto it = channel_invite_links_.find(channel_id); @@ -4222,7 +4223,8 @@ string ContactsManager::get_channel_invite_link(ChannelId channel_id) const { return channel_full->invite_link; } -MessageId ContactsManager::get_channel_pinned_message_id(ChannelId channel_id) const { +MessageId ContactsManager::get_channel_pinned_message_id( + ChannelId channel_id) { // should be non-const to update ChannelFull cache auto channel_full = get_channel_full(channel_id); if (channel_full == nullptr) { return MessageId(); @@ -8247,9 +8249,16 @@ ContactsManager::ChannelFull *ContactsManager::get_channel_full(ChannelId channe auto p = channels_full_.find(channel_id); if (p == channels_full_.end()) { return nullptr; - } else { - return &p->second; } + + auto channel_full = &p->second; + if (channel_full->is_expired()) { + auto input_channel = get_input_channel(channel_id); + CHECK(input_channel != nullptr); + send_get_channel_full_query(channel_id, std::move(input_channel), Auto()); + } + + return channel_full; } bool ContactsManager::get_channel_full(ChannelId channel_id, Promise &&promise) { @@ -8265,13 +8274,14 @@ bool ContactsManager::get_channel_full(ChannelId channel_id, Promise &&pro return false; } if (channel_full->is_expired()) { - auto input_channel = get_input_channel(channel_id); - CHECK(input_channel != nullptr); if (td_->auth_manager_->is_bot()) { + auto input_channel = get_input_channel(channel_id); + CHECK(input_channel != nullptr); send_get_channel_full_query(channel_id, std::move(input_channel), std::move(promise)); return false; } else { - send_get_channel_full_query(channel_id, std::move(input_channel), Auto()); + // request was already sent in get_channel_full + // send_get_channel_full_query(channel_id, std::move(input_channel), Auto()); } } diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 9496b9612..3af87691f 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -304,9 +304,9 @@ class ContactsManager : public Actor { string get_chat_invite_link(ChatId chat_id) const; - string get_channel_invite_link(ChannelId channel_id) const; + string get_channel_invite_link(ChannelId channel_id); - MessageId get_channel_pinned_message_id(ChannelId channel_id) const; + MessageId get_channel_pinned_message_id(ChannelId channel_id); ChannelId migrate_chat_to_megagroup(ChatId chat_id, Promise &promise); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 76d23437a..a2dee92f4 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -373,6 +373,76 @@ class GetChannelMessagesQuery : public Td::ResultHandler { } }; +class GetChannelPinnedMessageQuery : public Td::ResultHandler { + Promise promise_; + ChannelId channel_id_; + + public: + explicit GetChannelPinnedMessageQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(ChannelId channel_id) { + auto input_channel = td->contacts_manager_->get_input_channel(channel_id); + if (input_channel == nullptr) { + return promise_.set_error(Status::Error(6, "Can't access the chat")); + } + + channel_id_ = channel_id; + vector> input_messages; + input_messages.push_back(make_tl_object()); + send_query(G()->net_query_creator().create( + create_storer(telegram_api::channels_getMessages(std::move(input_channel), std::move(input_messages))))); + } + + void on_result(uint64 id, BufferSlice packet) override { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(id, result_ptr.move_as_error()); + } + + auto ptr = result_ptr.move_as_ok(); + LOG(DEBUG) << "Receive result for GetChannelPinnedMessageQuery " << to_string(ptr); + int32 constructor_id = ptr->get_id(); + switch (constructor_id) { + case telegram_api::messages_messages::ID: + case telegram_api::messages_messagesSlice::ID: + LOG(ERROR) << "Receive ordinary messages in GetChannelPinnedMessageQuery " << to_string(ptr); + return promise_.set_error(Status::Error(500, "Receive wrong request result")); + case telegram_api::messages_channelMessages::ID: { + auto messages = move_tl_object_as(ptr); + + td->contacts_manager_->on_get_chats(std::move(messages->chats_)); + td->contacts_manager_->on_get_users(std::move(messages->users_)); + if (messages->messages_.empty()) { + return promise_.set_value(MessageId()); + } + if (messages->messages_.size() >= 2) { + LOG(ERROR) << to_string(ptr); + return promise_.set_error(Status::Error(500, "More than 1 pinned message received")); + } + auto full_message_id = td->messages_manager_->on_get_message(std::move(messages->messages_[0]), false, true, + false, false, "get channel pinned messages"); + if (full_message_id.get_dialog_id().is_valid() && full_message_id.get_dialog_id() != DialogId(channel_id_)) { + LOG(ERROR) << full_message_id << " " << to_string(ptr); + return promise_.set_error(Status::Error(500, "Receive pinned message in a wrong chat")); + } + return promise_.set_value(full_message_id.get_message_id()); + } + default: + UNREACHABLE(); + } + } + + void on_error(uint64 id, Status status) override { + if (status.message() == "MESSAGE_IDS_EMPTY") { + promise_.set_value(MessageId()); + return; + } + td->contacts_manager_->on_get_channel_error(channel_id_, status, "GetChannelPinnedMessageQuery"); + promise_.set_error(std::move(status)); + } +}; + class ExportChannelMessageLinkQuery : public Td::ResultHandler { Promise promise_; ChannelId channel_id_; @@ -10966,31 +11036,23 @@ MessageId MessagesManager::get_replied_message(DialogId dialog_id, MessageId mes return replied_message_id; } -MessageId MessagesManager::get_dialog_pinned_message(DialogId dialog_id, bool force, Promise &&promise) { +void MessagesManager::get_dialog_pinned_message(DialogId dialog_id, Promise &&promise) { Dialog *d = get_dialog_force(dialog_id); if (d == nullptr) { - promise.set_error(Status::Error(6, "Chat not found")); - return MessageId(); + return promise.set_error(Status::Error(6, "Chat not found")); } if (dialog_id.get_type() != DialogType::Channel) { - promise.set_value(Unit()); - return MessageId(); + return promise.set_value(MessageId()); } auto channel_id = dialog_id.get_channel_id(); auto message_id = td_->contacts_manager_->get_channel_pinned_message_id(channel_id); - if (!message_id.is_valid()) { - if (force) { - promise.set_value(Unit()); - } else { - td_->contacts_manager_->get_channel_full(channel_id, std::move(promise)); - } - return MessageId(); + if (get_message_force(d, message_id) == nullptr) { + return td_->create_handler(std::move(promise))->send(channel_id); } - get_message_force_from_server(d, message_id, std::move(promise)); - return message_id; + promise.set_value(std::move(message_id)); } bool MessagesManager::get_messages(DialogId dialog_id, const vector &message_ids, Promise &&promise) { @@ -11076,6 +11138,7 @@ void MessagesManager::get_messages_from_server(vector &&message_i auto input_channel = td_->contacts_manager_->get_input_channel(it.first); if (input_channel == nullptr) { LOG(ERROR) << "Can't find info about " << it.first << " to get a message from it"; + promise.set_error(Status::Error(6, "Can't access the chat")); continue; } td_->create_handler(std::move(promise)) diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 7ef5b5819..d77d81ac5 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1105,7 +1105,7 @@ class MessagesManager : public Actor { MessageId get_replied_message(DialogId dialog_id, MessageId message_id, bool force, Promise &&promise); - MessageId get_dialog_pinned_message(DialogId dialog_id, bool force, Promise &&promise); + void get_dialog_pinned_message(DialogId dialog_id, Promise &&promise); bool get_messages(DialogId dialog_id, const vector &message_ids, Promise &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index f27cef769..745be5e1f 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1056,14 +1056,22 @@ class GetRepliedMessageRequest : public RequestOnceActor { } }; -class GetChatPinnedMessageRequest : public RequestActor<> { +class GetChatPinnedMessageRequest : public RequestActor { DialogId dialog_id_; MessageId pinned_message_id_; - void do_run(Promise &&promise) override { - pinned_message_id_ = - td->messages_manager_->get_dialog_pinned_message(dialog_id_, get_tries() < 3, std::move(promise)); + void do_run(Promise &&promise) override { + if (get_tries() < 2) { + promise.set_value(std::move(pinned_message_id_)); + return; + } + + td->messages_manager_->get_dialog_pinned_message(dialog_id_, std::move(promise)); + } + + void do_set_result(MessageId &&result) override { + pinned_message_id_ = result; } void do_send_result() override { @@ -1072,8 +1080,7 @@ class GetChatPinnedMessageRequest : public RequestActor<> { public: GetChatPinnedMessageRequest(ActorShared td, uint64 request_id, int64 dialog_id) - : RequestActor<>(std::move(td), request_id), dialog_id_(dialog_id) { - set_tries(3); + : RequestActor(std::move(td), request_id), dialog_id_(dialog_id) { } };