diff --git a/Telegram/Resources/tl/api.tl b/Telegram/Resources/tl/api.tl index 7c4eb9272..364d793de 100644 --- a/Telegram/Resources/tl/api.tl +++ b/Telegram/Resources/tl/api.tl @@ -620,7 +620,7 @@ channelParticipant#15ebac1d user_id:int date:int = ChannelParticipant; channelParticipantSelf#a3289a6d user_id:int inviter_id:int date:int = ChannelParticipant; channelParticipantCreator#447dca4b flags:# user_id:int admin_rights:ChatAdminRights rank:flags.0?string = ChannelParticipant; channelParticipantAdmin#ccbebbaf flags:# can_edit:flags.0?true self:flags.1?true user_id:int inviter_id:flags.1?int promoted_by:int date:int admin_rights:ChatAdminRights rank:flags.2?string = ChannelParticipant; -channelParticipantBanned#1c0facaf flags:# left:flags.0?true user_id:int kicked_by:int date:int banned_rights:ChatBannedRights = ChannelParticipant; +channelParticipantBanned#50a1dfd6 flags:# left:flags.0?true peer:Peer kicked_by:int date:int banned_rights:ChatBannedRights = ChannelParticipant; channelParticipantLeft#c3c6796b user_id:int = ChannelParticipant; channelParticipantsRecent#de3f3c79 = ChannelParticipantsFilter; @@ -632,10 +632,10 @@ channelParticipantsSearch#656ac4b q:string = ChannelParticipantsFilter; channelParticipantsContacts#bb6ae88d q:string = ChannelParticipantsFilter; channelParticipantsMentions#e04b5ceb flags:# q:flags.0?string top_msg_id:flags.1?int = ChannelParticipantsFilter; -channels.channelParticipants#f56ee2a8 count:int participants:Vector users:Vector = channels.ChannelParticipants; +channels.channelParticipants#9ab0feaf count:int participants:Vector chats:Vector users:Vector = channels.ChannelParticipants; channels.channelParticipantsNotModified#f0173fe9 = channels.ChannelParticipants; -channels.channelParticipant#d0d9b163 participant:ChannelParticipant users:Vector = channels.ChannelParticipant; +channels.channelParticipant#dfb80317 participant:ChannelParticipant chats:Vector users:Vector = channels.ChannelParticipant; help.termsOfService#780a0310 flags:# popup:flags.0?true id:DataJSON text:string entities:Vector min_age_confirm:flags.1?int = help.TermsOfService; @@ -1557,7 +1557,7 @@ channels.deleteUserHistory#d10dd71b channel:InputChannel user_id:InputUser = mes channels.reportSpam#fe087810 channel:InputChannel user_id:InputUser id:Vector = Bool; channels.getMessages#ad8c9a23 channel:InputChannel id:Vector = messages.Messages; channels.getParticipants#123e05e9 channel:InputChannel filter:ChannelParticipantsFilter offset:int limit:int hash:int = channels.ChannelParticipants; -channels.getParticipant#546dd7a6 channel:InputChannel user_id:InputUser = channels.ChannelParticipant; +channels.getParticipant#a0ab6cc6 channel:InputChannel participant:InputPeer = channels.ChannelParticipant; channels.getChannels#a7f6bbb id:Vector = messages.Chats; channels.getFullChannel#8736a09 channel:InputChannel = messages.ChatFull; channels.createChannel#3d5fb10f flags:# broadcast:flags.0?true megagroup:flags.1?true for_import:flags.3?true title:string about:string geo_point:flags.2?InputGeoPoint address:flags.2?string = Updates; @@ -1573,7 +1573,7 @@ channels.deleteChannel#c0111fe3 channel:InputChannel = Updates; channels.exportMessageLink#e63fadeb flags:# grouped:flags.0?true thread:flags.1?true channel:InputChannel id:int = ExportedMessageLink; channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates; channels.getAdminedPublicChannels#f8b036af flags:# by_location:flags.0?true check_limit:flags.1?true = messages.Chats; -channels.editBanned#72796912 channel:InputChannel user_id:InputUser banned_rights:ChatBannedRights = Updates; +channels.editBanned#96e6cd81 channel:InputChannel participant:InputPeer banned_rights:ChatBannedRights = Updates; channels.getAdminLog#33ddf480 flags:# channel:InputChannel q:string events_filter:flags.0?ChannelAdminLogEventsFilter admins:flags.1?Vector max_id:long min_id:long limit:int = channels.AdminLogResults; channels.setStickers#ea8ca4f9 channel:InputChannel stickerset:InputStickerSet = Bool; channels.readMessageContents#eab5dc38 channel:InputChannel id:Vector = Bool; @@ -1645,4 +1645,4 @@ stats.getMegagroupStats#dcdf8607 flags:# dark:flags.0?true channel:InputChannel stats.getMessagePublicForwards#5630281b channel:InputChannel msg_id:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages; stats.getMessageStats#b6e0a3f5 flags:# dark:flags.0?true channel:InputChannel msg_id:int = stats.MessageStats; -// LAYER 125 +// LAYER 126 diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 6ee12a8d3..de5d1f8e1 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -1526,8 +1526,11 @@ void ApiWrap::applyLastParticipantsList( MTP_flags(0), MTP_int(0)); for (const auto &p : list) { - const auto userId = p.match([](const auto &data) { - return data.vuser_id().v; + const auto participantId = p.match([]( + const MTPDchannelParticipantBanned &data) { + return peerFromMTP(data.vpeer()); + }, [](const auto &data) { + return peerFromUser(data.vuser_id()); }); const auto adminCanEdit = (p.type() == mtpc_channelParticipantAdmin) ? p.c_channelParticipantAdmin().is_can_edit() @@ -1542,27 +1545,32 @@ void ApiWrap::applyLastParticipantsList( const auto restrictedRights = (p.type() == mtpc_channelParticipantBanned) ? p.c_channelParticipantBanned().vbanned_rights() : emptyRestrictedRights; - if (!userId) { + if (!participantId) { continue; } - auto user = _session->data().user(userId); + const auto participant = _session->data().peer(participantId); + const auto user = participant->asUser(); if (p.type() == mtpc_channelParticipantCreator) { + Assert(user != nullptr); const auto &creator = p.c_channelParticipantCreator(); const auto rank = qs(creator.vrank().value_or_empty()); channel->mgInfo->creator = user; channel->mgInfo->creatorRank = rank; if (!channel->mgInfo->admins.empty()) { - Data::ChannelAdminChanges(channel).add(userId, rank); + Data::ChannelAdminChanges(channel).add( + peerToUser(participantId), + rank); } } - if (!base::contains(channel->mgInfo->lastParticipants, user)) { + if (user + && !base::contains(channel->mgInfo->lastParticipants, user)) { channel->mgInfo->lastParticipants.push_back(user); if (adminRights.c_chatAdminRights().vflags().v) { channel->mgInfo->lastAdmins.emplace( user, MegagroupInfo::Admin{ adminRights, adminCanEdit }); - } else if (restrictedRights.c_chatBannedRights().vflags().v != 0) { + } else if (Data::ChatBannedRightsFlags(restrictedRights) != 0) { channel->mgInfo->lastRestricted.emplace( user, MegagroupInfo::Restricted{ restrictedRights }); @@ -1607,22 +1615,27 @@ void ApiWrap::applyBotsList( auto botStatus = channel->mgInfo->botStatus; auto keyboardBotFound = !history || !history->lastKeyboardFrom; for (const auto &p : list) { - const auto userId = p.match([](const auto &data) { - return data.vuser_id().v; + const auto participantId = p.match([]( + const MTPDchannelParticipantBanned &data) { + return peerFromMTP(data.vpeer()); + }, [](const auto &data) { + return peerFromUser(data.vuser_id()); }); - if (!userId) { + if (!participantId) { continue; } - auto user = _session->data().user(userId); - if (user->isBot()) { + const auto participant = _session->data().peer(participantId); + const auto user = participant->asUser(); + if (user && user->isBot()) { channel->mgInfo->bots.insert(user); botStatus = 2;// (botStatus > 0/* || !i.key()->botInfo->readsAllHistory*/) ? 2 : 1; if (!user->botInfo->inited) { needBotsInfos = true; } } - if (!keyboardBotFound && user->id == history->lastKeyboardFrom) { + if (!keyboardBotFound + && participant->id == history->lastKeyboardFrom) { keyboardBotFound = true; } } @@ -1657,7 +1670,7 @@ void ApiWrap::requestSelfParticipant(not_null channel) { _selfParticipantRequests.emplace(channel); request(MTPchannels_GetParticipant( channel->inputChannel, - MTP_inputUserSelf() + MTP_inputPeerSelf() )).done([=](const MTPchannels_ChannelParticipant &result) { _selfParticipantRequests.erase(channel); result.match([&](const MTPDchannels_channelParticipant &data) { @@ -1698,11 +1711,13 @@ void ApiWrap::requestSelfParticipant(not_null channel) { void ApiWrap::kickParticipant( not_null chat, - not_null user) { + not_null participant) { + Expects(participant->isUser()); + request(MTPmessages_DeleteChatUser( MTP_flags(0), chat->inputChat, - user->inputUser + participant->asUser()->inputUser )).done([=](const MTPUpdates &result) { applyUpdates(result); }).send(); @@ -1710,21 +1725,21 @@ void ApiWrap::kickParticipant( void ApiWrap::kickParticipant( not_null channel, - not_null user, + not_null participant, const MTPChatBannedRights ¤tRights) { - const auto kick = KickRequest(channel, user); + const auto kick = KickRequest(channel, participant); if (_kickRequests.contains(kick)) return; const auto rights = ChannelData::KickedRestrictedRights(); const auto requestId = request(MTPchannels_EditBanned( channel->inputChannel, - user->inputUser, + participant->input, rights )).done([=](const MTPUpdates &result) { applyUpdates(result); - _kickRequests.remove(KickRequest(channel, user)); - channel->applyEditBanned(user, currentRights, rights); + _kickRequests.remove(KickRequest(channel, participant)); + channel->applyEditBanned(participant, currentRights, rights); }).fail([this, kick](const MTP::Error &error) { _kickRequests.remove(kick); }).send(); @@ -1734,20 +1749,20 @@ void ApiWrap::kickParticipant( void ApiWrap::unblockParticipant( not_null channel, - not_null user) { - const auto kick = KickRequest(channel, user); + not_null participant) { + const auto kick = KickRequest(channel, participant); if (_kickRequests.contains(kick)) { return; } const auto requestId = request(MTPchannels_EditBanned( channel->inputChannel, - user->inputUser, + participant->input, MTP_chatBannedRights(MTP_flags(0), MTP_int(0)) )).done([=](const MTPUpdates &result) { applyUpdates(result); - _kickRequests.remove(KickRequest(channel, user)); + _kickRequests.remove(KickRequest(channel, participant)); if (channel->kickedCount() > 0) { channel->setKickedCount(channel->kickedCount() - 1); } else { @@ -3183,12 +3198,18 @@ void ApiWrap::refreshChannelAdmins( const QVector &participants) { Data::ChannelAdminChanges changes(channel); for (const auto &p : participants) { - const auto userId = p.match([](const auto &data) { - return data.vuser_id().v; + const auto participantId = p.match([]( + const MTPDchannelParticipantBanned &data) { + return peerFromMTP(data.vpeer()); + }, [](const auto &data) { + return peerFromUser(data.vuser_id()); }); + const auto userId = peerToUser(participantId); p.match([&](const MTPDchannelParticipantAdmin &data) { + Assert(peerIsUser(participantId)); changes.add(userId, qs(data.vrank().value_or_empty())); }, [&](const MTPDchannelParticipantCreator &data) { + Assert(peerIsUser(participantId)); const auto rank = qs(data.vrank().value_or_empty()); if (const auto info = channel->mgInfo.get()) { info->creator = channel->owner().userLoaded(userId); @@ -3196,7 +3217,9 @@ void ApiWrap::refreshChannelAdmins( } changes.add(userId, rank); }, [&](const auto &data) { - changes.remove(userId); + if (userId) { + changes.remove(userId); + } }); } } diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 4d59c1c35..eadb14858 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -249,14 +249,16 @@ public: void markMediaRead(not_null item); void requestSelfParticipant(not_null channel); - void kickParticipant(not_null chat, not_null user); + void kickParticipant( + not_null chat, + not_null participant); void kickParticipant( not_null channel, - not_null user, + not_null participant, const MTPChatBannedRights ¤tRights); void unblockParticipant( not_null channel, - not_null user); + not_null participant); void deleteAllFromUser( not_null channel, not_null from); @@ -657,7 +659,7 @@ private: using KickRequest = std::pair< not_null, - not_null>; + not_null>; base::flat_map _kickRequests; base::flat_set> _selfParticipantRequests; diff --git a/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp b/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp index 4a37d1b93..e6abb774e 100644 --- a/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp @@ -467,8 +467,9 @@ void AddSpecialBoxController::loadMoreRows() { int availableCount, const QVector &list) { for (const auto &data : list) { - if (const auto user = _additional.applyParticipant(data)) { - appendRow(user); + if (const auto participant = _additional.applyParticipant( + data)) { + appendRow(participant); } } if (const auto size = list.size()) { @@ -502,9 +503,9 @@ void AddSpecialBoxController::rowClicked(not_null row) { template bool AddSpecialBoxController::checkInfoLoaded( - not_null user, + not_null participant, Callback callback) { - if (_additional.infoLoaded(user)) { + if (_additional.infoLoaded(participant)) { return true; } @@ -512,16 +513,15 @@ bool AddSpecialBoxController::checkInfoLoaded( const auto channel = _peer->asChannel(); _api.request(MTPchannels_GetParticipant( channel->inputChannel, - user->inputUser + participant->input )).done([=](const MTPchannels_ChannelParticipant &result) { - Expects(result.type() == mtpc_channels_channelParticipant); - - const auto &participant = result.c_channels_channelParticipant(); - channel->owner().processUsers(participant.vusers()); - _additional.applyParticipant(participant.vparticipant()); + result.match([&](const MTPDchannels_channelParticipant &data) { + channel->owner().processUsers(data.vusers()); + _additional.applyParticipant(data.vparticipant()); + }); callback(); }).fail([=](const MTP::Error &error) { - _additional.setExternal(user); + _additional.setExternal(participant); callback(); }).send(); return false; @@ -732,7 +732,7 @@ void AddSpecialBoxController::showRestricted( user, _additional.adminRights(user).has_value(), currentRights); - if (_additional.canRestrictUser(user)) { + if (_additional.canRestrictParticipant(user)) { const auto done = crl::guard(this, [=]( const MTPChatBannedRights &newRights) { editRestrictedDone(user, newRights); @@ -749,50 +749,61 @@ void AddSpecialBoxController::showRestricted( } void AddSpecialBoxController::editRestrictedDone( - not_null user, + not_null participant, const MTPChatBannedRights &rights) { if (_editParticipantBox) { _editParticipantBox->closeBox(); } const auto date = base::unixtime::now(); // Incorrect, but ignored. - if (rights.c_chatBannedRights().vflags().v == 0) { - _additional.applyParticipant(MTP_channelParticipant( - MTP_int(user->bareId()), - MTP_int(date))); + if (Data::ChatBannedRightsFlags(rights) == 0) { + if (const auto user = participant->asUser()) { + _additional.applyParticipant(MTP_channelParticipant( + MTP_int(user->bareId()), + MTP_int(date))); + } else { + _additional.setExternal(participant); + } } else { - const auto kicked = rights.c_chatBannedRights().is_view_messages(); - const auto alreadyRestrictedBy = _additional.restrictedBy(user); + const auto kicked = Data::ChatBannedRightsFlags(rights) + & ChatRestriction::f_view_messages; + const auto alreadyRestrictedBy = _additional.restrictedBy( + participant); _additional.applyParticipant(MTP_channelParticipantBanned( MTP_flags(kicked ? MTPDchannelParticipantBanned::Flag::f_left : MTPDchannelParticipantBanned::Flag(0)), - MTP_int(user->bareId()), + (participant->isUser() + ? MTP_peerUser(MTP_int(participant->bareId())) + : participant->isChat() + ? MTP_peerChat(MTP_int(participant->bareId())) + : MTP_peerChannel(MTP_int(participant->bareId()))), MTP_int(alreadyRestrictedBy ? alreadyRestrictedBy->bareId() - : user->session().userId()), + : participant->session().userId()), MTP_int(date), rights)); } if (const auto callback = _bannedDoneCallback) { - callback(user, rights); + callback(participant, rights); } } void AddSpecialBoxController::kickUser( - not_null user, + not_null participant, bool sure) { - if (!checkInfoLoaded(user, [=] { kickUser(user); })) { + if (!checkInfoLoaded(participant, [=] { kickUser(participant); })) { return; } const auto kickUserSure = crl::guard(this, [=] { - kickUser(user, true); + kickUser(participant, true); }); // Check restrictions. - if (_additional.adminRights(user).has_value() - || _additional.isCreator(user)) { + const auto user = participant->asUser(); + if (user && (_additional.adminRights(user).has_value() + || (_additional.isCreator(user)))) { // The user is an admin or creator. if (!_additional.isCreator(user) && _additional.canEditAdmin(user)) { if (!sure) { @@ -818,14 +829,14 @@ void AddSpecialBoxController::kickUser( : tr::lng_profile_sure_kick_channel)( tr::now, lt_user, - user->name); + participant->name); _editBox = Ui::show( Box(text, kickUserSure), Ui::LayerOption::KeepOther); return; } - const auto restrictedRights = _additional.restrictedRights(user); + const auto restrictedRights = _additional.restrictedRights(participant); const auto currentRights = restrictedRights ? *restrictedRights : MTPChatBannedRights(MTP_chatBannedRights( @@ -834,21 +845,25 @@ void AddSpecialBoxController::kickUser( const auto done = crl::guard(this, [=]( const MTPChatBannedRights &newRights) { - editRestrictedDone(user, newRights); + editRestrictedDone(participant, newRights); }); const auto fail = crl::guard(this, [=] { _editBox = nullptr; }); - const auto callback = SaveRestrictedCallback(_peer, user, done, fail); + const auto callback = SaveRestrictedCallback( + _peer, + participant, + done, + fail); callback(currentRights, ChannelData::KickedRestrictedRights()); } -bool AddSpecialBoxController::appendRow(not_null user) { - if (delegate()->peerListFindRow(user->id) - || (_excludeSelf && user->isSelf())) { +bool AddSpecialBoxController::appendRow(not_null participant) { + if (delegate()->peerListFindRow(participant->id) + || (_excludeSelf && participant->isSelf())) { return false; } - delegate()->peerListAppendRow(createRow(user)); + delegate()->peerListAppendRow(createRow(participant)); return true; } @@ -861,8 +876,8 @@ bool AddSpecialBoxController::prependRow(not_null user) { } std::unique_ptr AddSpecialBoxController::createRow( - not_null user) const { - return std::make_unique(user); + not_null participant) const { + return std::make_unique(participant); } AddSpecialBoxSearchController::AddSpecialBoxSearchController( diff --git a/Telegram/SourceFiles/boxes/peers/add_participants_box.h b/Telegram/SourceFiles/boxes/peers/add_participants_box.h index ee626f161..803860601 100644 --- a/Telegram/SourceFiles/boxes/peers/add_participants_box.h +++ b/Telegram/SourceFiles/boxes/peers/add_participants_box.h @@ -80,7 +80,7 @@ public: const MTPChatAdminRights &adminRights, const QString &rank)>; using BannedDoneCallback = Fn user, + not_null participant, const MTPChatBannedRights &bannedRights)>; AddSpecialBoxController( not_null peer, @@ -101,7 +101,7 @@ public: private: template - bool checkInfoLoaded(not_null user, Callback callback); + bool checkInfoLoaded(not_null participant, Callback callback); void prepareChatRows(not_null chat); void rebuildChatRows(not_null chat); @@ -113,12 +113,13 @@ private: const QString &rank); void showRestricted(not_null user, bool sure = false); void editRestrictedDone( - not_null user, + not_null participant, const MTPChatBannedRights &rights); - void kickUser(not_null user, bool sure = false); - bool appendRow(not_null user); + void kickUser(not_null participant, bool sure = false); + bool appendRow(not_null participant); bool prependRow(not_null user); - std::unique_ptr createRow(not_null user) const; + std::unique_ptr createRow( + not_null participant) const; void subscribeToMigration(); void migrate(not_null chat, not_null channel); diff --git a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp index d68fba011..e8c1d55df 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp @@ -612,11 +612,11 @@ void EditRestrictedBox::prepare() { const auto defaultRestrictions = chat ? chat->defaultRestrictions() : channel->defaultRestrictions(); - const auto prepareRights = _oldRights.c_chatBannedRights().vflags().v + const auto prepareRights = Data::ChatBannedRightsFlags(_oldRights) ? _oldRights : defaultRights(); const auto prepareFlags = FixDependentRestrictions( - prepareRights.c_chatBannedRights().vflags().v + Data::ChatBannedRightsFlags(prepareRights) | defaultRestrictions | ((channel && channel->isPublic()) ? (Flag::f_change_info | Flag::f_pin_messages) @@ -647,7 +647,7 @@ void EditRestrictedBox::prepare() { disabledMessages); addControl(std::move(checkboxes), QMargins()); - _until = prepareRights.c_chatBannedRights().vuntil_date().v; + _until = Data::ChatBannedRightsUntilDate(prepareRights); addControl(object_ptr(this), st::rightsUntilMargin); addControl( object_ptr( @@ -767,7 +767,7 @@ void EditRestrictedBox::createUntilVariants() { } }; auto addCurrentVariant = [&](TimeId from, TimeId to) { - auto oldUntil = _oldRights.c_chatBannedRights().vuntil_date().v; + auto oldUntil = Data::ChatBannedRightsUntilDate(_oldRights); if (oldUntil < _until) { addCustomVariant(oldUntil, from, to); } diff --git a/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp index 6ec9063d3..f963b439f 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp @@ -146,18 +146,18 @@ void SaveChannelAdmin( void SaveChannelRestriction( not_null channel, - not_null user, + not_null participant, const MTPChatBannedRights &oldRights, const MTPChatBannedRights &newRights, Fn onDone, Fn onFail) { channel->session().api().request(MTPchannels_EditBanned( channel->inputChannel, - user->inputUser, + participant->input, newRights )).done([=](const MTPUpdates &result) { channel->session().api().applyUpdates(result); - channel->applyEditBanned(user, oldRights, newRights); + channel->applyEditBanned(participant, oldRights, newRights); if (onDone) { onDone(); } @@ -243,7 +243,7 @@ Fn SaveRestrictedCallback( not_null peer, - not_null user, + not_null participant, Fn onDone, Fn onFail) { return [=]( @@ -253,19 +253,21 @@ Fn channel) { SaveChannelRestriction( channel, - user, + participant, oldRights, newRights, done, onFail); }; if (const auto chat = peer->asChatNotMigrated()) { - const auto flags = newRights.match([]( - const MTPDchatBannedRights &data) { - return data.vflags().v; - }); - if (flags & MTPDchatBannedRights::Flag::f_view_messages) { - SaveChatParticipantKick(chat, user, done, onFail); + const auto flags = Data::ChatBannedRightsFlags(newRights); + if (participant->isUser() + && (flags & MTPDchatBannedRights::Flag::f_view_messages)) { + SaveChatParticipantKick( + chat, + participant->asUser(), + done, + onFail); } else if (!flags) { done(); } else { @@ -313,9 +315,9 @@ ParticipantsAdditionalData::ParticipantsAdditionalData( } bool ParticipantsAdditionalData::infoLoaded( - not_null user) const { + not_null participant) const { return _peer->isChat() - || (_infoNotLoaded.find(user) == end(_infoNotLoaded)); + || (_infoNotLoaded.find(participant) == end(_infoNotLoaded)); } bool ParticipantsAdditionalData::canEditAdmin( @@ -342,9 +344,10 @@ bool ParticipantsAdditionalData::canAddOrEditAdmin( Unexpected("Peer in ParticipantsAdditionalData::canAddOrEditAdmin."); } -bool ParticipantsAdditionalData::canRestrictUser( - not_null user) const { - if (!canEditAdmin(user) || user->isSelf()) { +bool ParticipantsAdditionalData::canRestrictParticipant( + not_null participant) const { + const auto user = participant->asUser(); + if (user && (!canEditAdmin(user) || user->isSelf())) { return false; } else if (const auto chat = _peer->asChat()) { return chat->canBanMembers(); @@ -354,12 +357,14 @@ bool ParticipantsAdditionalData::canRestrictUser( Unexpected("Peer in ParticipantsAdditionalData::canRestrictUser."); } -bool ParticipantsAdditionalData::canRemoveUser( - not_null user) const { - if (canRestrictUser(user)) { +bool ParticipantsAdditionalData::canRemoveParticipant( + not_null participant) const { + const auto user = participant->asUser(); + if (canRestrictParticipant(participant)) { return true; } else if (const auto chat = _peer->asChat()) { - return !user->isSelf() + return user + && !user->isSelf() && chat->invitedByMe.contains(user) && (chat->amCreator() || !_admins.contains(user)); } @@ -388,12 +393,12 @@ QString ParticipantsAdditionalData::adminRank( } auto ParticipantsAdditionalData::restrictedRights( - not_null user) const + not_null participant) const -> std::optional { if (_peer->isChat()) { return std::nullopt; } - const auto i = _restrictedRights.find(user); + const auto i = _restrictedRights.find(participant); return (i != end(_restrictedRights)) ? std::make_optional(i->second) : std::nullopt; @@ -404,16 +409,18 @@ bool ParticipantsAdditionalData::isCreator(not_null user) const { } bool ParticipantsAdditionalData::isExternal( - not_null user) const { + not_null participant) const { return _peer->isChat() - ? !_members.contains(user) - : _external.find(user) != end(_external); + ? (participant->isUser() + && !_members.contains(participant->asUser())) + : _external.find(participant) != end(_external); } -bool ParticipantsAdditionalData::isKicked(not_null user) const { +bool ParticipantsAdditionalData::isKicked( + not_null participant) const { return _peer->isChat() ? false - : _kicked.find(user) != end(_kicked); + : _kicked.find(participant) != end(_kicked); } UserData *ParticipantsAdditionalData::adminPromotedBy( @@ -426,29 +433,41 @@ UserData *ParticipantsAdditionalData::adminPromotedBy( } UserData *ParticipantsAdditionalData::restrictedBy( - not_null user) const { + not_null participant) const { if (_peer->isChat()) { return nullptr; } - const auto i = _restrictedBy.find(user); + const auto i = _restrictedBy.find(participant); return (i != end(_restrictedBy)) ? i->second.get() : nullptr; } -void ParticipantsAdditionalData::setExternal(not_null user) { - _infoNotLoaded.erase(user); - _external.emplace(user); +void ParticipantsAdditionalData::setExternal( + not_null participant) { + if (const auto user = participant->asUser()) { + _adminRights.erase(user); + _adminCanEdit.erase(user); + _adminPromotedBy.erase(user); + _admins.erase(user); + } + _restrictedRights.erase(participant); + _kicked.erase(participant); + _restrictedBy.erase(participant); + _infoNotLoaded.erase(participant); + _external.emplace(participant); } -void ParticipantsAdditionalData::checkForLoaded(not_null user) { +void ParticipantsAdditionalData::checkForLoaded( + not_null participant) { const auto contains = [](const auto &map, const auto &value) { return map.find(value) != map.end(); }; - if (_creator != user - && !contains(_adminRights, user) - && !contains(_restrictedRights, user) - && !contains(_external, user) - && !contains(_kicked, user)) { - _infoNotLoaded.emplace(user); + const auto user = participant->asUser(); + if (!(user && _creator == user) + && !(user && contains(_adminRights, user)) + && !contains(_restrictedRights, participant) + && !contains(_external, participant) + && !contains(_kicked, participant)) { + _infoNotLoaded.emplace(participant); } } @@ -510,15 +529,15 @@ void ParticipantsAdditionalData::fillFromChannel( } } -UserData *ParticipantsAdditionalData::applyParticipant( +PeerData *ParticipantsAdditionalData::applyParticipant( const MTPChannelParticipant &data) { return applyParticipant(data, _role); } -UserData *ParticipantsAdditionalData::applyParticipant( +PeerData *ParticipantsAdditionalData::applyParticipant( const MTPChannelParticipant &data, Role overrideRole) { - const auto logBad = [&]() -> UserData* { + const auto logBad = [&]() -> PeerData* { LOG(("API Error: Bad participant type %1 got " "while requesting for participants, role: %2" ).arg(data.type() @@ -526,27 +545,28 @@ UserData *ParticipantsAdditionalData::applyParticipant( return nullptr; }; - return data.match([&](const MTPDchannelParticipantCreator &data) { + return data.match([&]( + const MTPDchannelParticipantCreator &data) -> PeerData* { if (overrideRole != Role::Profile && overrideRole != Role::Members && overrideRole != Role::Admins) { return logBad(); } return applyCreator(data); - }, [&](const MTPDchannelParticipantAdmin &data) { + }, [&](const MTPDchannelParticipantAdmin &data) -> PeerData* { if (overrideRole != Role::Profile && overrideRole != Role::Members && overrideRole != Role::Admins) { return logBad(); } return applyAdmin(data); - }, [&](const MTPDchannelParticipantSelf &data) { + }, [&](const MTPDchannelParticipantSelf &data) -> PeerData* { if (overrideRole != Role::Profile && overrideRole != Role::Members) { return logBad(); } return applyRegular(data.vuser_id()); - }, [&](const MTPDchannelParticipant &data) { + }, [&](const MTPDchannelParticipant &data) -> PeerData* { if (overrideRole != Role::Profile && overrideRole != Role::Members) { return logBad(); @@ -645,32 +665,35 @@ UserData *ParticipantsAdditionalData::applyRegular(MTPint userId) { return user; } -UserData *ParticipantsAdditionalData::applyBanned( +PeerData *ParticipantsAdditionalData::applyBanned( const MTPDchannelParticipantBanned &data) { - const auto user = _peer->owner().userLoaded(data.vuser_id().v); - if (!user) { + const auto participant = _peer->owner().peerLoaded( + peerFromMTP(data.vpeer())); + if (!participant) { return nullptr; } - _infoNotLoaded.erase(user); - _adminRights.erase(user); - _adminCanEdit.erase(user); - _adminPromotedBy.erase(user); - if (data.is_left()) { - _kicked.emplace(user); - } else { - _kicked.erase(user); + _infoNotLoaded.erase(participant); + if (const auto user = participant->asUser()) { + _adminRights.erase(user); + _adminCanEdit.erase(user); + _adminPromotedBy.erase(user); } - _restrictedRights[user] = data.vbanned_rights(); + if (data.is_left()) { + _kicked.emplace(participant); + } else { + _kicked.erase(participant); + } + _restrictedRights[participant] = data.vbanned_rights(); if (const auto by = _peer->owner().userLoaded(data.vkicked_by().v)) { - const auto i = _restrictedBy.find(user); + const auto i = _restrictedBy.find(participant); if (i == _restrictedBy.end()) { - _restrictedBy.emplace(user, by); + _restrictedBy.emplace(participant, by); } else { i->second = by; } } - return user; + return participant; } void ParticipantsAdditionalData::migrate( @@ -922,9 +945,9 @@ void ParticipantsBoxController::addNewItem() { editAdminDone(user, rights, rank); }); const auto restrictedDone = crl::guard(this, [=]( - not_null user, + not_null participant, const MTPChatBannedRights &rights) { - editRestrictedDone(user, rights); + editRestrictedDone(participant, rights); }); const auto initBox = [](not_null box) { box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); @@ -1316,8 +1339,9 @@ void ParticipantsBoxController::loadMoreRows() { int availableCount, const QVector &list) { for (const auto &data : list) { - if (const auto user = _additional.applyParticipant(data)) { - appendRow(user); + if (const auto participant = _additional.applyParticipant( + data)) { + appendRow(participant); } } if (const auto size = list.size()) { @@ -1398,17 +1422,18 @@ bool ParticipantsBoxController::feedMegagroupLastParticipants() { } void ParticipantsBoxController::rowClicked(not_null row) { - Expects(row->peer()->isUser()); - - const auto user = row->peer()->asUser(); + const auto participant = row->peer(); + const auto user = participant->asUser(); if (_role == Role::Admins) { + Assert(user != nullptr); showAdmin(user); } else if (_role == Role::Restricted - && (_peer->isChat() || _peer->isMegagroup())) { + && (_peer->isChat() || _peer->isMegagroup()) + && user) { showRestricted(user); } else { Assert(_navigation != nullptr); - _navigation->showPeerInfo(user); + _navigation->showPeerInfo(participant); } } @@ -1433,28 +1458,30 @@ base::unique_qptr ParticipantsBoxController::rowContextMenu( const auto chat = _peer->asChat(); const auto channel = _peer->asChannel(); - const auto user = row->peer()->asUser(); + const auto participant = row->peer(); + const auto user = participant->asUser(); auto result = base::make_unique_q(parent); if (_navigation) { result->addAction( tr::lng_context_view_profile(tr::now), - crl::guard(this, [=] { _navigation->showPeerInfo(user); })); + crl::guard(this, [=] { + _navigation->showPeerInfo(participant); })); } if (_role == Role::Kicked) { if (_peer->isMegagroup() - && _additional.canRestrictUser(user)) { - if (channel->canAddMembers()) { + && _additional.canRestrictParticipant(participant)) { + if (user && channel->canAddMembers()) { result->addAction( tr::lng_context_add_to_group(tr::now), crl::guard(this, [=] { unkickMember(user); })); } result->addAction( tr::lng_profile_delete_removed(tr::now), - crl::guard(this, [=] { removeKickedWithRow(user); })); + crl::guard(this, [=] { removeKickedWithRow(participant); })); } return result; } - if (_additional.canAddOrEditAdmin(user)) { + if (user && _additional.canAddOrEditAdmin(user)) { const auto isAdmin = _additional.isCreator(user) || _additional.adminRights(user).has_value(); result->addAction( @@ -1463,7 +1490,7 @@ base::unique_qptr ParticipantsBoxController::rowContextMenu( : tr::lng_context_promote_admin)(tr::now), crl::guard(this, [=] { showAdmin(user); })); } - if (_additional.canRestrictUser(user)) { + if (_additional.canRestrictParticipant(participant)) { const auto canRestrictWithoutKick = [&] { if (const auto chat = _peer->asChat()) { return chat->amCreator(); @@ -1476,8 +1503,8 @@ base::unique_qptr ParticipantsBoxController::rowContextMenu( crl::guard(this, [=] { showRestricted(user); })); } } - if (_additional.canRemoveUser(user)) { - if (!_additional.isKicked(user)) { + if (_additional.canRemoveParticipant(participant)) { + if (!_additional.isKicked(participant)) { const auto isGroup = _peer->isChat() || _peer->isMegagroup(); result->addAction( (isGroup @@ -1580,7 +1607,7 @@ void ParticipantsBoxController::showRestricted(not_null user) { currentRights); const auto chat = _peer->asChat(); const auto channel = _peer->asChannel(); - if (_additional.canRestrictUser(user)) { + if (_additional.canRestrictParticipant(user)) { const auto done = crl::guard(this, [=]( const MTPChatBannedRights &newRights) { editRestrictedDone(user, newRights); @@ -1597,29 +1624,40 @@ void ParticipantsBoxController::showRestricted(not_null user) { } void ParticipantsBoxController::editRestrictedDone( - not_null user, + not_null participant, const MTPChatBannedRights &rights) { _addBox = nullptr; if (_editParticipantBox) { _editParticipantBox->closeBox(); } + const auto user = participant->asUser(); const auto date = base::unixtime::now(); // Incorrect, but ignored. - if (rights.c_chatBannedRights().vflags().v == 0) { - _additional.applyParticipant(MTP_channelParticipant( - MTP_int(user->bareId()), - MTP_int(date))); + if (Data::ChatBannedRightsFlags(rights) == 0) { + if (user) { + _additional.applyParticipant(MTP_channelParticipant( + MTP_int(user->bareId()), + MTP_int(date))); + } else { + _additional.setExternal(participant); + } if (_role == Role::Kicked || _role == Role::Restricted) { - removeRow(user); + removeRow(participant); } } else { - const auto kicked = rights.c_chatBannedRights().is_view_messages(); - const auto alreadyRestrictedBy = _additional.restrictedBy(user); + const auto kicked = Data::ChatBannedRightsFlags(rights) + & ChatRestriction::f_view_messages; + const auto alreadyRestrictedBy = _additional.restrictedBy( + participant); _additional.applyParticipant(MTP_channelParticipantBanned( MTP_flags(kicked ? MTPDchannelParticipantBanned::Flag::f_left : MTPDchannelParticipantBanned::Flag(0)), - MTP_int(user->bareId()), + (participant->isUser() + ? MTP_peerUser(MTP_int(participant->bareId())) + : participant->isChat() + ? MTP_peerChat(MTP_int(participant->bareId())) + : MTP_peerChannel(MTP_int(participant->bareId()))), MTP_int(alreadyRestrictedBy ? alreadyRestrictedBy->bareId() : user->session().userId()), @@ -1647,18 +1685,19 @@ void ParticipantsBoxController::editRestrictedDone( delegate()->peerListRefreshRows(); } -void ParticipantsBoxController::kickMember(not_null user) { +void ParticipantsBoxController::kickMember(not_null participant) { + const auto user = participant->asUser(); const auto text = ((_peer->isChat() || _peer->isMegagroup()) ? tr::lng_profile_sure_kick : tr::lng_profile_sure_kick_channel)( tr::now, lt_user, - user->firstName); + user ? user->firstName : participant->name); _editBox = Ui::show( Box( text, tr::lng_box_remove(tr::now), - crl::guard(this, [=] { kickMemberSure(user); })), + crl::guard(this, [=] { kickMemberSure(participant); })), Ui::LayerOption::KeepOther); } @@ -1671,25 +1710,26 @@ void ParticipantsBoxController::unkickMember(not_null user) { _peer->session().api().addChatParticipants(_peer, { 1, user }); } -void ParticipantsBoxController::kickMemberSure(not_null user) { +void ParticipantsBoxController::kickMemberSure( + not_null participant) { _editBox = nullptr; - const auto restrictedRights = _additional.restrictedRights(user); + const auto restrictedRights = _additional.restrictedRights(participant); const auto currentRights = restrictedRights ? *restrictedRights : MTPChatBannedRights(MTP_chatBannedRights( MTP_flags(0), MTP_int(0))); - if (const auto row = delegate()->peerListFindRow(user->id)) { + if (const auto row = delegate()->peerListFindRow(participant->id)) { delegate()->peerListRemoveRow(row); delegate()->peerListRefreshRows(); } auto &session = _peer->session(); if (const auto chat = _peer->asChat()) { - session.api().kickParticipant(chat, user); + session.api().kickParticipant(chat, participant); } else if (const auto channel = _peer->asChannel()) { - session.api().kickParticipant(channel, user, currentRights); + session.api().kickParticipant(channel, participant, currentRights); } } @@ -1730,36 +1770,37 @@ void ParticipantsBoxController::removeAdminSure(not_null user) { } void ParticipantsBoxController::removeKickedWithRow( - not_null user) { - if (const auto row = delegate()->peerListFindRow(user->id)) { - removeKicked(row, user); + not_null participant) { + if (const auto row = delegate()->peerListFindRow(participant->id)) { + removeKicked(row, participant); } else { - removeKicked(user); + removeKicked(participant); } } -void ParticipantsBoxController::removeKicked(not_null user) { +void ParticipantsBoxController::removeKicked( + not_null participant) { if (const auto channel = _peer->asChannel()) { - channel->session().api().unblockParticipant(channel, user); + channel->session().api().unblockParticipant(channel, participant); } } void ParticipantsBoxController::removeKicked( not_null row, - not_null user) { + not_null participant) { delegate()->peerListRemoveRow(row); if (_role != Role::Kicked && !delegate()->peerListFullRowsCount()) { setDescriptionText(tr::lng_blocked_list_not_found(tr::now)); } delegate()->peerListRefreshRows(); - removeKicked(user); + removeKicked(participant); } -bool ParticipantsBoxController::appendRow(not_null user) { - if (delegate()->peerListFindRow(user->id)) { - recomputeTypeFor(user); +bool ParticipantsBoxController::appendRow(not_null participant) { + if (delegate()->peerListFindRow(participant->id)) { + recomputeTypeFor(participant); return false; - } else if (auto row = createRow(user)) { + } else if (auto row = createRow(participant)) { delegate()->peerListAppendRow(std::move(row)); if (_role != Role::Kicked) { setDescriptionText(QString()); @@ -1788,8 +1829,8 @@ bool ParticipantsBoxController::prependRow(not_null user) { return false; } -bool ParticipantsBoxController::removeRow(not_null user) { - if (auto row = delegate()->peerListFindRow(user->id)) { +bool ParticipantsBoxController::removeRow(not_null participant) { + if (auto row = delegate()->peerListFindRow(participant->id)) { if (_role == Role::Admins) { // Perhaps we are removing an admin from search results. row->setCustomStatus(tr::lng_channel_admin_status_not_admin(tr::now)); @@ -1807,24 +1848,28 @@ bool ParticipantsBoxController::removeRow(not_null user) { } std::unique_ptr ParticipantsBoxController::createRow( - not_null user) const { + not_null participant) const { + const auto user = participant->asUser(); if (_role == Role::Profile) { + Assert(user != nullptr); return std::make_unique(user, computeType(user)); } const auto chat = _peer->asChat(); const auto channel = _peer->asChannel(); - auto row = std::make_unique(user); + auto row = std::make_unique(participant); refreshCustomStatus(row.get()); if (_role == Role::Admins + && user && !_additional.isCreator(user) && _additional.adminRights(user).has_value() && _additional.canEditAdmin(user)) { row->setActionLink(tr::lng_profile_kick(tr::now)); } else if (_role == Role::Kicked || _role == Role::Restricted) { - if (_additional.canRestrictUser(user)) { + if (_additional.canRestrictParticipant(participant)) { row->setActionLink(tr::lng_profile_delete_removed(tr::now)); } } else if (_role == Role::Members) { + Assert(user != nullptr); if ((chat ? chat->canBanMembers() : channel->canBanMembers()) && !_additional.isCreator(user) && (!_additional.adminRights(user) @@ -1842,31 +1887,34 @@ std::unique_ptr ParticipantsBoxController::createRow( } auto ParticipantsBoxController::computeType( - not_null user) const -> Type { + not_null participant) const -> Type { + const auto user = participant->asUser(); auto result = Type(); - result.rights = _additional.isCreator(user) + result.rights = (user && _additional.isCreator(user)) ? Rights::Creator - : _additional.adminRights(user).has_value() + : (user && _additional.adminRights(user).has_value()) ? Rights::Admin : Rights::Normal; - result.canRemove = _additional.canRemoveUser(user); + result.canRemove = _additional.canRemoveParticipant(participant); return result; } void ParticipantsBoxController::recomputeTypeFor( - not_null user) { + not_null participant) { if (_role != Role::Profile) { return; } - if (const auto row = delegate()->peerListFindRow(user->id)) { - static_cast(row)->setType(computeType(user)); + if (const auto row = delegate()->peerListFindRow(participant->id)) { + static_cast(row)->setType(computeType(participant)); } } void ParticipantsBoxController::refreshCustomStatus( not_null row) const { - const auto user = row->peer()->asUser(); + const auto participant = row->peer(); + const auto user = participant->asUser(); if (_role == Role::Admins) { + Assert(user != nullptr); if (const auto by = _additional.adminPromotedBy(user)) { row->setCustomStatus(tr::lng_channel_admin_status_promoted_by( tr::now, @@ -1882,7 +1930,7 @@ void ParticipantsBoxController::refreshCustomStatus( } } } else if (_role == Role::Kicked || _role == Role::Restricted) { - const auto by = _additional.restrictedBy(user); + const auto by = _additional.restrictedBy(participant); row->setCustomStatus((_role == Role::Kicked ? tr::lng_channel_banned_status_removed_by : tr::lng_channel_banned_status_restricted_by)( diff --git a/Telegram/SourceFiles/boxes/peers/edit_participants_box.h b/Telegram/SourceFiles/boxes/peers/edit_participants_box.h index cff017b31..1a1be5122 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participants_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_participants_box.h @@ -33,7 +33,7 @@ Fn SaveRestrictedCallback( not_null peer, - not_null user, + not_null participant, Fn onDone, Fn onFail); @@ -77,29 +77,31 @@ public: ParticipantsAdditionalData(not_null peer, Role role); - UserData *applyParticipant(const MTPChannelParticipant &data); - UserData *applyParticipant( + PeerData *applyParticipant(const MTPChannelParticipant &data); + PeerData *applyParticipant( const MTPChannelParticipant &data, Role overrideRole); - void setExternal(not_null user); - void checkForLoaded(not_null user); + void setExternal(not_null participant); + void checkForLoaded(not_null participant); void fillFromPeer(); - [[nodiscard]] bool infoLoaded(not_null user) const; + [[nodiscard]] bool infoLoaded(not_null participant) const; [[nodiscard]] bool canEditAdmin(not_null user) const; [[nodiscard]] bool canAddOrEditAdmin(not_null user) const; - [[nodiscard]] bool canRestrictUser(not_null user) const; - [[nodiscard]] bool canRemoveUser(not_null user) const; + [[nodiscard]] bool canRestrictParticipant( + not_null participant) const; + [[nodiscard]] bool canRemoveParticipant( + not_null participant) const; [[nodiscard]] std::optional adminRights( not_null user) const; QString adminRank(not_null user) const; [[nodiscard]] std::optional restrictedRights( - not_null user) const; + not_null participant) const; [[nodiscard]] bool isCreator(not_null user) const; - [[nodiscard]] bool isExternal(not_null user) const; - [[nodiscard]] bool isKicked(not_null user) const; + [[nodiscard]] bool isExternal(not_null participant) const; + [[nodiscard]] bool isKicked(not_null participant) const; [[nodiscard]] UserData *adminPromotedBy(not_null user) const; - [[nodiscard]] UserData *restrictedBy(not_null user) const; + [[nodiscard]] UserData *restrictedBy(not_null participant) const; void migrate(not_null chat, not_null channel); @@ -107,7 +109,7 @@ private: UserData *applyCreator(const MTPDchannelParticipantCreator &data); UserData *applyAdmin(const MTPDchannelParticipantAdmin &data); UserData *applyRegular(MTPint userId); - UserData *applyBanned(const MTPDchannelParticipantBanned &data); + PeerData *applyBanned(const MTPDchannelParticipantBanned &data); void fillFromChat(not_null chat); void fillFromChannel(not_null channel); @@ -124,11 +126,11 @@ private: base::flat_map, QString> _adminRanks; base::flat_set> _adminCanEdit; base::flat_map, not_null> _adminPromotedBy; - std::map, MTPChatBannedRights> _restrictedRights; - std::set> _kicked; - std::map, not_null> _restrictedBy; - std::set> _external; - std::set> _infoNotLoaded; + std::map, MTPChatBannedRights> _restrictedRights; + std::set> _kicked; + std::map, not_null> _restrictedBy; + std::set> _external; + std::set> _infoNotLoaded; }; @@ -181,7 +183,7 @@ protected: Role role); virtual std::unique_ptr createRow( - not_null user) const; + not_null participant) const; private: using Row = Info::Profile::MemberListRow; @@ -223,23 +225,25 @@ private: const QString &rank); void showRestricted(not_null user); void editRestrictedDone( - not_null user, + not_null participant, const MTPChatBannedRights &rights); - void removeKicked(not_null row, not_null user); - void removeKickedWithRow(not_null user); - void removeKicked(not_null user); - void kickMember(not_null user); - void kickMemberSure(not_null user); + void removeKicked( + not_null row, + not_null participant); + void removeKickedWithRow(not_null participant); + void removeKicked(not_null participant); + void kickMember(not_null participant); + void kickMemberSure(not_null participant); void unkickMember(not_null user); void removeAdmin(not_null user); void removeAdminSure(not_null user); - bool appendRow(not_null user); + bool appendRow(not_null participant); bool prependRow(not_null user); - bool removeRow(not_null user); + bool removeRow(not_null participant); void refreshCustomStatus(not_null row) const; bool feedMegagroupLastParticipants(); - Type computeType(not_null user) const; - void recomputeTypeFor(not_null user); + Type computeType(not_null participant) const; + void recomputeTypeFor(not_null participant); void subscribeToMigration(); void migrate(not_null chat, not_null channel); diff --git a/Telegram/SourceFiles/calls/calls_group_call.cpp b/Telegram/SourceFiles/calls/calls_group_call.cpp index 380602c71..176d68f6a 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/calls_group_call.cpp @@ -1144,7 +1144,8 @@ void GroupCall::broadcastPartStart(std::shared_ptr task) { rejoin(); return; } - const auto status = MTP::IsFloodError(error) + const auto status = (MTP::IsFloodError(error) + || error.type() == u"TIME_TOO_BIG"_q) ? Status::NotReady : Status::ResyncNeeded; finish({ diff --git a/Telegram/SourceFiles/calls/calls_group_panel.cpp b/Telegram/SourceFiles/calls/calls_group_panel.cpp index b0994d1c6..b0a2ee7cf 100644 --- a/Telegram/SourceFiles/calls/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_group_panel.cpp @@ -82,7 +82,7 @@ private: [[nodiscard]] bool isAlreadyIn(not_null user) const; std::unique_ptr createRow( - not_null user) const override; + not_null participant) const override; not_null _peer; const base::flat_set> _alreadyIn; @@ -190,8 +190,9 @@ bool InviteController::isAlreadyIn(not_null user) const { } std::unique_ptr InviteController::createRow( - not_null user) const { - if (user->isSelf() || user->isBot()) { + not_null participant) const { + const auto user = participant->asUser(); + if (!user || user->isSelf() || user->isBot()) { return nullptr; } auto result = std::make_unique(user); diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index 84f607747..70f90494f 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -267,11 +267,17 @@ void ChannelData::applyEditAdmin( session().changes().peerUpdated(this, UpdateFlag::Admins); } -void ChannelData::applyEditBanned(not_null user, const MTPChatBannedRights &oldRights, const MTPChatBannedRights &newRights) { +void ChannelData::applyEditBanned( + not_null participant, + const MTPChatBannedRights &oldRights, + const MTPChatBannedRights &newRights) { auto flags = UpdateFlag::BannedUsers | UpdateFlag::None; - auto isKicked = (newRights.c_chatBannedRights().vflags().v & MTPDchatBannedRights::Flag::f_view_messages); - auto isRestricted = !isKicked && (newRights.c_chatBannedRights().vflags().v != 0); - if (mgInfo) { + auto isKicked = Data::ChatBannedRightsFlags(newRights) + & ChatRestriction::f_view_messages; + auto isRestricted = !isKicked + && (Data::ChatBannedRightsFlags(newRights) != 0); + const auto user = participant->asUser(); + if (mgInfo && user) { // If rights are empty - still remove admin? TODO check if (mgInfo->lastAdmins.contains(user)) { mgInfo->lastAdmins.remove(user); @@ -284,7 +290,9 @@ void ChannelData::applyEditBanned(not_null user, const MTPChatBannedR auto it = mgInfo->lastRestricted.find(user); if (isRestricted) { if (it == mgInfo->lastRestricted.cend()) { - mgInfo->lastRestricted.emplace(user, MegagroupInfo::Restricted { newRights }); + mgInfo->lastRestricted.emplace( + user, + MegagroupInfo::Restricted { newRights }); setRestrictedCount(restrictedCount() + 1); } else { it->second.rights = newRights; @@ -297,7 +305,9 @@ void ChannelData::applyEditBanned(not_null user, const MTPChatBannedR } } if (isKicked) { - auto i = ranges::find(mgInfo->lastParticipants, user); + auto i = ranges::find( + mgInfo->lastParticipants, + not_null{ user }); if (i != mgInfo->lastParticipants.end()) { mgInfo->lastParticipants.erase(i); } @@ -319,9 +329,9 @@ void ChannelData::applyEditBanned(not_null user, const MTPChatBannedR } } Data::ChannelAdminChanges(this).remove(peerToUser(user->id)); - } else { + } else if (!mgInfo) { if (isKicked) { - if (membersCount() > 1) { + if (user && membersCount() > 1) { setMembersCount(membersCount() - 1); flags |= UpdateFlag::Members; } @@ -543,12 +553,14 @@ void ChannelData::setAdminRights(const MTPChatAdminRights &rights) { } void ChannelData::setRestrictions(const MTPChatBannedRights &rights) { - if (rights.c_chatBannedRights().vflags().v == restrictions() - && rights.c_chatBannedRights().vuntil_date().v == _restrictedUntil) { + const auto restrictedFlags = Data::ChatBannedRightsFlags(rights); + const auto restrictedUntilDate = Data::ChatBannedRightsUntilDate(rights); + if (restrictedFlags == restrictions() + && restrictedUntilDate == _restrictedUntil) { return; } - _restrictedUntil = rights.c_chatBannedRights().vuntil_date().v; - _restrictions.set(rights.c_chatBannedRights().vflags().v); + _restrictedUntil = restrictedUntilDate; + _restrictions.set(restrictedFlags); if (isMegagroup()) { const auto self = session().user(); if (hasRestrictions()) { @@ -568,10 +580,11 @@ void ChannelData::setRestrictions(const MTPChatBannedRights &rights) { } void ChannelData::setDefaultRestrictions(const MTPChatBannedRights &rights) { - if (rights.c_chatBannedRights().vflags().v == defaultRestrictions()) { + const auto restrictionFlags = Data::ChatBannedRightsFlags(rights); + if (restrictionFlags == defaultRestrictions()) { return; } - _defaultRestrictions.set(rights.c_chatBannedRights().vflags().v); + _defaultRestrictions.set(restrictionFlags); session().changes().peerUpdated(this, UpdateFlag::Rights); } @@ -903,8 +916,11 @@ void ApplyMegagroupAdmins( auto admins = ranges::make_subrange( list.begin(), list.end() ) | ranges::views::transform([](const MTPChannelParticipant &p) { - const auto userId = p.match([](const auto &data) { - return data.vuser_id().v; + const auto participantId = p.match([]( + const MTPDchannelParticipantBanned &data) { + return peerFromMTP(data.vpeer()); + }, [](const auto &data) { + return peerFromUser(data.vuser_id()); }); const auto rank = p.match([](const MTPDchannelParticipantAdmin &data) { return qs(data.vrank().value_or_empty()); @@ -913,10 +929,13 @@ void ApplyMegagroupAdmins( }, [](const auto &data) { return QString(); }); - return std::make_pair(userId, rank); + return std::make_pair(participantId, rank); + }) | ranges::views::filter([](const auto &pair) { + return peerIsUser(pair.first); }); - for (const auto &[userId, rank] : admins) { - adding.emplace(userId, rank); + for (const auto &[participantId, rank] : admins) { + Assert(peerIsUser(participantId)); + adding.emplace(peerToUser(participantId), rank); } if (channel->mgInfo->creator) { adding.emplace( diff --git a/Telegram/SourceFiles/data/data_channel.h b/Telegram/SourceFiles/data/data_channel.h index 0cb9e88a7..7b9631120 100644 --- a/Telegram/SourceFiles/data/data_channel.h +++ b/Telegram/SourceFiles/data/data_channel.h @@ -220,7 +220,7 @@ public: const MTPChatAdminRights &newRights, const QString &rank); void applyEditBanned( - not_null user, + not_null participant, const MTPChatBannedRights &oldRights, const MTPChatBannedRights &newRights); diff --git a/Telegram/SourceFiles/data/data_chat.cpp b/Telegram/SourceFiles/data/data_chat.cpp index da0eaaad9..c12fdb867 100644 --- a/Telegram/SourceFiles/data/data_chat.cpp +++ b/Telegram/SourceFiles/data/data_chat.cpp @@ -156,10 +156,11 @@ void ChatData::setAdminRights(const MTPChatAdminRights &rights) { } void ChatData::setDefaultRestrictions(const MTPChatBannedRights &rights) { - if (rights.c_chatBannedRights().vflags().v == defaultRestrictions()) { + const auto restrictionFlags = Data::ChatBannedRightsFlags(rights); + if (restrictionFlags == defaultRestrictions()) { return; } - _defaultRestrictions.set(rights.c_chatBannedRights().vflags().v); + _defaultRestrictions.set(restrictionFlags); session().changes().peerUpdated(this, UpdateFlag::Rights); } diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 36b612466..8648943de 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -1172,4 +1172,16 @@ std::optional ResolvePinnedCount( : std::nullopt; } +ChatRestrictions ChatBannedRightsFlags(const MTPChatBannedRights &rights) { + return rights.match([](const MTPDchatBannedRights &data) { + return data.vflags().v; + }); +} + +TimeId ChatBannedRightsUntilDate(const MTPChatBannedRights &rights) { + return rights.match([](const MTPDchatBannedRights &data) { + return data.vuntil_date().v; + }); +} + } // namespace Data diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index 7c7670a29..960f0751a 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -95,6 +95,11 @@ struct UnavailableReason { } }; +[[nodiscard]] ChatRestrictions ChatBannedRightsFlags( + const MTPChatBannedRights &rights); +[[nodiscard]] TimeId ChatBannedRightsUntilDate( + const MTPChatBannedRights &rights); + } // namespace Data class PeerClickHandler : public ClickHandler { 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 07748ff17..baede6839 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp @@ -432,8 +432,11 @@ void InnerWidget::requestAdmins() { auto filtered = ( list ) | ranges::views::transform([&](const MTPChannelParticipant &p) { - const auto userId = p.match([](const auto &data) { - return data.vuser_id().v; + const auto participantId = p.match([]( + const MTPDchannelParticipantBanned &data) { + return peerFromMTP(data.vpeer()); + }, [](const auto &data) { + return peerFromUser(data.vuser_id()); }); const auto canEdit = p.match([]( const MTPDchannelParticipantAdmin &data) { @@ -441,10 +444,13 @@ void InnerWidget::requestAdmins() { }, [](const auto &) { return false; }); - return std::make_pair(userId, canEdit); + return std::make_pair(participantId, canEdit); }) | ranges::views::transform([&](auto &&pair) { return std::make_pair( - session().data().userLoaded(pair.first), + (peerIsUser(pair.first) + ? session().data().userLoaded( + peerToUser(pair.first)) + : nullptr), pair.second); }) | ranges::views::filter([&](auto &&pair) { return (pair.first != nullptr); @@ -1308,7 +1314,7 @@ void InnerWidget::suggestRestrictUser(not_null user) { } else { _api.request(MTPchannels_GetParticipant( _channel->inputChannel, - user->inputUser + user->input )).done([=](const MTPchannels_ChannelParticipant &result) { Expects(result.type() == mtpc_channels_channelParticipant); @@ -1352,8 +1358,7 @@ void InnerWidget::restrictUser( } void InnerWidget::restrictUserDone(not_null user, const MTPChatBannedRights &rights) { - Expects(rights.type() == mtpc_chatBannedRights); - if (rights.c_chatBannedRights().vflags().v) { + 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()); } 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 9a7d78bc5..fae37a714 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp @@ -204,14 +204,11 @@ TextWithEntities GenerateAdminChangeText( QString GenerateBannedChangeText( const MTPChatBannedRights *newRights, const MTPChatBannedRights *prevRights) { - Expects(!newRights || newRights->type() == mtpc_chatBannedRights); - Expects(!prevRights || prevRights->type() == mtpc_chatBannedRights); - using Flag = MTPDchatBannedRights::Flag; using Flags = MTPDchatBannedRights::Flags; - auto newFlags = newRights ? newRights->c_chatBannedRights().vflags().v : Flags(0); - auto prevFlags = prevRights ? prevRights->c_chatBannedRights().vflags().v : Flags(0); + auto newFlags = newRights ? Data::ChatBannedRightsFlags(*newRights) : Flags(0); + auto prevFlags = prevRights ? Data::ChatBannedRightsFlags(*prevRights) : Flags(0); static auto phraseMap = std::map>{ { Flag::f_view_messages, tr::lng_admin_log_banned_view_messages }, { Flag::f_send_messages, tr::lng_admin_log_banned_send_messages }, @@ -233,13 +230,11 @@ TextWithEntities GenerateBannedChangeText( const TextWithEntities &user, const MTPChatBannedRights *newRights, const MTPChatBannedRights *prevRights) { - Expects(!newRights || newRights->type() == mtpc_chatBannedRights); - using Flag = MTPDchatBannedRights::Flag; using Flags = MTPDchatBannedRights::Flags; - auto newFlags = newRights ? newRights->c_chatBannedRights().vflags().v : Flags(0); - auto newUntil = newRights ? newRights->c_chatBannedRights().vuntil_date().v : TimeId(0); + auto newFlags = newRights ? Data::ChatBannedRightsFlags(*newRights) : Flags(0); + auto newUntil = newRights ? Data::ChatBannedRightsUntilDate(*newRights) : TimeId(0); auto indefinitely = ChannelData::IsRestrictedForever(newUntil); if (newFlags & Flag::f_view_messages) { return tr::lng_admin_log_banned(tr::now, lt_user, user, Ui::Text::WithEntities); @@ -344,21 +339,23 @@ TextWithEntities GenerateInviteLinkChangeText( return result; }; -auto GenerateUserString( +auto GenerateParticipantString( not_null session, - MTPint userId) { + PeerId peerId) { // User name in "User name (@username)" format with entities. - auto user = session->data().user(userId.v); - auto name = TextWithEntities { user->name }; - auto entityData = QString::number(user->id) - + '.' - + QString::number(user->accessHash()); - name.entities.push_back({ - EntityType::MentionName, - 0, - name.text.size(), - entityData }); - auto username = user->userName(); + auto peer = session->data().peer(peerId); + auto name = TextWithEntities { peer->name }; + if (const auto user = peer->asUser()) { + auto entityData = QString::number(user->id) + + '.' + + QString::number(user->accessHash()); + name.entities.push_back({ + EntityType::MentionName, + 0, + name.text.size(), + entityData }); + } + auto username = peer->userName(); if (username.isEmpty()) { return name; } @@ -386,10 +383,14 @@ auto GenerateParticipantChangeTextInner( return tr::lng_admin_log_transferred( tr::now, lt_user, - GenerateUserString(&channel->session(), data.vuser_id()), + GenerateParticipantString( + &channel->session(), + peerFromUser(data.vuser_id())), Ui::Text::WithEntities); }, [&](const MTPDchannelParticipantAdmin &data) { - auto user = GenerateUserString(&channel->session(), data.vuser_id()); + const auto user = GenerateParticipantString( + &channel->session(), + peerFromUser(data.vuser_id())); return GenerateAdminChangeText( channel, user, @@ -398,7 +399,9 @@ auto GenerateParticipantChangeTextInner( ? &oldParticipant->c_channelParticipantAdmin().vadmin_rights() : nullptr); }, [&](const MTPDchannelParticipantBanned &data) { - auto user = GenerateUserString(&channel->session(), data.vuser_id()); + const auto user = GenerateParticipantString( + &channel->session(), + peerFromMTP(data.vpeer())); return GenerateBannedChangeText( user, &data.vbanned_rights(), @@ -406,7 +409,9 @@ auto GenerateParticipantChangeTextInner( ? &oldParticipant->c_channelParticipantBanned().vbanned_rights() : nullptr); }, [&](const auto &data) { - auto user = GenerateUserString(&channel->session(), data.vuser_id()); + auto user = GenerateParticipantString( + &channel->session(), + peerFromUser(data.vuser_id())); if (oldType == mtpc_channelParticipantAdmin) { return GenerateAdminChangeText( channel, diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 8c98416c6..82b6a2eda 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -1068,11 +1068,16 @@ void PeerMenuAddChannelMembers( auto already = ( list ) | ranges::views::transform([](const MTPChannelParticipant &p) { - return p.match([](const auto &data) { - return data.vuser_id().v; + return p.match([](const MTPDchannelParticipantBanned &data) { + return peerFromMTP(data.vpeer()); + }, [](const auto &data) { + return peerFromUser(data.vuser_id()); }); - }) | ranges::views::transform([&](UserId userId) { - return channel->owner().userLoaded(userId); + }) | ranges::views::transform([&](PeerId participantId) { + return peerIsUser(participantId) + ? channel->owner().userLoaded( + peerToUser(participantId)) + : nullptr; }) | ranges::views::filter([](UserData *user) { return (user != nullptr); }) | ranges::to_vector;