diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 78ac131a2..ae1bfd3cb 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -2292,7 +2292,7 @@ class InviteToChannelQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for InviteToChannelQuery: " << to_string(ptr); - td->contacts_manager_->invalidate_channel_full(channel_id_, false, false); + td->contacts_manager_->invalidate_channel_full(channel_id_, false); td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } @@ -2327,7 +2327,7 @@ class EditChannelAdminQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for EditChannelAdminQuery: " << to_string(ptr); - td->contacts_manager_->invalidate_channel_full(channel_id_, false, false); + td->contacts_manager_->invalidate_channel_full(channel_id_, false); td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } @@ -2362,7 +2362,7 @@ class EditChannelBannedQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for EditChannelBannedQuery: " << to_string(ptr); - td->contacts_manager_->invalidate_channel_full(channel_id_, false, false); + td->contacts_manager_->invalidate_channel_full(channel_id_, false); td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } @@ -2468,7 +2468,7 @@ class EditChannelCreatorQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for EditChannelCreatorQuery: " << to_string(ptr); - td->contacts_manager_->invalidate_channel_full(channel_id_, false, false); + td->contacts_manager_->invalidate_channel_full(channel_id_, false); td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } @@ -3518,7 +3518,7 @@ void ContactsManager::on_channel_unban_timeout(ChannelId channel_id) { LOG(INFO) << "Update " << channel_id << " status"; c->is_status_changed = true; - invalidate_channel_full(channel_id, false, !c->is_slow_mode_enabled); + invalidate_channel_full(channel_id, !c->is_slow_mode_enabled); update_channel(c, channel_id); // always call, because in case of failure we need to reactivate timeout } @@ -7135,8 +7135,7 @@ Status ContactsManager::can_manage_dialog_invite_links(DialogId dialog_id, bool if (!c->is_active) { return Status::Error(3, "Chat is deactivated"); } - auto status = get_chat_status(c); - bool have_rights = creator_only ? status.is_creator() : status.is_administrator() && status.can_invite_users(); + bool have_rights = creator_only ? c->status.is_creator() : c->status.can_manage_invite_links(); if (!have_rights) { return Status::Error(3, "Not enough rights to manage chat invite link"); } @@ -7147,8 +7146,7 @@ Status ContactsManager::can_manage_dialog_invite_links(DialogId dialog_id, bool if (c == nullptr) { return Status::Error(3, "Chat info not found"); } - auto status = get_channel_status(c); - bool have_rights = creator_only ? status.is_creator() : status.is_administrator() && status.can_invite_users(); + bool have_rights = creator_only ? c->status.is_creator() : c->status.can_manage_invite_links(); if (!have_rights) { return Status::Error(3, "Not enough rights to manage chat invite link"); } @@ -11510,7 +11508,7 @@ bool ContactsManager::on_get_channel_error(ChannelId channel_id, const Status &s remove_dialog_access_by_invite_link(DialogId(channel_id)); } - invalidate_channel_full(channel_id, false, !c->is_slow_mode_enabled); + invalidate_channel_full(channel_id, !c->is_slow_mode_enabled); 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))) @@ -11760,7 +11758,7 @@ void ContactsManager::speculative_add_channel_participants(ChannelId channel_id, bool by_me) { if (by_me) { // Currently ignore all changes made by the current user, because they may be already counted - invalidate_channel_full(channel_id, false, false); // just in case + invalidate_channel_full(channel_id, false); // just in case return; } @@ -11911,16 +11909,12 @@ void ContactsManager::drop_channel_photos(ChannelId channel_id, bool is_empty, b } } -void ContactsManager::invalidate_channel_full(ChannelId channel_id, bool need_drop_invite_link, - bool need_drop_slow_mode_delay) { +void ContactsManager::invalidate_channel_full(ChannelId channel_id, bool need_drop_slow_mode_delay) { LOG(INFO) << "Invalidate supergroup full for " << channel_id; // drop channel full cache auto channel_full = get_channel_full_force(channel_id, "invalidate_channel_full"); if (channel_full != nullptr) { channel_full->expires_at = 0.0; - if (need_drop_invite_link) { - on_update_channel_full_invite_link(channel_full, nullptr); - } if (need_drop_slow_mode_delay && channel_full->slow_mode_delay != 0) { channel_full->slow_mode_delay = 0; channel_full->slow_mode_next_send_date = 0; @@ -12909,10 +12903,17 @@ void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id const DialogParticipantStatus &new_status) { CHECK(c->is_update_supergroup_sent); - bool need_drop_invite_link = old_status.is_administrator() != new_status.is_administrator() || - old_status.is_member() != new_status.is_member(); bool need_reload_group_call = old_status.can_manage_calls() != new_status.can_manage_calls(); - invalidate_channel_full(channel_id, need_drop_invite_link, !c->is_slow_mode_enabled); + if (old_status.can_manage_invite_links() && !new_status.can_manage_invite_links()) { + auto channel_full = get_channel_full_force(channel_id, "on_channel_status_changed"); + if (channel_full != nullptr) { + on_update_channel_full_invite_link(channel_full, nullptr); + invalidate_channel_full(channel_id, !c->is_slow_mode_enabled); + update_channel_full(channel_full, channel_id); + } + } else { + invalidate_channel_full(channel_id, !c->is_slow_mode_enabled); + } if (old_status.is_creator() != new_status.is_creator()) { for (size_t i = 0; i < 2; i++) { @@ -12924,6 +12925,7 @@ void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id reload_dialog_administrators(DialogId(channel_id), 0, Auto()); remove_dialog_suggested_action(SuggestedAction{SuggestedAction::Type::ConvertToGigagroup, DialogId(channel_id)}); } + if (old_status.is_member() != new_status.is_member() || new_status.is_banned()) { remove_dialog_access_by_invite_link(DialogId(channel_id)); } @@ -12976,7 +12978,7 @@ void ContactsManager::on_channel_username_changed(Channel *c, ChannelId channel_ const string &new_username) { if (old_username.empty() || new_username.empty()) { // moving channel from private to public can change availability of chat members - invalidate_channel_full(channel_id, true, !c->is_slow_mode_enabled); + invalidate_channel_full(channel_id, !c->is_slow_mode_enabled); } } @@ -15220,7 +15222,7 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char c->is_gigagroup = is_gigagroup; c->is_changed = true; - invalidate_channel_full(channel_id, false, !c->is_slow_mode_enabled); + invalidate_channel_full(channel_id, !c->is_slow_mode_enabled); } if (c->is_verified != is_verified || c->sign_messages != sign_messages) { c->is_verified = is_verified; @@ -15311,7 +15313,7 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char } if (need_invalidate_channel_full) { - invalidate_channel_full(channel_id, false, !c->is_slow_mode_enabled); + invalidate_channel_full(channel_id, !c->is_slow_mode_enabled); } bool has_active_group_call = (channel.flags_ & CHANNEL_FLAG_HAS_ACTIVE_GROUP_CALL) != 0; @@ -15420,7 +15422,7 @@ void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, co } } if (need_invalidate_channel_full) { - invalidate_channel_full(channel_id, false, !c->is_slow_mode_enabled); + invalidate_channel_full(channel_id, !c->is_slow_mode_enabled); } } diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 86694d116..b620da9bc 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -233,7 +233,7 @@ class ContactsManager : public Actor { void speculative_delete_channel_participant(ChannelId channel_id, UserId deleted_user_id, bool by_me); - void invalidate_channel_full(ChannelId channel_id, bool need_drop_invite_link, bool need_drop_slow_mode_delay); + void invalidate_channel_full(ChannelId channel_id, bool need_drop_slow_mode_delay); bool on_get_channel_error(ChannelId channel_id, const Status &status, const string &source); diff --git a/td/telegram/DialogParticipant.h b/td/telegram/DialogParticipant.h index fb022a308..62ceea2b3 100644 --- a/td/telegram/DialogParticipant.h +++ b/td/telegram/DialogParticipant.h @@ -235,6 +235,11 @@ class DialogParticipantStatus { return (flags_ & CAN_INVITE_USERS_ADMIN) != 0 || (flags_ & CAN_INVITE_USERS_BANNED) != 0; } + bool can_manage_invite_links() const { + // invite links can be managed, only if administrator was explicitly granted the right + return (flags_ & CAN_INVITE_USERS_ADMIN) != 0; + } + bool can_restrict_members() const { return (flags_ & CAN_RESTRICT_MEMBERS) != 0; } diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index ba383eea9..52eacfeec 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -2213,7 +2213,7 @@ void UpdatesManager::on_update(tl_object_ptr } void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { - td_->contacts_manager_->invalidate_channel_full(ChannelId(update->channel_id_), false, false); + td_->contacts_manager_->invalidate_channel_full(ChannelId(update->channel_id_), false); promise.set_value(Unit()); }