mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Moved code for api participants to separated file.
This commit is contained in:
parent
3271cdf251
commit
b9c64499bd
24 changed files with 840 additions and 730 deletions
|
@ -112,6 +112,8 @@ PRIVATE
|
|||
api/api_chat_filters.h
|
||||
api/api_chat_invite.cpp
|
||||
api/api_chat_invite.h
|
||||
api/api_chat_participants.cpp
|
||||
api/api_chat_participants.h
|
||||
api/api_cloud_password.cpp
|
||||
api/api_cloud_password.h
|
||||
api/api_common.h
|
||||
|
|
659
Telegram/SourceFiles/api/api_chat_participants.cpp
Normal file
659
Telegram/SourceFiles/api/api_chat_participants.cpp
Normal file
|
@ -0,0 +1,659 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "api/api_chat_participants.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "boxes/add_contact_box.h" // ShowAddParticipantsError
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_channel_admins.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_histories.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "history/history.h"
|
||||
#include "main/main_session.h"
|
||||
#include "mtproto/mtproto_config.h"
|
||||
|
||||
namespace Api {
|
||||
namespace {
|
||||
|
||||
constexpr auto kSmallDelayMs = crl::time(5);
|
||||
|
||||
// 1 second wait before reload members in channel after adding.
|
||||
constexpr auto kReloadChannelMembersTimeout = 1000;
|
||||
|
||||
// Max users in one super group invite request.
|
||||
constexpr auto kMaxUsersPerInvite = 100;
|
||||
|
||||
// How many messages from chat history server should forward to user,
|
||||
// that was added to this chat.
|
||||
constexpr auto kForwardMessagesOnAdd = 100;
|
||||
|
||||
void ApplyMegagroupAdmins(
|
||||
not_null<ChannelData*> channel,
|
||||
const MTPDchannels_channelParticipants &data) {
|
||||
Expects(channel->isMegagroup());
|
||||
|
||||
channel->owner().processUsers(data.vusers());
|
||||
|
||||
const auto &list = data.vparticipants().v;
|
||||
const auto i = ranges::find(
|
||||
list,
|
||||
mtpc_channelParticipantCreator,
|
||||
&MTPChannelParticipant::type);
|
||||
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());
|
||||
} 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 = 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 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) {
|
||||
adding.emplace(
|
||||
peerToUser(channel->mgInfo->creator->id),
|
||||
channel->mgInfo->creatorRank);
|
||||
}
|
||||
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.emplace(0, QString());
|
||||
}
|
||||
|
||||
Data::ChannelAdminChanges changes(channel);
|
||||
for (const auto &[addingId, rank] : adding) {
|
||||
if (!removing.remove(addingId)) {
|
||||
changes.add(addingId, rank);
|
||||
}
|
||||
}
|
||||
for (const auto &[removingId, rank] : removing) {
|
||||
changes.remove(removingId);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ChatParticipants::ChatParticipants(not_null<ApiWrap*> api)
|
||||
: _session(&api->session())
|
||||
, _api(&api->instance()) {
|
||||
}
|
||||
|
||||
void ChatParticipants::requestForAdd(
|
||||
not_null<ChannelData*> channel,
|
||||
Fn<void(const MTPchannels_ChannelParticipants&)> callback) {
|
||||
_channelMembersForAddCallback = std::move(callback);
|
||||
if (_channelMembersForAdd == channel) {
|
||||
return;
|
||||
}
|
||||
_api.request(base::take(_channelMembersForAddRequestId)).cancel();
|
||||
|
||||
const auto offset = 0;
|
||||
const auto participantsHash = uint64(0);
|
||||
|
||||
_channelMembersForAdd = channel;
|
||||
_channelMembersForAddRequestId = _api.request(MTPchannels_GetParticipants(
|
||||
channel->inputChannel,
|
||||
MTP_channelParticipantsRecent(),
|
||||
MTP_int(offset),
|
||||
MTP_int(_session->serverConfig().chatSizeMax),
|
||||
MTP_long(participantsHash)
|
||||
)).done([=](const MTPchannels_ChannelParticipants &result) {
|
||||
base::take(_channelMembersForAddRequestId);
|
||||
base::take(_channelMembersForAdd);
|
||||
base::take(_channelMembersForAddCallback)(result);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
base::take(_channelMembersForAddRequestId);
|
||||
base::take(_channelMembersForAdd);
|
||||
base::take(_channelMembersForAddCallback);
|
||||
}).send();
|
||||
}
|
||||
|
||||
void ChatParticipants::refreshChannelAdmins(
|
||||
not_null<ChannelData*> channel,
|
||||
const QVector<MTPChannelParticipant> &participants) {
|
||||
Data::ChannelAdminChanges changes(channel);
|
||||
for (const auto &p : participants) {
|
||||
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 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;
|
||||
}
|
||||
changes.add(userId, rank);
|
||||
}, [&](const auto &data) {
|
||||
if (userId) {
|
||||
changes.remove(userId);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ChatParticipants::requestLast(not_null<ChannelData*> channel) {
|
||||
if (!channel->isMegagroup()
|
||||
|| _participantsRequests.contains(channel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto offset = 0;
|
||||
const auto participantsHash = uint64(0);
|
||||
const auto requestId = _api.request(MTPchannels_GetParticipants(
|
||||
channel->inputChannel,
|
||||
MTP_channelParticipantsRecent(),
|
||||
MTP_int(offset),
|
||||
MTP_int(_session->serverConfig().chatSizeMax),
|
||||
MTP_long(participantsHash)
|
||||
)).done([=](const MTPchannels_ChannelParticipants &result) {
|
||||
_participantsRequests.remove(channel);
|
||||
parse(channel, result, [&](
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list) {
|
||||
applyLastList(
|
||||
channel,
|
||||
availableCount,
|
||||
list);
|
||||
});
|
||||
}).fail([this, channel](const MTP::Error &error) {
|
||||
_participantsRequests.remove(channel);
|
||||
}).send();
|
||||
|
||||
_participantsRequests[channel] = requestId;
|
||||
}
|
||||
|
||||
void ChatParticipants::requestBots(not_null<ChannelData*> channel) {
|
||||
if (!channel->isMegagroup() || _botsRequests.contains(channel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto offset = 0;
|
||||
const auto participantsHash = uint64(0);
|
||||
const auto requestId = _api.request(MTPchannels_GetParticipants(
|
||||
channel->inputChannel,
|
||||
MTP_channelParticipantsBots(),
|
||||
MTP_int(offset),
|
||||
MTP_int(_session->serverConfig().chatSizeMax),
|
||||
MTP_long(participantsHash)
|
||||
)).done([=](const MTPchannels_ChannelParticipants &result) {
|
||||
_botsRequests.remove(channel);
|
||||
parse(channel, result, [&](
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list) {
|
||||
applyBotsList(
|
||||
channel,
|
||||
availableCount,
|
||||
list);
|
||||
});
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
_botsRequests.remove(channel);
|
||||
}).send();
|
||||
|
||||
_botsRequests[channel] = requestId;
|
||||
}
|
||||
|
||||
void ChatParticipants::requestAdmins(not_null<ChannelData*> channel) {
|
||||
if (!channel->isMegagroup() || _adminsRequests.contains(channel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto offset = 0;
|
||||
const auto participantsHash = uint64(0);
|
||||
const auto requestId = _api.request(MTPchannels_GetParticipants(
|
||||
channel->inputChannel,
|
||||
MTP_channelParticipantsAdmins(),
|
||||
MTP_int(offset),
|
||||
MTP_int(_session->serverConfig().chatSizeMax),
|
||||
MTP_long(participantsHash)
|
||||
)).done([=](const MTPchannels_ChannelParticipants &result) {
|
||||
_adminsRequests.remove(channel);
|
||||
result.match([&](const MTPDchannels_channelParticipants &data) {
|
||||
ApplyMegagroupAdmins(channel, data);
|
||||
}, [&](const MTPDchannels_channelParticipantsNotModified &) {
|
||||
LOG(("API Error: channels.channelParticipantsNotModified received!"));
|
||||
});
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
_adminsRequests.remove(channel);
|
||||
}).send();
|
||||
|
||||
_adminsRequests[channel] = requestId;
|
||||
}
|
||||
|
||||
void ChatParticipants::requestCountDelayed(
|
||||
not_null<ChannelData*> channel) {
|
||||
_participantsCountRequestTimer.call(
|
||||
kReloadChannelMembersTimeout,
|
||||
[=] { channel->updateFullForced(); });
|
||||
}
|
||||
|
||||
void ChatParticipants::add(
|
||||
not_null<PeerData*> peer,
|
||||
const std::vector<not_null<UserData*>> &users,
|
||||
Fn<void(bool)> done) {
|
||||
if (const auto chat = peer->asChat()) {
|
||||
for (const auto &user : users) {
|
||||
_api.request(MTPmessages_AddChatUser(
|
||||
chat->inputChat,
|
||||
user->inputUser,
|
||||
MTP_int(kForwardMessagesOnAdd)
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
_session->api().applyUpdates(result);
|
||||
if (done) done(true);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
ShowAddParticipantsError(error.type(), peer, { 1, user });
|
||||
if (done) done(false);
|
||||
}).afterDelay(kSmallDelayMs).send();
|
||||
}
|
||||
} else if (const auto channel = peer->asChannel()) {
|
||||
const auto hasBot = ranges::any_of(users, &UserData::isBot);
|
||||
if (!peer->isMegagroup() && hasBot) {
|
||||
ShowAddParticipantsError("USER_BOT", peer, users);
|
||||
return;
|
||||
}
|
||||
auto list = QVector<MTPInputUser>();
|
||||
list.reserve(std::min(int(users.size()), int(kMaxUsersPerInvite)));
|
||||
const auto send = [&] {
|
||||
const auto callback = base::take(done);
|
||||
_api.request(MTPchannels_InviteToChannel(
|
||||
channel->inputChannel,
|
||||
MTP_vector<MTPInputUser>(list)
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
_session->api().applyUpdates(result);
|
||||
requestCountDelayed(channel);
|
||||
if (callback) callback(true);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
ShowAddParticipantsError(error.type(), peer, users);
|
||||
if (callback) callback(false);
|
||||
}).afterDelay(kSmallDelayMs).send();
|
||||
};
|
||||
for (const auto &user : users) {
|
||||
list.push_back(user->inputUser);
|
||||
if (list.size() == kMaxUsersPerInvite) {
|
||||
send();
|
||||
list.clear();
|
||||
}
|
||||
}
|
||||
if (!list.empty()) {
|
||||
send();
|
||||
}
|
||||
} else {
|
||||
Unexpected("User in ChatParticipants::add.");
|
||||
}
|
||||
}
|
||||
|
||||
void ChatParticipants::parseRecent(
|
||||
not_null<ChannelData*> channel,
|
||||
const MTPchannels_ChannelParticipants &result,
|
||||
Fn<void(
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list)> callbackList,
|
||||
Fn<void()> callbackNotModified) {
|
||||
parse(channel, result, [&](
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list) {
|
||||
auto applyLast = channel->isMegagroup()
|
||||
&& (channel->mgInfo->lastParticipants.size() <= list.size());
|
||||
if (applyLast) {
|
||||
applyLastList(
|
||||
channel,
|
||||
availableCount,
|
||||
list);
|
||||
}
|
||||
if (callbackList) {
|
||||
callbackList(availableCount, list);
|
||||
}
|
||||
}, std::move(callbackNotModified));
|
||||
}
|
||||
|
||||
void ChatParticipants::parse(
|
||||
not_null<ChannelData*> channel,
|
||||
const MTPchannels_ChannelParticipants &result,
|
||||
Fn<void(
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list)> callbackList,
|
||||
Fn<void()> callbackNotModified) {
|
||||
result.match([&](const MTPDchannels_channelParticipants &data) {
|
||||
_session->data().processUsers(data.vusers());
|
||||
if (channel->mgInfo) {
|
||||
refreshChannelAdmins(channel, data.vparticipants().v);
|
||||
}
|
||||
if (callbackList) {
|
||||
callbackList(data.vcount().v, data.vparticipants().v);
|
||||
}
|
||||
}, [&](const MTPDchannels_channelParticipantsNotModified &) {
|
||||
if (callbackNotModified) {
|
||||
callbackNotModified();
|
||||
} else {
|
||||
LOG(("API Error: "
|
||||
"channels.channelParticipantsNotModified received!"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ChatParticipants::applyLastList(
|
||||
not_null<ChannelData*> channel,
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list) {
|
||||
channel->mgInfo->lastAdmins.clear();
|
||||
channel->mgInfo->lastRestricted.clear();
|
||||
channel->mgInfo->lastParticipants.clear();
|
||||
channel->mgInfo->lastParticipantsStatus = MegagroupInfo::LastParticipantsUpToDate
|
||||
| MegagroupInfo::LastParticipantsOnceReceived;
|
||||
|
||||
auto botStatus = channel->mgInfo->botStatus;
|
||||
for (const auto &p : list) {
|
||||
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());
|
||||
});
|
||||
if (!participantId) {
|
||||
continue;
|
||||
}
|
||||
const auto participant = _session->data().peer(participantId);
|
||||
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) {
|
||||
Assert(user != nullptr);
|
||||
const auto &creator = p.c_channelParticipantCreator();
|
||||
const auto rank = qs(creator.vrank().value_or_empty());
|
||||
channel->mgInfo->creator = user;
|
||||
channel->mgInfo->creatorRank = rank;
|
||||
if (!channel->mgInfo->admins.empty()) {
|
||||
Data::ChannelAdminChanges(channel).add(
|
||||
peerToUser(participantId),
|
||||
rank);
|
||||
}
|
||||
}
|
||||
if (user
|
||||
&& !base::contains(channel->mgInfo->lastParticipants, user)) {
|
||||
channel->mgInfo->lastParticipants.push_back(user);
|
||||
if (adminRights.flags) {
|
||||
channel->mgInfo->lastAdmins.emplace(
|
||||
user,
|
||||
MegagroupInfo::Admin{ adminRights, adminCanEdit });
|
||||
} else if (restrictedRights.flags) {
|
||||
channel->mgInfo->lastRestricted.emplace(
|
||||
user,
|
||||
MegagroupInfo::Restricted{ restrictedRights });
|
||||
}
|
||||
if (user->isBot()) {
|
||||
channel->mgInfo->bots.insert(user);
|
||||
if (channel->mgInfo->botStatus != 0 && channel->mgInfo->botStatus < 2) {
|
||||
channel->mgInfo->botStatus = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// 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()) {
|
||||
// channel->setMembersCount(channel->mgInfo->lastParticipants.size());
|
||||
//} else {
|
||||
// channel->setMembersCount(availableCount);
|
||||
//}
|
||||
_session->changes().peerUpdated(
|
||||
channel,
|
||||
(Data::PeerUpdate::Flag::Members | Data::PeerUpdate::Flag::Admins));
|
||||
|
||||
channel->mgInfo->botStatus = botStatus;
|
||||
_session->changes().peerUpdated(
|
||||
channel,
|
||||
Data::PeerUpdate::Flag::FullInfo);
|
||||
}
|
||||
|
||||
void ChatParticipants::applyBotsList(
|
||||
not_null<ChannelData*> channel,
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list) {
|
||||
const auto history = _session->data().historyLoaded(channel);
|
||||
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 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());
|
||||
});
|
||||
if (!participantId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto participant = _session->data().peer(participantId);
|
||||
const auto user = participant->asUser();
|
||||
if (user && user->isBot()) {
|
||||
channel->mgInfo->bots.insert(user);
|
||||
botStatus = 2;// (botStatus > 0/* || !i.key()->botInfo->readsAllHistory*/) ? 2 : 1;
|
||||
if (!user->botInfo->inited) {
|
||||
needBotsInfos = true;
|
||||
}
|
||||
}
|
||||
if (!keyboardBotFound
|
||||
&& participant->id == history->lastKeyboardFrom) {
|
||||
keyboardBotFound = true;
|
||||
}
|
||||
}
|
||||
if (needBotsInfos) {
|
||||
_session->api().requestFullPeer(channel);
|
||||
}
|
||||
if (!keyboardBotFound) {
|
||||
history->clearLastKeyboard();
|
||||
}
|
||||
|
||||
channel->mgInfo->botStatus = botStatus;
|
||||
_session->changes().peerUpdated(
|
||||
channel,
|
||||
Data::PeerUpdate::Flag::FullInfo);
|
||||
}
|
||||
|
||||
void ChatParticipants::requestSelf(not_null<ChannelData*> channel) {
|
||||
if (_selfParticipantRequests.contains(channel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto finalize = [=](
|
||||
UserId inviter = -1,
|
||||
TimeId inviteDate = 0,
|
||||
bool inviteViaRequest = false) {
|
||||
channel->inviter = inviter;
|
||||
channel->inviteDate = inviteDate;
|
||||
channel->inviteViaRequest = inviteViaRequest;
|
||||
if (const auto history = _session->data().historyLoaded(channel)) {
|
||||
if (history->lastMessageKnown()) {
|
||||
history->checkLocalMessages();
|
||||
history->owner().sendHistoryChangeNotifications();
|
||||
} else {
|
||||
history->owner().histories().requestDialogEntry(history);
|
||||
}
|
||||
}
|
||||
};
|
||||
_selfParticipantRequests.emplace(channel);
|
||||
_api.request(MTPchannels_GetParticipant(
|
||||
channel->inputChannel,
|
||||
MTP_inputPeerSelf()
|
||||
)).done([=](const MTPchannels_ChannelParticipant &result) {
|
||||
_selfParticipantRequests.erase(channel);
|
||||
result.match([&](const MTPDchannels_channelParticipant &data) {
|
||||
_session->data().processUsers(data.vusers());
|
||||
|
||||
const auto &participant = data.vparticipant();
|
||||
participant.match([&](const MTPDchannelParticipantSelf &data) {
|
||||
finalize(
|
||||
data.vinviter_id().v,
|
||||
data.vdate().v,
|
||||
data.is_via_request());
|
||||
}, [&](const MTPDchannelParticipantCreator &) {
|
||||
if (channel->mgInfo) {
|
||||
channel->mgInfo->creator = _session->user();
|
||||
}
|
||||
finalize(_session->userId(), channel->date);
|
||||
}, [&](const MTPDchannelParticipantAdmin &data) {
|
||||
const auto inviter = data.is_self()
|
||||
? data.vinviter_id().value_or(-1)
|
||||
: -1;
|
||||
finalize(inviter, data.vdate().v);
|
||||
}, [&](const MTPDchannelParticipantBanned &data) {
|
||||
LOG(("API Error: Got self banned participant."));
|
||||
finalize();
|
||||
}, [&](const MTPDchannelParticipant &data) {
|
||||
LOG(("API Error: Got self regular participant."));
|
||||
finalize();
|
||||
}, [&](const MTPDchannelParticipantLeft &data) {
|
||||
LOG(("API Error: Got self left participant."));
|
||||
finalize();
|
||||
});
|
||||
});
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
_selfParticipantRequests.erase(channel);
|
||||
if (error.type() == qstr("CHANNEL_PRIVATE")) {
|
||||
channel->privateErrorReceived();
|
||||
}
|
||||
finalize();
|
||||
}).afterDelay(kSmallDelayMs).send();
|
||||
}
|
||||
|
||||
void ChatParticipants::kick(
|
||||
not_null<ChatData*> chat,
|
||||
not_null<PeerData*> participant) {
|
||||
Expects(participant->isUser());
|
||||
|
||||
_api.request(MTPmessages_DeleteChatUser(
|
||||
MTP_flags(0),
|
||||
chat->inputChat,
|
||||
participant->asUser()->inputUser
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
_session->api().applyUpdates(result);
|
||||
}).send();
|
||||
}
|
||||
|
||||
void ChatParticipants::kick(
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<PeerData*> participant,
|
||||
ChatRestrictionsInfo currentRights) {
|
||||
const auto kick = KickRequest(channel, participant);
|
||||
if (_kickRequests.contains(kick)) return;
|
||||
|
||||
const auto rights = ChannelData::KickedRestrictedRights(participant);
|
||||
const auto requestId = _api.request(MTPchannels_EditBanned(
|
||||
channel->inputChannel,
|
||||
participant->input,
|
||||
MTP_chatBannedRights(
|
||||
MTP_flags(
|
||||
MTPDchatBannedRights::Flags::from_raw(uint32(rights.flags))),
|
||||
MTP_int(rights.until))
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
_session->api().applyUpdates(result);
|
||||
|
||||
_kickRequests.remove(KickRequest(channel, participant));
|
||||
channel->applyEditBanned(participant, currentRights, rights);
|
||||
}).fail([this, kick](const MTP::Error &error) {
|
||||
_kickRequests.remove(kick);
|
||||
}).send();
|
||||
|
||||
_kickRequests.emplace(kick, requestId);
|
||||
}
|
||||
|
||||
void ChatParticipants::unblock(
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<PeerData*> participant) {
|
||||
const auto kick = KickRequest(channel, participant);
|
||||
if (_kickRequests.contains(kick)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto requestId = _api.request(MTPchannels_EditBanned(
|
||||
channel->inputChannel,
|
||||
participant->input,
|
||||
MTP_chatBannedRights(MTP_flags(0), MTP_int(0))
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
_session->api().applyUpdates(result);
|
||||
|
||||
_kickRequests.remove(KickRequest(channel, participant));
|
||||
if (channel->kickedCount() > 0) {
|
||||
channel->setKickedCount(channel->kickedCount() - 1);
|
||||
} else {
|
||||
channel->updateFullForced();
|
||||
}
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
_kickRequests.remove(kick);
|
||||
}).send();
|
||||
|
||||
_kickRequests.emplace(kick, requestId);
|
||||
}
|
||||
|
||||
} // namespace Api
|
107
Telegram/SourceFiles/api/api_chat_participants.h
Normal file
107
Telegram/SourceFiles/api/api_chat_participants.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "mtproto/sender.h"
|
||||
#include "base/timer.h"
|
||||
|
||||
class ApiWrap;
|
||||
class ChannelData;
|
||||
|
||||
struct ChatRestrictionsInfo;
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
namespace Api {
|
||||
|
||||
class ChatParticipants final {
|
||||
public:
|
||||
explicit ChatParticipants(not_null<ApiWrap*> api);
|
||||
|
||||
void requestLast(not_null<ChannelData*> channel);
|
||||
void requestBots(not_null<ChannelData*> channel);
|
||||
void requestAdmins(not_null<ChannelData*> channel);
|
||||
void requestCountDelayed(not_null<ChannelData*> channel);
|
||||
|
||||
void parse(
|
||||
not_null<ChannelData*> channel,
|
||||
const MTPchannels_ChannelParticipants &result,
|
||||
Fn<void(
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list)> callbackList,
|
||||
Fn<void()> callbackNotModified = nullptr);
|
||||
void parseRecent(
|
||||
not_null<ChannelData*> channel,
|
||||
const MTPchannels_ChannelParticipants &result,
|
||||
Fn<void(
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list)> callbackList = nullptr,
|
||||
Fn<void()> callbackNotModified = nullptr);
|
||||
void add(
|
||||
not_null<PeerData*> peer,
|
||||
const std::vector<not_null<UserData*>> &users,
|
||||
Fn<void(bool)> done = nullptr);
|
||||
|
||||
void requestSelf(not_null<ChannelData*> channel);
|
||||
|
||||
void requestForAdd(
|
||||
not_null<ChannelData*> channel,
|
||||
Fn<void(const MTPchannels_ChannelParticipants&)> callback);
|
||||
|
||||
void kick(
|
||||
not_null<ChatData*> chat,
|
||||
not_null<PeerData*> participant);
|
||||
void kick(
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<PeerData*> participant,
|
||||
ChatRestrictionsInfo currentRights);
|
||||
void unblock(
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<PeerData*> participant);
|
||||
|
||||
private:
|
||||
void applyLastList(
|
||||
not_null<ChannelData*> channel,
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list);
|
||||
void applyBotsList(
|
||||
not_null<ChannelData*> channel,
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list);
|
||||
|
||||
void refreshChannelAdmins(
|
||||
not_null<ChannelData*> channel,
|
||||
const QVector<MTPChannelParticipant> &participants);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
MTP::Sender _api;
|
||||
|
||||
using PeerRequests = base::flat_map<PeerData*, mtpRequestId>;
|
||||
|
||||
PeerRequests _participantsRequests;
|
||||
PeerRequests _botsRequests;
|
||||
PeerRequests _adminsRequests;
|
||||
base::DelayedCallTimer _participantsCountRequestTimer;
|
||||
|
||||
ChannelData *_channelMembersForAdd = nullptr;
|
||||
mtpRequestId _channelMembersForAddRequestId = 0;
|
||||
Fn<void(
|
||||
const MTPchannels_ChannelParticipants&)> _channelMembersForAddCallback;
|
||||
|
||||
base::flat_set<not_null<ChannelData*>> _selfParticipantRequests;
|
||||
|
||||
using KickRequest = std::pair<
|
||||
not_null<ChannelData*>,
|
||||
not_null<PeerData*>>;
|
||||
base::flat_map<KickRequest, mtpRequestId> _kickRequests;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Api
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "api/api_invite_links.h"
|
||||
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_chat.h"
|
||||
|
@ -478,7 +479,7 @@ void InviteLinks::processRequest(
|
|||
++chat->count;
|
||||
}
|
||||
} else if (const auto channel = peer->asChannel()) {
|
||||
_api->requestParticipantsCountDelayed(channel);
|
||||
_api->chatParticipants().requestCountDelayed(channel);
|
||||
}
|
||||
_api->applyUpdates(result);
|
||||
if (link.isEmpty() && approved) {
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_updates.h"
|
||||
|
||||
#include "api/api_authorizations.h"
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "api/api_text_entities.h"
|
||||
#include "api/api_user_privacy.h"
|
||||
#include "main/main_session.h"
|
||||
|
@ -1498,7 +1499,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
|
|||
if (channel->mgInfo->lastParticipants.size() < _session->serverConfig().chatSizeMax
|
||||
&& (channel->mgInfo->lastParticipants.empty()
|
||||
|| channel->mgInfo->lastParticipants.size() < channel->membersCount())) {
|
||||
session().api().requestLastParticipants(channel);
|
||||
session().api().chatParticipants().requestLast(channel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2127,7 +2128,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
|
|||
history->owner().histories().requestDialogEntry(history);
|
||||
}
|
||||
if (!channel->amCreator()) {
|
||||
session().api().requestSelfParticipant(channel);
|
||||
session().api().chatParticipants().requestSelf(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_authorizations.h"
|
||||
#include "api/api_attached_stickers.h"
|
||||
#include "api/api_blocked_peers.h"
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "api/api_cloud_password.h"
|
||||
#include "api/api_hash.h"
|
||||
#include "api/api_invite_links.h"
|
||||
|
@ -89,19 +90,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace {
|
||||
|
||||
// 1 second wait before reload members in channel after adding.
|
||||
constexpr auto kReloadChannelMembersTimeout = 1000;
|
||||
|
||||
// Save draft to the cloud with 1 sec extra delay.
|
||||
constexpr auto kSaveCloudDraftTimeout = 1000;
|
||||
|
||||
// Max users in one super group invite request.
|
||||
constexpr auto kMaxUsersPerInvite = 100;
|
||||
|
||||
// How many messages from chat history server should forward to user,
|
||||
// that was added to this chat.
|
||||
constexpr auto kForwardMessagesOnAdd = 100;
|
||||
|
||||
constexpr auto kTopPromotionInterval = TimeId(60 * 60);
|
||||
constexpr auto kTopPromotionMinDelay = TimeId(10);
|
||||
constexpr auto kSmallDelayMs = 5;
|
||||
|
@ -150,7 +141,8 @@ ApiWrap::ApiWrap(not_null<Main::Session*> session)
|
|||
, _views(std::make_unique<Api::ViewsManager>(this))
|
||||
, _confirmPhone(std::make_unique<Api::ConfirmPhone>(this))
|
||||
, _peerPhoto(std::make_unique<Api::PeerPhoto>(this))
|
||||
, _polls(std::make_unique<Api::Polls>(this)) {
|
||||
, _polls(std::make_unique<Api::Polls>(this))
|
||||
, _chatParticipants(std::make_unique<Api::ChatParticipants>(this)) {
|
||||
crl::on_main(session, [=] {
|
||||
// You can't use _session->lifetime() in the constructor,
|
||||
// only queued, because it is not constructed yet.
|
||||
|
@ -1390,373 +1382,6 @@ void ApiWrap::requestPeers(const QList<PeerData*> &peers) {
|
|||
}
|
||||
}
|
||||
|
||||
void ApiWrap::requestLastParticipants(not_null<ChannelData*> channel) {
|
||||
if (!channel->isMegagroup()
|
||||
|| _participantsRequests.contains(channel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto offset = 0;
|
||||
const auto participantsHash = uint64(0);
|
||||
const auto requestId = request(MTPchannels_GetParticipants(
|
||||
channel->inputChannel,
|
||||
MTP_channelParticipantsRecent(),
|
||||
MTP_int(offset),
|
||||
MTP_int(_session->serverConfig().chatSizeMax),
|
||||
MTP_long(participantsHash)
|
||||
)).done([=](const MTPchannels_ChannelParticipants &result) {
|
||||
_participantsRequests.remove(channel);
|
||||
parseChannelParticipants(channel, result, [&](
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list) {
|
||||
applyLastParticipantsList(
|
||||
channel,
|
||||
availableCount,
|
||||
list);
|
||||
});
|
||||
}).fail([this, channel](const MTP::Error &error) {
|
||||
_participantsRequests.remove(channel);
|
||||
}).send();
|
||||
|
||||
_participantsRequests.insert(channel, requestId);
|
||||
}
|
||||
|
||||
void ApiWrap::requestBots(not_null<ChannelData*> channel) {
|
||||
if (!channel->isMegagroup() || _botsRequests.contains(channel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto offset = 0;
|
||||
const auto participantsHash = uint64(0);
|
||||
const auto requestId = request(MTPchannels_GetParticipants(
|
||||
channel->inputChannel,
|
||||
MTP_channelParticipantsBots(),
|
||||
MTP_int(offset),
|
||||
MTP_int(_session->serverConfig().chatSizeMax),
|
||||
MTP_long(participantsHash)
|
||||
)).done([=](const MTPchannels_ChannelParticipants &result) {
|
||||
_botsRequests.remove(channel);
|
||||
parseChannelParticipants(channel, result, [&](
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list) {
|
||||
applyBotsList(
|
||||
channel,
|
||||
availableCount,
|
||||
list);
|
||||
});
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
_botsRequests.remove(channel);
|
||||
}).send();
|
||||
|
||||
_botsRequests.insert(channel, requestId);
|
||||
}
|
||||
|
||||
void ApiWrap::requestAdmins(not_null<ChannelData*> channel) {
|
||||
if (!channel->isMegagroup() || _adminsRequests.contains(channel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto offset = 0;
|
||||
const auto participantsHash = uint64(0);
|
||||
const auto requestId = request(MTPchannels_GetParticipants(
|
||||
channel->inputChannel,
|
||||
MTP_channelParticipantsAdmins(),
|
||||
MTP_int(offset),
|
||||
MTP_int(_session->serverConfig().chatSizeMax),
|
||||
MTP_long(participantsHash)
|
||||
)).done([=](const MTPchannels_ChannelParticipants &result) {
|
||||
_adminsRequests.remove(channel);
|
||||
result.match([&](const MTPDchannels_channelParticipants &data) {
|
||||
Data::ApplyMegagroupAdmins(channel, data);
|
||||
}, [&](const MTPDchannels_channelParticipantsNotModified &) {
|
||||
LOG(("API Error: channels.channelParticipantsNotModified received!"));
|
||||
});
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
_adminsRequests.remove(channel);
|
||||
}).send();
|
||||
|
||||
_adminsRequests.insert(channel, requestId);
|
||||
}
|
||||
|
||||
void ApiWrap::applyLastParticipantsList(
|
||||
not_null<ChannelData*> channel,
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list) {
|
||||
channel->mgInfo->lastAdmins.clear();
|
||||
channel->mgInfo->lastRestricted.clear();
|
||||
channel->mgInfo->lastParticipants.clear();
|
||||
channel->mgInfo->lastParticipantsStatus = MegagroupInfo::LastParticipantsUpToDate
|
||||
| MegagroupInfo::LastParticipantsOnceReceived;
|
||||
|
||||
auto botStatus = channel->mgInfo->botStatus;
|
||||
for (const auto &p : list) {
|
||||
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());
|
||||
});
|
||||
if (!participantId) {
|
||||
continue;
|
||||
}
|
||||
const auto participant = _session->data().peer(participantId);
|
||||
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) {
|
||||
Assert(user != nullptr);
|
||||
const auto &creator = p.c_channelParticipantCreator();
|
||||
const auto rank = qs(creator.vrank().value_or_empty());
|
||||
channel->mgInfo->creator = user;
|
||||
channel->mgInfo->creatorRank = rank;
|
||||
if (!channel->mgInfo->admins.empty()) {
|
||||
Data::ChannelAdminChanges(channel).add(
|
||||
peerToUser(participantId),
|
||||
rank);
|
||||
}
|
||||
}
|
||||
if (user
|
||||
&& !base::contains(channel->mgInfo->lastParticipants, user)) {
|
||||
channel->mgInfo->lastParticipants.push_back(user);
|
||||
if (adminRights.flags) {
|
||||
channel->mgInfo->lastAdmins.emplace(
|
||||
user,
|
||||
MegagroupInfo::Admin{ adminRights, adminCanEdit });
|
||||
} else if (restrictedRights.flags) {
|
||||
channel->mgInfo->lastRestricted.emplace(
|
||||
user,
|
||||
MegagroupInfo::Restricted{ restrictedRights });
|
||||
}
|
||||
if (user->isBot()) {
|
||||
channel->mgInfo->bots.insert(user);
|
||||
if (channel->mgInfo->botStatus != 0 && channel->mgInfo->botStatus < 2) {
|
||||
channel->mgInfo->botStatus = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// 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()) {
|
||||
// channel->setMembersCount(channel->mgInfo->lastParticipants.size());
|
||||
//} else {
|
||||
// channel->setMembersCount(availableCount);
|
||||
//}
|
||||
session().changes().peerUpdated(
|
||||
channel,
|
||||
(Data::PeerUpdate::Flag::Members | Data::PeerUpdate::Flag::Admins));
|
||||
|
||||
channel->mgInfo->botStatus = botStatus;
|
||||
_session->changes().peerUpdated(
|
||||
channel,
|
||||
Data::PeerUpdate::Flag::FullInfo);
|
||||
}
|
||||
|
||||
void ApiWrap::applyBotsList(
|
||||
not_null<ChannelData*> channel,
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list) {
|
||||
const auto history = _session->data().historyLoaded(channel);
|
||||
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 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());
|
||||
});
|
||||
if (!participantId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto participant = _session->data().peer(participantId);
|
||||
const auto user = participant->asUser();
|
||||
if (user && user->isBot()) {
|
||||
channel->mgInfo->bots.insert(user);
|
||||
botStatus = 2;// (botStatus > 0/* || !i.key()->botInfo->readsAllHistory*/) ? 2 : 1;
|
||||
if (!user->botInfo->inited) {
|
||||
needBotsInfos = true;
|
||||
}
|
||||
}
|
||||
if (!keyboardBotFound
|
||||
&& participant->id == history->lastKeyboardFrom) {
|
||||
keyboardBotFound = true;
|
||||
}
|
||||
}
|
||||
if (needBotsInfos) {
|
||||
requestFullPeer(channel);
|
||||
}
|
||||
if (!keyboardBotFound) {
|
||||
history->clearLastKeyboard();
|
||||
}
|
||||
|
||||
channel->mgInfo->botStatus = botStatus;
|
||||
_session->changes().peerUpdated(
|
||||
channel,
|
||||
Data::PeerUpdate::Flag::FullInfo);
|
||||
}
|
||||
|
||||
void ApiWrap::requestSelfParticipant(not_null<ChannelData*> channel) {
|
||||
if (_selfParticipantRequests.contains(channel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto finalize = [=](
|
||||
UserId inviter = -1,
|
||||
TimeId inviteDate = 0,
|
||||
bool inviteViaRequest = false) {
|
||||
channel->inviter = inviter;
|
||||
channel->inviteDate = inviteDate;
|
||||
channel->inviteViaRequest = inviteViaRequest;
|
||||
if (const auto history = _session->data().historyLoaded(channel)) {
|
||||
if (history->lastMessageKnown()) {
|
||||
history->checkLocalMessages();
|
||||
history->owner().sendHistoryChangeNotifications();
|
||||
} else {
|
||||
history->owner().histories().requestDialogEntry(history);
|
||||
}
|
||||
}
|
||||
};
|
||||
_selfParticipantRequests.emplace(channel);
|
||||
request(MTPchannels_GetParticipant(
|
||||
channel->inputChannel,
|
||||
MTP_inputPeerSelf()
|
||||
)).done([=](const MTPchannels_ChannelParticipant &result) {
|
||||
_selfParticipantRequests.erase(channel);
|
||||
result.match([&](const MTPDchannels_channelParticipant &data) {
|
||||
_session->data().processUsers(data.vusers());
|
||||
|
||||
const auto &participant = data.vparticipant();
|
||||
participant.match([&](const MTPDchannelParticipantSelf &data) {
|
||||
finalize(
|
||||
data.vinviter_id().v,
|
||||
data.vdate().v,
|
||||
data.is_via_request());
|
||||
}, [&](const MTPDchannelParticipantCreator &) {
|
||||
if (channel->mgInfo) {
|
||||
channel->mgInfo->creator = _session->user();
|
||||
}
|
||||
finalize(_session->userId(), channel->date);
|
||||
}, [&](const MTPDchannelParticipantAdmin &data) {
|
||||
const auto inviter = data.is_self()
|
||||
? data.vinviter_id().value_or(-1)
|
||||
: -1;
|
||||
finalize(inviter, data.vdate().v);
|
||||
}, [&](const MTPDchannelParticipantBanned &data) {
|
||||
LOG(("API Error: Got self banned participant."));
|
||||
finalize();
|
||||
}, [&](const MTPDchannelParticipant &data) {
|
||||
LOG(("API Error: Got self regular participant."));
|
||||
finalize();
|
||||
}, [&](const MTPDchannelParticipantLeft &data) {
|
||||
LOG(("API Error: Got self left participant."));
|
||||
finalize();
|
||||
});
|
||||
});
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
_selfParticipantRequests.erase(channel);
|
||||
if (error.type() == qstr("CHANNEL_PRIVATE")) {
|
||||
channel->privateErrorReceived();
|
||||
}
|
||||
finalize();
|
||||
}).afterDelay(kSmallDelayMs).send();
|
||||
}
|
||||
|
||||
void ApiWrap::kickParticipant(
|
||||
not_null<ChatData*> chat,
|
||||
not_null<PeerData*> participant) {
|
||||
Expects(participant->isUser());
|
||||
|
||||
request(MTPmessages_DeleteChatUser(
|
||||
MTP_flags(0),
|
||||
chat->inputChat,
|
||||
participant->asUser()->inputUser
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
applyUpdates(result);
|
||||
}).send();
|
||||
}
|
||||
|
||||
void ApiWrap::kickParticipant(
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<PeerData*> participant,
|
||||
ChatRestrictionsInfo currentRights) {
|
||||
const auto kick = KickRequest(channel, participant);
|
||||
if (_kickRequests.contains(kick)) return;
|
||||
|
||||
const auto rights = ChannelData::KickedRestrictedRights(participant);
|
||||
const auto requestId = request(MTPchannels_EditBanned(
|
||||
channel->inputChannel,
|
||||
participant->input,
|
||||
MTP_chatBannedRights(
|
||||
MTP_flags(
|
||||
MTPDchatBannedRights::Flags::from_raw(uint32(rights.flags))),
|
||||
MTP_int(rights.until))
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
applyUpdates(result);
|
||||
|
||||
_kickRequests.remove(KickRequest(channel, participant));
|
||||
channel->applyEditBanned(participant, currentRights, rights);
|
||||
}).fail([this, kick](const MTP::Error &error) {
|
||||
_kickRequests.remove(kick);
|
||||
}).send();
|
||||
|
||||
_kickRequests.emplace(kick, requestId);
|
||||
}
|
||||
|
||||
void ApiWrap::unblockParticipant(
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<PeerData*> participant) {
|
||||
const auto kick = KickRequest(channel, participant);
|
||||
if (_kickRequests.contains(kick)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto requestId = request(MTPchannels_EditBanned(
|
||||
channel->inputChannel,
|
||||
participant->input,
|
||||
MTP_chatBannedRights(MTP_flags(0), MTP_int(0))
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
applyUpdates(result);
|
||||
|
||||
_kickRequests.remove(KickRequest(channel, participant));
|
||||
if (channel->kickedCount() > 0) {
|
||||
channel->setKickedCount(channel->kickedCount() - 1);
|
||||
} else {
|
||||
channel->updateFullForced();
|
||||
}
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
_kickRequests.remove(kick);
|
||||
}).send();
|
||||
|
||||
_kickRequests.emplace(kick, requestId);
|
||||
}
|
||||
|
||||
void ApiWrap::deleteAllFromParticipant(
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<PeerData*> from) {
|
||||
|
@ -1792,36 +1417,6 @@ void ApiWrap::deleteAllFromParticipantSend(
|
|||
}).send();
|
||||
}
|
||||
|
||||
void ApiWrap::requestChannelMembersForAdd(
|
||||
not_null<ChannelData*> channel,
|
||||
Fn<void(const MTPchannels_ChannelParticipants&)> callback) {
|
||||
_channelMembersForAddCallback = std::move(callback);
|
||||
if (_channelMembersForAdd == channel) {
|
||||
return;
|
||||
}
|
||||
request(base::take(_channelMembersForAddRequestId)).cancel();
|
||||
|
||||
const auto offset = 0;
|
||||
const auto participantsHash = uint64(0);
|
||||
|
||||
_channelMembersForAdd = channel;
|
||||
_channelMembersForAddRequestId = request(MTPchannels_GetParticipants(
|
||||
channel->inputChannel,
|
||||
MTP_channelParticipantsRecent(),
|
||||
MTP_int(offset),
|
||||
MTP_int(_session->serverConfig().chatSizeMax),
|
||||
MTP_long(participantsHash)
|
||||
)).done([=](const MTPchannels_ChannelParticipants &result) {
|
||||
base::take(_channelMembersForAddRequestId);
|
||||
base::take(_channelMembersForAdd);
|
||||
base::take(_channelMembersForAddCallback)(result);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
base::take(_channelMembersForAddRequestId);
|
||||
base::take(_channelMembersForAdd);
|
||||
base::take(_channelMembersForAddCallback);
|
||||
}).send();
|
||||
}
|
||||
|
||||
void ApiWrap::scheduleStickerSetRequest(uint64 setId, uint64 access) {
|
||||
if (!_stickerSetRequests.contains(setId)) {
|
||||
_stickerSetRequests.insert(setId, qMakePair(access, 0));
|
||||
|
@ -2700,13 +2295,6 @@ void ApiWrap::resolveWebPages() {
|
|||
}
|
||||
}
|
||||
|
||||
void ApiWrap::requestParticipantsCountDelayed(
|
||||
not_null<ChannelData*> channel) {
|
||||
_participantsCountRequestTimer.call(
|
||||
kReloadChannelMembersTimeout,
|
||||
[=] { channel->updateFullForced(); });
|
||||
}
|
||||
|
||||
template <typename Request>
|
||||
void ApiWrap::requestFileReference(
|
||||
Data::FileOrigin origin,
|
||||
|
@ -3220,88 +2808,6 @@ void ApiWrap::readFeaturedSets() {
|
|||
}
|
||||
}
|
||||
|
||||
void ApiWrap::parseChannelParticipants(
|
||||
not_null<ChannelData*> channel,
|
||||
const MTPchannels_ChannelParticipants &result,
|
||||
Fn<void(
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list)> callbackList,
|
||||
Fn<void()> callbackNotModified) {
|
||||
result.match([&](const MTPDchannels_channelParticipants &data) {
|
||||
_session->data().processUsers(data.vusers());
|
||||
if (channel->mgInfo) {
|
||||
refreshChannelAdmins(channel, data.vparticipants().v);
|
||||
}
|
||||
if (callbackList) {
|
||||
callbackList(data.vcount().v, data.vparticipants().v);
|
||||
}
|
||||
}, [&](const MTPDchannels_channelParticipantsNotModified &) {
|
||||
if (callbackNotModified) {
|
||||
callbackNotModified();
|
||||
} else {
|
||||
LOG(("API Error: "
|
||||
"channels.channelParticipantsNotModified received!"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ApiWrap::refreshChannelAdmins(
|
||||
not_null<ChannelData*> channel,
|
||||
const QVector<MTPChannelParticipant> &participants) {
|
||||
Data::ChannelAdminChanges changes(channel);
|
||||
for (const auto &p : participants) {
|
||||
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 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;
|
||||
}
|
||||
changes.add(userId, rank);
|
||||
}, [&](const auto &data) {
|
||||
if (userId) {
|
||||
changes.remove(userId);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ApiWrap::parseRecentChannelParticipants(
|
||||
not_null<ChannelData*> channel,
|
||||
const MTPchannels_ChannelParticipants &result,
|
||||
Fn<void(
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list)> callbackList,
|
||||
Fn<void()> callbackNotModified) {
|
||||
parseChannelParticipants(channel, result, [&](
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list) {
|
||||
auto applyLast = channel->isMegagroup()
|
||||
&& (channel->mgInfo->lastParticipants.size() <= list.size());
|
||||
if (applyLast) {
|
||||
applyLastParticipantsList(
|
||||
channel,
|
||||
availableCount,
|
||||
list);
|
||||
}
|
||||
if (callbackList) {
|
||||
callbackList(availableCount, list);
|
||||
}
|
||||
}, std::move(callbackNotModified));
|
||||
}
|
||||
|
||||
void ApiWrap::jumpToDate(Dialogs::Key chat, const QDate &date) {
|
||||
if (const auto peer = chat.peer()) {
|
||||
jumpToHistoryDate(peer, date);
|
||||
|
@ -3439,61 +2945,6 @@ void ApiWrap::checkForUnreadMentions(
|
|||
}
|
||||
}
|
||||
|
||||
void ApiWrap::addChatParticipants(
|
||||
not_null<PeerData*> peer,
|
||||
const std::vector<not_null<UserData*>> &users,
|
||||
Fn<void(bool)> done) {
|
||||
if (const auto chat = peer->asChat()) {
|
||||
for (const auto &user : users) {
|
||||
request(MTPmessages_AddChatUser(
|
||||
chat->inputChat,
|
||||
user->inputUser,
|
||||
MTP_int(kForwardMessagesOnAdd)
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
applyUpdates(result);
|
||||
if (done) done(true);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
ShowAddParticipantsError(error.type(), peer, { 1, user });
|
||||
if (done) done(false);
|
||||
}).afterDelay(crl::time(5)).send();
|
||||
}
|
||||
} else if (const auto channel = peer->asChannel()) {
|
||||
const auto hasBot = ranges::any_of(users, &UserData::isBot);
|
||||
if (!peer->isMegagroup() && hasBot) {
|
||||
ShowAddParticipantsError("USER_BOT", peer, users);
|
||||
return;
|
||||
}
|
||||
auto list = QVector<MTPInputUser>();
|
||||
list.reserve(qMin(int(users.size()), int(kMaxUsersPerInvite)));
|
||||
const auto send = [&] {
|
||||
const auto callback = base::take(done);
|
||||
request(MTPchannels_InviteToChannel(
|
||||
channel->inputChannel,
|
||||
MTP_vector<MTPInputUser>(list)
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
applyUpdates(result);
|
||||
requestParticipantsCountDelayed(channel);
|
||||
if (callback) callback(true);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
ShowAddParticipantsError(error.type(), peer, users);
|
||||
if (callback) callback(false);
|
||||
}).afterDelay(crl::time(5)).send();
|
||||
};
|
||||
for (const auto &user : users) {
|
||||
list.push_back(user->inputUser);
|
||||
if (list.size() == kMaxUsersPerInvite) {
|
||||
send();
|
||||
list.clear();
|
||||
}
|
||||
}
|
||||
if (!list.empty()) {
|
||||
send();
|
||||
}
|
||||
} else {
|
||||
Unexpected("User in ApiWrap::addChatParticipants.");
|
||||
}
|
||||
}
|
||||
|
||||
void ApiWrap::requestSharedMediaCount(
|
||||
not_null<PeerData*> peer,
|
||||
Storage::SharedMediaType type) {
|
||||
|
@ -4690,3 +4141,7 @@ Api::PeerPhoto &ApiWrap::peerPhoto() {
|
|||
Api::Polls &ApiWrap::polls() {
|
||||
return *_polls;
|
||||
}
|
||||
|
||||
Api::ChatParticipants &ApiWrap::chatParticipants() {
|
||||
return *_chatParticipants;
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ class ViewsManager;
|
|||
class ConfirmPhone;
|
||||
class PeerPhoto;
|
||||
class Polls;
|
||||
class ChatParticipants;
|
||||
|
||||
namespace details {
|
||||
|
||||
|
@ -172,10 +173,6 @@ public:
|
|||
void requestPeer(not_null<PeerData*> peer);
|
||||
void requestPeers(const QList<PeerData*> &peers);
|
||||
void requestPeerSettings(not_null<PeerData*> peer);
|
||||
void requestLastParticipants(not_null<ChannelData*> channel);
|
||||
void requestBots(not_null<ChannelData*> channel);
|
||||
void requestAdmins(not_null<ChannelData*> channel);
|
||||
void requestParticipantsCountDelayed(not_null<ChannelData*> channel);
|
||||
|
||||
using UpdatedFileReferences = Data::UpdatedFileReferences;
|
||||
using FileReferencesHandler = FnMut<void(const UpdatedFileReferences&)>;
|
||||
|
@ -204,9 +201,6 @@ public:
|
|||
Fn<void(const MTP::Error &)> fail);
|
||||
void importChatInvite(const QString &hash, bool isGroup);
|
||||
|
||||
void requestChannelMembersForAdd(
|
||||
not_null<ChannelData*> channel,
|
||||
Fn<void(const MTPchannels_ChannelParticipants&)> callback);
|
||||
void processFullPeer(
|
||||
not_null<PeerData*> peer,
|
||||
const MTPmessages_ChatFull &result);
|
||||
|
@ -219,17 +213,6 @@ public:
|
|||
void markMediaRead(const base::flat_set<not_null<HistoryItem*>> &items);
|
||||
void markMediaRead(not_null<HistoryItem*> item);
|
||||
|
||||
void requestSelfParticipant(not_null<ChannelData*> channel);
|
||||
void kickParticipant(
|
||||
not_null<ChatData*> chat,
|
||||
not_null<PeerData*> participant);
|
||||
void kickParticipant(
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<PeerData*> participant,
|
||||
ChatRestrictionsInfo currentRights);
|
||||
void unblockParticipant(
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<PeerData*> participant);
|
||||
void deleteAllFromParticipant(
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<PeerData*> from);
|
||||
|
@ -292,25 +275,6 @@ public:
|
|||
|
||||
void readFeaturedSetDelayed(uint64 setId);
|
||||
|
||||
void parseChannelParticipants(
|
||||
not_null<ChannelData*> channel,
|
||||
const MTPchannels_ChannelParticipants &result,
|
||||
Fn<void(
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list)> callbackList,
|
||||
Fn<void()> callbackNotModified = nullptr);
|
||||
void parseRecentChannelParticipants(
|
||||
not_null<ChannelData*> channel,
|
||||
const MTPchannels_ChannelParticipants &result,
|
||||
Fn<void(
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list)> callbackList = nullptr,
|
||||
Fn<void()> callbackNotModified = nullptr);
|
||||
void addChatParticipants(
|
||||
not_null<PeerData*> peer,
|
||||
const std::vector<not_null<UserData*>> &users,
|
||||
Fn<void(bool)> done = nullptr);
|
||||
|
||||
rpl::producer<SendAction> sendActions() const {
|
||||
return _sendActions.events();
|
||||
}
|
||||
|
@ -395,6 +359,7 @@ public:
|
|||
[[nodiscard]] Api::ConfirmPhone &confirmPhone();
|
||||
[[nodiscard]] Api::PeerPhoto &peerPhoto();
|
||||
[[nodiscard]] Api::Polls &polls();
|
||||
[[nodiscard]] Api::ChatParticipants &chatParticipants();
|
||||
|
||||
void updatePrivacyLastSeens();
|
||||
|
||||
|
@ -458,14 +423,6 @@ private:
|
|||
not_null<UserData*> user,
|
||||
const MTPusers_UserFull &result,
|
||||
mtpRequestId req);
|
||||
void applyLastParticipantsList(
|
||||
not_null<ChannelData*> channel,
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list);
|
||||
void applyBotsList(
|
||||
not_null<ChannelData*> channel,
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list);
|
||||
void resolveWebPages();
|
||||
void gotWebPages(
|
||||
ChannelData *channel,
|
||||
|
@ -482,10 +439,6 @@ private:
|
|||
void requestSavedGifs(TimeId now);
|
||||
void readFeaturedSets();
|
||||
|
||||
void refreshChannelAdmins(
|
||||
not_null<ChannelData*> channel,
|
||||
const QVector<MTPChannelParticipant> &participants);
|
||||
|
||||
void jumpToHistoryDate(not_null<PeerData*> peer, const QDate &date);
|
||||
template <typename Callback>
|
||||
void requestMessageAfterDate(
|
||||
|
@ -576,26 +529,10 @@ private:
|
|||
PeerRequests _peerRequests;
|
||||
base::flat_set<not_null<PeerData*>> _requestedPeerSettings;
|
||||
|
||||
PeerRequests _participantsRequests;
|
||||
PeerRequests _botsRequests;
|
||||
PeerRequests _adminsRequests;
|
||||
base::DelayedCallTimer _participantsCountRequestTimer;
|
||||
|
||||
ChannelData *_channelMembersForAdd = nullptr;
|
||||
mtpRequestId _channelMembersForAddRequestId = 0;
|
||||
Fn<void(
|
||||
const MTPchannels_ChannelParticipants&)> _channelMembersForAddCallback;
|
||||
base::flat_map<
|
||||
not_null<History*>,
|
||||
std::pair<mtpRequestId,Fn<void()>>> _historyArchivedRequests;
|
||||
|
||||
using KickRequest = std::pair<
|
||||
not_null<ChannelData*>,
|
||||
not_null<PeerData*>>;
|
||||
base::flat_map<KickRequest, mtpRequestId> _kickRequests;
|
||||
|
||||
base::flat_set<not_null<ChannelData*>> _selfParticipantRequests;
|
||||
|
||||
QMap<WebPageData*, mtpRequestId> _webPagesPending;
|
||||
base::Timer _webPagesTimer;
|
||||
|
||||
|
@ -702,6 +639,7 @@ private:
|
|||
const std::unique_ptr<Api::ConfirmPhone> _confirmPhone;
|
||||
const std::unique_ptr<Api::PeerPhoto> _peerPhoto;
|
||||
const std::unique_ptr<Api::Polls> _polls;
|
||||
const std::unique_ptr<Api::ChatParticipants> _chatParticipants;
|
||||
|
||||
mtpRequestId _wallPaperRequestId = 0;
|
||||
QString _wallPaperSlug;
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/delete_messages_box.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_chat.h"
|
||||
|
@ -478,7 +479,7 @@ void DeleteMessagesBox::deleteAndClear() {
|
|||
}
|
||||
if (_moderateFrom) {
|
||||
if (_banUser && _banUser->checked()) {
|
||||
_moderateInChannel->session().api().kickParticipant(
|
||||
_moderateInChannel->session().api().chatParticipants().kick(
|
||||
_moderateInChannel,
|
||||
_moderateFrom,
|
||||
ChatRestrictionsInfo());
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "boxes/peer_list_controllers.h"
|
||||
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "base/random.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
|
@ -71,7 +72,7 @@ void AddBotToGroup(not_null<UserData*> bot, not_null<PeerData*> chat) {
|
|||
if (bot->isBot() && !bot->botInfo->startGroupToken.isEmpty()) {
|
||||
chat->session().api().sendBotStart(bot, chat);
|
||||
} else {
|
||||
chat->session().api().addChatParticipants(chat, { 1, bot });
|
||||
chat->session().api().chatParticipants().add(chat, { 1, bot });
|
||||
}
|
||||
Ui::hideLayer();
|
||||
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "boxes/peers/add_participants_box.h"
|
||||
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "boxes/peers/edit_participant_box.h"
|
||||
#include "boxes/peers/edit_peer_type_box.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
|
@ -231,7 +232,7 @@ bool AddParticipantsBoxController::inviteSelectedUsers(
|
|||
if (users.empty()) {
|
||||
return false;
|
||||
}
|
||||
_peer->session().api().addChatParticipants(_peer, users);
|
||||
_peer->session().api().chatParticipants().add(_peer, users);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -465,7 +466,7 @@ void AddSpecialBoxController::loadMoreRows() {
|
|||
)).done([=](const MTPchannels_ChannelParticipants &result) {
|
||||
_loadRequestId = 0;
|
||||
auto &session = channel->session();
|
||||
session.api().parseChannelParticipants(channel, result, [&](
|
||||
session.api().chatParticipants().parse(channel, result, [&](
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list) {
|
||||
for (const auto &data : list) {
|
||||
|
@ -977,7 +978,7 @@ void AddSpecialBoxSearchController::searchParticipantsDone(
|
|||
_participantsQueries.erase(it);
|
||||
}
|
||||
};
|
||||
channel->session().api().parseChannelParticipants(
|
||||
channel->session().api().chatParticipants().parse(
|
||||
channel,
|
||||
result,
|
||||
addToCache);
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "boxes/peers/edit_participants_box.h"
|
||||
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "boxes/peer_list_controllers.h"
|
||||
#include "boxes/peers/edit_participant_box.h"
|
||||
#include "boxes/peers/add_participants_box.h"
|
||||
|
@ -1396,12 +1397,12 @@ void ParticipantsBoxController::loadMoreRows() {
|
|||
&& (_role == Role::Members || _role == Role::Profile);
|
||||
auto parseParticipants = [&](auto &&result, auto &&callback) {
|
||||
if (wasRecentRequest) {
|
||||
channel->session().api().parseRecentChannelParticipants(
|
||||
channel->session().api().chatParticipants().parseRecent(
|
||||
channel,
|
||||
result,
|
||||
callback);
|
||||
} else {
|
||||
channel->session().api().parseChannelParticipants(
|
||||
channel->session().api().chatParticipants().parse(
|
||||
channel,
|
||||
result,
|
||||
callback);
|
||||
|
@ -1732,7 +1733,7 @@ void ParticipantsBoxController::unkickParticipant(not_null<UserData*> user) {
|
|||
delegate()->peerListRemoveRow(row);
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
_peer->session().api().addChatParticipants(_peer, { 1, user });
|
||||
_peer->session().api().chatParticipants().add(_peer, { 1, user });
|
||||
}
|
||||
|
||||
void ParticipantsBoxController::kickParticipantSure(
|
||||
|
@ -1750,9 +1751,12 @@ void ParticipantsBoxController::kickParticipantSure(
|
|||
}
|
||||
auto &session = _peer->session();
|
||||
if (const auto chat = _peer->asChat()) {
|
||||
session.api().kickParticipant(chat, participant);
|
||||
session.api().chatParticipants().kick(chat, participant);
|
||||
} else if (const auto channel = _peer->asChannel()) {
|
||||
session.api().kickParticipant(channel, participant, currentRights);
|
||||
session.api().chatParticipants().kick(
|
||||
channel,
|
||||
participant,
|
||||
currentRights);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1803,7 +1807,9 @@ void ParticipantsBoxController::removeKickedWithRow(
|
|||
void ParticipantsBoxController::removeKicked(
|
||||
not_null<PeerData*> participant) {
|
||||
if (const auto channel = _peer->asChannel()) {
|
||||
channel->session().api().unblockParticipant(channel, participant);
|
||||
channel->session().api().chatParticipants().unblock(
|
||||
channel,
|
||||
participant);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2010,7 +2016,7 @@ void ParticipantsBoxController::subscribeToCreatorChange(
|
|||
channel->mgInfo->lastAdmins.clear();
|
||||
channel->mgInfo->lastRestricted.clear();
|
||||
channel->mgInfo->lastParticipants.clear();
|
||||
api->parseRecentChannelParticipants(channel, result);
|
||||
api->chatParticipants().parseRecent(channel, result);
|
||||
if (weak) {
|
||||
fullListRefresh();
|
||||
}
|
||||
|
@ -2175,7 +2181,7 @@ void ParticipantsBoxSearchController::searchDone(
|
|||
_queries.erase(it);
|
||||
}
|
||||
};
|
||||
_channel->session().api().parseChannelParticipants(
|
||||
_channel->session().api().chatParticipants().parse(
|
||||
_channel,
|
||||
result,
|
||||
addToCache);
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "calls/group/calls_group_invite_controller.h"
|
||||
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "calls/group/calls_group_call.h"
|
||||
#include "calls/group/calls_group_menu.h"
|
||||
#include "boxes/peer_lists_box.h"
|
||||
|
@ -221,7 +222,7 @@ object_ptr<Ui::BoxContent> PrepareInviteBox(
|
|||
const std::vector<not_null<UserData*>> &users,
|
||||
const std::vector<not_null<UserData*>> &nonMembers,
|
||||
Fn<void()> finish) {
|
||||
peer->session().api().addChatParticipants(
|
||||
peer->session().api().chatParticipants().add(
|
||||
peer,
|
||||
nonMembers,
|
||||
[=](bool) { invite(users); finish(); });
|
||||
|
|
|
@ -49,7 +49,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/unixtime.h"
|
||||
#include "base/qt_signal_producer.h"
|
||||
#include "base/timer_rpl.h"
|
||||
#include "apiwrap.h" // api().kickParticipant.
|
||||
#include "apiwrap.h" // api().kick.
|
||||
#include "api/api_chat_participants.h" // api().kick.
|
||||
#include "webrtc/webrtc_video_track.h"
|
||||
#include "webrtc/webrtc_media_devices.h" // UniqueDesktopCaptureSource.
|
||||
#include "webrtc/webrtc_audio_input_tester.h"
|
||||
|
@ -1344,7 +1345,7 @@ void Panel::showBox(
|
|||
|
||||
void Panel::kickParticipantSure(not_null<PeerData*> participantPeer) {
|
||||
if (const auto chat = _peer->asChat()) {
|
||||
chat->session().api().kickParticipant(chat, participantPeer);
|
||||
chat->session().api().chatParticipants().kick(chat, participantPeer);
|
||||
} else if (const auto channel = _peer->asChannel()) {
|
||||
const auto currentRestrictedRights = [&] {
|
||||
const auto user = participantPeer->asUser();
|
||||
|
@ -1356,7 +1357,7 @@ void Panel::kickParticipantSure(not_null<PeerData*> participantPeer) {
|
|||
? i->second.rights
|
||||
: ChatRestrictionsInfo();
|
||||
}();
|
||||
channel->session().api().kickParticipant(
|
||||
channel->session().api().chatParticipants().kick(
|
||||
channel,
|
||||
participantPeer,
|
||||
currentRestrictedRights);
|
||||
|
|
|
@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "chat_helpers/message_field.h" // PrepareMentionTag.
|
||||
#include "mainwindow.h"
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "main/main_session.h"
|
||||
#include "storage/storage_account.h"
|
||||
#include "core/application.h"
|
||||
|
@ -431,7 +432,8 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
|
|||
}
|
||||
} else if (_channel && _channel->isMegagroup()) {
|
||||
if (_channel->lastParticipantsRequestNeeded()) {
|
||||
_channel->session().api().requestLastParticipants(_channel);
|
||||
_channel->session().api().chatParticipants().requestLast(
|
||||
_channel);
|
||||
} else {
|
||||
mrows.reserve(mrows.size() + _channel->mgInfo->lastParticipants.size());
|
||||
for (const auto user : _channel->mgInfo->lastParticipants) {
|
||||
|
@ -489,7 +491,8 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
|
|||
} else if (_channel && _channel->isMegagroup()) {
|
||||
if (_channel->mgInfo->bots.empty()) {
|
||||
if (!_channel->mgInfo->botStatus) {
|
||||
_channel->session().api().requestBots(_channel);
|
||||
_channel->session().api().chatParticipants().requestBots(
|
||||
_channel);
|
||||
}
|
||||
} else {
|
||||
const auto &commands = _channel->mgInfo->botCommands();
|
||||
|
|
|
@ -927,77 +927,4 @@ void ApplyChannelUpdate(
|
|||
channel->owner().sendHistoryChangeNotifications();
|
||||
}
|
||||
|
||||
void ApplyMegagroupAdmins(
|
||||
not_null<ChannelData*> channel,
|
||||
const MTPDchannels_channelParticipants &data) {
|
||||
Expects(channel->isMegagroup());
|
||||
|
||||
channel->owner().processUsers(data.vusers());
|
||||
|
||||
const auto &list = data.vparticipants().v;
|
||||
const auto i = ranges::find(
|
||||
list,
|
||||
mtpc_channelParticipantCreator,
|
||||
&MTPChannelParticipant::type);
|
||||
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());
|
||||
} 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 = 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 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) {
|
||||
adding.emplace(
|
||||
peerToUser(channel->mgInfo->creator->id),
|
||||
channel->mgInfo->creatorRank);
|
||||
}
|
||||
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.emplace(0, QString());
|
||||
}
|
||||
|
||||
Data::ChannelAdminChanges changes(channel);
|
||||
for (const auto &[addingId, rank] : adding) {
|
||||
if (!removing.remove(addingId)) {
|
||||
changes.add(addingId, rank);
|
||||
}
|
||||
}
|
||||
for (const auto &[removingId, rank] : removing) {
|
||||
changes.remove(removingId);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -481,8 +481,4 @@ void ApplyChannelUpdate(
|
|||
not_null<ChannelData*> channel,
|
||||
const MTPDchannelFull &update);
|
||||
|
||||
void ApplyMegagroupAdmins(
|
||||
not_null<ChannelData*> channel,
|
||||
const MTPDchannels_channelParticipants &data);
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/crc32hash.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "main/main_session.h"
|
||||
#include "main/main_session_settings.h"
|
||||
|
@ -644,7 +645,7 @@ void PeerData::updateFullForced() {
|
|||
session().api().requestFullPeer(this);
|
||||
if (const auto channel = asChannel()) {
|
||||
if (!channel->amCreator() && !channel->inviter) {
|
||||
session().api().requestSelfParticipant(channel);
|
||||
session().api().chatParticipants().requestSelf(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "mainwidget.h"
|
||||
#include "core/application.h"
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "api/api_attached_stickers.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "main/main_session.h"
|
||||
|
@ -444,7 +445,7 @@ void InnerWidget::requestAdmins() {
|
|||
MTP_int(kMaxChannelAdmins),
|
||||
MTP_long(participantsHash)
|
||||
)).done([=](const MTPchannels_ChannelParticipants &result) {
|
||||
session().api().parseChannelParticipants(_channel, result, [&](
|
||||
session().api().chatParticipants().parse(_channel, result, [&](
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list) {
|
||||
auto filtered = (
|
||||
|
|
|
@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_histories.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "main/main_session.h"
|
||||
|
@ -2587,7 +2588,7 @@ void History::applyDialog(
|
|||
data.vtop_message().v);
|
||||
if (const auto item = owner().message(topMessageId)) {
|
||||
if (item->date() <= channel->date) {
|
||||
session().api().requestSelfParticipant(channel);
|
||||
session().api().chatParticipants().requestSelf(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "api/api_editing.h"
|
||||
#include "api/api_bot.h"
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "api/api_sending.h"
|
||||
#include "api/api_text_entities.h"
|
||||
#include "api/api_send_progress.h"
|
||||
|
@ -5675,7 +5676,8 @@ void HistoryWidget::handlePeerMigration() {
|
|||
showHistory(
|
||||
channel->id,
|
||||
(_showAtMsgId > 0) ? (-_showAtMsgId) : _showAtMsgId);
|
||||
channel->session().api().requestParticipantsCountDelayed(channel);
|
||||
channel->session().api().chatParticipants().requestCountDelayed(
|
||||
channel);
|
||||
} else {
|
||||
_migrated = _history->migrateFrom();
|
||||
_list->notifyMigrateUpdated();
|
||||
|
@ -6737,10 +6739,10 @@ void HistoryWidget::handlePeerUpdate() {
|
|||
session().api().requestFullPeer(_peer);
|
||||
} else if (auto channel = _peer->asMegagroup()) {
|
||||
if (!channel->mgInfo->botStatus) {
|
||||
session().api().requestBots(channel);
|
||||
session().api().chatParticipants().requestBots(channel);
|
||||
}
|
||||
if (channel->mgInfo->admins.empty()) {
|
||||
session().api().requestAdmins(channel);
|
||||
session().api().chatParticipants().requestAdmins(channel);
|
||||
}
|
||||
}
|
||||
if (!_a_show.animating()) {
|
||||
|
|
|
@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_web_page.h"
|
||||
#include "storage/storage_account.h"
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
|
@ -672,7 +673,7 @@ void ComposeControls::setHistory(SetHistoryArgs &&args) {
|
|||
session().api().requestFullPeer(peer);
|
||||
} else if (const auto channel = peer->asMegagroup()) {
|
||||
if (!channel->mgInfo->botStatus) {
|
||||
session().api().requestBots(channel);
|
||||
session().api().chatParticipants().requestBots(channel);
|
||||
}
|
||||
} else if (hasSilentBroadcastToggle()) {
|
||||
_silent = std::make_unique<Ui::SilentToggle>(
|
||||
|
|
|
@ -51,6 +51,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/unixtime.h"
|
||||
#include "support/support_helper.h"
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "styles/style_window.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
@ -1143,7 +1144,7 @@ void TopBarWidget::updateOnlineDisplay() {
|
|||
&& (channel->membersCount()
|
||||
<= channel->session().serverConfig().chatSizeMax)) {
|
||||
if (channel->lastParticipantsRequestNeeded()) {
|
||||
session().api().requestLastParticipants(channel);
|
||||
session().api().chatParticipants().requestLast(channel);
|
||||
}
|
||||
const auto self = session().user();
|
||||
auto online = 0;
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "profile/profile_block_group_members.h"
|
||||
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "styles/style_profile.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
|
@ -89,10 +90,10 @@ void GroupMembersWidget::removePeer(PeerData *selectedPeer) {
|
|||
const auto callback = [=] {
|
||||
Ui::hideLayer();
|
||||
if (const auto chat = peer->asChat()) {
|
||||
chat->session().api().kickParticipant(chat, user);
|
||||
chat->session().api().chatParticipants().kick(chat, user);
|
||||
Ui::showPeerHistory(chat, ShowAtTheEndMsgId);
|
||||
} else if (const auto channel = peer->asChannel()) {
|
||||
channel->session().api().kickParticipant(
|
||||
channel->session().api().chatParticipants().kick(
|
||||
channel,
|
||||
user,
|
||||
currentRestrictedRights);
|
||||
|
@ -158,7 +159,7 @@ void GroupMembersWidget::preloadMore() {
|
|||
//if (auto megagroup = peer()->asMegagroup()) {
|
||||
// auto &megagroupInfo = megagroup->mgInfo;
|
||||
// if (!megagroupInfo->lastParticipants.isEmpty() && megagroupInfo->lastParticipants.size() < megagroup->membersCount()) {
|
||||
// peer()->session().api().requestLastParticipants(megagroup, false);
|
||||
// peer()->session().api().requestLast(megagroup, false);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
@ -198,7 +199,8 @@ void GroupMembersWidget::refreshMembers() {
|
|||
fillChatMembers(chat);
|
||||
} else if (const auto megagroup = peer()->asMegagroup()) {
|
||||
if (megagroup->lastParticipantsRequestNeeded()) {
|
||||
megagroup->session().api().requestLastParticipants(megagroup);
|
||||
megagroup->session().api().chatParticipants().requestLast(
|
||||
megagroup);
|
||||
}
|
||||
fillMegagroupMembers(megagroup);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "window/window_peer_menu.h"
|
||||
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "boxes/delete_messages_box.h"
|
||||
|
@ -1090,9 +1091,9 @@ void PeerMenuAddChannelMembers(
|
|||
return;
|
||||
}
|
||||
const auto api = &channel->session().api();
|
||||
api->requestChannelMembersForAdd(channel, crl::guard(navigation, [=](
|
||||
api->chatParticipants().requestForAdd(channel, crl::guard(navigation, [=](
|
||||
const MTPchannels_ChannelParticipants &result) {
|
||||
api->parseChannelParticipants(channel, result, [&](
|
||||
api->chatParticipants().parse(channel, result, [&](
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list) {
|
||||
auto already = (
|
||||
|
|
Loading…
Add table
Reference in a new issue