From 85635dbefde7fbedf17304fe436ef529c274aedb Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 10 Jun 2015 15:48:26 +0300 Subject: [PATCH] 31 layer, IPv6 support, bot support started --- Telegram/Resources/lang.strings | 1 + Telegram/SourceFiles/app.cpp | 129 +-- Telegram/SourceFiles/app.h | 4 +- Telegram/SourceFiles/config.h | 29 +- Telegram/SourceFiles/dropdown.cpp | 4 +- Telegram/SourceFiles/history.cpp | 14 +- Telegram/SourceFiles/historywidget.cpp | 41 +- Telegram/SourceFiles/intro/introcode.cpp | 2 +- Telegram/SourceFiles/intro/intropwdcheck.cpp | 2 +- Telegram/SourceFiles/intro/introsignup.cpp | 2 +- Telegram/SourceFiles/localstorage.cpp | 36 +- Telegram/SourceFiles/mainwidget.cpp | 22 +- .../SourceFiles/mtproto/mtpConnection.cpp | 356 ++++--- Telegram/SourceFiles/mtproto/mtpConnection.h | 53 +- Telegram/SourceFiles/mtproto/mtpCoreTypes.h | 2 +- Telegram/SourceFiles/mtproto/mtpDC.cpp | 11 +- Telegram/SourceFiles/mtproto/mtpScheme.cpp | 201 ++-- Telegram/SourceFiles/mtproto/mtpScheme.h | 922 +++++++++++------- Telegram/SourceFiles/mtproto/scheme.tl | 34 +- Telegram/SourceFiles/profilewidget.cpp | 8 +- Telegram/SourceFiles/settings.h | 4 +- Telegram/SourceFiles/structs.cpp | 48 + Telegram/SourceFiles/structs.h | 23 +- Telegram/SourceFiles/types.h | 3 +- Telegram/SourceFiles/window.cpp | 3 +- 25 files changed, 1232 insertions(+), 722 deletions(-) diff --git a/Telegram/Resources/lang.strings b/Telegram/Resources/lang.strings index 5b12e1a2e0..acaa2f4326 100644 --- a/Telegram/Resources/lang.strings +++ b/Telegram/Resources/lang.strings @@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_reconnecting_try_now" = "Try now"; "lng_status_service_notifications" = "service notifications"; +"lng_status_bot" = "bot"; "lng_status_offline" = "last seen a long time ago"; "lng_status_recently" = "last seen recently"; "lng_status_last_week" = "last seen within a week"; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 6924764198..02983783a2 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -206,7 +206,11 @@ namespace App { return (peer_id & 0x100000000L) ? int32(peer_id & 0xFFFFFFFFL) : 0; } - int32 onlineForSort(int32 online, int32 now) { + int32 onlineForSort(UserData *user, int32 now) { + if (isServiceUser(user->id) || user->botInfo) { + return now - 1; + } + int32 online = user->onlineTill; if (online <= 0) { switch (online) { case 0: @@ -232,8 +236,12 @@ namespace App { return online; } - int32 onlineWillChangeIn(int32 online, int32 now) { - if (online <= 0) { + int32 onlineWillChangeIn(UserData *user, int32 now) { + if (isServiceUser(user->id) || user->botInfo) { + return 86400; + } + int32 online = user->onlineTill; + if (online <= 0) { if (-online > now) return -online - now; return 86400; } @@ -255,6 +263,8 @@ namespace App { QString onlineText(UserData *user, int32 now, bool precise) { if (isServiceUser(user->id)) { return lang(lng_status_service_notifications); + } else if (user->botInfo) { + return lang(lng_status_bot); } int32 online = user->onlineTill; if (online <= 0) { @@ -337,84 +347,48 @@ namespace App { status = &emptyStatus; data->contact = -1; } break; - case mtpc_userDeleted: { - const MTPDuserDeleted &d(user.c_userDeleted()); + case mtpc_user: { + const MTPDuser &d(user.c_user()); PeerId peer(peerFromUser(d.vid.v)); data = App::user(peer); - data->input = MTP_inputPeerContact(d.vid); - data->inputUser = MTP_inputUserContact(d.vid); - data->setName(lang(lng_deleted), QString(), QString(), QString()); -// data->setName(textOneLine(qs(d.vfirst_name)), textOneLine(qs(d.vlast_name)), QString(), textOneLine(qs(d.vusername))); - data->setPhoto(MTP_userProfilePhotoEmpty()); - data->access = UserNoAccess; + int32 flags = d.vflags.v; + if (flags & MTPDuser_flag_self) { + data->input = MTP_inputPeerSelf(); + data->inputUser = MTP_inputUserSelf(); + } else if ((flags & (MTPDuser_flag_contact | MTPDuser_flag_mutual_contact)) || !d.has_access_hash()) { + data->input = MTP_inputPeerContact(d.vid); + data->inputUser = MTP_inputUserContact(d.vid); + } else { + data->input = MTP_inputPeerForeign(d.vid, d.vaccess_hash); + data->inputUser = MTP_inputUserForeign(d.vid, d.vaccess_hash); + } + if (flags & MTPDuser_flag_deleted) { + data->setPhone(QString()); + data->setName(lang(lng_deleted), QString(), QString(), QString()); + data->setPhoto(MTP_userProfilePhotoEmpty()); + data->access = UserNoAccess; + status = &emptyStatus; + } else { + data->setPhone(d.has_phone() ? qs(d.vphone) : QString()); + QString fname = d.has_first_name() ? textOneLine(qs(d.vfirst_name)) : QString(); + QString lname = d.has_last_name() ? textOneLine(qs(d.vlast_name)) : QString(); + QString uname = d.has_username() ? textOneLine(qs(d.vusername)) : QString(); + bool showPhone = !isServiceUser(data->id) && !(flags & (MTPDuser_flag_self | MTPDuser_flag_contact | MTPDuser_flag_mutual_contact)); + QString pname = (showPhone && !data->phone.isEmpty()) ? formatPhone(data->phone) : QString(); + data->setName(fname, lname, QString(), uname); + data->setPhoto(d.has_photo() ? d.vphoto : MTP_userProfilePhotoEmpty()); + if (d.has_access_hash()) data->access = d.vaccess_hash.v; + status = d.has_status() ? &d.vstatus : &emptyStatus; + } wasContact = (data->contact > 0); - status = &emptyStatus; - data->contact = -1; - } break; - case mtpc_userSelf: { - const MTPDuserSelf &d(user.c_userSelf()); - - PeerId peer(peerFromUser(d.vid.v)); - data = App::user(peer); - data->input = MTP_inputPeerSelf(); - data->inputUser = MTP_inputUserSelf(); - data->setName(textOneLine(qs(d.vfirst_name)), textOneLine(qs(d.vlast_name)), QString(), textOneLine(qs(d.vusername))); - data->setPhoto(d.vphoto); - data->setPhone(qs(d.vphone)); - data->access = 0; - wasContact = (data->contact > 0); - status = &d.vstatus; - - if (::self != data) { + if (d.has_bot_info_version()) data->setBotInfoVersion(d.vbot_info_version.v); + data->contact = (flags & (MTPDuser_flag_contact | MTPDuser_flag_mutual_contact)) ? 1 : (data->phone.isEmpty() ? -1 : 0); + if ((flags & MTPDuser_flag_self) && ::self != data) { ::self = data; if (App::wnd()) App::wnd()->updateGlobalMenu(); } } break; - case mtpc_userContact: { - const MTPDuserContact &d(user.c_userContact()); - - PeerId peer(peerFromUser(d.vid.v)); - data = App::user(peer); - data->input = MTP_inputPeerContact(d.vid); - data->inputUser = MTP_inputUserContact(d.vid); - data->setName(textOneLine(qs(d.vfirst_name)), textOneLine(qs(d.vlast_name)), QString(), textOneLine(qs(d.vusername))); - data->setPhoto(d.vphoto); - data->setPhone(qs(d.vphone)); - data->access = d.vaccess_hash.v; - wasContact = (data->contact > 0); - data->contact = 1; - status = &d.vstatus; - } break; - case mtpc_userRequest: { - const MTPDuserRequest &d(user.c_userRequest()); - - PeerId peer(peerFromUser(d.vid.v)); - data = App::user(peer); - data->input = MTP_inputPeerForeign(d.vid, d.vaccess_hash); - data->inputUser = MTP_inputUserForeign(d.vid, d.vaccess_hash); - data->setPhone(qs(d.vphone)); - data->setName(textOneLine(qs(d.vfirst_name)), textOneLine(qs(d.vlast_name)), (!isServiceUser(data->id) && !data->phone.isEmpty()) ? formatPhone(data->phone) : QString(), textOneLine(qs(d.vusername))); - data->setPhoto(d.vphoto); - data->access = d.vaccess_hash.v; - wasContact = (data->contact > 0); - data->contact = 0; - status = &d.vstatus; - } break; - case mtpc_userForeign: { - const MTPDuserForeign &d(user.c_userForeign()); - - PeerId peer(peerFromUser(d.vid.v)); - data = App::user(peer); - data->input = MTP_inputPeerForeign(d.vid, d.vaccess_hash); - data->inputUser = MTP_inputUserForeign(d.vid, d.vaccess_hash); - data->setName(textOneLine(qs(d.vfirst_name)), textOneLine(qs(d.vlast_name)), QString(), textOneLine(qs(d.vusername))); - data->setPhoto(d.vphoto); - data->access = d.vaccess_hash.v; - wasContact = (data->contact > 0); - data->contact = -1; - status = &d.vstatus; - } break; } if (!data) continue; @@ -731,11 +705,7 @@ namespace App { MTPint userId(MTP_int(0)); switch (dv.vuser.type()) { case mtpc_userEmpty: userId = dv.vuser.c_userEmpty().vid; break; - case mtpc_userDeleted: userId = dv.vuser.c_userDeleted().vid; break; - case mtpc_userContact: userId = dv.vuser.c_userContact().vid; break; - case mtpc_userSelf: userId = dv.vuser.c_userSelf().vid; break; - case mtpc_userRequest: userId = dv.vuser.c_userRequest().vid; break; - case mtpc_userForeign: userId = dv.vuser.c_userForeign().vid; break; + case mtpc_user: userId = dv.vuser.c_user().vid; break; } if (userId.v) { feedUserLink(userId, dv.vmy_link, dv.vforeign_link); @@ -1183,6 +1153,7 @@ namespace App { } DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation) { + bool sentSticker = false; if (convert) { if (convert->id != document) { DocumentsData::iterator i = documentsData.find(convert->id); @@ -1191,6 +1162,7 @@ namespace App { } convert->id = document; convert->status = FileReady; + sentSticker = !!convert->sticker; } convert->access = access; if (!convert->date && date) { @@ -1266,6 +1238,7 @@ namespace App { } } } + if (sentSticker && App::main()) App::main()->incrementSticker(result); return result; } diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index 14fa5c8f16..b5c5459cc9 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -92,8 +92,8 @@ namespace App { int32 userFromPeer(const PeerId &peer_id); int32 chatFromPeer(const PeerId &peer_id); - int32 onlineForSort(int32 online, int32 now); - int32 onlineWillChangeIn(int32 onlineOnServer, int32 nowOnServer); + int32 onlineForSort(UserData *user, int32 now); + int32 onlineWillChangeIn(UserData *user, int32 nowOnServer); QString onlineText(UserData *user, int32 nowOnServer, bool precise = false); bool onlineColorUse(int32 online, int32 now); diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index 14a560e0f5..ed4ff4b952 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -43,7 +43,8 @@ enum { MTPMinConnectDelay = 1000, // tcp connect should take less then 1 second MTPMaxConnectDelay = 8000, // tcp connect should take 8 seconds max MTPConnectionOldTimeout = 192000, // 192 seconds - MTPTcpConnectionWaitTimeout = 3000, // 3 seconds waiting for tcp, until we accept http + MTPTcpConnectionWaitTimeout = 2000, // 2 seconds waiting for tcp, until we accept http + MTPIPv4ConnectionWaitTimeout = 1000, // 1 seconds waiting for ipv4, until we accept ipv6 MTPMillerRabinIterCount = 30, // 30 Miller-Rabin iterations for dh_prime primality check MTPUploadSessionsCount = 4, // max 4 upload sessions is created @@ -125,7 +126,7 @@ enum { SaveDraftTimeout = 1000, // save draft after 1 secs of not changing text SaveDraftAnywayTimeout = 5000, // or save anyway each 5 secs - HiddenIsOnlineAfterMessage = 30, // user with hidden last seen stays online for such amount of seconds in the interface + SetOnlineAfterActivity = 30, // user with hidden last seen stays online for such amount of seconds in the interface ServiceUserId = 777000, WebPageUserId = 701000, @@ -186,10 +187,24 @@ static const BuiltInDc _builtInDcs[] = { { 5, "149.154.171.5", 443 } }; +static const BuiltInDc _builtInDcsIPv6[] = { + { 1, "2001:b28:f23d:f001::a", 443 }, + { 2, "2001:67c:4e8:f002::a", 443 }, + { 3, "2001:b28:f23d:f003::a", 443 }, + { 4, "2001:67c:4e8:f004::a", 443 }, + { 5, "2001:b28:f23f:f005::a", 443 } +}; + static const BuiltInDc _builtInTestDcs[] = { { 1, "149.154.175.10", 443 }, { 2, "149.154.167.40", 443 }, - { 3, "174.140.142.5", 443 } + { 3, "149.154.175.117", 443 } +}; + +static const BuiltInDc _builtInTestDcsIPv6[] = { + { 1, "2001:b28:f23d:f001::e", 443 }, + { 2, "2001:67c:4e8:f002::e", 443 }, + { 3, "2001:b28:f23d:f003::e", 443 } }; inline const BuiltInDc *builtInDcs() { @@ -200,6 +215,14 @@ inline int builtInDcsCount() { return (cTestMode() ? sizeof(_builtInTestDcs) : sizeof(_builtInDcs)) / sizeof(BuiltInDc); } +inline const BuiltInDc *builtInDcsIPv6() { + return cTestMode() ? _builtInTestDcsIPv6 : _builtInDcsIPv6; +} + +inline int builtInDcsCountIPv6() { + return (cTestMode() ? sizeof(_builtInTestDcsIPv6) : sizeof(_builtInDcsIPv6)) / sizeof(BuiltInDc); +} + static const char *UpdatesPublicKey = "\ -----BEGIN RSA PUBLIC KEY-----\n\ MIGJAoGBAMA4ViQrjkPZ9xj0lrer3r23JvxOnrtE8nI69XLGSr+sRERz9YnUptnU\n\ diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp index 07a4d6d0bb..bdc0f937d0 100644 --- a/Telegram/SourceFiles/dropdown.cpp +++ b/Telegram/SourceFiles/dropdown.cpp @@ -2635,7 +2635,7 @@ void MentionsDropdown::updateFiltered(bool toDown) { UserData *user = i.key(); if (user->username.isEmpty()) continue; if (_filter.size() > 1 && (!user->username.startsWith(_filter.midRef(1), Qt::CaseInsensitive) || user->username.size() + 1 == _filter.size())) continue; - ordered.insertMulti(App::onlineForSort(user->onlineTill, now), user); + ordered.insertMulti(App::onlineForSort(user, now), user); } } for (MentionRows::const_iterator i = _chat->lastAuthors.cbegin(), e = _chat->lastAuthors.cend(); i != e; ++i) { @@ -2644,7 +2644,7 @@ void MentionsDropdown::updateFiltered(bool toDown) { if (_filter.size() > 1 && (!user->username.startsWith(_filter.midRef(1), Qt::CaseInsensitive) || user->username.size() + 1 == _filter.size())) continue; rows.push_back(user); if (!ordered.isEmpty()) { - ordered.remove(App::onlineForSort(user->onlineTill, now), user); + ordered.remove(App::onlineForSort(user, now), user); } } if (!ordered.isEmpty()) { diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 04f498f59a..07386ac81a 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -460,6 +460,8 @@ void Histories::regTyping(History *history, UserData *user) { uint64 ms = getms(true); history->typing[user] = ms + 6000; + user->madeAction(); + TypingHistories::const_iterator i = typing.find(history); if (i == typing.cend()) { typing.insert(history, ms); @@ -802,10 +804,7 @@ void History::newItemAdded(HistoryItem *item) { App::checkImageCacheSize(); if (item->from()) { unregTyping(item->from()); - if (item->from()->onlineTill < 0) { - item->from()->onlineTill = -unixtime() - HiddenIsOnlineAfterMessage; // pseudo-online - if (App::main()) App::main()->peerUpdated(item->from()); - } + item->from()->madeAction(); } if (item->out()) { if (unreadBar) unreadBar->destroy(); @@ -3083,7 +3082,6 @@ void HistorySticker::updateFrom(const MTPMessageMedia &media) { if (!data->data.isEmpty()) { Local::writeStickerImage(mediaKey(mtpToLocationType(mtpc_inputDocumentFileLocation), data->dc, data->id), data->data); } - if (App::main()) App::main()->incrementSticker(data); } } @@ -3417,11 +3415,13 @@ void HistoryWebPage::initDimensions(const HistoryItem *parent) { } QString title(data->title.isEmpty() ? data->author : data->title); if (!title.isEmpty()) { - _title.setText(st::webPageTitleFont, textClean(title), _webpageTitleOptions); + title = textClean(title); + if (!_asArticle && !data->photo && data->description.isEmpty()) title += textcmdSkipBlock(parent->timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y()); + _title.setText(st::webPageTitleFont, title, _webpageTitleOptions); if (_asArticle) { _maxw = qMax(_maxw, int32(st::webPageLeft + _title.maxWidth() + st::webPagePhotoDelta + st::webPagePhotoSize)); } else { - _maxw = qMax(_maxw, int32(st::webPageLeft + _title.maxWidth() + (data->photo ? parent->timeWidth(true) : 0))); + _maxw = qMax(_maxw, int32(st::webPageLeft + _title.maxWidth())); _minh += qMin(_title.minHeight(), 2 * st::webPageTitleFont->height); } } diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 9c580cfe5b..3ae597ea63 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -2779,14 +2779,15 @@ void HistoryWidget::shareContact(const PeerId &peer, const QString &phone, const h->loadAround(0); PeerData *p = App::peer(peer); - int32 flags = (p->input.type() == mtpc_inputPeerSelf) ? 0 : (MTPDmessage_flag_unread | MTPDmessage_flag_out); // unread, out + int32 flags = newMessageFlags(p); // unread, out + int32 sendFlags = 0; if (replyTo) { flags |= MTPDmessage::flag_reply_to_msg_id; sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id; } - h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(peer), MTPint(), MTPint(), MTP_int(_replyToId), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname), MTP_int(userId)))); - h->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), p->input, MTP_int(replyTo), MTP_inputMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname)), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(peer), MTPint(), MTPint(), MTP_int(_replyToId), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname), MTP_int(userId)), MTPnullMarkup)); + h->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), p->input, MTP_int(replyTo), MTP_inputMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname)), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); App::historyRegRandom(randomId, newId); @@ -3287,13 +3288,13 @@ void HistoryWidget::updateOnlineDisplayTimer() { if (chat->participants.isEmpty()) return; for (ChatData::Participants::const_iterator i = chat->participants.cbegin(), e = chat->participants.cend(); i != e; ++i) { - int32 onlineWillChangeIn = App::onlineWillChangeIn(i.key()->onlineTill, t); + int32 onlineWillChangeIn = App::onlineWillChangeIn(i.key(), t); if (onlineWillChangeIn < minIn) { minIn = onlineWillChangeIn; } } } else { - minIn = App::onlineWillChangeIn(histPeer->asUser()->onlineTill, t); + minIn = App::onlineWillChangeIn(histPeer->asUser(), t); } App::main()->updateOnlineDisplayIn(minIn * 1000); } @@ -3458,21 +3459,15 @@ void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) { App::uploader()->uploadMedia(newId, img); History *h = App::history(img.peer); + h->loadAround(0); + int32 flags = newMessageFlags(h->peer); // unread, out + if (img.replyTo) flags |= MTPDmessage::flag_reply_to_msg_id; if (img.type == ToPreparePhoto) { - h->loadAround(0); - int32 flags = (h->peer->input.type() == mtpc_inputPeerSelf) ? 0 : (MTPDmessage_flag_unread | MTPDmessage_flag_out); // unread, out - if (img.replyTo) flags |= MTPDmessage::flag_reply_to_msg_id; - h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaPhoto(img.photo, MTP_string("")))); + h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaPhoto(img.photo, MTP_string("")), MTPnullMarkup)); } else if (img.type == ToPrepareDocument) { - h->loadAround(0); - int32 flags = (h->peer->input.type() == mtpc_inputPeerSelf) ? 0 : (MTPDmessage_flag_unread | MTPDmessage_flag_out); // unread, out - if (img.replyTo) flags |= MTPDmessage::flag_reply_to_msg_id; - h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(img.document))); + h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(img.document), MTPnullMarkup)); } else if (img.type == ToPrepareAudio) { - h->loadAround(0); - int32 flags = (h->peer->input.type() == mtpc_inputPeerSelf) ? 0 : (MTPDmessage_flag_unread | MTPDmessage_flag_out | MTPDmessage_flag_media_unread); // unread, out - if (img.replyTo) flags |= MTPDmessage::flag_reply_to_msg_id; - h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaAudio(img.audio))); + h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaAudio(img.audio), MTPnullMarkup)); } if (hist && histPeer && img.peer == histPeer->id) { @@ -3503,7 +3498,7 @@ void HistoryWidget::onPhotoUploaded(MsgId newId, const MTPInputFile &file) { if (replyTo) { sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id; } - hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedPhoto(file, MTP_string("")), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::sendPhotoFailed, randomId), 0, 0, hist->sendRequestId); + hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedPhoto(file, MTP_string("")), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::sendPhotoFailed, randomId), 0, 0, hist->sendRequestId); } } @@ -3543,7 +3538,7 @@ void HistoryWidget::onDocumentUploaded(MsgId newId, const MTPInputFile &file) { if (replyTo) { sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id; } - hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedDocument(file, MTP_string(document->mime), _composeDocumentAttributes(document)), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedDocument(file, MTP_string(document->mime), _composeDocumentAttributes(document)), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); } } } @@ -3569,7 +3564,7 @@ void HistoryWidget::onThumbDocumentUploaded(MsgId newId, const MTPInputFile &fil if (replyTo) { sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id; } - hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedThumbDocument(file, thumb, MTP_string(document->mime), _composeDocumentAttributes(document)), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedThumbDocument(file, thumb, MTP_string(document->mime), _composeDocumentAttributes(document)), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); } } } @@ -3593,7 +3588,7 @@ void HistoryWidget::onAudioUploaded(MsgId newId, const MTPInputFile &file) { if (replyTo) { sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id; } - hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedAudio(file, MTP_int(audio->duration), MTP_string(audio->mime)), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedAudio(file, MTP_int(audio->duration), MTP_string(audio->mime)), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); } } } @@ -3895,7 +3890,7 @@ void HistoryWidget::onStickerSend(DocumentData *sticker) { hist->loadAround(0); bool out = (histPeer->input.type() != mtpc_inputPeerSelf), unread = (histPeer->input.type() != mtpc_inputPeerSelf); - int32 flags = (histPeer->input.type() != mtpc_inputPeerSelf) ? (MTPDmessage_flag_out | MTPDmessage_flag_unread) : 0; + int32 flags = newMessageFlags(histPeer); // unread, out int32 sendFlags = 0; if (_replyToId) { flags |= MTPDmessage::flag_reply_to_msg_id; @@ -3903,7 +3898,7 @@ void HistoryWidget::onStickerSend(DocumentData *sticker) { } hist->addToBackDocument(newId, flags, _replyToId, date(MTP_int(unixtime())), MTP::authedId(), sticker); - hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), histPeer->input, MTP_int(_replyToId), MTP_inputMediaDocument(MTP_inputDocument(MTP_long(sticker->id), MTP_long(sticker->access))), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), histPeer->input, MTP_int(_replyToId), MTP_inputMediaDocument(MTP_inputDocument(MTP_long(sticker->id), MTP_long(sticker->access))), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); App::main()->finishForwarding(hist); cancelReply(); diff --git a/Telegram/SourceFiles/intro/introcode.cpp b/Telegram/SourceFiles/intro/introcode.cpp index f34631f9c9..b9dc0bf57e 100644 --- a/Telegram/SourceFiles/intro/introcode.cpp +++ b/Telegram/SourceFiles/intro/introcode.cpp @@ -202,7 +202,7 @@ void IntroCode::codeSubmitDone(const MTPauth_Authorization &result) { stopCheck(); code.setDisabled(false); const MTPDauth_authorization &d(result.c_auth_authorization()); - if (d.vuser.type() != mtpc_userSelf) { // wtf? + if (d.vuser.type() != mtpc_user || !(d.vuser.c_user().vflags.v & MTPDuser_flag_self)) { // wtf? showError(lang(lng_server_error)); return; } diff --git a/Telegram/SourceFiles/intro/intropwdcheck.cpp b/Telegram/SourceFiles/intro/intropwdcheck.cpp index e24b4527e7..4dc59c8b68 100644 --- a/Telegram/SourceFiles/intro/intropwdcheck.cpp +++ b/Telegram/SourceFiles/intro/intropwdcheck.cpp @@ -181,7 +181,7 @@ void IntroPwdCheck::pwdSubmitDone(bool recover, const MTPauth_Authorization &res _pwdField.setDisabled(false); _codeField.setDisabled(false); const MTPDauth_authorization &d(result.c_auth_authorization()); - if (d.vuser.type() != mtpc_userSelf) { // wtf? + if (d.vuser.type() != mtpc_user || !(d.vuser.c_user().vflags.v & MTPDuser_flag_self)) { // wtf? showError(lang(lng_server_error)); return; } diff --git a/Telegram/SourceFiles/intro/introsignup.cpp b/Telegram/SourceFiles/intro/introsignup.cpp index bfe4ad2f99..d299773623 100644 --- a/Telegram/SourceFiles/intro/introsignup.cpp +++ b/Telegram/SourceFiles/intro/introsignup.cpp @@ -216,7 +216,7 @@ void IntroSignup::nameSubmitDone(const MTPauth_Authorization &result) { first.setDisabled(false); last.setDisabled(false); const MTPDauth_authorization &d(result.c_auth_authorization()); - if (d.vuser.type() != mtpc_userSelf) { // wtf? + if (d.vuser.type() != mtpc_user || !(d.vuser.c_user().vflags.v & MTPDuser_flag_self)) { // wtf? showError(lang(lng_server_error)); return; } diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp index e99c617ca7..9745126ba1 100644 --- a/Telegram/SourceFiles/localstorage.cpp +++ b/Telegram/SourceFiles/localstorage.cpp @@ -609,13 +609,22 @@ namespace { mtpDcOptions *_dcOpts = 0; bool _readSetting(quint32 blockId, QDataStream &stream, int version) { switch (blockId) { - case dbiDcOption: { + case dbiDcOptionOld: { quint32 dcId, port; QString host, ip; stream >> dcId >> host >> ip >> port; if (!_checkStreamStatus(stream)) return false; - if (_dcOpts) _dcOpts->insert(dcId, mtpDcOption(dcId, host.toUtf8().constData(), ip.toUtf8().constData(), port)); + if (_dcOpts) _dcOpts->insert(dcId, mtpDcOption(dcId, 0, ip.toUtf8().constData(), port)); + } break; + + case dbiDcOption: { + quint32 dcIdWithShift, flags, port; + QString ip; + stream >> dcIdWithShift >> flags >> ip >> port; + if (!_checkStreamStatus(stream)) return false; + + if (_dcOpts) _dcOpts->insert(dcIdWithShift, mtpDcOption(dcIdWithShift % _mtp_internal::dcShift, flags, ip.toUtf8().constData(), port)); } break; case dbiMaxGroupCount: { @@ -1723,9 +1732,16 @@ namespace Local { if (dcOpts.isEmpty()) { const BuiltInDc *bdcs = builtInDcs(); for (int i = 0, l = builtInDcsCount(); i < l; ++i) { - dcOpts.insert(bdcs[i].id, mtpDcOption(bdcs[i].id, "", bdcs[i].ip, bdcs[i].port)); + dcOpts.insert(bdcs[i].id, mtpDcOption(bdcs[i].id, 0, bdcs[i].ip, bdcs[i].port)); DEBUG_LOG(("MTP Info: adding built in DC %1 connect option: %2:%3").arg(bdcs[i].id).arg(bdcs[i].ip).arg(bdcs[i].port)); } + + const BuiltInDc *bdcsipv6 = builtInDcsIPv6(); + for (int i = 0, l = builtInDcsCountIPv6(); i < l; ++i) { + int32 flags = MTPDdcOption_flag_ipv6, idWithShift = bdcsipv6[i].id + (flags * _mtp_internal::dcShift); + dcOpts.insert(idWithShift, mtpDcOption(bdcsipv6[i].id, flags, bdcsipv6[i].ip, bdcsipv6[i].port)); + DEBUG_LOG(("MTP Info: adding built in DC %1 IPv6 connect option: %2:%3").arg(bdcsipv6[i].id).arg(bdcsipv6[i].ip).arg(bdcsipv6[i].port)); + } } { QWriteLocker lock(MTP::dcOptionsMutex()); @@ -1759,10 +1775,16 @@ namespace Local { if (dcOpts.isEmpty()) { const BuiltInDc *bdcs = builtInDcs(); for (int i = 0, l = builtInDcsCount(); i < l; ++i) { - dcOpts.insert(bdcs[i].id, mtpDcOption(bdcs[i].id, "", bdcs[i].ip, bdcs[i].port)); + dcOpts.insert(bdcs[i].id, mtpDcOption(bdcs[i].id, 0, bdcs[i].ip, bdcs[i].port)); DEBUG_LOG(("MTP Info: adding built in DC %1 connect option: %2:%3").arg(bdcs[i].id).arg(bdcs[i].ip).arg(bdcs[i].port)); } + const BuiltInDc *bdcsipv6 = builtInDcsIPv6(); + for (int i = 0, l = builtInDcsCountIPv6(); i < l; ++i) { + dcOpts.insert(bdcsipv6[i].id + (MTPDdcOption_flag_ipv6 * _mtp_internal::dcShift), mtpDcOption(bdcsipv6[i].id, MTPDdcOption_flag_ipv6, bdcsipv6[i].ip, bdcsipv6[i].port)); + DEBUG_LOG(("MTP Info: adding built in DC %1 IPv6 connect option: %2:%3").arg(bdcsipv6[i].id).arg(bdcsipv6[i].ip).arg(bdcsipv6[i].port)); + } + QWriteLocker lock(MTP::dcOptionsMutex()); cSetDcOptions(dcOpts); } @@ -1770,7 +1792,7 @@ namespace Local { quint32 size = 10 * (sizeof(quint32) + sizeof(qint32)); for (mtpDcOptions::const_iterator i = dcOpts.cbegin(), e = dcOpts.cend(); i != e; ++i) { size += sizeof(quint32) + sizeof(quint32) + sizeof(quint32); - size += _stringSize(QString::fromUtf8(i->host.data(), i->host.size())) + _stringSize(QString::fromUtf8(i->ip.data(), i->ip.size())); + size += sizeof(quint32) + _stringSize(QString::fromUtf8(i->ip.data(), i->ip.size())); } size += sizeof(quint32) + _stringSize(cLangFile()); @@ -1794,8 +1816,8 @@ namespace Local { data.stream << quint32(dbiScale) << qint32(cConfigScale()); data.stream << quint32(dbiLang) << qint32(cLang()); for (mtpDcOptions::const_iterator i = dcOpts.cbegin(), e = dcOpts.cend(); i != e; ++i) { - data.stream << quint32(dbiDcOption) << quint32(i->id); - data.stream << QString::fromUtf8(i->host.data(), i->host.size()) << QString::fromUtf8(i->ip.data(), i->ip.size()); + data.stream << quint32(dbiDcOption) << quint32(i.key()); + data.stream << quint32(i->flags) << QString::fromUtf8(i->ip.data(), i->ip.size()); data.stream << quint32(i->port); } data.stream << quint32(dbiLangFile) << cLangFile(); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 17592dba28..9c1f02d00f 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -494,9 +494,13 @@ void MainWidget::finishForwarding(History *hist) { if (_toForward.size() < 2) { uint64 randomId = MTP::nonce(); MsgId newId = clientMsgId(); - hist->addToBackForwarded(newId, static_cast(_toForward.cbegin().value())); + HistoryMessage *msg = static_cast(_toForward.cbegin().value()); + hist->addToBackForwarded(newId, msg); App::historyRegRandom(randomId, newId); hist->sendRequestId = MTP::send(MTPmessages_ForwardMessage(hist->peer->input, MTP_int(_toForward.cbegin().key()), MTP_long(randomId)), rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + if (HistorySticker *sticker = dynamic_cast(msg->getMedia())) { + App::main()->incrementSticker(sticker->document()); + } } else { QVector ids; QVector randomIds; @@ -940,7 +944,7 @@ void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId repl App::historyRegRandom(randomId, newId); MTPstring msgText(MTP_string(sendingText)); - int32 flags = (hist->peer->input.type() == mtpc_inputPeerSelf) ? 0 : (MTPDmessage_flag_unread | MTPDmessage_flag_out); + int32 flags = newMessageFlags(hist->peer); // unread, out int32 sendFlags = 0; if (replyTo) { flags |= MTPDmessage::flag_reply_to_msg_id; @@ -953,8 +957,8 @@ void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId repl WebPageData *page = App::webPage(webPageId); media = MTP_messageMediaWebPage(MTP_webPagePending(MTP_long(page->id), MTP_int(page->pendingTill))); } - hist->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(hist->peer->id), MTPint(), MTPint(), MTP_int(replyTo), MTP_int(unixtime()), msgText, media)); - hist->sendRequestId = MTP::send(MTPmessages_SendMessage(MTP_int(sendFlags), hist->peer->input, MTP_int(replyTo), msgText, MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentDataReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + hist->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(hist->peer->id), MTPint(), MTPint(), MTP_int(replyTo), MTP_int(unixtime()), msgText, media, MTPnullMarkup)); + hist->sendRequestId = MTP::send(MTPmessages_SendMessage(MTP_int(sendFlags), hist->peer->input, MTP_int(replyTo), msgText, MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentDataReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); } finishForwarding(hist); @@ -1575,7 +1579,7 @@ void MainWidget::serviceNotification(const QString &msg, const MTPMessageMedia & QString sendingText, leftText = msg; HistoryItem *item = 0; while (textSplit(sendingText, leftText, MaxMessageSize)) { - item = App::histories().addToBack(MTP_message(MTP_int(flags), MTP_int(clientMsgId()), MTP_int(ServiceUserId), MTP_peerUser(MTP_int(MTP::authedId())), MTPint(), MTPint(), MTPint(), MTP_int(unixtime()), MTP_string(sendingText), media), unread ? 1 : 2); + item = App::histories().addToBack(MTP_message(MTP_int(flags), MTP_int(clientMsgId()), MTP_int(ServiceUserId), MTP_peerUser(MTP_int(MTP::authedId())), MTPint(), MTPint(), MTPint(), MTP_int(unixtime()), MTP_string(sendingText), media, MTPnullMarkup), unread ? 1 : 2); } if (item) { history.peerMessagesUpdated(item->history()->peer->id); @@ -2491,7 +2495,7 @@ void MainWidget::mtpPing() { } void MainWidget::start(const MTPUser &user) { - int32 uid = user.c_userSelf().vid.v; + int32 uid = user.c_user().vid.v; if (MTP::authedId() != uid) { MTP::authed(uid); Local::writeMtpData(); @@ -2666,7 +2670,7 @@ bool MainWidget::inviteImportFail(const RPCError &error) { void MainWidget::startFull(const MTPVector &users) { const QVector &v(users.c_vector().v); - if (v.isEmpty() || v[0].type() != mtpc_userSelf) { // wtf?.. + if (v.isEmpty() || v[0].type() != mtpc_user || !(v[0].c_user().vflags.v & MTPDuser_flag_self)) { // wtf?.. return App::logOut(); } start(v[0]); @@ -3054,7 +3058,7 @@ void MainWidget::handleUpdates(const MTPUpdates &updates) { return; } bool out = (d.vflags.v & MTPDmessage_flag_out); - HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, out ? MTP_int(MTP::authedId()) : d.vuser_id, MTP_peerUser(out ? d.vuser_id : MTP_int(MTP::authedId())), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty())); + HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, out ? MTP_int(MTP::authedId()) : d.vuser_id, MTP_peerUser(out ? d.vuser_id : MTP_int(MTP::authedId())), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup)); if (item) { history.peerMessagesUpdated(item->history()->peer->id); } @@ -3074,7 +3078,7 @@ void MainWidget::handleUpdates(const MTPUpdates &updates) { _byPtsUpdates.insert(ptsKey(SkippedUpdates), updates); return; } - HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, d.vfrom_id, MTP_peerChat(d.vchat_id), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty())); + HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, d.vfrom_id, MTP_peerChat(d.vchat_id), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup)); if (item) { history.peerMessagesUpdated(item->history()->peer->id); } diff --git a/Telegram/SourceFiles/mtproto/mtpConnection.cpp b/Telegram/SourceFiles/mtproto/mtpConnection.cpp index 0597e48434..6b34c27801 100644 --- a/Telegram/SourceFiles/mtproto/mtpConnection.cpp +++ b/Telegram/SourceFiles/mtproto/mtpConnection.cpp @@ -743,8 +743,9 @@ void MTPautoConnection::disconnectFromServer() { status = FinishedWork; } -void MTPautoConnection::connectToServer(const QString &addr, int32 port) { - address = QUrl(qsl("http://%1:%2/api").arg(addr).arg(80));//not port - always 80 port for http transport +void MTPautoConnection::connectToServer(const QString &addr, int32 port, int32 flags) { + address = QUrl(((flags & MTPDdcOption_flag_ipv6) ? qsl("http://[%1]:%2/api") : qsl("http://%1:%2/api")).arg(addr).arg(80));//not p - always 80 port for http transport + TCP_LOG(("HTTP Info: address is %1").arg(address.toDisplayString())); connect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*))); _addr = addr; @@ -943,7 +944,7 @@ void MTPtcpConnection::disconnectFromServer() { sock.close(); } -void MTPtcpConnection::connectToServer(const QString &addr, int32 port) { +void MTPtcpConnection::connectToServer(const QString &addr, int32 port, int32 flags) { connect(&sock, SIGNAL(readyRead()), this, SLOT(socketRead())); sock.connectToHost(QHostAddress(addr), port); } @@ -1013,8 +1014,9 @@ void MTPhttpConnection::disconnectFromServer() { address = QUrl(); } -void MTPhttpConnection::connectToServer(const QString &addr, int32 p) { - address = QUrl(qsl("http://%1:%2/api").arg(addr).arg(80));//not p - always 80 port for http transport +void MTPhttpConnection::connectToServer(const QString &addr, int32 p, int32 flags) { + address = QUrl(((flags & MTPDdcOption_flag_ipv6) ? qsl("http://[%1]:%2/api") : qsl("http://%1:%2/api")).arg(addr).arg(80));//not p - always 80 port for http transport + TCP_LOG(("HTTP Info: address is %1").arg(address.toDisplayString())); connect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*))); emit connected(); } @@ -1062,19 +1064,30 @@ QString MTPhttpConnection::transport() const { return qsl("HTTP"); } -void MTProtoConnectionPrivate::createConn() { - if (conn) { - conn->deleteLater(); +void MTProtoConnectionPrivate::createConn(bool createIPv4, bool createIPv6) { + destroyConn(); + if (createIPv4) { + if (cConnectionType() == dbictAuto) { + _conn4 = new MTPautoConnection(thread()); + } else if (cConnectionType() == dbictTcpProxy) { + _conn4 = new MTPtcpConnection(thread()); + } else { + _conn4 = new MTPhttpConnection(thread()); + } + connect(_conn4, SIGNAL(error(bool)), this, SLOT(onError4(bool))); + connect(_conn4, SIGNAL(receivedSome()), this, SLOT(onReceivedSome())); } - if (cConnectionType() == dbictAuto) { - conn = new MTPautoConnection(thread()); - } else if (cConnectionType() == dbictTcpProxy) { - conn = new MTPtcpConnection(thread()); - } else { - conn = new MTPhttpConnection(thread()); + if (createIPv6) { + if (cConnectionType() == dbictAuto) { + _conn6 = new MTPautoConnection(thread()); + } else if (cConnectionType() == dbictTcpProxy) { + _conn6 = new MTPtcpConnection(thread()); + } else { + _conn6 = new MTPhttpConnection(thread()); + } + connect(_conn6, SIGNAL(error(bool)), this, SLOT(onError6(bool))); + connect(_conn6, SIGNAL(receivedSome()), this, SLOT(onReceivedSome())); } - connect(conn, SIGNAL(error(bool)), this, SLOT(onError(bool))); - connect(conn, SIGNAL(receivedSome()), this, SLOT(onReceivedSome())); firstSentAt = 0; if (oldConnection) { oldConnection = false; @@ -1083,17 +1096,35 @@ void MTProtoConnectionPrivate::createConn() { oldConnectionTimer.start(MTPConnectionOldTimeout); } +void MTProtoConnectionPrivate::destroyConn(MTPabstractConnection **conn) { + if (conn) { + if (*conn) { + disconnect(*conn, SIGNAL(disconnected()), 0, 0); + disconnect(*conn, SIGNAL(receivedData()), 0, 0); + disconnect(*conn, SIGNAL(receivedSome()), 0, 0); + + (*conn)->disconnectFromServer(); + (*conn)->deleteLater(); + *conn = 0; + } + } else { + destroyConn(&_conn4); + destroyConn(&_conn6); + _conn = 0; + } +} + MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConnection *owner, MTPSessionData *data, uint32 _dc) : QObject(0) , _state(MTProtoConnection::Disconnected) , _needSessionReset(false) , dc(_dc) , _owner(owner) - , conn(0) + , _conn(0), _conn4(0), _conn6(0) , retryTimeout(1) , oldConnection(true) - , receiveDelay(MTPMinReceiveDelay) - , connectDelay(MTPMinConnectDelay) + , _waitForReceived(MTPMinReceiveDelay) + , _waitForConnected(MTPMinConnectDelay) , firstSentAt(-1) , _pingId(0) , _pingIdToSend(0) @@ -1107,14 +1138,13 @@ MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConne , authKeyStrings(0) { oldConnectionTimer.moveToThread(thread); - cantConnectTimer.moveToThread(thread); - connCheckTimer.moveToThread(thread); + _waitForConnectedTimer.moveToThread(thread); + _waitForReceivedTimer.moveToThread(thread); + _waitForIPv4Timer.moveToThread(thread); _pingSender.moveToThread(thread); retryTimer.moveToThread(thread); moveToThread(thread); -// createConn(); - if (!dc) { QReadLocker lock(mtpDcOptionsMutex()); const mtpDcOptions &options(cDcOptions()); @@ -1131,8 +1161,9 @@ MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConne connect(thread, SIGNAL(finished()), this, SLOT(doFinish())); connect(&retryTimer, SIGNAL(timeout()), this, SLOT(retryByTimer())); - connect(&connCheckTimer, SIGNAL(timeout()), this, SLOT(onBadConnection())); - connect(&cantConnectTimer, SIGNAL(timeout()), this, SLOT(onCantConnect())); + connect(&_waitForConnectedTimer, SIGNAL(timeout()), this, SLOT(onWaitConnectedFailed())); + connect(&_waitForReceivedTimer, SIGNAL(timeout()), this, SLOT(onWaitReceivedFailed())); + connect(&_waitForIPv4Timer, SIGNAL(timeout()), this, SLOT(onWaitIPv4Failed())); connect(&oldConnectionTimer, SIGNAL(timeout()), this, SLOT(onOldConnection())); connect(&_pingSender, SIGNAL(timeout()), this, SLOT(onPingSender())); connect(sessionData->owner(), SIGNAL(authKeyCreated()), this, SLOT(updateAuthKey()), Qt::QueuedConnection); @@ -1183,10 +1214,10 @@ int32 MTProtoConnectionPrivate::getState() const { } QString MTProtoConnectionPrivate::transport() const { - if (!conn || _state < 0) { + if ((!_conn4 && !_conn6) || _state < 0) { return QString(); } - return conn->transport(); + return (_conn4 ? _conn4 : _conn6)->transport(); } bool MTProtoConnectionPrivate::setState(int32 state, int32 ifState) { @@ -1421,7 +1452,7 @@ mtpMsgId MTProtoConnectionPrivate::placeToContainer(mtpRequest &toSendRequest, m void MTProtoConnectionPrivate::tryToSend() { QReadLocker lockFinished(&sessionDataMutex); - if (!sessionData || !conn) { + if (!sessionData || !_conn) { return; } @@ -1513,7 +1544,7 @@ void MTProtoConnectionPrivate::tryToSend() { stateRequest->msDate = getms(true); // > 0 - can send without container stateRequest->requestId = reqid();// add to haveSent / wereAcked maps, but don't add to requestMap } - if (conn->usingHttpWait()) { + if (_conn->usingHttpWait()) { MTPHttpWait req(MTP_http_wait(MTP_int(100), MTP_int(30), MTP_int(25000))); httpWaitRequest = mtpRequestData::prepare(req.innerLength() >> 2); @@ -1734,47 +1765,63 @@ void MTProtoConnectionPrivate::restartNow() { } void MTProtoConnectionPrivate::socketStart(bool afterConfig) { - if (!conn) createConn(); - retryTimer.stop(); - cantConnectTimer.stop(); - - if (conn->isConnected()) { - onConnected(); - return; - } - setState(MTProtoConnection::Connecting); - _pingId = _pingMsgId = _pingIdToSend = _pingSendAt = 0; - _pingSender.stop(); - - std::string ip; - uint32 port = 0; + int32 flags4 = 0, flags6 = 0; + std::string ip4, ip6; + uint32 port4 = 0, port6 = 0; { QReadLocker lock(mtpDcOptionsMutex()); const mtpDcOptions &options(cDcOptions()); - mtpDcOptions::const_iterator dcIndex = options.constFind(dc % _mtp_internal::dcShift); - DEBUG_LOG(("MTP Info: connecting to DC %1..").arg(dc)); - if (dcIndex != options.cend()) { - ip = dcIndex->ip; - port = dcIndex->port; + mtpDcOptions::const_iterator dcIndex4 = options.constFind(dc % _mtp_internal::dcShift); + if (dcIndex4 != options.cend()) { + ip4 = dcIndex4->ip; + flags4 = dcIndex4->flags; + port4 = dcIndex4->port; + } + mtpDcOptions::const_iterator dcIndex6 = options.constFind((dc % _mtp_internal::dcShift) + (_mtp_internal::dcShift * MTPDdcOption_flag_ipv6)); + if (dcIndex6 != options.cend()) { + ip6 = dcIndex6->ip; + flags6 = dcIndex6->flags; + port6 = dcIndex6->port; } } - if (!port || ip.empty()) { + bool noIPv4 = (!port4 || ip4.empty()), noIPv6 = (!port6 || ip6.empty()); + if (noIPv4 && noIPv6) { if (afterConfig) { - LOG(("MTP Error: DC %1 options not found right after config load!").arg(dc)); + if (noIPv4) LOG(("MTP Error: DC %1 options for IPv4 not found right after config load!").arg(dc)); + if (noIPv6) LOG(("MTP Error: DC %1 options for IPv6 not found right after config load!").arg(dc)); return restart(); } - DEBUG_LOG(("MTP Info: DC %1 options not found, waiting for config").arg(dc)); + if (noIPv4) DEBUG_LOG(("MTP Info: DC %1 options for IPv4 not found, waiting for config").arg(dc)); + if (noIPv6) DEBUG_LOG(("MTP Info: DC %1 options for IPv6 not found, waiting for config").arg(dc)); connect(mtpConfigLoader(), SIGNAL(loaded()), this, SLOT(onConfigLoaded())); mtpConfigLoader()->load(); return; } - DEBUG_LOG(("MTP Info: socket connection to %1:%2..").arg(ip.c_str()).arg(port)); - connect(conn, SIGNAL(connected()), this, SLOT(onConnected())); - connect(conn, SIGNAL(disconnected()), this, SLOT(restart())); + if (afterConfig && (_conn4 || _conn6)) return; - cantConnectTimer.start(connectDelay); - conn->connectToServer(ip.c_str(), port); + createConn(!noIPv4, !noIPv6); + retryTimer.stop(); + _waitForConnectedTimer.stop(); + + setState(MTProtoConnection::Connecting); + _pingId = _pingMsgId = _pingIdToSend = _pingSendAt = 0; + _pingSender.stop(); + + if (!noIPv4) DEBUG_LOG(("MTP Info: creating IPv4 connection to %1:%2..").arg(ip4.c_str()).arg(port4)); + if (!noIPv6) DEBUG_LOG(("MTP Info: creating IPv6 connection to [%1]:%2..").arg(ip6.c_str()).arg(port6)); + + _waitForConnectedTimer.start(_waitForConnected); + if (_conn4) { + connect(_conn4, SIGNAL(connected()), this, SLOT(onConnected4())); + connect(_conn4, SIGNAL(disconnected()), this, SLOT(onDisconnected4())); + _conn4->connectToServer(ip4.c_str(), port4, flags4); + } + if (_conn6) { + connect(_conn6, SIGNAL(connected()), this, SLOT(onConnected6())); + connect(_conn6, SIGNAL(disconnected()), this, SLOT(onDisconnected6())); + _conn6->connectToServer(ip6.c_str(), port6, flags6); + } } void MTProtoConnectionPrivate::restart(bool maybeBadKey) { @@ -1783,8 +1830,8 @@ void MTProtoConnectionPrivate::restart(bool maybeBadKey) { DEBUG_LOG(("MTP Info: restarting MTProtoConnection, maybe bad key = %1").arg(logBool(maybeBadKey))); - connCheckTimer.stop(); - cantConnectTimer.stop(); + _waitForReceivedTimer.stop(); + _waitForConnectedTimer.stop(); mtpAuthKeyPtr key(sessionData->getKey()); if (key) { @@ -1812,12 +1859,12 @@ void MTProtoConnectionPrivate::restart(bool maybeBadKey) { } void MTProtoConnectionPrivate::onSentSome(uint64 size) { - if (!connCheckTimer.isActive()) { - uint64 remain = receiveDelay; + if (!_waitForReceivedTimer.isActive()) { + uint64 remain = _waitForReceived; if (!oldConnection) { - uint64 remainBySize = size * receiveDelay / 8192; // 8kb / sec, so 512 kb give 64 sec + uint64 remainBySize = size * _waitForReceived / 8192; // 8kb / sec, so 512 kb give 64 sec remain = snap(remainBySize, remain, uint64(MTPMaxReceiveDelay)); - if (remain != receiveDelay) { + if (remain != _waitForReceived) { DEBUG_LOG(("Checking connect for request with size %1 bytes, delay will be %2").arg(size).arg(remain)); } } @@ -1826,7 +1873,7 @@ void MTProtoConnectionPrivate::onSentSome(uint64 size) { } else if (dc >= MTP::dld[0] && dc < MTP::dld[MTPDownloadSessionsCount - 1] + _mtp_internal::dcShift) { remain *= MTPDownloadSessionsCount; } - connCheckTimer.start(remain); + _waitForReceivedTimer.start(remain); } if (!firstSentAt) firstSentAt = getms(true); } @@ -1837,20 +1884,20 @@ void MTProtoConnectionPrivate::onReceivedSome() { DEBUG_LOG(("This connection marked as not old!")); } oldConnectionTimer.start(MTPConnectionOldTimeout); - connCheckTimer.stop(); + _waitForReceivedTimer.stop(); if (firstSentAt > 0) { int32 ms = getms(true) - firstSentAt; - DEBUG_LOG(("MTP Info: response in %1ms, receiveDelay: %2ms").arg(ms).arg(receiveDelay)); + DEBUG_LOG(("MTP Info: response in %1ms, _waitForReceived: %2ms").arg(ms).arg(_waitForReceived)); - if (ms > 0 && ms * 2 < int32(receiveDelay)) receiveDelay = qMax(ms * 2, int32(MTPMinReceiveDelay)); + if (ms > 0 && ms * 2 < int32(_waitForReceived)) _waitForReceived = qMax(ms * 2, int32(MTPMinReceiveDelay)); firstSentAt = -1; } } void MTProtoConnectionPrivate::onOldConnection() { oldConnection = true; - receiveDelay = MTPMinReceiveDelay; - DEBUG_LOG(("This connection marked as old! delay now %1ms").arg(receiveDelay)); + _waitForReceived = MTPMinReceiveDelay; + DEBUG_LOG(("This connection marked as old! _waitForReceived now %1ms").arg(_waitForReceived)); } void MTProtoConnectionPrivate::onPingSender() { @@ -1874,14 +1921,14 @@ void MTProtoConnectionPrivate::onPingSendForce() { } } -void MTProtoConnectionPrivate::onBadConnection() { +void MTProtoConnectionPrivate::onWaitReceivedFailed() { if (cConnectionType() != dbictAuto && cConnectionType() != dbictTcpProxy) { return; } - DEBUG_LOG(("MTP Info: bad connection, delay: %1ms").arg(receiveDelay)); - if (receiveDelay < MTPMaxReceiveDelay) { - receiveDelay *= 2; + DEBUG_LOG(("MTP Info: bad connection, _waitForReceived: %1ms").arg(_waitForReceived)); + if (_waitForReceived < MTPMaxReceiveDelay) { + _waitForReceived *= 2; } doDisconnect(); restarted = true; @@ -1891,9 +1938,9 @@ void MTProtoConnectionPrivate::onBadConnection() { QTimer::singleShot(0, this, SLOT(socketStart())); } -void MTProtoConnectionPrivate::onCantConnect() { - DEBUG_LOG(("MTP Info: can't connect in %1ms").arg(connectDelay)); - if (connectDelay < MTPMaxConnectDelay) connectDelay *= 2; +void MTProtoConnectionPrivate::onWaitConnectedFailed() { + DEBUG_LOG(("MTP Info: can't connect in %1ms").arg(_waitForConnected)); + if (_waitForConnected < MTPMaxConnectDelay) _waitForConnected *= 2; doDisconnect(); restarted = true; @@ -1902,16 +1949,21 @@ void MTProtoConnectionPrivate::onCantConnect() { QTimer::singleShot(0, this, SLOT(socketStart())); } -void MTProtoConnectionPrivate::doDisconnect() { - if (conn) { - disconnect(conn, SIGNAL(disconnected()), 0, 0); - disconnect(conn, SIGNAL(receivedData()), 0, 0); - disconnect(conn, SIGNAL(receivedSome()), 0, 0); +void MTProtoConnectionPrivate::onWaitIPv4Failed() { + _conn = _conn6; + destroyConn(&_conn4); + + if (_conn) { + DEBUG_LOG(("MTP Info: can't connect through IPv4, using IPv6 connection.")); - conn->disconnectFromServer(); - conn->deleteLater(); - conn = 0; + updateAuthKey(); + } else { + restart(); } +} + +void MTProtoConnectionPrivate::doDisconnect() { + destroyConn(); unlockKey(); @@ -1946,9 +1998,8 @@ void MTProtoConnectionPrivate::handleReceived() { return restart(); } - - while (conn->received().size()) { - const mtpBuffer &encryptedBuf(conn->received().front()); + while (_conn->received().size()) { + const mtpBuffer &encryptedBuf(_conn->received().front()); uint32 len = encryptedBuf.size(); const mtpPrime *encrypted(encryptedBuf.data()); if (len < 18) { // 2 auth_key_id, 4 msg_key, 2 salt, 2 session, 2 msg_id, 1 seq_no, 1 length, (1 data + 3 padding) min @@ -1976,14 +2027,14 @@ void MTProtoConnectionPrivate::handleReceived() { if (uint32(dataBuffer.size()) < msgLen + 8 * sizeof(mtpPrime) || (msgLen & 0x03)) { LOG(("TCP Error: bad msg_len received %1, data size: %2").arg(msgLen).arg(dataBuffer.size())); TCP_LOG(("TCP Error: bad message %1").arg(mb(encrypted, len * sizeof(mtpPrime)).str())); - conn->received().pop_front(); + _conn->received().pop_front(); return restart(); } uchar sha1Buffer[20]; if (memcmp(&msgKey, hashSha1(data, msgLen + 8 * sizeof(mtpPrime), sha1Buffer) + 1, sizeof(msgKey))) { LOG(("TCP Error: bad SHA1 hash after aesDecrypt in message")); TCP_LOG(("TCP Error: bad message %1").arg(mb(encrypted, len * sizeof(mtpPrime)).str())); - conn->received().pop_front(); + _conn->received().pop_front(); return restart(); } TCP_LOG(("TCP Info: decrypted message %1,%2,%3 is %4 len").arg(msgId).arg(seqNo).arg(logBool(needAck)).arg(msgLen + 8 * sizeof(mtpPrime))); @@ -1992,11 +2043,11 @@ void MTProtoConnectionPrivate::handleReceived() { if (session != serverSession) { LOG(("MTP Error: bad server session received")); TCP_LOG(("MTP Error: bad server session %1 instead of %2 in message received").arg(session).arg(serverSession)); - conn->received().pop_front(); + _conn->received().pop_front(); return restart(); } - conn->received().pop_front(); + _conn->received().pop_front(); int32 serverTime((int32)(msgId >> 32)), clientTime(unixtime()); bool isReply = ((msgId & 0x03) == 1); @@ -2079,6 +2130,7 @@ void MTProtoConnectionPrivate::handleReceived() { _needSessionReset = (res < -1); return restart(); } + retryTimeout = 1; // reset restart() timer if (!sessionData->isCheckedKey()) { DEBUG_LOG(("MTP Info: marked auth key as checked")); @@ -2091,7 +2143,7 @@ void MTProtoConnectionPrivate::handleReceived() { } } } - if (conn->needHttpWait()) { + if (_conn->needHttpWait()) { emit sendHttpWaitAsync(); } } @@ -2588,8 +2640,6 @@ int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mt } } requestsAcked(ids, true); - - retryTimeout = 1; // reset restart() timer } return 1; } @@ -2836,27 +2886,72 @@ void MTProtoConnectionPrivate::resendMany(QVector msgIds, quint64 msCan emit resendManyAsync(msgIds, msCanWait, forceContainer, sendMsgStateInfo); } -void MTProtoConnectionPrivate::onConnected() { - connectDelay = MTPMinConnectDelay; - cantConnectTimer.stop(); +void MTProtoConnectionPrivate::onConnected4() { + _waitForConnected = MTPMinConnectDelay; + _waitForConnectedTimer.stop(); + + _waitForIPv4Timer.stop(); QReadLocker lockFinished(&sessionDataMutex); if (!sessionData) return; - disconnect(conn, SIGNAL(connected()), this, SLOT(onConnected())); - if (!conn->isConnected()) { - LOG(("Connection Error: not connected in onConnected(), state: %1").arg(conn->debugState())); + disconnect(_conn4, SIGNAL(connected()), this, SLOT(onConnected4())); + if (!_conn4->isConnected()) { + LOG(("Connection Error: not connected in onConnected4(), state: %1").arg(_conn4->debugState())); return restart(); } - TCP_LOG(("Connection Info: connection succeed.")); + _conn = _conn4; + destroyConn(&_conn6); + + DEBUG_LOG(("MTP Info: connection through IPv4 succeed.")); updateAuthKey(); } +void MTProtoConnectionPrivate::onConnected6() { + _waitForConnected = MTPMinConnectDelay; + _waitForConnectedTimer.stop(); + + QReadLocker lockFinished(&sessionDataMutex); + if (!sessionData) return; + + disconnect(_conn6, SIGNAL(connected()), this, SLOT(onConnected())); + if (!_conn6->isConnected()) { + LOG(("Connection Error: not connected in onConnected(), state: %1").arg(_conn6->debugState())); + return restart(); + } + + DEBUG_LOG(("MTP Info: connection through IPv6 succeed, waiting IPv4 for %1ms.").arg(MTPIPv4ConnectionWaitTimeout)); + + _waitForIPv4Timer.start(MTPIPv4ConnectionWaitTimeout); +} + +void MTProtoConnectionPrivate::onDisconnected4() { + if (_conn && _conn == _conn6) return; // disconnected the unused + + if (_conn || !_conn6) { + destroyConn(); + restart(); + } else { + destroyConn(&_conn4); + } +} + +void MTProtoConnectionPrivate::onDisconnected6() { + if (_conn && _conn == _conn4) return; // disconnected the unused + + if (_conn || !_conn4) { + destroyConn(); + restart(); + } else { + destroyConn(&_conn6); + } +} + void MTProtoConnectionPrivate::updateAuthKey() { QReadLocker lockFinished(&sessionDataMutex); - if (!sessionData || !conn) return; + if (!sessionData || !_conn) return; DEBUG_LOG(("AuthKey Info: MTProtoConnection updating key from MTProtoSession, dc %1").arg(dc)); uint64 newKeyId = 0; @@ -2899,20 +2994,20 @@ void MTProtoConnectionPrivate::updateAuthKey() { MTPReq_pq req_pq; req_pq.vnonce = authKeyData->nonce; - connect(conn, SIGNAL(receivedData()), this, SLOT(pqAnswered())); + connect(_conn, SIGNAL(receivedData()), this, SLOT(pqAnswered())); DEBUG_LOG(("AuthKey Info: sending Req_pq..")); sendRequestNotSecure(req_pq); } void MTProtoConnectionPrivate::clearMessages() { - if (keyId && keyId != mtpAuthKey::RecreateKeyId && conn) { - conn->received().clear(); + if (keyId && keyId != mtpAuthKey::RecreateKeyId && _conn) { + _conn->received().clear(); } } void MTProtoConnectionPrivate::pqAnswered() { - disconnect(conn, SIGNAL(receivedData()), this, SLOT(pqAnswered())); + disconnect(_conn, SIGNAL(receivedData()), this, SLOT(pqAnswered())); DEBUG_LOG(("AuthKey Info: receiving Req_pq answer..")); MTPReq_pq::ResponseType res_pq; @@ -3008,14 +3103,14 @@ void MTProtoConnectionPrivate::pqAnswered() { return restart(); } - connect(conn, SIGNAL(receivedData()), this, SLOT(dhParamsAnswered())); + connect(_conn, SIGNAL(receivedData()), this, SLOT(dhParamsAnswered())); DEBUG_LOG(("AuthKey Info: sending Req_DH_params..")); sendRequestNotSecure(req_DH_params); } void MTProtoConnectionPrivate::dhParamsAnswered() { - disconnect(conn, SIGNAL(receivedData()), this, SLOT(dhParamsAnswered())); + disconnect(_conn, SIGNAL(receivedData()), this, SLOT(dhParamsAnswered())); DEBUG_LOG(("AuthKey Info: receiving Req_DH_params answer..")); MTPReq_DH_params::ResponseType res_DH_params; @@ -3190,7 +3285,7 @@ void MTProtoConnectionPrivate::dhClientParamsSend() { aesEncrypt(&encBuffer[0], &sdhEncString[0], encFullSize * sizeof(mtpPrime), authKeyData->aesKey, authKeyData->aesIV); - connect(conn, SIGNAL(receivedData()), this, SLOT(dhClientParamsAnswered())); + connect(_conn, SIGNAL(receivedData()), this, SLOT(dhClientParamsAnswered())); DEBUG_LOG(("AuthKey Info: sending Req_client_DH_params..")); sendRequestNotSecure(req_client_DH_params); @@ -3200,7 +3295,7 @@ void MTProtoConnectionPrivate::dhClientParamsAnswered() { QReadLocker lockFinished(&sessionDataMutex); if (!sessionData) return; - disconnect(conn, SIGNAL(receivedData()), this, SLOT(dhClientParamsAnswered())); + disconnect(_conn, SIGNAL(receivedData()), this, SLOT(dhClientParamsAnswered())); DEBUG_LOG(("AuthKey Info: receiving Req_client_DH_params answer..")); MTPSet_client_DH_params::ResponseType res_client_DH_params; @@ -3295,7 +3390,7 @@ void MTProtoConnectionPrivate::dhClientParamsAnswered() { void MTProtoConnectionPrivate::authKeyCreated() { clearAuthKeyData(); - connect(conn, SIGNAL(receivedData()), this, SLOT(handleReceived())); + connect(_conn, SIGNAL(receivedData()), this, SLOT(handleReceived())); if (sessionData->getSalt()) { // else receive salt in bad_server_salt first, then try to send all the requests setState(MTProtoConnection::Connected); @@ -3328,11 +3423,32 @@ void MTProtoConnectionPrivate::clearAuthKeyData() { } } -void MTProtoConnectionPrivate::onError(bool mayBeBadKey) { - cantConnectTimer.stop(); +void MTProtoConnectionPrivate::onError4(bool mayBeBadKey) { + if (_conn && _conn == _conn6) return; // error in the unused - MTP_LOG(dc, ("Restarting after error, maybe bad key: %1..").arg(logBool(mayBeBadKey))); - return restart(mayBeBadKey); + if (_conn || !_conn6) { + destroyConn(); + _waitForConnectedTimer.stop(); + + MTP_LOG(dc, ("Restarting after error in IPv4 connection, maybe bad key: %1..").arg(logBool(mayBeBadKey))); + return restart(mayBeBadKey); + } else { + destroyConn(&_conn4); + } +} + +void MTProtoConnectionPrivate::onError6(bool mayBeBadKey) { + if (_conn && _conn == _conn4) return; // error in the unused + + if (_conn || !_conn4) { + destroyConn(); + _waitForConnectedTimer.stop(); + + MTP_LOG(dc, ("Restarting after error in IPv6 connection, maybe bad key: %1..").arg(logBool(mayBeBadKey))); + return restart(mayBeBadKey); + } else { + destroyConn(&_conn6); + } } void MTProtoConnectionPrivate::onReadyData() { @@ -3359,7 +3475,7 @@ void MTProtoConnectionPrivate::sendRequestNotSecure(const TRequest &request) { DEBUG_LOG(("AuthKey Info: sending request, size: %1, num: %2, time: %3").arg(requestSize).arg(authKeyData->req_num).arg(buffer[5])); - conn->sendData(buffer); + _conn->sendData(buffer); onSentSome(buffer.size() * sizeof(mtpPrime)); @@ -3373,12 +3489,12 @@ bool MTProtoConnectionPrivate::readResponseNotSecure(TResponse &response) { onReceivedSome(); try { - if (conn->received().isEmpty()) { + if (_conn->received().isEmpty()) { LOG(("AuthKey Error: trying to read response from empty received list")); return false; } - mtpBuffer buffer(conn->received().front()); - conn->received().pop_front(); + mtpBuffer buffer(_conn->received().front()); + _conn->received().pop_front(); const mtpPrime *answer(buffer.constData()); uint32 len = buffer.size(); @@ -3449,8 +3565,8 @@ bool MTProtoConnectionPrivate::sendRequest(mtpRequest &request, bool needAnyResp DEBUG_LOG(("MTP Info: sending request, size: %1, num: %2, time: %3").arg(fullSize + 6).arg((*request)[4]).arg((*request)[5])); - conn->setSentEncrypted(); - conn->sendData(result); + _conn->setSentEncrypted(); + _conn->sendData(result); if (needAnyResponse) { onSentSome(result.size() * sizeof(mtpPrime)); diff --git a/Telegram/SourceFiles/mtproto/mtpConnection.h b/Telegram/SourceFiles/mtproto/mtpConnection.h index fa00f0865b..eedd583b6f 100644 --- a/Telegram/SourceFiles/mtproto/mtpConnection.h +++ b/Telegram/SourceFiles/mtproto/mtpConnection.h @@ -25,9 +25,23 @@ enum { MTPDmessage_flag_out = (1 << 1), MTPDmessage_flag_notify_by_from = (1 << 4), MTPDmessage_flag_media_unread = (1 << 5), + MTPmessages_SendMessage_flag_skipWebPage = (1 << 1), + + MTPDdcOption_flag_ipv6 = (1 << 0), + MTPDdcOption_flag_files = (1 << 1), + + MTPDuser_flag_self = (1 << 10), + MTPDuser_flag_contact = (1 << 11), + MTPDuser_flag_mutual_contact = (1 << 12), + MTPDuser_flag_deleted = (1 << 13), + MTPDuser_flag_bot = (1 << 14), + MTPDuser_flag_bot_reads_all = (1 << 15), + MTPDuser_flag_bot_cant_join = (1 << 16), }; +static const MTPReplyMarkup MTPnullMarkup = MTP_replyKeyboardMarkup(MTP_vector(0)); + #include "mtproto/mtpPublicRSA.h" #include "mtproto/mtpAuthKey.h" @@ -97,11 +111,6 @@ public: int32 state() const; QString transport() const; - /*template // not used - uint64 sendAsync(const TRequest &request) { - return data->sendAsync(request); - }*/ - private: QThread *thread; @@ -125,7 +134,7 @@ public: virtual void sendData(mtpBuffer &buffer) = 0; // has size + 3, buffer[0] = len, buffer[1] = packetnum, buffer[last] = crc32 virtual void disconnectFromServer() = 0; - virtual void connectToServer(const QString &addr, int32 port) = 0; + virtual void connectToServer(const QString &addr, int32 port, int32 flags) = 0; virtual bool isConnected() = 0; virtual bool usingHttpWait() { return false; @@ -193,7 +202,7 @@ public: void sendData(mtpBuffer &buffer); void disconnectFromServer(); - void connectToServer(const QString &addr, int32 port); + void connectToServer(const QString &addr, int32 port, int32 flags); bool isConnected(); bool usingHttpWait(); bool needHttpWait(); @@ -255,7 +264,7 @@ public: void sendData(mtpBuffer &buffer); void disconnectFromServer(); - void connectToServer(const QString &addr, int32 port); + void connectToServer(const QString &addr, int32 port, int32 flags); bool isConnected(); int32 debugState() const; @@ -281,7 +290,7 @@ public: void sendData(mtpBuffer &buffer); void disconnectFromServer(); - void connectToServer(const QString &addr, int32 port); + void connectToServer(const QString &addr, int32 port, int32 flags); bool isConnected(); bool usingHttpWait(); bool needHttpWait(); @@ -343,16 +352,25 @@ public slots: void onPingSender(); void onPingSendForce(); - void onBadConnection(); - void onCantConnect(); + + void onWaitConnectedFailed(); + void onWaitReceivedFailed(); + void onWaitIPv4Failed(); + void onOldConnection(); void onSentSome(uint64 size); void onReceivedSome(); - void onError(bool maybeBadKey = false); void onReadyData(); void socketStart(bool afterConfig = false); - void onConnected(); + + void onConnected4(); + void onConnected6(); + void onDisconnected4(); + void onDisconnected6(); + void onError4(bool maybeBadKey = false); + void onError6(bool maybeBadKey = false); + void doDisconnect(); void doFinish(); @@ -373,7 +391,8 @@ public slots: private: - void createConn(); + void createConn(bool createIPv4, bool createIPv6); + void destroyConn(MTPabstractConnection **conn = 0); // 0 - destory all mtpMsgId placeToContainer(mtpRequest &toSendRequest, mtpMsgId &bigMsgId, mtpMsgId *&haveSentArr, mtpRequest &req); mtpMsgId prepareToSend(mtpRequest &request, mtpMsgId currentLastId); @@ -397,7 +416,7 @@ private: uint32 dc; MTProtoConnection *_owner; - MTPabstractConnection *conn; + MTPabstractConnection *_conn, *_conn4, *_conn6; SingleTimer retryTimer; // exp retry timer uint32 retryTimeout; @@ -406,8 +425,8 @@ private: SingleTimer oldConnectionTimer; bool oldConnection; - SingleTimer connCheckTimer, cantConnectTimer; - uint32 receiveDelay, connectDelay; + SingleTimer _waitForConnectedTimer, _waitForReceivedTimer, _waitForIPv4Timer; + uint32 _waitForReceived, _waitForConnected; int64 firstSentAt; QVector ackRequestData, resendRequestData; diff --git a/Telegram/SourceFiles/mtproto/mtpCoreTypes.h b/Telegram/SourceFiles/mtproto/mtpCoreTypes.h index 3feb4bf86f..90fdf7d91c 100644 --- a/Telegram/SourceFiles/mtproto/mtpCoreTypes.h +++ b/Telegram/SourceFiles/mtproto/mtpCoreTypes.h @@ -366,7 +366,7 @@ static const mtpTypeId mtpLayers[] = { mtpc_invokeWithLayer17, mtpc_invokeWithLayer18, }, mtpLayerMaxSingle = sizeof(mtpLayers) / sizeof(mtpLayers[0]); -static const mtpPrime mtpCurrentLayer = 29; +static const mtpPrime mtpCurrentLayer = 31; template class MTPBoxed : public bareT { diff --git a/Telegram/SourceFiles/mtproto/mtpDC.cpp b/Telegram/SourceFiles/mtproto/mtpDC.cpp index bbd5b28f85..d3d77695ac 100644 --- a/Telegram/SourceFiles/mtproto/mtpDC.cpp +++ b/Telegram/SourceFiles/mtproto/mtpDC.cpp @@ -175,15 +175,16 @@ void mtpUpdateDcOptions(const QVector &options) { } for (QVector::const_iterator i = options.cbegin(), e = options.cend(); i != e; ++i) { const MTPDdcOption &optData(i->c_dcOption()); - if (already.constFind(optData.vid.v) == already.cend()) { - already.insert(optData.vid.v); - mtpDcOptions::const_iterator a = opts.constFind(optData.vid.v); + int32 id = optData.vid.v, idWithShift = id + (optData.vflags.v * _mtp_internal::dcShift); + if (already.constFind(idWithShift) == already.cend()) { + already.insert(idWithShift); + mtpDcOptions::const_iterator a = opts.constFind(idWithShift); if (a != opts.cend()) { if (a.value().ip != optData.vip_address.c_string().v || a.value().port != optData.vport.v) { - restart.insert(optData.vid.v); + restart.insert(id); } } - opts.insert(optData.vid.v, mtpDcOption(optData.vid.v, optData.vhostname.c_string().v, optData.vip_address.c_string().v, optData.vport.v)); + opts.insert(idWithShift, mtpDcOption(id, optData.vflags.v, optData.vip_address.c_string().v, optData.vport.v)); } } { diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.cpp b/Telegram/SourceFiles/mtproto/mtpScheme.cpp index b93923d00b..9f037c2624 100644 --- a/Telegram/SourceFiles/mtproto/mtpScheme.cpp +++ b/Telegram/SourceFiles/mtproto/mtpScheme.cpp @@ -1109,96 +1109,24 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; - case mtpc_userSelf: + case mtpc_user: if (stage) { to.add(",\n").addSpaces(lev); } else { - to.add("{ userSelf"); + to.add("{ user"); to.add("\n").addSpaces(lev); } switch (stage) { - case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" first_name: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" last_name: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" username: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" phone: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 6: to.add(" status: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } - break; - - case mtpc_userContact: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ userContact"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" first_name: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" last_name: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" username: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" phone: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 6: to.add(" photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 7: to.add(" status: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } - break; - - case mtpc_userRequest: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ userRequest"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" first_name: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" last_name: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" username: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" phone: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 6: to.add(" photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 7: to.add(" status: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } - break; - - case mtpc_userForeign: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ userForeign"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" first_name: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" last_name: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" username: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 6: to.add(" status: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } - break; - - case mtpc_userDeleted: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ userDeleted"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" first_name: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" last_name: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" username: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" access_hash: "); ++stages.back(); if (flag & MTPDuser::flag_access_hash) { types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; + case 3: to.add(" first_name: "); ++stages.back(); if (flag & MTPDuser::flag_first_name) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break; + case 4: to.add(" last_name: "); ++stages.back(); if (flag & MTPDuser::flag_last_name) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break; + case 5: to.add(" username: "); ++stages.back(); if (flag & MTPDuser::flag_username) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break; + case 6: to.add(" phone: "); ++stages.back(); if (flag & MTPDuser::flag_phone) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 4 IN FIELD flags ]"); } break; + case 7: to.add(" photo: "); ++stages.back(); if (flag & MTPDuser::flag_photo) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 5 IN FIELD flags ]"); } break; + case 8: to.add(" status: "); ++stages.back(); if (flag & MTPDuser::flag_status) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 6 IN FIELD flags ]"); } break; + case 9: to.add(" bot_info_version: "); ++stages.back(); if (flag & MTPDuser::flag_bot_info_version) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 14 IN FIELD flags ]"); } break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; @@ -1347,6 +1275,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP case 2: to.add(" chat_photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 3: to.add(" notify_settings: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 4: to.add(" exported_invite: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 5: to.add(" bot_info: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; @@ -1444,6 +1373,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP case 7: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 8: to.add(" message: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 9: to.add(" media: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 10: to.add(" reply_markup: "); ++stages.back(); if (flag & MTPDmessage::flag_reply_markup) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 6 IN FIELD flags ]"); } break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; @@ -1893,8 +1823,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP to.add("\n").addSpaces(lev); } switch (stage) { - case 0: to.add(" expires: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" user: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 0: to.add(" user: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; @@ -2048,8 +1977,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP case 2: to.add(" profile_photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 3: to.add(" notify_settings: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 4: to.add(" blocked: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" real_first_name: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 6: to.add(" real_last_name: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 5: to.add(" bot_info: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; @@ -3057,8 +2985,8 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP to.add("\n").addSpaces(lev); } switch (stage) { - case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" hostname: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 2: to.add(" ip_address: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 3: to.add(" port: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; @@ -4353,6 +4281,81 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; + case mtpc_botCommand: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ botCommand"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" command: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" params: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" description: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_botInfoEmpty: + to.add("{ botInfoEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); + break; + + case mtpc_botInfo: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ botInfo"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" version: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" share_text: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" description: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 4: to.add(" commands: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_keyboardButton: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ keyboardButton"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" text: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_keyboardButtonRow: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ keyboardButtonRow"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" buttons: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_replyKeyboardMarkup: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ replyKeyboardMarkup"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" rows: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + case mtpc_req_pq: if (stage) { to.add(",\n").addSpaces(lev); @@ -5018,6 +5021,22 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; + case mtpc_auth_importBotAuthorization: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ auth_importBotAuthorization"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" flags: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" api_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" api_hash: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" bot_auth_token: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + case mtpc_auth_checkPassword: if (stage) { to.add(",\n").addSpaces(lev); @@ -5388,6 +5407,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP case 2: to.add(" reply_to_msg_id: "); ++stages.back(); if (flag & MTPmessages_sendMessage::flag_reply_to_msg_id) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; case 3: to.add(" message: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 4: to.add(" random_id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 5: to.add(" reply_markup: "); ++stages.back(); if (flag & MTPmessages_sendMessage::flag_reply_markup) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; @@ -5405,6 +5425,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP case 2: to.add(" reply_to_msg_id: "); ++stages.back(); if (flag & MTPmessages_sendMedia::flag_reply_to_msg_id) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; case 3: to.add(" media: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 4: to.add(" random_id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 5: to.add(" reply_markup: "); ++stages.back(); if (flag & MTPmessages_sendMedia::flag_reply_markup) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.h b/Telegram/SourceFiles/mtproto/mtpScheme.h index ccdb699f11..1ec3d9612b 100644 --- a/Telegram/SourceFiles/mtproto/mtpScheme.h +++ b/Telegram/SourceFiles/mtproto/mtpScheme.h @@ -113,11 +113,6 @@ enum { mtpc_fileLocationUnavailable = 0x7c596b46, mtpc_fileLocation = 0x53d69076, mtpc_userEmpty = 0x200250ba, - mtpc_userSelf = 0x1c60e608, - mtpc_userContact = 0xcab35e18, - mtpc_userRequest = 0xd9ccc4ef, - mtpc_userForeign = 0x75cf7a8, - mtpc_userDeleted = 0xd6016d7a, mtpc_userProfilePhotoEmpty = 0x4f11bae1, mtpc_userProfilePhoto = 0xd559d8c8, mtpc_userStatusEmpty = 0x9d05049, @@ -126,14 +121,14 @@ enum { mtpc_chatEmpty = 0x9ba2d800, mtpc_chat = 0x6e9c9bc7, mtpc_chatForbidden = 0xfb0ccc41, - mtpc_chatFull = 0xcade0791, + mtpc_chatFull = 0x2e02a614, mtpc_chatParticipant = 0xc8d7493e, mtpc_chatParticipantsForbidden = 0xfd2bb8a, mtpc_chatParticipants = 0x7841b415, mtpc_chatPhotoEmpty = 0x37c1011c, mtpc_chatPhoto = 0x6153276a, mtpc_messageEmpty = 0x83e5de54, - mtpc_message = 0xa7ab1991, + mtpc_message = 0xc3060325, mtpc_messageService = 0x1d86f70e, mtpc_messageMediaEmpty = 0x3ded6320, mtpc_messageMediaPhoto = 0x3d8ce53d, @@ -160,7 +155,7 @@ enum { mtpc_geoPoint = 0x2049d70c, mtpc_auth_checkedPhone = 0x811ea28e, mtpc_auth_sentCode = 0xefed51d9, - mtpc_auth_authorization = 0xf6b673a4, + mtpc_auth_authorization = 0xff036af1, mtpc_auth_exportedAuthorization = 0xdf969c2d, mtpc_inputNotifyPeer = 0xb8bc5b0c, mtpc_inputNotifyUsers = 0x193b4417, @@ -174,7 +169,7 @@ enum { mtpc_peerNotifySettingsEmpty = 0x70a68512, mtpc_peerNotifySettings = 0x8d5e11ee, mtpc_wallPaper = 0xccb03657, - mtpc_userFull = 0x771095da, + mtpc_userFull = 0x5a89ac5b, mtpc_contact = 0xf911c994, mtpc_importedContact = 0xd0028438, mtpc_contactBlocked = 0x561bc879, @@ -230,7 +225,7 @@ enum { mtpc_photos_photosSlice = 0x15051f54, mtpc_photos_photo = 0x20212ca8, mtpc_upload_file = 0x96a18d5, - mtpc_dcOption = 0x2ec2a43c, + mtpc_dcOption = 0x5d8c6cc, mtpc_config = 0x4e32b894, mtpc_nearestDc = 0x8e1a1775, mtpc_help_appUpdate = 0x8987f311, @@ -383,6 +378,13 @@ enum { mtpc_inputStickerSetShortName = 0x861cc8a0, mtpc_stickerSet = 0xa7a43b17, mtpc_messages_stickerSet = 0xb60a24a6, + mtpc_user = 0x22e49072, + mtpc_botCommand = 0xb79d22ab, + mtpc_botInfoEmpty = 0xbb2e37ce, + mtpc_botInfo = 0x9cf585d, + mtpc_keyboardButton = 0xa2fa4880, + mtpc_keyboardButtonRow = 0x77608b83, + mtpc_replyKeyboardMarkup = 0xd59bfc31, mtpc_invokeAfterMsg = 0xcb9f372d, mtpc_invokeAfterMsgs = 0x3dc4b4f0, mtpc_auth_checkPhone = 0x6fe51dfb, @@ -426,8 +428,8 @@ enum { mtpc_messages_deleteMessages = 0xa5f18925, mtpc_messages_receivedMessages = 0x5a954c0, mtpc_messages_setTyping = 0xa3825e50, - mtpc_messages_sendMessage = 0x9add8f26, - mtpc_messages_sendMedia = 0x2d7923b1, + mtpc_messages_sendMessage = 0xfc55e6b5, + mtpc_messages_sendMedia = 0xc8f16791, mtpc_messages_forwardMessages = 0x55e1728d, mtpc_messages_getChats = 0x3c6aa187, mtpc_messages_getFullChat = 0x3b831c66, @@ -493,6 +495,7 @@ enum { mtpc_messages_getStickers = 0xae22e045, mtpc_messages_getAllStickers = 0xaa3bc868, mtpc_account_updateDeviceLocked = 0x38df3532, + mtpc_auth_importBotAuthorization = 0x67a3ff2c, mtpc_messages_getWebPagePreview = 0x25223e24, mtpc_account_getAuthorizations = 0xe320c158, mtpc_account_resetAuthorization = 0xdf77f3bc, @@ -655,11 +658,7 @@ class MTPDfileLocation; class MTPuser; class MTPDuserEmpty; -class MTPDuserSelf; -class MTPDuserContact; -class MTPDuserRequest; -class MTPDuserForeign; -class MTPDuserDeleted; +class MTPDuser; class MTPuserProfilePhoto; class MTPDuserProfilePhoto; @@ -1063,6 +1062,21 @@ class MTPDstickerSet; class MTPmessages_stickerSet; class MTPDmessages_stickerSet; +class MTPbotCommand; +class MTPDbotCommand; + +class MTPbotInfo; +class MTPDbotInfo; + +class MTPkeyboardButton; +class MTPDkeyboardButton; + +class MTPkeyboardButtonRow; +class MTPDkeyboardButtonRow; + +class MTPreplyMarkup; +class MTPDreplyKeyboardMarkup; + // Boxed types definitions typedef MTPBoxed MTPResPQ; @@ -1209,6 +1223,11 @@ typedef MTPBoxed MTPChatInvite; typedef MTPBoxed MTPInputStickerSet; typedef MTPBoxed MTPStickerSet; typedef MTPBoxed MTPmessages_StickerSet; +typedef MTPBoxed MTPBotCommand; +typedef MTPBoxed MTPBotInfo; +typedef MTPBoxed MTPKeyboardButton; +typedef MTPBoxed MTPKeyboardButtonRow; +typedef MTPBoxed MTPReplyMarkup; // Type classes definitions @@ -2928,64 +2947,16 @@ public: return *(const MTPDuserEmpty*)data; } - MTPDuserSelf &_userSelf() { + MTPDuser &_user() { if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_userSelf) throw mtpErrorWrongTypeId(_type, mtpc_userSelf); + if (_type != mtpc_user) throw mtpErrorWrongTypeId(_type, mtpc_user); split(); - return *(MTPDuserSelf*)data; + return *(MTPDuser*)data; } - const MTPDuserSelf &c_userSelf() const { + const MTPDuser &c_user() const { if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_userSelf) throw mtpErrorWrongTypeId(_type, mtpc_userSelf); - return *(const MTPDuserSelf*)data; - } - - MTPDuserContact &_userContact() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_userContact) throw mtpErrorWrongTypeId(_type, mtpc_userContact); - split(); - return *(MTPDuserContact*)data; - } - const MTPDuserContact &c_userContact() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_userContact) throw mtpErrorWrongTypeId(_type, mtpc_userContact); - return *(const MTPDuserContact*)data; - } - - MTPDuserRequest &_userRequest() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_userRequest) throw mtpErrorWrongTypeId(_type, mtpc_userRequest); - split(); - return *(MTPDuserRequest*)data; - } - const MTPDuserRequest &c_userRequest() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_userRequest) throw mtpErrorWrongTypeId(_type, mtpc_userRequest); - return *(const MTPDuserRequest*)data; - } - - MTPDuserForeign &_userForeign() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_userForeign) throw mtpErrorWrongTypeId(_type, mtpc_userForeign); - split(); - return *(MTPDuserForeign*)data; - } - const MTPDuserForeign &c_userForeign() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_userForeign) throw mtpErrorWrongTypeId(_type, mtpc_userForeign); - return *(const MTPDuserForeign*)data; - } - - MTPDuserDeleted &_userDeleted() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_userDeleted) throw mtpErrorWrongTypeId(_type, mtpc_userDeleted); - split(); - return *(MTPDuserDeleted*)data; - } - const MTPDuserDeleted &c_userDeleted() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_userDeleted) throw mtpErrorWrongTypeId(_type, mtpc_userDeleted); - return *(const MTPDuserDeleted*)data; + if (_type != mtpc_user) throw mtpErrorWrongTypeId(_type, mtpc_user); + return *(const MTPDuser*)data; } uint32 innerLength() const; @@ -2998,18 +2969,10 @@ public: private: explicit MTPuser(mtpTypeId type); explicit MTPuser(MTPDuserEmpty *_data); - explicit MTPuser(MTPDuserSelf *_data); - explicit MTPuser(MTPDuserContact *_data); - explicit MTPuser(MTPDuserRequest *_data); - explicit MTPuser(MTPDuserForeign *_data); - explicit MTPuser(MTPDuserDeleted *_data); + explicit MTPuser(MTPDuser *_data); friend MTPuser MTP_userEmpty(MTPint _id); - friend MTPuser MTP_userSelf(MTPint _id, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username, const MTPstring &_phone, const MTPUserProfilePhoto &_photo, const MTPUserStatus &_status); - friend MTPuser MTP_userContact(MTPint _id, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username, const MTPlong &_access_hash, const MTPstring &_phone, const MTPUserProfilePhoto &_photo, const MTPUserStatus &_status); - friend MTPuser MTP_userRequest(MTPint _id, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username, const MTPlong &_access_hash, const MTPstring &_phone, const MTPUserProfilePhoto &_photo, const MTPUserStatus &_status); - friend MTPuser MTP_userForeign(MTPint _id, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username, const MTPlong &_access_hash, const MTPUserProfilePhoto &_photo, const MTPUserStatus &_status); - friend MTPuser MTP_userDeleted(MTPint _id, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username); + friend MTPuser MTP_user(MTPint _flags, MTPint _id, const MTPlong &_access_hash, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username, const MTPstring &_phone, const MTPUserProfilePhoto &_photo, const MTPUserStatus &_status, MTPint _bot_info_version); mtpTypeId _type; }; @@ -3214,7 +3177,7 @@ public: private: explicit MTPchatFull(MTPDchatFull *_data); - friend MTPchatFull MTP_chatFull(MTPint _id, const MTPChatParticipants &_participants, const MTPPhoto &_chat_photo, const MTPPeerNotifySettings &_notify_settings, const MTPExportedChatInvite &_exported_invite); + friend MTPchatFull MTP_chatFull(MTPint _id, const MTPChatParticipants &_participants, const MTPPhoto &_chat_photo, const MTPPeerNotifySettings &_notify_settings, const MTPExportedChatInvite &_exported_invite, const MTPVector &_bot_info); }; typedef MTPBoxed MTPChatFull; @@ -3396,7 +3359,7 @@ private: explicit MTPmessage(MTPDmessageService *_data); friend MTPmessage MTP_messageEmpty(MTPint _id); - friend MTPmessage MTP_message(MTPint _flags, MTPint _id, MTPint _from_id, const MTPPeer &_to_id, MTPint _fwd_from_id, MTPint _fwd_date, MTPint _reply_to_msg_id, MTPint _date, const MTPstring &_message, const MTPMessageMedia &_media); + friend MTPmessage MTP_message(MTPint _flags, MTPint _id, MTPint _from_id, const MTPPeer &_to_id, MTPint _fwd_from_id, MTPint _fwd_date, MTPint _reply_to_msg_id, MTPint _date, const MTPstring &_message, const MTPMessageMedia &_media, const MTPReplyMarkup &_reply_markup); friend MTPmessage MTP_messageService(MTPint _flags, MTPint _id, MTPint _from_id, const MTPPeer &_to_id, MTPint _date, const MTPMessageAction &_action); mtpTypeId _type; @@ -4009,7 +3972,7 @@ public: private: explicit MTPauth_authorization(MTPDauth_authorization *_data); - friend MTPauth_authorization MTP_auth_authorization(MTPint _expires, const MTPUser &_user); + friend MTPauth_authorization MTP_auth_authorization(const MTPUser &_user); }; typedef MTPBoxed MTPauth_Authorization; @@ -4295,7 +4258,7 @@ public: private: explicit MTPuserFull(MTPDuserFull *_data); - friend MTPuserFull MTP_userFull(const MTPUser &_user, const MTPcontacts_Link &_link, const MTPPhoto &_profile_photo, const MTPPeerNotifySettings &_notify_settings, MTPBool _blocked, const MTPstring &_real_first_name, const MTPstring &_real_last_name); + friend MTPuserFull MTP_userFull(const MTPUser &_user, const MTPcontacts_Link &_link, const MTPPhoto &_profile_photo, const MTPPeerNotifySettings &_notify_settings, MTPBool _blocked, const MTPBotInfo &_bot_info); }; typedef MTPBoxed MTPUserFull; @@ -5723,7 +5686,7 @@ public: private: explicit MTPdcOption(MTPDdcOption *_data); - friend MTPdcOption MTP_dcOption(MTPint _id, const MTPstring &_hostname, const MTPstring &_ip_address, MTPint _port); + friend MTPdcOption MTP_dcOption(MTPint _flags, MTPint _id, const MTPstring &_ip_address, MTPint _port); }; typedef MTPBoxed MTPDcOption; @@ -7884,6 +7847,168 @@ private: }; typedef MTPBoxed MTPmessages_StickerSet; +class MTPbotCommand : private mtpDataOwner { +public: + MTPbotCommand(); + MTPbotCommand(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_botCommand) : mtpDataOwner(0) { + read(from, end, cons); + } + + MTPDbotCommand &_botCommand() { + if (!data) throw mtpErrorUninitialized(); + split(); + return *(MTPDbotCommand*)data; + } + const MTPDbotCommand &c_botCommand() const { + if (!data) throw mtpErrorUninitialized(); + return *(const MTPDbotCommand*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_botCommand); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPbotCommand(MTPDbotCommand *_data); + + friend MTPbotCommand MTP_botCommand(const MTPstring &_command, const MTPstring &_params, const MTPstring &_description); +}; +typedef MTPBoxed MTPBotCommand; + +class MTPbotInfo : private mtpDataOwner { +public: + MTPbotInfo() : mtpDataOwner(0), _type(0) { + } + MTPbotInfo(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) { + read(from, end, cons); + } + + MTPDbotInfo &_botInfo() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_botInfo) throw mtpErrorWrongTypeId(_type, mtpc_botInfo); + split(); + return *(MTPDbotInfo*)data; + } + const MTPDbotInfo &c_botInfo() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_botInfo) throw mtpErrorWrongTypeId(_type, mtpc_botInfo); + return *(const MTPDbotInfo*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPbotInfo(mtpTypeId type); + explicit MTPbotInfo(MTPDbotInfo *_data); + + friend MTPbotInfo MTP_botInfoEmpty(); + friend MTPbotInfo MTP_botInfo(MTPint _user_id, MTPint _version, const MTPstring &_share_text, const MTPstring &_description, const MTPVector &_commands); + + mtpTypeId _type; +}; +typedef MTPBoxed MTPBotInfo; + +class MTPkeyboardButton : private mtpDataOwner { +public: + MTPkeyboardButton(); + MTPkeyboardButton(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_keyboardButton) : mtpDataOwner(0) { + read(from, end, cons); + } + + MTPDkeyboardButton &_keyboardButton() { + if (!data) throw mtpErrorUninitialized(); + split(); + return *(MTPDkeyboardButton*)data; + } + const MTPDkeyboardButton &c_keyboardButton() const { + if (!data) throw mtpErrorUninitialized(); + return *(const MTPDkeyboardButton*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_keyboardButton); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPkeyboardButton(MTPDkeyboardButton *_data); + + friend MTPkeyboardButton MTP_keyboardButton(const MTPstring &_text); +}; +typedef MTPBoxed MTPKeyboardButton; + +class MTPkeyboardButtonRow : private mtpDataOwner { +public: + MTPkeyboardButtonRow(); + MTPkeyboardButtonRow(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_keyboardButtonRow) : mtpDataOwner(0) { + read(from, end, cons); + } + + MTPDkeyboardButtonRow &_keyboardButtonRow() { + if (!data) throw mtpErrorUninitialized(); + split(); + return *(MTPDkeyboardButtonRow*)data; + } + const MTPDkeyboardButtonRow &c_keyboardButtonRow() const { + if (!data) throw mtpErrorUninitialized(); + return *(const MTPDkeyboardButtonRow*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_keyboardButtonRow); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPkeyboardButtonRow(MTPDkeyboardButtonRow *_data); + + friend MTPkeyboardButtonRow MTP_keyboardButtonRow(const MTPVector &_buttons); +}; +typedef MTPBoxed MTPKeyboardButtonRow; + +class MTPreplyMarkup : private mtpDataOwner { +public: + MTPreplyMarkup(); + MTPreplyMarkup(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_replyKeyboardMarkup) : mtpDataOwner(0) { + read(from, end, cons); + } + + MTPDreplyKeyboardMarkup &_replyKeyboardMarkup() { + if (!data) throw mtpErrorUninitialized(); + split(); + return *(MTPDreplyKeyboardMarkup*)data; + } + const MTPDreplyKeyboardMarkup &c_replyKeyboardMarkup() const { + if (!data) throw mtpErrorUninitialized(); + return *(const MTPDreplyKeyboardMarkup*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_replyKeyboardMarkup); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPreplyMarkup(MTPDreplyKeyboardMarkup *_data); + + friend MTPreplyMarkup MTP_replyKeyboardMarkup(const MTPVector &_rows); +}; +typedef MTPBoxed MTPReplyMarkup; + // Type constructors with data class MTPDresPQ : public mtpDataImpl { @@ -8653,83 +8778,43 @@ public: MTPint vid; }; -class MTPDuserSelf : public mtpDataImpl { +class MTPDuser : public mtpDataImpl { public: - MTPDuserSelf() { + MTPDuser() { } - MTPDuserSelf(MTPint _id, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username, const MTPstring &_phone, const MTPUserProfilePhoto &_photo, const MTPUserStatus &_status) : vid(_id), vfirst_name(_first_name), vlast_name(_last_name), vusername(_username), vphone(_phone), vphoto(_photo), vstatus(_status) { + MTPDuser(MTPint _flags, MTPint _id, const MTPlong &_access_hash, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username, const MTPstring &_phone, const MTPUserProfilePhoto &_photo, const MTPUserStatus &_status, MTPint _bot_info_version) : vflags(_flags), vid(_id), vaccess_hash(_access_hash), vfirst_name(_first_name), vlast_name(_last_name), vusername(_username), vphone(_phone), vphoto(_photo), vstatus(_status), vbot_info_version(_bot_info_version) { } + MTPint vflags; MTPint vid; + MTPlong vaccess_hash; MTPstring vfirst_name; MTPstring vlast_name; MTPstring vusername; MTPstring vphone; MTPUserProfilePhoto vphoto; MTPUserStatus vstatus; -}; + MTPint vbot_info_version; -class MTPDuserContact : public mtpDataImpl { -public: - MTPDuserContact() { - } - MTPDuserContact(MTPint _id, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username, const MTPlong &_access_hash, const MTPstring &_phone, const MTPUserProfilePhoto &_photo, const MTPUserStatus &_status) : vid(_id), vfirst_name(_first_name), vlast_name(_last_name), vusername(_username), vaccess_hash(_access_hash), vphone(_phone), vphoto(_photo), vstatus(_status) { - } + enum { + flag_access_hash = (1 << 0), + flag_first_name = (1 << 1), + flag_last_name = (1 << 2), + flag_username = (1 << 3), + flag_phone = (1 << 4), + flag_photo = (1 << 5), + flag_status = (1 << 6), + flag_bot_info_version = (1 << 14), + }; - MTPint vid; - MTPstring vfirst_name; - MTPstring vlast_name; - MTPstring vusername; - MTPlong vaccess_hash; - MTPstring vphone; - MTPUserProfilePhoto vphoto; - MTPUserStatus vstatus; -}; - -class MTPDuserRequest : public mtpDataImpl { -public: - MTPDuserRequest() { - } - MTPDuserRequest(MTPint _id, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username, const MTPlong &_access_hash, const MTPstring &_phone, const MTPUserProfilePhoto &_photo, const MTPUserStatus &_status) : vid(_id), vfirst_name(_first_name), vlast_name(_last_name), vusername(_username), vaccess_hash(_access_hash), vphone(_phone), vphoto(_photo), vstatus(_status) { - } - - MTPint vid; - MTPstring vfirst_name; - MTPstring vlast_name; - MTPstring vusername; - MTPlong vaccess_hash; - MTPstring vphone; - MTPUserProfilePhoto vphoto; - MTPUserStatus vstatus; -}; - -class MTPDuserForeign : public mtpDataImpl { -public: - MTPDuserForeign() { - } - MTPDuserForeign(MTPint _id, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username, const MTPlong &_access_hash, const MTPUserProfilePhoto &_photo, const MTPUserStatus &_status) : vid(_id), vfirst_name(_first_name), vlast_name(_last_name), vusername(_username), vaccess_hash(_access_hash), vphoto(_photo), vstatus(_status) { - } - - MTPint vid; - MTPstring vfirst_name; - MTPstring vlast_name; - MTPstring vusername; - MTPlong vaccess_hash; - MTPUserProfilePhoto vphoto; - MTPUserStatus vstatus; -}; - -class MTPDuserDeleted : public mtpDataImpl { -public: - MTPDuserDeleted() { - } - MTPDuserDeleted(MTPint _id, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username) : vid(_id), vfirst_name(_first_name), vlast_name(_last_name), vusername(_username) { - } - - MTPint vid; - MTPstring vfirst_name; - MTPstring vlast_name; - MTPstring vusername; + bool has_access_hash() const { return vflags.v & flag_access_hash; } + bool has_first_name() const { return vflags.v & flag_first_name; } + bool has_last_name() const { return vflags.v & flag_last_name; } + bool has_username() const { return vflags.v & flag_username; } + bool has_phone() const { return vflags.v & flag_phone; } + bool has_photo() const { return vflags.v & flag_photo; } + bool has_status() const { return vflags.v & flag_status; } + bool has_bot_info_version() const { return vflags.v & flag_bot_info_version; } }; class MTPDuserProfilePhoto : public mtpDataImpl { @@ -8826,7 +8911,7 @@ class MTPDchatFull : public mtpDataImpl { public: MTPDchatFull() { } - MTPDchatFull(MTPint _id, const MTPChatParticipants &_participants, const MTPPhoto &_chat_photo, const MTPPeerNotifySettings &_notify_settings, const MTPExportedChatInvite &_exported_invite) : vid(_id), vparticipants(_participants), vchat_photo(_chat_photo), vnotify_settings(_notify_settings), vexported_invite(_exported_invite) { + MTPDchatFull(MTPint _id, const MTPChatParticipants &_participants, const MTPPhoto &_chat_photo, const MTPPeerNotifySettings &_notify_settings, const MTPExportedChatInvite &_exported_invite, const MTPVector &_bot_info) : vid(_id), vparticipants(_participants), vchat_photo(_chat_photo), vnotify_settings(_notify_settings), vexported_invite(_exported_invite), vbot_info(_bot_info) { } MTPint vid; @@ -8834,6 +8919,7 @@ public: MTPPhoto vchat_photo; MTPPeerNotifySettings vnotify_settings; MTPExportedChatInvite vexported_invite; + MTPVector vbot_info; }; class MTPDchatParticipant : public mtpDataImpl { @@ -8896,7 +8982,7 @@ class MTPDmessage : public mtpDataImpl { public: MTPDmessage() { } - MTPDmessage(MTPint _flags, MTPint _id, MTPint _from_id, const MTPPeer &_to_id, MTPint _fwd_from_id, MTPint _fwd_date, MTPint _reply_to_msg_id, MTPint _date, const MTPstring &_message, const MTPMessageMedia &_media) : vflags(_flags), vid(_id), vfrom_id(_from_id), vto_id(_to_id), vfwd_from_id(_fwd_from_id), vfwd_date(_fwd_date), vreply_to_msg_id(_reply_to_msg_id), vdate(_date), vmessage(_message), vmedia(_media) { + MTPDmessage(MTPint _flags, MTPint _id, MTPint _from_id, const MTPPeer &_to_id, MTPint _fwd_from_id, MTPint _fwd_date, MTPint _reply_to_msg_id, MTPint _date, const MTPstring &_message, const MTPMessageMedia &_media, const MTPReplyMarkup &_reply_markup) : vflags(_flags), vid(_id), vfrom_id(_from_id), vto_id(_to_id), vfwd_from_id(_fwd_from_id), vfwd_date(_fwd_date), vreply_to_msg_id(_reply_to_msg_id), vdate(_date), vmessage(_message), vmedia(_media), vreply_markup(_reply_markup) { } MTPint vflags; @@ -8909,16 +8995,19 @@ public: MTPint vdate; MTPstring vmessage; MTPMessageMedia vmedia; + MTPReplyMarkup vreply_markup; enum { flag_fwd_from_id = (1 << 2), flag_fwd_date = (1 << 2), flag_reply_to_msg_id = (1 << 3), + flag_reply_markup = (1 << 6), }; bool has_fwd_from_id() const { return vflags.v & flag_fwd_from_id; } bool has_fwd_date() const { return vflags.v & flag_fwd_date; } bool has_reply_to_msg_id() const { return vflags.v & flag_reply_to_msg_id; } + bool has_reply_markup() const { return vflags.v & flag_reply_markup; } }; class MTPDmessageService : public mtpDataImpl { @@ -9254,10 +9343,9 @@ class MTPDauth_authorization : public mtpDataImpl { public: MTPDauth_authorization() { } - MTPDauth_authorization(MTPint _expires, const MTPUser &_user) : vexpires(_expires), vuser(_user) { + MTPDauth_authorization(const MTPUser &_user) : vuser(_user) { } - MTPint vexpires; MTPUser vuser; }; @@ -9348,7 +9436,7 @@ class MTPDuserFull : public mtpDataImpl { public: MTPDuserFull() { } - MTPDuserFull(const MTPUser &_user, const MTPcontacts_Link &_link, const MTPPhoto &_profile_photo, const MTPPeerNotifySettings &_notify_settings, MTPBool _blocked, const MTPstring &_real_first_name, const MTPstring &_real_last_name) : vuser(_user), vlink(_link), vprofile_photo(_profile_photo), vnotify_settings(_notify_settings), vblocked(_blocked), vreal_first_name(_real_first_name), vreal_last_name(_real_last_name) { + MTPDuserFull(const MTPUser &_user, const MTPcontacts_Link &_link, const MTPPhoto &_profile_photo, const MTPPeerNotifySettings &_notify_settings, MTPBool _blocked, const MTPBotInfo &_bot_info) : vuser(_user), vlink(_link), vprofile_photo(_profile_photo), vnotify_settings(_notify_settings), vblocked(_blocked), vbot_info(_bot_info) { } MTPUser vuser; @@ -9356,8 +9444,7 @@ public: MTPPhoto vprofile_photo; MTPPeerNotifySettings vnotify_settings; MTPBool vblocked; - MTPstring vreal_first_name; - MTPstring vreal_last_name; + MTPBotInfo vbot_info; }; class MTPDcontact : public mtpDataImpl { @@ -10150,11 +10237,11 @@ class MTPDdcOption : public mtpDataImpl { public: MTPDdcOption() { } - MTPDdcOption(MTPint _id, const MTPstring &_hostname, const MTPstring &_ip_address, MTPint _port) : vid(_id), vhostname(_hostname), vip_address(_ip_address), vport(_port) { + MTPDdcOption(MTPint _flags, MTPint _id, const MTPstring &_ip_address, MTPint _port) : vflags(_flags), vid(_id), vip_address(_ip_address), vport(_port) { } + MTPint vflags; MTPint vid; - MTPstring vhostname; MTPstring vip_address; MTPint vport; }; @@ -11122,6 +11209,62 @@ public: MTPVector vdocuments; }; +class MTPDbotCommand : public mtpDataImpl { +public: + MTPDbotCommand() { + } + MTPDbotCommand(const MTPstring &_command, const MTPstring &_params, const MTPstring &_description) : vcommand(_command), vparams(_params), vdescription(_description) { + } + + MTPstring vcommand; + MTPstring vparams; + MTPstring vdescription; +}; + +class MTPDbotInfo : public mtpDataImpl { +public: + MTPDbotInfo() { + } + MTPDbotInfo(MTPint _user_id, MTPint _version, const MTPstring &_share_text, const MTPstring &_description, const MTPVector &_commands) : vuser_id(_user_id), vversion(_version), vshare_text(_share_text), vdescription(_description), vcommands(_commands) { + } + + MTPint vuser_id; + MTPint vversion; + MTPstring vshare_text; + MTPstring vdescription; + MTPVector vcommands; +}; + +class MTPDkeyboardButton : public mtpDataImpl { +public: + MTPDkeyboardButton() { + } + MTPDkeyboardButton(const MTPstring &_text) : vtext(_text) { + } + + MTPstring vtext; +}; + +class MTPDkeyboardButtonRow : public mtpDataImpl { +public: + MTPDkeyboardButtonRow() { + } + MTPDkeyboardButtonRow(const MTPVector &_buttons) : vbuttons(_buttons) { + } + + MTPVector vbuttons; +}; + +class MTPDreplyKeyboardMarkup : public mtpDataImpl { +public: + MTPDreplyKeyboardMarkup() { + } + MTPDreplyKeyboardMarkup(const MTPVector &_rows) : vrows(_rows) { + } + + MTPVector vrows; +}; + // RPC methods class MTPreq_pq { // RPC method 'req_pq' @@ -13282,23 +13425,26 @@ public: MTPint vreply_to_msg_id; MTPstring vmessage; MTPlong vrandom_id; + MTPReplyMarkup vreply_markup; MTPmessages_sendMessage() { } MTPmessages_sendMessage(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_sendMessage) { read(from, end, cons); } - MTPmessages_sendMessage(MTPint _flags, const MTPInputPeer &_peer, MTPint _reply_to_msg_id, const MTPstring &_message, const MTPlong &_random_id) : vflags(_flags), vpeer(_peer), vreply_to_msg_id(_reply_to_msg_id), vmessage(_message), vrandom_id(_random_id) { + MTPmessages_sendMessage(MTPint _flags, const MTPInputPeer &_peer, MTPint _reply_to_msg_id, const MTPstring &_message, const MTPlong &_random_id, const MTPReplyMarkup &_reply_markup) : vflags(_flags), vpeer(_peer), vreply_to_msg_id(_reply_to_msg_id), vmessage(_message), vrandom_id(_random_id), vreply_markup(_reply_markup) { } enum { flag_reply_to_msg_id = (1 << 0), + flag_reply_markup = (1 << 2), }; bool has_reply_to_msg_id() const { return vflags.v & flag_reply_to_msg_id; } + bool has_reply_markup() const { return vflags.v & flag_reply_markup; } uint32 innerLength() const { - return vflags.innerLength() + vpeer.innerLength() + (has_reply_to_msg_id() ? vreply_to_msg_id.innerLength() : 0) + vmessage.innerLength() + vrandom_id.innerLength(); + return vflags.innerLength() + vpeer.innerLength() + (has_reply_to_msg_id() ? vreply_to_msg_id.innerLength() : 0) + vmessage.innerLength() + vrandom_id.innerLength() + (has_reply_markup() ? vreply_markup.innerLength() : 0); } mtpTypeId type() const { return mtpc_messages_sendMessage; @@ -13309,6 +13455,7 @@ public: if (has_reply_to_msg_id()) { vreply_to_msg_id.read(from, end); } else { vreply_to_msg_id = MTPint(); } vmessage.read(from, end); vrandom_id.read(from, end); + if (has_reply_markup()) { vreply_markup.read(from, end); } else { vreply_markup = MTPReplyMarkup(); } } void write(mtpBuffer &to) const { vflags.write(to); @@ -13316,6 +13463,7 @@ public: if (has_reply_to_msg_id()) vreply_to_msg_id.write(to); vmessage.write(to); vrandom_id.write(to); + if (has_reply_markup()) vreply_markup.write(to); } typedef MTPmessages_SentMessage ResponseType; @@ -13328,7 +13476,7 @@ public: } MTPmessages_SendMessage(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { } - MTPmessages_SendMessage(MTPint _flags, const MTPInputPeer &_peer, MTPint _reply_to_msg_id, const MTPstring &_message, const MTPlong &_random_id) : MTPBoxed(MTPmessages_sendMessage(_flags, _peer, _reply_to_msg_id, _message, _random_id)) { + MTPmessages_SendMessage(MTPint _flags, const MTPInputPeer &_peer, MTPint _reply_to_msg_id, const MTPstring &_message, const MTPlong &_random_id, const MTPReplyMarkup &_reply_markup) : MTPBoxed(MTPmessages_sendMessage(_flags, _peer, _reply_to_msg_id, _message, _random_id, _reply_markup)) { } }; @@ -13339,23 +13487,26 @@ public: MTPint vreply_to_msg_id; MTPInputMedia vmedia; MTPlong vrandom_id; + MTPReplyMarkup vreply_markup; MTPmessages_sendMedia() { } MTPmessages_sendMedia(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_sendMedia) { read(from, end, cons); } - MTPmessages_sendMedia(MTPint _flags, const MTPInputPeer &_peer, MTPint _reply_to_msg_id, const MTPInputMedia &_media, const MTPlong &_random_id) : vflags(_flags), vpeer(_peer), vreply_to_msg_id(_reply_to_msg_id), vmedia(_media), vrandom_id(_random_id) { + MTPmessages_sendMedia(MTPint _flags, const MTPInputPeer &_peer, MTPint _reply_to_msg_id, const MTPInputMedia &_media, const MTPlong &_random_id, const MTPReplyMarkup &_reply_markup) : vflags(_flags), vpeer(_peer), vreply_to_msg_id(_reply_to_msg_id), vmedia(_media), vrandom_id(_random_id), vreply_markup(_reply_markup) { } enum { flag_reply_to_msg_id = (1 << 0), + flag_reply_markup = (1 << 2), }; bool has_reply_to_msg_id() const { return vflags.v & flag_reply_to_msg_id; } + bool has_reply_markup() const { return vflags.v & flag_reply_markup; } uint32 innerLength() const { - return vflags.innerLength() + vpeer.innerLength() + (has_reply_to_msg_id() ? vreply_to_msg_id.innerLength() : 0) + vmedia.innerLength() + vrandom_id.innerLength(); + return vflags.innerLength() + vpeer.innerLength() + (has_reply_to_msg_id() ? vreply_to_msg_id.innerLength() : 0) + vmedia.innerLength() + vrandom_id.innerLength() + (has_reply_markup() ? vreply_markup.innerLength() : 0); } mtpTypeId type() const { return mtpc_messages_sendMedia; @@ -13366,6 +13517,7 @@ public: if (has_reply_to_msg_id()) { vreply_to_msg_id.read(from, end); } else { vreply_to_msg_id = MTPint(); } vmedia.read(from, end); vrandom_id.read(from, end); + if (has_reply_markup()) { vreply_markup.read(from, end); } else { vreply_markup = MTPReplyMarkup(); } } void write(mtpBuffer &to) const { vflags.write(to); @@ -13373,6 +13525,7 @@ public: if (has_reply_to_msg_id()) vreply_to_msg_id.write(to); vmedia.write(to); vrandom_id.write(to); + if (has_reply_markup()) vreply_markup.write(to); } typedef MTPUpdates ResponseType; @@ -13385,7 +13538,7 @@ public: } MTPmessages_SendMedia(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { } - MTPmessages_SendMedia(MTPint _flags, const MTPInputPeer &_peer, MTPint _reply_to_msg_id, const MTPInputMedia &_media, const MTPlong &_random_id) : MTPBoxed(MTPmessages_sendMedia(_flags, _peer, _reply_to_msg_id, _media, _random_id)) { + MTPmessages_SendMedia(MTPint _flags, const MTPInputPeer &_peer, MTPint _reply_to_msg_id, const MTPInputMedia &_media, const MTPlong &_random_id, const MTPReplyMarkup &_reply_markup) : MTPBoxed(MTPmessages_sendMedia(_flags, _peer, _reply_to_msg_id, _media, _random_id, _reply_markup)) { } }; @@ -16130,6 +16283,54 @@ public: } }; +class MTPauth_importBotAuthorization { // RPC method 'auth.importBotAuthorization' +public: + MTPint vflags; + MTPint vapi_id; + MTPstring vapi_hash; + MTPstring vbot_auth_token; + + MTPauth_importBotAuthorization() { + } + MTPauth_importBotAuthorization(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_auth_importBotAuthorization) { + read(from, end, cons); + } + MTPauth_importBotAuthorization(MTPint _flags, MTPint _api_id, const MTPstring &_api_hash, const MTPstring &_bot_auth_token) : vflags(_flags), vapi_id(_api_id), vapi_hash(_api_hash), vbot_auth_token(_bot_auth_token) { + } + + uint32 innerLength() const { + return vflags.innerLength() + vapi_id.innerLength() + vapi_hash.innerLength() + vbot_auth_token.innerLength(); + } + mtpTypeId type() const { + return mtpc_auth_importBotAuthorization; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_auth_importBotAuthorization) { + vflags.read(from, end); + vapi_id.read(from, end); + vapi_hash.read(from, end); + vbot_auth_token.read(from, end); + } + void write(mtpBuffer &to) const { + vflags.write(to); + vapi_id.write(to); + vapi_hash.write(to); + vbot_auth_token.write(to); + } + + typedef MTPauth_Authorization ResponseType; +}; +class MTPauth_ImportBotAuthorization : public MTPBoxed { +public: + MTPauth_ImportBotAuthorization() { + } + MTPauth_ImportBotAuthorization(const MTPauth_importBotAuthorization &v) : MTPBoxed(v) { + } + MTPauth_ImportBotAuthorization(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPauth_ImportBotAuthorization(MTPint _flags, MTPint _api_id, const MTPstring &_api_hash, const MTPstring &_bot_auth_token) : MTPBoxed(MTPauth_importBotAuthorization(_flags, _api_id, _api_hash, _bot_auth_token)) { + } +}; + class MTPmessages_getWebPagePreview { // RPC method 'messages.getWebPagePreview' public: MTPstring vmessage; @@ -18930,25 +19131,9 @@ inline uint32 MTPuser::innerLength() const { const MTPDuserEmpty &v(c_userEmpty()); return v.vid.innerLength(); } - case mtpc_userSelf: { - const MTPDuserSelf &v(c_userSelf()); - return v.vid.innerLength() + v.vfirst_name.innerLength() + v.vlast_name.innerLength() + v.vusername.innerLength() + v.vphone.innerLength() + v.vphoto.innerLength() + v.vstatus.innerLength(); - } - case mtpc_userContact: { - const MTPDuserContact &v(c_userContact()); - return v.vid.innerLength() + v.vfirst_name.innerLength() + v.vlast_name.innerLength() + v.vusername.innerLength() + v.vaccess_hash.innerLength() + v.vphone.innerLength() + v.vphoto.innerLength() + v.vstatus.innerLength(); - } - case mtpc_userRequest: { - const MTPDuserRequest &v(c_userRequest()); - return v.vid.innerLength() + v.vfirst_name.innerLength() + v.vlast_name.innerLength() + v.vusername.innerLength() + v.vaccess_hash.innerLength() + v.vphone.innerLength() + v.vphoto.innerLength() + v.vstatus.innerLength(); - } - case mtpc_userForeign: { - const MTPDuserForeign &v(c_userForeign()); - return v.vid.innerLength() + v.vfirst_name.innerLength() + v.vlast_name.innerLength() + v.vusername.innerLength() + v.vaccess_hash.innerLength() + v.vphoto.innerLength() + v.vstatus.innerLength(); - } - case mtpc_userDeleted: { - const MTPDuserDeleted &v(c_userDeleted()); - return v.vid.innerLength() + v.vfirst_name.innerLength() + v.vlast_name.innerLength() + v.vusername.innerLength(); + case mtpc_user: { + const MTPDuser &v(c_user()); + return v.vflags.innerLength() + v.vid.innerLength() + (v.has_access_hash() ? v.vaccess_hash.innerLength() : 0) + (v.has_first_name() ? v.vfirst_name.innerLength() : 0) + (v.has_last_name() ? v.vlast_name.innerLength() : 0) + (v.has_username() ? v.vusername.innerLength() : 0) + (v.has_phone() ? v.vphone.innerLength() : 0) + (v.has_photo() ? v.vphoto.innerLength() : 0) + (v.has_status() ? v.vstatus.innerLength() : 0) + (v.has_bot_info_version() ? v.vbot_info_version.innerLength() : 0); } } return 0; @@ -18965,59 +19150,19 @@ inline void MTPuser::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId MTPDuserEmpty &v(_userEmpty()); v.vid.read(from, end); } break; - case mtpc_userSelf: _type = cons; { - if (!data) setData(new MTPDuserSelf()); - MTPDuserSelf &v(_userSelf()); + case mtpc_user: _type = cons; { + if (!data) setData(new MTPDuser()); + MTPDuser &v(_user()); + v.vflags.read(from, end); v.vid.read(from, end); - v.vfirst_name.read(from, end); - v.vlast_name.read(from, end); - v.vusername.read(from, end); - v.vphone.read(from, end); - v.vphoto.read(from, end); - v.vstatus.read(from, end); - } break; - case mtpc_userContact: _type = cons; { - if (!data) setData(new MTPDuserContact()); - MTPDuserContact &v(_userContact()); - v.vid.read(from, end); - v.vfirst_name.read(from, end); - v.vlast_name.read(from, end); - v.vusername.read(from, end); - v.vaccess_hash.read(from, end); - v.vphone.read(from, end); - v.vphoto.read(from, end); - v.vstatus.read(from, end); - } break; - case mtpc_userRequest: _type = cons; { - if (!data) setData(new MTPDuserRequest()); - MTPDuserRequest &v(_userRequest()); - v.vid.read(from, end); - v.vfirst_name.read(from, end); - v.vlast_name.read(from, end); - v.vusername.read(from, end); - v.vaccess_hash.read(from, end); - v.vphone.read(from, end); - v.vphoto.read(from, end); - v.vstatus.read(from, end); - } break; - case mtpc_userForeign: _type = cons; { - if (!data) setData(new MTPDuserForeign()); - MTPDuserForeign &v(_userForeign()); - v.vid.read(from, end); - v.vfirst_name.read(from, end); - v.vlast_name.read(from, end); - v.vusername.read(from, end); - v.vaccess_hash.read(from, end); - v.vphoto.read(from, end); - v.vstatus.read(from, end); - } break; - case mtpc_userDeleted: _type = cons; { - if (!data) setData(new MTPDuserDeleted()); - MTPDuserDeleted &v(_userDeleted()); - v.vid.read(from, end); - v.vfirst_name.read(from, end); - v.vlast_name.read(from, end); - v.vusername.read(from, end); + if (v.has_access_hash()) { v.vaccess_hash.read(from, end); } else { v.vaccess_hash = MTPlong(); } + if (v.has_first_name()) { v.vfirst_name.read(from, end); } else { v.vfirst_name = MTPstring(); } + if (v.has_last_name()) { v.vlast_name.read(from, end); } else { v.vlast_name = MTPstring(); } + if (v.has_username()) { v.vusername.read(from, end); } else { v.vusername = MTPstring(); } + if (v.has_phone()) { v.vphone.read(from, end); } else { v.vphone = MTPstring(); } + if (v.has_photo()) { v.vphoto.read(from, end); } else { v.vphoto = MTPUserProfilePhoto(); } + if (v.has_status()) { v.vstatus.read(from, end); } else { v.vstatus = MTPUserStatus(); } + if (v.has_bot_info_version()) { v.vbot_info_version.read(from, end); } else { v.vbot_info_version = MTPint(); } } break; default: throw mtpErrorUnexpected(cons, "MTPuser"); } @@ -19028,97 +19173,37 @@ inline void MTPuser::write(mtpBuffer &to) const { const MTPDuserEmpty &v(c_userEmpty()); v.vid.write(to); } break; - case mtpc_userSelf: { - const MTPDuserSelf &v(c_userSelf()); + case mtpc_user: { + const MTPDuser &v(c_user()); + v.vflags.write(to); v.vid.write(to); - v.vfirst_name.write(to); - v.vlast_name.write(to); - v.vusername.write(to); - v.vphone.write(to); - v.vphoto.write(to); - v.vstatus.write(to); - } break; - case mtpc_userContact: { - const MTPDuserContact &v(c_userContact()); - v.vid.write(to); - v.vfirst_name.write(to); - v.vlast_name.write(to); - v.vusername.write(to); - v.vaccess_hash.write(to); - v.vphone.write(to); - v.vphoto.write(to); - v.vstatus.write(to); - } break; - case mtpc_userRequest: { - const MTPDuserRequest &v(c_userRequest()); - v.vid.write(to); - v.vfirst_name.write(to); - v.vlast_name.write(to); - v.vusername.write(to); - v.vaccess_hash.write(to); - v.vphone.write(to); - v.vphoto.write(to); - v.vstatus.write(to); - } break; - case mtpc_userForeign: { - const MTPDuserForeign &v(c_userForeign()); - v.vid.write(to); - v.vfirst_name.write(to); - v.vlast_name.write(to); - v.vusername.write(to); - v.vaccess_hash.write(to); - v.vphoto.write(to); - v.vstatus.write(to); - } break; - case mtpc_userDeleted: { - const MTPDuserDeleted &v(c_userDeleted()); - v.vid.write(to); - v.vfirst_name.write(to); - v.vlast_name.write(to); - v.vusername.write(to); + if (v.has_access_hash()) v.vaccess_hash.write(to); + if (v.has_first_name()) v.vfirst_name.write(to); + if (v.has_last_name()) v.vlast_name.write(to); + if (v.has_username()) v.vusername.write(to); + if (v.has_phone()) v.vphone.write(to); + if (v.has_photo()) v.vphoto.write(to); + if (v.has_status()) v.vstatus.write(to); + if (v.has_bot_info_version()) v.vbot_info_version.write(to); } break; } } inline MTPuser::MTPuser(mtpTypeId type) : mtpDataOwner(0), _type(type) { switch (type) { case mtpc_userEmpty: setData(new MTPDuserEmpty()); break; - case mtpc_userSelf: setData(new MTPDuserSelf()); break; - case mtpc_userContact: setData(new MTPDuserContact()); break; - case mtpc_userRequest: setData(new MTPDuserRequest()); break; - case mtpc_userForeign: setData(new MTPDuserForeign()); break; - case mtpc_userDeleted: setData(new MTPDuserDeleted()); break; + case mtpc_user: setData(new MTPDuser()); break; default: throw mtpErrorBadTypeId(type, "MTPuser"); } } inline MTPuser::MTPuser(MTPDuserEmpty *_data) : mtpDataOwner(_data), _type(mtpc_userEmpty) { } -inline MTPuser::MTPuser(MTPDuserSelf *_data) : mtpDataOwner(_data), _type(mtpc_userSelf) { -} -inline MTPuser::MTPuser(MTPDuserContact *_data) : mtpDataOwner(_data), _type(mtpc_userContact) { -} -inline MTPuser::MTPuser(MTPDuserRequest *_data) : mtpDataOwner(_data), _type(mtpc_userRequest) { -} -inline MTPuser::MTPuser(MTPDuserForeign *_data) : mtpDataOwner(_data), _type(mtpc_userForeign) { -} -inline MTPuser::MTPuser(MTPDuserDeleted *_data) : mtpDataOwner(_data), _type(mtpc_userDeleted) { +inline MTPuser::MTPuser(MTPDuser *_data) : mtpDataOwner(_data), _type(mtpc_user) { } inline MTPuser MTP_userEmpty(MTPint _id) { return MTPuser(new MTPDuserEmpty(_id)); } -inline MTPuser MTP_userSelf(MTPint _id, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username, const MTPstring &_phone, const MTPUserProfilePhoto &_photo, const MTPUserStatus &_status) { - return MTPuser(new MTPDuserSelf(_id, _first_name, _last_name, _username, _phone, _photo, _status)); -} -inline MTPuser MTP_userContact(MTPint _id, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username, const MTPlong &_access_hash, const MTPstring &_phone, const MTPUserProfilePhoto &_photo, const MTPUserStatus &_status) { - return MTPuser(new MTPDuserContact(_id, _first_name, _last_name, _username, _access_hash, _phone, _photo, _status)); -} -inline MTPuser MTP_userRequest(MTPint _id, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username, const MTPlong &_access_hash, const MTPstring &_phone, const MTPUserProfilePhoto &_photo, const MTPUserStatus &_status) { - return MTPuser(new MTPDuserRequest(_id, _first_name, _last_name, _username, _access_hash, _phone, _photo, _status)); -} -inline MTPuser MTP_userForeign(MTPint _id, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username, const MTPlong &_access_hash, const MTPUserProfilePhoto &_photo, const MTPUserStatus &_status) { - return MTPuser(new MTPDuserForeign(_id, _first_name, _last_name, _username, _access_hash, _photo, _status)); -} -inline MTPuser MTP_userDeleted(MTPint _id, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username) { - return MTPuser(new MTPDuserDeleted(_id, _first_name, _last_name, _username)); +inline MTPuser MTP_user(MTPint _flags, MTPint _id, const MTPlong &_access_hash, const MTPstring &_first_name, const MTPstring &_last_name, const MTPstring &_username, const MTPstring &_phone, const MTPUserProfilePhoto &_photo, const MTPUserStatus &_status, MTPint _bot_info_version) { + return MTPuser(new MTPDuser(_flags, _id, _access_hash, _first_name, _last_name, _username, _phone, _photo, _status, _bot_info_version)); } inline uint32 MTPuserProfilePhoto::innerLength() const { @@ -19399,7 +19484,7 @@ inline MTPchatFull::MTPchatFull() : mtpDataOwner(new MTPDchatFull()) { inline uint32 MTPchatFull::innerLength() const { const MTPDchatFull &v(c_chatFull()); - return v.vid.innerLength() + v.vparticipants.innerLength() + v.vchat_photo.innerLength() + v.vnotify_settings.innerLength() + v.vexported_invite.innerLength(); + return v.vid.innerLength() + v.vparticipants.innerLength() + v.vchat_photo.innerLength() + v.vnotify_settings.innerLength() + v.vexported_invite.innerLength() + v.vbot_info.innerLength(); } inline mtpTypeId MTPchatFull::type() const { return mtpc_chatFull; @@ -19414,6 +19499,7 @@ inline void MTPchatFull::read(const mtpPrime *&from, const mtpPrime *end, mtpTyp v.vchat_photo.read(from, end); v.vnotify_settings.read(from, end); v.vexported_invite.read(from, end); + v.vbot_info.read(from, end); } inline void MTPchatFull::write(mtpBuffer &to) const { const MTPDchatFull &v(c_chatFull()); @@ -19422,11 +19508,12 @@ inline void MTPchatFull::write(mtpBuffer &to) const { v.vchat_photo.write(to); v.vnotify_settings.write(to); v.vexported_invite.write(to); + v.vbot_info.write(to); } inline MTPchatFull::MTPchatFull(MTPDchatFull *_data) : mtpDataOwner(_data) { } -inline MTPchatFull MTP_chatFull(MTPint _id, const MTPChatParticipants &_participants, const MTPPhoto &_chat_photo, const MTPPeerNotifySettings &_notify_settings, const MTPExportedChatInvite &_exported_invite) { - return MTPchatFull(new MTPDchatFull(_id, _participants, _chat_photo, _notify_settings, _exported_invite)); +inline MTPchatFull MTP_chatFull(MTPint _id, const MTPChatParticipants &_participants, const MTPPhoto &_chat_photo, const MTPPeerNotifySettings &_notify_settings, const MTPExportedChatInvite &_exported_invite, const MTPVector &_bot_info) { + return MTPchatFull(new MTPDchatFull(_id, _participants, _chat_photo, _notify_settings, _exported_invite, _bot_info)); } inline MTPchatParticipant::MTPchatParticipant() : mtpDataOwner(new MTPDchatParticipant()) { @@ -19588,7 +19675,7 @@ inline uint32 MTPmessage::innerLength() const { } case mtpc_message: { const MTPDmessage &v(c_message()); - return v.vflags.innerLength() + v.vid.innerLength() + v.vfrom_id.innerLength() + v.vto_id.innerLength() + (v.has_fwd_from_id() ? v.vfwd_from_id.innerLength() : 0) + (v.has_fwd_date() ? v.vfwd_date.innerLength() : 0) + (v.has_reply_to_msg_id() ? v.vreply_to_msg_id.innerLength() : 0) + v.vdate.innerLength() + v.vmessage.innerLength() + v.vmedia.innerLength(); + return v.vflags.innerLength() + v.vid.innerLength() + v.vfrom_id.innerLength() + v.vto_id.innerLength() + (v.has_fwd_from_id() ? v.vfwd_from_id.innerLength() : 0) + (v.has_fwd_date() ? v.vfwd_date.innerLength() : 0) + (v.has_reply_to_msg_id() ? v.vreply_to_msg_id.innerLength() : 0) + v.vdate.innerLength() + v.vmessage.innerLength() + v.vmedia.innerLength() + (v.has_reply_markup() ? v.vreply_markup.innerLength() : 0); } case mtpc_messageService: { const MTPDmessageService &v(c_messageService()); @@ -19622,6 +19709,7 @@ inline void MTPmessage::read(const mtpPrime *&from, const mtpPrime *end, mtpType v.vdate.read(from, end); v.vmessage.read(from, end); v.vmedia.read(from, end); + if (v.has_reply_markup()) { v.vreply_markup.read(from, end); } else { v.vreply_markup = MTPReplyMarkup(); } } break; case mtpc_messageService: _type = cons; { if (!data) setData(new MTPDmessageService()); @@ -19654,6 +19742,7 @@ inline void MTPmessage::write(mtpBuffer &to) const { v.vdate.write(to); v.vmessage.write(to); v.vmedia.write(to); + if (v.has_reply_markup()) v.vreply_markup.write(to); } break; case mtpc_messageService: { const MTPDmessageService &v(c_messageService()); @@ -19683,8 +19772,8 @@ inline MTPmessage::MTPmessage(MTPDmessageService *_data) : mtpDataOwner(_data), inline MTPmessage MTP_messageEmpty(MTPint _id) { return MTPmessage(new MTPDmessageEmpty(_id)); } -inline MTPmessage MTP_message(MTPint _flags, MTPint _id, MTPint _from_id, const MTPPeer &_to_id, MTPint _fwd_from_id, MTPint _fwd_date, MTPint _reply_to_msg_id, MTPint _date, const MTPstring &_message, const MTPMessageMedia &_media) { - return MTPmessage(new MTPDmessage(_flags, _id, _from_id, _to_id, _fwd_from_id, _fwd_date, _reply_to_msg_id, _date, _message, _media)); +inline MTPmessage MTP_message(MTPint _flags, MTPint _id, MTPint _from_id, const MTPPeer &_to_id, MTPint _fwd_from_id, MTPint _fwd_date, MTPint _reply_to_msg_id, MTPint _date, const MTPstring &_message, const MTPMessageMedia &_media, const MTPReplyMarkup &_reply_markup) { + return MTPmessage(new MTPDmessage(_flags, _id, _from_id, _to_id, _fwd_from_id, _fwd_date, _reply_to_msg_id, _date, _message, _media, _reply_markup)); } inline MTPmessage MTP_messageService(MTPint _flags, MTPint _id, MTPint _from_id, const MTPPeer &_to_id, MTPint _date, const MTPMessageAction &_action) { return MTPmessage(new MTPDmessageService(_flags, _id, _from_id, _to_id, _date, _action)); @@ -20517,7 +20606,7 @@ inline MTPauth_authorization::MTPauth_authorization() : mtpDataOwner(new MTPDaut inline uint32 MTPauth_authorization::innerLength() const { const MTPDauth_authorization &v(c_auth_authorization()); - return v.vexpires.innerLength() + v.vuser.innerLength(); + return v.vuser.innerLength(); } inline mtpTypeId MTPauth_authorization::type() const { return mtpc_auth_authorization; @@ -20527,18 +20616,16 @@ inline void MTPauth_authorization::read(const mtpPrime *&from, const mtpPrime *e if (!data) setData(new MTPDauth_authorization()); MTPDauth_authorization &v(_auth_authorization()); - v.vexpires.read(from, end); v.vuser.read(from, end); } inline void MTPauth_authorization::write(mtpBuffer &to) const { const MTPDauth_authorization &v(c_auth_authorization()); - v.vexpires.write(to); v.vuser.write(to); } inline MTPauth_authorization::MTPauth_authorization(MTPDauth_authorization *_data) : mtpDataOwner(_data) { } -inline MTPauth_authorization MTP_auth_authorization(MTPint _expires, const MTPUser &_user) { - return MTPauth_authorization(new MTPDauth_authorization(_expires, _user)); +inline MTPauth_authorization MTP_auth_authorization(const MTPUser &_user) { + return MTPauth_authorization(new MTPDauth_authorization(_user)); } inline MTPauth_exportedAuthorization::MTPauth_exportedAuthorization() : mtpDataOwner(new MTPDauth_exportedAuthorization()) { @@ -20880,7 +20967,7 @@ inline MTPuserFull::MTPuserFull() : mtpDataOwner(new MTPDuserFull()) { inline uint32 MTPuserFull::innerLength() const { const MTPDuserFull &v(c_userFull()); - return v.vuser.innerLength() + v.vlink.innerLength() + v.vprofile_photo.innerLength() + v.vnotify_settings.innerLength() + v.vblocked.innerLength() + v.vreal_first_name.innerLength() + v.vreal_last_name.innerLength(); + return v.vuser.innerLength() + v.vlink.innerLength() + v.vprofile_photo.innerLength() + v.vnotify_settings.innerLength() + v.vblocked.innerLength() + v.vbot_info.innerLength(); } inline mtpTypeId MTPuserFull::type() const { return mtpc_userFull; @@ -20895,8 +20982,7 @@ inline void MTPuserFull::read(const mtpPrime *&from, const mtpPrime *end, mtpTyp v.vprofile_photo.read(from, end); v.vnotify_settings.read(from, end); v.vblocked.read(from, end); - v.vreal_first_name.read(from, end); - v.vreal_last_name.read(from, end); + v.vbot_info.read(from, end); } inline void MTPuserFull::write(mtpBuffer &to) const { const MTPDuserFull &v(c_userFull()); @@ -20905,13 +20991,12 @@ inline void MTPuserFull::write(mtpBuffer &to) const { v.vprofile_photo.write(to); v.vnotify_settings.write(to); v.vblocked.write(to); - v.vreal_first_name.write(to); - v.vreal_last_name.write(to); + v.vbot_info.write(to); } inline MTPuserFull::MTPuserFull(MTPDuserFull *_data) : mtpDataOwner(_data) { } -inline MTPuserFull MTP_userFull(const MTPUser &_user, const MTPcontacts_Link &_link, const MTPPhoto &_profile_photo, const MTPPeerNotifySettings &_notify_settings, MTPBool _blocked, const MTPstring &_real_first_name, const MTPstring &_real_last_name) { - return MTPuserFull(new MTPDuserFull(_user, _link, _profile_photo, _notify_settings, _blocked, _real_first_name, _real_last_name)); +inline MTPuserFull MTP_userFull(const MTPUser &_user, const MTPcontacts_Link &_link, const MTPPhoto &_profile_photo, const MTPPeerNotifySettings &_notify_settings, MTPBool _blocked, const MTPBotInfo &_bot_info) { + return MTPuserFull(new MTPDuserFull(_user, _link, _profile_photo, _notify_settings, _blocked, _bot_info)); } inline MTPcontact::MTPcontact() : mtpDataOwner(new MTPDcontact()) { @@ -22814,7 +22899,7 @@ inline MTPdcOption::MTPdcOption() : mtpDataOwner(new MTPDdcOption()) { inline uint32 MTPdcOption::innerLength() const { const MTPDdcOption &v(c_dcOption()); - return v.vid.innerLength() + v.vhostname.innerLength() + v.vip_address.innerLength() + v.vport.innerLength(); + return v.vflags.innerLength() + v.vid.innerLength() + v.vip_address.innerLength() + v.vport.innerLength(); } inline mtpTypeId MTPdcOption::type() const { return mtpc_dcOption; @@ -22824,22 +22909,22 @@ inline void MTPdcOption::read(const mtpPrime *&from, const mtpPrime *end, mtpTyp if (!data) setData(new MTPDdcOption()); MTPDdcOption &v(_dcOption()); + v.vflags.read(from, end); v.vid.read(from, end); - v.vhostname.read(from, end); v.vip_address.read(from, end); v.vport.read(from, end); } inline void MTPdcOption::write(mtpBuffer &to) const { const MTPDdcOption &v(c_dcOption()); + v.vflags.write(to); v.vid.write(to); - v.vhostname.write(to); v.vip_address.write(to); v.vport.write(to); } inline MTPdcOption::MTPdcOption(MTPDdcOption *_data) : mtpDataOwner(_data) { } -inline MTPdcOption MTP_dcOption(MTPint _id, const MTPstring &_hostname, const MTPstring &_ip_address, MTPint _port) { - return MTPdcOption(new MTPDdcOption(_id, _hostname, _ip_address, _port)); +inline MTPdcOption MTP_dcOption(MTPint _flags, MTPint _id, const MTPstring &_ip_address, MTPint _port) { + return MTPdcOption(new MTPDdcOption(_flags, _id, _ip_address, _port)); } inline MTPconfig::MTPconfig() : mtpDataOwner(new MTPDconfig()) { @@ -25637,6 +25722,175 @@ inline MTPmessages_stickerSet MTP_messages_stickerSet(const MTPStickerSet &_set, return MTPmessages_stickerSet(new MTPDmessages_stickerSet(_set, _packs, _documents)); } +inline MTPbotCommand::MTPbotCommand() : mtpDataOwner(new MTPDbotCommand()) { +} + +inline uint32 MTPbotCommand::innerLength() const { + const MTPDbotCommand &v(c_botCommand()); + return v.vcommand.innerLength() + v.vparams.innerLength() + v.vdescription.innerLength(); +} +inline mtpTypeId MTPbotCommand::type() const { + return mtpc_botCommand; +} +inline void MTPbotCommand::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != mtpc_botCommand) throw mtpErrorUnexpected(cons, "MTPbotCommand"); + + if (!data) setData(new MTPDbotCommand()); + MTPDbotCommand &v(_botCommand()); + v.vcommand.read(from, end); + v.vparams.read(from, end); + v.vdescription.read(from, end); +} +inline void MTPbotCommand::write(mtpBuffer &to) const { + const MTPDbotCommand &v(c_botCommand()); + v.vcommand.write(to); + v.vparams.write(to); + v.vdescription.write(to); +} +inline MTPbotCommand::MTPbotCommand(MTPDbotCommand *_data) : mtpDataOwner(_data) { +} +inline MTPbotCommand MTP_botCommand(const MTPstring &_command, const MTPstring &_params, const MTPstring &_description) { + return MTPbotCommand(new MTPDbotCommand(_command, _params, _description)); +} + +inline uint32 MTPbotInfo::innerLength() const { + switch (_type) { + case mtpc_botInfo: { + const MTPDbotInfo &v(c_botInfo()); + return v.vuser_id.innerLength() + v.vversion.innerLength() + v.vshare_text.innerLength() + v.vdescription.innerLength() + v.vcommands.innerLength(); + } + } + return 0; +} +inline mtpTypeId MTPbotInfo::type() const { + if (!_type) throw mtpErrorUninitialized(); + return _type; +} +inline void MTPbotInfo::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != _type) setData(0); + switch (cons) { + case mtpc_botInfoEmpty: _type = cons; break; + case mtpc_botInfo: _type = cons; { + if (!data) setData(new MTPDbotInfo()); + MTPDbotInfo &v(_botInfo()); + v.vuser_id.read(from, end); + v.vversion.read(from, end); + v.vshare_text.read(from, end); + v.vdescription.read(from, end); + v.vcommands.read(from, end); + } break; + default: throw mtpErrorUnexpected(cons, "MTPbotInfo"); + } +} +inline void MTPbotInfo::write(mtpBuffer &to) const { + switch (_type) { + case mtpc_botInfo: { + const MTPDbotInfo &v(c_botInfo()); + v.vuser_id.write(to); + v.vversion.write(to); + v.vshare_text.write(to); + v.vdescription.write(to); + v.vcommands.write(to); + } break; + } +} +inline MTPbotInfo::MTPbotInfo(mtpTypeId type) : mtpDataOwner(0), _type(type) { + switch (type) { + case mtpc_botInfoEmpty: break; + case mtpc_botInfo: setData(new MTPDbotInfo()); break; + default: throw mtpErrorBadTypeId(type, "MTPbotInfo"); + } +} +inline MTPbotInfo::MTPbotInfo(MTPDbotInfo *_data) : mtpDataOwner(_data), _type(mtpc_botInfo) { +} +inline MTPbotInfo MTP_botInfoEmpty() { + return MTPbotInfo(mtpc_botInfoEmpty); +} +inline MTPbotInfo MTP_botInfo(MTPint _user_id, MTPint _version, const MTPstring &_share_text, const MTPstring &_description, const MTPVector &_commands) { + return MTPbotInfo(new MTPDbotInfo(_user_id, _version, _share_text, _description, _commands)); +} + +inline MTPkeyboardButton::MTPkeyboardButton() : mtpDataOwner(new MTPDkeyboardButton()) { +} + +inline uint32 MTPkeyboardButton::innerLength() const { + const MTPDkeyboardButton &v(c_keyboardButton()); + return v.vtext.innerLength(); +} +inline mtpTypeId MTPkeyboardButton::type() const { + return mtpc_keyboardButton; +} +inline void MTPkeyboardButton::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != mtpc_keyboardButton) throw mtpErrorUnexpected(cons, "MTPkeyboardButton"); + + if (!data) setData(new MTPDkeyboardButton()); + MTPDkeyboardButton &v(_keyboardButton()); + v.vtext.read(from, end); +} +inline void MTPkeyboardButton::write(mtpBuffer &to) const { + const MTPDkeyboardButton &v(c_keyboardButton()); + v.vtext.write(to); +} +inline MTPkeyboardButton::MTPkeyboardButton(MTPDkeyboardButton *_data) : mtpDataOwner(_data) { +} +inline MTPkeyboardButton MTP_keyboardButton(const MTPstring &_text) { + return MTPkeyboardButton(new MTPDkeyboardButton(_text)); +} + +inline MTPkeyboardButtonRow::MTPkeyboardButtonRow() : mtpDataOwner(new MTPDkeyboardButtonRow()) { +} + +inline uint32 MTPkeyboardButtonRow::innerLength() const { + const MTPDkeyboardButtonRow &v(c_keyboardButtonRow()); + return v.vbuttons.innerLength(); +} +inline mtpTypeId MTPkeyboardButtonRow::type() const { + return mtpc_keyboardButtonRow; +} +inline void MTPkeyboardButtonRow::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != mtpc_keyboardButtonRow) throw mtpErrorUnexpected(cons, "MTPkeyboardButtonRow"); + + if (!data) setData(new MTPDkeyboardButtonRow()); + MTPDkeyboardButtonRow &v(_keyboardButtonRow()); + v.vbuttons.read(from, end); +} +inline void MTPkeyboardButtonRow::write(mtpBuffer &to) const { + const MTPDkeyboardButtonRow &v(c_keyboardButtonRow()); + v.vbuttons.write(to); +} +inline MTPkeyboardButtonRow::MTPkeyboardButtonRow(MTPDkeyboardButtonRow *_data) : mtpDataOwner(_data) { +} +inline MTPkeyboardButtonRow MTP_keyboardButtonRow(const MTPVector &_buttons) { + return MTPkeyboardButtonRow(new MTPDkeyboardButtonRow(_buttons)); +} + +inline MTPreplyMarkup::MTPreplyMarkup() : mtpDataOwner(new MTPDreplyKeyboardMarkup()) { +} + +inline uint32 MTPreplyMarkup::innerLength() const { + const MTPDreplyKeyboardMarkup &v(c_replyKeyboardMarkup()); + return v.vrows.innerLength(); +} +inline mtpTypeId MTPreplyMarkup::type() const { + return mtpc_replyKeyboardMarkup; +} +inline void MTPreplyMarkup::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != mtpc_replyKeyboardMarkup) throw mtpErrorUnexpected(cons, "MTPreplyMarkup"); + + if (!data) setData(new MTPDreplyKeyboardMarkup()); + MTPDreplyKeyboardMarkup &v(_replyKeyboardMarkup()); + v.vrows.read(from, end); +} +inline void MTPreplyMarkup::write(mtpBuffer &to) const { + const MTPDreplyKeyboardMarkup &v(c_replyKeyboardMarkup()); + v.vrows.write(to); +} +inline MTPreplyMarkup::MTPreplyMarkup(MTPDreplyKeyboardMarkup *_data) : mtpDataOwner(_data) { +} +inline MTPreplyMarkup MTP_replyKeyboardMarkup(const MTPVector &_rows) { + return MTPreplyMarkup(new MTPDreplyKeyboardMarkup(_rows)); +} + // Human-readable text serialization #if (defined _DEBUG || defined _WITH_DEBUG) diff --git a/Telegram/SourceFiles/mtproto/scheme.tl b/Telegram/SourceFiles/mtproto/scheme.tl index 128aff6f62..26b003bda7 100644 --- a/Telegram/SourceFiles/mtproto/scheme.tl +++ b/Telegram/SourceFiles/mtproto/scheme.tl @@ -193,11 +193,6 @@ fileLocationUnavailable#7c596b46 volume_id:long local_id:int secret:long = FileL fileLocation#53d69076 dc_id:int volume_id:long local_id:int secret:long = FileLocation; userEmpty#200250ba id:int = User; -userSelf#1c60e608 id:int first_name:string last_name:string username:string phone:string photo:UserProfilePhoto status:UserStatus = User; -userContact#cab35e18 id:int first_name:string last_name:string username:string access_hash:long phone:string photo:UserProfilePhoto status:UserStatus = User; -userRequest#d9ccc4ef id:int first_name:string last_name:string username:string access_hash:long phone:string photo:UserProfilePhoto status:UserStatus = User; -userForeign#75cf7a8 id:int first_name:string last_name:string username:string access_hash:long photo:UserProfilePhoto status:UserStatus = User; -userDeleted#d6016d7a id:int first_name:string last_name:string username:string = User; userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto; userProfilePhoto#d559d8c8 photo_id:long photo_small:FileLocation photo_big:FileLocation = UserProfilePhoto; @@ -210,7 +205,7 @@ chatEmpty#9ba2d800 id:int = Chat; chat#6e9c9bc7 id:int title:string photo:ChatPhoto participants_count:int date:int left:Bool version:int = Chat; chatForbidden#fb0ccc41 id:int title:string date:int = Chat; -chatFull#cade0791 id:int participants:ChatParticipants chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite = ChatFull; +chatFull#2e02a614 id:int participants:ChatParticipants chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector = ChatFull; chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant; @@ -221,7 +216,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto; chatPhoto#6153276a photo_small:FileLocation photo_big:FileLocation = ChatPhoto; messageEmpty#83e5de54 id:int = Message; -message#a7ab1991 flags:# id:int from_id:int to_id:Peer fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int date:int message:string media:MessageMedia = Message; +message#c3060325 flags:# id:int from_id:int to_id:Peer fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int date:int message:string media:MessageMedia reply_markup:flags.6?ReplyMarkup = Message; messageService#1d86f70e flags:int id:int from_id:int to_id:Peer date:int action:MessageAction = Message; messageMediaEmpty#3ded6320 = MessageMedia; @@ -258,7 +253,7 @@ auth.checkedPhone#811ea28e phone_registered:Bool = auth.CheckedPhone; auth.sentCode#efed51d9 phone_registered:Bool phone_code_hash:string send_call_timeout:int is_password:Bool = auth.SentCode; -auth.authorization#f6b673a4 expires:int user:User = auth.Authorization; +auth.authorization#ff036af1 user:User = auth.Authorization; auth.exportedAuthorization#df969c2d id:int bytes:bytes = auth.ExportedAuthorization; @@ -280,7 +275,7 @@ peerNotifySettings#8d5e11ee mute_until:int sound:string show_previews:Bool event wallPaper#ccb03657 id:int title:string sizes:Vector color:int = WallPaper; -userFull#771095da user:User link:contacts.Link profile_photo:Photo notify_settings:PeerNotifySettings blocked:Bool real_first_name:string real_last_name:string = UserFull; +userFull#5a89ac5b user:User link:contacts.Link profile_photo:Photo notify_settings:PeerNotifySettings blocked:Bool bot_info:BotInfo = UserFull; contact#f911c994 user_id:int mutual:Bool = Contact; @@ -363,7 +358,7 @@ photos.photo#20212ca8 photo:Photo users:Vector = photos.Photo; upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File; -dcOption#2ec2a43c id:int hostname:string ip_address:string port:int = DcOption; +dcOption#5d8c6cc flags:# id:int ip_address:string port:int = DcOption; config#4e32b894 date:int expires:int test_mode:Bool this_dc:int dc_options:Vector chat_size_max:int broadcast_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int disabled_features:Vector = Config; @@ -596,6 +591,19 @@ stickerSet#a7a43b17 id:long access_hash:long title:string short_name:string = St messages.stickerSet#b60a24a6 set:StickerSet packs:Vector documents:Vector = messages.StickerSet; +user#22e49072 flags:# id:int access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int = User; + +botCommand#b79d22ab command:string params:string description:string = BotCommand; + +botInfoEmpty#bb2e37ce = BotInfo; +botInfo#9cf585d user_id:int version:int share_text:string description:string commands:Vector = BotInfo; + +keyboardButton#a2fa4880 text:string = KeyboardButton; + +keyboardButtonRow#77608b83 buttons:Vector = KeyboardButtonRow; + +replyKeyboardMarkup#d59bfc31 rows:Vector = ReplyMarkup; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -647,8 +655,8 @@ messages.deleteHistory#f4f8fb61 peer:InputPeer offset:int = messages.AffectedHis messages.deleteMessages#a5f18925 id:Vector = messages.AffectedMessages; messages.receivedMessages#5a954c0 max_id:int = Vector; messages.setTyping#a3825e50 peer:InputPeer action:SendMessageAction = Bool; -messages.sendMessage#9add8f26 flags:# peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long = messages.SentMessage; -messages.sendMedia#2d7923b1 flags:# peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia random_id:long = Updates; +messages.sendMessage#fc55e6b5 flags:# peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup = messages.SentMessage; +messages.sendMedia#c8f16791 flags:# peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia random_id:long reply_markup:flags.2?ReplyMarkup = Updates; messages.forwardMessages#55e1728d peer:InputPeer id:Vector random_id:Vector = Updates; messages.getChats#3c6aa187 id:Vector = messages.Chats; messages.getFullChat#3b831c66 chat_id:int = messages.ChatFull; @@ -736,6 +744,8 @@ messages.getAllStickers#aa3bc868 hash:string = messages.AllStickers; account.updateDeviceLocked#38df3532 period:int = Bool; +auth.importBotAuthorization#67a3ff2c flags:int api_id:int api_hash:string bot_auth_token:string = auth.Authorization; + messages.getWebPagePreview#25223e24 message:string = MessageMedia; account.getAuthorizations#e320c158 = account.Authorizations; diff --git a/Telegram/SourceFiles/profilewidget.cpp b/Telegram/SourceFiles/profilewidget.cpp index f77ef4c4e4..17d6702124 100644 --- a/Telegram/SourceFiles/profilewidget.cpp +++ b/Telegram/SourceFiles/profilewidget.cpp @@ -325,13 +325,13 @@ void ProfileInner::updateOnlineDisplayTimer() { if (_peerChat->participants.isEmpty()) return; for (ChatData::Participants::const_iterator i = _peerChat->participants.cbegin(), e = _peerChat->participants.cend(); i != e; ++i) { - int32 onlineWillChangeIn = App::onlineWillChangeIn(i.key()->onlineTill, t); + int32 onlineWillChangeIn = App::onlineWillChangeIn(i.key(), t); if (onlineWillChangeIn < minIn) { minIn = onlineWillChangeIn; } } } else { - minIn = App::onlineWillChangeIn(_peerUser->onlineTill, t); + minIn = App::onlineWillChangeIn(_peerUser, t); } App::main()->updateOnlineDisplayIn(minIn * 1000); } @@ -354,13 +354,13 @@ void ProfileInner::reorderParticipants() { bool onlyMe = true; for (ChatData::Participants::const_iterator i = _peerChat->participants.cbegin(), e = _peerChat->participants.cend(); i != e; ++i) { UserData *user = i.key(); - int32 until = App::onlineForSort(user->onlineTill, t); + int32 until = App::onlineForSort(user, t); Participants::iterator before = _participants.begin(); if (user != self) { if (before != _participants.end() && (*before) == self) { ++before; } - while (before != _participants.end() && App::onlineForSort((*before)->onlineTill, t) >= until) { + while (before != _participants.end() && App::onlineForSort(*before, t) >= until) { ++before; } if (until > t && onlyMe) onlyMe = false; diff --git a/Telegram/SourceFiles/settings.h b/Telegram/SourceFiles/settings.h index c9ee6c3c84..0b857dd5b7 100644 --- a/Telegram/SourceFiles/settings.h +++ b/Telegram/SourceFiles/settings.h @@ -53,11 +53,11 @@ inline bool rtl() { } struct mtpDcOption { - mtpDcOption(int _id, const string &_host, const string &_ip, int _port) : id(_id), host(_host), ip(_ip), port(_port) { + mtpDcOption(int id, int flags, const string &ip, int port) : id(id), flags(flags), ip(ip), port(port) { } int id; - string host; + int flags; string ip; int port; }; diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index 2332171f3d..8a3f56eb13 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -201,10 +201,58 @@ void UserData::setPhone(const QString &newPhone) { ++nameVersion; } +void UserData::setBotInfoVersion(int32 version) { + if (!botInfo) { + botInfo = new BotInfo(); + botInfo->version = version; + } else if (botInfo->version < version) { + botInfo->commands.clear(); + botInfo->description.clear(); + botInfo->shareText.clear(); + botInfo->version = version; + } +} +void UserData::setBotInfo(const MTPBotInfo &info) { + switch (info.type()) { + case mtpc_botInfoEmpty: + delete botInfo; + botInfo = 0; + break; + case mtpc_botInfo: { + const MTPDbotInfo &d(info.c_botInfo()); + if (d.vuser_id.v != id) return; + setBotInfoVersion(d.vversion.v); + if (botInfo->version > d.vversion.v) return; + botInfo->description = qs(d.vdescription); + botInfo->shareText = qs(d.vshare_text); + + const QVector &v(d.vcommands.c_vector().v); + botInfo->commands.clear(); + botInfo->commands.reserve(v.size()); + for (int32 i = 0, l = v.size(); i < l; ++i) { + if (v.at(i).type() == mtpc_botCommand) { + botInfo->commands.push_back(BotCommand(qs(v.at(i).c_botCommand().vcommand), qs(v.at(i).c_botCommand().vparams), qs(v.at(i).c_botCommand().vdescription))); + } + } + } break; + } +} + void UserData::nameUpdated() { nameText.setText(st::msgNameFont, name, _textNameOptions); } +void UserData::madeAction() { + int32 t = unixtime(); + if (onlineTill <= 0 && -onlineTill < t) { + onlineTill = -t - SetOnlineAfterActivity; + if (App::main()) App::main()->peerUpdated(this); + } else if (onlineTill > 0 && onlineTill < t + 1) { + onlineTill = t + SetOnlineAfterActivity; + if (App::main()) App::main()->peerUpdated(this); + } +} + void ChatData::setPhoto(const MTPChatPhoto &p, const PhotoId &phId) { switch (p.type()) { case mtpc_chatPhoto: { diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index d27d6dee89..733475b25e 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -118,15 +118,30 @@ private: PeerData *_peer; }; +struct BotCommand { + BotCommand(const QString &command, const QString ¶ms, const QString &description) : command(command), params(params), description(description) { + } + QString command, params, description; +}; +struct BotInfo { + int32 version; + QString shareText, description; + QList commands; +}; + struct PhotoData; struct UserData : public PeerData { - UserData(const PeerId &id) : PeerData(id), lnk(new PeerLink(this)), onlineTill(0), contact(-1), photosCount(-1) { + UserData(const PeerId &id) : PeerData(id), lnk(new PeerLink(this)), photoId(0), onlineTill(0), contact(-1), photosCount(-1), botInfo(0) { } void setPhoto(const MTPUserProfilePhoto &photo); void setName(const QString &first, const QString &last, const QString &phoneName, const QString &username); void setPhone(const QString &newPhone); + void setBotInfoVersion(int32 version); + void setBotInfo(const MTPBotInfo &info); void nameUpdated(); + void madeAction(); // pseudo-online + QString firstName; QString lastName; QString username; @@ -140,6 +155,8 @@ struct UserData : public PeerData { typedef QList Photos; Photos photos; int32 photosCount; // -1 not loaded, 0 all loaded + + BotInfo *botInfo; }; struct ChatData : public PeerData { @@ -164,6 +181,10 @@ struct ChatData : public PeerData { // geo }; +inline int32 newMessageFlags(PeerData *p) { + return (p->input.type() == mtpc_inputPeerSelf) ? 0 : (((p->chat || !p->asUser()->botInfo) ? MTPDmessage_flag_unread : 0) | MTPDmessage_flag_out); +} + typedef QMap PreparedPhotoThumbs; struct PhotoData { PhotoData(const PhotoId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr()) : diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h index 790a84833f..a27937f24e 100644 --- a/Telegram/SourceFiles/types.h +++ b/Telegram/SourceFiles/types.h @@ -233,7 +233,7 @@ QString rusKeyboardLayoutSwitch(const QString &from); enum DataBlockId { dbiKey = 0x00, dbiUser = 0x01, - dbiDcOption = 0x02, + dbiDcOptionOld = 0x02, dbiMaxGroupCount = 0x03, dbiMutePeer = 0x04, dbiSendKey = 0x05, @@ -270,6 +270,7 @@ enum DataBlockId { dbiRecentEmojis = 0x24, dbiEmojiVariants = 0x25, dbiRecentStickers = 0x26, + dbiDcOption = 0x27, dbiEncryptedWithSalt = 333, dbiEncrypted = 444, diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp index a373791ea2..ea6ba43b9c 100644 --- a/Telegram/SourceFiles/window.cpp +++ b/Telegram/SourceFiles/window.cpp @@ -606,7 +606,8 @@ void Window::sendServiceHistoryRequest() { UserData *user = App::userLoaded(ServiceUserId); if (!user) { - user = App::feedUsers(MTP_vector(1, MTP_userRequest(MTP_int(ServiceUserId), MTP_string("Telegram"), MTP_string(""), MTP_string(""), MTP_long(-1), MTP_string("42777"), MTP_userProfilePhotoEmpty(), MTP_userStatusRecently()))); + int32 userFlags = MTPDuser::flag_first_name | MTPDuser::flag_phone | MTPDuser::flag_status; + user = App::feedUsers(MTP_vector(1, MTP_user(MTP_int(userFlags), MTP_int(ServiceUserId), MTPlong(), MTP_string("Telegram"), MTPstring(), MTPstring(), MTP_string("42777"), MTP_userProfilePhotoEmpty(), MTP_userStatusRecently(), MTPint()))); } _serviceHistoryRequest = MTP::send(MTPmessages_GetHistory(user->input, MTP_int(0), MTP_int(0), MTP_int(1)), main->rpcDone(&MainWidget::serviceHistoryDone), main->rpcFail(&MainWidget::serviceHistoryFail)); }