Disallow restricted member status in channels.

This commit is contained in:
levlam 2023-10-19 22:37:44 +03:00
parent 80d8e9336f
commit 21ef7d0f6c
8 changed files with 90 additions and 58 deletions

View File

@ -4801,9 +4801,9 @@ void ContactsManager::Chat::parse(ParserT &parser) {
} else {
status = DialogParticipantStatus::Member();
}
default_permissions =
RestrictedRights(true, true, true, true, true, true, true, true, true, true, true, true, true,
everyone_is_administrator, everyone_is_administrator, everyone_is_administrator, false);
default_permissions = RestrictedRights(true, true, true, true, true, true, true, true, true, true, true, true, true,
everyone_is_administrator, everyone_is_administrator,
everyone_is_administrator, false, ChannelType::Unknown);
}
if (has_default_permissions_version) {
parse(default_permissions_version, parser);
@ -5108,7 +5108,7 @@ void ContactsManager::Channel::parse(ParserT &parser) {
parse(default_permissions, parser);
} else {
default_permissions = RestrictedRights(true, true, true, true, true, true, true, true, true, true, true, true,
true, false, anyone_can_invite, false, false);
true, false, anyone_can_invite, false, false, ChannelType::Megagroup);
}
}
if (has_cache_version) {
@ -5142,6 +5142,13 @@ void ContactsManager::Channel::parse(ParserT &parser) {
if (legacy_has_active_group_call) {
cache_version = 0;
}
if (!is_megagroup && status.is_restricted()) {
if (status.is_member()) {
status = DialogParticipantStatus::Member();
} else {
status = DialogParticipantStatus::Left();
}
}
}
template <class StorerT>
@ -5872,17 +5879,17 @@ RestrictedRights ContactsManager::get_user_default_permissions(UserId user_id) c
auto u = get_user(user_id);
if (u == nullptr || user_id == get_replies_bot_user_id()) {
return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false, false, false,
false, false, u != nullptr, false);
false, false, u != nullptr, false, ChannelType::Unknown);
}
return RestrictedRights(true, true, true, true, true, true, true, true, true, true, true, true, true, false, false,
true, false);
true, false, ChannelType::Unknown);
}
RestrictedRights ContactsManager::get_chat_default_permissions(ChatId chat_id) const {
auto c = get_chat(chat_id);
if (c == nullptr) {
return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false);
false, false, false, false, ChannelType::Unknown);
}
return c->default_permissions;
}
@ -5891,7 +5898,7 @@ RestrictedRights ContactsManager::get_channel_default_permissions(ChannelId chan
auto c = get_channel(channel_id);
if (c == nullptr) {
return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false);
false, false, false, false, ChannelType::Unknown);
}
return c->default_permissions;
}
@ -5900,10 +5907,10 @@ RestrictedRights ContactsManager::get_secret_chat_default_permissions(SecretChat
auto c = get_secret_chat(secret_chat_id);
if (c == nullptr) {
return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false);
false, false, false, false, ChannelType::Unknown);
}
return RestrictedRights(true, true, true, true, true, true, true, true, true, true, true, true, true, false, false,
false, false);
false, false, ChannelType::Unknown);
}
bool ContactsManager::get_chat_has_protected_content(ChatId chat_id) const {
@ -12281,7 +12288,8 @@ void ContactsManager::update_channel(Channel *c, ChannelId channel_id, bool from
if (c->is_default_permissions_changed) {
td_->messages_manager_->on_dialog_default_permissions_updated(DialogId(channel_id));
if (c->default_permissions != RestrictedRights(false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false)) {
false, false, false, false, false, false, false,
ChannelType::Unknown)) {
remove_dialog_suggested_action(SuggestedAction{SuggestedAction::Type::ConvertToGigagroup, DialogId(channel_id)});
}
c->is_default_permissions_changed = false;
@ -13345,9 +13353,10 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
SuggestedAction suggested_action(action_str, DialogId(channel_id));
if (!suggested_action.is_empty()) {
if (suggested_action == SuggestedAction{SuggestedAction::Type::ConvertToGigagroup, DialogId(channel_id)} &&
(c->is_gigagroup || c->default_permissions != RestrictedRights(false, false, false, false, false, false,
false, false, false, false, false, false,
false, false, false, false, false))) {
(c->is_gigagroup ||
c->default_permissions != RestrictedRights(false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, ChannelType::Unknown))) {
LOG(INFO) << "Skip ConvertToGigagroup suggested action";
} else {
suggested_actions.push_back(suggested_action);
@ -16387,7 +16396,7 @@ void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id
void ContactsManager::on_update_channel_default_permissions(Channel *c, ChannelId channel_id,
RestrictedRights default_permissions) {
if (c->default_permissions != default_permissions) {
if (c->is_megagroup && c->default_permissions != default_permissions) {
LOG(INFO) << "Update " << channel_id << " default permissions from " << c->default_permissions << " to "
<< default_permissions;
c->default_permissions = default_permissions;
@ -18913,7 +18922,8 @@ void ContactsManager::on_get_chat(telegram_api::chat &chat, const char *source)
c->need_save_to_database = true;
}
on_update_chat_status(c, chat_id, std::move(status));
on_update_chat_default_permissions(c, chat_id, RestrictedRights(chat.default_banned_rights_), chat.version_);
on_update_chat_default_permissions(c, chat_id, RestrictedRights(chat.default_banned_rights_, ChannelType::Unknown),
chat.version_);
on_update_chat_photo(c, chat_id, std::move(chat.photo_));
on_update_chat_active(c, chat_id, is_active);
on_update_chat_noforwards(c, chat_id, chat.noforwards_);
@ -19042,7 +19052,8 @@ void ContactsManager::on_get_channel(telegram_api::channel &channel, const char
return DialogParticipantStatus(false, std::move(channel.admin_rights_), string(),
is_megagroup ? ChannelType::Megagroup : ChannelType::Broadcast);
} else if (channel.banned_rights_ != nullptr) {
return DialogParticipantStatus(!has_left, std::move(channel.banned_rights_));
return DialogParticipantStatus(!has_left, std::move(channel.banned_rights_),
is_megagroup ? ChannelType::Megagroup : ChannelType::Broadcast);
} else if (has_left) {
return DialogParticipantStatus::Left();
} else {
@ -19063,7 +19074,8 @@ void ContactsManager::on_get_channel(telegram_api::channel &channel, const char
if (!c->status.is_banned()) {
on_update_channel_photo(c, channel_id, std::move(channel.photo_));
}
on_update_channel_default_permissions(c, channel_id, RestrictedRights(channel.default_banned_rights_));
on_update_channel_default_permissions(c, channel_id,
RestrictedRights(channel.default_banned_rights_, ChannelType::Megagroup));
on_update_channel_has_location(c, channel_id, channel.has_geo_);
on_update_channel_noforwards(c, channel_id, channel.noforwards_);
@ -19145,7 +19157,8 @@ void ContactsManager::on_get_channel(telegram_api::channel &channel, const char
c, channel_id,
Usernames(std::move(channel.username_),
std::move(channel.usernames_))); // uses status, must be called after on_update_channel_status
on_update_channel_default_permissions(c, channel_id, RestrictedRights(channel.default_banned_rights_));
on_update_channel_default_permissions(c, channel_id,
RestrictedRights(channel.default_banned_rights_, ChannelType::Megagroup));
on_update_channel_has_location(c, channel_id, channel.has_geo_);
on_update_channel_noforwards(c, channel_id, channel.noforwards_);
if (!td_->auth_manager_->is_bot() && !channel.stories_hidden_min_) {
@ -19255,7 +19268,7 @@ void ContactsManager::on_get_channel_forbidden(telegram_api::channelForbidden &c
on_update_channel_status(c, channel_id, DialogParticipantStatus::Banned(channel.until_date_));
// on_update_channel_usernames(c, channel_id, Usernames()); // don't know if channel usernames are empty, so don't update it
tl_object_ptr<telegram_api::chatBannedRights> banned_rights; // == nullptr
on_update_channel_default_permissions(c, channel_id, RestrictedRights(banned_rights));
on_update_channel_default_permissions(c, channel_id, RestrictedRights(banned_rights, ChannelType::Megagroup));
// on_update_channel_has_location(c, channel_id, false);
on_update_channel_noforwards(c, channel_id, false);
td_->messages_manager_->on_update_dialog_group_call(DialogId(channel_id), false, false, "on_get_channel_forbidden");

View File

@ -906,7 +906,7 @@ class ContactsManager final : public Actor {
DialogParticipantStatus status = DialogParticipantStatus::Banned(0);
RestrictedRights default_permissions{false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false};
false, false, false, false, false, false, false, false, ChannelType::Unknown};
static constexpr uint32 CACHE_VERSION = 4;
uint32 cache_version = 0;
@ -982,7 +982,7 @@ class ContactsManager final : public Actor {
vector<RestrictionReason> restriction_reasons;
DialogParticipantStatus status = DialogParticipantStatus::Banned(0);
RestrictedRights default_permissions{false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false};
false, false, false, false, false, false, false, false, ChannelType::Unknown};
int32 date = 0;
int32 participant_count = 0;

View File

@ -146,8 +146,9 @@ static td_api::object_ptr<td_api::ChatEventAction> get_chat_event_action_object(
}
case telegram_api::channelAdminLogEventActionDefaultBannedRights::ID: {
auto action = move_tl_object_as<telegram_api::channelAdminLogEventActionDefaultBannedRights>(action_ptr);
auto old_permissions = RestrictedRights(action->prev_banned_rights_);
auto new_permissions = RestrictedRights(action->new_banned_rights_);
auto channel_type = td->contacts_manager_->get_channel_type(channel_id);
auto old_permissions = RestrictedRights(action->prev_banned_rights_, channel_type);
auto new_permissions = RestrictedRights(action->new_banned_rights_, channel_type);
return td_api::make_object<td_api::chatEventPermissionsChanged>(old_permissions.get_chat_permissions_object(),
new_permissions.get_chat_permissions_object());
}

View File

@ -214,8 +214,9 @@ StringBuilder &operator<<(StringBuilder &string_builder, const AdministratorRigh
return string_builder;
}
RestrictedRights::RestrictedRights(const tl_object_ptr<telegram_api::chatBannedRights> &rights) {
if (rights == nullptr) {
RestrictedRights::RestrictedRights(const tl_object_ptr<telegram_api::chatBannedRights> &rights,
ChannelType channel_type) {
if (rights == nullptr || channel_type == ChannelType::Broadcast) {
flags_ = 0;
return;
}
@ -229,21 +230,23 @@ RestrictedRights::RestrictedRights(const tl_object_ptr<telegram_api::chatBannedR
!rights->send_videos_, !rights->send_roundvideos_, !rights->send_voices_,
!rights->send_stickers_, !rights->send_gifs_, !rights->send_games_, !rights->send_inline_,
!rights->embed_links_, !rights->send_polls_, !rights->change_info_, !rights->invite_users_,
!rights->pin_messages_, !rights->manage_topics_);
!rights->pin_messages_, !rights->manage_topics_, channel_type);
}
RestrictedRights::RestrictedRights(const td_api::object_ptr<td_api::chatPermissions> &rights) {
if (rights == nullptr) {
RestrictedRights::RestrictedRights(const td_api::object_ptr<td_api::chatPermissions> &rights,
ChannelType channel_type) {
if (rights == nullptr || channel_type == ChannelType::Broadcast) {
flags_ = 0;
return;
}
*this = RestrictedRights(
rights->can_send_basic_messages_, rights->can_send_audios_, rights->can_send_documents_, rights->can_send_photos_,
rights->can_send_videos_, rights->can_send_video_notes_, rights->can_send_voice_notes_,
rights->can_send_other_messages_, rights->can_send_other_messages_, rights->can_send_other_messages_,
rights->can_send_other_messages_, rights->can_add_web_page_previews_, rights->can_send_polls_,
rights->can_change_info_, rights->can_invite_users_, rights->can_pin_messages_, rights->can_manage_topics_);
*this = RestrictedRights(rights->can_send_basic_messages_, rights->can_send_audios_, rights->can_send_documents_,
rights->can_send_photos_, rights->can_send_videos_, rights->can_send_video_notes_,
rights->can_send_voice_notes_, rights->can_send_other_messages_,
rights->can_send_other_messages_, rights->can_send_other_messages_,
rights->can_send_other_messages_, rights->can_add_web_page_previews_,
rights->can_send_polls_, rights->can_change_info_, rights->can_invite_users_,
rights->can_pin_messages_, rights->can_manage_topics_, channel_type);
}
RestrictedRights::RestrictedRights(bool can_send_messages, bool can_send_audios, bool can_send_documents,
@ -251,7 +254,11 @@ RestrictedRights::RestrictedRights(bool can_send_messages, bool can_send_audios,
bool can_send_voice_notes, bool can_send_stickers, bool can_send_animations,
bool can_send_games, bool can_use_inline_bots, bool can_add_web_page_previews,
bool can_send_polls, bool can_change_info_and_settings, bool can_invite_users,
bool can_pin_messages, bool can_manage_topics) {
bool can_pin_messages, bool can_manage_topics, ChannelType channel_type) {
if (channel_type == ChannelType::Broadcast) {
flags_ = 0;
return;
}
flags_ = (static_cast<uint64>(can_send_messages) * CAN_SEND_MESSAGES) |
(static_cast<uint64>(can_send_audios) * CAN_SEND_AUDIOS) |
(static_cast<uint64>(can_send_documents) * CAN_SEND_DOCUMENTS) |
@ -443,9 +450,9 @@ DialogParticipantStatus DialogParticipantStatus::Member() {
}
DialogParticipantStatus DialogParticipantStatus::Restricted(RestrictedRights restricted_rights, bool is_member,
int32 restricted_until_date) {
int32 restricted_until_date, ChannelType channel_type) {
uint64 flags = restricted_rights.flags_;
if (flags == RestrictedRights::ALL_RESTRICTED_RIGHTS) {
if (flags == RestrictedRights::ALL_RESTRICTED_RIGHTS || channel_type == ChannelType::Broadcast) {
return is_member ? Member() : Left();
}
flags |= (static_cast<uint64>(is_member) * IS_MEMBER);
@ -482,27 +489,32 @@ DialogParticipantStatus::DialogParticipantStatus(bool can_be_edited,
}
DialogParticipantStatus::DialogParticipantStatus(bool is_member,
tl_object_ptr<telegram_api::chatBannedRights> &&banned_rights) {
tl_object_ptr<telegram_api::chatBannedRights> &&banned_rights,
ChannelType channel_type) {
CHECK(banned_rights != nullptr);
if (banned_rights->view_messages_) {
*this = Banned(banned_rights->until_date_);
return;
}
if (channel_type == ChannelType::Broadcast) {
*this = is_member ? Member() : Left();
return;
}
auto until_date = fix_until_date(banned_rights->until_date_);
banned_rights->until_date_ = std::numeric_limits<int32>::max();
// manually create Restricted status, because the user can be restricted, but with yet unknown restrictions
uint64 flags = RestrictedRights(banned_rights).flags_ | (static_cast<uint64>(is_member) * IS_MEMBER);
uint64 flags = RestrictedRights(banned_rights, channel_type).flags_ | (static_cast<uint64>(is_member) * IS_MEMBER);
*this = DialogParticipantStatus(Type::Restricted, flags, until_date, string());
}
RestrictedRights DialogParticipantStatus::get_effective_restricted_rights() const {
RestrictedRights DialogParticipantStatus::get_effective_restricted_rights(ChannelType channel_type) const {
return RestrictedRights(can_send_messages(), can_send_audios(), can_send_documents(), can_send_photos(),
can_send_videos(), can_send_video_notes(), can_send_voice_notes(), can_send_stickers(),
can_send_animations(), can_send_games(), can_use_inline_bots(), can_add_web_page_previews(),
can_send_polls(), can_change_info_and_settings(), can_invite_users(), can_pin_messages(),
can_create_topics());
can_create_topics(), channel_type);
}
tl_object_ptr<td_api::ChatMemberStatus> DialogParticipantStatus::get_chat_member_status_object() const {
@ -693,8 +705,8 @@ DialogParticipantStatus get_dialog_participant_status(const td_api::object_ptr<t
return DialogParticipantStatus::Member();
case td_api::chatMemberStatusRestricted::ID: {
auto st = static_cast<const td_api::chatMemberStatusRestricted *>(status.get());
return DialogParticipantStatus::Restricted(RestrictedRights(st->permissions_), st->is_member_,
fix_until_date(st->restricted_until_date_));
return DialogParticipantStatus::Restricted(RestrictedRights(st->permissions_, channel_type), st->is_member_,
fix_until_date(st->restricted_until_date_), channel_type);
}
case td_api::chatMemberStatusLeft::ID:
return DialogParticipantStatus::Left();
@ -786,7 +798,7 @@ DialogParticipant::DialogParticipant(tl_object_ptr<telegram_api::ChannelParticip
case telegram_api::channelParticipantBanned::ID: {
auto participant = move_tl_object_as<telegram_api::channelParticipantBanned>(participant_ptr);
*this = {DialogId(participant->peer_), UserId(participant->kicked_by_), participant->date_,
DialogParticipantStatus(!participant->left_, std::move(participant->banned_rights_))};
DialogParticipantStatus(!participant->left_, std::move(participant->banned_rights_), channel_type)};
break;
}
default:

View File

@ -194,15 +194,15 @@ class RestrictedRights {
}
public:
explicit RestrictedRights(const tl_object_ptr<telegram_api::chatBannedRights> &rights);
RestrictedRights(const tl_object_ptr<telegram_api::chatBannedRights> &rights, ChannelType channel_type);
explicit RestrictedRights(const td_api::object_ptr<td_api::chatPermissions> &rights);
RestrictedRights(const td_api::object_ptr<td_api::chatPermissions> &rights, ChannelType channel_type);
RestrictedRights(bool can_send_messages, bool can_send_audios, bool can_send_documents, bool can_send_photos,
bool can_send_videos, bool can_send_video_notes, bool can_send_voice_notes, bool can_send_stickers,
bool can_send_animations, bool can_send_games, bool can_use_inline_bots,
bool can_add_web_page_previews, bool can_send_polls, bool can_change_info_and_settings,
bool can_invite_users, bool can_pin_messages, bool can_manage_topics);
bool can_invite_users, bool can_pin_messages, bool can_manage_topics, ChannelType channel_type);
td_api::object_ptr<td_api::chatPermissions> get_chat_permissions_object() const;
@ -346,7 +346,7 @@ class DialogParticipantStatus {
static DialogParticipantStatus Member();
static DialogParticipantStatus Restricted(RestrictedRights restricted_rights, bool is_member,
int32 restricted_until_date);
int32 restricted_until_date, ChannelType channel_type);
static DialogParticipantStatus Left();
@ -363,7 +363,8 @@ class DialogParticipantStatus {
ChannelType channel_type);
// forcely returns a restricted or banned
DialogParticipantStatus(bool is_member, tl_object_ptr<telegram_api::chatBannedRights> &&banned_rights);
DialogParticipantStatus(bool is_member, tl_object_ptr<telegram_api::chatBannedRights> &&banned_rights,
ChannelType channel_type);
bool has_all_administrator_rights(AdministratorRights administrator_rights) const {
auto flags = administrator_rights.flags_ &
@ -371,7 +372,7 @@ class DialogParticipantStatus {
return (get_administrator_rights().flags_ & flags) == flags;
}
RestrictedRights get_effective_restricted_rights() const;
RestrictedRights get_effective_restricted_rights(ChannelType channel_type) const;
DialogParticipantStatus apply_restrictions(RestrictedRights default_restrictions, bool is_bot) const;

View File

@ -15,6 +15,7 @@
#include "td/telegram/BackgroundInfo.hpp"
#include "td/telegram/CallDiscardReason.h"
#include "td/telegram/ChannelId.h"
#include "td/telegram/ChannelType.h"
#include "td/telegram/ChatId.h"
#include "td/telegram/Contact.h"
#include "td/telegram/ContactsManager.h"
@ -3170,10 +3171,11 @@ Status can_send_message_content(DialogId dialog_id, const MessageContent *conten
case DialogType::User:
return td->contacts_manager_->get_user_default_permissions(dialog_id.get_user_id());
case DialogType::Chat:
return td->contacts_manager_->get_chat_permissions(dialog_id.get_chat_id()).get_effective_restricted_rights();
return td->contacts_manager_->get_chat_permissions(dialog_id.get_chat_id())
.get_effective_restricted_rights(ChannelType::Unknown);
case DialogType::Channel:
return td->contacts_manager_->get_channel_permissions(dialog_id.get_channel_id())
.get_effective_restricted_rights();
.get_effective_restricted_rights(td->contacts_manager_->get_channel_type(dialog_id.get_channel_id()));
case DialogType::SecretChat:
return td->contacts_manager_->get_secret_chat_default_permissions(dialog_id.get_secret_chat_id());
case DialogType::None:

View File

@ -32790,7 +32790,7 @@ RestrictedRights MessagesManager::get_dialog_default_permissions(DialogId dialog
default:
UNREACHABLE();
return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false);
false, false, false, false, ChannelType::Unknown);
}
}
@ -33786,6 +33786,7 @@ void MessagesManager::set_dialog_permissions(DialogId dialog_id,
return promise.set_error(Status::Error(400, "New permissions must be non-empty"));
}
ChannelType channel_type = ChannelType::Unknown;
switch (dialog_id.get_type()) {
case DialogType::User:
return promise.set_error(Status::Error(400, "Can't change private chat permissions"));
@ -33805,6 +33806,7 @@ void MessagesManager::set_dialog_permissions(DialogId dialog_id,
if (!status.can_restrict_members()) {
return promise.set_error(Status::Error(400, "Not enough rights to change chat permissions"));
}
channel_type = ChannelType::Megagroup;
break;
}
case DialogType::SecretChat:
@ -33814,7 +33816,7 @@ void MessagesManager::set_dialog_permissions(DialogId dialog_id,
UNREACHABLE();
}
RestrictedRights new_permissions(permissions);
RestrictedRights new_permissions(permissions, channel_type);
// TODO this can be wrong if there were previous change permissions requests
if (get_dialog_default_permissions(dialog_id) == new_permissions) {

View File

@ -3934,15 +3934,16 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChatParticipant
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChatDefaultBannedRights> update,
Promise<Unit> &&promise) {
DialogId dialog_id(update->peer_);
RestrictedRights permissions(update->default_banned_rights_);
auto version = update->version_;
switch (dialog_id.get_type()) {
case DialogType::Chat:
td_->contacts_manager_->on_update_chat_default_permissions(dialog_id.get_chat_id(), permissions, version);
td_->contacts_manager_->on_update_chat_default_permissions(
dialog_id.get_chat_id(), RestrictedRights(update->default_banned_rights_, ChannelType::Unknown), version);
break;
case DialogType::Channel:
LOG_IF(ERROR, version != 0) << "Receive version " << version << " in " << dialog_id;
td_->contacts_manager_->on_update_channel_default_permissions(dialog_id.get_channel_id(), permissions);
td_->contacts_manager_->on_update_channel_default_permissions(
dialog_id.get_channel_id(), RestrictedRights(update->default_banned_rights_, ChannelType::Megagroup));
break;
case DialogType::None:
case DialogType::User: