Request all admins when first opening a supergroup.

This commit is contained in:
John Preston 2017-12-03 20:43:42 +04:00
parent 9ba482f56f
commit f3c8da4819
7 changed files with 263 additions and 178 deletions

View File

@ -565,15 +565,8 @@ void ApiWrap::requestPeers(const QList<PeerData*> &peers) {
} }
} }
void ApiWrap::requestLastParticipants(ChannelData *channel) { void ApiWrap::requestLastParticipants(not_null<ChannelData*> channel) {
if (!channel || !channel->isMegagroup()) { if (!channel->isMegagroup() || _participantsRequests.contains(channel)) {
return;
}
auto needAdmins = channel->canViewAdmins();
auto adminsOutdated = (channel->mgInfo->lastParticipantsStatus & MegagroupInfo::LastParticipantsAdminsOutdated) != 0;
auto i = _participantsRequests.find(channel);
if (i != _participantsRequests.cend()) {
return; return;
} }
@ -585,20 +578,25 @@ void ApiWrap::requestLastParticipants(ChannelData *channel) {
MTP_int(offset), MTP_int(offset),
MTP_int(Global::ChatSizeMax()), MTP_int(Global::ChatSizeMax()),
MTP_int(participantsHash) MTP_int(participantsHash)
)).done([this, channel](const MTPchannels_ChannelParticipants &result, mtpRequestId requestId) { )).done([this, channel](const MTPchannels_ChannelParticipants &result) {
lastParticipantsDone(channel, result, requestId); _participantsRequests.remove(channel);
}).fail([this, channel](const RPCError &error, mtpRequestId requestId) { parseChannelParticipants(channel, result, [&](
if (_participantsRequests.value(channel) == requestId int availableCount,
|| _participantsRequests.value(channel) == -requestId) { const QVector<MTPChannelParticipant> &list) {
_participantsRequests.remove(channel); applyLastParticipantsList(
} channel,
availableCount,
list);
});
}).fail([this, channel](const RPCError &error) {
_participantsRequests.remove(channel);
}).send(); }).send();
_participantsRequests.insert(channel, requestId); _participantsRequests.insert(channel, requestId);
} }
void ApiWrap::requestBots(ChannelData *channel) { void ApiWrap::requestBots(not_null<ChannelData*> channel) {
if (!channel || !channel->isMegagroup() || _botsRequests.contains(channel)) { if (!channel->isMegagroup() || _botsRequests.contains(channel)) {
return; return;
} }
@ -610,154 +608,203 @@ void ApiWrap::requestBots(ChannelData *channel) {
MTP_int(offset), MTP_int(offset),
MTP_int(Global::ChatSizeMax()), MTP_int(Global::ChatSizeMax()),
MTP_int(participantsHash) MTP_int(participantsHash)
)).done([this, channel](const MTPchannels_ChannelParticipants &result, mtpRequestId requestId) { )).done([this, channel](const MTPchannels_ChannelParticipants &result) {
lastParticipantsDone(channel, result, requestId); _botsRequests.remove(channel);
}).fail([this, channel](const RPCError &error, mtpRequestId requestId) { parseChannelParticipants(channel, result, [&](
if (_botsRequests.value(channel) == requestId) { int availableCount,
_botsRequests.remove(channel); const QVector<MTPChannelParticipant> &list) {
} applyBotsList(
channel,
availableCount,
list);
});
}).fail([this, channel](const RPCError &error) {
_botsRequests.remove(channel);
}).send(); }).send();
_botsRequests.insert(channel, requestId); _botsRequests.insert(channel, requestId);
} }
void ApiWrap::lastParticipantsDone( void ApiWrap::requestAdmins(not_null<ChannelData*> channel) {
ChannelData *peer, if (!channel->isMegagroup() || _adminsRequests.contains(channel)) {
const MTPchannels_ChannelParticipants &result, return;
mtpRequestId requestId) {
auto bots = (_botsRequests.value(peer) == requestId);
auto fromStart = false;
if (bots) {
_botsRequests.remove(peer);
} else {
auto was = _participantsRequests.value(peer);
if (was == requestId) {
fromStart = true;
} else if (was != -requestId) {
return;
}
_participantsRequests.remove(peer);
} }
if (!peer->mgInfo) return; auto offset = 0;
auto participantsHash = 0;
auto requestId = request(MTPchannels_GetParticipants(
channel->inputChannel,
MTP_channelParticipantsAdmins(),
MTP_int(offset),
MTP_int(Global::ChatSizeMax()),
MTP_int(participantsHash)
)).done([this, channel](const MTPchannels_ChannelParticipants &result) {
_adminsRequests.remove(channel);
TLHelp::VisitChannelParticipants(result, base::overload([&](
const MTPDchannels_channelParticipants &data) {
App::feedUsers(data.vusers);
applyAdminsList(
channel,
data.vcount.v,
data.vparticipants.v);
}, [&](mtpTypeId) {
LOG(("API Error: channels.channelParticipantsNotModified received!"));
}));
}).fail([this, channel](const RPCError &error) {
_adminsRequests.remove(channel);
}).send();
parseChannelParticipants(peer, result, [&]( _adminsRequests.insert(channel, requestId);
int availableCount,
const QVector<MTPChannelParticipant> &list) {
applyLastParticipantsList(
peer,
availableCount,
list,
bots,
fromStart);
});
} }
void ApiWrap::applyLastParticipantsList( void ApiWrap::applyLastParticipantsList(
ChannelData *peer, not_null<ChannelData*> channel,
int availableCount, int availableCount,
const QVector<MTPChannelParticipant> &list, const QVector<MTPChannelParticipant> &list) {
bool bots, channel->mgInfo->lastAdmins.clear();
bool fromStart) { channel->mgInfo->lastRestricted.clear();
auto h = bots ? App::historyLoaded(peer->id) : nullptr; channel->mgInfo->lastParticipants.clear();
if (bots) { channel->mgInfo->lastParticipantsStatus = MegagroupInfo::LastParticipantsUpToDate;
peer->mgInfo->bots.clear();
peer->mgInfo->botStatus = -1;
} else if (fromStart) {
peer->mgInfo->lastAdmins.clear();
peer->mgInfo->lastParticipants.clear();
peer->mgInfo->lastParticipantsStatus = MegagroupInfo::LastParticipantsUpToDate;
}
auto added = false; auto botStatus = channel->mgInfo->botStatus;
auto needBotsInfos = false; const auto emptyAdminRights = MTP_channelAdminRights(MTP_flags(0));
auto botStatus = peer->mgInfo->botStatus; const auto emptyRestrictedRights = MTP_channelBannedRights(
auto keyboardBotFound = !h || !h->lastKeyboardFrom; MTP_flags(0),
auto emptyAdminRights = MTP_channelAdminRights(MTP_flags(0)); MTP_int(0));
auto emptyRestrictedRights = MTP_channelBannedRights(MTP_flags(0), MTP_int(0)); for (const auto &p : list) {
for (auto &participant : list) { const auto userId = TLHelp::ReadChannelParticipantUserId(p);
auto userId = UserId(0); const auto adminCanEdit = (p.type() == mtpc_channelParticipantAdmin)
auto adminCanEdit = false; ? p.c_channelParticipantAdmin().is_can_edit()
auto adminRights = emptyAdminRights; : false;
auto restrictedRights = emptyRestrictedRights; const auto adminRights = (p.type() == mtpc_channelParticipantAdmin)
? p.c_channelParticipantAdmin().vadmin_rights
switch (participant.type()) { : emptyAdminRights;
case mtpc_channelParticipant: userId = participant.c_channelParticipant().vuser_id.v; break; const auto restrictedRights = (p.type() == mtpc_channelParticipantBanned)
case mtpc_channelParticipantSelf: userId = participant.c_channelParticipantSelf().vuser_id.v; break; ? p.c_channelParticipantBanned().vbanned_rights
case mtpc_channelParticipantAdmin: : emptyRestrictedRights;
userId = participant.c_channelParticipantAdmin().vuser_id.v;
adminCanEdit = participant.c_channelParticipantAdmin().is_can_edit();
adminRights = participant.c_channelParticipantAdmin().vadmin_rights;
break;
case mtpc_channelParticipantBanned:
userId = participant.c_channelParticipantBanned().vuser_id.v;
restrictedRights = participant.c_channelParticipantBanned().vbanned_rights;
break;
case mtpc_channelParticipantCreator: userId = participant.c_channelParticipantCreator().vuser_id.v; break;
}
if (!userId) { if (!userId) {
continue; continue;
} }
auto u = App::user(userId); auto user = App::user(userId);
if (participant.type() == mtpc_channelParticipantCreator) { if (p.type() == mtpc_channelParticipantCreator) {
peer->mgInfo->creator = u; channel->mgInfo->creator = user;
if (!channel->mgInfo->admins.empty()
&& !channel->mgInfo->admins.contains(userId)) {
Data::ChannelAdminChanges changes(channel);
changes.feed(userId, true);
}
} }
if (bots) { if (!base::contains(channel->mgInfo->lastParticipants, user)) {
if (u->botInfo) { channel->mgInfo->lastParticipants.push_back(user);
peer->mgInfo->bots.insert(u); if (adminRights.c_channelAdminRights().vflags.v) {
botStatus = 2;// (botStatus > 0/* || !i.key()->botInfo->readsAllHistory*/) ? 2 : 1; channel->mgInfo->lastAdmins.emplace(
if (!u->botInfo->inited) { user,
needBotsInfos = true; MegagroupInfo::Admin{ adminRights, adminCanEdit });
} else if (restrictedRights.c_channelBannedRights().vflags.v != 0) {
channel->mgInfo->lastRestricted.emplace(
user,
MegagroupInfo::Restricted{ restrictedRights });
}
if (user->botInfo) {
channel->mgInfo->bots.insert(user);
if (channel->mgInfo->botStatus != 0 && channel->mgInfo->botStatus < 2) {
channel->mgInfo->botStatus = 2;
} }
} }
if (!keyboardBotFound && u->id == h->lastKeyboardFrom) { }
keyboardBotFound = true; }
} //
} else { // getParticipants(Recent) sometimes can't return all members,
if (!base::contains(peer->mgInfo->lastParticipants, u)) { // only some last subset, size of this subset is availableCount.
peer->mgInfo->lastParticipants.push_back(u); //
if (adminRights.c_channelAdminRights().vflags.v) { // So both list size and availableCount have nothing to do with
peer->mgInfo->lastAdmins.emplace(u, MegagroupInfo::Admin { adminRights, adminCanEdit }); // the full supergroup members count.
} else if (restrictedRights.c_channelBannedRights().vflags.v != 0) { //
peer->mgInfo->lastRestricted.emplace(u, MegagroupInfo::Restricted { restrictedRights }); //if (list.isEmpty()) {
} // channel->setMembersCount(channel->mgInfo->lastParticipants.size());
if (u->botInfo) { //} else {
peer->mgInfo->bots.insert(u); // channel->setMembersCount(availableCount);
if (peer->mgInfo->botStatus != 0 && peer->mgInfo->botStatus < 2) { //}
peer->mgInfo->botStatus = 2; Notify::PeerUpdate update(channel);
} update.flags |= Notify::PeerUpdate::Flag::MembersChanged | Notify::PeerUpdate::Flag::AdminsChanged;
} Notify::peerUpdatedDelayed(update);
added = true;
channel->mgInfo->botStatus = botStatus;
if (App::main()) fullPeerUpdated().notify(channel);
}
void ApiWrap::applyBotsList(
not_null<ChannelData*> channel,
int availableCount,
const QVector<MTPChannelParticipant> &list) {
const auto history = App::historyLoaded(channel->id);
channel->mgInfo->bots.clear();
channel->mgInfo->botStatus = -1;
auto needBotsInfos = false;
auto botStatus = channel->mgInfo->botStatus;
auto keyboardBotFound = !history || !history->lastKeyboardFrom;
for (const auto &p : list) {
const auto userId = TLHelp::ReadChannelParticipantUserId(p);
if (!userId) {
continue;
}
auto user = App::user(userId);
if (user->botInfo) {
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) {
keyboardBotFound = true;
}
} }
if (needBotsInfos) { if (needBotsInfos) {
requestFullPeer(peer); requestFullPeer(channel);
} }
if (!keyboardBotFound) { if (!keyboardBotFound) {
h->clearLastKeyboard(); history->clearLastKeyboard();
}
if (!bots) {
//
// getParticipants(Recent) sometimes can't return all members,
// only some last subset, size of this subset is availableCount.
//
// So both list size and availableCount have nothing to do with
// the full supergroup members count.
//
//if (list.isEmpty()) {
// peer->setMembersCount(peer->mgInfo->lastParticipants.size());
//} else {
// peer->setMembersCount(availableCount);
//}
Notify::PeerUpdate update(peer);
update.flags |= Notify::PeerUpdate::Flag::MembersChanged | Notify::PeerUpdate::Flag::AdminsChanged;
Notify::peerUpdatedDelayed(update);
} }
peer->mgInfo->botStatus = botStatus; channel->mgInfo->botStatus = botStatus;
if (App::main()) fullPeerUpdated().notify(peer); if (App::main()) fullPeerUpdated().notify(channel);
}
void ApiWrap::applyAdminsList(
not_null<ChannelData*> channel,
int availableCount,
const QVector<MTPChannelParticipant> &list) {
auto admins = ranges::make_iterator_range(
list.begin(), list.end()
) | ranges::view::transform([](const MTPChannelParticipant &p) {
return TLHelp::ReadChannelParticipantUserId(p);
});
auto adding = base::flat_set<UserId>{ admins.begin(), admins.end() };
if (channel->mgInfo->creator) {
adding.insert(peerToUser(channel->mgInfo->creator->id));
}
auto removing = channel->mgInfo->admins;
if (removing.empty() && adding.empty()) {
// Add some admin-placeholder so we don't DDOS
// server with admins list requests.
LOG(("API Error: Got empty admins list from server."));
adding.insert(0);
}
Data::ChannelAdminChanges changes(channel);
for (const auto addingId : adding) {
if (!removing.remove(addingId)) {
changes.feed(addingId, true);
}
}
for (const auto removingId : removing) {
changes.feed(removingId, false);
}
} }
void ApiWrap::requestSelfParticipant(ChannelData *channel) { void ApiWrap::requestSelfParticipant(ChannelData *channel) {
@ -765,7 +812,10 @@ void ApiWrap::requestSelfParticipant(ChannelData *channel) {
return; return;
} }
auto requestId = request(MTPchannels_GetParticipant(channel->inputChannel, MTP_inputUserSelf())).done([this, channel](const MTPchannels_ChannelParticipant &result) { auto requestId = request(MTPchannels_GetParticipant(
channel->inputChannel,
MTP_inputUserSelf()
)).done([this, channel](const MTPchannels_ChannelParticipant &result) {
_selfParticipantRequests.remove(channel); _selfParticipantRequests.remove(channel);
if (result.type() != mtpc_channels_channelParticipant) { if (result.type() != mtpc_channels_channelParticipant) {
LOG(("API Error: unknown type in gotSelfParticipant (%1)").arg(result.type())); LOG(("API Error: unknown type in gotSelfParticipant (%1)").arg(result.type()));
@ -1500,10 +1550,11 @@ void ApiWrap::resolveWebPages() {
} }
} }
void ApiWrap::requestParticipantsCountDelayed(ChannelData *channel) { void ApiWrap::requestParticipantsCountDelayed(
_participantsCountRequestTimer.call(kReloadChannelMembersTimeout, [this, channel] { not_null<ChannelData*> channel) {
channel->updateFullForced(); _participantsCountRequestTimer.call(
}); kReloadChannelMembersTimeout,
[this, channel] { channel->updateFullForced(); });
} }
void ApiWrap::gotWebPages(ChannelData *channel, const MTPmessages_Messages &msgs, mtpRequestId req) { void ApiWrap::gotWebPages(ChannelData *channel, const MTPmessages_Messages &msgs, mtpRequestId req) {
@ -1819,9 +1870,7 @@ void ApiWrap::parseRecentChannelParticipants(
applyLastParticipantsList( applyLastParticipantsList(
channel, channel,
availableCount, availableCount,
list, list);
false,
true);
} }
callbackList(availableCount, list); callbackList(availableCount, list);
}, std::move(callbackNotModified)); }, std::move(callbackNotModified));

View File

@ -61,9 +61,10 @@ public:
void requestFullPeer(PeerData *peer); void requestFullPeer(PeerData *peer);
void requestPeer(PeerData *peer); void requestPeer(PeerData *peer);
void requestPeers(const QList<PeerData*> &peers); void requestPeers(const QList<PeerData*> &peers);
void requestLastParticipants(ChannelData *channel); void requestLastParticipants(not_null<ChannelData*> channel);
void requestBots(ChannelData *channel); void requestBots(not_null<ChannelData*> channel);
void requestParticipantsCountDelayed(ChannelData *channel); void requestAdmins(not_null<ChannelData*> channel);
void requestParticipantsCountDelayed(not_null<ChannelData*> channel);
void requestChannelMembersForAdd( void requestChannelMembersForAdd(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
@ -187,16 +188,18 @@ private:
void gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mtpRequestId req); void gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mtpRequestId req);
void gotUserFull(UserData *user, const MTPUserFull &result, mtpRequestId req); void gotUserFull(UserData *user, const MTPUserFull &result, mtpRequestId req);
void lastParticipantsDone(
ChannelData *peer,
const MTPchannels_ChannelParticipants &result,
mtpRequestId req);
void applyLastParticipantsList( void applyLastParticipantsList(
ChannelData *peer, not_null<ChannelData*> channel,
int availableCount, int availableCount,
const QVector<MTPChannelParticipant> &list, const QVector<MTPChannelParticipant> &list);
bool bots, void applyBotsList(
bool fromStart); not_null<ChannelData*> channel,
int availableCount,
const QVector<MTPChannelParticipant> &list);
void applyAdminsList(
not_null<ChannelData*> channel,
int availableCount,
const QVector<MTPChannelParticipant> &list);
void resolveWebPages(); void resolveWebPages();
void gotWebPages(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId req); void gotWebPages(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId req);
void gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result); void gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result);
@ -255,6 +258,7 @@ private:
PeerRequests _participantsRequests; PeerRequests _participantsRequests;
PeerRequests _botsRequests; PeerRequests _botsRequests;
PeerRequests _adminsRequests;
base::DelayedCallTimer _participantsCountRequestTimer; base::DelayedCallTimer _participantsCountRequestTimer;
ChannelData *_channelMembersForAdd = nullptr; ChannelData *_channelMembersForAdd = nullptr;

