From 2ffda9f2408471c01e31504f2ae0b942423c754e Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Thu, 8 Jul 2021 13:34:06 +0300
Subject: [PATCH] Don't use MTP* for ChatAdminRight / ChatRestriction.

---
 Telegram/SourceFiles/apiwrap.cpp              |  25 ++--
 Telegram/SourceFiles/apiwrap.h                |   3 +-
 .../SourceFiles/boxes/add_contact_box.cpp     |   2 +-
 Telegram/SourceFiles/boxes/confirm_box.cpp    |   2 +-
 .../boxes/peer_list_controllers.cpp           |   2 +-
 .../boxes/peers/add_participants_box.cpp      |  36 +++--
 .../boxes/peers/add_participants_box.h        |  11 +-
 .../boxes/peers/edit_participant_box.cpp      |  83 ++++++------
 .../boxes/peers/edit_participant_box.h        |  31 ++---
 .../boxes/peers/edit_participants_box.cpp     | 116 ++++++++--------
 .../boxes/peers/edit_participants_box.h       |  27 ++--
 .../boxes/peers/edit_peer_info_box.cpp        |  11 +-
 .../boxes/peers/edit_peer_permissions_box.cpp | 128 +++++++++---------
 .../boxes/peers/edit_peer_permissions_box.h   |  14 +-
 .../calls/group/calls_group_call.cpp          |   3 +-
 .../calls/group/calls_group_panel.cpp         |   4 +-
 .../chat_helpers/tabbed_selector.cpp          |   4 +-
 Telegram/SourceFiles/data/data_channel.cpp    | 115 ++++++++--------
 Telegram/SourceFiles/data/data_channel.h      |  28 ++--
 Telegram/SourceFiles/data/data_chat.cpp       |  70 +++++-----
 Telegram/SourceFiles/data/data_chat.h         |   7 +-
 .../SourceFiles/data/data_media_types.cpp     |  14 +-
 Telegram/SourceFiles/data/data_peer.cpp       |  84 ++++++------
 Telegram/SourceFiles/data/data_peer.h         |  78 +++++++++--
 .../SourceFiles/data/data_peer_values.cpp     |  44 +++---
 Telegram/SourceFiles/data/data_session.cpp    |  32 ++---
 .../admin_log/history_admin_log_inner.cpp     |  38 +++---
 .../admin_log/history_admin_log_inner.h       |   6 +-
 .../admin_log/history_admin_log_item.cpp      | 126 ++++++++---------
 .../SourceFiles/history/history_message.cpp   |   6 +-
 .../SourceFiles/history/history_widget.cpp    |  18 +--
 .../history_view_compose_controls.cpp         |   8 +-
 .../view/history_view_replies_section.cpp     |  12 +-
 .../view/history_view_scheduled_section.cpp   |   8 +-
 .../inline_bots/inline_bot_send_data.cpp      |  12 +-
 .../inline_bots/inline_results_inner.cpp      |   2 +-
 Telegram/SourceFiles/mainwidget.cpp           |   2 +-
 .../profile/profile_block_group_members.cpp   |   6 +-
 38 files changed, 649 insertions(+), 569 deletions(-)

diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp
index 4102b5ac6..5bab9a03e 100644
--- a/Telegram/SourceFiles/apiwrap.cpp
+++ b/Telegram/SourceFiles/apiwrap.cpp
@@ -1526,7 +1526,6 @@ void ApiWrap::applyLastParticipantsList(
 		| MegagroupInfo::LastParticipantsOnceReceived;
 
 	auto botStatus = channel->mgInfo->botStatus;
-	const auto emptyAdminRights = MTP_chatAdminRights(MTP_flags(0));
 	for (const auto &p : list) {
 		const auto participantId = p.match([](
 				const MTPDchannelParticipantBanned &data) {
@@ -1547,13 +1546,14 @@ void ApiWrap::applyLastParticipantsList(
 			? channel->amCreator()
 			: false;
 		const auto adminRights = (p.type() == mtpc_channelParticipantAdmin)
-			? p.c_channelParticipantAdmin().vadmin_rights()
+			? ChatAdminRightsInfo(p.c_channelParticipantAdmin().vadmin_rights())
 			: (p.type() == mtpc_channelParticipantCreator)
-			? p.c_channelParticipantCreator().vadmin_rights()
-			: emptyAdminRights;
+			? ChatAdminRightsInfo(p.c_channelParticipantCreator().vadmin_rights())
+			: ChatAdminRightsInfo();
 		const auto restrictedRights = (p.type() == mtpc_channelParticipantBanned)
-			? p.c_channelParticipantBanned().vbanned_rights()
-			: ChannelData::EmptyRestrictedRights(participant);
+			? ChatRestrictionsInfo(
+				p.c_channelParticipantBanned().vbanned_rights())
+			: ChatRestrictionsInfo();
 		if (p.type() == mtpc_channelParticipantCreator) {
 			Assert(user != nullptr);
 			const auto &creator = p.c_channelParticipantCreator();
@@ -1569,11 +1569,11 @@ void ApiWrap::applyLastParticipantsList(
 		if (user
 			&& !base::contains(channel->mgInfo->lastParticipants, user)) {
 			channel->mgInfo->lastParticipants.push_back(user);
-			if (adminRights.c_chatAdminRights().vflags().v) {
+			if (adminRights.flags) {
 				channel->mgInfo->lastAdmins.emplace(
 					user,
 					MegagroupInfo::Admin{ adminRights, adminCanEdit });
-			} else if (Data::ChatBannedRightsFlags(restrictedRights) != 0) {
+			} else if (restrictedRights.flags) {
 				channel->mgInfo->lastRestricted.emplace(
 					user,
 					MegagroupInfo::Restricted{ restrictedRights });
@@ -1731,7 +1731,7 @@ void ApiWrap::kickParticipant(
 void ApiWrap::kickParticipant(
 		not_null<ChannelData*> channel,
 		not_null<PeerData*> participant,
-		const MTPChatBannedRights &currentRights) {
+		ChatRestrictionsInfo currentRights) {
 	const auto kick = KickRequest(channel, participant);
 	if (_kickRequests.contains(kick)) return;
 
@@ -1739,7 +1739,10 @@ void ApiWrap::kickParticipant(
 	const auto requestId = request(MTPchannels_EditBanned(
 		channel->inputChannel,
 		participant->input,
-		rights
+		MTP_chatBannedRights(
+			MTP_flags(
+				MTPDchatBannedRights::Flags::from_raw(uint32(rights.flags))),
+			MTP_int(rights.until))
 	)).done([=](const MTPUpdates &result) {
 		applyUpdates(result);
 
@@ -1763,7 +1766,7 @@ void ApiWrap::unblockParticipant(
 	const auto requestId = request(MTPchannels_EditBanned(
 		channel->inputChannel,
 		participant->input,
-		ChannelData::EmptyRestrictedRights(participant)
+		MTP_chatBannedRights(MTP_flags(0), MTP_int(0))
 	)).done([=](const MTPUpdates &result) {
 		applyUpdates(result);
 
diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h
index dfb94ef59..649033272 100644
--- a/Telegram/SourceFiles/apiwrap.h
+++ b/Telegram/SourceFiles/apiwrap.h
@@ -20,6 +20,7 @@ struct MessageGroupId;
 struct SendingAlbum;
 enum class SendMediaType;
 struct FileLoadTo;
+struct ChatRestrictionsInfo;
 
 namespace Main {
 class Session;
@@ -264,7 +265,7 @@ public:
 	void kickParticipant(
 		not_null<ChannelData*> channel,
 		not_null<PeerData*> participant,
-		const MTPChatBannedRights &currentRights);
+		ChatRestrictionsInfo currentRights);
 	void unblockParticipant(
 		not_null<ChannelData*> channel,
 		not_null<PeerData*> participant);
diff --git a/Telegram/SourceFiles/boxes/add_contact_box.cpp b/Telegram/SourceFiles/boxes/add_contact_box.cpp
index b81576845..5b79312a2 100644
--- a/Telegram/SourceFiles/boxes/add_contact_box.cpp
+++ b/Telegram/SourceFiles/boxes/add_contact_box.cpp
@@ -158,7 +158,7 @@ void ShowAddParticipantsError(
 				auto box = Box<EditAdminBox>(
 					channel,
 					user,
-					MTP_chatAdminRights(MTP_flags(0)),
+					ChatAdminRightsInfo(),
 					QString());
 				box->setSaveCallback(saveCallback);
 				*weak = Ui::show(std::move(box));
diff --git a/Telegram/SourceFiles/boxes/confirm_box.cpp b/Telegram/SourceFiles/boxes/confirm_box.cpp
index 90a72d84e..0e291b9b6 100644
--- a/Telegram/SourceFiles/boxes/confirm_box.cpp
+++ b/Telegram/SourceFiles/boxes/confirm_box.cpp
@@ -901,7 +901,7 @@ void DeleteMessagesBox::deleteAndClear() {
 			_moderateInChannel->session().api().kickParticipant(
 				_moderateInChannel,
 				_moderateFrom,
-				ChannelData::EmptyRestrictedRights(_moderateFrom));
+				ChatRestrictionsInfo());
 		}
 		if (_reportSpam->checked()) {
 			_moderateInChannel->session().api().request(
diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp
index 03f533d5c..680070490 100644
--- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp
+++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp
@@ -516,7 +516,7 @@ bool AddBotToGroupBoxController::needToCreateRow(
 		not_null<PeerData*> peer) const {
 	if (sharingBotGame()) {
 		if (!peer->canWrite()
-			|| peer->amRestricted(ChatRestriction::f_send_games)) {
+			|| peer->amRestricted(ChatRestriction::SendGames)) {
 			return false;
 		}
 		return true;
diff --git a/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp b/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp
index 42e70faf0..52d90ca79 100644
--- a/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp
@@ -626,7 +626,7 @@ void AddSpecialBoxController::showAdmin(
 	// Finally show the admin.
 	const auto currentRights = adminRights
 		? *adminRights
-		: MTPChatAdminRights(MTP_chatAdminRights(MTP_flags(0)));
+		: ChatAdminRightsInfo();
 	auto box = Box<EditAdminBox>(
 		_peer,
 		user,
@@ -634,7 +634,7 @@ void AddSpecialBoxController::showAdmin(
 		_additional.adminRank(user));
 	if (_additional.canAddOrEditAdmin(user)) {
 		const auto done = crl::guard(this, [=](
-				const MTPChatAdminRights &newRights,
+				ChatAdminRightsInfo newRights,
 				const QString &rank) {
 			editAdminDone(user, newRights, rank);
 		});
@@ -650,7 +650,7 @@ void AddSpecialBoxController::showAdmin(
 
 void AddSpecialBoxController::editAdminDone(
 		not_null<UserData*> user,
-		const MTPChatAdminRights &rights,
+		ChatAdminRightsInfo rights,
 		const QString &rank) {
 	if (_editParticipantBox) {
 		_editParticipantBox->closeBox();
@@ -662,9 +662,11 @@ void AddSpecialBoxController::editAdminDone(
 		_additional.applyParticipant(MTP_channelParticipantCreator(
 			MTP_flags(rank.isEmpty() ? Flag(0) : Flag::f_rank),
 			peerToBareMTPInt(user->id),
-			rights,
+			MTP_chatAdminRights(
+				MTP_flags(MTPDchatAdminRights::Flags::from_raw(
+					uint32(rights.flags)))),
 			MTP_string(rank)));
-	} else if (rights.c_chatAdminRights().vflags().v == 0) {
+	} else if (!rights.flags) {
 		_additional.applyParticipant(MTP_channelParticipant(
 			peerToBareMTPInt(user->id),
 			MTP_int(date)));
@@ -680,7 +682,9 @@ void AddSpecialBoxController::editAdminDone(
 				? alreadyPromotedBy->id
 				: user->session().userPeerId()),
 			MTP_int(date),
-			rights,
+			MTP_chatAdminRights(
+				MTP_flags(MTPDchatAdminRights::Flags::from_raw(
+					uint32(rights.flags)))),
 			MTP_string(rank)));
 	}
 	if (const auto callback = _adminDoneCallback) {
@@ -730,7 +734,7 @@ void AddSpecialBoxController::showRestricted(
 	// Finally edit the restricted.
 	const auto currentRights = restrictedRights
 		? *restrictedRights
-		: ChannelData::EmptyRestrictedRights(user);
+		: ChatRestrictionsInfo();
 	auto box = Box<EditRestrictedBox>(
 		_peer,
 		user,
@@ -738,7 +742,7 @@ void AddSpecialBoxController::showRestricted(
 		currentRights);
 	if (_additional.canRestrictParticipant(user)) {
 		const auto done = crl::guard(this, [=](
-				const MTPChatBannedRights &newRights) {
+				ChatRestrictionsInfo newRights) {
 			editRestrictedDone(user, newRights);
 		});
 		const auto fail = crl::guard(this, [=] {
@@ -754,13 +758,13 @@ void AddSpecialBoxController::showRestricted(
 
 void AddSpecialBoxController::editRestrictedDone(
 		not_null<PeerData*> participant,
-		const MTPChatBannedRights &rights) {
+		ChatRestrictionsInfo rights) {
 	if (_editParticipantBox) {
 		_editParticipantBox->closeBox();
 	}
 
 	const auto date = base::unixtime::now(); // Incorrect, but ignored.
-	if (Data::ChatBannedRightsFlags(rights) == 0) {
+	if (!rights.flags) {
 		if (const auto user = participant->asUser()) {
 			_additional.applyParticipant(MTP_channelParticipant(
 				peerToBareMTPInt(user->id),
@@ -769,8 +773,7 @@ void AddSpecialBoxController::editRestrictedDone(
 			_additional.setExternal(participant);
 		}
 	} else {
-		const auto kicked = Data::ChatBannedRightsFlags(rights)
-			& ChatRestriction::f_view_messages;
+		const auto kicked = rights.flags & ChatRestriction::ViewMessages;
 		const auto alreadyRestrictedBy = _additional.restrictedBy(
 			participant);
 		_additional.applyParticipant(MTP_channelParticipantBanned(
@@ -782,7 +785,10 @@ void AddSpecialBoxController::editRestrictedDone(
 				? alreadyRestrictedBy->id
 				: participant->session().userPeerId()),
 			MTP_int(date),
-			rights));
+			MTP_chatBannedRights(
+				MTP_flags(MTPDchatBannedRights::Flags::from_raw(
+					uint32(rights.flags))),
+				MTP_int(rights.until))));
 	}
 	if (const auto callback = _bannedDoneCallback) {
 		callback(participant, rights);
@@ -839,10 +845,10 @@ void AddSpecialBoxController::kickUser(
 	const auto restrictedRights = _additional.restrictedRights(participant);
 	const auto currentRights = restrictedRights
 		? *restrictedRights
-		: ChannelData::EmptyRestrictedRights(participant);
+		: ChatRestrictionsInfo();
 
 	const auto done = crl::guard(this, [=](
-			const MTPChatBannedRights &newRights) {
+			ChatRestrictionsInfo newRights) {
 		editRestrictedDone(participant, newRights);
 	});
 	const auto fail = crl::guard(this, [=] {
diff --git a/Telegram/SourceFiles/boxes/peers/add_participants_box.h b/Telegram/SourceFiles/boxes/peers/add_participants_box.h
index 803860601..b2f64dd3f 100644
--- a/Telegram/SourceFiles/boxes/peers/add_participants_box.h
+++ b/Telegram/SourceFiles/boxes/peers/add_participants_box.h
@@ -10,6 +10,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "boxes/peer_list_controllers.h"
 #include "boxes/peers/edit_participants_box.h"
 
+struct ChatAdminRightsInfo;
+struct ChatRestrictionsInfo;
+
 namespace Window {
 class SessionNavigation;
 } // namespace Window
@@ -77,11 +80,11 @@ public:
 
 	using AdminDoneCallback = Fn<void(
 		not_null<UserData*> user,
-		const MTPChatAdminRights &adminRights,
+		ChatAdminRightsInfo adminRights,
 		const QString &rank)>;
 	using BannedDoneCallback = Fn<void(
 		not_null<PeerData*> participant,
-		const MTPChatBannedRights &bannedRights)>;
+		ChatRestrictionsInfo bannedRights)>;
 	AddSpecialBoxController(
 		not_null<PeerData*> peer,
 		Role role,
@@ -109,12 +112,12 @@ private:
 	void showAdmin(not_null<UserData*> user, bool sure = false);
 	void editAdminDone(
 		not_null<UserData*> user,
-		const MTPChatAdminRights &rights,
+		ChatAdminRightsInfo rights,
 		const QString &rank);
 	void showRestricted(not_null<UserData*> user, bool sure = false);
 	void editRestrictedDone(
 		not_null<PeerData*> participant,
-		const MTPChatBannedRights &rights);
+		ChatRestrictionsInfo rights);
 	void kickUser(not_null<PeerData*> participant, bool sure = false);
 	bool appendRow(not_null<PeerData*> participant);
 	bool prependRow(not_null<UserData*> user);
diff --git a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp
index e8c1d55df..daae81777 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp
@@ -197,43 +197,45 @@ EditAdminBox::EditAdminBox(
 	QWidget*,
 	not_null<PeerData*> peer,
 	not_null<UserData*> user,
-	const MTPChatAdminRights &rights,
+	ChatAdminRightsInfo rights,
 	const QString &rank)
 : EditParticipantBox(
 	nullptr,
 	peer,
 	user,
-	(rights.c_chatAdminRights().vflags().v != 0))
+	(rights.flags != 0))
 , _oldRights(rights)
 , _oldRank(rank) {
 }
 
-MTPChatAdminRights EditAdminBox::defaultRights() const {
-	const auto flags = peer()->isChat()
+ChatAdminRightsInfo EditAdminBox::defaultRights() const {
+	using Flag = ChatAdminRight;
+
+	return peer()->isChat()
 		? peer()->asChat()->defaultAdminRights(user())
 		: peer()->isMegagroup()
-		? (Flag::f_change_info
-			| Flag::f_delete_messages
-			| Flag::f_ban_users
-			| Flag::f_invite_users
-			| Flag::f_pin_messages
-			| Flag::f_manage_call)
-		: (Flag::f_change_info
-			| Flag::f_post_messages
-			| Flag::f_edit_messages
-			| Flag::f_delete_messages
-			| Flag::f_invite_users
-			| Flag::f_manage_call);
-	return MTP_chatAdminRights(MTP_flags(flags));
+		? ChatAdminRightsInfo{ (Flag::ChangeInfo
+			| Flag::DeleteMessages
+			| Flag::BanUsers
+			| Flag::InviteUsers
+			| Flag::PinMessages
+			| Flag::ManageCall) }
+		: ChatAdminRightsInfo{ (Flag::ChangeInfo
+			| Flag::PostMessages
+			| Flag::EditMessages
+			| Flag::DeleteMessages
+			| Flag::InviteUsers
+			| Flag::ManageCall) };
 }
 
 void EditAdminBox::prepare() {
 	using namespace rpl::mappers;
+	using Flag = ChatAdminRight;
+	using Flags = ChatAdminRights;
 
 	EditParticipantBox::prepare();
 
-	auto hadRights = _oldRights.c_chatAdminRights().vflags().v;
-	setTitle(hadRights
+	setTitle(_oldRights.flags
 		? tr::lng_rights_edit_admin()
 		: tr::lng_channel_add_admin());
 
@@ -243,16 +245,18 @@ void EditAdminBox::prepare() {
 
 	const auto chat = peer()->asChat();
 	const auto channel = peer()->asChannel();
-	const auto prepareRights = hadRights ? _oldRights : defaultRights();
+	const auto prepareRights = _oldRights.flags
+		? _oldRights
+		: defaultRights();
 	const auto disabledByDefaults = (channel && !channel->isMegagroup())
-		? MTPDchatAdminRights::Flags(0)
+		? ChatAdminRights()
 		: DisabledByDefaultRestrictions(peer());
 	const auto filterByMyRights = canSave()
-		&& !hadRights
+		&& !_oldRights.flags
 		&& channel
 		&& !channel->amCreator();
 	const auto prepareFlags = disabledByDefaults
-		| (prepareRights.c_chatAdminRights().vflags().v
+		| (prepareRights.flags
 			& (filterByMyRights ? channel->adminRights() : ~Flag(0)));
 
 	const auto disabledMessages = [&] {
@@ -267,7 +271,7 @@ void EditAdminBox::prepare() {
 				tr::lng_rights_permission_for_all(tr::now));
 			if (amCreator() && user()->isSelf()) {
 				result.emplace(
-					~Flag::f_anonymous,
+					~Flag::Anonymous,
 					tr::lng_rights_permission_cant_edit(tr::now));
 			} else if (const auto channel = peer()->asChannel()) {
 				if (!channel->amCreator()) {
@@ -304,7 +308,7 @@ void EditAdminBox::prepare() {
 	rpl::duplicate(
 		selectedFlags
 	) | rpl::map(
-		(_1 & Flag::f_add_admins) != 0
+		(_1 & Flag::AddAdmins) != 0
 	) | rpl::distinct_until_changed(
 	) | rpl::start_with_next([=](bool checked) {
 		refreshAboutAddAdminsText(checked);
@@ -330,13 +334,13 @@ void EditAdminBox::prepare() {
 			if (!_saveCallback) {
 				return;
 			}
-			const auto newFlags = (value() | ChatAdminRight::f_other)
+			const auto newFlags = (value() | ChatAdminRight::Other)
 				& ((!channel || channel->amCreator())
 					? ~Flags(0)
 					: channel->adminRights());
 			_saveCallback(
 				_oldRights,
-				MTP_chatAdminRights(MTP_flags(newFlags)),
+				ChatAdminRightsInfo(newFlags),
 				rank ? rank->getLastText().trimmed() : QString());
 		});
 		addButton(tr::lng_cancel(), [=] { closeBox(); });
@@ -593,12 +597,15 @@ EditRestrictedBox::EditRestrictedBox(
 	not_null<PeerData*> peer,
 	not_null<UserData*> user,
 	bool hasAdminRights,
-	const MTPChatBannedRights &rights)
+	ChatRestrictionsInfo rights)
 : EditParticipantBox(nullptr, peer, user, hasAdminRights)
 , _oldRights(rights) {
 }
 
 void EditRestrictedBox::prepare() {
+	using Flag = ChatRestriction;
+	using Flags = ChatRestrictions;
+
 	EditParticipantBox::prepare();
 
 	setTitle(tr::lng_rights_user_restrictions());
@@ -612,14 +619,14 @@ void EditRestrictedBox::prepare() {
 	const auto defaultRestrictions = chat
 		? chat->defaultRestrictions()
 		: channel->defaultRestrictions();
-	const auto prepareRights = Data::ChatBannedRightsFlags(_oldRights)
+	const auto prepareRights = _oldRights.flags
 		? _oldRights
 		: defaultRights();
 	const auto prepareFlags = FixDependentRestrictions(
-		Data::ChatBannedRightsFlags(prepareRights)
+		prepareRights.flags
 		| defaultRestrictions
 		| ((channel && channel->isPublic())
-			? (Flag::f_change_info | Flag::f_pin_messages)
+			? (Flag::ChangeInfo | Flag::PinMessages)
 			: Flags(0)));
 	const auto disabledMessages = [&] {
 		auto result = std::map<Flags, QString>();
@@ -631,7 +638,7 @@ void EditRestrictedBox::prepare() {
 			const auto disabled = FixDependentRestrictions(
 				defaultRestrictions
 				| ((channel && channel->isPublic())
-					? (Flag::f_change_info | Flag::f_pin_messages)
+					? (Flag::ChangeInfo | Flag::PinMessages)
 					: Flags(0)));
 			result.emplace(
 				disabled,
@@ -647,7 +654,7 @@ void EditRestrictedBox::prepare() {
 		disabledMessages);
 	addControl(std::move(checkboxes), QMargins());
 
-	_until = Data::ChatBannedRightsUntilDate(prepareRights);
+	_until = prepareRights.until;
 	addControl(object_ptr<Ui::BoxContentDivider>(this), st::rightsUntilMargin);
 	addControl(
 		object_ptr<Ui::FlatLabel>(
@@ -670,9 +677,7 @@ void EditRestrictedBox::prepare() {
 			}
 			_saveCallback(
 				_oldRights,
-				MTP_chatBannedRights(
-					MTP_flags(value()),
-					MTP_int(getRealUntilValue())));
+				ChatRestrictionsInfo{ value(), getRealUntilValue() });
 		};
 		addButton(tr::lng_settings_save(), save);
 		addButton(tr::lng_cancel(), [=] { closeBox(); });
@@ -681,8 +686,8 @@ void EditRestrictedBox::prepare() {
 	}
 }
 
-MTPChatBannedRights EditRestrictedBox::defaultRights() const {
-	return MTP_chatBannedRights(MTP_flags(0), MTP_int(0));
+ChatRestrictionsInfo EditRestrictedBox::defaultRights() const {
+	return ChatRestrictionsInfo();
 }
 
 void EditRestrictedBox::showRestrictUntil() {
@@ -767,7 +772,7 @@ void EditRestrictedBox::createUntilVariants() {
 		}
 	};
 	auto addCurrentVariant = [&](TimeId from, TimeId to) {
-		auto oldUntil = Data::ChatBannedRightsUntilDate(_oldRights);
+		auto oldUntil = _oldRights.until;
 		if (oldUntil < _until) {
 			addCustomVariant(oldUntil, from, to);
 		}
diff --git a/Telegram/SourceFiles/boxes/peers/edit_participant_box.h b/Telegram/SourceFiles/boxes/peers/edit_participant_box.h
index 56f3b0a56..bbcf517a2 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_participant_box.h
+++ b/Telegram/SourceFiles/boxes/peers/edit_participant_box.h
@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 
 #include "boxes/abstract_box.h"
 #include "base/unique_qptr.h"
+#include "data/data_peer.h"
 
 namespace MTP {
 class Error;
@@ -73,13 +74,13 @@ public:
 		QWidget*,
 		not_null<PeerData*> peer,
 		not_null<UserData*> user,
-		const MTPChatAdminRights &rights,
+		ChatAdminRightsInfo rights,
 		const QString &rank);
 
 	void setSaveCallback(
 			Fn<void(
-				MTPChatAdminRights,
-				MTPChatAdminRights,
+				ChatAdminRightsInfo,
+				ChatAdminRightsInfo,
 				const QString &rank)> callback) {
 		_saveCallback = std::move(callback);
 	}
@@ -88,10 +89,7 @@ protected:
 	void prepare() override;
 
 private:
-	using Flag = MTPDchatAdminRights::Flag;
-	using Flags = MTPDchatAdminRights::Flags;
-
-	[[nodiscard]] MTPChatAdminRights defaultRights() const;
+	[[nodiscard]] ChatAdminRightsInfo defaultRights() const;
 
 	not_null<Ui::InputField*> addRankInput();
 	void transferOwnership();
@@ -109,11 +107,11 @@ private:
 	bool canTransferOwnership() const;
 	not_null<Ui::SlideWrap<Ui::RpWidget>*> setupTransferButton(bool isGroup);
 
-	const MTPChatAdminRights _oldRights;
+	const ChatAdminRightsInfo _oldRights;
 	const QString _oldRank;
 	Fn<void(
-		MTPChatAdminRights,
-		MTPChatAdminRights,
+		ChatAdminRightsInfo,
+		ChatAdminRightsInfo,
 		const QString &rank)> _saveCallback;
 
 	QPointer<Ui::FlatLabel> _aboutAddAdmins;
@@ -132,10 +130,10 @@ public:
 		not_null<PeerData*> peer,
 		not_null<UserData*> user,
 		bool hasAdminRights,
-		const MTPChatBannedRights &rights);
+		ChatRestrictionsInfo rights);
 
 	void setSaveCallback(
-			Fn<void(MTPChatBannedRights, MTPChatBannedRights)> callback) {
+			Fn<void(ChatRestrictionsInfo, ChatRestrictionsInfo)> callback) {
 		_saveCallback = std::move(callback);
 	}
 
@@ -143,10 +141,7 @@ protected:
 	void prepare() override;
 
 private:
-	using Flag = MTPDchatBannedRights::Flag;
-	using Flags = MTPDchatBannedRights::Flags;
-
-	[[nodiscard]] MTPChatBannedRights defaultRights() const;
+	[[nodiscard]] ChatRestrictionsInfo defaultRights() const;
 
 	bool canSave() const {
 		return !!_saveCallback;
@@ -158,9 +153,9 @@ private:
 	void createUntilVariants();
 	TimeId getRealUntilValue() const;
 
-	const MTPChatBannedRights _oldRights;
+	const ChatRestrictionsInfo _oldRights;
 	TimeId _until = 0;
-	Fn<void(MTPChatBannedRights, MTPChatBannedRights)> _saveCallback;
+	Fn<void(ChatRestrictionsInfo, ChatRestrictionsInfo)> _saveCallback;
 
 	std::shared_ptr<Ui::RadiobuttonGroup> _untilGroup;
 	std::vector<base::unique_qptr<Ui::Radiobutton>> _untilVariants;
diff --git a/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp
index 35fff4895..883dda163 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp
@@ -43,7 +43,7 @@ constexpr auto kSortByOnlineDelay = crl::time(1000);
 void RemoveAdmin(
 		not_null<ChannelData*> channel,
 		not_null<UserData*> user,
-		const MTPChatAdminRights &oldRights,
+		ChatAdminRightsInfo oldRights,
 		Fn<void()> onDone,
 		Fn<void()> onFail) {
 	const auto newRights = MTP_chatAdminRights(MTP_flags(0));
@@ -54,7 +54,7 @@ void RemoveAdmin(
 		MTP_string(QString())
 	)).done([=](const MTPUpdates &result) {
 		channel->session().api().applyUpdates(result);
-		channel->applyEditAdmin(user, oldRights, newRights, QString());
+		channel->applyEditAdmin(user, oldRights, ChatAdminRightsInfo(), QString());
 		if (onDone) {
 			onDone();
 		}
@@ -120,15 +120,16 @@ void SaveChatAdmin(
 void SaveChannelAdmin(
 		not_null<ChannelData*> channel,
 		not_null<UserData*> user,
-		const MTPChatAdminRights &oldRights,
-		const MTPChatAdminRights &newRights,
+		ChatAdminRightsInfo oldRights,
+		ChatAdminRightsInfo newRights,
 		const QString &rank,
 		Fn<void()> onDone,
 		Fn<void()> onFail) {
 	channel->session().api().request(MTPchannels_EditAdmin(
 		channel->inputChannel,
 		user->inputUser,
-		newRights,
+		MTP_chatAdminRights(MTP_flags(
+			MTPDchatAdminRights::Flags::from_raw(uint32(newRights.flags)))),
 		MTP_string(rank)
 	)).done([=](const MTPUpdates &result) {
 		channel->session().api().applyUpdates(result);
@@ -147,14 +148,17 @@ void SaveChannelAdmin(
 void SaveChannelRestriction(
 		not_null<ChannelData*> channel,
 		not_null<PeerData*> participant,
-		const MTPChatBannedRights &oldRights,
-		const MTPChatBannedRights &newRights,
+		ChatRestrictionsInfo oldRights,
+		ChatRestrictionsInfo newRights,
 		Fn<void()> onDone,
 		Fn<void()> onFail) {
 	channel->session().api().request(MTPchannels_EditBanned(
 		channel->inputChannel,
 		participant->input,
-		newRights
+		MTP_chatBannedRights(
+			MTP_flags(MTPDchatBannedRights::Flags::from_raw(
+				uint32(newRights.flags))),
+			MTP_int(newRights.until))
 	)).done([=](const MTPUpdates &result) {
 		channel->session().api().applyUpdates(result);
 		channel->applyEditBanned(participant, oldRights, newRights);
@@ -192,18 +196,18 @@ void SaveChatParticipantKick(
 } // namespace
 
 Fn<void(
-	const MTPChatAdminRights &oldRights,
-	const MTPChatAdminRights &newRights,
+	ChatAdminRightsInfo oldRights,
+	ChatAdminRightsInfo newRights,
 	const QString &rank)> SaveAdminCallback(
 		not_null<PeerData*> peer,
 		not_null<UserData*> user,
 		Fn<void(
-			const MTPChatAdminRights &newRights,
+			ChatAdminRightsInfo newRights,
 			const QString &rank)> onDone,
 		Fn<void()> onFail) {
 	return [=](
-			const MTPChatAdminRights &oldRights,
-			const MTPChatAdminRights &newRights,
+			ChatAdminRightsInfo oldRights,
+			ChatAdminRightsInfo newRights,
 			const QString &rank) {
 		const auto done = [=] { if (onDone) onDone(newRights, rank); };
 		const auto saveForChannel = [=](not_null<ChannelData*> channel) {
@@ -220,13 +224,10 @@ Fn<void(
 			const auto saveChatAdmin = [&](bool isAdmin) {
 				SaveChatAdmin(chat, user, isAdmin, done, onFail);
 			};
-			const auto flags = newRights.match([](
-					const MTPDchatAdminRights &data) {
-				return data.vflags().v;
-			});
-			if (flags == chat->defaultAdminRights(user) && rank.isEmpty()) {
+			if (newRights.flags == chat->defaultAdminRights(user).flags
+				&& rank.isEmpty()) {
 				saveChatAdmin(true);
-			} else if (!flags) {
+			} else if (!newRights.flags) {
 				saveChatAdmin(false);
 			} else {
 				peer->session().api().migrateChat(chat, saveForChannel);
@@ -240,15 +241,15 @@ Fn<void(
 }
 
 Fn<void(
-	const MTPChatBannedRights &oldRights,
-	const MTPChatBannedRights &newRights)> SaveRestrictedCallback(
+	ChatRestrictionsInfo oldRights,
+	ChatRestrictionsInfo newRights)> SaveRestrictedCallback(
 		not_null<PeerData*> peer,
 		not_null<PeerData*> participant,
-		Fn<void(const MTPChatBannedRights &newRights)> onDone,
+		Fn<void(ChatRestrictionsInfo newRights)> onDone,
 		Fn<void()> onFail) {
 	return [=](
-			const MTPChatBannedRights &oldRights,
-			const MTPChatBannedRights &newRights) {
+			ChatRestrictionsInfo oldRights,
+			ChatRestrictionsInfo newRights) {
 		const auto done = [=] { if (onDone) onDone(newRights); };
 		const auto saveForChannel = [=](not_null<ChannelData*> channel) {
 			SaveChannelRestriction(
@@ -260,15 +261,14 @@ Fn<void(
 				onFail);
 		};
 		if (const auto chat = peer->asChatNotMigrated()) {
-			const auto flags = Data::ChatBannedRightsFlags(newRights);
 			if (participant->isUser()
-				&& (flags & MTPDchatBannedRights::Flag::f_view_messages)) {
+				&& (newRights.flags & ChatRestriction::ViewMessages)) {
 				SaveChatParticipantKick(
 					chat,
 					participant->asUser(),
 					done,
 					onFail);
-			} else if (!flags) {
+			} else if (!newRights.flags) {
 				done();
 			} else {
 				peer->session().api().migrateChat(chat, saveForChannel);
@@ -373,11 +373,10 @@ bool ParticipantsAdditionalData::canRemoveParticipant(
 
 auto ParticipantsAdditionalData::adminRights(
 	not_null<UserData*> user) const
--> std::optional<MTPChatAdminRights> {
+-> std::optional<ChatAdminRightsInfo> {
 	if (const auto chat = _peer->asChat()) {
 		return _admins.contains(user)
-			? std::make_optional(MTPChatAdminRights(MTP_chatAdminRights(
-				MTP_flags(chat->defaultAdminRights(user)))))
+			? std::make_optional(chat->defaultAdminRights(user))
 			: std::nullopt;
 	}
 	const auto i = _adminRights.find(user);
@@ -394,7 +393,7 @@ QString ParticipantsAdditionalData::adminRank(
 
 auto ParticipantsAdditionalData::restrictedRights(
 	not_null<PeerData*> participant) const
--> std::optional<MTPChatBannedRights> {
+-> std::optional<ChatRestrictionsInfo> {
 	if (_peer->isChat()) {
 		return std::nullopt;
 	}
@@ -589,7 +588,7 @@ UserData *ParticipantsAdditionalData::applyCreator(
 		const MTPDchannelParticipantCreator &data) {
 	if (const auto user = applyRegular(data.vuser_id())) {
 		_creator = user;
-		_adminRights[user] = data.vadmin_rights();
+		_adminRights[user] = ChatAdminRightsInfo(data.vadmin_rights());
 		if (user->isSelf()) {
 			_adminCanEdit.emplace(user);
 		} else {
@@ -620,7 +619,7 @@ UserData *ParticipantsAdditionalData::applyAdmin(
 	_restrictedRights.erase(user);
 	_kicked.erase(user);
 	_restrictedBy.erase(user);
-	_adminRights[user] = data.vadmin_rights();
+	_adminRights[user] = ChatAdminRightsInfo(data.vadmin_rights());
 	if (data.is_can_edit()) {
 		_adminCanEdit.emplace(user);
 	} else {
@@ -684,7 +683,8 @@ PeerData *ParticipantsAdditionalData::applyBanned(
 	} else {
 		_kicked.erase(participant);
 	}
-	_restrictedRights[participant] = data.vbanned_rights();
+	_restrictedRights[participant] = ChatRestrictionsInfo(
+		data.vbanned_rights());
 	if (const auto by = _peer->owner().userLoaded(data.vkicked_by())) {
 		const auto i = _restrictedBy.find(participant);
 		if (i == _restrictedBy.end()) {
@@ -703,9 +703,7 @@ void ParticipantsAdditionalData::migrate(
 	fillFromChannel(channel);
 
 	for (const auto user : _admins) {
-		_adminRights.emplace(
-			user,
-			MTP_chatAdminRights(MTP_flags(chat->defaultAdminRights(user))));
+		_adminRights.emplace(user, chat->defaultAdminRights(user));
 		if (channel->amCreator()) {
 			_adminCanEdit.emplace(user);
 		}
@@ -940,13 +938,13 @@ void ParticipantsBoxController::addNewItem() {
 	}
 	const auto adminDone = crl::guard(this, [=](
 			not_null<UserData*> user,
-			const MTPChatAdminRights &rights,
+			ChatAdminRightsInfo rights,
 			const QString &rank) {
 		editAdminDone(user, rights, rank);
 	});
 	const auto restrictedDone = crl::guard(this, [=](
 			not_null<PeerData*> participant,
-			const MTPChatBannedRights &rights) {
+			ChatRestrictionsInfo rights) {
 		editRestrictedDone(participant, rights);
 	});
 	const auto initBox = [](not_null<PeerListBox*> box) {
@@ -1523,9 +1521,7 @@ base::unique_qptr<Ui::PopupMenu> ParticipantsBoxController::rowContextMenu(
 
 void ParticipantsBoxController::showAdmin(not_null<UserData*> user) {
 	const auto adminRights = _additional.adminRights(user);
-	const auto currentRights = adminRights
-		? *adminRights
-		: MTPChatAdminRights(MTP_chatAdminRights(MTP_flags(0)));
+	const auto currentRights = adminRights.value_or(ChatAdminRightsInfo());
 	auto box = Box<EditAdminBox>(
 		_peer,
 		user,
@@ -1535,7 +1531,7 @@ void ParticipantsBoxController::showAdmin(not_null<UserData*> user) {
 	const auto channel = _peer->asChannel();
 	if (_additional.canAddOrEditAdmin(user)) {
 		const auto done = crl::guard(this, [=](
-				const MTPChatAdminRights &newRights,
+				ChatAdminRightsInfo newRights,
 				const QString &rank) {
 			editAdminDone(user, newRights, rank);
 		});
@@ -1551,7 +1547,7 @@ void ParticipantsBoxController::showAdmin(not_null<UserData*> user) {
 
 void ParticipantsBoxController::editAdminDone(
 		not_null<UserData*> user,
-		const MTPChatAdminRights &rights,
+		ChatAdminRightsInfo rights,
 		const QString &rank) {
 	_addBox = nullptr;
 	if (_editParticipantBox) {
@@ -1564,9 +1560,11 @@ void ParticipantsBoxController::editAdminDone(
 		_additional.applyParticipant(MTP_channelParticipantCreator(
 			MTP_flags(rank.isEmpty() ? Flag(0) : Flag::f_rank),
 			peerToBareMTPInt(user->id),
-			rights,
+			MTP_chatAdminRights(
+				MTP_flags(MTPDchatAdminRights::Flags::from_raw(
+					uint32(rights.flags)))),
 			MTP_string(rank)));
-	} else if (rights.c_chatAdminRights().vflags().v == 0) {
+	} else if (!rights.flags) {
 		_additional.applyParticipant(MTP_channelParticipant(
 			peerToBareMTPInt(user->id),
 			MTP_int(date)));
@@ -1585,7 +1583,9 @@ void ParticipantsBoxController::editAdminDone(
 				? alreadyPromotedBy->id
 				: user->session().userPeerId()),
 			MTP_int(date),
-			rights,
+			MTP_chatAdminRights(
+				MTP_flags(MTPDchatAdminRights::Flags::from_raw(
+					uint32(rights.flags)))),
 			MTP_string(rank)));
 		if (_role == Role::Admins) {
 			prependRow(user);
@@ -1601,7 +1601,7 @@ void ParticipantsBoxController::showRestricted(not_null<UserData*> user) {
 	const auto restrictedRights = _additional.restrictedRights(user);
 	const auto currentRights = restrictedRights
 		? *restrictedRights
-		: ChannelData::EmptyRestrictedRights(user);
+		: ChatRestrictionsInfo();
 	const auto hasAdminRights = _additional.adminRights(user).has_value();
 	auto box = Box<EditRestrictedBox>(
 		_peer,
@@ -1612,7 +1612,7 @@ void ParticipantsBoxController::showRestricted(not_null<UserData*> user) {
 	const auto channel = _peer->asChannel();
 	if (_additional.canRestrictParticipant(user)) {
 		const auto done = crl::guard(this, [=](
-				const MTPChatBannedRights &newRights) {
+				ChatRestrictionsInfo newRights) {
 			editRestrictedDone(user, newRights);
 		});
 		const auto fail = crl::guard(this, [=] {
@@ -1628,7 +1628,7 @@ void ParticipantsBoxController::showRestricted(not_null<UserData*> user) {
 
 void ParticipantsBoxController::editRestrictedDone(
 		not_null<PeerData*> participant,
-		const MTPChatBannedRights &rights) {
+		ChatRestrictionsInfo rights) {
 	_addBox = nullptr;
 	if (_editParticipantBox) {
 		_editParticipantBox->closeBox();
@@ -1636,7 +1636,7 @@ void ParticipantsBoxController::editRestrictedDone(
 
 	const auto user = participant->asUser();
 	const auto date = base::unixtime::now(); // Incorrect, but ignored.
-	if (Data::ChatBannedRightsFlags(rights) == 0) {
+	if (!rights.flags) {
 		if (user) {
 			_additional.applyParticipant(MTP_channelParticipant(
 				peerToBareMTPInt(user->id),
@@ -1648,8 +1648,7 @@ void ParticipantsBoxController::editRestrictedDone(
 			removeRow(participant);
 		}
 	} else {
-		const auto kicked = Data::ChatBannedRightsFlags(rights)
-			& ChatRestriction::f_view_messages;
+		const auto kicked = rights.flags & ChatRestriction::ViewMessages;
 		const auto alreadyRestrictedBy = _additional.restrictedBy(
 			participant);
 		_additional.applyParticipant(MTP_channelParticipantBanned(
@@ -1661,7 +1660,10 @@ void ParticipantsBoxController::editRestrictedDone(
 				? alreadyRestrictedBy->id
 				: participant->session().userPeerId()),
 			MTP_int(date),
-			rights));
+			MTP_chatBannedRights(
+				MTP_flags(MTPDchatBannedRights::Flags::from_raw(
+					uint32(rights.flags))),
+				MTP_int(rights.until))));
 		if (kicked) {
 			if (_role == Role::Kicked) {
 				prependRow(participant);
@@ -1716,7 +1718,7 @@ void ParticipantsBoxController::kickParticipantSure(
 	const auto restrictedRights = _additional.restrictedRights(participant);
 	const auto currentRights = restrictedRights
 		? *restrictedRights
-		: ChannelData::EmptyRestrictedRights(participant);
+		: ChatRestrictionsInfo();
 
 	if (const auto row = delegate()->peerListFindRow(participant->id.value)) {
 		delegate()->peerListRemoveRow(row);
@@ -1749,7 +1751,7 @@ void ParticipantsBoxController::removeAdminSure(not_null<UserData*> user) {
 		SaveChatAdmin(chat, user, false, crl::guard(this, [=] {
 			editAdminDone(
 				user,
-				MTP_chatAdminRights(MTP_flags(0)),
+				ChatAdminRightsInfo(),
 				QString());
 		}), nullptr);
 	} else if (const auto channel = _peer->asChannel()) {
@@ -1760,7 +1762,7 @@ void ParticipantsBoxController::removeAdminSure(not_null<UserData*> user) {
 		RemoveAdmin(channel, user, *adminRights, crl::guard(this, [=] {
 			editAdminDone(
 				user,
-				MTP_chatAdminRights(MTP_flags(0)),
+				ChatAdminRightsInfo(),
 				QString());
 		}), nullptr);
 	}
diff --git a/Telegram/SourceFiles/boxes/peers/edit_participants_box.h b/Telegram/SourceFiles/boxes/peers/edit_participants_box.h
index cb5550f47..d46f76243 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_participants_box.h
+++ b/Telegram/SourceFiles/boxes/peers/edit_participants_box.h
@@ -14,27 +14,30 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "base/weak_ptr.h"
 #include "info/profile/info_profile_members_controllers.h"
 
+struct ChatAdminRightsInfo;
+struct ChatRestrictionsInfo;
+
 namespace Window {
 class SessionNavigation;
 } // namespace Window
 
 Fn<void(
-	const MTPChatAdminRights &oldRights,
-	const MTPChatAdminRights &newRights,
+	ChatAdminRightsInfo oldRights,
+	ChatAdminRightsInfo newRights,
 	const QString &rank)> SaveAdminCallback(
 		not_null<PeerData*> peer,
 		not_null<UserData*> user,
 		Fn<void(
-			const MTPChatAdminRights &newRights,
+			ChatAdminRightsInfo newRights,
 			const QString &rank)> onDone,
 		Fn<void()> onFail);
 
 Fn<void(
-	const MTPChatBannedRights &oldRights,
-	const MTPChatBannedRights &newRights)> SaveRestrictedCallback(
+	ChatRestrictionsInfo oldRights,
+	ChatRestrictionsInfo newRights)> SaveRestrictedCallback(
 		not_null<PeerData*> peer,
 		not_null<PeerData*> participant,
-		Fn<void(const MTPChatBannedRights &newRights)> onDone,
+		Fn<void(ChatRestrictionsInfo newRights)> onDone,
 		Fn<void()> onFail);
 
 void SubscribeToMigration(
@@ -92,10 +95,10 @@ public:
 		not_null<PeerData*> participant) const;
 	[[nodiscard]] bool canRemoveParticipant(
 		not_null<PeerData*> participant) const;
-	[[nodiscard]] std::optional<MTPChatAdminRights> adminRights(
+	[[nodiscard]] std::optional<ChatAdminRightsInfo> adminRights(
 		not_null<UserData*> user) const;
 	QString adminRank(not_null<UserData*> user) const;
-	[[nodiscard]] std::optional<MTPChatBannedRights> restrictedRights(
+	[[nodiscard]] std::optional<ChatRestrictionsInfo> restrictedRights(
 		not_null<PeerData*> participant) const;
 	[[nodiscard]] bool isCreator(not_null<UserData*> user) const;
 	[[nodiscard]] bool isExternal(not_null<PeerData*> participant) const;
@@ -122,11 +125,11 @@ private:
 	base::flat_set<not_null<UserData*>> _admins;
 
 	// Data for channels.
-	base::flat_map<not_null<UserData*>, MTPChatAdminRights> _adminRights;
+	base::flat_map<not_null<UserData*>, ChatAdminRightsInfo> _adminRights;
 	base::flat_map<not_null<UserData*>, QString> _adminRanks;
 	base::flat_set<not_null<UserData*>> _adminCanEdit;
 	base::flat_map<not_null<UserData*>, not_null<UserData*>> _adminPromotedBy;
-	std::map<not_null<PeerData*>, MTPChatBannedRights> _restrictedRights;
+	std::map<not_null<PeerData*>, ChatRestrictionsInfo> _restrictedRights;
 	std::set<not_null<PeerData*>> _kicked;
 	std::map<not_null<PeerData*>, not_null<UserData*>> _restrictedBy;
 	std::set<not_null<PeerData*>> _external;
@@ -221,12 +224,12 @@ private:
 	void showAdmin(not_null<UserData*> user);
 	void editAdminDone(
 		not_null<UserData*> user,
-		const MTPChatAdminRights &rights,
+		ChatAdminRightsInfo rights,
 		const QString &rank);
 	void showRestricted(not_null<UserData*> user);
 	void editRestrictedDone(
 		not_null<PeerData*> participant,
-		const MTPChatBannedRights &rights);
+		ChatRestrictionsInfo rights);
 	void removeKicked(
 		not_null<PeerListRow*> row,
 		not_null<PeerData*> participant);
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp
index 35b92a931..c46bacfb2 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp
@@ -140,7 +140,7 @@ void AddButtonDelete(
 
 void SaveDefaultRestrictions(
 		not_null<PeerData*> peer,
-		MTPChatBannedRights rights,
+		ChatRestrictions rights,
 		Fn<void()> done) {
 	const auto api = &peer->session().api();
 	const auto key = Api::RequestKey("default_restrictions", peer->id);
@@ -148,7 +148,10 @@ void SaveDefaultRestrictions(
 	const auto requestId = api->request(
 		MTPmessages_EditChatDefaultBannedRights(
 			peer->input,
-			rights)
+			MTP_chatBannedRights(
+				MTP_flags(
+					MTPDchatBannedRights::Flags::from_raw(uint32(rights))),
+				MTP_int(0)))
 	).done([=](const MTPUpdates &result) {
 		api->clearModifyRequest(key);
 		api->applyUpdates(result);
@@ -215,7 +218,7 @@ void ShowEditPermissions(
 		const auto close = crl::guard(box, [=] { box->closeBox(); });
 		SaveDefaultRestrictions(
 			peer,
-			MTP_chatBannedRights(MTP_flags(result.rights), MTP_int(0)),
+			result.rights,
 			close);
 		if (const auto channel = peer->asChannel()) {
 			SaveSlowmodeSeconds(channel, result.slowmodeSeconds, close);
@@ -260,7 +263,7 @@ void ShowEditInviteLinks(
 		const auto close = crl::guard(box, [=] { box->closeBox(); });
 		SaveDefaultRestrictions(
 			peer,
-			MTP_chatBannedRights(MTP_flags(result.rights), MTP_int(0)),
+			result.rights,
 			close);
 		if (const auto channel = peer->asChannel()) {
 			SaveSlowmodeSeconds(channel, result.slowmodeSeconds, close);
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp
index aa8573235..bec94468e 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp
@@ -133,26 +133,26 @@ std::vector<std::pair<ChatAdminRights, QString>> AdminRightLabels(
 
 	if (isGroup) {
 		return {
-			{ Flag::f_change_info, tr::lng_rights_group_info(tr::now) },
-			{ Flag::f_delete_messages, tr::lng_rights_group_delete(tr::now) },
-			{ Flag::f_ban_users, tr::lng_rights_group_ban(tr::now) },
-			{ Flag::f_invite_users, anyoneCanAddMembers
+			{ Flag::ChangeInfo, tr::lng_rights_group_info(tr::now) },
+			{ Flag::DeleteMessages, tr::lng_rights_group_delete(tr::now) },
+			{ Flag::BanUsers, tr::lng_rights_group_ban(tr::now) },
+			{ Flag::InviteUsers, anyoneCanAddMembers
 				? tr::lng_rights_group_invite_link(tr::now)
 				: tr::lng_rights_group_invite(tr::now) },
-			{ Flag::f_pin_messages, tr::lng_rights_group_pin(tr::now) },
-			{ Flag::f_manage_call, tr::lng_rights_group_manage_calls(tr::now) },
-			{ Flag::f_anonymous, tr::lng_rights_group_anonymous(tr::now) },
-			{ Flag::f_add_admins, tr::lng_rights_add_admins(tr::now) },
+			{ Flag::PinMessages, tr::lng_rights_group_pin(tr::now) },
+			{ Flag::ManageCall, tr::lng_rights_group_manage_calls(tr::now) },
+			{ Flag::Anonymous, tr::lng_rights_group_anonymous(tr::now) },
+			{ Flag::AddAdmins, tr::lng_rights_add_admins(tr::now) },
 		};
 	} else {
 		return {
-			{ Flag::f_change_info, tr::lng_rights_channel_info(tr::now) },
-			{ Flag::f_post_messages, tr::lng_rights_channel_post(tr::now) },
-			{ Flag::f_edit_messages, tr::lng_rights_channel_edit(tr::now) },
-			{ Flag::f_delete_messages, tr::lng_rights_channel_delete(tr::now) },
-			{ Flag::f_invite_users, tr::lng_rights_group_invite(tr::now) },
-			{ Flag::f_manage_call, tr::lng_rights_group_manage_calls(tr::now) },
-			{ Flag::f_add_admins, tr::lng_rights_add_admins(tr::now) }
+			{ Flag::ChangeInfo, tr::lng_rights_channel_info(tr::now) },
+			{ Flag::PostMessages, tr::lng_rights_channel_post(tr::now) },
+			{ Flag::EditMessages, tr::lng_rights_channel_edit(tr::now) },
+			{ Flag::DeleteMessages, tr::lng_rights_channel_delete(tr::now) },
+			{ Flag::InviteUsers, tr::lng_rights_group_invite(tr::now) },
+			{ Flag::ManageCall, tr::lng_rights_group_manage_calls(tr::now) },
+			{ Flag::AddAdmins, tr::lng_rights_add_admins(tr::now) }
 		};
 	}
 }
@@ -163,31 +163,31 @@ auto Dependencies(ChatRestrictions)
 
 	return {
 		// stickers <-> gifs
-		{ Flag::f_send_gifs, Flag::f_send_stickers },
-		{ Flag::f_send_stickers, Flag::f_send_gifs },
+		{ Flag::SendGifs, Flag::SendStickers },
+		{ Flag::SendStickers, Flag::SendGifs },
 
 		// stickers <-> games
-		{ Flag::f_send_games, Flag::f_send_stickers },
-		{ Flag::f_send_stickers, Flag::f_send_games },
+		{ Flag::SendGames, Flag::SendStickers },
+		{ Flag::SendStickers, Flag::SendGames },
 
 		// stickers <-> inline
-		{ Flag::f_send_inline, Flag::f_send_stickers },
-		{ Flag::f_send_stickers, Flag::f_send_inline },
+		{ Flag::SendInline, Flag::SendStickers },
+		{ Flag::SendStickers, Flag::SendInline },
 
-		// stickers -> send_media
-		{ Flag::f_send_stickers, Flag::f_send_messages },
+		// stickers -> send_messages
+		{ Flag::SendStickers, Flag::SendMessages },
 
-		// embed_links -> send_media
-		{ Flag::f_embed_links, Flag::f_send_messages },
+		// embed_links -> send_messages
+		{ Flag::EmbedLinks, Flag::SendMessages },
 
 		// send_media -> send_messages
-		{ Flag::f_send_media, Flag::f_send_messages },
+		{ Flag::SendMedia, Flag::SendMessages },
 
 		// send_polls -> send_messages
-		{ Flag::f_send_polls, Flag::f_send_messages },
+		{ Flag::SendPolls, Flag::SendMessages },
 
 		// send_messages -> view_messages
-		{ Flag::f_send_messages, Flag::f_view_messages },
+		{ Flag::SendMessages, Flag::ViewMessages },
 	};
 }
 
@@ -196,18 +196,18 @@ ChatRestrictions NegateRestrictions(ChatRestrictions value) {
 
 	return (~value) & (Flag(0)
 		// view_messages is always allowed, so it is never in restrictions.
-		//| Flag::f_view_messages
-		| Flag::f_change_info
-		| Flag::f_embed_links
-		| Flag::f_invite_users
-		| Flag::f_pin_messages
-		| Flag::f_send_games
-		| Flag::f_send_gifs
-		| Flag::f_send_inline
-		| Flag::f_send_media
-		| Flag::f_send_messages
-		| Flag::f_send_polls
-		| Flag::f_send_stickers);
+		//| Flag::ViewMessages
+		| Flag::ChangeInfo
+		| Flag::EmbedLinks
+		| Flag::InviteUsers
+		| Flag::PinMessages
+		| Flag::SendGames
+		| Flag::SendGifs
+		| Flag::SendInline
+		| Flag::SendMedia
+		| Flag::SendMessages
+		| Flag::SendPolls
+		| Flag::SendStickers);
 }
 
 auto Dependencies(ChatAdminRights)
@@ -236,15 +236,15 @@ ChatRestrictions DisabledByAdminRights(not_null<PeerData*> peer) {
 		Unexpected("User in DisabledByAdminRights.");
 	}();
 	return Flag(0)
-		| ((adminRights & Admin::f_pin_messages)
+		| ((adminRights & Admin::PinMessages)
 			? Flag(0)
-			: Flag::f_pin_messages)
-		| ((adminRights & Admin::f_invite_users)
+			: Flag::PinMessages)
+		| ((adminRights & Admin::InviteUsers)
 			? Flag(0)
-			: Flag::f_invite_users)
-		| ((adminRights & Admin::f_change_info)
+			: Flag::InviteUsers)
+		| ((adminRights & Admin::ChangeInfo)
 			? Flag(0)
-			: Flag::f_change_info);
+			: Flag::ChangeInfo);
 }
 
 } // namespace
@@ -262,21 +262,21 @@ ChatAdminRights DisabledByDefaultRestrictions(not_null<PeerData*> peer) {
 		Unexpected("User in DisabledByDefaultRestrictions.");
 	}());
 	return Flag(0)
-		| ((restrictions & Restriction::f_pin_messages)
+		| ((restrictions & Restriction::PinMessages)
 			? Flag(0)
-			: Flag::f_pin_messages)
+			: Flag::PinMessages)
 		//
 		// We allow to edit 'invite_users' admin right no matter what
 		// is chosen in default permissions for 'invite_users', because
 		// if everyone can 'invite_users' it handles invite link for admins.
 		//
-		//| ((restrictions & Restriction::f_invite_users)
+		//| ((restrictions & Restriction::InviteUsers)
 		//	? Flag(0)
-		//	: Flag::f_invite_users)
+		//	: Flag::InviteUsers)
 		//
-		| ((restrictions & Restriction::f_change_info)
+		| ((restrictions & Restriction::ChangeInfo)
 			? Flag(0)
-			: Flag::f_change_info);
+			: Flag::ChangeInfo);
 }
 
 ChatRestrictions FixDependentRestrictions(ChatRestrictions restrictions) {
@@ -284,10 +284,10 @@ ChatRestrictions FixDependentRestrictions(ChatRestrictions restrictions) {
 
 	// Fix iOS bug of saving send_inline like embed_links.
 	// We copy send_stickers to send_inline.
-	if (restrictions & ChatRestriction::f_send_stickers) {
-		restrictions |= ChatRestriction::f_send_inline;
+	if (restrictions & ChatRestriction::SendStickers) {
+		restrictions |= ChatRestriction::SendInline;
 	} else {
-		restrictions &= ~ChatRestriction::f_send_inline;
+		restrictions &= ~ChatRestriction::SendInline;
 	}
 
 	// Apply the strictest.
@@ -308,7 +308,7 @@ ChatRestrictions FixDependentRestrictions(ChatRestrictions restrictions) {
 ChatAdminRights AdminRightsForOwnershipTransfer(bool isGroup) {
 	auto result = ChatAdminRights();
 	for (const auto &[flag, label] : AdminRightLabels(isGroup, true)) {
-		if (!(flag & ChatAdminRight::f_anonymous)) {
+		if (!(flag & ChatAdminRight::Anonymous)) {
 			result |= flag;
 		}
 	}
@@ -407,7 +407,7 @@ void EditPeerPermissionsBox::prepare() {
 		} else if (const auto channel = _peer->asChannel()) {
 			return channel->defaultRestrictions()
 				| (channel->isPublic()
-					? (Flag::f_change_info | Flag::f_pin_messages)
+					? (Flag::ChangeInfo | Flag::PinMessages)
 					: Flags(0))
 				| disabledByAdminRights;
 		}
@@ -421,7 +421,7 @@ void EditPeerPermissionsBox::prepare() {
 		if (const auto channel = _peer->asChannel()) {
 			if (channel->isPublic()) {
 				result.emplace(
-					Flag::f_change_info | Flag::f_pin_messages,
+					Flag::ChangeInfo | Flag::PinMessages,
 					tr::lng_rights_permission_unavailable(tr::now));
 			}
 		}
@@ -753,11 +753,11 @@ EditFlagsControl<Flags> CreateEditFlags(
 	};
 }
 
-EditFlagsControl<MTPDchatBannedRights::Flags> CreateEditRestrictions(
+EditFlagsControl<ChatRestrictions> CreateEditRestrictions(
 		QWidget *parent,
 		rpl::producer<QString> header,
-		MTPDchatBannedRights::Flags restrictions,
-		std::map<MTPDchatBannedRights::Flags, QString> disabledMessages) {
+		ChatRestrictions restrictions,
+		std::map<ChatRestrictions, QString> disabledMessages) {
 	auto result = CreateEditFlags(
 		parent,
 		header,
@@ -774,11 +774,11 @@ EditFlagsControl<MTPDchatBannedRights::Flags> CreateEditRestrictions(
 	return result;
 }
 
-EditFlagsControl<MTPDchatAdminRights::Flags> CreateEditAdminRights(
+EditFlagsControl<ChatAdminRights> CreateEditAdminRights(
 		QWidget *parent,
 		rpl::producer<QString> header,
-		MTPDchatAdminRights::Flags rights,
-		std::map<MTPDchatAdminRights::Flags, QString> disabledMessages,
+		ChatAdminRights rights,
+		std::map<ChatAdminRights, QString> disabledMessages,
 		bool isGroup,
 		bool anyoneCanAddMembers) {
 	return CreateEditFlags(
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h
index ee4dfc0df..d11e18626 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h
@@ -27,7 +27,7 @@ public:
 		not_null<PeerData*> peer);
 
 	struct Result {
-		MTPDchatBannedRights::Flags rights;
+		ChatRestrictions rights;
 		int slowmodeSeconds = 0;
 	};
 
@@ -59,17 +59,17 @@ struct EditFlagsControl {
 	rpl::producer<Flags> changes;
 };
 
-EditFlagsControl<MTPDchatBannedRights::Flags> CreateEditRestrictions(
+EditFlagsControl<ChatRestrictions> CreateEditRestrictions(
 	QWidget *parent,
 	rpl::producer<QString> header,
-	MTPDchatBannedRights::Flags restrictions,
-	std::map<MTPDchatBannedRights::Flags, QString> disabledMessages);
+	ChatRestrictions restrictions,
+	std::map<ChatRestrictions, QString> disabledMessages);
 
-EditFlagsControl<MTPDchatAdminRights::Flags> CreateEditAdminRights(
+EditFlagsControl<ChatAdminRights> CreateEditAdminRights(
 	QWidget *parent,
 	rpl::producer<QString> header,
-	MTPDchatAdminRights::Flags rights,
-	std::map<MTPDchatAdminRights::Flags, QString> disabledMessages,
+	ChatAdminRights rights,
+	std::map<ChatAdminRights, QString> disabledMessages,
 	bool isGroup,
 	bool anyoneCanAddMembers);
 
diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.cpp b/Telegram/SourceFiles/calls/group/calls_group_call.cpp
index dae5d4255..fa300c229 100644
--- a/Telegram/SourceFiles/calls/group/calls_group_call.cpp
+++ b/Telegram/SourceFiles/calls/group/calls_group_call.cpp
@@ -230,8 +230,7 @@ GroupCall::VideoTrack::VideoTrack(
 			if (i == mgInfo->lastAdmins.end()) {
 				return false;
 			}
-			const auto &rights = i->second.rights;
-			return rights.c_chatAdminRights().is_manage_call();
+			return (i->second.rights.flags & ChatAdminRight::ManageCall);
 		}
 	}
 	return false;
diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp
index 600c2c913..d864f2724 100644
--- a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp
+++ b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp
@@ -1368,12 +1368,12 @@ void Panel::kickParticipantSure(not_null<PeerData*> participantPeer) {
 		const auto currentRestrictedRights = [&] {
 			const auto user = participantPeer->asUser();
 			if (!channel->mgInfo || !user) {
-				return ChannelData::EmptyRestrictedRights(participantPeer);
+				return ChatRestrictionsInfo();
 			}
 			const auto i = channel->mgInfo->lastRestricted.find(user);
 			return (i != channel->mgInfo->lastRestricted.cend())
 				? i->second.rights
-				: ChannelData::EmptyRestrictedRights(participantPeer);
+				: ChatRestrictionsInfo();
 		}();
 		channel->session().api().kickParticipant(
 			channel,
diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp
index ec76cb790..2b1b84056 100644
--- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp
+++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp
@@ -803,11 +803,11 @@ void TabbedSelector::checkRestrictedPeer() {
 		const auto error = (_currentTabType == SelectorTab::Stickers)
 			? Data::RestrictionError(
 				_currentPeer,
-				ChatRestriction::f_send_stickers)
+				ChatRestriction::SendStickers)
 			: (_currentTabType == SelectorTab::Gifs)
 			? Data::RestrictionError(
 				_currentPeer,
-				ChatRestriction::f_send_gifs)
+				ChatRestriction::SendGifs)
 			: std::nullopt;
 		if (error) {
 			if (!_restrictedLabel) {
diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp
index 805c7e311..500889129 100644
--- a/Telegram/SourceFiles/data/data_channel.cpp
+++ b/Telegram/SourceFiles/data/data_channel.cpp
@@ -105,7 +105,7 @@ void ChannelData::setInviteLink(const QString &newInviteLink) {
 
 bool ChannelData::canHaveInviteLink() const {
 	return amCreator()
-		|| (adminRights() & AdminRight::f_invite_users);
+		|| (adminRights() & AdminRight::InviteUsers);
 }
 
 void ChannelData::setLocation(const MTPChannelLocation &data) {
@@ -189,31 +189,26 @@ void ChannelData::setKickedCount(int newKickedCount) {
 	}
 }
 
-MTPChatBannedRights ChannelData::EmptyRestrictedRights(
+ChatRestrictionsInfo ChannelData::KickedRestrictedRights(
 		not_null<PeerData*> participant) {
-	return MTP_chatBannedRights(MTP_flags(0), MTP_int(0));
-}
-
-MTPChatBannedRights ChannelData::KickedRestrictedRights(
-		not_null<PeerData*> participant) {
-	using Flag = MTPDchatBannedRights::Flag;
-	const auto flags = Flag::f_view_messages
-		| Flag::f_send_messages
-		| Flag::f_send_media
-		| Flag::f_embed_links
-		| Flag::f_send_stickers
-		| Flag::f_send_gifs
-		| Flag::f_send_games
-		| Flag::f_send_inline;
-	return MTP_chatBannedRights(
-		MTP_flags(participant->isUser() ? flags : Flag::f_view_messages),
-		MTP_int(std::numeric_limits<int32>::max()));
+	using Flag = ChatRestriction;
+	const auto flags = Flag::ViewMessages
+		| Flag::SendMessages
+		| Flag::SendMedia
+		| Flag::EmbedLinks
+		| Flag::SendStickers
+		| Flag::SendGifs
+		| Flag::SendGames
+		| Flag::SendInline;
+	return ChatRestrictionsInfo(
+		(participant->isUser() ? flags : Flag::ViewMessages),
+		std::numeric_limits<int32>::max());
 }
 
 void ChannelData::applyEditAdmin(
 		not_null<UserData*> user,
-		const MTPChatAdminRights &oldRights,
-		const MTPChatAdminRights &newRights,
+		ChatAdminRightsInfo oldRights,
+		ChatAdminRightsInfo newRights,
 		const QString &rank) {
 	if (mgInfo) {
 		// If rights are empty - still add participant? TODO check
@@ -237,7 +232,7 @@ void ChannelData::applyEditAdmin(
 
 		auto userId = peerToUser(user->id);
 		auto it = mgInfo->lastAdmins.find(user);
-		if (newRights.c_chatAdminRights().vflags().v != 0) {
+		if (newRights.flags) {
 			auto lastAdmin = MegagroupInfo::Admin { newRights };
 			lastAdmin.canEdit = true;
 			if (it == mgInfo->lastAdmins.cend()) {
@@ -257,7 +252,7 @@ void ChannelData::applyEditAdmin(
 			Data::ChannelAdminChanges(this).remove(userId);
 		}
 	}
-	if (oldRights.c_chatAdminRights().vflags().v && !newRights.c_chatAdminRights().vflags().v) {
+	if (oldRights.flags && !newRights.flags) {
 		// We removed an admin.
 		if (adminsCount() > 1) {
 			setAdminsCount(adminsCount() - 1);
@@ -266,7 +261,7 @@ void ChannelData::applyEditAdmin(
 			// Removing bot admin removes it from channel.
 			setMembersCount(membersCount() - 1);
 		}
-	} else if (!oldRights.c_chatAdminRights().vflags().v && newRights.c_chatAdminRights().vflags().v) {
+	} else if (!oldRights.flags && newRights.flags) {
 		// We added an admin.
 		setAdminsCount(adminsCount() + 1);
 		updateFullForced();
@@ -276,13 +271,11 @@ void ChannelData::applyEditAdmin(
 
 void ChannelData::applyEditBanned(
 		not_null<PeerData*> participant,
-		const MTPChatBannedRights &oldRights,
-		const MTPChatBannedRights &newRights) {
+		ChatRestrictionsInfo oldRights,
+		ChatRestrictionsInfo newRights) {
 	auto flags = UpdateFlag::BannedUsers | UpdateFlag::None;
-	auto isKicked = Data::ChatBannedRightsFlags(newRights)
-		& ChatRestriction::f_view_messages;
-	auto isRestricted = !isKicked
-		&& (Data::ChatBannedRightsFlags(newRights) != 0);
+	auto isKicked = newRights.flags & ChatRestriction::ViewMessages;
+	auto isRestricted = !isKicked && newRights.flags;
 	const auto user = participant->asUser();
 	if (mgInfo && user) {
 		// If rights are empty - still remove admin? TODO check
@@ -401,21 +394,21 @@ void ChannelData::setAvailableMinId(MsgId availableMinId) {
 
 bool ChannelData::canBanMembers() const {
 	return amCreator()
-		|| (adminRights() & AdminRight::f_ban_users);
+		|| (adminRights() & AdminRight::BanUsers);
 }
 
 bool ChannelData::canEditMessages() const {
 	return amCreator()
-		|| (adminRights() & AdminRight::f_edit_messages);
+		|| (adminRights() & AdminRight::EditMessages);
 }
 
 bool ChannelData::canDeleteMessages() const {
 	return amCreator()
-		|| (adminRights() & AdminRight::f_delete_messages);
+		|| (adminRights() & AdminRight::DeleteMessages);
 }
 
 bool ChannelData::anyoneCanAddMembers() const {
-	return !(defaultRestrictions() & Restriction::f_invite_users);
+	return !(defaultRestrictions() & Restriction::InviteUsers);
 }
 
 bool ChannelData::hiddenPreHistory() const {
@@ -424,22 +417,22 @@ bool ChannelData::hiddenPreHistory() const {
 
 bool ChannelData::canAddMembers() const {
 	return isMegagroup()
-		? !amRestricted(ChatRestriction::f_invite_users)
-		: ((adminRights() & AdminRight::f_invite_users) || amCreator());
+		? !amRestricted(ChatRestriction::InviteUsers)
+		: ((adminRights() & AdminRight::InviteUsers) || amCreator());
 }
 
 bool ChannelData::canSendPolls() const {
-	return canWrite() && !amRestricted(ChatRestriction::f_send_polls);
+	return canWrite() && !amRestricted(ChatRestriction::SendPolls);
 }
 
 bool ChannelData::canAddAdmins() const {
 	return amCreator()
-		|| (adminRights() & AdminRight::f_add_admins);
+		|| (adminRights() & AdminRight::AddAdmins);
 }
 
 bool ChannelData::canPublish() const {
 	return amCreator()
-		|| (adminRights() & AdminRight::f_post_messages);
+		|| (adminRights() & AdminRight::PostMessages);
 }
 
 bool ChannelData::canWrite() const {
@@ -447,7 +440,7 @@ bool ChannelData::canWrite() const {
 	const auto allowed = amIn() || (flags() & MTPDchannel::Flag::f_has_link);
 	return allowed && (canPublish()
 			|| (!isBroadcast()
-				&& !amRestricted(Restriction::f_send_messages)));
+				&& !amRestricted(Restriction::SendMessages)));
 }
 
 bool ChannelData::canViewMembers() const {
@@ -465,14 +458,14 @@ bool ChannelData::canViewBanned() const {
 
 bool ChannelData::canEditInformation() const {
 	return isMegagroup()
-		? !amRestricted(Restriction::f_change_info)
-		: ((adminRights() & AdminRight::f_change_info) || amCreator());
+		? !amRestricted(Restriction::ChangeInfo)
+		: ((adminRights() & AdminRight::ChangeInfo) || amCreator());
 }
 
 bool ChannelData::canEditPermissions() const {
 	return isMegagroup()
 		&& !isGigagroup()
-		&& ((adminRights() & AdminRight::f_ban_users) || amCreator());
+		&& ((adminRights() & AdminRight::BanUsers) || amCreator());
 }
 
 bool ChannelData::canEditSignatures() const {
@@ -481,7 +474,7 @@ bool ChannelData::canEditSignatures() const {
 
 bool ChannelData::canEditPreHistoryHidden() const {
 	return isMegagroup()
-		&& ((adminRights() & AdminRight::f_ban_users) || amCreator())
+		&& ((adminRights() & AdminRight::BanUsers) || amCreator())
 		&& (!isPublic() || canEditUsername());
 }
 
@@ -521,7 +514,7 @@ bool ChannelData::canEditAdmin(not_null<UserData*> user) const {
 	} else if (!canEditLastAdmin(user)) {
 		return false;
 	}
-	return adminRights() & AdminRight::f_add_admins;
+	return adminRights() & AdminRight::AddAdmins;
 }
 
 bool ChannelData::canRestrictParticipant(
@@ -536,19 +529,20 @@ bool ChannelData::canRestrictParticipant(
 			return false;
 		}
 	}
-	return adminRights() & AdminRight::f_ban_users;
+	return adminRights() & AdminRight::BanUsers;
 }
 
-void ChannelData::setAdminRights(const MTPChatAdminRights &rights) {
-	if (rights.c_chatAdminRights().vflags().v == adminRights()) {
+void ChannelData::setAdminRights(ChatAdminRights rights) {
+	if (rights == adminRights()) {
 		return;
 	}
-	_adminRights.set(rights.c_chatAdminRights().vflags().v);
+	_adminRights.set(rights);
 	if (isMegagroup()) {
 		const auto self = session().user();
 		if (hasAdminRights()) {
 			if (!amCreator()) {
-				auto me = MegagroupInfo::Admin { rights };
+				auto me = MegagroupInfo::Admin{
+					ChatAdminRightsInfo{ rights } };
 				me.canEdit = false;
 				mgInfo->lastAdmins.emplace(self, me);
 			}
@@ -562,15 +556,12 @@ void ChannelData::setAdminRights(const MTPChatAdminRights &rights) {
 		UpdateFlag::Rights | UpdateFlag::Admins | UpdateFlag::BannedUsers);
 }
 
-void ChannelData::setRestrictions(const MTPChatBannedRights &rights) {
-	const auto restrictedFlags = Data::ChatBannedRightsFlags(rights);
-	const auto restrictedUntilDate = Data::ChatBannedRightsUntilDate(rights);
-	if (restrictedFlags == restrictions()
-		&& restrictedUntilDate == _restrictedUntil) {
+void ChannelData::setRestrictions(ChatRestrictionsInfo rights) {
+	if (rights.flags == restrictions() && rights.until == _restrictedUntil) {
 		return;
 	}
-	_restrictedUntil = restrictedUntilDate;
-	_restrictions.set(restrictedFlags);
+	_restrictedUntil = rights.until;
+	_restrictions.set(rights.flags);
 	if (isMegagroup()) {
 		const auto self = session().user();
 		if (hasRestrictions()) {
@@ -589,12 +580,11 @@ void ChannelData::setRestrictions(const MTPChatBannedRights &rights) {
 		UpdateFlag::Rights | UpdateFlag::Admins | UpdateFlag::BannedUsers);
 }
 
-void ChannelData::setDefaultRestrictions(const MTPChatBannedRights &rights) {
-	const auto restrictionFlags = Data::ChatBannedRightsFlags(rights);
-	if (restrictionFlags == defaultRestrictions()) {
+void ChannelData::setDefaultRestrictions(ChatRestrictions rights) {
+	if (rights == defaultRestrictions()) {
 		return;
 	}
-	_defaultRestrictions.set(restrictionFlags);
+	_defaultRestrictions.set(rights);
 	session().changes().peerUpdated(this, UpdateFlag::Rights);
 }
 
@@ -765,7 +755,8 @@ void ApplyChannelUpdate(
 		!= ChannelData::UpdateStatus::Good) {
 		return;
 	}
-	channel->setDefaultRestrictions(update.vdefault_banned_rights());
+	channel->setDefaultRestrictions(Data::ChatBannedRightsFlags(
+		update.vdefault_banned_rights()));
 }
 
 void ApplyChannelUpdate(
diff --git a/Telegram/SourceFiles/data/data_channel.h b/Telegram/SourceFiles/data/data_channel.h
index 469deda18..a5fdf4407 100644
--- a/Telegram/SourceFiles/data/data_channel.h
+++ b/Telegram/SourceFiles/data/data_channel.h
@@ -32,22 +32,22 @@ struct ChannelLocation {
 class MegagroupInfo {
 public:
 	struct Admin {
-		explicit Admin(MTPChatAdminRights rights)
+		explicit Admin(ChatAdminRightsInfo rights)
 		: rights(rights) {
 		}
-		Admin(MTPChatAdminRights rights, bool canEdit)
+		Admin(ChatAdminRightsInfo rights, bool canEdit)
 		: rights(rights)
 		, canEdit(canEdit) {
 		}
-		MTPChatAdminRights rights;
+		ChatAdminRightsInfo rights;
 		bool canEdit = false;
 	};
 
 	struct Restricted {
-		explicit Restricted(MTPChatBannedRights rights)
+		explicit Restricted(ChatRestrictionsInfo rights)
 		: rights(rights) {
 		}
-		MTPChatBannedRights rights;
+		ChatRestrictionsInfo rights;
 	};
 
 	ChatData *getMigrateFromChat() const;
@@ -214,9 +214,7 @@ public:
 		return flags() & MTPDchannel::Flag::f_fake;
 	}
 
-	static MTPChatBannedRights EmptyRestrictedRights(
-		not_null<PeerData*> participant);
-	static MTPChatBannedRights KickedRestrictedRights(
+	[[nodiscard]] static ChatRestrictionsInfo KickedRestrictedRights(
 		not_null<PeerData*> participant);
 	static constexpr auto kRestrictUntilForever = TimeId(INT_MAX);
 	[[nodiscard]] static bool IsRestrictedForever(TimeId until) {
@@ -224,13 +222,13 @@ public:
 	}
 	void applyEditAdmin(
 		not_null<UserData*> user,
-		const MTPChatAdminRights &oldRights,
-		const MTPChatAdminRights &newRights,
+		ChatAdminRightsInfo oldRights,
+		ChatAdminRightsInfo newRights,
 		const QString &rank);
 	void applyEditBanned(
 		not_null<PeerData*> participant,
-		const MTPChatBannedRights &oldRights,
-		const MTPChatBannedRights &newRights);
+		ChatRestrictionsInfo oldRights,
+		ChatRestrictionsInfo newRights);
 
 	void markForbidden();
 
@@ -264,7 +262,7 @@ public:
 	[[nodiscard]] auto adminRightsValue() const {
 		return _adminRights.value();
 	}
-	void setAdminRights(const MTPChatAdminRights &rights);
+	void setAdminRights(ChatAdminRights rights);
 	[[nodiscard]] bool hasAdminRights() const {
 		return (adminRights() != 0);
 	}
@@ -278,7 +276,7 @@ public:
 	[[nodiscard]] TimeId restrictedUntil() const {
 		return _restrictedUntil;
 	}
-	void setRestrictions(const MTPChatBannedRights &rights);
+	void setRestrictions(ChatRestrictionsInfo rights);
 	[[nodiscard]] bool hasRestrictions() const {
 		return (restrictions() != 0);
 	}
@@ -293,7 +291,7 @@ public:
 	[[nodiscard]] auto defaultRestrictionsValue() const {
 		return _defaultRestrictions.value();
 	}
-	void setDefaultRestrictions(const MTPChatBannedRights &rights);
+	void setDefaultRestrictions(ChatRestrictions rights);
 
 	// Like in ChatData.
 	[[nodiscard]] bool canWrite() const;
diff --git a/Telegram/SourceFiles/data/data_chat.cpp b/Telegram/SourceFiles/data/data_chat.cpp
index 82f14af04..6affa384d 100644
--- a/Telegram/SourceFiles/data/data_chat.cpp
+++ b/Telegram/SourceFiles/data/data_chat.cpp
@@ -44,32 +44,32 @@ void ChatData::setPhoto(const MTPChatPhoto &photo) {
 	});
 }
 
-auto ChatData::defaultAdminRights(not_null<UserData*> user) -> AdminRights {
+ChatAdminRightsInfo ChatData::defaultAdminRights(not_null<UserData*> user) {
 	const auto isCreator = (creator == peerToUser(user->id))
 		|| (user->isSelf() && amCreator());
 	using Flag = AdminRight;
-	return Flag::f_other
-		| Flag::f_change_info
-		| Flag::f_delete_messages
-		| Flag::f_ban_users
-		| Flag::f_invite_users
-		| Flag::f_pin_messages
-		| Flag::f_manage_call
-		| (isCreator ? Flag::f_add_admins : Flag(0));
+	return ChatAdminRightsInfo(Flag::Other
+		| Flag::ChangeInfo
+		| Flag::DeleteMessages
+		| Flag::BanUsers
+		| Flag::InviteUsers
+		| Flag::PinMessages
+		| Flag::ManageCall
+		| (isCreator ? Flag::AddAdmins : Flag(0)));
 }
 
 bool ChatData::canWrite() const {
 	// Duplicated in Data::CanWriteValue().
-	return amIn() && !amRestricted(Restriction::f_send_messages);
+	return amIn() && !amRestricted(Restriction::SendMessages);
 }
 
 bool ChatData::canEditInformation() const {
-	return amIn() && !amRestricted(Restriction::f_change_info);
+	return amIn() && !amRestricted(Restriction::ChangeInfo);
 }
 
 bool ChatData::canEditPermissions() const {
 	return amIn()
-		&& (amCreator() || (adminRights() & AdminRight::f_ban_users));
+		&& (amCreator() || (adminRights() & AdminRight::BanUsers));
 }
 
 bool ChatData::canEditUsername() const {
@@ -83,15 +83,15 @@ bool ChatData::canEditPreHistoryHidden() const {
 
 bool ChatData::canDeleteMessages() const {
 	return amCreator()
-		|| (adminRights() & AdminRight::f_delete_messages);
+		|| (adminRights() & AdminRight::DeleteMessages);
 }
 
 bool ChatData::canAddMembers() const {
-	return amIn() && !amRestricted(Restriction::f_invite_users);
+	return amIn() && !amRestricted(Restriction::InviteUsers);
 }
 
 bool ChatData::canSendPolls() const {
-	return amIn() && !amRestricted(Restriction::f_send_polls);
+	return amIn() && !amRestricted(Restriction::SendPolls);
 }
 
 bool ChatData::canAddAdmins() const {
@@ -100,11 +100,11 @@ bool ChatData::canAddAdmins() const {
 
 bool ChatData::canBanMembers() const {
 	return amCreator()
-		|| (adminRights() & AdminRight::f_ban_users);
+		|| (adminRights() & AdminRight::BanUsers);
 }
 
 bool ChatData::anyoneCanAddMembers() const {
-	return !(defaultRestrictions() & Restriction::f_invite_users);
+	return !(defaultRestrictions() & Restriction::InviteUsers);
 }
 
 void ChatData::setName(const QString &newName) {
@@ -123,8 +123,8 @@ void ChatData::applyEditAdmin(not_null<UserData*> user, bool isAdmin) {
 void ChatData::invalidateParticipants() {
 	participants.clear();
 	admins.clear();
-	setAdminRights(MTP_chatAdminRights(MTP_flags(0)));
-	//setDefaultRestrictions(MTP_chatBannedRights(MTP_flags(0), MTP_int(0)));
+	setAdminRights(ChatAdminRights());
+	//setDefaultRestrictions(ChatRestrictions());
 	invitedByMe.clear();
 	botStatus = 0;
 	session().changes().peerUpdated(
@@ -138,25 +138,24 @@ void ChatData::setInviteLink(const QString &newInviteLink) {
 
 bool ChatData::canHaveInviteLink() const {
 	return amCreator()
-		|| (adminRights() & AdminRight::f_invite_users);
+		|| (adminRights() & AdminRight::InviteUsers);
 }
 
-void ChatData::setAdminRights(const MTPChatAdminRights &rights) {
-	if (rights.c_chatAdminRights().vflags().v == adminRights()) {
+void ChatData::setAdminRights(ChatAdminRights rights) {
+	if (rights == adminRights()) {
 		return;
 	}
-	_adminRights.set(rights.c_chatAdminRights().vflags().v);
+	_adminRights.set(rights);
 	session().changes().peerUpdated(
 		this,
 		UpdateFlag::Rights | UpdateFlag::Admins | UpdateFlag::BannedUsers);
 }
 
-void ChatData::setDefaultRestrictions(const MTPChatBannedRights &rights) {
-	const auto restrictionFlags = Data::ChatBannedRightsFlags(rights);
-	if (restrictionFlags == defaultRestrictions()) {
+void ChatData::setDefaultRestrictions(ChatRestrictions rights) {
+	if (rights == defaultRestrictions()) {
 		return;
 	}
-	_defaultRestrictions.set(restrictionFlags);
+	_defaultRestrictions.set(rights);
 	session().changes().peerUpdated(this, UpdateFlag::Rights);
 }
 
@@ -329,7 +328,7 @@ void ApplyChatUpdate(
 		chat->invitedByMe.remove(user);
 		chat->admins.remove(user);
 		if (user->isSelf()) {
-			chat->setAdminRights(MTP_chatAdminRights(MTP_flags(0)));
+			chat->setAdminRights(ChatAdminRights());
 		}
 		if (const auto history = chat->owner().historyLoaded(chat)) {
 			if (history->lastKeyboardFrom == user->id) {
@@ -357,9 +356,9 @@ void ApplyChatUpdate(
 		return;
 	}
 	if (user->isSelf()) {
-		chat->setAdminRights(MTP_chatAdminRights(mtpIsTrue(update.vis_admin())
-			? MTP_flags(chat->defaultAdminRights(user))
-			: MTP_flags(0)));
+		chat->setAdminRights(mtpIsTrue(update.vis_admin())
+			? chat->defaultAdminRights(user).flags
+			: ChatAdminRights());
 	}
 	if (mtpIsTrue(update.vis_admin())) {
 		if (chat->noParticipantInfo()) {
@@ -380,7 +379,8 @@ void ApplyChatUpdate(
 		!= ChatData::UpdateStatus::Good) {
 		return;
 	}
-	chat->setDefaultRestrictions(update.vdefault_banned_rights());
+	chat->setDefaultRestrictions(Data::ChatBannedRightsFlags(
+		update.vdefault_banned_rights()));
 }
 
 void ApplyChatUpdate(not_null<ChatData*> chat, const MTPDchatFull &update) {
@@ -450,7 +450,7 @@ void ApplyChatUpdate(
 		chat->participants.clear();
 		chat->invitedByMe.clear();
 		chat->admins.clear();
-		chat->setAdminRights(MTP_chatAdminRights(MTP_flags(0)));
+		chat->setAdminRights(ChatAdminRights());
 		const auto selfUserId = session->userId();
 		for (const auto &participant : list) {
 			const auto userId = participant.match([&](const auto &data) {
@@ -479,8 +479,8 @@ void ApplyChatUpdate(
 			}, [&](const MTPDchatParticipantAdmin &data) {
 				chat->admins.emplace(user);
 				if (user->isSelf()) {
-					chat->setAdminRights(MTP_chatAdminRights(
-						MTP_flags(chat->defaultAdminRights(user))));
+					chat->setAdminRights(
+						chat->defaultAdminRights(user).flags);
 				}
 			}, [](const MTPDchatParticipant &) {
 			});
diff --git a/Telegram/SourceFiles/data/data_chat.h b/Telegram/SourceFiles/data/data_chat.h
index f84988805..33e5dc077 100644
--- a/Telegram/SourceFiles/data/data_chat.h
+++ b/Telegram/SourceFiles/data/data_chat.h
@@ -85,7 +85,7 @@ public:
 	[[nodiscard]] auto adminRightsValue() const {
 		return _adminRights.value();
 	}
-	void setAdminRights(const MTPChatAdminRights &rights);
+	void setAdminRights(ChatAdminRights rights);
 	[[nodiscard]] bool hasAdminRights() const {
 		return (adminRights() != 0);
 	}
@@ -96,7 +96,7 @@ public:
 	[[nodiscard]] auto defaultRestrictionsValue() const {
 		return _defaultRestrictions.value();
 	}
-	void setDefaultRestrictions(const MTPChatBannedRights &rights);
+	void setDefaultRestrictions(ChatRestrictions rights);
 
 	[[nodiscard]] bool isForbidden() const {
 		return flags() & MTPDchat_ClientFlag::f_forbidden;
@@ -123,7 +123,8 @@ public:
 		return flags() & MTPDchat::Flag::f_migrated_to;
 	}
 
-	[[nodiscard]] AdminRights defaultAdminRights(not_null<UserData*> user);
+	[[nodiscard]] ChatAdminRightsInfo defaultAdminRights(
+		not_null<UserData*> user);
 
 	// Like in ChannelData.
 	[[nodiscard]] bool canWrite() const;
diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp
index 6382e20ef..8b8201879 100644
--- a/Telegram/SourceFiles/data/data_media_types.cpp
+++ b/Telegram/SourceFiles/data/data_media_types.cpp
@@ -360,7 +360,7 @@ bool MediaPhoto::allowsEditMedia() const {
 QString MediaPhoto::errorTextForForward(not_null<PeerData*> peer) const {
 	return Data::RestrictionError(
 		peer,
-		ChatRestriction::f_send_media
+		ChatRestriction::SendMedia
 	).value_or(QString());
 }
 
@@ -629,26 +629,26 @@ QString MediaFile::errorTextForForward(not_null<PeerData*> peer) const {
 	if (const auto sticker = _document->sticker()) {
 		if (const auto error = Data::RestrictionError(
 				peer,
-				ChatRestriction::f_send_stickers)) {
+				ChatRestriction::SendStickers)) {
 			return *error;
 		}
 	} else if (_document->isAnimation()) {
 		if (_document->isVideoMessage()) {
 			if (const auto error = Data::RestrictionError(
 					peer,
-					ChatRestriction::f_send_media)) {
+					ChatRestriction::SendMedia)) {
 				return *error;
 			}
 		} else {
 			if (const auto error = Data::RestrictionError(
 					peer,
-					ChatRestriction::f_send_gifs)) {
+					ChatRestriction::SendGifs)) {
 				return *error;
 			}
 		}
 	} else if (const auto error = Data::RestrictionError(
 			peer,
-			ChatRestriction::f_send_media)) {
+			ChatRestriction::SendMedia)) {
 		return *error;
 	}
 	return QString();
@@ -1135,7 +1135,7 @@ TextForMimeData MediaGame::clipboardText() const {
 QString MediaGame::errorTextForForward(not_null<PeerData*> peer) const {
 	return Data::RestrictionError(
 		peer,
-		ChatRestriction::f_send_games
+		ChatRestriction::SendGames
 	).value_or(QString());
 }
 
@@ -1289,7 +1289,7 @@ QString MediaPoll::errorTextForForward(not_null<PeerData*> peer) const {
 	}
 	return Data::RestrictionError(
 		peer,
-		ChatRestriction::f_send_polls
+		ChatRestriction::SendPolls
 	).value_or(QString());
 }
 
diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp
index 3fb9fdaa6..1f757e25b 100644
--- a/Telegram/SourceFiles/data/data_peer.cpp
+++ b/Telegram/SourceFiles/data/data_peer.cpp
@@ -501,11 +501,11 @@ bool PeerData::canPinMessages() const {
 		return user->fullFlags() & MTPDuserFull::Flag::f_can_pin_message;
 	} else if (const auto chat = asChat()) {
 		return chat->amIn()
-			&& !chat->amRestricted(ChatRestriction::f_pin_messages);
+			&& !chat->amRestricted(ChatRestriction::PinMessages);
 	} else if (const auto channel = asChannel()) {
 		return channel->isMegagroup()
-			? !channel->amRestricted(ChatRestriction::f_pin_messages)
-			: ((channel->adminRights() & ChatAdminRight::f_edit_messages)
+			? !channel->amRestricted(ChatRestriction::PinMessages)
+			: ((channel->adminRights() & ChatAdminRight::EditMessages)
 				|| channel->amCreator());
 	}
 	Unexpected("Peer type in PeerData::canPinMessages.");
@@ -851,12 +851,12 @@ Data::RestrictionCheckResult PeerData::amRestricted(
 		ChatRestriction right) const {
 	using Result = Data::RestrictionCheckResult;
 	const auto allowByAdminRights = [](auto right, auto chat) -> bool {
-		if (right == ChatRestriction::f_invite_users) {
-			return chat->adminRights() & ChatAdminRight::f_invite_users;
-		} else if (right == ChatRestriction::f_change_info) {
-			return chat->adminRights() & ChatAdminRight::f_change_info;
-		} else if (right == ChatRestriction::f_pin_messages) {
-			return chat->adminRights() & ChatAdminRight::f_pin_messages;
+		if (right == ChatRestriction::InviteUsers) {
+			return chat->adminRights() & ChatAdminRight::InviteUsers;
+		} else if (right == ChatRestriction::ChangeInfo) {
+			return chat->adminRights() & ChatAdminRight::ChangeInfo;
+		} else if (right == ChatRestriction::PinMessages) {
+			return chat->adminRights() & ChatAdminRight::PinMessages;
 		} else {
 			return chat->hasAdminRights();
 		}
@@ -864,7 +864,7 @@ Data::RestrictionCheckResult PeerData::amRestricted(
 	if (const auto channel = asChannel()) {
 		const auto defaultRestrictions = channel->defaultRestrictions()
 			| (channel->isPublic()
-				? (ChatRestriction::f_pin_messages | ChatRestriction::f_change_info)
+				? (ChatRestriction::PinMessages | ChatRestriction::ChangeInfo)
 				: ChatRestrictions(0));
 		return (channel->amCreator() || allowByAdminRights(right, channel))
 			? Result::Allowed()
@@ -886,7 +886,7 @@ Data::RestrictionCheckResult PeerData::amRestricted(
 bool PeerData::amAnonymous() const {
 	return isBroadcast()
 		|| (isChannel()
-			&& (asChannel()->adminRights() & ChatAdminRight::f_anonymous));
+			&& (asChannel()->adminRights() & ChatAdminRight::Anonymous));
 }
 
 bool PeerData::canRevokeFullHistory() const {
@@ -967,10 +967,10 @@ bool PeerData::canSendPolls() const {
 bool PeerData::canManageGroupCall() const {
 	if (const auto chat = asChat()) {
 		return chat->amCreator()
-			|| (chat->adminRights() & ChatAdminRight::f_manage_call);
+			|| (chat->adminRights() & ChatAdminRight::ManageCall);
 	} else if (const auto group = asChannel()) {
 		return group->amCreator()
-			|| (group->adminRights() & ChatAdminRight::f_manage_call);
+			|| (group->adminRights() & ChatAdminRight::ManageCall);
 	}
 	return false;
 }
@@ -1034,17 +1034,17 @@ std::vector<ChatRestrictions> ListOfRestrictions() {
 	using Flag = ChatRestriction;
 
 	return {
-		Flag::f_send_messages,
-		Flag::f_send_media,
-		Flag::f_send_stickers
-		| Flag::f_send_gifs
-		| Flag::f_send_games
-		| Flag::f_send_inline,
-		Flag::f_embed_links,
-		Flag::f_send_polls,
-		Flag::f_invite_users,
-		Flag::f_pin_messages,
-		Flag::f_change_info,
+		Flag::SendMessages,
+		Flag::SendMedia,
+		Flag::SendStickers
+		| Flag::SendGifs
+		| Flag::SendGames
+		| Flag::SendInline,
+		Flag::EmbedLinks,
+		Flag::SendPolls,
+		Flag::InviteUsers,
+		Flag::PinMessages,
+		Flag::ChangeInfo,
 	};
 }
 
@@ -1063,23 +1063,23 @@ std::optional<QString> RestrictionError(
 				auto time = restrictedUntilDateTime.toString(cTimeFormat());
 
 				switch (restriction) {
-				case Flag::f_send_polls:
+				case Flag::SendPolls:
 					return tr::lng_restricted_send_polls_until(
 						tr::now, lt_date, date, lt_time, time);
-				case Flag::f_send_messages:
+				case Flag::SendMessages:
 					return tr::lng_restricted_send_message_until(
 						tr::now, lt_date, date, lt_time, time);
-				case Flag::f_send_media:
+				case Flag::SendMedia:
 					return tr::lng_restricted_send_media_until(
 						tr::now, lt_date, date, lt_time, time);
-				case Flag::f_send_stickers:
+				case Flag::SendStickers:
 					return tr::lng_restricted_send_stickers_until(
 						tr::now, lt_date, date, lt_time, time);
-				case Flag::f_send_gifs:
+				case Flag::SendGifs:
 					return tr::lng_restricted_send_gifs_until(
 						tr::now, lt_date, date, lt_time, time);
-				case Flag::f_send_inline:
-				case Flag::f_send_games:
+				case Flag::SendInline:
+				case Flag::SendGames:
 					return tr::lng_restricted_send_inline_until(
 						tr::now, lt_date, date, lt_time, time);
 				}
@@ -1087,28 +1087,28 @@ std::optional<QString> RestrictionError(
 			}
 		}
 		switch (restriction) {
-		case Flag::f_send_polls:
+		case Flag::SendPolls:
 			return all
 				? tr::lng_restricted_send_polls_all(tr::now)
 				: tr::lng_restricted_send_polls(tr::now);
-		case Flag::f_send_messages:
+		case Flag::SendMessages:
 			return all
 				? tr::lng_restricted_send_message_all(tr::now)
 				: tr::lng_restricted_send_message(tr::now);
-		case Flag::f_send_media:
+		case Flag::SendMedia:
 			return all
 				? tr::lng_restricted_send_media_all(tr::now)
 				: tr::lng_restricted_send_media(tr::now);
-		case Flag::f_send_stickers:
+		case Flag::SendStickers:
 			return all
 				? tr::lng_restricted_send_stickers_all(tr::now)
 				: tr::lng_restricted_send_stickers(tr::now);
-		case Flag::f_send_gifs:
+		case Flag::SendGifs:
 			return all
 				? tr::lng_restricted_send_gifs_all(tr::now)
 				: tr::lng_restricted_send_gifs(tr::now);
-		case Flag::f_send_inline:
-		case Flag::f_send_games:
+		case Flag::SendInline:
+		case Flag::SendGames:
 			return all
 				? tr::lng_restricted_send_inline_all(tr::now)
 				: tr::lng_restricted_send_inline(tr::now);
@@ -1236,9 +1236,15 @@ std::optional<int> ResolvePinnedCount(
 		: std::nullopt;
 }
 
+ChatAdminRights ChatAdminRightsFlags(const MTPChatAdminRights &rights) {
+	return rights.match([](const MTPDchatAdminRights &data) {
+		return ChatAdminRights::from_raw(int32(data.vflags().v));
+	});
+}
+
 ChatRestrictions ChatBannedRightsFlags(const MTPChatBannedRights &rights) {
 	return rights.match([](const MTPDchatBannedRights &data) {
-		return data.vflags().v;
+		return ChatRestrictions::from_raw(int32(data.vflags().v));
 	});
 }
 
diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h
index bfa9df284..30a2299cf 100644
--- a/Telegram/SourceFiles/data/data_peer.h
+++ b/Telegram/SourceFiles/data/data_peer.h
@@ -17,10 +17,75 @@ class UserData;
 class ChatData;
 class ChannelData;
 
-using ChatAdminRight = MTPDchatAdminRights::Flag;
-using ChatRestriction = MTPDchatBannedRights::Flag;
-using ChatAdminRights = MTPDchatAdminRights::Flags;
-using ChatRestrictions = MTPDchatBannedRights::Flags;
+enum class ChatAdminRight {
+	ChangeInfo = (1 << 0),
+	PostMessages = (1 << 1),
+	EditMessages = (1 << 2),
+	DeleteMessages = (1 << 3),
+	BanUsers = (1 << 4),
+	InviteUsers = (1 << 5),
+	PinMessages = (1 << 7),
+	AddAdmins = (1 << 9),
+	Anonymous = (1 << 10),
+	ManageCall = (1 << 11),
+	Other = (1 << 12),
+};
+inline constexpr bool is_flag_type(ChatAdminRight) { return true; }
+using ChatAdminRights = base::flags<ChatAdminRight>;
+
+enum class ChatRestriction {
+	ViewMessages = (1 << 0),
+	SendMessages = (1 << 1),
+	SendMedia = (1 << 2),
+	SendStickers = (1 << 3),
+	SendGifs = (1 << 4),
+	SendGames = (1 << 5),
+	SendInline = (1 << 6),
+	EmbedLinks = (1 << 7),
+	SendPolls = (1 << 8),
+	ChangeInfo = (1 << 10),
+	InviteUsers = (1 << 15),
+	PinMessages = (1 << 17),
+};
+inline constexpr bool is_flag_type(ChatRestriction) { return true; }
+using ChatRestrictions = base::flags<ChatRestriction>;
+
+namespace Data {
+
+[[nodiscard]] ChatAdminRights ChatAdminRightsFlags(
+	const MTPChatAdminRights &rights);
+[[nodiscard]] ChatRestrictions ChatBannedRightsFlags(
+	const MTPChatBannedRights &rights);
+[[nodiscard]] TimeId ChatBannedRightsUntilDate(
+	const MTPChatBannedRights &rights);
+
+} // namespace Data
+
+struct ChatAdminRightsInfo {
+	ChatAdminRightsInfo() = default;
+	explicit ChatAdminRightsInfo(ChatAdminRights flags) : flags(flags) {
+	}
+	explicit ChatAdminRightsInfo(const MTPChatAdminRights &rights)
+	: flags(Data::ChatAdminRightsFlags(rights)) {
+	}
+
+	ChatAdminRights flags;
+};
+
+struct ChatRestrictionsInfo {
+	ChatRestrictionsInfo() = default;
+	ChatRestrictionsInfo(ChatRestrictions flags, TimeId until)
+	: flags(flags)
+	, until(until) {
+	}
+	explicit ChatRestrictionsInfo(const MTPChatBannedRights &rights)
+	: flags(Data::ChatBannedRightsFlags(rights))
+	, until(Data::ChatBannedRightsUntilDate(rights)) {
+	}
+
+	ChatRestrictions flags;
+	TimeId until = 0;
+};
 
 struct BotCommand {
 	QString command;
@@ -100,11 +165,6 @@ struct UnavailableReason {
 	}
 };
 
-[[nodiscard]] ChatRestrictions ChatBannedRightsFlags(
-	const MTPChatBannedRights &rights);
-[[nodiscard]] TimeId ChatBannedRightsUntilDate(
-	const MTPChatBannedRights &rights);
-
 bool UpdateBotCommands(
 	std::vector<BotCommand> &commands,
 	const MTPVector<MTPBotCommand> &data);
diff --git a/Telegram/SourceFiles/data/data_peer_values.cpp b/Telegram/SourceFiles/data/data_peer_values.cpp
index 74086aeed..227a236c1 100644
--- a/Telegram/SourceFiles/data/data_peer_values.cpp
+++ b/Telegram/SourceFiles/data/data_peer_values.cpp
@@ -83,13 +83,13 @@ inline auto AdminRightsValue(not_null<ChannelData*> channel) {
 
 inline auto AdminRightsValue(
 		not_null<ChannelData*> channel,
-		MTPDchatAdminRights::Flags mask) {
+		ChatAdminRights mask) {
 	return FlagsValueWithMask(AdminRightsValue(channel), mask);
 }
 
 inline auto AdminRightValue(
 		not_null<ChannelData*> channel,
-		MTPDchatAdminRights::Flag flag) {
+		ChatAdminRight flag) {
 	return SingleFlagValue(AdminRightsValue(channel), flag);
 }
 
@@ -99,13 +99,13 @@ inline auto AdminRightsValue(not_null<ChatData*> chat) {
 
 inline auto AdminRightsValue(
 		not_null<ChatData*> chat,
-		MTPDchatAdminRights::Flags mask) {
+		ChatAdminRights mask) {
 	return FlagsValueWithMask(AdminRightsValue(chat), mask);
 }
 
 inline auto AdminRightValue(
 		not_null<ChatData*> chat,
-		MTPDchatAdminRights::Flag flag) {
+		ChatAdminRight flag) {
 	return SingleFlagValue(AdminRightsValue(chat), flag);
 }
 
@@ -115,13 +115,13 @@ inline auto RestrictionsValue(not_null<ChannelData*> channel) {
 
 inline auto RestrictionsValue(
 		not_null<ChannelData*> channel,
-		MTPDchatBannedRights::Flags mask) {
+		ChatRestrictions mask) {
 	return FlagsValueWithMask(RestrictionsValue(channel), mask);
 }
 
 inline auto RestrictionValue(
 		not_null<ChannelData*> channel,
-		MTPDchatBannedRights::Flag flag) {
+		ChatRestriction flag) {
 	return SingleFlagValue(RestrictionsValue(channel), flag);
 }
 
@@ -131,13 +131,13 @@ inline auto DefaultRestrictionsValue(not_null<ChannelData*> channel) {
 
 inline auto DefaultRestrictionsValue(
 		not_null<ChannelData*> channel,
-		MTPDchatBannedRights::Flags mask) {
+		ChatRestrictions mask) {
 	return FlagsValueWithMask(DefaultRestrictionsValue(channel), mask);
 }
 
 inline auto DefaultRestrictionValue(
 		not_null<ChannelData*> channel,
-		MTPDchatBannedRights::Flag flag) {
+		ChatRestriction flag) {
 	return SingleFlagValue(DefaultRestrictionsValue(channel), flag);
 }
 
@@ -147,13 +147,13 @@ inline auto DefaultRestrictionsValue(not_null<ChatData*> chat) {
 
 inline auto DefaultRestrictionsValue(
 		not_null<ChatData*> chat,
-		MTPDchatBannedRights::Flags mask) {
+		ChatRestrictions mask) {
 	return FlagsValueWithMask(DefaultRestrictionsValue(chat), mask);
 }
 
 inline auto DefaultRestrictionValue(
 		not_null<ChatData*> chat,
-		MTPDchatBannedRights::Flag flag) {
+		ChatRestriction flag) {
 	return SingleFlagValue(DefaultRestrictionsValue(chat), flag);
 }
 
@@ -192,7 +192,7 @@ rpl::producer<bool> CanWriteValue(ChatData *chat) {
 		AdminRightsValue(chat),
 		DefaultRestrictionValue(
 			chat,
-			MTPDchatBannedRights::Flag::f_send_messages),
+			ChatRestriction::SendMessages),
 		[](
 				MTPDchat::Flags flags,
 				Data::Flags<ChatAdminRights>::Change adminRights,
@@ -204,7 +204,7 @@ rpl::producer<bool> CanWriteValue(ChatData *chat) {
 				| MTPDchat::Flag::f_kicked;
 			return !(flags & amOutFlags)
 				&& ((flags & MTPDchat::Flag::f_creator)
-					|| (adminRights.value != MTPDchatAdminRights::Flags(0))
+					|| (adminRights.value != ChatAdminRights(0))
 					|| !defaultSendMessagesRestriction);
 		});
 }
@@ -220,13 +220,13 @@ rpl::producer<bool> CanWriteValue(ChannelData *channel) {
 		PeerFlagsValue(channel, mask),
 		AdminRightValue(
 			channel,
-			MTPDchatAdminRights::Flag::f_post_messages),
+			ChatAdminRight::PostMessages),
 		RestrictionValue(
 			channel,
-			MTPDchatBannedRights::Flag::f_send_messages),
+			ChatRestriction::SendMessages),
 		DefaultRestrictionValue(
 			channel,
-			MTPDchatBannedRights::Flag::f_send_messages),
+			ChatRestriction::SendMessages),
 		[](
 				MTPDchannel::Flags flags,
 				bool postMessagesRight,
@@ -273,8 +273,8 @@ rpl::producer<bool> CanPinMessagesValue(not_null<PeerData*> peer) {
 			| MTPDchat::Flag::f_kicked;
 		return rpl::combine(
 			PeerFlagsValue(chat, mask),
-			AdminRightValue(chat, ChatAdminRight::f_pin_messages),
-			DefaultRestrictionValue(chat, ChatRestriction::f_pin_messages),
+			AdminRightValue(chat, ChatAdminRight::PinMessages),
+			DefaultRestrictionValue(chat, ChatRestriction::PinMessages),
 			[](
 				MTPDchat::Flags flags,
 				bool adminRightAllows,
@@ -294,8 +294,8 @@ rpl::producer<bool> CanPinMessagesValue(not_null<PeerData*> peer) {
 			return rpl::single(true);
 		}
 		return rpl::combine(
-			AdminRightValue(megagroup, ChatAdminRight::f_pin_messages),
-			DefaultRestrictionValue(megagroup, ChatRestriction::f_pin_messages),
+			AdminRightValue(megagroup, ChatAdminRight::PinMessages),
+			DefaultRestrictionValue(megagroup, ChatRestriction::PinMessages),
 			PeerFlagValue(megagroup, MTPDchannel::Flag::f_username),
 			PeerFullFlagValue(megagroup, MTPDchannelFull::Flag::f_location),
 			megagroup->restrictionsValue()
@@ -309,19 +309,19 @@ rpl::producer<bool> CanPinMessagesValue(not_null<PeerData*> peer) {
 				|| (!hasUsername
 					&& !hasLocation
 					&& !defaultRestriction
-					&& !(restrictions.value & ChatRestriction::f_pin_messages));
+					&& !(restrictions.value & ChatRestriction::PinMessages));
 		});
 	} else if (const auto channel = peer->asChannel()) {
 		if (channel->amCreator()) {
 			return rpl::single(true);
 		}
-		return AdminRightValue(channel, ChatAdminRight::f_edit_messages);
+		return AdminRightValue(channel, ChatAdminRight::EditMessages);
 	}
 	Unexpected("Peer type in CanPinMessagesValue.");
 }
 
 rpl::producer<bool> CanManageGroupCallValue(not_null<PeerData*> peer) {
-	const auto flag = MTPDchatAdminRights::Flag::f_manage_call;
+	const auto flag = ChatAdminRight::ManageCall;
 	if (const auto chat = peer->asChat()) {
 		return chat->amCreator()
 			? (rpl::single(true) | rpl::type_erased())
diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp
index fca539d24..c7ca2310a 100644
--- a/Telegram/SourceFiles/data/data_session.cpp
+++ b/Telegram/SourceFiles/data/data_session.cpp
@@ -590,15 +590,14 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
 		chat->date = data.vdate().v;
 
 		if (const auto rights = data.vadmin_rights()) {
-			chat->setAdminRights(*rights);
+			chat->setAdminRights(ChatAdminRightsInfo(*rights).flags);
 		} else {
-			chat->setAdminRights(MTP_chatAdminRights(MTP_flags(0)));
+			chat->setAdminRights(ChatAdminRights());
 		}
 		if (const auto rights = data.vdefault_banned_rights()) {
-			chat->setDefaultRestrictions(*rights);
+			chat->setDefaultRestrictions(ChatRestrictionsInfo(*rights).flags);
 		} else {
-			chat->setDefaultRestrictions(
-				MTP_chatBannedRights(MTP_flags(0), MTP_int(0)));
+			chat->setDefaultRestrictions(ChatRestrictions());
 		}
 
 		if (const auto migratedTo = data.vmigrated_to()) {
@@ -639,9 +638,8 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
 		chat->count = -1;
 		chat->invalidateParticipants();
 		chat->setFlags(MTPDchat_ClientFlag::f_forbidden | 0);
-		chat->setAdminRights(MTP_chatAdminRights(MTP_flags(0)));
-		chat->setDefaultRestrictions(
-			MTP_chatBannedRights(MTP_flags(0), MTP_int(0)));
+		chat->setAdminRights(ChatAdminRights());
+		chat->setDefaultRestrictions(ChatRestrictions());
 
 		if (canAddMembers != chat->canAddMembers()) {
 			flags |= UpdateFlag::Rights;
@@ -663,10 +661,9 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
 			channel->setMembersCount(count->v);
 		}
 		if (const auto rights = data.vdefault_banned_rights()) {
-			channel->setDefaultRestrictions(*rights);
+			channel->setDefaultRestrictions(ChatRestrictionsInfo(*rights).flags);
 		} else {
-			channel->setDefaultRestrictions(
-				MTP_chatBannedRights(MTP_flags(0), MTP_int(0)));
+			channel->setDefaultRestrictions(ChatRestrictions());
 		}
 		const auto callFlag = MTPDchannel::Flag::f_call_not_empty;
 		const auto callNotEmpty = (data.vflags().v & callFlag)
@@ -689,15 +686,14 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
 			}
 		} else {
 			if (const auto rights = data.vadmin_rights()) {
-				channel->setAdminRights(*rights);
+				channel->setAdminRights(ChatAdminRightsInfo(*rights).flags);
 			} else if (channel->hasAdminRights()) {
-				channel->setAdminRights(MTP_chatAdminRights(MTP_flags(0)));
+				channel->setAdminRights(ChatAdminRights());
 			}
 			if (const auto rights = data.vbanned_rights()) {
-				channel->setRestrictions(*rights);
+				channel->setRestrictions(ChatRestrictionsInfo(*rights));
 			} else if (channel->hasRestrictions()) {
-				channel->setRestrictions(
-					MTP_chatBannedRights(MTP_flags(0), MTP_int(0)));
+				channel->setRestrictions(ChatRestrictionsInfo());
 			}
 			channel->setAccessHash(
 				data.vaccess_hash().value_or(channel->access));
@@ -741,10 +737,10 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
 		channel->setFlags((channel->flags() & ~mask) | (mtpCastFlags(data.vflags()) & mask) | MTPDchannel_ClientFlag::f_forbidden);
 
 		if (channel->hasAdminRights()) {
-			channel->setAdminRights(MTP_chatAdminRights(MTP_flags(0)));
+			channel->setAdminRights(ChatAdminRights());
 		}
 		if (channel->hasRestrictions()) {
-			channel->setRestrictions(MTP_chatBannedRights(MTP_flags(0), MTP_int(0)));
+			channel->setRestrictions(ChatRestrictionsInfo());
 		}
 
 		channel->setName(qs(data.vtitle()), QString());
diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp
index 635f17c26..046c4a144 100644
--- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp
+++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp
@@ -1335,13 +1335,13 @@ void InnerWidget::suggestRestrictUser(not_null<UserData*> user) {
 		}
 	}
 	_menu->addAction(tr::lng_context_restrict_user(tr::now), [=] {
-		auto editRestrictions = [=](bool hasAdminRights, const MTPChatBannedRights &currentRights) {
+		auto editRestrictions = [=](bool hasAdminRights, ChatRestrictionsInfo currentRights) {
 			auto weak = QPointer<InnerWidget>(this);
 			auto weakBox = std::make_shared<QPointer<EditRestrictedBox>>();
 			auto box = Box<EditRestrictedBox>(_channel, user, hasAdminRights, currentRights);
 			box->setSaveCallback([=](
-					const MTPChatBannedRights &oldRights,
-					const MTPChatBannedRights &newRights) {
+					ChatRestrictionsInfo oldRights,
+					ChatRestrictionsInfo newRights) {
 				if (weak) {
 					weak->restrictUser(user, oldRights, newRights);
 				}
@@ -1355,7 +1355,7 @@ void InnerWidget::suggestRestrictUser(not_null<UserData*> user) {
 				Ui::LayerOption::KeepOther);
 		};
 		if (base::contains(_admins, user)) {
-			editRestrictions(true, ChannelData::EmptyRestrictedRights(user));
+			editRestrictions(true, ChatRestrictionsInfo());
 		} else {
 			_api.request(MTPchannels_GetParticipant(
 				_channel->inputChannel,
@@ -1368,16 +1368,16 @@ void InnerWidget::suggestRestrictUser(not_null<UserData*> user) {
 				auto type = participant.vparticipant().type();
 				if (type == mtpc_channelParticipantBanned) {
 					auto &banned = participant.vparticipant().c_channelParticipantBanned();
-					editRestrictions(false, banned.vbanned_rights());
+					editRestrictions(
+						false,
+						ChatRestrictionsInfo(banned.vbanned_rights()));
 				} else {
 					auto hasAdminRights = (type == mtpc_channelParticipantAdmin)
 						|| (type == mtpc_channelParticipantCreator);
-					auto bannedRights = ChannelData::EmptyRestrictedRights(user);
-					editRestrictions(hasAdminRights, bannedRights);
+					editRestrictions(hasAdminRights, ChatRestrictionsInfo());
 				}
 			}).fail([=](const MTP::Error &error) {
-				auto bannedRights = ChannelData::EmptyRestrictedRights(user);
-				editRestrictions(false, bannedRights);
+				editRestrictions(false, ChatRestrictionsInfo());
 			}).send();
 		}
 	});
@@ -1385,9 +1385,9 @@ void InnerWidget::suggestRestrictUser(not_null<UserData*> user) {
 
 void InnerWidget::restrictUser(
 		not_null<UserData*> user,
-		const MTPChatBannedRights &oldRights,
-		const MTPChatBannedRights &newRights) {
-	const auto done = [=](const MTPChatBannedRights &newRights) {
+		ChatRestrictionsInfo oldRights,
+		ChatRestrictionsInfo newRights) {
+	const auto done = [=](ChatRestrictionsInfo newRights) {
 		restrictUserDone(user, newRights);
 	};
 	const auto callback = SaveRestrictedCallback(
@@ -1398,10 +1398,16 @@ void InnerWidget::restrictUser(
 	callback(oldRights, newRights);
 }
 
-void InnerWidget::restrictUserDone(not_null<UserData*> user, const MTPChatBannedRights &rights) {
-	if (Data::ChatBannedRightsFlags(rights)) {
-		_admins.erase(std::remove(_admins.begin(), _admins.end(), user), _admins.end());
-		_adminsCanEdit.erase(std::remove(_adminsCanEdit.begin(), _adminsCanEdit.end(), user), _adminsCanEdit.end());
+void InnerWidget::restrictUserDone(
+		not_null<UserData*> user,
+		ChatRestrictionsInfo rights) {
+	if (rights.flags) {
+		_admins.erase(
+			std::remove(_admins.begin(), _admins.end(), user),
+			_admins.end());
+		_adminsCanEdit.erase(
+			std::remove(_adminsCanEdit.begin(), _adminsCanEdit.end(), user),
+			_adminsCanEdit.end());
 	}
 	_downLoaded = false;
 	checkPreloadMore();
diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h
index c10296a00..af0698c25 100644
--- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h
+++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h
@@ -16,6 +16,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "mtproto/sender.h"
 #include "base/timer.h"
 
+struct ChatRestrictionsInfo;
+
 namespace Data {
 class CloudImageView;
 } // namespace Data
@@ -196,8 +198,8 @@ private:
 	void copySelectedText();
 	TextForMimeData getSelectedText() const;
 	void suggestRestrictUser(not_null<UserData*> user);
-	void restrictUser(not_null<UserData*> user, const MTPChatBannedRights &oldRights, const MTPChatBannedRights &newRights);
-	void restrictUserDone(not_null<UserData*> user, const MTPChatBannedRights &rights);
+	void restrictUser(not_null<UserData*> user, ChatRestrictionsInfo oldRights, ChatRestrictionsInfo newRights);
+	void restrictUserDone(not_null<UserData*> user, ChatRestrictionsInfo rights);
 
 	void requestAdmins();
 	void checkPreloadMore();
diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp
index b0b878b4b..450186842 100644
--- a/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp
+++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp
@@ -158,16 +158,11 @@ const auto CollectChanges = [](auto &phraseMap, auto plusFlags, auto minusFlags)
 TextWithEntities GenerateAdminChangeText(
 		not_null<ChannelData*> channel,
 		const TextWithEntities &user,
-		const MTPChatAdminRights *newRights,
-		const MTPChatAdminRights *prevRights) {
-	Expects(!newRights || newRights->type() == mtpc_chatAdminRights);
-	Expects(!prevRights || prevRights->type() == mtpc_chatAdminRights);
+		ChatAdminRightsInfo newRights,
+		ChatAdminRightsInfo prevRights) {
+	using Flag = ChatAdminRight;
+	using Flags = ChatAdminRights;
 
-	using Flag = MTPDchatAdminRights::Flag;
-	using Flags = MTPDchatAdminRights::Flags;
-
-	auto newFlags = newRights ? newRights->c_chatAdminRights().vflags().v : MTPDchatAdminRights::Flags(0);
-	auto prevFlags = prevRights ? prevRights->c_chatAdminRights().vflags().v : MTPDchatAdminRights::Flags(0);
 	auto result = tr::lng_admin_log_promoted(tr::now, lt_user, user, Ui::Text::WithEntities);
 
 	auto useInviteLinkPhrase = channel->isMegagroup() && channel->anyoneCanAddMembers();
@@ -175,25 +170,25 @@ TextWithEntities GenerateAdminChangeText(
 		? tr::lng_admin_log_admin_invite_link
 		: tr::lng_admin_log_admin_invite_users;
 	static auto phraseMap = std::map<Flags, tr::phrase<>> {
-		{ Flag::f_change_info, tr::lng_admin_log_admin_change_info },
-		{ Flag::f_post_messages, tr::lng_admin_log_admin_post_messages },
-		{ Flag::f_edit_messages, tr::lng_admin_log_admin_edit_messages },
-		{ Flag::f_delete_messages, tr::lng_admin_log_admin_delete_messages },
-		{ Flag::f_ban_users, tr::lng_admin_log_admin_ban_users },
-		{ Flag::f_invite_users, invitePhrase },
-		{ Flag::f_pin_messages, tr::lng_admin_log_admin_pin_messages },
-		{ Flag::f_manage_call, tr::lng_admin_log_admin_manage_calls },
-		{ Flag::f_add_admins, tr::lng_admin_log_admin_add_admins },
+		{ Flag::ChangeInfo, tr::lng_admin_log_admin_change_info },
+		{ Flag::PostMessages, tr::lng_admin_log_admin_post_messages },
+		{ Flag::EditMessages, tr::lng_admin_log_admin_edit_messages },
+		{ Flag::DeleteMessages, tr::lng_admin_log_admin_delete_messages },
+		{ Flag::BanUsers, tr::lng_admin_log_admin_ban_users },
+		{ Flag::InviteUsers, invitePhrase },
+		{ Flag::PinMessages, tr::lng_admin_log_admin_pin_messages },
+		{ Flag::ManageCall, tr::lng_admin_log_admin_manage_calls },
+		{ Flag::AddAdmins, tr::lng_admin_log_admin_add_admins },
 	};
-	phraseMap[Flag::f_invite_users] = invitePhrase;
+	phraseMap[Flag::InviteUsers] = invitePhrase;
 
 	if (!channel->isMegagroup()) {
 		// Don't display "Ban users" changes in channels.
-		newFlags &= ~Flag::f_ban_users;
-		prevFlags &= ~Flag::f_ban_users;
+		newRights.flags &= ~Flag::BanUsers;
+		prevRights.flags &= ~Flag::BanUsers;
 	}
 
-	auto changes = CollectChanges(phraseMap, newFlags, prevFlags);
+	auto changes = CollectChanges(phraseMap, newRights.flags, prevRights.flags);
 	if (!changes.isEmpty()) {
 		result.text.append('\n' + changes);
 	}
@@ -202,45 +197,43 @@ TextWithEntities GenerateAdminChangeText(
 };
 
 QString GenerateBannedChangeText(
-		const MTPChatBannedRights *newRights,
-		const MTPChatBannedRights *prevRights) {
-	using Flag = MTPDchatBannedRights::Flag;
-	using Flags = MTPDchatBannedRights::Flags;
+		ChatRestrictionsInfo newRights,
+		ChatRestrictionsInfo prevRights) {
+	using Flag = ChatRestriction;
+	using Flags = ChatRestrictions;
 
-	auto newFlags = newRights ? Data::ChatBannedRightsFlags(*newRights) : Flags(0);
-	auto prevFlags = prevRights ? Data::ChatBannedRightsFlags(*prevRights) : Flags(0);
 	static auto phraseMap = std::map<Flags, tr::phrase<>>{
-		{ Flag::f_view_messages, tr::lng_admin_log_banned_view_messages },
-		{ Flag::f_send_messages, tr::lng_admin_log_banned_send_messages },
-		{ Flag::f_send_media, tr::lng_admin_log_banned_send_media },
-		{ Flag::f_send_stickers
-			| Flag::f_send_gifs
-			| Flag::f_send_inline
-			| Flag::f_send_games, tr::lng_admin_log_banned_send_stickers },
-		{ Flag::f_embed_links, tr::lng_admin_log_banned_embed_links },
-		{ Flag::f_send_polls, tr::lng_admin_log_banned_send_polls },
-		{ Flag::f_change_info, tr::lng_admin_log_admin_change_info },
-		{ Flag::f_invite_users, tr::lng_admin_log_admin_invite_users },
-		{ Flag::f_pin_messages, tr::lng_admin_log_admin_pin_messages },
+		{ Flag::ViewMessages, tr::lng_admin_log_banned_view_messages },
+		{ Flag::SendMessages, tr::lng_admin_log_banned_send_messages },
+		{ Flag::SendMedia, tr::lng_admin_log_banned_send_media },
+		{ Flag::SendStickers
+			| Flag::SendGifs
+			| Flag::SendInline
+			| Flag::SendGames, tr::lng_admin_log_banned_send_stickers },
+		{ Flag::EmbedLinks, tr::lng_admin_log_banned_embed_links },
+		{ Flag::SendPolls, tr::lng_admin_log_banned_send_polls },
+		{ Flag::ChangeInfo, tr::lng_admin_log_admin_change_info },
+		{ Flag::InviteUsers, tr::lng_admin_log_admin_invite_users },
+		{ Flag::PinMessages, tr::lng_admin_log_admin_pin_messages },
 	};
-	return CollectChanges(phraseMap, prevFlags, newFlags);
+	return CollectChanges(phraseMap, prevRights.flags, newRights.flags);
 }
 
 TextWithEntities GenerateBannedChangeText(
 		PeerId participantId,
 		const TextWithEntities &user,
-		const MTPChatBannedRights *newRights,
-		const MTPChatBannedRights *prevRights) {
-	using Flag = MTPDchatBannedRights::Flag;
-	using Flags = MTPDchatBannedRights::Flags;
+		ChatRestrictionsInfo newRights,
+		ChatRestrictionsInfo prevRights) {
+	using Flag = ChatRestriction;
+	using Flags = ChatRestrictions;
 
-	auto newFlags = newRights ? Data::ChatBannedRightsFlags(*newRights) : Flags(0);
-	auto newUntil = newRights ? Data::ChatBannedRightsUntilDate(*newRights) : TimeId(0);
-	auto prevFlags = prevRights ? Data::ChatBannedRightsFlags(*prevRights) : Flags(0);
+	auto newFlags = newRights.flags;
+	auto newUntil = newRights.until;
+	auto prevFlags = prevRights.flags;
 	auto indefinitely = ChannelData::IsRestrictedForever(newUntil);
-	if (newFlags & Flag::f_view_messages) {
+	if (newFlags & Flag::ViewMessages) {
 		return tr::lng_admin_log_banned(tr::now, lt_user, user, Ui::Text::WithEntities);
-	} else if (newFlags == 0 && (prevFlags & Flag::f_view_messages) && !peerIsUser(participantId)) {
+	} else if (newFlags == 0 && (prevFlags & Flag::ViewMessages) && !peerIsUser(participantId)) {
 		return tr::lng_admin_log_unbanned(tr::now, lt_user, user, Ui::Text::WithEntities);
 	}
 	auto untilText = indefinitely
@@ -390,14 +383,16 @@ auto GenerateParticipantChangeTextInner(
 			return GenerateAdminChangeText(
 				channel,
 				user,
-				nullptr,
-				&oldParticipant->c_channelParticipantAdmin().vadmin_rights());
+				ChatAdminRightsInfo(),
+				ChatAdminRightsInfo(
+					oldParticipant->c_channelParticipantAdmin().vadmin_rights()));
 		} else if (oldType == mtpc_channelParticipantBanned) {
 			return GenerateBannedChangeText(
 				participantId,
 				user,
-				nullptr,
-				&oldParticipant->c_channelParticipantBanned().vbanned_rights());
+				ChatRestrictionsInfo(),
+				ChatRestrictionsInfo(
+					oldParticipant->c_channelParticipantBanned().vbanned_rights()));
 		}
 		return tr::lng_admin_log_invited(tr::now, lt_user, user, Ui::Text::WithEntities);
 	};
@@ -417,10 +412,11 @@ auto GenerateParticipantChangeTextInner(
 		return GenerateAdminChangeText(
 			channel,
 			user,
-			&data.vadmin_rights(),
+			ChatAdminRightsInfo(data.vadmin_rights()),
 			(oldType == mtpc_channelParticipantAdmin
-				? &oldParticipant->c_channelParticipantAdmin().vadmin_rights()
-				: nullptr));
+				? ChatAdminRightsInfo(
+					oldParticipant->c_channelParticipantAdmin().vadmin_rights())
+				: ChatAdminRightsInfo()));
 	}, [&](const MTPDchannelParticipantBanned &data) {
 		const auto participantId = peerFromMTP(data.vpeer());
 		const auto user = GenerateParticipantString(
@@ -429,10 +425,11 @@ auto GenerateParticipantChangeTextInner(
 		return GenerateBannedChangeText(
 			participantId,
 			user,
-			&data.vbanned_rights(),
+			ChatRestrictionsInfo(data.vbanned_rights()),
 			(oldType == mtpc_channelParticipantBanned
-				? &oldParticipant->c_channelParticipantBanned().vbanned_rights()
-				: nullptr));
+				? ChatRestrictionsInfo(
+					oldParticipant->c_channelParticipantBanned().vbanned_rights())
+				: ChatRestrictionsInfo()));
 	}, [&](const MTPDchannelParticipantLeft &data) {
 		return generateOther(peerFromMTP(data.vpeer()));
 	}, [&](const auto &data) {
@@ -446,9 +443,9 @@ TextWithEntities GenerateParticipantChangeText(not_null<ChannelData*> channel, c
 	return result;
 }
 
-TextWithEntities GenerateDefaultBannedRightsChangeText(not_null<ChannelData*> channel, const MTPChatBannedRights &rights, const MTPChatBannedRights &oldRights) {
+TextWithEntities GenerateDefaultBannedRightsChangeText(not_null<ChannelData*> channel, ChatRestrictionsInfo rights, ChatRestrictionsInfo oldRights) {
 	auto result = TextWithEntities{ tr::lng_admin_log_changed_default_permissions(tr::now) };
-	const auto changes = GenerateBannedChangeText(&rights, &oldRights);
+	const auto changes = GenerateBannedChangeText(rights, oldRights);
 	if (!changes.isEmpty()) {
 		result.text.append('\n' + changes);
 	}
@@ -850,7 +847,10 @@ void GenerateItems(
 		auto bodyClientFlags = MTPDmessage_ClientFlag::f_admin_log_entry;
 		auto bodyReplyTo = 0;
 		auto bodyViaBotId = 0;
-		auto bodyText = GenerateDefaultBannedRightsChangeText(channel, action.vnew_banned_rights(), action.vprev_banned_rights());
+		auto bodyText = GenerateDefaultBannedRightsChangeText(
+			channel,
+			ChatRestrictionsInfo(action.vnew_banned_rights()),
+			ChatRestrictionsInfo(action.vprev_banned_rights()));
 		addPart(history->makeMessage(
 			history->nextNonHistoryEntryId(),
 			bodyFlags,
diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp
index 891dc4d9e..6ee57cfb4 100644
--- a/Telegram/SourceFiles/history/history_message.cpp
+++ b/Telegram/SourceFiles/history/history_message.cpp
@@ -70,7 +70,7 @@ namespace {
 	if (const auto media = fwd->media()) {
 		if (dynamic_cast<Data::MediaWebPage*>(media)) {
 			// Drop web page if we're not allowed to send it.
-			if (peer->amRestricted(ChatRestriction::f_embed_links)) {
+			if (peer->amRestricted(ChatRestriction::EmbedLinks)) {
 				result &= ~MTPDmessage::Flag::f_media;
 			}
 		}
@@ -152,7 +152,7 @@ QString GetErrorTextForSending(
 	}
 	const auto error = Data::RestrictionError(
 		peer,
-		ChatRestriction::f_send_inline);
+		ChatRestriction::SendInline);
 	if (error && HasInlineItems(items)) {
 		return *error;
 	}
@@ -639,7 +639,7 @@ HistoryMessage::HistoryMessage(
 
 	const auto ignoreMedia = [&] {
 		if (mediaOriginal && mediaOriginal->webpage()) {
-			if (peer->amRestricted(ChatRestriction::f_embed_links)) {
+			if (peer->amRestricted(ChatRestriction::EmbedLinks)) {
 				return true;
 			}
 		}
diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp
index 5969ddeb5..796ca7563 100644
--- a/Telegram/SourceFiles/history/history_widget.cpp
+++ b/Telegram/SourceFiles/history/history_widget.cpp
@@ -787,7 +787,7 @@ void HistoryWidget::initVoiceRecordBar() {
 
 	_voiceRecordBar->setStartRecordingFilter([=] {
 		const auto error = _peer
-			? Data::RestrictionError(_peer, ChatRestriction::f_send_media)
+			? Data::RestrictionError(_peer, ChatRestriction::SendMedia)
 			: std::nullopt;
 		if (error) {
 			controller()->show(Box<InformBox>(*error));
@@ -1331,7 +1331,7 @@ void HistoryWidget::updateStickersByEmoji() {
 	const auto emoji = [&] {
 		const auto errorForStickers = Data::RestrictionError(
 			_peer,
-			ChatRestriction::f_send_stickers);
+			ChatRestriction::SendStickers);
 		if (!_editMsgId && !errorForStickers) {
 			const auto &text = _field->getTextWithTags().text;
 			auto length = 0;
@@ -2185,7 +2185,7 @@ bool HistoryWidget::canWriteMessage() const {
 
 std::optional<QString> HistoryWidget::writeRestriction() const {
 	return _peer
-		? Data::RestrictionError(_peer, ChatRestriction::f_send_messages)
+		? Data::RestrictionError(_peer, ChatRestriction::SendMessages)
 		: std::nullopt;
 }
 
@@ -3528,7 +3528,7 @@ void HistoryWidget::chooseAttach() {
 		return;
 	} else if (const auto error = Data::RestrictionError(
 			_peer,
-			ChatRestriction::f_send_media)) {
+			ChatRestriction::SendMedia)) {
 		Ui::ShowMultilineToast({
 			.text = { *error },
 		});
@@ -4269,7 +4269,7 @@ void HistoryWidget::updateFieldPlaceholder() {
 				return session().data().notifySilentPosts(channel)
 					? tr::lng_broadcast_silent_ph()
 					: tr::lng_broadcast_ph();
-			} else if (channel->adminRights() & ChatAdminRight::f_anonymous) {
+			} else if (channel->adminRights() & ChatAdminRight::Anonymous) {
 				return tr::lng_send_anonymous_ph();
 			} else {
 				return tr::lng_message_ph();
@@ -4287,7 +4287,7 @@ bool HistoryWidget::showSendingFilesError(
 		const auto error = _peer
 			? Data::RestrictionError(
 				_peer,
-				ChatRestriction::f_send_media)
+				ChatRestriction::SendMedia)
 			: std::nullopt;
 		if (error) {
 			return *error;
@@ -5681,7 +5681,7 @@ bool HistoryWidget::sendExistingDocument(
 		not_null<DocumentData*> document,
 		Api::SendOptions options) {
 	const auto error = _peer
-		? Data::RestrictionError(_peer, ChatRestriction::f_send_stickers)
+		? Data::RestrictionError(_peer, ChatRestriction::SendStickers)
 		: std::nullopt;
 	if (error) {
 		controller()->show(
@@ -5717,7 +5717,7 @@ bool HistoryWidget::sendExistingPhoto(
 		not_null<PhotoData*> photo,
 		Api::SendOptions options) {
 	const auto error = _peer
-		? Data::RestrictionError(_peer, ChatRestriction::f_send_media)
+		? Data::RestrictionError(_peer, ChatRestriction::SendMedia)
 		: std::nullopt;
 	if (error) {
 		controller()->show(
@@ -6091,7 +6091,7 @@ void HistoryWidget::previewCancel() {
 
 void HistoryWidget::checkPreview() {
 	const auto previewRestricted = [&] {
-		return _peer && _peer->amRestricted(ChatRestriction::f_embed_links);
+		return _peer && _peer->amRestricted(ChatRestriction::EmbedLinks);
 	}();
 	if (_previewState != Data::PreviewState::Allowed || previewRestricted) {
 		previewCancel();
diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp
index 4380894ea..76e14e5de 100644
--- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp
+++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp
@@ -1264,7 +1264,7 @@ void ComposeControls::updateStickersByEmoji() {
 	const auto emoji = [&] {
 		const auto errorForStickers = Data::RestrictionError(
 			_history->peer,
-			ChatRestriction::f_send_stickers);
+			ChatRestriction::SendStickers);
 		if (!isEditingMessage() && !errorForStickers) {
 			const auto &text = _field->getTextWithTags().text;
 			auto length = 0;
@@ -1297,7 +1297,7 @@ void ComposeControls::updateFieldPlaceholder() {
 				return session().data().notifySilentPosts(channel)
 					? tr::lng_broadcast_silent_ph()
 					: tr::lng_broadcast_ph();
-			} else if (channel->adminRights() & ChatAdminRight::f_anonymous) {
+			} else if (channel->adminRights() & ChatAdminRight::Anonymous) {
 				return tr::lng_send_anonymous_ph();
 			} else {
 				return tr::lng_message_ph();
@@ -1652,7 +1652,7 @@ void ComposeControls::initVoiceRecordBar() {
 		const auto error = _history
 			? Data::RestrictionError(
 				_history->peer,
-				ChatRestriction::f_send_media)
+				ChatRestriction::SendMedia)
 			: std::nullopt;
 		if (error) {
 			_window->show(Box<InformBox>(*error));
@@ -2171,7 +2171,7 @@ void ComposeControls::initWebpageProcess() {
 
 	const auto checkPreview = crl::guard(_wrap.get(), [=] {
 		const auto previewRestricted = peer
-			&& peer->amRestricted(ChatRestriction::f_embed_links);
+			&& peer->amRestricted(ChatRestriction::EmbedLinks);
 		if (_previewState != Data::PreviewState::Allowed
 			|| previewRestricted) {
 			_previewCancel();
diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp
index 468bb1382..f618163c8 100644
--- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp
+++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp
@@ -410,7 +410,7 @@ void RepliesWidget::setupComposeControls() {
 	) | rpl::map([=] {
 		return Data::RestrictionError(
 			_history->peer,
-			ChatRestriction::f_send_messages);
+			ChatRestriction::SendMessages);
 	});
 
 	_composeControls->setHistory({
@@ -541,7 +541,7 @@ void RepliesWidget::setupComposeControls() {
 void RepliesWidget::chooseAttach() {
 	if (const auto error = Data::RestrictionError(
 			_history->peer,
-			ChatRestriction::f_send_media)) {
+			ChatRestriction::SendMedia)) {
 		Ui::ShowMultilineToast({
 			.text = { *error },
 		});
@@ -749,7 +749,7 @@ bool RepliesWidget::showSlowmodeError() {
 std::optional<QString> RepliesWidget::writeRestriction() const {
 	return Data::RestrictionError(
 		_history->peer,
-		ChatRestriction::f_send_messages);
+		ChatRestriction::SendMessages);
 }
 
 void RepliesWidget::pushReplyReturn(not_null<HistoryItem*> item) {
@@ -818,7 +818,7 @@ bool RepliesWidget::showSendingFilesError(
 		const auto peer = _history->peer;
 		const auto error = Data::RestrictionError(
 			peer,
-			ChatRestriction::f_send_media);
+			ChatRestriction::SendMedia);
 		if (error) {
 			return *error;
 		}
@@ -1013,7 +1013,7 @@ bool RepliesWidget::sendExistingDocument(
 		Api::SendOptions options) {
 	const auto error = Data::RestrictionError(
 		_history->peer,
-		ChatRestriction::f_send_stickers);
+		ChatRestriction::SendStickers);
 	if (error) {
 		controller()->show(
 			Box<InformBox>(*error),
@@ -1049,7 +1049,7 @@ bool RepliesWidget::sendExistingPhoto(
 		Api::SendOptions options) {
 	const auto error = Data::RestrictionError(
 		_history->peer,
-		ChatRestriction::f_send_media);
+		ChatRestriction::SendMedia);
 	if (error) {
 		controller()->show(
 			Box<InformBox>(*error),
diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp
index bfdc92209..956d81878 100644
--- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp
+++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp
@@ -271,7 +271,7 @@ void ScheduledWidget::setupComposeControls() {
 void ScheduledWidget::chooseAttach() {
 	if (const auto error = Data::RestrictionError(
 			_history->peer,
-			ChatRestriction::f_send_media)) {
+			ChatRestriction::SendMedia)) {
 		Ui::ShowMultilineToast({
 			.text = { *error },
 		});
@@ -461,7 +461,7 @@ bool ScheduledWidget::showSendingFilesError(
 	const auto text = [&] {
 		const auto error = Data::RestrictionError(
 			_history->peer,
-			ChatRestriction::f_send_media);
+			ChatRestriction::SendMedia);
 		if (error) {
 			return *error;
 		}
@@ -645,7 +645,7 @@ bool ScheduledWidget::sendExistingDocument(
 		Api::SendOptions options) {
 	const auto error = Data::RestrictionError(
 		_history->peer,
-		ChatRestriction::f_send_stickers);
+		ChatRestriction::SendStickers);
 	if (error) {
 		controller()->show(
 			Box<InformBox>(*error),
@@ -677,7 +677,7 @@ bool ScheduledWidget::sendExistingPhoto(
 		Api::SendOptions options) {
 	const auto error = Data::RestrictionError(
 		_history->peer,
-		ChatRestriction::f_send_media);
+		ChatRestriction::SendMedia);
 	if (error) {
 		controller()->show(
 			Box<InformBox>(*error),
diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_send_data.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_send_data.cpp
index 4b9c2bd87..70db1395e 100644
--- a/Telegram/SourceFiles/inline_bots/inline_bot_send_data.cpp
+++ b/Telegram/SourceFiles/inline_bots/inline_bot_send_data.cpp
@@ -84,7 +84,7 @@ QString SendDataCommon::getErrorOnSend(
 		not_null<History*> history) const {
 	const auto error = Data::RestrictionError(
 		history->peer,
-		ChatRestriction::f_send_messages);
+		ChatRestriction::SendMessages);
 	return error.value_or(QString());
 }
 
@@ -177,7 +177,7 @@ QString SendPhoto::getErrorOnSend(
 		not_null<History*> history) const {
 	const auto error = Data::RestrictionError(
 		history->peer,
-		ChatRestriction::f_send_media);
+		ChatRestriction::SendMedia);
 	return error.value_or(QString());
 }
 
@@ -212,13 +212,13 @@ QString SendFile::getErrorOnSend(
 		not_null<History*> history) const {
 	const auto errorMedia = Data::RestrictionError(
 		history->peer,
-		ChatRestriction::f_send_media);
+		ChatRestriction::SendMedia);
 	const auto errorStickers = Data::RestrictionError(
 		history->peer,
-		ChatRestriction::f_send_stickers);
+		ChatRestriction::SendStickers);
 	const auto errorGifs = Data::RestrictionError(
 		history->peer,
-		ChatRestriction::f_send_gifs);
+		ChatRestriction::SendGifs);
 	return errorMedia
 		? *errorMedia
 		: (errorStickers && (_document->sticker() != nullptr))
@@ -260,7 +260,7 @@ QString SendGame::getErrorOnSend(
 		not_null<History*> history) const {
 	const auto error = Data::RestrictionError(
 		history->peer,
-		ChatRestriction::f_send_games);
+		ChatRestriction::SendGames);
 	return error.value_or(QString());
 }
 
diff --git a/Telegram/SourceFiles/inline_bots/inline_results_inner.cpp b/Telegram/SourceFiles/inline_bots/inline_results_inner.cpp
index 899775afc..12c9ecd9a 100644
--- a/Telegram/SourceFiles/inline_bots/inline_results_inner.cpp
+++ b/Telegram/SourceFiles/inline_bots/inline_results_inner.cpp
@@ -88,7 +88,7 @@ void Inner::checkRestrictedPeer() {
 	if (_inlineQueryPeer) {
 		const auto error = Data::RestrictionError(
 			_inlineQueryPeer,
-			ChatRestriction::f_send_inline);
+			ChatRestriction::SendInline);
 		if (error) {
 			if (!_restrictedLabel) {
 				_restrictedLabel.create(this, *error, st::stickersRestrictedLabel);
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index 0f3f52ea0..2e3e5e3f0 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -610,7 +610,7 @@ bool MainWidget::sendPaths(PeerId peerId) {
 		return false;
 	} else if (const auto error = Data::RestrictionError(
 			peer,
-			ChatRestriction::f_send_media)) {
+			ChatRestriction::SendMedia)) {
 		Ui::show(Box<InformBox>(*error));
 		return false;
 	}
diff --git a/Telegram/SourceFiles/profile/profile_block_group_members.cpp b/Telegram/SourceFiles/profile/profile_block_group_members.cpp
index 0b9360118..552ddcf6d 100644
--- a/Telegram/SourceFiles/profile/profile_block_group_members.cpp
+++ b/Telegram/SourceFiles/profile/profile_block_group_members.cpp
@@ -75,14 +75,14 @@ void GroupMembersWidget::removePeer(PeerData *selectedPeer) {
 	Assert(user != nullptr);
 
 	auto text = tr::lng_profile_sure_kick(tr::now, lt_user, user->firstName);
-	auto currentRestrictedRights = [&]() -> MTPChatBannedRights {
+	auto currentRestrictedRights = [&]() -> ChatRestrictionsInfo {
 		if (auto channel = peer()->asMegagroup()) {
 			auto it = channel->mgInfo->lastRestricted.find(user);
 			if (it != channel->mgInfo->lastRestricted.cend()) {
 				return it->second.rights;
 			}
 		}
-		return ChannelData::EmptyRestrictedRights(user);
+		return ChatRestrictionsInfo();
 	}();
 
 	const auto peer = this->peer();
@@ -306,7 +306,7 @@ void GroupMembersWidget::setItemFlags(
 	if (item->peer->id == chat->session().userPeerId()) {
 		item->hasRemoveLink = false;
 	} else if (chat->amCreator()
-		|| ((chat->adminRights() & ChatAdminRight::f_ban_users)
+		|| ((chat->adminRights() & ChatAdminRight::BanUsers)
 			&& (adminState == AdminState::None))) {
 		item->hasRemoveLink = true;
 	} else if (chat->invitedByMe.contains(user)