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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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