diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index be20a9136..05baa2632 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -437,13 +437,14 @@ basicGroupFullInfo description:string creator_user_id:int32 members:vector is_public:Bool = ChatInviteLinkInfo; @@ -2380,7 +2381,7 @@ chatReportReasonUnrelatedLocation = ChatReportReason; chatReportReasonCustom text:string = ChatReportReason; -//@description Contains a public HTTPS link to a message in a public supergroup or channel with a username @link Message link @html HTML-code for embedding the message +//@description Contains a public HTTPS link to a message in a supergroup or a channel with a username @link Message link @html HTML-code for embedding the message publicMessageLink link:string html:string = PublicMessageLink; //@description Contains information about a link to a message in a chat @@ -2560,7 +2561,7 @@ topChatCategoryForwardChats = TopChatCategory; //@description A URL linking to a user @user_id Identifier of the user tMeUrlTypeUser user_id:int32 = TMeUrlType; -//@description A URL linking to a public supergroup or channel @supergroup_id Identifier of the supergroup or channel +//@description A URL linking to a public supergroup or a channel @supergroup_id Identifier of the supergroup or channel tMeUrlTypeSupergroup supergroup_id:int53 = TMeUrlType; //@description A chat invite link @info Chat invite link info @@ -3160,7 +3161,7 @@ removeNotification notification_group_id:int32 notification_id:int32 = Ok; removeNotificationGroup notification_group_id:int32 max_notification_id:int32 = Ok; -//@description Returns a public HTTPS link to a message. Available only for messages in supergroups and channels with username +//@description Returns a public HTTPS link to a message. Available only for messages in supergroups and channels with a username //@chat_id Identifier of the chat to which the message belongs //@message_id Identifier of the message //@for_album Pass true if a link for a whole media album should be returned diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index e20857f81..fa0e7a04b 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 d7d705852..33eb56eec 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -2943,6 +2943,7 @@ void ContactsManager::Channel::store(StorerT &storer) const { STORE_FLAG(is_scam); STORE_FLAG(has_cache_version); STORE_FLAG(has_linked_channel); + STORE_FLAG(has_location); END_STORE_FLAGS(); store(status, storer); @@ -3004,6 +3005,7 @@ void ContactsManager::Channel::parse(ParserT &parser) { PARSE_FLAG(is_scam); PARSE_FLAG(has_cache_version); PARSE_FLAG(has_linked_channel); + PARSE_FLAG(has_location); END_PARSE_FLAGS(); if (use_new_rights) { @@ -3350,7 +3352,7 @@ bool ContactsManager::have_input_peer_channel(const Channel *c, ChannelId channe return false; } if (access_rights == AccessRights::Read) { - if (!c->username.empty()) { + if (!c->username.empty() || c->has_location) { return true; } if (!from_linked && c->has_linked_channel) { @@ -4644,9 +4646,10 @@ void ContactsManager::toggle_channel_is_all_history_available(ChannelId channel_ if (get_channel_type(c) != ChannelType::Megagroup) { return promise.set_error(Status::Error(6, "Message history can be hidden in supergroups only")); } - if (c->has_linked_channel) { + if (c->has_linked_channel && !is_all_history_available) { return promise.set_error(Status::Error(6, "Message history can't be hidden in discussion supergroups")); } + // it can be toggled in public chats, but will not affect them td_->create_handler(std::move(promise)) ->send(channel_id, is_all_history_available); @@ -8485,11 +8488,19 @@ bool ContactsManager::on_get_channel_error(ChannelId channel_id, const Status &s telegram_api::channelForbidden update(flags, false /*ignored*/, false /*ignored*/, channel_id.get(), c->access_hash, c->title, 0); on_chat_update(update, "CHANNEL_PRIVATE"); - } else if (!c->username.empty()) { - LOG(INFO) << "Drop username of " << channel_id; - on_update_channel_username(c, channel_id, ""); - update_channel(c, channel_id); + } else { + if (!c->username.empty()) { + LOG(INFO) << "Drop username of " << channel_id; + on_update_channel_username(c, channel_id, ""); + update_channel(c, channel_id); + } + if (c->has_location) { + LOG(INFO) << "Drop location of " << channel_id; + c->has_location = false; + update_channel(c, channel_id); + } } + invalidate_channel_full(channel_id, false); LOG_IF(ERROR, have_input_peer_channel(c, channel_id, AccessRights::Read)) << "Have read access to channel after receiving CHANNEL_PRIVATE. Channel state: " << oneline(to_string(get_supergroup_object(channel_id, c))) @@ -10270,6 +10281,14 @@ FileSourceId ContactsManager::get_chat_photo_file_source_id(ChatId chat_id) { return source_id; } +bool ContactsManager::is_channel_public(ChannelId channel_id) const { + return is_channel_public(get_channel(channel_id)); +} + +bool ContactsManager::is_channel_public(const Channel *c) { + return c != nullptr && (!c->username.empty() || c->has_location); +} + ChannelType ContactsManager::get_channel_type(ChannelId channel_id) const { auto c = get_channel(channel_id); if (c == nullptr) { @@ -11118,6 +11137,7 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char auto access_hash = has_access_hash ? channel.access_hash_ : 0; bool has_linked_channel = (channel.flags_ & CHANNEL_FLAG_HAS_LINKED_CHAT) != 0; + bool has_location = (channel.flags_ & CHANNEL_FLAG_HAS_LOCATION) != 0; bool sign_messages = (channel.flags_ & CHANNEL_FLAG_SIGN_MESSAGES) != 0; bool is_megagroup = (channel.flags_ & CHANNEL_FLAG_IS_MEGAGROUP) != 0; bool is_verified = (channel.flags_ & CHANNEL_FLAG_IS_VERIFIED) != 0; @@ -11209,10 +11229,11 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char c->need_send_update = true; } - if (c->has_linked_channel != has_linked_channel || c->sign_messages != sign_messages || - c->is_megagroup != is_megagroup || c->is_verified != is_verified || c->restriction_reason != restriction_reason || - c->is_scam != is_scam) { + if (c->has_linked_channel != has_linked_channel || c->has_location != has_location || + c->sign_messages != sign_messages || c->is_megagroup != is_megagroup || c->is_verified != is_verified || + c->restriction_reason != restriction_reason || c->is_scam != is_scam) { c->has_linked_channel = has_linked_channel; + c->has_location = has_location; c->sign_messages = sign_messages; c->is_megagroup = is_megagroup; c->is_verified = is_verified; @@ -11268,6 +11289,7 @@ void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, co on_update_channel_default_permissions(c, channel_id, get_restricted_rights(banned_rights)); bool has_linked_channel = false; + bool has_location = false; bool sign_messages = false; bool is_megagroup = (channel.flags_ & CHANNEL_FLAG_IS_MEGAGROUP) != 0; bool is_verified = false; @@ -11290,10 +11312,11 @@ void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, co c->need_send_update = true; } - if (c->has_linked_channel != has_linked_channel || c->sign_messages != sign_messages || - c->is_megagroup != is_megagroup || c->is_verified != is_verified || c->restriction_reason != restriction_reason || - c->is_scam != is_scam) { + if (c->has_linked_channel != has_linked_channel || c->has_location != has_location || + c->sign_messages != sign_messages || c->is_megagroup != is_megagroup || c->is_verified != is_verified || + c->restriction_reason != restriction_reason || c->is_scam != is_scam) { c->has_linked_channel = has_linked_channel; + c->has_location = has_location; c->sign_messages = sign_messages; c->is_megagroup = is_megagroup; c->is_verified = is_verified; @@ -11458,21 +11481,20 @@ tl_object_ptr ContactsManager::get_basic_group_object(ChatId return get_basic_group_object(chat_id, get_chat(chat_id)); } -tl_object_ptr ContactsManager::get_basic_group_object(ChatId chat_id, const Chat *chat) { - if (chat == nullptr) { +tl_object_ptr ContactsManager::get_basic_group_object(ChatId chat_id, const Chat *c) { + if (c == nullptr) { return nullptr; } - if (chat->migrated_to_channel_id.is_valid()) { - get_channel_force(chat->migrated_to_channel_id); + if (c->migrated_to_channel_id.is_valid()) { + get_channel_force(c->migrated_to_channel_id); } - return get_basic_group_object_const(chat_id, chat); + return get_basic_group_object_const(chat_id, c); } -tl_object_ptr ContactsManager::get_basic_group_object_const(ChatId chat_id, - const Chat *chat) const { +tl_object_ptr ContactsManager::get_basic_group_object_const(ChatId chat_id, const Chat *c) const { return make_tl_object( - chat_id.get(), chat->participant_count, get_chat_status(chat).get_chat_member_status_object(), chat->is_active, - get_supergroup_id_object(chat->migrated_to_channel_id, "get_basic_group_object")); + chat_id.get(), c->participant_count, get_chat_status(c).get_chat_member_status_object(), c->is_active, + get_supergroup_id_object(c->migrated_to_channel_id, "get_basic_group_object")); } tl_object_ptr ContactsManager::get_basic_group_full_info_object(ChatId chat_id) const { @@ -11496,7 +11518,7 @@ int32 ContactsManager::get_supergroup_id_object(ChannelId channel_id, const char send_closure(G()->td(), &Td::send_update, td_api::make_object(td_api::make_object( channel_id.get(), string(), 0, DialogParticipantStatus::Banned(0).get_chat_member_status_object(), - 0, false, false, true, false, "", false))); + 0, false, false, false, true, false, "", false))); } return channel_id.get(); } @@ -11505,15 +11527,14 @@ tl_object_ptr ContactsManager::get_supergroup_object(Channel return get_supergroup_object(channel_id, get_channel(channel_id)); } -tl_object_ptr ContactsManager::get_supergroup_object(ChannelId channel_id, - const Channel *channel) const { - if (channel == nullptr) { +tl_object_ptr ContactsManager::get_supergroup_object(ChannelId channel_id, const Channel *c) const { + if (c == nullptr) { return nullptr; } - return make_tl_object( - channel_id.get(), channel->username, channel->date, get_channel_status(channel).get_chat_member_status_object(), - channel->participant_count, channel->has_linked_channel, channel->sign_messages, !channel->is_megagroup, - channel->is_verified, channel->restriction_reason, channel->is_scam); + return make_tl_object(channel_id.get(), c->username, c->date, + get_channel_status(c).get_chat_member_status_object(), c->participant_count, + c->has_linked_channel, c->has_location, c->sign_messages, !c->is_megagroup, + c->is_verified, c->restriction_reason, c->is_scam); } tl_object_ptr ContactsManager::get_supergroup_full_info_object(ChannelId channel_id) const { @@ -11649,7 +11670,7 @@ tl_object_ptr ContactsManager::get_chat_invite_link_ if (c != nullptr) { title = c->title; photo = &c->photo; - is_public = !c->username.empty(); + is_public = is_channel_public(c); is_megagroup = c->is_megagroup; participant_count = c->participant_count; } else { diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 75259d6b7..da908770a 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -391,6 +391,8 @@ class ContactsManager : public Actor { void reload_channel(ChannelId chnanel_id, Promise &&promise); bool get_channel_full(ChannelId channel_id, Promise &&promise); + bool is_channel_public(ChannelId channel_id) const; + bool have_secret_chat(SecretChatId secret_chat_id) const; bool have_secret_chat_force(SecretChatId secret_chat_id); bool get_secret_chat(SecretChatId secret_chat_id, bool force, Promise &&promise); @@ -667,10 +669,11 @@ class ContactsManager : public Actor { int32 date = 0; int32 participant_count = 0; - static constexpr uint32 CACHE_VERSION = 2; + static constexpr uint32 CACHE_VERSION = 3; uint32 cache_version = 0; bool has_linked_channel = false; + bool has_location = false; bool sign_messages = false; bool is_megagroup = false; @@ -844,6 +847,7 @@ class ContactsManager : public Actor { static constexpr int32 CHANNEL_FLAG_HAS_PARTICIPANT_COUNT = 1 << 17; static constexpr int32 CHANNEL_FLAG_IS_SCAM = 1 << 19; static constexpr int32 CHANNEL_FLAG_HAS_LINKED_CHAT = 1 << 20; + static constexpr int32 CHANNEL_FLAG_HAS_LOCATION = 1 << 21; static constexpr int32 CHANNEL_FULL_FLAG_HAS_PARTICIPANT_COUNT = 1 << 0; static constexpr int32 CHANNEL_FULL_FLAG_HAS_ADMINISTRATOR_COUNT = 1 << 1; @@ -1106,6 +1110,8 @@ class ContactsManager : public Actor { void on_clear_imported_contacts(vector &&contacts, vector contacts_unique_id, std::pair, vector> &&to_add, Promise &&promise); + static bool is_channel_public(const Channel *c); + static bool is_valid_invite_link(const string &invite_link); bool update_invite_link(string &invite_link, tl_object_ptr &&invite_link_ptr); @@ -1133,13 +1139,13 @@ class ContactsManager : public Actor { tl_object_ptr get_user_full_info_object(UserId user_id, const UserFull *user_full) const; - tl_object_ptr get_basic_group_object(ChatId chat_id, const Chat *chat); + tl_object_ptr get_basic_group_object(ChatId chat_id, const Chat *c); - tl_object_ptr get_basic_group_object_const(ChatId chat_id, const Chat *chat) const; + tl_object_ptr get_basic_group_object_const(ChatId chat_id, const Chat *c) const; tl_object_ptr get_basic_group_full_info_object(const ChatFull *chat_full) const; - tl_object_ptr get_supergroup_object(ChannelId channel_id, const Channel *channel) const; + tl_object_ptr get_supergroup_object(ChannelId channel_id, const Channel *c) const; tl_object_ptr get_supergroup_full_info_object(const ChannelFull *channel_full) const; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index c1d1118b0..e50a18f4a 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -8266,7 +8266,7 @@ void MessagesManager::delete_dialog_history(DialogId dialog_id, bool remove_from if (is_broadcast_channel(dialog_id)) { return promise.set_error(Status::Error(3, "Can't delete chat history in a channel")); } - if (!get_dialog_username(dialog_id).empty()) { + if (td_->contacts_manager_->is_channel_public(dialog_id.get_channel_id())) { return promise.set_error(Status::Error(3, "Can't delete chat history in a public supergroup")); } break; @@ -13013,7 +13013,7 @@ std::pair MessagesManager::get_public_message_link(FullMessageId if (dialog_id.get_type() != DialogType::Channel || td_->contacts_manager_->get_channel_username(dialog_id.get_channel_id()).empty()) { promise.set_error(Status::Error( - 6, "Public message links are available only for messages in public supergroups and channel chats")); + 6, "Public message links are available only for messages in supergroups and channel chats with a username")); return {}; } @@ -14450,7 +14450,7 @@ td_api::object_ptr MessagesManager::get_chat_object(const Dialog * break; case DialogType::Channel: if (is_broadcast_channel(d->dialog_id) || - !td_->contacts_manager_->get_channel_username(d->dialog_id.get_channel_id()).empty()) { + td_->contacts_manager_->is_channel_public(d->dialog_id.get_channel_id())) { // deleteChatHistory can't be used in channels and public supergroups } else { // private supergroups can be deleted for self