support of bots added to megagroups

This commit is contained in:
John Preston 2015-11-20 16:34:37 +03:00
parent 417024e6d2
commit ecc49f9cd4
13 changed files with 166 additions and 31 deletions

View File

@ -313,6 +313,20 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
App::main()->peerUpdated(cfrom);
}
}
const QVector<MTPBotInfo> &v(f.vbot_info.c_vector().v);
for (QVector<MTPBotInfo>::const_iterator i = v.cbegin(), e = v.cend(); i < e; ++i) {
switch (i->type()) {
case mtpc_botInfo: {
const MTPDbotInfo &b(i->c_botInfo());
UserData *user = App::userLoaded(b.vuser_id.v);
if (user) {
user->setBotInfo(*i);
App::clearPeerUpdated(user);
emit fullPeerUpdated(user);
}
} break;
}
}
channel->about = qs(f.vabout);
int32 newCount = f.has_participants_count() ? f.vparticipants_count.v : 0;
if (newCount != channel->count) {
@ -437,9 +451,11 @@ void ApiWrap::requestLastParticipants(ChannelData *peer, bool fromStart) {
}
mtpRequestId req = MTP::send(MTPchannels_GetParticipants(peer->inputChannel, MTP_channelParticipantsRecent(), MTP_int(fromStart ? 0 : peer->mgInfo->lastParticipants.size()), MTP_int(1)), rpcDone(&ApiWrap::lastParticipantsDone, peer), rpcFail(&ApiWrap::lastParticipantsFail, peer));
_participantsRequests.insert(peer, fromStart ? req : -req);
if (fromStart) {
_botsRequests.insert(peer, MTP::send(MTPchannels_GetParticipants(peer->inputChannel, MTP_channelParticipantsBots(), MTP_int(0), MTP_int(cMaxGroupCount())), rpcDone(&ApiWrap::lastParticipantsDone, peer), rpcFail(&ApiWrap::lastParticipantsFail, peer)));
}
}
void ApiWrap::requestBots(ChannelData *peer) {
if (!peer || !peer->isMegagroup() || _botsRequests.contains(peer)) return;
_botsRequests.insert(peer, MTP::send(MTPchannels_GetParticipants(peer->inputChannel, MTP_channelParticipantsBots(), MTP_int(0), MTP_int(cMaxGroupCount())), rpcDone(&ApiWrap::lastParticipantsDone, peer), rpcFail(&ApiWrap::lastParticipantsFail, peer)));
}
void ApiWrap::gotChat(PeerData *peer, const MTPmessages_Chats &result) {
@ -518,7 +534,7 @@ void ApiWrap::lastParticipantsDone(ChannelData *peer, const MTPchannels_ChannelP
const MTPDchannels_channelParticipants &d(result.c_channels_channelParticipants());
const QVector<MTPChannelParticipant> &v(d.vparticipants.c_vector().v);
App::feedUsers(d.vusers);
bool added = false;
bool added = false, needBotsInfos = false;
int32 botStatus = peer->mgInfo->botStatus;
for (QVector<MTPChannelParticipant>::const_iterator i = v.cbegin(), e = v.cend(); i != e; ++i) {
int32 userId = 0;
@ -536,16 +552,28 @@ void ApiWrap::lastParticipantsDone(ChannelData *peer, const MTPchannels_ChannelP
if (bots) {
if (u->botInfo) {
peer->mgInfo->bots.insert(u, true);
botStatus = (botStatus > 0/* || i.key()->botInfo->readsAllHistory*/) ? 2 : 1;
botStatus = 2;// (botStatus > 0/* || !i.key()->botInfo->readsAllHistory*/) ? 2 : 1;
if (!u->botInfo->inited) {
needBotsInfos = true;
}
}
} else {
if (peer->mgInfo->lastParticipants.indexOf(u) < 0) {
peer->mgInfo->lastParticipants.push_back(u);
if (admin) peer->mgInfo->lastAdmins.insert(u, true);
if (u->botInfo) {
peer->mgInfo->bots.insert(u, true);
if (peer->mgInfo->botStatus != 0 && peer->mgInfo->botStatus < 2) {
peer->mgInfo->botStatus = 2;
}
}
added = true;
}
}
}
if (needBotsInfos) {
requestFullPeer(peer);
}
if (d.vcount.v > peer->count) {
peer->count = d.vcount.v;
} else if (v.count() > peer->count) {

View File

@ -37,6 +37,7 @@ public:
void requestPeer(PeerData *peer);
void requestPeers(const QList<PeerData*> &peers);
void requestLastParticipants(ChannelData *peer, bool fromStart = true);
void requestBots(ChannelData *peer);
void processFullPeer(PeerData *peer, const MTPmessages_ChatFull &result);
void processFullPeer(PeerData *peer, const MTPUserFull &result);

View File

@ -680,7 +680,7 @@ namespace App {
i = chat->participants.erase(i);
} else {
if (i.key()->botInfo) {
botStatus = (botStatus > 0/* || i.key()->botInfo->readsAllHistory*/) ? 2 : 1;
botStatus = 2;// (botStatus > 0/* || !i.key()->botInfo->readsAllHistory*/) ? 2 : 1;
if (requestBotInfos && !i.key()->botInfo->inited && App::api()) App::api()->requestFullPeer(i.key());
}
if (!found && i.key()->id == h->lastKeyboardFrom) {
@ -737,7 +737,7 @@ namespace App {
}
chat->count++;
if (user->botInfo) {
chat->botStatus = (chat->botStatus > 0/* || !user->botInfo->readsAllHistory*/) ? 2 : 1;
chat->botStatus = 2;// (chat->botStatus > 0/* || !user->botInfo->readsAllHistory*/) ? 2 : 1;
if (!user->botInfo->inited && App::api()) App::api()->requestFullPeer(user);
}
}
@ -798,7 +798,7 @@ namespace App {
int32 botStatus = -1;
for (ChatData::Participants::const_iterator j = chat->participants.cbegin(), e = chat->participants.cend(); j != e; ++j) {
if (j.key()->botInfo) {
if (botStatus > 0/* || !j.key()->botInfo->readsAllHistory*/) {
if (true || botStatus > 0/* || !j.key()->botInfo->readsAllHistory*/) {
botStatus = 2;
break;
}
@ -2516,8 +2516,8 @@ namespace App {
}
inline const ReplyMarkup &replyMarkup(const ReplyMarkups &markups, MsgId msgId) {
ReplyMarkups::const_iterator i = replyMarkups.constFind(msgId);
if (i == replyMarkups.cend()) return zeroMarkup;
ReplyMarkups::const_iterator i = markups.constFind(msgId);
if (i == markups.cend()) return zeroMarkup;
return i.value();
}
const ReplyMarkup &replyMarkup(ChannelId channelId, MsgId msgId) {
@ -2847,3 +2847,19 @@ namespace App {
}
}
namespace Notify {
void userIsBotChanged(UserData *user) {
if (MainWidget *m = App::main()) {
m->notifyUserIsBotChanged(user);
}
}
void botCommandsChanged(UserData *user) {
if (MainWidget *m = App::main()) {
m->notifyBotCommandsChanged(user);
}
}
}

View File

@ -315,3 +315,8 @@ namespace App {
void showLayerLast(LayeredWidget *w);
};
namespace Notify {
void userIsBotChanged(UserData *user);
void botCommandsChanged(UserData *user);
};

View File

@ -1954,7 +1954,8 @@ void DialogsWidget::loadDialogs() {
return;
}
int32 loadCount = _dialogsOffsetDate ? DialogsPerPage : DialogsFirstLoad;
int32 loadCount = (!cTestMode() || _dialogsOffsetDate) ? DialogsPerPage : DialogsFirstLoad;
if (!cTestMode() && _dialogsOffsetDate) return;
_dialogsRequest = MTP::send(MTPmessages_GetDialogs(MTP_int(_dialogsOffsetDate), MTP_int(_dialogsOffsetId), _dialogsOffsetPeer ? _dialogsOffsetPeer->input : MTP_inputPeerEmpty(), MTP_int(loadCount)), rpcDone(&DialogsWidget::dialogsReceived), rpcFail(&DialogsWidget::dialogsFailed));
}

View File

@ -3047,7 +3047,7 @@ void MentionsDropdown::updateFiltered(bool toDown) {
bots.insert(_user, true);
} else if (_channel && _channel->isMegagroup()) {
if (_channel->mgInfo->bots.isEmpty()) {
if (!_channel->mgInfo->botStatus && App::api()) App::api()->requestLastParticipants(_channel);
if (!_channel->mgInfo->botStatus && App::api()) App::api()->requestBots(_channel);
} else {
for (MegagroupInfo::Bots::const_iterator i = _channel->mgInfo->bots.cbegin(), e = _channel->mgInfo->bots.cend(); i != e; ++i) {
UserData *user = i.key();

View File

@ -271,6 +271,11 @@ void DialogRow::paint(Painter &p, int32 w, bool act, bool sel, bool onlyBackgrou
}
}
if (history->peer->isUser() && history->peer->isVerified()) {
rectForName.setWidth(rectForName.width() - st::verifiedCheck.pxWidth() - st::verifiedCheckPos.x());
p.drawSprite(rectForName.topLeft() + QPoint(qMin(history->peer->dialogName().maxWidth(), rectForName.width()), 0) + st::verifiedCheckPos, (act ? st::verifiedCheckInv : st::verifiedCheck));
}
p.setPen((act ? st::dlgActiveColor : st::dlgNameColor)->p);
history->peer->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
}
@ -337,6 +342,11 @@ void FakeDialogRow::paint(Painter &p, int32 w, bool act, bool sel, bool onlyBack
int32 lastWidth = namewidth;
_item->drawInDialog(p, QRect(nameleft, st::dlgPaddingVer + st::dlgFont->height + st::dlgSep, lastWidth, st::dlgFont->height), act, _cacheFor, _cache);
if (history->peer->isUser() && history->peer->isVerified()) {
rectForName.setWidth(rectForName.width() - st::verifiedCheck.pxWidth() - st::verifiedCheckPos.x());
p.drawSprite(rectForName.topLeft() + QPoint(qMin(history->peer->dialogName().maxWidth(), rectForName.width()), 0) + st::verifiedCheckPos, (act ? st::verifiedCheckInv : st::verifiedCheck));
}
p.setPen((act ? st::dlgActiveColor : st::dlgNameColor)->p);
history->peer->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
}
@ -933,6 +943,8 @@ HistoryItem *ChannelHistory::addNewToBlocks(const MTPMessage &msg, NewMessageTyp
if (!isImportantFlags && !onlyImportant() && !isEmpty() && type == NewMessageLast) {
clear(true);
} else if (isMegagroup() && !isEmpty() && type == NewMessageLast && idFromMessage(msg) > maxMsgId()) { // temp
clear(true);
}
HistoryBlock *to = 0;
@ -1490,6 +1502,12 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo
if (peer->asChannel()->mgInfo->lastParticipants.indexOf(user) < 0) {
peer->asChannel()->mgInfo->lastParticipants.push_front(user);
}
if (user->botInfo) {
peer->asChannel()->mgInfo->bots.insert(user, true);
if (peer->asChannel()->mgInfo->botStatus != 0 && peer->asChannel()->mgInfo->botStatus < 2) {
peer->asChannel()->mgInfo->botStatus = 2;
}
}
}
}
}
@ -1498,8 +1516,16 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo
case mtpc_messageActionChatJoinedByLink: {
const MTPDmessageActionChatJoinedByLink &d(action.c_messageActionChatJoinedByLink());
if (peer->isMegagroup()) {
if (result->from()->isUser() && peer->asChannel()->mgInfo->lastParticipants.indexOf(result->from()->asUser()) < 0) {
peer->asChannel()->mgInfo->lastParticipants.push_front(result->from()->asUser());
if (result->from()->isUser()) {
if (peer->asChannel()->mgInfo->lastParticipants.indexOf(result->from()->asUser()) < 0) {
peer->asChannel()->mgInfo->lastParticipants.push_front(result->from()->asUser());
}
if (result->from()->asUser()->botInfo) {
peer->asChannel()->mgInfo->bots.insert(result->from()->asUser(), true);
if (peer->asChannel()->mgInfo->botStatus != 0 && peer->asChannel()->mgInfo->botStatus < 2) {
peer->asChannel()->mgInfo->botStatus = 2;
}
}
}
}
} break;
@ -1511,10 +1537,23 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo
case mtpc_messageActionChatDeleteUser: {
const MTPDmessageActionChatDeleteUser &d(action.c_messageActionChatDeleteUser());
if (lastKeyboardFrom == peerFromUser(d.vuser_id)) {
PeerId uid = peerFromUser(d.vuser_id);
if (lastKeyboardFrom == uid) {
clearLastKeyboard();
}
// App::peer(App::peerFromUser(d.vuser_id)); left
if (peer->isMegagroup()) {
if (UserData *user = App::userLoaded(uid)) {
int32 index = peer->asChannel()->mgInfo->lastParticipants.indexOf(user);
if (index >= 0) {
peer->asChannel()->mgInfo->lastParticipants.removeAt(index);
}
peer->asChannel()->mgInfo->lastAdmins.remove(user);
peer->asChannel()->mgInfo->bots.remove(user);
if (peer->asChannel()->mgInfo->bots.isEmpty() && peer->asChannel()->mgInfo->botStatus > 0) {
peer->asChannel()->mgInfo->botStatus = -1;
}
}
}
} break;
case mtpc_messageActionChatEditPhoto: {
@ -1748,6 +1787,12 @@ HistoryItem *History::addNewItem(HistoryBlock *to, bool newBlock, HistoryItem *a
} else if (peer->isMegagroup()) {
lastAuthors = &peer->asChannel()->mgInfo->lastParticipants;
peer->asChannel()->mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsAdminsOutdated;
if (adding->from()->asUser()->botInfo) {
peer->asChannel()->mgInfo->bots.insert(adding->from()->asUser(), true);
if (peer->asChannel()->mgInfo->botStatus != 0 && peer->asChannel()->mgInfo->botStatus < 2) {
peer->asChannel()->mgInfo->botStatus = 2;
}
}
}
if (lastAuthors) {
int prev = lastAuthors->indexOf(adding->from()->asUser());

View File

@ -1727,6 +1727,13 @@ int32 HistoryInner::itemTop(const HistoryItem *item) const { // -1 if should not
return (top < 0) ? top : (top + item->y + item->block()->y);
}
void HistoryInner::notifyIsBotChanged() {
_botInfo = (_history && _history->peer->isUser()) ? _history->peer->asUser()->botInfo : 0;
if (_botInfo && !_botInfo->inited && App::api()) {
App::api()->requestFullPeer(_peer);
}
}
void HistoryInner::applyDragSelection() {
applyDragSelection(&_selected);
}
@ -2935,7 +2942,7 @@ void HistoryWidget::updateStickers() {
_stickersUpdateRequest = MTP::send(MTPmessages_GetAllStickers(MTP_string(cStickersHash())), rpcDone(&HistoryWidget::stickersGot), rpcFail(&HistoryWidget::stickersFailed));
}
void HistoryWidget::botCommandsChanged(UserData *user) {
void HistoryWidget::notifyBotCommandsChanged(UserData *user) {
if (_peer && (_peer == user || !_peer->isUser())) {
if (_attachMention.clearFilteredCommands()) {
checkMentionDropdown();
@ -2943,6 +2950,15 @@ void HistoryWidget::botCommandsChanged(UserData *user) {
}
}
void HistoryWidget::notifyUserIsBotChanged(UserData *user) {
if (_peer && _peer == user) {
_list->notifyIsBotChanged();
_list->updateBotInfo();
updateControlsVisibility();
resizeEvent(0);
}
}
void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
cSetLastStickersUpdate(getms(true));
_stickersUpdateRequest = 0;
@ -6344,6 +6360,8 @@ void HistoryWidget::peerUpdated(PeerData *data) {
App::api()->requestFullPeer(data);
} else if (data->isUser() && data->asUser()->blocked == UserBlockUnknown) {
App::api()->requestFullPeer(data);
} else if (data->isMegagroup() && !data->asChannel()->mgInfo->botStatus) {
App::api()->requestBots(data->asChannel());
}
}
if (!_a_show.animating()) {

View File

@ -95,6 +95,8 @@ public:
int32 historyDrawTop() const;
int32 itemTop(const HistoryItem *item) const; // -1 if should not be visible, -2 if bad history()
void notifyIsBotChanged();
~HistoryInner();
public slots:
@ -555,6 +557,9 @@ public:
resizeEvent(0);
}
void notifyBotCommandsChanged(UserData *user);
void notifyUserIsBotChanged(UserData *user);
~HistoryWidget();
signals:
@ -649,7 +654,6 @@ public slots:
void onDraftSave(bool delayed = false);
void updateStickers();
void botCommandsChanged(UserData *user);
void onRecordError();
void onRecordDone(QByteArray result, qint32 samples);

View File

@ -682,8 +682,12 @@ void MainWidget::updateStickers() {
history.updateStickers();
}
void MainWidget::botCommandsChanged(UserData *bot) {
history.botCommandsChanged(bot);
void MainWidget::notifyUserIsBotChanged(UserData *bot) {
history.notifyUserIsBotChanged(bot);
}
void MainWidget::notifyBotCommandsChanged(UserData *bot) {
history.notifyBotCommandsChanged(bot);
}
void MainWidget::onUpdateMuted() {

View File

@ -384,7 +384,8 @@ public:
void updateMutedIn(int32 seconds);
void updateStickers();
void botCommandsChanged(UserData *bot);
void notifyBotCommandsChanged(UserData *bot);
void notifyUserIsBotChanged(UserData *bot);
void choosePeer(PeerId peerId, MsgId showAtMsgId); // does offerPeer or showPeerHistory
void clearBotStartToken(PeerData *peer);

View File

@ -235,15 +235,23 @@ void UserData::setPhone(const QString &newPhone) {
void UserData::setBotInfoVersion(int32 version) {
if (version < 0) {
delete botInfo;
botInfo = 0;
if (botInfo) {
if (!botInfo->commands.isEmpty()) {
botInfo->commands.clear();
Notify::botCommandsChanged(this);
}
delete botInfo;
botInfo = 0;
Notify::userIsBotChanged(this);
}
} else if (!botInfo) {
botInfo = new BotInfo();
botInfo->version = version;
Notify::userIsBotChanged(this);
} else if (botInfo->version < version) {
if (!botInfo->commands.isEmpty()) {
botInfo->commands.clear();
if (App::main()) App::main()->botCommandsChanged(this);
Notify::botCommandsChanged(this);
}
botInfo->description.clear();
botInfo->shareText.clear();
@ -255,11 +263,15 @@ void UserData::setBotInfoVersion(int32 version) {
void UserData::setBotInfo(const MTPBotInfo &info) {
switch (info.type()) {
case mtpc_botInfoEmpty:
if (botInfo && !botInfo->commands.isEmpty()) {
if (App::main()) App::main()->botCommandsChanged(this);
if (botInfo) {
if (!botInfo->commands.isEmpty()) {
botInfo->commands.clear();
Notify::botCommandsChanged(this);
}
delete botInfo;
botInfo = 0;
Notify::userIsBotChanged(this);
}
delete botInfo;
botInfo = 0;
break;
case mtpc_botInfo: {
const MTPDbotInfo &d(info.c_botInfo());
@ -307,8 +319,8 @@ void UserData::setBotInfo(const MTPBotInfo &info) {
botInfo->inited = true;
if (changedCommands && App::main()) {
App::main()->botCommandsChanged(this);
if (changedCommands) {
Notify::botCommandsChanged(this);
}
} break;
}

View File

@ -526,7 +526,7 @@ private:
};
struct MegagroupInfo {
MegagroupInfo() : botStatus(-1), migrateFromPtr(0), lastParticipantsStatus(LastParticipantsUpToDate), lastParticipantsCount(0) {
MegagroupInfo() : botStatus(0), migrateFromPtr(0), lastParticipantsStatus(LastParticipantsUpToDate), lastParticipantsCount(0) {
}
typedef QList<UserData*> LastParticipants;
LastParticipants lastParticipants;