diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index 29459592c..0d29eb60d 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -999,7 +999,7 @@ void Updates::handleSendActionUpdate( const auto chat = peer->asChat(); const auto channel = peer->asChannel(); const auto active = chat - ? (chat->flags() & MTPDchat::Flag::f_call_active) + ? (chat->flags() & ChatDataFlag::CallActive) : (channel->flags() & MTPDchannel::Flag::f_call_active); if (active) { _pendingSpeakingCallParticipants.emplace( diff --git a/Telegram/SourceFiles/data/data_chat.cpp b/Telegram/SourceFiles/data/data_chat.cpp index 6affa384d..ff6518a50 100644 --- a/Telegram/SourceFiles/data/data_chat.cpp +++ b/Telegram/SourceFiles/data/data_chat.cpp @@ -28,7 +28,7 @@ ChatData::ChatData(not_null owner, PeerId id) , inputChat(MTP_int(peerToChat(id).bare)) { _flags.changes( ) | rpl::start_with_next([=](const Flags::Change &change) { - if (change.diff & MTPDchat::Flag::f_call_not_empty) { + if (change.diff & ChatDataFlag::CallNotEmpty) { if (const auto history = this->owner().historyLoaded(this)) { history->updateChatListEntry(); } @@ -74,7 +74,7 @@ bool ChatData::canEditPermissions() const { bool ChatData::canEditUsername() const { return amCreator() - && (fullFlags() & MTPDchatFull::Flag::f_can_set_username); + && (flags() & ChatDataFlag::CanSetUsername); } bool ChatData::canEditPreHistoryHidden() const { @@ -219,7 +219,7 @@ void ChatData::setGroupCall( scheduleDate); owner().registerGroupCall(_call.get()); session().changes().peerUpdated(this, UpdateFlag::GroupCall); - addFlags(MTPDchat::Flag::f_call_active); + addFlags(ChatDataFlag::CallActive); }); } @@ -233,8 +233,7 @@ void ChatData::clearGroupCall() { _call = nullptr; } session().changes().peerUpdated(this, UpdateFlag::GroupCall); - removeFlags(MTPDchat::Flag::f_call_active - | MTPDchat::Flag::f_call_not_empty); + removeFlags(ChatDataFlag::CallActive | ChatDataFlag::CallNotEmpty); } void ChatData::setGroupCallDefaultJoinAs(PeerId peerId) { @@ -403,7 +402,10 @@ void ApplyChatUpdate(not_null chat, const MTPDchatFull &update) { } else { chat->setBotCommands(MTP_vector()); } - chat->setFullFlags(update.vflags().v); + using Flag = ChatDataFlag; + const auto mask = Flag::CanSetUsername; + chat->setFlags((chat->flags() & ~mask) + | (update.is_can_set_username() ? Flag::CanSetUsername : Flag())); if (const auto photo = update.vchat_photo()) { chat->setUserpicPhoto(*photo); } else { diff --git a/Telegram/SourceFiles/data/data_chat.h b/Telegram/SourceFiles/data/data_chat.h index 33e5dc077..814512d80 100644 --- a/Telegram/SourceFiles/data/data_chat.h +++ b/Telegram/SourceFiles/data/data_chat.h @@ -9,26 +9,23 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_peer.h" +enum class ChatDataFlag { + Left = (1 << 0), + Kicked = (1 << 1), + Creator = (1 << 2), + Deactivated = (1 << 3), + Forbidden = (1 << 4), + CallActive = (1 << 5), + CallNotEmpty = (1 << 6), + CanSetUsername = (1 << 7), +}; +inline constexpr bool is_flag_type(ChatDataFlag) { return true; }; +using ChatDataFlags = base::flags; + class ChatData : public PeerData { public: - static constexpr auto kEssentialFlags = 0 - | MTPDchat::Flag::f_creator - | MTPDchat::Flag::f_kicked - | MTPDchat::Flag::f_left - | MTPDchat::Flag::f_deactivated - | MTPDchat::Flag::f_migrated_to - | MTPDchat::Flag::f_admin_rights - | MTPDchat::Flag::f_call_not_empty - | MTPDchat::Flag::f_default_banned_rights; - using Flags = Data::Flags< - MTPDchat::Flags, - kEssentialFlags>; - - static constexpr auto kEssentialFullFlags = 0 - | MTPDchatFull::Flag::f_can_set_username; - using FullFlags = Data::Flags< - MTPDchatFull::Flags, - kEssentialFullFlags>; + using Flag = ChatDataFlag; + using Flags = Data::Flags; using AdminRight = ChatAdminRight; using Restriction = ChatRestriction; @@ -47,13 +44,13 @@ public: return (count > 0 || amIn()) && participants.empty(); } - void setFlags(MTPDchat::Flags which) { + void setFlags(ChatDataFlags which) { _flags.set(which); } - void addFlags(MTPDchat::Flags which) { + void addFlags(ChatDataFlags which) { _flags.add(which); } - void removeFlags(MTPDchat::Flags which) { + void removeFlags(ChatDataFlags which) { _flags.remove(which); } [[nodiscard]] auto flags() const { @@ -63,22 +60,6 @@ public: return _flags.value(); } - void setFullFlags(MTPDchatFull::Flags which) { - _fullFlags.set(which); - } - void addFullFlags(MTPDchatFull::Flags which) { - _fullFlags.add(which); - } - void removeFullFlags(MTPDchatFull::Flags which) { - _fullFlags.remove(which); - } - [[nodiscard]] auto fullFlags() const { - return _fullFlags.current(); - } - [[nodiscard]] auto fullFlagsValue() const { - return _fullFlags.value(); - } - [[nodiscard]] auto adminRights() const { return _adminRights.current(); } @@ -99,7 +80,7 @@ public: void setDefaultRestrictions(ChatRestrictions rights); [[nodiscard]] bool isForbidden() const { - return flags() & MTPDchat_ClientFlag::f_forbidden; + return flags() & Flag::Forbidden; } [[nodiscard]] bool amIn() const { return !isForbidden() @@ -108,19 +89,19 @@ public: && !wasKicked(); } [[nodiscard]] bool haveLeft() const { - return flags() & MTPDchat::Flag::f_left; + return flags() & ChatDataFlag::Left; } [[nodiscard]] bool wasKicked() const { - return flags() & MTPDchat::Flag::f_kicked; + return flags() & ChatDataFlag::Kicked; } [[nodiscard]] bool amCreator() const { - return flags() & MTPDchat::Flag::f_creator; + return flags() & ChatDataFlag::Creator; } [[nodiscard]] bool isDeactivated() const { - return flags() & MTPDchat::Flag::f_deactivated; + return flags() & ChatDataFlag::Deactivated; } [[nodiscard]] bool isMigrated() const { - return flags() & MTPDchat::Flag::f_migrated_to; + return (_migratedTo != nullptr); } [[nodiscard]] ChatAdminRightsInfo defaultAdminRights( @@ -196,7 +177,6 @@ public: private: Flags _flags; - FullFlags _fullFlags; QString _inviteLink; RestrictionFlags _defaultRestrictions; diff --git a/Telegram/SourceFiles/data/data_group_call.cpp b/Telegram/SourceFiles/data/data_group_call.cpp index 06d222de5..e337fd679 100644 --- a/Telegram/SourceFiles/data/data_group_call.cpp +++ b/Telegram/SourceFiles/data/data_group_call.cpp @@ -174,7 +174,7 @@ void GroupCall::setServerParticipantsCount(int count) { void GroupCall::changePeerEmptyCallFlag() { const auto chat = _peer->asChat(); const auto channel = _peer->asChannel(); - constexpr auto chatFlag = MTPDchat::Flag::f_call_not_empty; + constexpr auto chatFlag = ChatDataFlag::CallNotEmpty; constexpr auto channelFlag = MTPDchannel::Flag::f_call_not_empty; if (_peer->groupCall() != this) { return; diff --git a/Telegram/SourceFiles/data/data_peer_values.cpp b/Telegram/SourceFiles/data/data_peer_values.cpp index e541e66db..8577e6371 100644 --- a/Telegram/SourceFiles/data/data_peer_values.cpp +++ b/Telegram/SourceFiles/data/data_peer_values.cpp @@ -157,12 +157,6 @@ inline auto DefaultRestrictionValue( return SingleFlagValue(DefaultRestrictionsValue(chat), flag); } -rpl::producer PeerFlagValue( - ChatData *chat, - MTPDchat_ClientFlag flag) { - return PeerFlagValue(chat, static_cast(flag)); -} - rpl::producer PeerFlagValue( ChannelData *channel, MTPDchannel_ClientFlag flag) { @@ -182,11 +176,11 @@ rpl::producer CanWriteValue(UserData *user) { rpl::producer CanWriteValue(ChatData *chat) { using namespace rpl::mappers; const auto mask = 0 - | MTPDchat::Flag::f_deactivated - | MTPDchat_ClientFlag::f_forbidden - | MTPDchat::Flag::f_left - | MTPDchat::Flag::f_creator - | MTPDchat::Flag::f_kicked; + | ChatDataFlag::Deactivated + | ChatDataFlag::Forbidden + | ChatDataFlag::Left + | ChatDataFlag::Creator + | ChatDataFlag::Kicked; return rpl::combine( PeerFlagsValue(chat, mask), AdminRightsValue(chat), @@ -194,16 +188,16 @@ rpl::producer CanWriteValue(ChatData *chat) { chat, ChatRestriction::SendMessages), []( - MTPDchat::Flags flags, + ChatDataFlags flags, Data::Flags::Change adminRights, bool defaultSendMessagesRestriction) { const auto amOutFlags = 0 - | MTPDchat::Flag::f_deactivated - | MTPDchat_ClientFlag::f_forbidden - | MTPDchat::Flag::f_left - | MTPDchat::Flag::f_kicked; + | ChatDataFlag::Deactivated + | ChatDataFlag::Forbidden + | ChatDataFlag::Left + | ChatDataFlag::Kicked; return !(flags & amOutFlags) - && ((flags & MTPDchat::Flag::f_creator) + && ((flags & ChatDataFlag::Creator) || (adminRights.value != ChatAdminRights(0)) || !defaultSendMessagesRestriction); }); @@ -266,26 +260,26 @@ rpl::producer CanPinMessagesValue(not_null peer) { ) | rpl::map(_1 != UserDataFlag(0)); } else if (const auto chat = peer->asChat()) { const auto mask = 0 - | MTPDchat::Flag::f_deactivated - | MTPDchat_ClientFlag::f_forbidden - | MTPDchat::Flag::f_left - | MTPDchat::Flag::f_creator - | MTPDchat::Flag::f_kicked; + | ChatDataFlag::Deactivated + | ChatDataFlag::Forbidden + | ChatDataFlag::Left + | ChatDataFlag::Creator + | ChatDataFlag::Kicked; return rpl::combine( PeerFlagsValue(chat, mask), AdminRightValue(chat, ChatAdminRight::PinMessages), DefaultRestrictionValue(chat, ChatRestriction::PinMessages), - []( - MTPDchat::Flags flags, + []( + ChatDataFlags flags, bool adminRightAllows, bool defaultRestriction) { const auto amOutFlags = 0 - | MTPDchat::Flag::f_deactivated - | MTPDchat_ClientFlag::f_forbidden - | MTPDchat::Flag::f_left - | MTPDchat::Flag::f_kicked; + | ChatDataFlag::Deactivated + | ChatDataFlag::Forbidden + | ChatDataFlag::Left + | ChatDataFlag::Kicked; return !(flags & amOutFlags) - && ((flags & MTPDchat::Flag::f_creator) + && ((flags & ChatDataFlag::Creator) || adminRightAllows || !defaultRestriction); }); diff --git a/Telegram/SourceFiles/data/data_peer_values.h b/Telegram/SourceFiles/data/data_peer_values.h index 2b6df7f15..3d71af8eb 100644 --- a/Telegram/SourceFiles/data/data_peer_values.h +++ b/Telegram/SourceFiles/data/data_peer_values.h @@ -65,10 +65,6 @@ inline auto PeerFlagValue( return SingleFlagValue(PeerFlagsValue(peer), flag); } -rpl::producer PeerFlagValue( - ChatData *chat, - MTPDchat_ClientFlag flag); - rpl::producer PeerFlagValue( ChannelData *channel, MTPDchannel_ClientFlag flag); diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index d7ef3ae58..c222d8709 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -632,12 +632,25 @@ not_null Session::processChat(const MTPChat &data) { }); } - const auto callFlag = MTPDchat::Flag::f_call_not_empty; - const auto callNotEmpty = (data.vflags().v & callFlag) - || (chat->groupCall() - && chat->groupCall()->fullCount() > 0); - chat->setFlags(data.vflags().v - | (callNotEmpty ? callFlag : MTPDchat::Flag(0))); + using Flag = ChatDataFlag; + const auto flagsMask = Flag::Left + | Flag::Kicked + | Flag::Creator + | Flag::Deactivated + | Flag::Forbidden + | Flag::CallActive + | Flag::CallNotEmpty; + const auto flagsSet = (data.is_left() ? Flag::Left : Flag()) + | (data.is_kicked() ? Flag::Kicked : Flag()) + | (data.is_creator() ? Flag::Creator : Flag()) + | (data.is_deactivated() ? Flag::Deactivated : Flag()) + | (data.is_call_active() ? Flag::CallActive : Flag()) + | ((data.is_call_not_empty() + || (chat->groupCall() + && chat->groupCall()->fullCount() > 0)) + ? Flag::CallNotEmpty + : Flag()); + chat->setFlags((chat->flags() & ~flagsMask) | flagsSet); chat->count = data.vparticipants_count().v; if (canAddMembers != chat->canAddMembers()) { @@ -654,7 +667,7 @@ not_null Session::processChat(const MTPChat &data) { chat->date = 0; chat->count = -1; chat->invalidateParticipants(); - chat->setFlags(MTPDchat_ClientFlag::f_forbidden | 0); + chat->setFlags(ChatDataFlag::Forbidden); chat->setAdminRights(ChatAdminRights()); chat->setDefaultRestrictions(ChatRestrictions()); diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 58361965e..e1897cc6a 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -980,7 +980,7 @@ void History::applyServiceChanges( } }, [&](const MTPDmessageActionChatMigrateTo &data) { if (const auto chat = peer->asChat()) { - chat->addFlags(MTPDchat::Flag::f_deactivated); + chat->addFlags(ChatDataFlag::Deactivated); if (const auto channel = owner().channelLoaded( data.vchannel_id().v)) { Data::ApplyMigration(chat, channel); diff --git a/Telegram/SourceFiles/history/history_service.cpp b/Telegram/SourceFiles/history/history_service.cpp index 962126cea..05c203c74 100644 --- a/Telegram/SourceFiles/history/history_service.cpp +++ b/Telegram/SourceFiles/history/history_service.cpp @@ -48,7 +48,7 @@ constexpr auto kPinnedMessageTextLimit = 16; if (peer->groupCall() != nullptr) { return true; } else if (const auto chat = peer->asChat()) { - return !(chat->flags() & MTPDchat::Flag::f_call_active); + return !(chat->flags() & ChatDataFlag::CallActive); } else if (const auto channel = peer->asChannel()) { return !(channel->flags() & MTPDchannel::Flag::f_call_active); } diff --git a/Telegram/SourceFiles/mtproto/type_utils.h b/Telegram/SourceFiles/mtproto/type_utils.h index 182431fc2..d2175e2eb 100644 --- a/Telegram/SourceFiles/mtproto/type_utils.h +++ b/Telegram/SourceFiles/mtproto/type_utils.h @@ -113,24 +113,6 @@ enum class MTPDstickerSet_ClientFlag : uint32 { }; DEFINE_MTP_CLIENT_FLAGS(MTPDstickerSet) -//enum class MTPDuser_ClientFlag : uint32 { -// // forbidden constructor received -// f_inaccessible = (1U << 31), -// -// // update this when adding new client side flags -// MIN_FIELD = (1U << 31), -//}; -//DEFINE_MTP_CLIENT_FLAGS(MTPDuser) - -enum class MTPDchat_ClientFlag : uint32 { - // forbidden constructor received - f_forbidden = (1U << 31), - - // update this when adding new client side flags - MIN_FIELD = (1U << 31), -}; -DEFINE_MTP_CLIENT_FLAGS(MTPDchat) - enum class MTPDchannel_ClientFlag : uint32 { // forbidden constructor received f_forbidden = (1U << 31), diff --git a/Telegram/SourceFiles/storage/serialize_peer.cpp b/Telegram/SourceFiles/storage/serialize_peer.cpp index e7c29db43..cc30c74db 100644 --- a/Telegram/SourceFiles/storage/serialize_peer.cpp +++ b/Telegram/SourceFiles/storage/serialize_peer.cpp @@ -112,29 +112,33 @@ uint32 peerSize(not_null peer) { uint32 result = sizeof(quint64) + sizeof(quint64) + imageLocationSize(peer->userpicLocation()); - if (peer->isUser()) { - UserData *user = peer->asUser(); - - // first + last + phone + username + access - result += stringSize(user->firstName) + stringSize(user->lastName) + stringSize(user->phone()) + stringSize(user->username) + sizeof(quint64); - - // flags - if (AppVersion >= 9012) { - result += sizeof(qint32); - } - - // onlineTill + contact + botInfoVersion - result += sizeof(qint32) + sizeof(qint32) + sizeof(qint32); - } else if (peer->isChat()) { - ChatData *chat = peer->asChat(); - - // name + count + date + version + admin + old forbidden + left + inviteLink - result += stringSize(chat->name) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(quint32) + stringSize(chat->inviteLink()); - } else if (peer->isChannel()) { - ChannelData *channel = peer->asChannel(); - - // name + access + date + version + old forbidden + flags + inviteLink - result += stringSize(channel->name) + sizeof(quint64) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(quint32) + stringSize(channel->inviteLink()); + if (const auto user = peer->asUser()) { + result += stringSize(user->firstName) + + stringSize(user->lastName) + + stringSize(user->phone()) + + stringSize(user->username) + + sizeof(quint64) // access + + sizeof(qint32) // flags + + sizeof(qint32) // onlineTill + + sizeof(qint32) // contact + + sizeof(qint32); // botInfoVersion + } else if (const auto chat = peer->asChat()) { + result += stringSize(chat->name) + + sizeof(qint32) // count + + sizeof(qint32) // date + + sizeof(qint32) // version + + sizeof(qint32) // creator id 1 + + sizeof(qint32) // creator id 2 + + sizeof(quint32) // flags + + stringSize(chat->inviteLink()); + } else if (const auto channel = peer->asChannel()) { + result += stringSize(channel->name) + + sizeof(quint64) // access + + sizeof(qint32) // date + + sizeof(qint32) // version + + sizeof(qint32) // old forbidden + + sizeof(quint32) // flags + + stringSize(channel->inviteLink()); } return result; } @@ -143,22 +147,17 @@ void writePeer(QDataStream &stream, not_null peer) { stream << SerializePeerId(peer->id) << quint64(peer->userpicPhotoId()); writeImageLocation(stream, peer->userpicLocation()); if (const auto user = peer->asUser()) { + const auto botInlinePlaceholder = user->isBot() + ? user->botInfo->inlinePlaceholder + : QString(); stream << user->firstName << user->lastName << user->phone() << user->username - << quint64(user->accessHash()); - if (AppVersion >= 9012) { - stream << qint32(user->flags()); - } - if (AppVersion >= 9016) { - const auto botInlinePlaceholder = user->isBot() - ? user->botInfo->inlinePlaceholder - : QString(); - stream << botInlinePlaceholder; - } - stream + << quint64(user->accessHash()) + << qint32(user->flags()) + << botInlinePlaceholder << qint32(user->onlineTill) << qint32(user->isContact() ? 1 : 0) << qint32(user->isBot() ? user->botInfo->version : -1); @@ -227,42 +226,45 @@ PeerData *readPeer( userpicAccessHash = access; - const auto showPhone = !user->isServiceUser() - && (user->id != selfId) - && (contact <= 0); - const auto pname = (showPhone && !phone.isEmpty()) - ? App::formatPhone(phone) - : QString(); - if (apply) { + const auto showPhone = !user->isServiceUser() + && (user->id != selfId) + && (contact <= 0); + const auto pname = (showPhone && !phone.isEmpty()) + ? App::formatPhone(phone) + : QString(); + user->setPhone(phone); user->setName(first, last, pname, username); - - using Saved = MTPDuser::Flag; - using Flag = UserDataFlag; - struct Conversion { - Saved saved; - Flag flag; - }; - const auto conversions = { - Conversion{ Saved::f_deleted, Flag::Deleted }, - Conversion{ Saved::f_verified, Flag::Verified }, - Conversion{ Saved::f_scam, Flag::Scam }, - Conversion{ Saved::f_fake, Flag::Fake }, - Conversion{ Saved::f_bot_inline_geo, Flag::BotInlineGeo }, - Conversion{ Saved::f_support, Flag::Support }, - Conversion{ Saved::f_contact, Flag::Contact }, - Conversion{ Saved::f_mutual_contact, Flag::MutualContact }, - }; - auto flagsMask = Flag() | Flag(); - auto flagsSet = Flag() | Flag(); - for (const auto &conversion : conversions) { - flagsMask |= conversion.flag; - if (flags & int(conversion.saved)) { - flagsSet |= conversion.flag; + if (streamAppVersion >= 2008007) { + user->setFlags(UserDataFlags::from_raw(flags)); + } else { + using Saved = MTPDuser::Flag; + using Flag = UserDataFlag; + struct Conversion { + Saved saved; + Flag flag; + }; + const auto conversions = { + Conversion{ Saved::f_deleted, Flag::Deleted }, + Conversion{ Saved::f_verified, Flag::Verified }, + Conversion{ Saved::f_scam, Flag::Scam }, + Conversion{ Saved::f_fake, Flag::Fake }, + Conversion{ Saved::f_bot_inline_geo, Flag::BotInlineGeo }, + Conversion{ Saved::f_support, Flag::Support }, + Conversion{ Saved::f_contact, Flag::Contact }, + Conversion{ Saved::f_mutual_contact, Flag::MutualContact }, + }; + auto flagsMask = Flag() | Flag(); + auto flagsSet = Flag() | Flag(); + for (const auto &conversion : conversions) { + flagsMask |= conversion.flag; + if (flags & int(conversion.saved)) { + flagsSet |= conversion.flag; + } } + user->setFlags((user->flags() & ~flagsMask) | flagsSet); } - user->setFlags((user->flags() & ~flagsMask) | flagsSet); user->setAccessHash(access); user->onlineTill = onlineTill; user->setIsContact(contact == 1); @@ -283,25 +285,19 @@ PeerData *readPeer( } else if (const auto chat = result->asChat()) { QString name, inviteLink; qint32 count, date, version, field1, field2; - quint32 flagsData, flags; - stream >> name >> count >> date >> version >> field1 >> field2 >> flagsData >> inviteLink; - - const auto creator = UserId( - BareId(uint32(field1)) | (BareId(uint32(field2) >> 8) << 32)); - const auto oldForbidden = ((uint32(field2) & 0xFF) == 1); - - if (streamAppVersion >= 9012) { - flags = flagsData; - } else { - // flagsData was haveLeft - flags = (flagsData == 1) - ? MTPDchat::Flags(MTPDchat::Flag::f_left) - : MTPDchat::Flags(0); - } - if (oldForbidden) { - flags |= quint32(MTPDchat_ClientFlag::f_forbidden); - } + quint32 flags; + stream + >> name + >> count + >> date + >> version + >> field1 + >> field2 + >> flags + >> inviteLink; if (apply) { + const auto creator = UserId( + BareId(uint32(field1)) | (BareId(uint32(field2) >> 8) << 32)); chat->setName(name); chat->count = count; chat->date = date; @@ -310,8 +306,49 @@ PeerData *readPeer( // So we don't restore the version field, info is still unknown. chat->setVersion(0); + if (streamAppVersion >= 2008007) { + chat->setFlags(ChatDataFlags::from_raw(flags)); + } else { + const auto oldForbidden = ((uint32(field2) & 0xFF) == 1); + + using Saved = MTPDchat::Flag; + using Flag = ChatDataFlag; + struct Conversion { + Saved saved; + Flag flag; + }; + const auto conversions = { + Conversion{ Saved::f_left, Flag::Left }, + Conversion{ Saved::f_kicked, Flag::Kicked }, + Conversion{ Saved::f_creator, Flag::Creator }, + Conversion{ Saved::f_deactivated, Flag::Deactivated }, + Conversion{ Saved(1U << 31), Flag::Forbidden }, + Conversion{ Saved::f_call_active, Flag::CallActive }, + Conversion{ Saved::f_call_not_empty, Flag::CallNotEmpty }, + }; + + auto flagsMask = Flag() | Flag(); + auto flagsSet = Flag() | Flag(); + if (streamAppVersion >= 9012) { + for (const auto &conversion : conversions) { + flagsMask |= conversion.flag; + if (flags & int(conversion.saved)) { + flagsSet |= conversion.flag; + } + } + } else { + // flags was haveLeft + if (flags == 1) { + flagsSet |= Flag::Left; + } + } + if (oldForbidden) { + flagsSet |= Flag::Forbidden; + } + chat->setFlags((chat->flags() & ~flagsMask) | flagsSet); + } + chat->creator = creator; - chat->setFlags(MTPDchat::Flags::from_raw(flags)); chat->setInviteLink(inviteLink); // #TODO ids