Replaced use of raw MTP* participant type with new transitional class.

This commit is contained in:
23rd 2021-11-24 07:25:05 +03:00 committed by John Preston
parent c65468f270
commit f255573070
7 changed files with 249 additions and 324 deletions

View file

@ -23,6 +23,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Api { namespace Api {
namespace { namespace {
using Members = ChatParticipants::Members;
constexpr auto kSmallDelayMs = crl::time(5); constexpr auto kSmallDelayMs = crl::time(5);
// 1 second wait before reload members in channel after adding. // 1 second wait before reload members in channel after adding.
@ -35,57 +37,32 @@ constexpr auto kMaxUsersPerInvite = 100;
// that was added to this chat. // that was added to this chat.
constexpr auto kForwardMessagesOnAdd = 100; constexpr auto kForwardMessagesOnAdd = 100;
[[nodiscard]] PeerId TLToPeerId(const MTPChannelParticipant &p) { std::vector<ChatParticipant> ParseList(
return p.match([](const MTPDchannelParticipantBanned &data) { const ChatParticipants::TLMembers &data,
return peerFromMTP(data.vpeer()); not_null<PeerData*> peer) {
}, [](const MTPDchannelParticipantLeft &data) { return ranges::views::all(
return peerFromMTP(data.vpeer()); data.vparticipants().v
}, [](const auto &data) { ) | ranges::views::transform([&](const MTPChannelParticipant &p) {
return peerFromUser(data.vuser_id()); return ChatParticipant(p, peer);
}); }) | ranges::to_vector;
} }
void ApplyMegagroupAdmins( void ApplyMegagroupAdmins(not_null<ChannelData*> channel, Members list) {
not_null<ChannelData*> channel,
const MTPDchannels_channelParticipants &data) {
Expects(channel->isMegagroup()); Expects(channel->isMegagroup());
channel->owner().processUsers(data.vusers()); const auto i = ranges::find_if(list, &Api::ChatParticipant::isCreator);
const auto &list = data.vparticipants().v;
const auto i = ranges::find(
list,
mtpc_channelParticipantCreator,
&MTPChannelParticipant::type);
if (i != list.end()) { if (i != list.end()) {
const auto &data = i->c_channelParticipantCreator(); i->tryApplyCreatorTo(channel);
const auto userId = data.vuser_id().v;
channel->mgInfo->creator = channel->owner().userLoaded(userId);
channel->mgInfo->creatorRank = qs(data.vrank().value_or_empty());
} else { } else {
channel->mgInfo->creator = nullptr; channel->mgInfo->creator = nullptr;
channel->mgInfo->creatorRank = QString(); channel->mgInfo->creatorRank = QString();
} }
auto adding = base::flat_map<UserId, QString>(); auto adding = base::flat_map<UserId, QString>();
auto admins = ranges::make_subrange( for (const auto &p : list) {
list.begin(), list.end() if (p.isUser()) {
) | ranges::views::transform([](const MTPChannelParticipant &p) { adding.emplace(p.userId(), p.rank());
const auto participantId = TLToPeerId(p); }
const auto rank = p.match([](const MTPDchannelParticipantAdmin &data) {
return qs(data.vrank().value_or_empty());
}, [](const MTPDchannelParticipantCreator &data) {
return qs(data.vrank().value_or_empty());
}, [](const auto &data) {
return QString();
});
return std::make_pair(participantId, rank);
}) | ranges::views::filter([](const auto &pair) {
return peerIsUser(pair.first);
});
for (const auto &[participantId, rank] : admins) {
Assert(peerIsUser(participantId));
adding.emplace(peerToUser(participantId), rank);
} }
if (channel->mgInfo->creator) { if (channel->mgInfo->creator) {
adding.emplace( adding.emplace(
@ -113,34 +90,24 @@ void ApplyMegagroupAdmins(
void RefreshChannelAdmins( void RefreshChannelAdmins(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
ChatParticipants::TLMembersList participants) { Members participants) {
Data::ChannelAdminChanges changes(channel); Data::ChannelAdminChanges changes(channel);
for (const auto &p : participants) { for (const auto &p : participants) {
const auto participantId = TLToPeerId(p); if (p.isUser()) {
const auto userId = peerToUser(participantId); if (p.isCreatorOrAdmin()) {
p.match([&](const MTPDchannelParticipantAdmin &data) { p.tryApplyCreatorTo(channel);
Assert(peerIsUser(participantId)); changes.add(p.userId(), p.rank());
changes.add(userId, qs(data.vrank().value_or_empty())); } else {
}, [&](const MTPDchannelParticipantCreator &data) { changes.remove(p.userId());
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);
info->creatorRank = rank;
} }
changes.add(userId, rank); }
}, [&](const auto &data) {
if (userId) {
changes.remove(userId);
}
});
} }
} }
void ApplyLastList( void ApplyLastList(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
int availableCount, int availableCount,
ChatParticipants::TLMembersList list) { Members list) {
channel->mgInfo->lastAdmins.clear(); channel->mgInfo->lastAdmins.clear();
channel->mgInfo->lastRestricted.clear(); channel->mgInfo->lastRestricted.clear();
channel->mgInfo->lastParticipants.clear(); channel->mgInfo->lastParticipants.clear();
@ -150,36 +117,15 @@ void ApplyLastList(
auto botStatus = channel->mgInfo->botStatus; auto botStatus = channel->mgInfo->botStatus;
for (const auto &p : list) { for (const auto &p : list) {
const auto participantId = TLToPeerId(p); const auto participant = channel->owner().peer(p.id());
if (!participantId) {
continue;
}
const auto participant = channel->owner().peer(participantId);
const auto user = participant->asUser(); const auto user = participant->asUser();
const auto adminCanEdit = (p.type() == mtpc_channelParticipantAdmin) const auto adminRights = p.rights();
? p.c_channelParticipantAdmin().is_can_edit() const auto restrictedRights = p.restrictions();
: (p.type() == mtpc_channelParticipantCreator) if (p.isCreator()) {
? channel->amCreator()
: false;
const auto adminRights = (p.type() == mtpc_channelParticipantAdmin)
? ChatAdminRightsInfo(p.c_channelParticipantAdmin().vadmin_rights())
: (p.type() == mtpc_channelParticipantCreator)
? ChatAdminRightsInfo(p.c_channelParticipantCreator().vadmin_rights())
: ChatAdminRightsInfo();
const auto restrictedRights = (p.type() == mtpc_channelParticipantBanned)
? ChatRestrictionsInfo(
p.c_channelParticipantBanned().vbanned_rights())
: ChatRestrictionsInfo();
if (p.type() == mtpc_channelParticipantCreator) {
Assert(user != nullptr); Assert(user != nullptr);
const auto &creator = p.c_channelParticipantCreator(); p.tryApplyCreatorTo(channel);
const auto rank = qs(creator.vrank().value_or_empty());
channel->mgInfo->creator = user;
channel->mgInfo->creatorRank = rank;
if (!channel->mgInfo->admins.empty()) { if (!channel->mgInfo->admins.empty()) {
Data::ChannelAdminChanges(channel).add( Data::ChannelAdminChanges(channel).add(p.userId(), p.rank());
peerToUser(participantId),
rank);
} }
} }
if (user if (user
@ -188,7 +134,7 @@ void ApplyLastList(
if (adminRights.flags) { if (adminRights.flags) {
channel->mgInfo->lastAdmins.emplace( channel->mgInfo->lastAdmins.emplace(
user, user,
MegagroupInfo::Admin{ adminRights, adminCanEdit }); MegagroupInfo::Admin{ adminRights, p.canBeEdited() });
} else if (restrictedRights.flags) { } else if (restrictedRights.flags) {
channel->mgInfo->lastRestricted.emplace( channel->mgInfo->lastRestricted.emplace(
user, user,
@ -196,7 +142,8 @@ void ApplyLastList(
} }
if (user->isBot()) { if (user->isBot()) {
channel->mgInfo->bots.insert(user); channel->mgInfo->bots.insert(user);
if (channel->mgInfo->botStatus != 0 && channel->mgInfo->botStatus < 2) { if ((channel->mgInfo->botStatus != 0)
&& (channel->mgInfo->botStatus < 2)) {
channel->mgInfo->botStatus = 2; channel->mgInfo->botStatus = 2;
} }
} }
@ -227,7 +174,7 @@ void ApplyLastList(
void ApplyBotsList( void ApplyBotsList(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
int availableCount, int availableCount,
ChatParticipants::TLMembersList list) { Members list) {
const auto history = channel->owner().historyLoaded(channel); const auto history = channel->owner().historyLoaded(channel);
channel->mgInfo->bots.clear(); channel->mgInfo->bots.clear();
channel->mgInfo->botStatus = -1; channel->mgInfo->botStatus = -1;
@ -236,12 +183,7 @@ void ApplyBotsList(
auto botStatus = channel->mgInfo->botStatus; auto botStatus = channel->mgInfo->botStatus;
auto keyboardBotFound = !history || !history->lastKeyboardFrom; auto keyboardBotFound = !history || !history->lastKeyboardFrom;
for (const auto &p : list) { for (const auto &p : list) {
const auto participantId = TLToPeerId(p); const auto participant = channel->owner().peer(p.id());
if (!participantId) {
continue;
}
const auto participant = channel->owner().peer(participantId);
const auto user = participant->asUser(); const auto user = participant->asUser();
if (user && user->isBot()) { if (user && user->isBot()) {
channel->mgInfo->bots.insert(user); channel->mgInfo->bots.insert(user);
@ -409,8 +351,14 @@ void ChatParticipants::requestForAdd(
MTP_int(channel->session().serverConfig().chatSizeMax), MTP_int(channel->session().serverConfig().chatSizeMax),
MTP_long(participantsHash) MTP_long(participantsHash)
)).done([=](const MTPchannels_ChannelParticipants &result) { )).done([=](const MTPchannels_ChannelParticipants &result) {
base::take(_forAdd).callback(result); result.match([&](const MTPDchannels_channelParticipants &data) {
}).fail([=](const MTP::Error &error) { base::take(_forAdd).callback(data);
}, [&](const MTPDchannels_channelParticipantsNotModified &) {
base::take(_forAdd);
LOG(("API Error: "
"channels.channelParticipantsNotModified received!"));
});
}).fail([=] {
base::take(_forAdd); base::take(_forAdd);
}).send(); }).send();
} }
@ -431,11 +379,13 @@ void ChatParticipants::requestLast(not_null<ChannelData*> channel) {
MTP_long(participantsHash) MTP_long(participantsHash)
)).done([=](const MTPchannels_ChannelParticipants &result) { )).done([=](const MTPchannels_ChannelParticipants &result) {
_participantsRequests.remove(channel); _participantsRequests.remove(channel);
parse(channel, result, [&](int availableCount, TLMembersList list) {
ApplyLastList( result.match([&](const MTPDchannels_channelParticipants &data) {
channel, const auto &[availableCount, list] = Parse(channel, data);
availableCount, ApplyLastList(channel, availableCount, list);
list); }, [](const MTPDchannels_channelParticipantsNotModified &) {
LOG(("API Error: "
"channels.channelParticipantsNotModified received!"));
}); });
}).fail([this, channel](const MTP::Error &error) { }).fail([this, channel](const MTP::Error &error) {
_participantsRequests.remove(channel); _participantsRequests.remove(channel);
@ -459,11 +409,12 @@ void ChatParticipants::requestBots(not_null<ChannelData*> channel) {
MTP_long(participantsHash) MTP_long(participantsHash)
)).done([=](const MTPchannels_ChannelParticipants &result) { )).done([=](const MTPchannels_ChannelParticipants &result) {
_botsRequests.remove(channel); _botsRequests.remove(channel);
parse(channel, result, [&](int availableCount, TLMembersList list) { result.match([&](const MTPDchannels_channelParticipants &data) {
ApplyBotsList( const auto &[availableCount, list] = Parse(channel, data);
channel, ApplyLastList(channel, availableCount, list);
availableCount, }, [](const MTPDchannels_channelParticipantsNotModified &) {
list); LOG(("API Error: "
"channels.channelParticipantsNotModified received!"));
}); });
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {
_botsRequests.remove(channel); _botsRequests.remove(channel);
@ -488,7 +439,8 @@ void ChatParticipants::requestAdmins(not_null<ChannelData*> channel) {
)).done([=](const MTPchannels_ChannelParticipants &result) { )).done([=](const MTPchannels_ChannelParticipants &result) {
_adminsRequests.remove(channel); _adminsRequests.remove(channel);
result.match([&](const MTPDchannels_channelParticipants &data) { result.match([&](const MTPDchannels_channelParticipants &data) {
ApplyMegagroupAdmins(channel, data); channel->owner().processUsers(data.vusers());
ApplyMegagroupAdmins(channel, ParseList(data, channel));
}, [](const MTPDchannels_channelParticipantsNotModified &) { }, [](const MTPDchannels_channelParticipantsNotModified &) {
LOG(("API Error: " LOG(("API Error: "
"channels.channelParticipantsNotModified received!")); "channels.channelParticipantsNotModified received!"));
@ -562,40 +514,27 @@ void ChatParticipants::add(
} }
} }
void ChatParticipants::parseRecent( ChatParticipants::Parsed ChatParticipants::Parse(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
const TLMembers &result, const TLMembers &data) {
Fn<void(int availableCount, TLMembersList list)> callbackList) { channel->owner().processUsers(data.vusers());
parse(channel, result, [&](int availableCount, TLMembersList list) { auto list = ParseList(data, channel);
const auto applyLast = channel->isMegagroup() if (channel->mgInfo) {
&& (channel->mgInfo->lastParticipants.size() <= list.size()); RefreshChannelAdmins(channel, list);
if (applyLast) { }
ApplyLastList( return { data.vcount().v, std::move(list) };
channel,
availableCount,
list);
}
if (callbackList) {
callbackList(availableCount, list);
}
});
} }
void ChatParticipants::parse( ChatParticipants::Parsed ChatParticipants::ParseRecent(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
const TLMembers &result, const TLMembers &data) {
Fn<void(int availableCount, TLMembersList list)> callbackList) { const auto result = Parse(channel, data);
result.match([&](const MTPDchannels_channelParticipants &data) { const auto applyLast = channel->isMegagroup()
channel->owner().processUsers(data.vusers()); && (channel->mgInfo->lastParticipants.size() <= result.list.size());
if (channel->mgInfo) { if (applyLast) {
RefreshChannelAdmins(channel, data.vparticipants().v); ApplyLastList(channel, result.availableCount, result.list);
} }
if (callbackList) { return result;
callbackList(data.vcount().v, data.vparticipants().v);
}
}, [&](const MTPDchannels_channelParticipantsNotModified &) {
LOG(("API Error: channels.channelParticipantsNotModified received!"));
});
} }
void ChatParticipants::requestSelf(not_null<ChannelData*> channel) { void ChatParticipants::requestSelf(not_null<ChannelData*> channel) {

View file

@ -72,8 +72,13 @@ private:
class ChatParticipants final { class ChatParticipants final {
public: public:
using TLMembers = MTPchannels_ChannelParticipants; struct Parsed {
using TLMembersList = const QVector<MTPChannelParticipant> &; const int availableCount;
const std::vector<ChatParticipant> list;
};
using TLMembers = MTPDchannels_channelParticipants;
using Members = const std::vector<ChatParticipant> &;
explicit ChatParticipants(not_null<ApiWrap*> api); explicit ChatParticipants(not_null<ApiWrap*> api);
void requestLast(not_null<ChannelData*> channel); void requestLast(not_null<ChannelData*> channel);
@ -81,14 +86,12 @@ public:
void requestAdmins(not_null<ChannelData*> channel); void requestAdmins(not_null<ChannelData*> channel);
void requestCountDelayed(not_null<ChannelData*> channel); void requestCountDelayed(not_null<ChannelData*> channel);
void parse( static Parsed Parse(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
const TLMembers &result, const TLMembers &data);
Fn<void(int availableCount, TLMembersList list)> callbackList); static Parsed ParseRecent(
void parseRecent(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
const TLMembers &result, const TLMembers &data);
Fn<void(int availableCount, TLMembersList)> callbackList = nullptr);
void add( void add(
not_null<PeerData*> peer, not_null<PeerData*> peer,
const std::vector<not_null<UserData*>> &users, const std::vector<not_null<UserData*>> &users,

View file

@ -466,9 +466,10 @@ void AddSpecialBoxController::loadMoreRows() {
)).done([=](const MTPchannels_ChannelParticipants &result) { )).done([=](const MTPchannels_ChannelParticipants &result) {
_loadRequestId = 0; _loadRequestId = 0;
auto &session = channel->session(); auto &session = channel->session();
session.api().chatParticipants().parse(channel, result, [&]( result.match([&](const MTPDchannels_channelParticipants &data) {
int availableCount, const auto &[availableCount, list] = Api::ChatParticipants::Parse(
const QVector<MTPChannelParticipant> &list) { channel,
data);
for (const auto &data : list) { for (const auto &data : list) {
if (const auto participant = _additional.applyParticipant( if (const auto participant = _additional.applyParticipant(
data)) { data)) {
@ -481,8 +482,9 @@ void AddSpecialBoxController::loadMoreRows() {
// To be sure - wait for a whole empty result list. // To be sure - wait for a whole empty result list.
_allLoaded = true; _allLoaded = true;
} }
}, [&](const MTPDchannels_channelParticipantsNotModified &) {
LOG(("API Error: channels.channelParticipantsNotModified received!"));
}); });
if (delegate()->peerListFullRowsCount() > 0) { if (delegate()->peerListFullRowsCount() > 0) {
setDescriptionText(QString()); setDescriptionText(QString());
} else if (_allLoaded) { } else if (_allLoaded) {
@ -525,7 +527,8 @@ bool AddSpecialBoxController::checkInfoLoaded(
)).done([=](const MTPchannels_ChannelParticipant &result) { )).done([=](const MTPchannels_ChannelParticipant &result) {
result.match([&](const MTPDchannels_channelParticipant &data) { result.match([&](const MTPDchannels_channelParticipant &data) {
channel->owner().processUsers(data.vusers()); channel->owner().processUsers(data.vusers());
_additional.applyParticipant(data.vparticipant()); _additional.applyParticipant(
Api::ChatParticipant(data.vparticipant(), channel));
}); });
callback(); callback();
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {
@ -966,7 +969,7 @@ void AddSpecialBoxSearchController::searchParticipantsDone(
const auto channel = _peer->asChannel(); const auto channel = _peer->asChannel();
auto query = _query; auto query = _query;
if (requestId) { if (requestId) {
const auto addToCache = [&](auto&&...) { const auto addToCache = [&] {
auto it = _participantsQueries.find(requestId); auto it = _participantsQueries.find(requestId);
if (it != _participantsQueries.cend()) { if (it != _participantsQueries.cend()) {
query = it->second.text; query = it->second.text;
@ -978,10 +981,13 @@ void AddSpecialBoxSearchController::searchParticipantsDone(
_participantsQueries.erase(it); _participantsQueries.erase(it);
} }
}; };
channel->session().api().chatParticipants().parse( result.match([&](const MTPDchannels_channelParticipants &data) {
channel, Api::ChatParticipants::Parse(channel, data);
result, addToCache();
addToCache); }, [&](const MTPDchannels_channelParticipantsNotModified &) {
LOG(("API Error: "
"channels.channelParticipantsNotModified received!"));
});
} }
if (_requestId != requestId) { if (_requestId != requestId) {
@ -1001,7 +1007,8 @@ void AddSpecialBoxSearchController::searchParticipantsDone(
} }
} }
for (const auto &data : list) { for (const auto &data : list) {
if (const auto user = _additional->applyParticipant(data)) { if (const auto user = _additional->applyParticipant(
Api::ChatParticipant(data, channel))) {
delegate()->peerListSearchAddRow(user); delegate()->peerListSearchAddRow(user);
} }
} }

View file

@ -537,34 +537,33 @@ void ParticipantsAdditionalData::applyAdminLocally(
const QString &rank) { const QString &rank) {
const auto date = base::unixtime::now(); // Incorrect, but ignored. const auto date = base::unixtime::now(); // Incorrect, but ignored.
if (isCreator(user) && user->isSelf()) { if (isCreator(user) && user->isSelf()) {
using Flag = MTPDchannelParticipantCreator::Flag; applyParticipant(Api::ChatParticipant(
applyParticipant(MTP_channelParticipantCreator( Api::ChatParticipant::Type::Creator,
MTP_flags(rank.isEmpty() ? Flag(0) : Flag::f_rank), user->id,
peerToBareMTPInt(user->id), UserId(),
MTP_chatAdminRights( ChatRestrictionsInfo(),
MTP_flags(MTPDchatAdminRights::Flags::from_raw( std::move(rights),
uint32(rights.flags)))), true, // As the creator is self.
MTP_string(rank))); rank));
} else if (!rights.flags) { } else if (!rights.flags) {
applyParticipant(MTP_channelParticipant( applyParticipant(Api::ChatParticipant(
peerToBareMTPInt(user->id), Api::ChatParticipant::Type::Member,
MTP_int(date))); user->id,
UserId(),
ChatRestrictionsInfo(),
ChatAdminRightsInfo()));
} else { } else {
using Flag = MTPDchannelParticipantAdmin::Flag;
const auto alreadyPromotedBy = adminPromotedBy(user); const auto alreadyPromotedBy = adminPromotedBy(user);
applyParticipant(MTP_channelParticipantAdmin( applyParticipant(Api::ChatParticipant(
MTP_flags(Flag::f_can_edit Api::ChatParticipant::Type::Admin,
| (rank.isEmpty() ? Flag(0) : Flag::f_rank)), user->id,
peerToBareMTPInt(user->id), alreadyPromotedBy
MTPlong(), // inviter_id ? peerToUser(alreadyPromotedBy->id)
peerToBareMTPInt(alreadyPromotedBy : user->session().userId(),
? alreadyPromotedBy->id ChatRestrictionsInfo(),
: user->session().userPeerId()), std::move(rights),
MTP_int(date), true,
MTP_chatAdminRights( rank));
MTP_flags(MTPDchatAdminRights::Flags::from_raw(
uint32(rights.flags)))),
MTP_string(rank)));
} }
} }
@ -575,76 +574,73 @@ void ParticipantsAdditionalData::applyBannedLocally(
const auto date = base::unixtime::now(); // Incorrect, but ignored. const auto date = base::unixtime::now(); // Incorrect, but ignored.
if (!rights.flags) { if (!rights.flags) {
if (user) { if (user) {
applyParticipant(MTP_channelParticipant( applyParticipant(Api::ChatParticipant(
peerToBareMTPInt(user->id), Api::ChatParticipant::Type::Member,
MTP_int(date))); user->id,
UserId(),
ChatRestrictionsInfo(),
ChatAdminRightsInfo()));
} else { } else {
setExternal(participant); setExternal(participant);
} }
} else { } else {
const auto kicked = rights.flags & ChatRestriction::ViewMessages; const auto kicked = rights.flags & ChatRestriction::ViewMessages;
const auto alreadyRestrictedBy = restrictedBy( const auto alreadyRestrictedBy = restrictedBy(participant);
participant); applyParticipant(Api::ChatParticipant(
applyParticipant(MTP_channelParticipantBanned( kicked
MTP_flags(kicked ? Api::ChatParticipant::Type::Banned
? MTPDchannelParticipantBanned::Flag::f_left : Api::ChatParticipant::Type::Restricted,
: MTPDchannelParticipantBanned::Flag(0)), participant->id,
peerToMTP(participant->id), alreadyRestrictedBy
peerToBareMTPInt(alreadyRestrictedBy ? peerToUser(alreadyRestrictedBy->id)
? alreadyRestrictedBy->id : participant->session().userId(),
: participant->session().userPeerId()), std::move(rights),
MTP_int(date), ChatAdminRightsInfo()));
MTP_chatBannedRights(
MTP_flags(MTPDchatBannedRights::Flags::from_raw(
uint32(rights.flags))),
MTP_int(rights.until))));
} }
} }
PeerData *ParticipantsAdditionalData::applyParticipant( PeerData *ParticipantsAdditionalData::applyParticipant(
const MTPChannelParticipant &data) { const Api::ChatParticipant &data) {
return applyParticipant(data, _role); return applyParticipant(data, _role);
} }
PeerData *ParticipantsAdditionalData::applyParticipant( PeerData *ParticipantsAdditionalData::applyParticipant(
const MTPChannelParticipant &data, const Api::ChatParticipant &data,
Role overrideRole) { Role overrideRole) {
const auto logBad = [&]() -> PeerData* { const auto logBad = [&]() -> PeerData* {
LOG(("API Error: Bad participant type %1 got " LOG(("API Error: Bad participant type %1 got "
"while requesting for participants, role: %2" "while requesting for participants, role: %2"
).arg(data.type() ).arg(static_cast<int>(data.type())
).arg(static_cast<int>(overrideRole))); ).arg(static_cast<int>(overrideRole)));
return nullptr; return nullptr;
}; };
return data.match([&]( switch (data.type()) {
const MTPDchannelParticipantCreator &data) -> PeerData* { case Api::ChatParticipant::Type::Creator: {
if (overrideRole != Role::Profile if (overrideRole != Role::Profile
&& overrideRole != Role::Members && overrideRole != Role::Members
&& overrideRole != Role::Admins) { && overrideRole != Role::Admins) {
return logBad(); return logBad();
} }
return applyCreator(data); return applyCreator(data);
}, [&](const MTPDchannelParticipantAdmin &data) -> PeerData* { }
case Api::ChatParticipant::Type::Admin: {
if (overrideRole != Role::Profile if (overrideRole != Role::Profile
&& overrideRole != Role::Members && overrideRole != Role::Members
&& overrideRole != Role::Admins) { && overrideRole != Role::Admins) {
return logBad(); return logBad();
} }
return applyAdmin(data); return applyAdmin(data);
}, [&](const MTPDchannelParticipantSelf &data) -> PeerData* { }
case Api::ChatParticipant::Type::Member: {
if (overrideRole != Role::Profile if (overrideRole != Role::Profile
&& overrideRole != Role::Members) { && overrideRole != Role::Members) {
return logBad(); return logBad();
} }
return applyRegular(data.vuser_id()); return applyRegular(data.userId());
}, [&](const MTPDchannelParticipant &data) -> PeerData* { }
if (overrideRole != Role::Profile case Api::ChatParticipant::Type::Restricted:
&& overrideRole != Role::Members) { case Api::ChatParticipant::Type::Banned:
return logBad();
}
return applyRegular(data.vuser_id());
}, [&](const MTPDchannelParticipantBanned &data) {
if (overrideRole != Role::Profile if (overrideRole != Role::Profile
&& overrideRole != Role::Members && overrideRole != Role::Members
&& overrideRole != Role::Restricted && overrideRole != Role::Restricted
@ -652,23 +648,23 @@ PeerData *ParticipantsAdditionalData::applyParticipant(
return logBad(); return logBad();
} }
return applyBanned(data); return applyBanned(data);
}, [&](const MTPDchannelParticipantLeft &data) { case Api::ChatParticipant::Type::Left:
return logBad(); return logBad();
}); };
} }
UserData *ParticipantsAdditionalData::applyCreator( UserData *ParticipantsAdditionalData::applyCreator(
const MTPDchannelParticipantCreator &data) { const Api::ChatParticipant &data) {
if (const auto user = applyRegular(data.vuser_id())) { if (const auto user = applyRegular(data.userId())) {
_creator = user; _creator = user;
_adminRights[user] = ChatAdminRightsInfo(data.vadmin_rights()); _adminRights[user] = data.rights();
if (user->isSelf()) { if (user->isSelf()) {
_adminCanEdit.emplace(user); _adminCanEdit.emplace(user);
} else { } else {
_adminCanEdit.erase(user); _adminCanEdit.erase(user);
} }
if (const auto rank = data.vrank()) { if (data.rank().isEmpty()) {
_adminRanks[user] = qs(*rank); _adminRanks[user] = data.rank();
} else { } else {
_adminRanks.remove(user); _adminRanks.remove(user);
} }
@ -678,8 +674,8 @@ UserData *ParticipantsAdditionalData::applyCreator(
} }
UserData *ParticipantsAdditionalData::applyAdmin( UserData *ParticipantsAdditionalData::applyAdmin(
const MTPDchannelParticipantAdmin &data) { const Api::ChatParticipant &data) {
const auto user = _peer->owner().userLoaded(UserId(data.vuser_id().v)); const auto user = _peer->owner().userLoaded(data.userId());
if (!user) { if (!user) {
return nullptr; return nullptr;
} else if (const auto chat = _peer->asChat()) { } else if (const auto chat = _peer->asChat()) {
@ -692,18 +688,18 @@ UserData *ParticipantsAdditionalData::applyAdmin(
_restrictedRights.erase(user); _restrictedRights.erase(user);
_kicked.erase(user); _kicked.erase(user);
_restrictedBy.erase(user); _restrictedBy.erase(user);
_adminRights[user] = ChatAdminRightsInfo(data.vadmin_rights()); _adminRights[user] = data.rights();
if (data.is_can_edit()) { if (data.canBeEdited()) {
_adminCanEdit.emplace(user); _adminCanEdit.emplace(user);
} else { } else {
_adminCanEdit.erase(user); _adminCanEdit.erase(user);
} }
if (const auto rank = data.vrank()) { if (data.rank().isEmpty()) {
_adminRanks[user] = qs(*rank); _adminRanks[user] = data.rank();
} else { } else {
_adminRanks.remove(user); _adminRanks.remove(user);
} }
if (const auto by = _peer->owner().userLoaded(data.vpromoted_by())) { if (const auto by = _peer->owner().userLoaded(data.by())) {
const auto i = _adminPromotedBy.find(user); const auto i = _adminPromotedBy.find(user);
if (i == _adminPromotedBy.end()) { if (i == _adminPromotedBy.end()) {
_adminPromotedBy.emplace(user, by); _adminPromotedBy.emplace(user, by);
@ -712,12 +708,12 @@ UserData *ParticipantsAdditionalData::applyAdmin(
} }
} else { } else {
LOG(("API Error: No user %1 for admin promoted by." LOG(("API Error: No user %1 for admin promoted by."
).arg(data.vpromoted_by().v)); ).arg(data.by().bare));
} }
return user; return user;
} }
UserData *ParticipantsAdditionalData::applyRegular(MTPlong userId) { UserData *ParticipantsAdditionalData::applyRegular(UserId userId) {
const auto user = _peer->owner().userLoaded(userId); const auto user = _peer->owner().userLoaded(userId);
if (!user) { if (!user) {
return nullptr; return nullptr;
@ -738,9 +734,8 @@ UserData *ParticipantsAdditionalData::applyRegular(MTPlong userId) {
} }
PeerData *ParticipantsAdditionalData::applyBanned( PeerData *ParticipantsAdditionalData::applyBanned(
const MTPDchannelParticipantBanned &data) { const Api::ChatParticipant &data) {
const auto participant = _peer->owner().peerLoaded( const auto participant = _peer->owner().peerLoaded(data.id());
peerFromMTP(data.vpeer()));
if (!participant) { if (!participant) {
return nullptr; return nullptr;
} }
@ -751,14 +746,13 @@ PeerData *ParticipantsAdditionalData::applyBanned(
_adminCanEdit.erase(user); _adminCanEdit.erase(user);
_adminPromotedBy.erase(user); _adminPromotedBy.erase(user);
} }
if (data.is_left()) { if (data.isKicked()) {
_kicked.emplace(participant); _kicked.emplace(participant);
} else { } else {
_kicked.erase(participant); _kicked.erase(participant);
} }
_restrictedRights[participant] = ChatRestrictionsInfo( _restrictedRights[participant] = data.restrictions();
data.vbanned_rights()); if (const auto by = _peer->owner().userLoaded(data.by())) {
if (const auto by = _peer->owner().userLoaded(data.vkicked_by())) {
const auto i = _restrictedBy.find(participant); const auto i = _restrictedBy.find(participant);
if (i == _restrictedBy.end()) { if (i == _restrictedBy.end()) {
_restrictedBy.emplace(participant, by); _restrictedBy.emplace(participant, by);
@ -1395,17 +1389,11 @@ void ParticipantsBoxController::loadMoreRows() {
auto wasRecentRequest = firstLoad auto wasRecentRequest = firstLoad
&& (_role == Role::Members || _role == Role::Profile); && (_role == Role::Members || _role == Role::Profile);
auto parseParticipants = [&](auto &&result, auto &&callback) {
auto &api = channel->session().api().chatParticipants(); result.match([&](const MTPDchannels_channelParticipants &data) {
if (wasRecentRequest) { const auto &[availableCount, list] = wasRecentRequest
api.parseRecent(channel, result, callback); ? Api::ChatParticipants::ParseRecent(channel, data)
} else { : Api::ChatParticipants::Parse(channel, data);
api.parse(channel, result, callback);
}
};
parseParticipants(result, [&](
int availableCount,
const QVector<MTPChannelParticipant> &list) {
for (const auto &data : list) { for (const auto &data : list) {
if (const auto participant = _additional.applyParticipant( if (const auto participant = _additional.applyParticipant(
data)) { data)) {
@ -1418,6 +1406,9 @@ void ParticipantsBoxController::loadMoreRows() {
// To be sure - wait for a whole empty result list. // To be sure - wait for a whole empty result list.
_allLoaded = true; _allLoaded = true;
} }
}, [](const MTPDchannels_channelParticipantsNotModified &) {
LOG(("API Error: "
"channels.channelParticipantsNotModified received!"));
}); });
if (_allLoaded if (_allLoaded
@ -2011,7 +2002,12 @@ void ParticipantsBoxController::subscribeToCreatorChange(
channel->mgInfo->lastAdmins.clear(); channel->mgInfo->lastAdmins.clear();
channel->mgInfo->lastRestricted.clear(); channel->mgInfo->lastRestricted.clear();
channel->mgInfo->lastParticipants.clear(); channel->mgInfo->lastParticipants.clear();
api->chatParticipants().parseRecent(channel, result);
result.match([&](const MTPDchannels_channelParticipants &data) {
Api::ChatParticipants::ParseRecent(channel, data);
}, [](const MTPDchannels_channelParticipantsNotModified &) {
});
if (weak) { if (weak) {
fullListRefresh(); fullListRefresh();
} }
@ -2176,10 +2172,13 @@ void ParticipantsBoxSearchController::searchDone(
_queries.erase(it); _queries.erase(it);
} }
}; };
_channel->session().api().chatParticipants().parse( result.match([&](const MTPDchannels_channelParticipants &data) {
_channel, Api::ChatParticipants::Parse(_channel, data);
result, addToCache();
addToCache); }, [&](const MTPDchannels_channelParticipantsNotModified &) {
LOG(("API Error: "
"channels.channelParticipantsNotModified received!"));
});
} }
if (_requestId != requestId) { if (_requestId != requestId) {
return; return;
@ -2199,7 +2198,7 @@ void ParticipantsBoxSearchController::searchDone(
: _role; : _role;
for (const auto &data : list) { for (const auto &data : list) {
const auto user = _additional->applyParticipant( const auto user = _additional->applyParticipant(
data, Api::ChatParticipant(data, _channel),
overrideRole); overrideRole);
if (user) { if (user) {
delegate()->peerListSearchAddRow(user); delegate()->peerListSearchAddRow(user);

View file

@ -21,6 +21,10 @@ namespace Window {
class SessionNavigation; class SessionNavigation;
} // namespace Window } // namespace Window
namespace Api {
class ChatParticipant;
} // namespace Api
Fn<void( Fn<void(
ChatAdminRightsInfo oldRights, ChatAdminRightsInfo oldRights,
ChatAdminRightsInfo newRights, ChatAdminRightsInfo newRights,
@ -80,9 +84,9 @@ public:
ParticipantsAdditionalData(not_null<PeerData*> peer, Role role); ParticipantsAdditionalData(not_null<PeerData*> peer, Role role);
PeerData *applyParticipant(const MTPChannelParticipant &data); PeerData *applyParticipant(const Api::ChatParticipant &data);
PeerData *applyParticipant( PeerData *applyParticipant(
const MTPChannelParticipant &data, const Api::ChatParticipant &data,
Role overrideRole); Role overrideRole);
void setExternal(not_null<PeerData*> participant); void setExternal(not_null<PeerData*> participant);
void checkForLoaded(not_null<PeerData*> participant); void checkForLoaded(not_null<PeerData*> participant);
@ -117,10 +121,10 @@ public:
ChatRestrictionsInfo rights); ChatRestrictionsInfo rights);
private: private:
UserData *applyCreator(const MTPDchannelParticipantCreator &data); UserData *applyCreator(const Api::ChatParticipant &data);
UserData *applyAdmin(const MTPDchannelParticipantAdmin &data); UserData *applyAdmin(const Api::ChatParticipant &data);
UserData *applyRegular(MTPlong userId); UserData *applyRegular(UserId userId);
PeerData *applyBanned(const MTPDchannelParticipantBanned &data); PeerData *applyBanned(const Api::ChatParticipant &data);
void fillFromChat(not_null<ChatData*> chat); void fillFromChat(not_null<ChatData*> chat);
void fillFromChannel(not_null<ChannelData*> channel); void fillFromChannel(not_null<ChannelData*> channel);

View file

@ -445,44 +445,27 @@ void InnerWidget::requestAdmins() {
MTP_int(kMaxChannelAdmins), MTP_int(kMaxChannelAdmins),
MTP_long(participantsHash) MTP_long(participantsHash)
)).done([=](const MTPchannels_ChannelParticipants &result) { )).done([=](const MTPchannels_ChannelParticipants &result) {
session().api().chatParticipants().parse(_channel, result, [&]( result.match([&](const MTPDchannels_channelParticipants &data) {
int availableCount, const auto &[availableCount, list] = Api::ChatParticipants::Parse(
const QVector<MTPChannelParticipant> &list) { _channel,
auto filtered = ( data);
list _admins.clear();
) | ranges::views::transform([&](const MTPChannelParticipant &p) { _adminsCanEdit.clear();
const auto participantId = p.match([]( for (const auto &parsed : list) {
const MTPDchannelParticipantBanned &data) { if (parsed.isUser()) {
return peerFromMTP(data.vpeer()); const auto user = _channel->owner().userLoaded(
}, [](const MTPDchannelParticipantLeft &data) { parsed.userId());
return peerFromMTP(data.vpeer()); if (user) {
}, [](const auto &data) { _admins.emplace_back(user);
return peerFromUser(data.vuser_id()); if (parsed.canBeEdited() && !parsed.isCreator()) {
}); _adminsCanEdit.emplace_back(user);
const auto canEdit = p.match([]( }
const MTPDchannelParticipantAdmin &data) { }
return data.is_can_edit();
}, [](const auto &) {
return false;
});
return std::make_pair(participantId, canEdit);
}) | ranges::views::transform([&](auto &&pair) {
return std::make_pair(
(peerIsUser(pair.first)
? session().data().userLoaded(
peerToUser(pair.first))
: nullptr),
pair.second);
}) | ranges::views::filter([&](auto &&pair) {
return (pair.first != nullptr);
});
for (auto [user, canEdit] : filtered) {
_admins.emplace_back(user);
if (canEdit) {
_adminsCanEdit.emplace_back(user);
} }
} }
}, [&](const MTPDchannels_channelParticipantsNotModified &) {
LOG(("API Error: c"
"hannels.channelParticipantsNotModified received!"));
}); });
if (_admins.empty()) { if (_admins.empty()) {
_admins.push_back(session().user()); _admins.push_back(session().user());

View file

@ -1092,34 +1092,24 @@ void PeerMenuAddChannelMembers(
} }
const auto api = &channel->session().api(); const auto api = &channel->session().api();
api->chatParticipants().requestForAdd(channel, crl::guard(navigation, [=]( api->chatParticipants().requestForAdd(channel, crl::guard(navigation, [=](
const MTPchannels_ChannelParticipants &result) { const Api::ChatParticipants::TLMembers &data) {
api->chatParticipants().parse(channel, result, [&]( const auto &[availableCount, list] = Api::ChatParticipants::Parse(
int availableCount, channel,
const QVector<MTPChannelParticipant> &list) { data);
auto already = ( const auto already = (
list list
) | ranges::views::transform([](const MTPChannelParticipant &p) { ) | ranges::views::transform([&](const Api::ChatParticipant &p) {
return p.match([](const MTPDchannelParticipantBanned &data) { return p.isUser()
return peerFromMTP(data.vpeer()); ? channel->owner().userLoaded(p.userId())
}, [](const MTPDchannelParticipantLeft &data) { : nullptr;
return peerFromMTP(data.vpeer()); }) | ranges::views::filter([](UserData *user) {
}, [](const auto &data) { return (user != nullptr);
return peerFromUser(data.vuser_id()); }) | ranges::to_vector;
});
}) | 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;
AddParticipantsBoxController::Start( AddParticipantsBoxController::Start(
navigation, navigation,
channel, channel,
{ already.begin(), already.end() }); { already.begin(), already.end() });
});
})); }));
} }