diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 2aeb997c6..151cccf26 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -414,8 +414,8 @@ supergroupMembersFilterBots = SupergroupMembersFilter; //@upgraded_to_supergroup_id Identifier of the supergroup to which this group was upgraded; 0 if none basicGroup id:int32 member_count:int32 status:ChatMemberStatus everyone_is_administrator:Bool is_active:Bool upgraded_to_supergroup_id:int32 = BasicGroup; -//@description Contains full information about a basic group @creator_user_id User identifier of the creator of the group; 0 if unknown @members Group members @invite_link Invite link for this group; available only for the group creator and only after it has been generated at least once -basicGroupFullInfo creator_user_id:int32 members:vector invite_link:string = BasicGroupFullInfo; +//@description Contains full information about a basic group @param_description Group description @creator_user_id User identifier of the creator of the group; 0 if unknown @members Group members @invite_link Invite link for this group; available only for the group creator and only after it has been generated at least once +basicGroupFullInfo description:string creator_user_id:int32 members:vector invite_link:string = BasicGroupFullInfo; //@description Represents a supergroup or channel with zero or more members (subscribers in the case of channels). From the point of view of the system, a channel is a special kind of a supergroup: only administrators can post and see the list of members, and posts from all administrators use the name and photo of the channel instead of individual names and profile photos. Unlike supergroups, channels can have an unlimited number of subscribers @@ -3179,6 +3179,9 @@ toggleChatDefaultDisableNotification chat_id:int53 default_disable_notification: //@description Changes client data associated with a chat @chat_id Chat identifier @client_data New value of client_data setChatClientData chat_id:int53 client_data:string = Ok; +//@description Changes information about a chat. Available for basic groups, supergroups, and channels. Requires appropriate administrator rights @chat_id Identifier of the chat @param_description New chat description; 0-255 characters +setChatDescription chat_id:int53 description:string = Ok; + //@description Pins a message in a chat; requires appropriate administrator rights in the group or channel @chat_id Identifier of the chat @message_id Identifier of the new pinned message @disable_notification True, if there should be no notification about the pinned message pinChatMessage chat_id:int53 message_id:int53 disable_notification:Bool = Ok; @@ -3499,9 +3502,6 @@ toggleSupergroupSignMessages supergroup_id:int32 sign_messages:Bool = Ok; //@description Toggles whether the message history of a supergroup is available to new members; requires appropriate administrator rights in the supergroup. @supergroup_id The identifier of the supergroup @is_all_history_available The new value of is_all_history_available toggleSupergroupIsAllHistoryAvailable supergroup_id:int32 is_all_history_available:Bool = Ok; -//@description Changes information about a supergroup or channel; requires appropriate administrator rights @supergroup_id Identifier of the supergroup or channel @param_description New supergroup or channel description; 0-255 characters -setSupergroupDescription supergroup_id:int32 description:string = Ok; - //@description Reports some messages from a user in a supergroup as spam; requires administrator rights in the supergroup @supergroup_id Supergroup identifier @user_id User identifier @message_ids Identifiers of messages sent in the supergroup by the user. This list must be non-empty reportSupergroupSpam supergroup_id:int32 user_id:int32 message_ids:vector = Ok; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 69f4a1798..77a6a4362 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 036cd3864..82656eb27 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -1127,19 +1127,32 @@ class ToggleChannelIsAllHistoryAvailableQuery : public Td::ResultHandler { } }; -class EditChannelAboutQuery : public Td::ResultHandler { +class EditChatAboutQuery : public Td::ResultHandler { Promise promise_; - ChannelId channel_id_; + DialogId dialog_id_; string about_; - public: - explicit EditChannelAboutQuery(Promise &&promise) : promise_(std::move(promise)) { + void on_success() { + switch (dialog_id_.get_type()) { + case DialogType::Chat: + return td->contacts_manager_->on_update_chat_description(dialog_id_.get_chat_id(), std::move(about_)); + case DialogType::Channel: + return td->contacts_manager_->on_update_channel_description(dialog_id_.get_channel_id(), std::move(about_)); + case DialogType::User: + case DialogType::SecretChat: + case DialogType::None: + UNREACHABLE(); + } } - void send(ChannelId channel_id, const string &about) { - channel_id_ = channel_id; + public: + explicit EditChatAboutQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(DialogId dialog_id, const string &about) { + dialog_id_ = dialog_id; about_ = about; - auto input_peer = td->messages_manager_->get_input_peer(DialogId(channel_id), AccessRights::Read); + auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Write); if (input_peer == nullptr) { return on_error(0, Status::Error(400, "Can't access the chat")); } @@ -1154,24 +1167,24 @@ class EditChannelAboutQuery : public Td::ResultHandler { } bool result = result_ptr.ok(); - LOG(DEBUG) << "Receive result for editChannelAbout " << result; + LOG(DEBUG) << "Receive result for editChatAbout " << result; if (!result) { return on_error(id, Status::Error(500, "Chat description is not updated")); } - td->contacts_manager_->on_update_channel_description(channel_id_, std::move(about_)); + on_success(); promise_.set_value(Unit()); } void on_error(uint64 id, Status status) override { if (status.message() == "CHAT_ABOUT_NOT_MODIFIED" || status.message() == "CHAT_NOT_MODIFIED") { - td->contacts_manager_->on_update_channel_description(channel_id_, std::move(about_)); + on_success(); if (!td->auth_manager_->is_bot()) { promise_.set_value(Unit()); return; } } else { - td->contacts_manager_->on_get_channel_error(channel_id_, status, "EditChannelAboutQuery"); + td->messages_manager_->on_get_dialog_error(dialog_id_, status, "EditChatAboutQuery"); } promise_.set_error(std::move(status)); } @@ -3969,6 +3982,19 @@ void ContactsManager::set_username(const string &username, Promise &&promi td_->create_handler(std::move(promise))->send(username); } +void ContactsManager::set_chat_description(ChatId chat_id, const string &description, Promise &&promise) { + auto new_description = strip_empty_characters(description, MAX_DESCRIPTION_LENGTH); + auto c = get_chat(chat_id); + if (c == nullptr) { + return promise.set_error(Status::Error(6, "Chat info not found")); + } + if (!get_chat_status(c).can_change_info_and_settings()) { + return promise.set_error(Status::Error(6, "Not enough rights to set chat description")); + } + + td_->create_handler(std::move(promise))->send(DialogId(chat_id), new_description); +} + void ContactsManager::set_channel_username(ChannelId channel_id, const string &username, Promise &&promise) { auto c = get_channel(channel_id); if (c == nullptr) { @@ -4060,13 +4086,13 @@ void ContactsManager::set_channel_description(ChannelId channel_id, const string auto new_description = strip_empty_characters(description, MAX_DESCRIPTION_LENGTH); auto c = get_channel(channel_id); if (c == nullptr) { - return promise.set_error(Status::Error(6, "Supergroup not found")); + return promise.set_error(Status::Error(6, "Chat info not found")); } if (!get_channel_status(c).can_change_info_and_settings()) { - return promise.set_error(Status::Error(6, "Not enough rights to set supergroup description")); + return promise.set_error(Status::Error(6, "Not enough rights to set chat description")); } - td_->create_handler(std::move(promise))->send(channel_id, new_description); + td_->create_handler(std::move(promise))->send(DialogId(channel_id), new_description); } void ContactsManager::report_channel_spam(ChannelId channel_id, UserId user_id, const vector &message_ids, @@ -6606,6 +6632,11 @@ void ContactsManager::on_get_chat_full(tl_object_ptr &&c } } + if (chat->description != chat_full->about_) { + chat->description = std::move(chat_full->about_); + chat->is_changed = true; + } + on_get_chat_participants(std::move(chat_full->participants_)); td_->messages_manager_->on_update_dialog_notify_settings(DialogId(chat_id), std::move(chat_full->notify_settings_), "on_get_chat_full"); @@ -8305,6 +8336,23 @@ void ContactsManager::on_update_chat_migrated_to_channel_id(Chat *c, ChatId chat } } +void ContactsManager::on_update_chat_description(ChatId chat_id, string &&description) { + if (!chat_id.is_valid()) { + LOG(ERROR) << "Receive invalid " << chat_id; + return; + } + + auto chat_full = get_chat_full(chat_id); + if (chat_full == nullptr) { + return; + } + if (chat_full->description != description) { + chat_full->description = std::move(description); + chat_full->is_changed = true; + update_chat_full(chat_full, chat_id); + } +} + bool ContactsManager::on_update_chat_full_participants_short(ChatFull *chat_full, ChatId chat_id, int32 version) { if (version <= -1) { LOG(ERROR) << "Receive wrong version " << version << " for " << chat_id; @@ -10180,7 +10228,7 @@ tl_object_ptr ContactsManager::get_basic_group_full_ const ChatFull *chat_full) const { CHECK(chat_full != nullptr); return make_tl_object( - get_user_id_object(chat_full->creator_user_id, "basicGroupFullInfo"), + chat_full->description, get_user_id_object(chat_full->creator_user_id, "basicGroupFullInfo"), transform(chat_full->participants, [this](const DialogParticipant &chat_participant) { return get_chat_member_object(chat_participant); }), chat_full->invite_link); diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index d42a9eae8..00ba72660 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -163,6 +163,7 @@ class ContactsManager : public Actor { void on_get_chat_participants(tl_object_ptr &&participants); void on_update_chat_add_user(ChatId chat_id, UserId inviter_user_id, UserId user_id, int32 date, int32 version); + void on_update_chat_description(ChatId chat_id, string &&description); void on_update_chat_edit_administrator(ChatId chat_id, UserId user_id, bool is_administrator, int32 version); void on_update_chat_delete_user(ChatId chat_id, UserId user_id, int32 version); void on_update_chat_everyone_is_administrator(ChatId chat_id, bool everyone_is_administrator, int32 version); @@ -283,6 +284,8 @@ class ContactsManager : public Actor { void set_username(const string &username, Promise &&promise); + void set_chat_description(ChatId chat_id, const string &description, Promise &&promise); + void set_channel_username(ChannelId channel_id, const string &username, Promise &&promise); void set_channel_sticker_set(ChannelId channel_id, int64 sticker_set_id, Promise &&promise); @@ -594,6 +597,8 @@ class ContactsManager : public Actor { UserId creator_user_id; vector participants; + string description; + string invite_link; bool is_changed = true; @@ -710,7 +715,7 @@ class ContactsManager : public Actor { static constexpr int32 MAX_GET_PROFILE_PHOTOS = 100; // server side limit static constexpr size_t MAX_NAME_LENGTH = 64; // server side limit for first/last name - static constexpr size_t MAX_DESCRIPTION_LENGTH = 255; // server side limit for channel description + static constexpr size_t MAX_DESCRIPTION_LENGTH = 255; // server side limit for chat/channel description static constexpr size_t MAX_BIO_LENGTH = 70; // server side limit static constexpr int32 MAX_GET_CHANNEL_PARTICIPANTS = 200; // server side limit diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 342c41b3b..fd689e141 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -15423,7 +15423,7 @@ Status MessagesManager::can_send_message_content(DialogId dialog_id, const Messa can_send_stickers = channel_status.can_send_stickers(); can_send_animations = channel_status.can_send_animations(); can_send_games = channel_status.can_send_games(); - // can_send_polls = channel_status.can_send_polls(); TODO + can_send_polls = channel_status.can_send_polls(); break; } case DialogType::SecretChat: @@ -21462,6 +21462,30 @@ void MessagesManager::set_dialog_title(DialogId dialog_id, const string &title, td_->create_handler(std::move(promise))->send(dialog_id, new_title); } +void MessagesManager::set_dialog_description(DialogId dialog_id, const string &description, Promise &&promise) { + LOG(INFO) << "Receive setChatDescription request to set description of " << dialog_id << " to \"" << description + << '"'; + + if (!have_dialog_force(dialog_id)) { + return promise.set_error(Status::Error(3, "Chat not found")); + } + + switch (dialog_id.get_type()) { + case DialogType::User: + return promise.set_error(Status::Error(3, "Can't change private chat description")); + case DialogType::Chat: + return td_->contacts_manager_->set_chat_description(dialog_id.get_chat_id(), description, std::move(promise)); + case DialogType::Channel: + return td_->contacts_manager_->set_channel_description(dialog_id.get_channel_id(), description, + std::move(promise)); + case DialogType::SecretChat: + return promise.set_error(Status::Error(3, "Can't change secret chat description")); + case DialogType::None: + default: + UNREACHABLE(); + } +} + void MessagesManager::pin_dialog_message(DialogId dialog_id, MessageId message_id, bool disable_notification, bool is_unpin, Promise &&promise) { auto d = get_dialog_force(dialog_id); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index c90b28e64..0eb6318b5 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -418,6 +418,8 @@ class MessagesManager : public Actor { void set_dialog_title(DialogId dialog_id, const string &title, Promise &&promise); + void set_dialog_description(DialogId dialog_id, const string &description, Promise &&promise); + void pin_dialog_message(DialogId dialog_id, MessageId message_id, bool disable_notification, bool is_unpin, Promise &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 3c5d39f5a..73c059789 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5698,6 +5698,23 @@ void Td::on_request(uint64 id, td_api::setChatClientData &request) { id, messages_manager_->set_dialog_client_data(DialogId(request.chat_id_), std::move(request.client_data_))); } +void Td::on_request(uint64 id, td_api::setChatDescription &request) { + CLEAN_INPUT_STRING(request.description_); + CREATE_OK_REQUEST_PROMISE(); + messages_manager_->set_dialog_description(DialogId(request.chat_id_), request.description_, 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_), + request.disable_notification_, false, std::move(promise)); +} + +void Td::on_request(uint64 id, const td_api::unpinChatMessage &request) { + CREATE_OK_REQUEST_PROMISE(); + messages_manager_->pin_dialog_message(DialogId(request.chat_id_), MessageId(), false, true, std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::joinChat &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); @@ -6069,24 +6086,6 @@ void Td::on_request(uint64 id, const td_api::toggleSupergroupIsAllHistoryAvailab request.is_all_history_available_, std::move(promise)); } -void Td::on_request(uint64 id, td_api::setSupergroupDescription &request) { - CLEAN_INPUT_STRING(request.description_); - CREATE_OK_REQUEST_PROMISE(); - contacts_manager_->set_channel_description(ChannelId(request.supergroup_id_), request.description_, - 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_), - request.disable_notification_, false, std::move(promise)); -} - -void Td::on_request(uint64 id, const td_api::unpinChatMessage &request) { - CREATE_OK_REQUEST_PROMISE(); - messages_manager_->pin_dialog_message(DialogId(request.chat_id_), MessageId(), false, true, std::move(promise)); -} - void Td::on_request(uint64 id, const td_api::reportSupergroupSpam &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index cf3b8a517..f7205b2b2 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -650,6 +650,8 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, td_api::setChatClientData &request); + void on_request(uint64 id, td_api::setChatDescription &request); + void on_request(uint64 id, const td_api::pinChatMessage &request); void on_request(uint64 id, const td_api::unpinChatMessage &request); @@ -742,8 +744,6 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, const td_api::toggleSupergroupIsAllHistoryAvailable &request); - void on_request(uint64 id, td_api::setSupergroupDescription &request); - void on_request(uint64 id, const td_api::reportSupergroupSpam &request); void on_request(uint64 id, td_api::getSupergroupMembers &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index b352061f9..f8e83f195 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3377,12 +3377,12 @@ class CliClient final : public Actor { std::tie(supergroup_id, sign_messages) = split(args); send_request(td_api::make_object(as_supergroup_id(supergroup_id), as_bool(sign_messages))); - } else if (op == "csgd" || op == "cchd") { - string supergroup_id; + } else if (op == "scd") { + string chat_id; string description; - std::tie(supergroup_id, description) = split(args); - send_request(td_api::make_object(as_supergroup_id(supergroup_id), description)); + std::tie(chat_id, description) = split(args); + send_request(td_api::make_object(as_chat_id(chat_id), description)); } else if (op == "pcm" || op == "pcms") { string chat_id; string message_id;