diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 4724cea07..6f437233f 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -440,7 +440,7 @@ basicGroupFullInfo description:string creator_user_id:int32 members:vector promise_; + ChannelId broadcast_channel_id_; + ChannelId group_channel_id_; + + public: + explicit SetDiscussionGroupQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(ChannelId broadcast_channel_id, + telegram_api::object_ptr broadcast_input_channel, ChannelId group_channel_id, + telegram_api::object_ptr group_input_channel) { + broadcast_channel_id_ = broadcast_channel_id; + group_channel_id_ = group_channel_id; + send_query(G()->net_query_creator().create(create_storer(telegram_api::channels_setDiscussionGroup( + std::move(broadcast_input_channel), std::move(group_input_channel))))); + } + + 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()); + } + + bool result = result_ptr.move_as_ok(); + LOG_IF(INFO, !result) << "Set discussion group has failed"; + + td->contacts_manager_->on_update_channel_linked_channel_id(broadcast_channel_id_, group_channel_id_); + promise_.set_value(Unit()); + } + + void on_error(uint64 id, Status status) override { + if (status.message() == "LINK_NOT_MODIFIED") { + return promise_.set_value(Unit()); + } + promise_.set_error(std::move(status)); + } +}; + class ReportChannelSpamQuery : public Td::ResultHandler { Promise promise_; ChannelId channel_id_; @@ -4303,6 +4342,76 @@ void ContactsManager::set_channel_description(ChannelId channel_id, const string td_->create_handler(std::move(promise))->send(DialogId(channel_id), new_description); } +void ContactsManager::set_channel_discussion_group(DialogId dialog_id, DialogId discussion_dialog_id, + Promise &&promise) { + if (!dialog_id.is_valid() && !discussion_dialog_id.is_valid()) { + return promise.set_error(Status::Error(400, "Invalid chat identifiers specified")); + } + + ChannelId broadcast_channel_id; + telegram_api::object_ptr broadcast_input_channel; + if (dialog_id.is_valid()) { + if (!td_->messages_manager_->have_dialog_force(dialog_id)) { + return promise.set_error(Status::Error(400, "Chat not found")); + } + + if (dialog_id.get_type() != DialogType::Channel) { + return promise.set_error(Status::Error(400, "Chat is not a channel")); + } + + broadcast_channel_id = dialog_id.get_channel_id(); + const Channel *c = get_channel(broadcast_channel_id); + if (c == nullptr) { + return promise.set_error(Status::Error(400, "Chat info not found")); + } + + if (c->is_megagroup) { + return promise.set_error(Status::Error(400, "Chat is not a channel")); + } + if (!c->status.is_administrator() || !c->status.can_change_info_and_settings()) { + return promise.set_error(Status::Error(400, "Have not enough rights in the channel")); + } + + broadcast_input_channel = td_->contacts_manager_->get_input_channel(broadcast_channel_id); + CHECK(broadcast_input_channel != nullptr); + } else { + broadcast_input_channel = telegram_api::make_object(); + } + + ChannelId group_channel_id; + telegram_api::object_ptr group_input_channel; + if (discussion_dialog_id.is_valid()) { + if (!td_->messages_manager_->have_dialog_force(discussion_dialog_id)) { + return promise.set_error(Status::Error(400, "Discussion chat not found")); + } + if (discussion_dialog_id.get_type() != DialogType::Channel) { + return promise.set_error(Status::Error(400, "Discussion chat is not a supergroup")); + } + + group_channel_id = discussion_dialog_id.get_channel_id(); + const Channel *c = get_channel(group_channel_id); + if (c == nullptr) { + return promise.set_error(Status::Error(400, "Discussion chat info not found")); + } + + if (!c->is_megagroup) { + return promise.set_error(Status::Error(400, "Discussion chat is not a supergroup")); + } + if (!c->status.is_administrator() || !c->status.can_pin_messages()) { + return promise.set_error(Status::Error(400, "Have not enough rights in the supergroup")); + } + + group_input_channel = td_->contacts_manager_->get_input_channel(group_channel_id); + CHECK(group_input_channel != nullptr); + } else { + group_input_channel = telegram_api::make_object(); + } + + td_->create_handler(std::move(promise)) + ->send(broadcast_channel_id, std::move(broadcast_input_channel), group_channel_id, + std::move(group_input_channel)); +} + void ContactsManager::report_channel_spam(ChannelId channel_id, UserId user_id, const vector &message_ids, Promise &&promise) { auto c = get_channel(channel_id); @@ -8180,13 +8289,13 @@ void ContactsManager::on_update_channel_full_invite_link( void ContactsManager::on_update_channel_full_linked_channel_id(ChannelFull *channel_full, ChannelId channel_id, ChannelId linked_channel_id) { - CHECK(channel_full != nullptr); - if (channel_full->linked_channel_id != linked_channel_id) { + if (channel_full != nullptr && channel_full->linked_channel_id != linked_channel_id) { if (channel_full->linked_channel_id.is_valid()) { // remove link from a previously linked channel_full auto linked_channel = get_channel_force(channel_full->linked_channel_id); if (linked_channel != nullptr && linked_channel->has_linked_channel) { linked_channel->has_linked_channel = false; + linked_channel->need_send_update = true; update_channel(linked_channel, channel_full->linked_channel_id); reload_channel(channel_full->linked_channel_id, Auto()); } @@ -8206,6 +8315,7 @@ void ContactsManager::on_update_channel_full_linked_channel_id(ChannelFull *chan auto linked_channel = get_channel_force(channel_full->linked_channel_id); if (linked_channel != nullptr && !linked_channel->has_linked_channel) { linked_channel->has_linked_channel = true; + linked_channel->need_send_update = true; update_channel(linked_channel, channel_full->linked_channel_id); reload_channel(channel_full->linked_channel_id, Auto()); } @@ -8972,6 +9082,23 @@ void ContactsManager::on_update_channel_sticker_set(ChannelId channel_id, int64 } } +void ContactsManager::on_update_channel_linked_channel_id(ChannelId channel_id, ChannelId group_channel_id) { + if (channel_id.is_valid()) { + auto channel_full = get_channel_full(channel_id); + on_update_channel_full_linked_channel_id(channel_full, channel_id, group_channel_id); + if (channel_full != nullptr) { + update_channel_full(channel_full, channel_id); + } + } + if (group_channel_id.is_valid()) { + auto channel_full = get_channel_full(group_channel_id); + on_update_channel_full_linked_channel_id(channel_full, group_channel_id, channel_id); + if (channel_full != nullptr) { + update_channel_full(channel_full, group_channel_id); + } + } +} + void ContactsManager::on_update_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available) { if (!channel_id.is_valid()) { LOG(ERROR) << "Receive invalid " << channel_id; diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 6b4289c54..7254eab3a 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -177,6 +177,7 @@ class ContactsManager : public Actor { void on_update_channel_username(ChannelId channel_id, string &&username); void on_update_channel_description(ChannelId channel_id, string &&description); void on_update_channel_sticker_set(ChannelId channel_id, int64 sticker_set_id); + void on_update_channel_linked_channel_id(ChannelId channel_id, ChannelId group_channel_id); void on_update_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available); void on_update_channel_default_permissions(ChannelId channel_id, RestrictedRights default_permissions); @@ -306,6 +307,8 @@ class ContactsManager : public Actor { void set_channel_description(ChannelId channel_id, const string &description, Promise &&promise); + void set_channel_discussion_group(DialogId dialog_id, DialogId discussion_dialog_id, Promise &&promise); + void report_channel_spam(ChannelId channel_id, UserId user_id, const vector &message_ids, Promise &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 0ecba8ac5..de2ec72b0 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6064,6 +6064,13 @@ void Td::on_request(uint64 id, td_api::setChatDescription &request) { messages_manager_->set_dialog_description(DialogId(request.chat_id_), request.description_, std::move(promise)); } +void Td::on_request(uint64 id, const td_api::setChatDiscussionGroup &request) { + CHECK_IS_USER(); + CREATE_OK_REQUEST_PROMISE(); + contacts_manager_->set_channel_discussion_group(DialogId(request.chat_id_), DialogId(request.discussion_chat_id_), + std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::pinChatMessage &request) { CREATE_OK_REQUEST_PROMISE(); messages_manager_->pin_dialog_message(DialogId(request.chat_id_), MessageId(request.message_id_), diff --git a/td/telegram/Td.h b/td/telegram/Td.h index a385ae2d7..dbcf20430 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -668,6 +668,8 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, td_api::setChatDescription &request); + void on_request(uint64 id, const td_api::setChatDiscussionGroup &request); + void on_request(uint64 id, const td_api::pinChatMessage &request); void on_request(uint64 id, const td_api::unpinChatMessage &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index bd5478147..7f0c421a7 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3473,6 +3473,12 @@ class CliClient final : public Actor { std::tie(chat_id, description) = split(args); send_request(td_api::make_object(as_chat_id(chat_id), description)); + } else if (op == "scdg") { + string chat_id; + string group_chat_id; + + std::tie(chat_id, group_chat_id) = split(args); + send_request(td_api::make_object(as_chat_id(chat_id), as_chat_id(group_chat_id))); } else if (op == "pcm" || op == "pcms") { string chat_id; string message_id;