From ecc49f9cd486eeeb3e8aad450dae644c2cba81ec Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 20 Nov 2015 16:34:37 +0300 Subject: [PATCH] support of bots added to megagroups --- Telegram/SourceFiles/apiwrap.cpp | 38 +++++++++++++++--- Telegram/SourceFiles/apiwrap.h | 1 + Telegram/SourceFiles/app.cpp | 26 ++++++++++--- Telegram/SourceFiles/app.h | 5 +++ Telegram/SourceFiles/dialogswidget.cpp | 3 +- Telegram/SourceFiles/dropdown.cpp | 2 +- Telegram/SourceFiles/history.cpp | 53 ++++++++++++++++++++++++-- Telegram/SourceFiles/historywidget.cpp | 20 +++++++++- Telegram/SourceFiles/historywidget.h | 6 ++- Telegram/SourceFiles/mainwidget.cpp | 8 +++- Telegram/SourceFiles/mainwidget.h | 3 +- Telegram/SourceFiles/structs.cpp | 30 ++++++++++----- Telegram/SourceFiles/structs.h | 2 +- 13 files changed, 166 insertions(+), 31 deletions(-) diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index d0f9d7460..dede73032 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -313,6 +313,20 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt App::main()->peerUpdated(cfrom); } } + const QVector &v(f.vbot_info.c_vector().v); + for (QVector::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 &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::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) { diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 1e2fd040e..1bf537098 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -37,6 +37,7 @@ public: void requestPeer(PeerData *peer); void requestPeers(const QList &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); diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 4d31f06a3..1db244376 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -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); + } + } + +} diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index 60f0717bd..e1aaae4f1 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -315,3 +315,8 @@ namespace App { void showLayerLast(LayeredWidget *w); }; + +namespace Notify { + void userIsBotChanged(UserData *user); + void botCommandsChanged(UserData *user); +}; diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index 931554bd9..18520147a 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -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)); } diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp index a52541d73..c8b066bf3 100644 --- a/Telegram/SourceFiles/dropdown.cpp +++ b/Telegram/SourceFiles/dropdown.cpp @@ -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(); diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 613fa1729..606b73107 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -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()); diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index d94a67004..6a12248bb 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -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()) { diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index 87ec9b201..960eb78d6 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -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); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index e4edb3e6e..71fe3e66b 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -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() { diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 8bb36a983..165239ef4 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -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); diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index 1d27c9def..8934fa08c 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -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; } diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index 1435211a7..0a95e2c93 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -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 LastParticipants; LastParticipants lastParticipants;