View File

@ -755,7 +755,6 @@ struct MegagroupInfo {
enum LastParticipantsStatus { enum LastParticipantsStatus {
LastParticipantsUpToDate = 0x00, LastParticipantsUpToDate = 0x00,
LastParticipantsAdminsOutdated = 0x01,
LastParticipantsCountOutdated = 0x02, LastParticipantsCountOutdated = 0x02,
}; };
mutable int lastParticipantsStatus = LastParticipantsUpToDate; mutable int lastParticipantsStatus = LastParticipantsUpToDate;

View File

@ -948,7 +948,6 @@ HistoryItem *History::createItem(const MTPMessage &msg, bool applyServiceAction,
if (auto user = App::userLoaded(peerFromUser(v[i]))) { if (auto user = App::userLoaded(peerFromUser(v[i]))) {
if (!base::contains(mgInfo->lastParticipants, user)) { if (!base::contains(mgInfo->lastParticipants, user)) {
mgInfo->lastParticipants.push_front(user); mgInfo->lastParticipants.push_front(user);
mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsAdminsOutdated;
Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::MembersChanged); Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::MembersChanged);
Auth().data().addNewMegagroupParticipant(megagroup, user); Auth().data().addNewMegagroupParticipant(megagroup, user);
} }
@ -1339,7 +1338,7 @@ HistoryItem *History::addNewItem(HistoryItem *adding, bool newMsg) {
if (index > 0) { if (index > 0) {
lastAuthors->erase(prev); lastAuthors->erase(prev);
} else if (index < 0 && peer->isMegagroup()) { // nothing is outdated if just reordering } else if (index < 0 && peer->isMegagroup()) { // nothing is outdated if just reordering
peer->asChannel()->mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsAdminsOutdated; // admins information outdated
} }
if (index) { if (index) {
lastAuthors->push_front(user); lastAuthors->push_front(user);
@ -1610,10 +1609,6 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice) {
if (auto user = item->from()->asUser()) { if (auto user = item->from()->asUser()) {
if (!base::contains(*lastAuthors, user)) { if (!base::contains(*lastAuthors, user)) {
lastAuthors->push_back(user); lastAuthors->push_back(user);
if (peer->isMegagroup()) {
peer->asChannel()->mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsAdminsOutdated;
Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::MembersChanged);
}
} }
} }
} }

View File

@ -5989,8 +5989,13 @@ void HistoryWidget::handlePeerUpdate() {
Auth().api().requestFullPeer(_peer); Auth().api().requestFullPeer(_peer);
} else if (_peer->isUser() && (_peer->asUser()->blockStatus() == UserData::BlockStatus::Unknown || _peer->asUser()->callsStatus() == UserData::CallsStatus::Unknown)) { } else if (_peer->isUser() && (_peer->asUser()->blockStatus() == UserData::BlockStatus::Unknown || _peer->asUser()->callsStatus() == UserData::CallsStatus::Unknown)) {
Auth().api().requestFullPeer(_peer); Auth().api().requestFullPeer(_peer);
} else if (_peer->isMegagroup() && !_peer->asChannel()->mgInfo->botStatus) { } else if (auto channel = _peer->asMegagroup()) {
Auth().api().requestBots(_peer->asChannel()); if (!channel->mgInfo->botStatus) {
Auth().api().requestBots(channel);
}
if (channel->mgInfo->admins.empty()) {
Auth().api().requestAdmins(channel);
}
} }
if (!_a_show.animating()) { if (!_a_show.animating()) {
if (_unblock->isHidden() == isBlocked() || (!isBlocked() && _joinChannel->isHidden() == isJoinChannel())) { if (_unblock->isHidden() == isBlocked() || (!isBlocked() && _joinChannel->isHidden() == isJoinChannel())) {

View File

@ -1233,24 +1233,47 @@ void MainWidget::deleteAllFromUserPart(DeleteAllFromUserParams params, const MTP
} }
} }
void MainWidget::addParticipants(PeerData *chatOrChannel, const std::vector<not_null<UserData*>> &users) { void MainWidget::addParticipants(
if (chatOrChannel->isChat()) { not_null<PeerData*> chatOrChannel,
auto chat = chatOrChannel->asChat(); const std::vector<not_null<UserData*>> &users) {
if (auto chat = chatOrChannel->asChat()) {
for_const (auto user, users) { for_const (auto user, users) {
MTP::send(MTPmessages_AddChatUser(chat->inputChat, user->inputUser, MTP_int(ForwardOnAdd)), rpcDone(&MainWidget::sentUpdatesReceived), rpcFail(&MainWidget::addParticipantFail, { user, chat }), 0, 5); MTP::send(
MTPmessages_AddChatUser(
chat->inputChat,
user->inputUser,
MTP_int(ForwardOnAdd)),
rpcDone(&MainWidget::sentUpdatesReceived),
rpcFail(&MainWidget::addParticipantFail, { user, chat }),
0,
5);
} }
} else if (chatOrChannel->isChannel()) { } else if (auto channel = chatOrChannel->asChannel()) {
QVector<MTPInputUser> inputUsers; QVector<MTPInputUser> inputUsers;
inputUsers.reserve(qMin(int(users.size()), int(MaxUsersPerInvite))); inputUsers.reserve(qMin(int(users.size()), int(MaxUsersPerInvite)));
for (auto i = users.cbegin(), e = users.cend(); i != e; ++i) { for (auto i = users.cbegin(), e = users.cend(); i != e; ++i) {
inputUsers.push_back((*i)->inputUser); inputUsers.push_back((*i)->inputUser);
if (inputUsers.size() == MaxUsersPerInvite) { if (inputUsers.size() == MaxUsersPerInvite) {
MTP::send(MTPchannels_InviteToChannel(chatOrChannel->asChannel()->inputChannel, MTP_vector<MTPInputUser>(inputUsers)), rpcDone(&MainWidget::inviteToChannelDone, chatOrChannel->asChannel()), rpcFail(&MainWidget::addParticipantsFail, chatOrChannel->asChannel()), 0, 5); MTP::send(
MTPchannels_InviteToChannel(
channel->inputChannel,
MTP_vector<MTPInputUser>(inputUsers)),
rpcDone(&MainWidget::inviteToChannelDone, { channel }),
rpcFail(&MainWidget::addParticipantsFail, { channel }),
0,
5);
inputUsers.clear(); inputUsers.clear();
} }
} }
if (!inputUsers.isEmpty()) { if (!inputUsers.isEmpty()) {
MTP::send(MTPchannels_InviteToChannel(chatOrChannel->asChannel()->inputChannel, MTP_vector<MTPInputUser>(inputUsers)), rpcDone(&MainWidget::inviteToChannelDone, chatOrChannel->asChannel()), rpcFail(&MainWidget::addParticipantsFail, chatOrChannel->asChannel()), 0, 5); MTP::send(
MTPchannels_InviteToChannel(
channel->inputChannel,
MTP_vector<MTPInputUser>(inputUsers)),
rpcDone(&MainWidget::inviteToChannelDone, { channel }),
rpcFail(&MainWidget::addParticipantsFail, { channel }),
0,
5);
} }
} }
} }
@ -1275,7 +1298,9 @@ bool MainWidget::addParticipantFail(UserAndPeer data, const RPCError &error) {
return false; return false;
} }
bool MainWidget::addParticipantsFail(ChannelData *channel, const RPCError &error) { bool MainWidget::addParticipantsFail(
not_null<ChannelData*> channel,
const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false; if (MTP::isDefaultHandledError(error)) return false;
QString text = lang(lng_failed_add_participant); QString text = lang(lng_failed_add_participant);
@ -3070,7 +3095,9 @@ bool MainWidget::deleteChannelFailed(const RPCError &error) {
return true; return true;
} }
void MainWidget::inviteToChannelDone(ChannelData *channel, const MTPUpdates &updates) { void MainWidget::inviteToChannelDone(
not_null<ChannelData*> channel,
const MTPUpdates &updates) {
sentUpdatesReceived(updates); sentUpdatesReceived(updates);
Auth().api().requestParticipantsCountDelayed(channel); Auth().api().requestParticipantsCountDelayed(channel);
} }

View File

@ -135,7 +135,9 @@ public:
return sentUpdatesReceived(0, updates); return sentUpdatesReceived(0, updates);
} }
bool deleteChannelFailed(const RPCError &error); bool deleteChannelFailed(const RPCError &error);
void inviteToChannelDone(ChannelData *channel, const MTPUpdates &updates); void inviteToChannelDone(
not_null<ChannelData*> channel,
const MTPUpdates &updates);
void historyToDown(History *hist); void historyToDown(History *hist);
void dialogsToUp(); void dialogsToUp();
void newUnreadMsg(History *history, HistoryItem *item); void newUnreadMsg(History *history, HistoryItem *item);
@ -215,13 +217,17 @@ public:
void deleteAndExit(ChatData *chat); void deleteAndExit(ChatData *chat);
void deleteAllFromUser(ChannelData *channel, UserData *from); void deleteAllFromUser(ChannelData *channel, UserData *from);
void addParticipants(PeerData *chatOrChannel, const std::vector<not_null<UserData*>> &users); void addParticipants(
not_null<PeerData*> chatOrChannel,
const std::vector<not_null<UserData*>> &users);
struct UserAndPeer { struct UserAndPeer {
UserData *user; UserData *user;
PeerData *peer; PeerData *peer;
}; };
bool addParticipantFail(UserAndPeer data, const RPCError &e); bool addParticipantFail(UserAndPeer data, const RPCError &e);
bool addParticipantsFail(ChannelData *channel, const RPCError &e); // for multi invite in channels bool addParticipantsFail(
not_null<ChannelData*> channel,
const RPCError &e); // for multi invite in channels
void kickParticipant(ChatData *chat, UserData *user); void kickParticipant(ChatData *chat, UserData *user);
bool kickParticipantFail(ChatData *chat, const RPCError &e); bool kickParticipantFail(ChatData *chat, const RPCError &e);