mirror of https://github.com/procxx/kepka.git
Request all admins when first opening a supergroup.
This commit is contained in:
parent
9ba482f56f
commit
f3c8da4819
|
@ -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));
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue