Skip to content

Commit

Permalink
Update scheme for special export methods.
Browse files Browse the repository at this point in the history
Export all saved contacts.
  • Loading branch information
john-preston committed Jun 16, 2018
1 parent 241fee8 commit 9d02e53
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 51 deletions.
10 changes: 7 additions & 3 deletions Telegram/Resources/scheme.tl
Original file line number Diff line number Diff line change
Expand Up @@ -843,8 +843,6 @@ webDocumentNoProxy#f9c8bcc6 url:string size:int mime_type:string attributes:Vect
inputWebDocument#9bed434d url:string size:int mime_type:string attributes:Vector<DocumentAttribute> = InputWebDocument;

inputWebFileLocation#c239d686 url:string access_hash:long = InputWebFileLocation;
inputWebFileGeoPointLocation#66275a62 geo_point:InputGeoPoint w:int h:int zoom:int scale:int = InputWebFileLocation;
inputWebFileGeoMessageLocation#553f32eb peer:InputPeer msg_id:int w:int h:int zoom:int scale:int = InputWebFileLocation;

upload.webFile#21e753bc size:int mime_type:string file_type:storage.FileType mtime:int bytes:bytes = upload.WebFile;

Expand Down Expand Up @@ -1014,20 +1012,24 @@ account.sentEmailCode#811f854f email_pattern:string length:int = account.SentEma
help.deepLinkInfoEmpty#66afa166 = help.DeepLinkInfo;
help.deepLinkInfo#6a4ee832 flags:# update_app:flags.0?true message:string entities:flags.1?Vector<MessageEntity> = help.DeepLinkInfo;

savedPhoneContact#1142bd56 phone:string first_name:string last_name:string date:int = SavedContact;

account.takeout#4dba4501 id:long = account.Takeout;

---functions---

invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
invokeAfterMsgs#3dc4b4f0 {X:Type} msg_ids:Vector<long> query:!X = X;
initConnection#785188b8 {X:Type} flags:# api_id:int device_model:string system_version:string app_version:string system_lang_code:string lang_pack:string lang_code:string proxy:flags.0?InputClientProxy query:!X = X;
invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X;
invokeWithoutUpdates#bf9459b7 {X:Type} query:!X = X;
invokeWithTakeout#aca9fd2e {X:Type} takeout_id:long query:!X = X;

auth.sendCode#86aef0ec flags:# allow_flashcall:flags.0?true phone_number:string current_number:flags.0?Bool api_id:int api_hash:string = auth.SentCode;
auth.signUp#1b067634 phone_number:string phone_code_hash:string phone_code:string first_name:string last_name:string = auth.Authorization;
auth.signIn#bcd51581 phone_number:string phone_code_hash:string phone_code:string = auth.Authorization;
auth.logOut#5717da40 = Bool;
auth.resetAuthorizations#9fab0d1a = Bool;
auth.sendInvites#771c1d97 phone_numbers:Vector<string> message:string = Bool;
auth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization;
auth.importAuthorization#e3ef9613 id:int bytes:bytes = auth.Authorization;
auth.bindTempAuthKey#cdd42a05 perm_auth_key_id:long nonce:long expires_at:int encrypted_message:bytes = Bool;
Expand Down Expand Up @@ -1079,6 +1081,7 @@ account.sendVerifyPhoneCode#823380b4 flags:# allow_flashcall:flags.0?true phone_
account.verifyPhone#4dd3a7f6 phone_number:string phone_code_hash:string phone_code:string = Bool;
account.sendVerifyEmailCode#7011509f email:string = account.SentEmailCode;
account.verifyEmail#ecba39db email:string code:string = Bool;
account.initTakeoutSession#f05b4804 flags:# contacts:flags.0?true message_users:flags.1?true message_chats:flags.2?true message_megagroups:flags.3?true message_channels:flags.4?true files:flags.5?true file_max_size:flags.5?int = account.Takeout;

users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
Expand All @@ -1099,6 +1102,7 @@ contacts.resolveUsername#f93ccba3 username:string = contacts.ResolvedPeer;
contacts.getTopPeers#d4982db5 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true groups:flags.10?true channels:flags.15?true offset:int limit:int hash:int = contacts.TopPeers;
contacts.resetTopPeerRating#1ae373ac category:TopPeerCategory peer:InputPeer = Bool;
contacts.resetSaved#879537f1 = Bool;
contacts.getSaved#82f1e39f = Vector<SavedContact>;

messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
messages.getDialogs#191ba9c5 flags:# exclude_pinned:flags.0?true offset_date:int offset_id:int offset_peer:InputPeer limit:int = messages.Dialogs;
Expand Down
3 changes: 3 additions & 0 deletions Telegram/SourceFiles/base/bytes.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,7 @@ vector concatenate(SpanRange args) {
return result;
}

// Implemented in base/openssl_help.h
void set_random(span destination);

} // namespace bytes
37 changes: 31 additions & 6 deletions Telegram/SourceFiles/export/data/export_data_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,23 @@ ContactsList ParseContactsList(const MTPcontacts_Contacts &data) {
return result;
}

ContactsList ParseContactsList(const MTPVector<MTPSavedContact> &data) {
auto result = ContactsList();
result.list.reserve(data.v.size());
for (const auto &contact : data.v) {
auto info = contact.match([](const MTPDsavedPhoneContact &data) {
auto info = ContactInfo();
info.firstName = ParseString(data.vfirst_name);
info.lastName = ParseString(data.vlast_name);
info.phoneNumber = ParseString(data.vphone);
info.date = data.vdate.v;
return info;
});
result.list.push_back(std::move(info));
}
return result;
}

std::vector<int> SortedContactsIndices(const ContactsList &data) {
const auto names = ranges::view::all(
data.list
Expand Down Expand Up @@ -890,14 +907,19 @@ DialogsInfo ParseDialogsInfo(const MTPmessages_Dialogs &data) {
const auto peerId = ParsePeerId(fields.vpeer);
const auto peerIt = peers.find(peerId);
if (peerIt != end(peers)) {
using Type = DialogInfo::Type;
const auto &peer = peerIt->second;
info.type = peer.user()
? DialogInfo::Type::Personal
: peer.chat()->broadcast
? DialogInfo::Type::Channel
: peer.chat()->username.isEmpty()
? DialogInfo::Type::PrivateGroup
: DialogInfo::Type::PublicGroup;
? (peer.user()->isBot
? Type::Bot
: Type::Personal)
: (peer.chat()->broadcast
? (peer.chat()->username.isEmpty()
? Type::PrivateChannel
: Type::PublicChannel)
: (peer.chat()->username.isEmpty()
? Type::PrivateGroup
: Type::PublicGroup));
info.name = peer.name();
info.input = peer.input();
}
Expand Down Expand Up @@ -940,6 +962,9 @@ Utf8String FormatDateTime(
QChar dateSeparator,
QChar timeSeparator,
QChar separator) {
if (!date) {
return Utf8String();
}
const auto value = QDateTime::fromTime_t(date);
return (QString("%1") + dateSeparator + "%2" + dateSeparator + "%3"
+ separator + "%4" + timeSeparator + "%5" + timeSeparator + "%6"
Expand Down
6 changes: 5 additions & 1 deletion Telegram/SourceFiles/export/data/export_data_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ struct ContactInfo {
Utf8String firstName;
Utf8String lastName;
Utf8String phoneNumber;
TimeId date = 0;

Utf8String name() const;
};
Expand Down Expand Up @@ -196,6 +197,7 @@ struct ContactsList {
};

ContactsList ParseContactsList(const MTPcontacts_Contacts &data);
ContactsList ParseContactsList(const MTPVector<MTPSavedContact> &data);
std::vector<int> SortedContactsIndices(const ContactsList &data);

struct Session {
Expand Down Expand Up @@ -394,9 +396,11 @@ struct DialogInfo {
enum class Type {
Unknown,
Personal,
Bot,
PrivateGroup,
PublicGroup,
Channel,
PrivateChannel,
PublicChannel,
};
Type type = Type::Unknown;
Utf8String name;
Expand Down
96 changes: 75 additions & 21 deletions Telegram/SourceFiles/export/export_api_wrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ For license and copyright information please follow this link:
#include "export/data/export_data_types.h"
#include "export/output/export_output_file.h"
#include "mtproto/rpc_sender.h"
#include "base/bytes.h"

#include <deque>

Expand All @@ -23,6 +24,7 @@ constexpr auto kFileRequestsCount = 2;
constexpr auto kFileNextRequestDelay = TimeMs(20);
constexpr auto kChatsSliceLimit = 100;
constexpr auto kMessagesSliceLimit = 100;
constexpr auto kFileMaxSize = 1500 * 1024 * 1024;

bool WillLoadFile(const Data::File &file) {
return file.relativePath.isEmpty()
Expand Down Expand Up @@ -102,23 +104,29 @@ ApiWrap::DialogsProcess::Single::Single(const Data::DialogInfo &info)

template <typename Request>
auto ApiWrap::mainRequest(Request &&request) {
return std::move(_mtp.request(
std::move(request)
).fail([=](RPCError &&result) {
Expects(_takeoutId.has_value());

return std::move(_mtp.request(MTPInvokeWithTakeout<Request>(
MTP_long(*_takeoutId),
request
)).fail([=](RPCError &&result) {
error(std::move(result));
}).toDC(MTP::ShiftDcId(0, MTP::kExportDcShift)));
}

auto ApiWrap::fileRequest(const Data::FileLocation &location, int offset) {
Expects(location.dcId != 0);

return std::move(_mtp.request(MTPupload_GetFile(
location.data,
MTP_int(offset),
MTP_int(kFileChunkSize)
Expects(_takeoutId.has_value());

return std::move(_mtp.request(MTPInvokeWithTakeout<MTPupload_GetFile>(
MTP_long(*_takeoutId),
MTPupload_GetFile(
location.data,
MTP_int(offset),
MTP_int(kFileChunkSize))
)).fail([=](RPCError &&result) {
error(std::move(result));
}).toDC(MTP::ShiftDcId(location.dcId, MTP::kExportDcShift)));
}).toDC(MTP::ShiftDcId(location.dcId, MTP::kExportMediaDcShift)));
}

ApiWrap::ApiWrap(Fn<void(FnMut<void()>)> runner)
Expand All @@ -129,10 +137,57 @@ rpl::producer<RPCError> ApiWrap::errors() const {
return _errors.events();
}

void ApiWrap::startExport(const Settings &settings) {
void ApiWrap::startExport(
const Settings &settings,
FnMut<void()> done) {
Expects(_settings == nullptr);

_settings = std::make_unique<Settings>(settings);
startMainSession(std::move(done));
}

void ApiWrap::startMainSession(FnMut<void()> done) {
auto sizeLimit = _settings->defaultMedia.sizeLimit;
auto hasFiles = _settings->defaultMedia.types != 0;
for (const auto &item : _settings->customMedia) {
sizeLimit = std::max(sizeLimit, item.second.sizeLimit);
hasFiles = hasFiles || (item.second.types != 0);
}
if (!sizeLimit) {
hasFiles = false;
}

using Type = Settings::Type;
using Flag = MTPaccount_InitTakeoutSession::Flag;
const auto flags = Flag(0)
| (_settings->types & Type::Contacts ? Flag::f_contacts : Flag(0))
| (hasFiles ? Flag::f_files : Flag(0))
| (sizeLimit < kFileMaxSize ? Flag::f_file_max_size : Flag(0))
| (_settings->types & (Type::PersonalChats | Type::BotChats)
? Flag::f_message_users
: Flag(0))
| (_settings->types & Type::PrivateGroups
? (Flag::f_message_chats | Flag::f_message_megagroups)
: Flag(0))
| (_settings->types & Type::PublicGroups
? Flag::f_message_megagroups
: Flag(0))
| (_settings->types & (Type::PrivateChannels | Type::PublicChannels)
? Flag::f_message_channels
: Flag(0));

_mtp.request(MTPaccount_InitTakeoutSession(
MTP_flags(flags),
MTP_int(sizeLimit)
)).done([=, done = std::move(done)](
const MTPaccount_Takeout &result) mutable {
_takeoutId = result.match([](const MTPDaccount_takeout &data) {
return data.vid.v;
});
done();
}).fail([=](RPCError &&result) {
error(std::move(result));
}).toDC(MTP::ShiftDcId(0, MTP::kExportDcShift)).send();
}

void ApiWrap::requestPersonalInfo(FnMut<void(Data::PersonalInfo&&)> done) {
Expand Down Expand Up @@ -266,16 +321,10 @@ void ApiWrap::finishUserpics() {
}

void ApiWrap::requestContacts(FnMut<void(Data::ContactsList&&)> done) {
const auto hash = 0;
mainRequest(MTPcontacts_GetContacts(
MTP_int(hash)
mainRequest(MTPcontacts_GetSaved(
)).done([=, done = std::move(done)](
const MTPcontacts_Contacts &result) mutable {
if (result.type() == mtpc_contacts_contacts) {
done(Data::ParseContactsList(result));
} else {
error("Bad contacts type.");
}
const MTPVector<MTPSavedContact> &result) mutable {
done(Data::ParseContactsList(result));
}).send();
}

Expand Down Expand Up @@ -354,12 +403,16 @@ void ApiWrap::appendDialogsSlice(Data::DialogsInfo &&info) {
switch (info.type) {
case DialogType::Personal:
return Settings::Type::PersonalChats;
case DialogType::Bot:
return Settings::Type::BotChats;
case DialogType::PrivateGroup:
return Settings::Type::PrivateGroups;
case DialogType::PublicGroup:
return Settings::Type::PublicGroups;
case DialogType::Channel:
return Settings::Type::MyChannels;
case DialogType::PrivateChannel:
return Settings::Type::PrivateChannels;
case DialogType::PublicChannel:
return Settings::Type::PublicChannels;
}
return Settings::Type(0);
}();
Expand Down Expand Up @@ -536,6 +589,7 @@ void ApiWrap::loadFile(const Data::File &file, FnMut<void(QString)> done) {
_settings->path + relativePath);
_fileProcess->relativePath = relativePath;
_fileProcess->location = file.location;
_fileProcess->size = file.size;
_fileProcess->done = std::move(done);

if (!file.content.isEmpty()) {
Expand Down
9 changes: 8 additions & 1 deletion Telegram/SourceFiles/export/export_api_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ class ApiWrap {

rpl::producer<RPCError> errors() const;

void startExport(const Settings &settings);
void startExport(
const Settings &settings,
FnMut<void()> done);

void requestPersonalInfo(FnMut<void(Data::PersonalInfo&&)> done);

Expand All @@ -54,12 +56,16 @@ class ApiWrap {
~ApiWrap();

private:
void startMainSession(FnMut<void()> done);

void handleUserpicsSlice(const MTPphotos_Photos &result);
void loadUserpicsFiles(Data::UserpicsSlice &&slice);
void loadNextUserpic();
void loadUserpicDone(const QString &relativePath);
void finishUserpics();

void requestSavedContacts();

void requestDialogsSlice();
void appendDialogsSlice(Data::DialogsInfo &&info);
void finishDialogsList();
Expand Down Expand Up @@ -88,6 +94,7 @@ class ApiWrap {
void error(const QString &text);

MTP::ConcurrentSender _mtp;
base::optional<uint64> _takeoutId;

std::unique_ptr<Settings> _settings;
MTPInputUser _user = MTP_inputUserSelf();
Expand Down
9 changes: 6 additions & 3 deletions Telegram/SourceFiles/export/export_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,10 @@ void Controller::startExport(const Settings &settings) {
return;
}
_writer = Output::CreateWriter(_settings.format);
_api.startExport(_settings);
fillExportSteps();
exportNext();
_api.startExport(_settings, [=] {
exportNext();
});
}

bool Controller::normalizePath() {
Expand Down Expand Up @@ -207,9 +208,11 @@ void Controller::fillExportSteps() {
_steps.push_back(Step::Sessions);
}
const auto dialogTypes = Type::PersonalChats
| Type::BotChats
| Type::PrivateGroups
| Type::PublicGroups
| Type::MyChannels;
| Type::PrivateChannels
| Type::PublicChannels;
if (_settings.types & dialogTypes) {
_steps.push_back(Step::Dialogs);
}
Expand Down
3 changes: 3 additions & 0 deletions Telegram/SourceFiles/export/export_pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@ For license and copyright information please follow this link:
#include "platform/win/windows_range_v3_helpers.h"
#endif // Q_OS_WIN

#include "base/flat_map.h"
#include "base/flat_set.h"

#include "scheme.h"
#include "logs.h"
Loading

0 comments on commit 9d02e53

Please sign in to comment.